From ecdee48d72c5a3f5a717a920b92b3a9f81ad4fbd Mon Sep 17 00:00:00 2001 From: Aleksey Bragin Date: Sun, 6 Jan 2008 16:18:31 +0000 Subject: [PATCH] - Update rpcrt4 to Wine-20080105, so it corresponds to the WIDL. Local changes applied. svn path=/trunk/; revision=31631 --- reactos/dll/win32/rpcrt4_new/cproxy.c | 4 +- reactos/dll/win32/rpcrt4_new/cstub.c | 36 +- reactos/dll/win32/rpcrt4_new/epm_towers.h | 2 +- reactos/dll/win32/rpcrt4_new/ncastatus.h | 132 +- .../dll/win32/rpcrt4_new/ndr_clientserver.c | 434 +- .../dll/win32/rpcrt4_new/ndr_contexthandle.c | 345 + .../dll/win32/rpcrt4_new/ndr_fullpointer.c | 472 +- reactos/dll/win32/rpcrt4_new/ndr_marshall.c | 12280 ++++++++-------- reactos/dll/win32/rpcrt4_new/ndr_misc.h | 130 +- reactos/dll/win32/rpcrt4_new/ndr_ole.c | 786 +- reactos/dll/win32/rpcrt4_new/ndr_stubless.c | 3080 ++-- reactos/dll/win32/rpcrt4_new/ndr_stubless.h | 236 + reactos/dll/win32/rpcrt4_new/rpc_assoc.c | 539 + reactos/dll/win32/rpcrt4_new/rpc_assoc.h | 58 + reactos/dll/win32/rpcrt4_new/rpc_binding.c | 32 +- reactos/dll/win32/rpcrt4_new/rpc_binding.h | 49 +- reactos/dll/win32/rpcrt4_new/rpc_defs.h | 2 +- reactos/dll/win32/rpcrt4_new/rpc_epmap.c | 4 +- reactos/dll/win32/rpcrt4_new/rpc_message.c | 41 +- reactos/dll/win32/rpcrt4_new/rpc_message.h | 2 +- reactos/dll/win32/rpcrt4_new/rpc_server.c | 69 +- reactos/dll/win32/rpcrt4_new/rpc_transport.c | 3471 +++-- reactos/dll/win32/rpcrt4_new/rpcrt4.rbuild | 2 + reactos/dll/win32/rpcrt4_new/rpcrt4.spec | 1130 +- reactos/dll/win32/rpcrt4_new/rpcrt4_main.c | 225 +- .../dll/win32/rpcrt4_new/rpcss_np_client.c | 14 +- 26 files changed, 12518 insertions(+), 11057 deletions(-) create mode 100644 reactos/dll/win32/rpcrt4_new/ndr_contexthandle.c create mode 100644 reactos/dll/win32/rpcrt4_new/ndr_stubless.h create mode 100644 reactos/dll/win32/rpcrt4_new/rpc_assoc.c create mode 100644 reactos/dll/win32/rpcrt4_new/rpc_assoc.h diff --git a/reactos/dll/win32/rpcrt4_new/cproxy.c b/reactos/dll/win32/rpcrt4_new/cproxy.c index 23dfb0251dd..b3101fdf526 100644 --- a/reactos/dll/win32/rpcrt4_new/cproxy.c +++ b/reactos/dll/win32/rpcrt4_new/cproxy.c @@ -16,7 +16,7 @@ * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - * + * * TODO: Handle non-i386 architectures */ @@ -173,7 +173,7 @@ HRESULT WINAPI StdProxy_Construct(REFIID riid, } } } - else + else This->PVtbl = vtbl->Vtbl; This->lpVtbl = &StdProxy_Vtbl; diff --git a/reactos/dll/win32/rpcrt4_new/cstub.c b/reactos/dll/win32/rpcrt4_new/cstub.c index d2f0b49da1d..22dc97ecd1d 100644 --- a/reactos/dll/win32/rpcrt4_new/cstub.c +++ b/reactos/dll/win32/rpcrt4_new/cstub.c @@ -41,7 +41,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole); static WINE_EXCEPTION_FILTER(stub_filter) { - if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION) + if (GetExceptionInformation()->ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE) return EXCEPTION_CONTINUE_SEARCH; return EXCEPTION_EXECUTE_HANDLER; } @@ -109,13 +109,15 @@ static CRITICAL_SECTION delegating_vtbl_section = { &critsect_debug, -1, 0, 0, 0 typedef struct { DWORD ref; + DWORD size; + void **methods; IUnknownVtbl vtbl; + /* remaining entries in vtbl */ } ref_counted_vtbl; static struct { ref_counted_vtbl *table; - DWORD size; } current_vtbl; @@ -156,7 +158,7 @@ typedef struct { } vtbl_method_t; #include "poppack.h" -static void fill_table(IUnknownVtbl *vtbl, DWORD num) +static void fill_table(IUnknownVtbl *vtbl, void **methods, DWORD num) { vtbl_method_t *method; void **entry; @@ -166,7 +168,7 @@ static void fill_table(IUnknownVtbl *vtbl, DWORD num) vtbl->AddRef = delegating_AddRef; vtbl->Release = delegating_Release; - method = (vtbl_method_t*)((void **)vtbl + num); + method = (vtbl_method_t*)methods; entry = (void**)(vtbl + 1); for(i = 3; i < num; i++) @@ -209,19 +211,25 @@ void create_delegating_vtbl(DWORD num_methods) } EnterCriticalSection(&delegating_vtbl_section); - if(num_methods > current_vtbl.size) + if(!current_vtbl.table || num_methods > current_vtbl.table->size) { DWORD size; + DWORD old_protect; if(current_vtbl.table && current_vtbl.table->ref == 0) { TRACE("freeing old table\n"); + VirtualFree(current_vtbl.table->methods, + (current_vtbl.table->size - 3) * sizeof(vtbl_method_t), + MEM_RELEASE); HeapFree(GetProcessHeap(), 0, current_vtbl.table); } - size = sizeof(DWORD) + num_methods * sizeof(void*) + (num_methods - 3) * sizeof(vtbl_method_t); - current_vtbl.table = HeapAlloc(GetProcessHeap(), 0, size); - fill_table(¤t_vtbl.table->vtbl, num_methods); + size = (num_methods - 3) * sizeof(vtbl_method_t); + current_vtbl.table = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(ref_counted_vtbl, vtbl) + num_methods * sizeof(void*)); current_vtbl.table->ref = 0; - current_vtbl.size = num_methods; + current_vtbl.table->size = num_methods; + current_vtbl.table->methods = VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); + fill_table(¤t_vtbl.table->vtbl, current_vtbl.table->methods, num_methods); + VirtualProtect(current_vtbl.table->methods, size, PAGE_EXECUTE_READ, &old_protect); } LeaveCriticalSection(&delegating_vtbl_section); } @@ -247,6 +255,9 @@ static void release_delegating_vtbl(IUnknownVtbl *vtbl) if(table->ref == 0 && table != current_vtbl.table) { TRACE("... and we're not current so free'ing\n"); + VirtualFree(current_vtbl.table->methods, + (current_vtbl.table->size - 3) * sizeof(vtbl_method_t), + MEM_RELEASE); HeapFree(GetProcessHeap(), 0, table); } LeaveCriticalSection(&delegating_vtbl_section); @@ -558,6 +569,9 @@ void WINAPI NdrStubInitialize(PRPC_MESSAGE pRpcMsg, TRACE("(%p,%p,%p,%p)\n", pRpcMsg, pStubMsg, pStubDescriptor, pRpcChannelBuffer); NdrServerInitializeNew(pRpcMsg, pStubMsg, pStubDescriptor); pStubMsg->pRpcChannelBuffer = pRpcChannelBuffer; + IRpcChannelBuffer_GetDestCtx(pStubMsg->pRpcChannelBuffer, + &pStubMsg->dwDestContext, + &pStubMsg->pvDestContext); } /*********************************************************************** @@ -581,7 +595,5 @@ void WINAPI NdrStubGetBuffer(LPRPCSTUBBUFFER iface, return; } - pStubMsg->BufferStart = pStubMsg->RpcMsg->Buffer; - pStubMsg->BufferEnd = pStubMsg->BufferStart + pStubMsg->BufferLength; - pStubMsg->Buffer = pStubMsg->BufferStart; + pStubMsg->Buffer = pStubMsg->RpcMsg->Buffer; } diff --git a/reactos/dll/win32/rpcrt4_new/epm_towers.h b/reactos/dll/win32/rpcrt4_new/epm_towers.h index d0661d484d4..9c58ff0c3dd 100644 --- a/reactos/dll/win32/rpcrt4_new/epm_towers.h +++ b/reactos/dll/win32/rpcrt4_new/epm_towers.h @@ -39,7 +39,7 @@ #define EPM_PROTOCOL_DSP 0x16 /* AppleTalk Data Stream Protocol */ #define EPM_PROTOCOL_DDP 0x17 /* AppleTalk Data Datagram Protocol */ #define EPM_PROTOCOL_APPLETALK 0x18 /* AppleTalk */ -#define EPM_PROTOCOL_VINES_SPP 0x1a +#define EPM_PROTOCOL_VINES_SPP 0x1a #define EPM_PROTOCOL_VINES_IPC 0x1b /* Inter Process Communication */ #define EPM_PROTOCOL_STREETTALK 0x1c /* Vines Streettalk */ #define EPM_PROTOCOL_HTTP 0x1f diff --git a/reactos/dll/win32/rpcrt4_new/ncastatus.h b/reactos/dll/win32/rpcrt4_new/ncastatus.h index 0a9700268e2..2c054236423 100644 --- a/reactos/dll/win32/rpcrt4_new/ncastatus.h +++ b/reactos/dll/win32/rpcrt4_new/ncastatus.h @@ -1,66 +1,66 @@ -/* - * NCA Status definitions - * - * Copyright 2007 Robert Shearman - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#define NCA_S_COMM_FAILURE 0x1C010001 -#define NCA_S_OP_RNG_ERROR 0x1C010002 -#define NCA_S_UNK_IF 0x1C010003 -#define NCA_S_WRONG_BOOT_TIME 0x1C010006 -#define NCA_S_YOU_CRASHED 0x1C010009 -#define NCA_S_PROTO_ERROR 0x1C01000B -#define NCA_S_OUT_ARGS_TOO_BIG 0x1C010013 -#define NCA_S_SERVER_TOO_BUSY 0x1C010014 -#define NCA_S_FAULT_STRING_TOO_LONG 0x1C010015 -#define NCA_S_UNSUPPORTED_TYPE 0x1C010017 - -#define NCA_S_FAULT_INT_DIV_BY_ZERO 0x1C000001 -#define NCA_S_FAULT_ADDR_ERROR 0x1C000002 -#define NCA_S_FAULT_FP_DIV_ZERO 0x1C000003 -#define NCA_S_FAULT_FP_UNDERFLOW 0x1C000004 -#define NCA_S_FAULT_FP_OVERFLOW 0x1C000005 -#define NCA_S_FAULT_INVALID_TAG 0x1C000006 -#define NCA_S_FAULT_INVALID_BOUND 0x1C000007 -#define NCA_S_RPC_VERSION_MISMATCH 0x1C000008 -#define NCA_S_UNSPEC_REJECT 0x1C000009 -#define NCA_S_BAD_ACTID 0x1C00000A -#define NCA_S_WHO_ARE_YOU_FAILED 0x1C00000B -#define NCA_S_MANAGER_NOT_ENTERED 0x1C00000C -#define NCA_S_FAULT_CANCEL 0x1C00000D -#define NCA_S_FAULT_ILL_INST 0x1C00000E -#define NCA_S_FAULT_FP_ERROR 0x1C00000F -#define NCA_S_FAULT_INT_OVERFLOW 0x1C000010 -#define NCA_S_FAULT_UNSPEC 0x1C000012 -#define NCA_S_FAULT_REMOTE_COMM_FAILURE 0x1C000013 -#define NCA_S_FAULT_PIPE_EMPTY 0x1C000014 -#define NCA_S_FAULT_PIPE_CLOSED 0x1C000015 -#define NCA_S_FAULT_PIPE_ORDER 0x1C000016 -#define NCA_S_FAULT_PIPE_DISCIPLINE 0x1C000017 -#define NCA_S_FAULT_PIPE_COMM_ERROR 0x1C000018 -#define NCA_S_FAULT_PIPE_MEMORY 0x1C000019 -#define NCA_S_FAULT_CONTEXT_MISMATCH 0x1C00001A -#define NCA_S_FAULT_REMOTE_NO_MEMORY 0x1C00001B -#define NCA_S_INVALID_PRES_CONTEXT_ID 0x1C00001C -#define NCA_S_UNSUPPORTED_AUTHN_LEVEL 0x1C00001D -#define NCA_S_INVALID_CHECKSUM 0x1C00001F -#define NCA_S_INVALID_CRC 0x1C000020 -#define NCA_S_FAULT_USER_DEFINED 0x1C000021 -#define NCA_S_FAULT_TX_OPEN_FAILED 0x1C000022 -#define NCA_S_FAULT_CODESET_CONV_ERROR 0x1C000023 -#define NCA_S_FAULT_OBJECT_NOT_FOUND 0x1C000024 -#define NCA_S_FAULT_NO_CLIENT_STUB 0x1C000025 +/* + * NCA Status definitions + * + * Copyright 2007 Robert Shearman + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define NCA_S_COMM_FAILURE 0x1C010001 +#define NCA_S_OP_RNG_ERROR 0x1C010002 +#define NCA_S_UNK_IF 0x1C010003 +#define NCA_S_WRONG_BOOT_TIME 0x1C010006 +#define NCA_S_YOU_CRASHED 0x1C010009 +#define NCA_S_PROTO_ERROR 0x1C01000B +#define NCA_S_OUT_ARGS_TOO_BIG 0x1C010013 +#define NCA_S_SERVER_TOO_BUSY 0x1C010014 +#define NCA_S_FAULT_STRING_TOO_LONG 0x1C010015 +#define NCA_S_UNSUPPORTED_TYPE 0x1C010017 + +#define NCA_S_FAULT_INT_DIV_BY_ZERO 0x1C000001 +#define NCA_S_FAULT_ADDR_ERROR 0x1C000002 +#define NCA_S_FAULT_FP_DIV_ZERO 0x1C000003 +#define NCA_S_FAULT_FP_UNDERFLOW 0x1C000004 +#define NCA_S_FAULT_FP_OVERFLOW 0x1C000005 +#define NCA_S_FAULT_INVALID_TAG 0x1C000006 +#define NCA_S_FAULT_INVALID_BOUND 0x1C000007 +#define NCA_S_RPC_VERSION_MISMATCH 0x1C000008 +#define NCA_S_UNSPEC_REJECT 0x1C000009 +#define NCA_S_BAD_ACTID 0x1C00000A +#define NCA_S_WHO_ARE_YOU_FAILED 0x1C00000B +#define NCA_S_MANAGER_NOT_ENTERED 0x1C00000C +#define NCA_S_FAULT_CANCEL 0x1C00000D +#define NCA_S_FAULT_ILL_INST 0x1C00000E +#define NCA_S_FAULT_FP_ERROR 0x1C00000F +#define NCA_S_FAULT_INT_OVERFLOW 0x1C000010 +#define NCA_S_FAULT_UNSPEC 0x1C000012 +#define NCA_S_FAULT_REMOTE_COMM_FAILURE 0x1C000013 +#define NCA_S_FAULT_PIPE_EMPTY 0x1C000014 +#define NCA_S_FAULT_PIPE_CLOSED 0x1C000015 +#define NCA_S_FAULT_PIPE_ORDER 0x1C000016 +#define NCA_S_FAULT_PIPE_DISCIPLINE 0x1C000017 +#define NCA_S_FAULT_PIPE_COMM_ERROR 0x1C000018 +#define NCA_S_FAULT_PIPE_MEMORY 0x1C000019 +#define NCA_S_FAULT_CONTEXT_MISMATCH 0x1C00001A +#define NCA_S_FAULT_REMOTE_NO_MEMORY 0x1C00001B +#define NCA_S_INVALID_PRES_CONTEXT_ID 0x1C00001C +#define NCA_S_UNSUPPORTED_AUTHN_LEVEL 0x1C00001D +#define NCA_S_INVALID_CHECKSUM 0x1C00001F +#define NCA_S_INVALID_CRC 0x1C000020 +#define NCA_S_FAULT_USER_DEFINED 0x1C000021 +#define NCA_S_FAULT_TX_OPEN_FAILED 0x1C000022 +#define NCA_S_FAULT_CODESET_CONV_ERROR 0x1C000023 +#define NCA_S_FAULT_OBJECT_NOT_FOUND 0x1C000024 +#define NCA_S_FAULT_NO_CLIENT_STUB 0x1C000025 diff --git a/reactos/dll/win32/rpcrt4_new/ndr_clientserver.c b/reactos/dll/win32/rpcrt4_new/ndr_clientserver.c index fe424a63cc0..ab73e66d32e 100644 --- a/reactos/dll/win32/rpcrt4_new/ndr_clientserver.c +++ b/reactos/dll/win32/rpcrt4_new/ndr_clientserver.c @@ -1,207 +1,227 @@ -/* - * MIDL proxy/stub stuff - * - * Copyright 2002 Ove Kåven, TransGaming Technologies - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - * - * TODO: - * - figure out whether we *really* got this right - * - check for errors and throw exceptions - */ - -#include -#include -#include -#include - -#define COBJMACROS - -#include "windef.h" -#include "winbase.h" -#include "winerror.h" - -#include "objbase.h" - -#include "rpcproxy.h" - -#include "wine/debug.h" - -#include "ndr_misc.h" -#include "rpcndr.h" - -WINE_DEFAULT_DEBUG_CHANNEL(rpc); - -/************************************************************************ - * NdrClientInitializeNew [RPCRT4.@] - */ -void WINAPI NdrClientInitializeNew( PRPC_MESSAGE pRpcMessage, PMIDL_STUB_MESSAGE pStubMsg, - PMIDL_STUB_DESC pStubDesc, unsigned int ProcNum ) -{ - TRACE("(pRpcMessage == ^%p, pStubMsg == ^%p, pStubDesc == ^%p, ProcNum == %d)\n", - pRpcMessage, pStubMsg, pStubDesc, ProcNum); - - assert( pRpcMessage && pStubMsg && pStubDesc ); - - pRpcMessage->Handle = NULL; - pRpcMessage->ProcNum = ProcNum; - pRpcMessage->RpcInterfaceInformation = pStubDesc->RpcInterfaceInformation; - pRpcMessage->RpcFlags = 0; - pRpcMessage->DataRepresentation = NDR_LOCAL_DATA_REPRESENTATION; - - pStubMsg->RpcMsg = pRpcMessage; - pStubMsg->BufferStart = NULL; - pStubMsg->BufferEnd = NULL; - pStubMsg->BufferLength = 0; - pStubMsg->IsClient = TRUE; - pStubMsg->ReuseBuffer = FALSE; - pStubMsg->pAllocAllNodesContext = NULL; - pStubMsg->pPointerQueueState = NULL; - pStubMsg->IgnoreEmbeddedPointers = 0; - pStubMsg->PointerBufferMark = NULL; - pStubMsg->fBufferValid = 0; - pStubMsg->uFlags = 0; - pStubMsg->pfnAllocate = pStubDesc->pfnAllocate; - pStubMsg->pfnFree = pStubDesc->pfnFree; - pStubMsg->StackTop = NULL; - pStubMsg->StubDesc = pStubDesc; - pStubMsg->FullPtrRefId = 0; - pStubMsg->PointerLength = 0; - pStubMsg->fInDontFree = 0; - pStubMsg->fDontCallFreeInst = 0; - pStubMsg->fInOnlyParam = 0; - pStubMsg->fHasReturn = 0; - pStubMsg->fHasExtensions = 0; - pStubMsg->fHasNewCorrDesc = 0; - pStubMsg->fUnused = 0; - pStubMsg->dwDestContext = MSHCTX_DIFFERENTMACHINE; - pStubMsg->pvDestContext = NULL; - pStubMsg->pRpcChannelBuffer = NULL; - pStubMsg->pArrayInfo = NULL; - pStubMsg->dwStubPhase = 0; - /* FIXME: LowStackMark */ - pStubMsg->pAsyncMsg = NULL; - pStubMsg->pCorrInfo = NULL; - pStubMsg->pCorrMemory = NULL; - pStubMsg->pMemoryList = NULL; -} - -/*********************************************************************** - * NdrServerInitializeNew [RPCRT4.@] - */ -unsigned char* WINAPI NdrServerInitializeNew( PRPC_MESSAGE pRpcMsg, PMIDL_STUB_MESSAGE pStubMsg, - PMIDL_STUB_DESC pStubDesc ) -{ - TRACE("(pRpcMsg == ^%p, pStubMsg == ^%p, pStubDesc == ^%p)\n", pRpcMsg, pStubMsg, pStubDesc); - - assert( pRpcMsg && pStubMsg && pStubDesc ); - - /* not everyone allocates stack space for w2kReserved */ - memset(pStubMsg, 0, FIELD_OFFSET(MIDL_STUB_MESSAGE,pCSInfo)); - - pStubMsg->ReuseBuffer = TRUE; - pStubMsg->IsClient = FALSE; - pStubMsg->StubDesc = pStubDesc; - pStubMsg->pfnAllocate = pStubDesc->pfnAllocate; - pStubMsg->pfnFree = pStubDesc->pfnFree; - pStubMsg->RpcMsg = pRpcMsg; - pStubMsg->Buffer = pStubMsg->BufferStart = pRpcMsg->Buffer; - pStubMsg->BufferLength = pRpcMsg->BufferLength; - pStubMsg->BufferEnd = pStubMsg->Buffer + pStubMsg->BufferLength; - - /* FIXME: determine the proper return value */ - return NULL; -} - -/*********************************************************************** - * NdrGetBuffer [RPCRT4.@] - */ -unsigned char *WINAPI NdrGetBuffer(PMIDL_STUB_MESSAGE stubmsg, ULONG buflen, RPC_BINDING_HANDLE handle) -{ - TRACE("(stubmsg == ^%p, buflen == %u, handle == %p): wild guess.\n", stubmsg, buflen, handle); - - assert( stubmsg && stubmsg->RpcMsg ); - - /* I guess this is our chance to put the binding handle into the RPC_MESSAGE */ - stubmsg->RpcMsg->Handle = handle; - - stubmsg->RpcMsg->BufferLength = buflen; - if (I_RpcGetBuffer(stubmsg->RpcMsg) != S_OK) - return NULL; - - stubmsg->Buffer = stubmsg->BufferStart = stubmsg->RpcMsg->Buffer; - stubmsg->BufferLength = stubmsg->RpcMsg->BufferLength; - stubmsg->BufferEnd = stubmsg->Buffer + stubmsg->BufferLength; - return (stubmsg->Buffer = (unsigned char *)stubmsg->RpcMsg->Buffer); -} -/*********************************************************************** - * NdrFreeBuffer [RPCRT4.@] - */ -void WINAPI NdrFreeBuffer(PMIDL_STUB_MESSAGE pStubMsg) -{ - TRACE("(pStubMsg == ^%p): wild guess.\n", pStubMsg); - I_RpcFreeBuffer(pStubMsg->RpcMsg); - pStubMsg->BufferLength = 0; - pStubMsg->Buffer = pStubMsg->BufferEnd = (unsigned char *)(pStubMsg->RpcMsg->Buffer = NULL); -} - -/************************************************************************ - * NdrSendReceive [RPCRT4.@] - */ -unsigned char *WINAPI NdrSendReceive( PMIDL_STUB_MESSAGE stubmsg, unsigned char *buffer ) -{ - RPC_STATUS status; - - TRACE("(stubmsg == ^%p, buffer == ^%p)\n", stubmsg, buffer); - - /* FIXME: how to handle errors? (raise exception?) */ - if (!stubmsg) { - ERR("NULL stub message. No action taken.\n"); - return NULL; - } - if (!stubmsg->RpcMsg) { - ERR("RPC Message not present in stub message. No action taken.\n"); - return NULL; - } - - stubmsg->RpcMsg->BufferLength = buffer - (unsigned char *)stubmsg->RpcMsg->Buffer; - status = I_RpcSendReceive(stubmsg->RpcMsg); - if (status != RPC_S_OK) - RpcRaiseException(status); - - stubmsg->BufferLength = stubmsg->RpcMsg->BufferLength; - stubmsg->BufferStart = stubmsg->RpcMsg->Buffer; - stubmsg->BufferEnd = stubmsg->BufferStart + stubmsg->BufferLength; - stubmsg->Buffer = stubmsg->BufferStart; - - /* FIXME: is this the right return value? */ - return NULL; -} - -/************************************************************************ - * NdrMapCommAndFaultStatus [RPCRT4.@] - */ -RPC_STATUS RPC_ENTRY NdrMapCommAndFaultStatus( PMIDL_STUB_MESSAGE pStubMsg, - ULONG *pCommStatus, - ULONG *pFaultStatus, - RPC_STATUS Status ) -{ - FIXME("(%p, %p, %p, %ld): stub\n", pStubMsg, pCommStatus, pFaultStatus, Status); - - *pCommStatus = 0; - *pFaultStatus = 0; - - return RPC_S_OK; -} +/* + * MIDL proxy/stub stuff + * + * Copyright 2002 Ove Kåven, TransGaming Technologies + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + * + * TODO: + * - figure out whether we *really* got this right + * - check for errors and throw exceptions + */ + +#include +#include +#include +#include + +#define COBJMACROS + +#include "windef.h" +#include "winbase.h" +#include "winerror.h" + +#include "objbase.h" + +#include "rpcproxy.h" + +#include "wine/debug.h" + +#include "ndr_misc.h" +#include "rpcndr.h" + +WINE_DEFAULT_DEBUG_CHANNEL(rpc); + +/************************************************************************ + * NdrClientInitializeNew [RPCRT4.@] + */ +void WINAPI NdrClientInitializeNew( PRPC_MESSAGE pRpcMessage, PMIDL_STUB_MESSAGE pStubMsg, + PMIDL_STUB_DESC pStubDesc, unsigned int ProcNum ) +{ + TRACE("(pRpcMessage == ^%p, pStubMsg == ^%p, pStubDesc == ^%p, ProcNum == %d)\n", + pRpcMessage, pStubMsg, pStubDesc, ProcNum); + + pRpcMessage->Handle = NULL; + pRpcMessage->ProcNum = ProcNum; + pRpcMessage->RpcInterfaceInformation = pStubDesc->RpcInterfaceInformation; + pRpcMessage->RpcFlags = 0; + pRpcMessage->DataRepresentation = NDR_LOCAL_DATA_REPRESENTATION; + + pStubMsg->RpcMsg = pRpcMessage; + pStubMsg->BufferStart = NULL; + pStubMsg->BufferEnd = NULL; + pStubMsg->BufferLength = 0; + pStubMsg->IsClient = TRUE; + pStubMsg->ReuseBuffer = FALSE; + pStubMsg->pAllocAllNodesContext = NULL; + pStubMsg->pPointerQueueState = NULL; + pStubMsg->IgnoreEmbeddedPointers = 0; + pStubMsg->PointerBufferMark = NULL; + pStubMsg->fBufferValid = 0; + pStubMsg->uFlags = 0; + pStubMsg->pfnAllocate = pStubDesc->pfnAllocate; + pStubMsg->pfnFree = pStubDesc->pfnFree; + pStubMsg->StackTop = NULL; + pStubMsg->StubDesc = pStubDesc; + pStubMsg->FullPtrRefId = 0; + pStubMsg->PointerLength = 0; + pStubMsg->fInDontFree = 0; + pStubMsg->fDontCallFreeInst = 0; + pStubMsg->fInOnlyParam = 0; + pStubMsg->fHasReturn = 0; + pStubMsg->fHasExtensions = 0; + pStubMsg->fHasNewCorrDesc = 0; + pStubMsg->fUnused = 0; + pStubMsg->dwDestContext = MSHCTX_DIFFERENTMACHINE; + pStubMsg->pvDestContext = NULL; + pStubMsg->pRpcChannelBuffer = NULL; + pStubMsg->pArrayInfo = NULL; + pStubMsg->dwStubPhase = 0; + /* FIXME: LowStackMark */ + pStubMsg->pAsyncMsg = NULL; + pStubMsg->pCorrInfo = NULL; + pStubMsg->pCorrMemory = NULL; + pStubMsg->pMemoryList = NULL; +} + +/*********************************************************************** + * NdrServerInitializeNew [RPCRT4.@] + */ +unsigned char* WINAPI NdrServerInitializeNew( PRPC_MESSAGE pRpcMsg, PMIDL_STUB_MESSAGE pStubMsg, + PMIDL_STUB_DESC pStubDesc ) +{ + TRACE("(pRpcMsg == ^%p, pStubMsg == ^%p, pStubDesc == ^%p)\n", pRpcMsg, pStubMsg, pStubDesc); + + pStubMsg->RpcMsg = pRpcMsg; + pStubMsg->Buffer = pStubMsg->BufferStart = pRpcMsg->Buffer; + pStubMsg->BufferEnd = pStubMsg->Buffer + pRpcMsg->BufferLength; + pStubMsg->BufferLength = pRpcMsg->BufferLength; + pStubMsg->IsClient = FALSE; + pStubMsg->ReuseBuffer = FALSE; + pStubMsg->pAllocAllNodesContext = NULL; + pStubMsg->pPointerQueueState = NULL; + pStubMsg->IgnoreEmbeddedPointers = 0; + pStubMsg->PointerBufferMark = NULL; + pStubMsg->uFlags = 0; + pStubMsg->pfnAllocate = pStubDesc->pfnAllocate; + pStubMsg->pfnFree = pStubDesc->pfnFree; + pStubMsg->StackTop = NULL; + pStubMsg->StubDesc = pStubDesc; + pStubMsg->FullPtrXlatTables = NULL; + pStubMsg->FullPtrRefId = 0; + pStubMsg->PointerLength = 0; + pStubMsg->fInDontFree = 0; + pStubMsg->fDontCallFreeInst = 0; + pStubMsg->fInOnlyParam = 0; + pStubMsg->fHasReturn = 0; + pStubMsg->fHasExtensions = 0; + pStubMsg->fHasNewCorrDesc = 0; + pStubMsg->fUnused = 0; + pStubMsg->dwDestContext = MSHCTX_DIFFERENTMACHINE; + pStubMsg->pvDestContext = NULL; + pStubMsg->pRpcChannelBuffer = NULL; + pStubMsg->pArrayInfo = NULL; + pStubMsg->dwStubPhase = 0; + /* FIXME: LowStackMark */ + pStubMsg->pAsyncMsg = NULL; + pStubMsg->pCorrInfo = NULL; + pStubMsg->pCorrMemory = NULL; + pStubMsg->pMemoryList = NULL; + + return NULL; +} + +/*********************************************************************** + * NdrGetBuffer [RPCRT4.@] + */ +unsigned char *WINAPI NdrGetBuffer(PMIDL_STUB_MESSAGE stubmsg, ULONG buflen, RPC_BINDING_HANDLE handle) +{ + RPC_STATUS status; + + TRACE("(stubmsg == ^%p, buflen == %u, handle == %p)\n", stubmsg, buflen, handle); + + stubmsg->RpcMsg->Handle = handle; + stubmsg->RpcMsg->BufferLength = buflen; + + status = I_RpcGetBuffer(stubmsg->RpcMsg); + if (status != RPC_S_OK) + RpcRaiseException(status); + + stubmsg->Buffer = stubmsg->RpcMsg->Buffer; + stubmsg->fBufferValid = TRUE; + stubmsg->BufferLength = stubmsg->RpcMsg->BufferLength; + return stubmsg->Buffer; +} +/*********************************************************************** + * NdrFreeBuffer [RPCRT4.@] + */ +void WINAPI NdrFreeBuffer(PMIDL_STUB_MESSAGE pStubMsg) +{ + TRACE("(pStubMsg == ^%p)\n", pStubMsg); + if (pStubMsg->fBufferValid) + { + I_RpcFreeBuffer(pStubMsg->RpcMsg); + pStubMsg->fBufferValid = FALSE; + } +} + +/************************************************************************ + * NdrSendReceive [RPCRT4.@] + */ +unsigned char *WINAPI NdrSendReceive( PMIDL_STUB_MESSAGE stubmsg, unsigned char *buffer ) +{ + RPC_STATUS status; + + TRACE("(stubmsg == ^%p, buffer == ^%p)\n", stubmsg, buffer); + + /* FIXME: how to handle errors? (raise exception?) */ + if (!stubmsg) { + ERR("NULL stub message. No action taken.\n"); + return NULL; + } + if (!stubmsg->RpcMsg) { + ERR("RPC Message not present in stub message. No action taken.\n"); + return NULL; + } + + stubmsg->RpcMsg->BufferLength = buffer - (unsigned char *)stubmsg->RpcMsg->Buffer; + status = I_RpcSendReceive(stubmsg->RpcMsg); + if (status != RPC_S_OK) + RpcRaiseException(status); + + stubmsg->BufferLength = stubmsg->RpcMsg->BufferLength; + stubmsg->BufferStart = stubmsg->RpcMsg->Buffer; + stubmsg->BufferEnd = stubmsg->BufferStart + stubmsg->BufferLength; + stubmsg->Buffer = stubmsg->BufferStart; + + /* FIXME: is this the right return value? */ + return NULL; +} + +/************************************************************************ + * NdrMapCommAndFaultStatus [RPCRT4.@] + */ +RPC_STATUS RPC_ENTRY NdrMapCommAndFaultStatus( PMIDL_STUB_MESSAGE pStubMsg, + ULONG *pCommStatus, + ULONG *pFaultStatus, + RPC_STATUS Status ) +{ + FIXME("(%p, %p, %p, %ld): stub\n", pStubMsg, pCommStatus, pFaultStatus, Status); + + *pCommStatus = 0; + *pFaultStatus = 0; + + return RPC_S_OK; +} diff --git a/reactos/dll/win32/rpcrt4_new/ndr_contexthandle.c b/reactos/dll/win32/rpcrt4_new/ndr_contexthandle.c new file mode 100644 index 00000000000..21d87473830 --- /dev/null +++ b/reactos/dll/win32/rpcrt4_new/ndr_contexthandle.c @@ -0,0 +1,345 @@ +/* + * NDR data marshalling + * + * Copyright 2006 Mike McCormack (for CodeWeavers) + * Copyright 2006-2007 Robert Shearman (for CodeWeavers) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "ndr_misc.h" +#include "rpc_assoc.h" +#include "rpcndr.h" + +#include "wine/rpcfc.h" + +#include "wine/debug.h" +#include "wine/list.h" + +WINE_DEFAULT_DEBUG_CHANNEL(ole); + +#define NDR_CONTEXT_HANDLE_MAGIC 0x4352444e + +typedef struct ndr_context_handle +{ + ULONG attributes; + GUID uuid; +} ndr_context_handle; + +struct context_handle_entry +{ + struct list entry; + DWORD magic; + RPC_BINDING_HANDLE handle; + ndr_context_handle wire_data; +}; + +static struct list context_handle_list = LIST_INIT(context_handle_list); + +static CRITICAL_SECTION ndr_context_cs; +static CRITICAL_SECTION_DEBUG ndr_context_debug = +{ + 0, 0, &ndr_context_cs, + { &ndr_context_debug.ProcessLocksList, &ndr_context_debug.ProcessLocksList }, + 0, 0, { (DWORD_PTR)(__FILE__ ": ndr_context") } +}; +static CRITICAL_SECTION ndr_context_cs = { &ndr_context_debug, -1, 0, 0, 0, 0 }; + +static struct context_handle_entry *get_context_entry(NDR_CCONTEXT CContext) +{ + struct context_handle_entry *che = (struct context_handle_entry*) CContext; + + if (che->magic != NDR_CONTEXT_HANDLE_MAGIC) + return NULL; + return che; +} + +static struct context_handle_entry *context_entry_from_guid(LPCGUID uuid) +{ + struct context_handle_entry *che; + LIST_FOR_EACH_ENTRY(che, &context_handle_list, struct context_handle_entry, entry) + if (IsEqualGUID(&che->wire_data.uuid, uuid)) + return che; + return NULL; +} + +RPC_BINDING_HANDLE WINAPI NDRCContextBinding(NDR_CCONTEXT CContext) +{ + struct context_handle_entry *che; + RPC_BINDING_HANDLE handle = NULL; + + TRACE("%p\n", CContext); + + EnterCriticalSection(&ndr_context_cs); + che = get_context_entry(CContext); + if (che) + handle = che->handle; + LeaveCriticalSection(&ndr_context_cs); + + if (!handle) + RpcRaiseException(ERROR_INVALID_HANDLE); + return handle; +} + +void WINAPI NDRCContextMarshall(NDR_CCONTEXT CContext, void *pBuff) +{ + struct context_handle_entry *che; + + TRACE("%p %p\n", CContext, pBuff); + + if (CContext) + { + EnterCriticalSection(&ndr_context_cs); + che = get_context_entry(CContext); + memcpy(pBuff, &che->wire_data, sizeof (ndr_context_handle)); + LeaveCriticalSection(&ndr_context_cs); + } + else + { + ndr_context_handle *wire_data = (ndr_context_handle *)pBuff; + wire_data->attributes = 0; + wire_data->uuid = GUID_NULL; + } +} + +/*********************************************************************** + * RpcSmDestroyClientContext [RPCRT4.@] + */ +RPC_STATUS WINAPI RpcSmDestroyClientContext(void **ContextHandle) +{ + RPC_STATUS status = RPC_X_SS_CONTEXT_MISMATCH; + struct context_handle_entry *che = NULL; + + TRACE("(%p)\n", ContextHandle); + + EnterCriticalSection(&ndr_context_cs); + che = get_context_entry(*ContextHandle); + *ContextHandle = NULL; + if (che) + { + status = RPC_S_OK; + list_remove(&che->entry); + } + + LeaveCriticalSection(&ndr_context_cs); + + if (che) + { + RpcBindingFree(&che->handle); + HeapFree(GetProcessHeap(), 0, che); + } + + return status; +} + +/*********************************************************************** + * RpcSsDestroyClientContext [RPCRT4.@] + */ +void WINAPI RpcSsDestroyClientContext(void **ContextHandle) +{ + RPC_STATUS status = RpcSmDestroyClientContext(ContextHandle); + if (status != RPC_S_OK) + RpcRaiseException(status); +} + +static UINT ndr_update_context_handle(NDR_CCONTEXT *CContext, + RPC_BINDING_HANDLE hBinding, + const ndr_context_handle *chi) +{ + struct context_handle_entry *che = NULL; + + /* a null UUID means we should free the context handle */ + if (IsEqualGUID(&chi->uuid, &GUID_NULL)) + { + if (*CContext) + { + che = get_context_entry(*CContext); + if (!che) + return ERROR_INVALID_HANDLE; + list_remove(&che->entry); + RpcBindingFree(&che->handle); + HeapFree(GetProcessHeap(), 0, che); + che = NULL; + } + } + /* if there's no existing entry matching the GUID, allocate one */ + else if (!(che = context_entry_from_guid(&chi->uuid))) + { + che = HeapAlloc(GetProcessHeap(), 0, sizeof *che); + if (!che) + return ERROR_NOT_ENOUGH_MEMORY; + che->magic = NDR_CONTEXT_HANDLE_MAGIC; + RpcBindingCopy(hBinding, &che->handle); + list_add_tail(&context_handle_list, &che->entry); + memcpy(&che->wire_data, chi, sizeof *chi); + } + + *CContext = che; + + return ERROR_SUCCESS; +} + +/*********************************************************************** + * NDRCContextUnmarshall [RPCRT4.@] + */ +void WINAPI NDRCContextUnmarshall(NDR_CCONTEXT *CContext, + RPC_BINDING_HANDLE hBinding, + void *pBuff, ULONG DataRepresentation) +{ + UINT r; + + TRACE("*%p=(%p) %p %p %08x\n", + CContext, *CContext, hBinding, pBuff, DataRepresentation); + + EnterCriticalSection(&ndr_context_cs); + r = ndr_update_context_handle(CContext, hBinding, pBuff); + LeaveCriticalSection(&ndr_context_cs); + if (r) + RpcRaiseException(r); +} + +/*********************************************************************** + * NDRSContextMarshall [RPCRT4.@] + */ +void WINAPI NDRSContextMarshall(NDR_SCONTEXT SContext, + void *pBuff, + NDR_RUNDOWN userRunDownIn) +{ + TRACE("(%p %p %p)\n", SContext, pBuff, userRunDownIn); + NDRSContextMarshall2(I_RpcGetCurrentCallHandle(), SContext, pBuff, userRunDownIn, NULL, 0); +} + +/*********************************************************************** + * NDRSContextMarshallEx [RPCRT4.@] + */ +void WINAPI NDRSContextMarshallEx(RPC_BINDING_HANDLE hBinding, + NDR_SCONTEXT SContext, + void *pBuff, + NDR_RUNDOWN userRunDownIn) +{ + TRACE("(%p %p %p %p)\n", hBinding, SContext, pBuff, userRunDownIn); + NDRSContextMarshall2(hBinding, SContext, pBuff, userRunDownIn, NULL, 0); +} + +/*********************************************************************** + * NDRSContextMarshall2 [RPCRT4.@] + */ +void WINAPI NDRSContextMarshall2(RPC_BINDING_HANDLE hBinding, + NDR_SCONTEXT SContext, + void *pBuff, + NDR_RUNDOWN userRunDownIn, + void *CtxGuard, ULONG Flags) +{ + RpcBinding *binding = hBinding; + RPC_STATUS status; + ndr_context_handle *ndr = pBuff; + + TRACE("(%p %p %p %p %p %u)\n", + hBinding, SContext, pBuff, userRunDownIn, CtxGuard, Flags); + + if (!binding->server || !binding->Assoc) + RpcRaiseException(ERROR_INVALID_HANDLE); + + if (SContext->userContext) + { + status = RpcServerAssoc_UpdateContextHandle(binding->Assoc, SContext, CtxGuard, userRunDownIn); + if (status != RPC_S_OK) + RpcRaiseException(status); + ndr->attributes = 0; + RpcContextHandle_GetUuid(SContext, &ndr->uuid); + + RPCRT4_RemoveThreadContextHandle(SContext); + RpcServerAssoc_ReleaseContextHandle(binding->Assoc, SContext, TRUE); + } + else + { + if (!RpcContextHandle_IsGuardCorrect(SContext, CtxGuard)) + RpcRaiseException(ERROR_INVALID_HANDLE); + memset(ndr, 0, sizeof(*ndr)); + + RPCRT4_RemoveThreadContextHandle(SContext); + /* Note: release the context handle twice in this case to release + * one ref being kept around for the data and one ref for the + * unmarshall/marshall sequence */ + if (!RpcServerAssoc_ReleaseContextHandle(binding->Assoc, SContext, TRUE)) + return; /* this is to cope with the case of the data not being valid + * before and so not having a further reference */ + RpcServerAssoc_ReleaseContextHandle(binding->Assoc, SContext, FALSE); + } +} + +/*********************************************************************** + * NDRSContextUnmarshall [RPCRT4.@] + */ +NDR_SCONTEXT WINAPI NDRSContextUnmarshall(void *pBuff, + ULONG DataRepresentation) +{ + TRACE("(%p %08x)\n", pBuff, DataRepresentation); + return NDRSContextUnmarshall2(I_RpcGetCurrentCallHandle(), pBuff, DataRepresentation, NULL, 0); +} + +/*********************************************************************** + * NDRSContextUnmarshallEx [RPCRT4.@] + */ +NDR_SCONTEXT WINAPI NDRSContextUnmarshallEx(RPC_BINDING_HANDLE hBinding, + void *pBuff, + ULONG DataRepresentation) +{ + TRACE("(%p %p %08x)\n", hBinding, pBuff, DataRepresentation); + return NDRSContextUnmarshall2(hBinding, pBuff, DataRepresentation, NULL, 0); +} + +/*********************************************************************** + * NDRSContextUnmarshall2 [RPCRT4.@] + */ +NDR_SCONTEXT WINAPI NDRSContextUnmarshall2(RPC_BINDING_HANDLE hBinding, + void *pBuff, + ULONG DataRepresentation, + void *CtxGuard, ULONG Flags) +{ + RpcBinding *binding = hBinding; + NDR_SCONTEXT SContext; + RPC_STATUS status; + + TRACE("(%p %p %08x %p %u)\n", + hBinding, pBuff, DataRepresentation, CtxGuard, Flags); + + if (!binding->server || !binding->Assoc) + RpcRaiseException(ERROR_INVALID_HANDLE); + + if (!pBuff) + status = RpcServerAssoc_AllocateContextHandle(binding->Assoc, CtxGuard, + &SContext); + else + { + const ndr_context_handle *context_ndr = pBuff; + if (context_ndr->attributes) + { + ERR("non-null attributes 0x%x\n", context_ndr->attributes); + status = ERROR_INVALID_HANDLE; + } + else + status = RpcServerAssoc_FindContextHandle(binding->Assoc, + &context_ndr->uuid, + CtxGuard, Flags, + &SContext); + } + + if (status != RPC_S_OK) + RpcRaiseException(status); + + RPCRT4_PushThreadContextHandle(SContext); + return SContext; +} diff --git a/reactos/dll/win32/rpcrt4_new/ndr_fullpointer.c b/reactos/dll/win32/rpcrt4_new/ndr_fullpointer.c index 5640769783d..e3d37e2dc1d 100644 --- a/reactos/dll/win32/rpcrt4_new/ndr_fullpointer.c +++ b/reactos/dll/win32/rpcrt4_new/ndr_fullpointer.c @@ -1,233 +1,239 @@ -/* - * Full Pointer Translation Routines - * - * Copyright 2006 Robert Shearman - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include - -#include "windef.h" -#include "winbase.h" -#include "rpc.h" -#include "rpcndr.h" - -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(rpc); - -PFULL_PTR_XLAT_TABLES WINAPI NdrFullPointerXlatInit(ULONG NumberOfPointers, - XLAT_SIDE XlatSide) -{ - ULONG NumberOfBuckets; - PFULL_PTR_XLAT_TABLES pXlatTables = HeapAlloc(GetProcessHeap(), 0, sizeof(*pXlatTables)); - - TRACE("(%d, %d)\n", NumberOfPointers, XlatSide); - - if (!NumberOfPointers) NumberOfPointers = 512; - NumberOfBuckets = ((NumberOfPointers + 3) & ~3) - 1; - - pXlatTables->RefIdToPointer.XlatTable = - HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, - sizeof(void *) * NumberOfPointers); - pXlatTables->RefIdToPointer.StateTable = - HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, - sizeof(unsigned char) * NumberOfPointers); - pXlatTables->RefIdToPointer.NumberOfEntries = NumberOfPointers; - - TRACE("NumberOfBuckets = %d\n", NumberOfBuckets); - pXlatTables->PointerToRefId.XlatTable = - HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, - sizeof(PFULL_PTR_TO_REFID_ELEMENT) * NumberOfBuckets); - pXlatTables->PointerToRefId.NumberOfBuckets = NumberOfBuckets; - pXlatTables->PointerToRefId.HashMask = NumberOfBuckets - 1; - - pXlatTables->NextRefId = 1; - pXlatTables->XlatSide = XlatSide; - - return pXlatTables; -} - -void WINAPI NdrFullPointerXlatFree(PFULL_PTR_XLAT_TABLES pXlatTables) -{ - TRACE("(%p)\n", pXlatTables); - - HeapFree(GetProcessHeap(), 0, pXlatTables->RefIdToPointer.XlatTable); - HeapFree(GetProcessHeap(), 0, pXlatTables->RefIdToPointer.StateTable); - HeapFree(GetProcessHeap(), 0, pXlatTables->PointerToRefId.XlatTable); - - HeapFree(GetProcessHeap(), 0, pXlatTables); -} - -static void expand_pointer_table_if_necessary(PFULL_PTR_XLAT_TABLES pXlatTables, ULONG RefId) -{ - if (RefId >= pXlatTables->RefIdToPointer.NumberOfEntries) - { - pXlatTables->RefIdToPointer.NumberOfEntries = RefId * 2; - pXlatTables->RefIdToPointer.XlatTable = - HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, - pXlatTables->RefIdToPointer.XlatTable, - sizeof(void *) * pXlatTables->RefIdToPointer.NumberOfEntries); - pXlatTables->RefIdToPointer.StateTable = - HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, - pXlatTables->RefIdToPointer.StateTable, - sizeof(unsigned char) * pXlatTables->RefIdToPointer.NumberOfEntries); - - if (!pXlatTables->RefIdToPointer.XlatTable || !pXlatTables->RefIdToPointer.StateTable) - pXlatTables->RefIdToPointer.NumberOfEntries = 0; - } -} - -int WINAPI NdrFullPointerQueryPointer(PFULL_PTR_XLAT_TABLES pXlatTables, - void *pPointer, unsigned char QueryType, - ULONG *pRefId ) -{ - ULONG Hash = 0; - int i; - PFULL_PTR_TO_REFID_ELEMENT XlatTableEntry; - - TRACE("(%p, %p, %d, %p)\n", pXlatTables, pPointer, QueryType, pRefId); - - if (!pPointer) - { - *pRefId = 0; - return 1; - } - - /* simple hashing algorithm, don't know whether it matches native */ - for (i = 0; i < sizeof(pPointer); i++) - Hash = (Hash * 3) ^ ((unsigned char *)&pPointer)[i]; - - XlatTableEntry = pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask]; - for (; XlatTableEntry; XlatTableEntry = XlatTableEntry->Next) - if (pPointer == XlatTableEntry->Pointer) - { - *pRefId = XlatTableEntry->RefId; - if (XlatTableEntry->State & QueryType) - return 1; - XlatTableEntry->State |= QueryType; - return 0; - } - - XlatTableEntry = HeapAlloc(GetProcessHeap(), 0, sizeof(*XlatTableEntry)); - XlatTableEntry->Next = pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask]; - XlatTableEntry->Pointer = pPointer; - XlatTableEntry->RefId = *pRefId = pXlatTables->NextRefId++; - XlatTableEntry->State = QueryType; - pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask] = XlatTableEntry; - - /* insert pointer into mapping table */ - expand_pointer_table_if_necessary(pXlatTables, XlatTableEntry->RefId); - if (pXlatTables->RefIdToPointer.NumberOfEntries > XlatTableEntry->RefId) - { - pXlatTables->RefIdToPointer.XlatTable[XlatTableEntry->RefId] = pPointer; - pXlatTables->RefIdToPointer.StateTable[XlatTableEntry->RefId] = QueryType; - } - - return 0; -} - -int WINAPI NdrFullPointerQueryRefId(PFULL_PTR_XLAT_TABLES pXlatTables, - ULONG RefId, unsigned char QueryType, - void **ppPointer) -{ - TRACE("(%p, 0x%x, %d, %p)\n", pXlatTables, RefId, QueryType, ppPointer); - - expand_pointer_table_if_necessary(pXlatTables, RefId); - - pXlatTables->NextRefId = max(RefId + 1, pXlatTables->NextRefId); - - if (pXlatTables->RefIdToPointer.NumberOfEntries > RefId) - { - *ppPointer = pXlatTables->RefIdToPointer.XlatTable[RefId]; - if (QueryType) - { - if (pXlatTables->RefIdToPointer.StateTable[RefId] & QueryType) - return 1; - pXlatTables->RefIdToPointer.StateTable[RefId] |= QueryType; - return 0; - } - else - return 0; - } - *ppPointer = NULL; - return 0; -} - -void WINAPI NdrFullPointerInsertRefId(PFULL_PTR_XLAT_TABLES pXlatTables, - ULONG RefId, void *pPointer) -{ - ULONG Hash = 0; - int i; - PFULL_PTR_TO_REFID_ELEMENT XlatTableEntry; - - TRACE("(%p, 0x%x, %p)\n", pXlatTables, RefId, pPointer); - - /* simple hashing algorithm, don't know whether it matches native */ - for (i = 0; i < sizeof(pPointer); i++) - Hash = (Hash * 3) ^ ((unsigned char *)&pPointer)[i]; - - XlatTableEntry = HeapAlloc(GetProcessHeap(), 0, sizeof(*XlatTableEntry)); - XlatTableEntry->Next = pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask]; - XlatTableEntry->Pointer = pPointer; - XlatTableEntry->RefId = RefId; - XlatTableEntry->State = 0; - pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask] = XlatTableEntry; - - /* insert pointer into mapping table */ - expand_pointer_table_if_necessary(pXlatTables, RefId); - if (pXlatTables->RefIdToPointer.NumberOfEntries > RefId) - pXlatTables->RefIdToPointer.XlatTable[XlatTableEntry->RefId] = pPointer; -} - -int WINAPI NdrFullPointerFree(PFULL_PTR_XLAT_TABLES pXlatTables, void *Pointer) -{ - ULONG Hash = 0; - int i; - PFULL_PTR_TO_REFID_ELEMENT XlatTableEntry; - ULONG RefId = 0; - - TRACE("(%p, %p)\n", pXlatTables, Pointer); - - if (!Pointer) - return 1; - - /* simple hashing algorithm, don't know whether it matches native */ - for (i = 0; i < sizeof(Pointer); i++) - Hash = (Hash * 3) ^ ((unsigned char *)&Pointer)[i]; - - XlatTableEntry = pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask]; - for (; XlatTableEntry; XlatTableEntry = XlatTableEntry->Next) - if (Pointer == XlatTableEntry->Pointer) - { - if (XlatTableEntry->State & 0x20) - return 0; - XlatTableEntry->State |= 0x20; - RefId = XlatTableEntry->RefId; - break; - } - - if (!XlatTableEntry) - return 0; - - if (pXlatTables->RefIdToPointer.NumberOfEntries > RefId) - { - pXlatTables->RefIdToPointer.StateTable[RefId] |= 0x20; - return 1; - } - - return 0; -} +/* + * Full Pointer Translation Routines + * + * Copyright 2006 Robert Shearman + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include + +#include "windef.h" +#include "winbase.h" +#include "rpc.h" +#include "rpcndr.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(rpc); + +PFULL_PTR_XLAT_TABLES WINAPI NdrFullPointerXlatInit(ULONG NumberOfPointers, + XLAT_SIDE XlatSide) +{ + ULONG NumberOfBuckets; + PFULL_PTR_XLAT_TABLES pXlatTables = HeapAlloc(GetProcessHeap(), 0, sizeof(*pXlatTables)); + + TRACE("(%d, %d)\n", NumberOfPointers, XlatSide); + + if (!NumberOfPointers) NumberOfPointers = 512; + NumberOfBuckets = ((NumberOfPointers + 3) & ~3) - 1; + + pXlatTables->RefIdToPointer.XlatTable = + HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof(void *) * NumberOfPointers); + pXlatTables->RefIdToPointer.StateTable = + HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof(unsigned char) * NumberOfPointers); + pXlatTables->RefIdToPointer.NumberOfEntries = NumberOfPointers; + + TRACE("NumberOfBuckets = %d\n", NumberOfBuckets); + pXlatTables->PointerToRefId.XlatTable = + HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof(PFULL_PTR_TO_REFID_ELEMENT) * NumberOfBuckets); + pXlatTables->PointerToRefId.NumberOfBuckets = NumberOfBuckets; + pXlatTables->PointerToRefId.HashMask = NumberOfBuckets - 1; + + pXlatTables->NextRefId = 1; + pXlatTables->XlatSide = XlatSide; + + return pXlatTables; +} + +void WINAPI NdrFullPointerXlatFree(PFULL_PTR_XLAT_TABLES pXlatTables) +{ + ULONG i; + + TRACE("(%p)\n", pXlatTables); + + /* free the entries in the table */ + for (i = 0; i < pXlatTables->RefIdToPointer.NumberOfEntries; i++) + HeapFree(GetProcessHeap(), 0, pXlatTables->RefIdToPointer.XlatTable[i]); + + HeapFree(GetProcessHeap(), 0, pXlatTables->RefIdToPointer.XlatTable); + HeapFree(GetProcessHeap(), 0, pXlatTables->RefIdToPointer.StateTable); + HeapFree(GetProcessHeap(), 0, pXlatTables->PointerToRefId.XlatTable); + + HeapFree(GetProcessHeap(), 0, pXlatTables); +} + +static void expand_pointer_table_if_necessary(PFULL_PTR_XLAT_TABLES pXlatTables, ULONG RefId) +{ + if (RefId >= pXlatTables->RefIdToPointer.NumberOfEntries) + { + pXlatTables->RefIdToPointer.NumberOfEntries = RefId * 2; + pXlatTables->RefIdToPointer.XlatTable = + HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + pXlatTables->RefIdToPointer.XlatTable, + sizeof(void *) * pXlatTables->RefIdToPointer.NumberOfEntries); + pXlatTables->RefIdToPointer.StateTable = + HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + pXlatTables->RefIdToPointer.StateTable, + sizeof(unsigned char) * pXlatTables->RefIdToPointer.NumberOfEntries); + + if (!pXlatTables->RefIdToPointer.XlatTable || !pXlatTables->RefIdToPointer.StateTable) + pXlatTables->RefIdToPointer.NumberOfEntries = 0; + } +} + +int WINAPI NdrFullPointerQueryPointer(PFULL_PTR_XLAT_TABLES pXlatTables, + void *pPointer, unsigned char QueryType, + ULONG *pRefId ) +{ + ULONG Hash = 0; + int i; + PFULL_PTR_TO_REFID_ELEMENT XlatTableEntry; + + TRACE("(%p, %p, %d, %p)\n", pXlatTables, pPointer, QueryType, pRefId); + + if (!pPointer) + { + *pRefId = 0; + return 1; + } + + /* simple hashing algorithm, don't know whether it matches native */ + for (i = 0; i < sizeof(pPointer); i++) + Hash = (Hash * 3) ^ ((unsigned char *)&pPointer)[i]; + + XlatTableEntry = pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask]; + for (; XlatTableEntry; XlatTableEntry = XlatTableEntry->Next) + if (pPointer == XlatTableEntry->Pointer) + { + *pRefId = XlatTableEntry->RefId; + if (XlatTableEntry->State & QueryType) + return 1; + XlatTableEntry->State |= QueryType; + return 0; + } + + XlatTableEntry = HeapAlloc(GetProcessHeap(), 0, sizeof(*XlatTableEntry)); + XlatTableEntry->Next = pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask]; + XlatTableEntry->Pointer = pPointer; + XlatTableEntry->RefId = *pRefId = pXlatTables->NextRefId++; + XlatTableEntry->State = QueryType; + pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask] = XlatTableEntry; + + /* insert pointer into mapping table */ + expand_pointer_table_if_necessary(pXlatTables, XlatTableEntry->RefId); + if (pXlatTables->RefIdToPointer.NumberOfEntries > XlatTableEntry->RefId) + { + pXlatTables->RefIdToPointer.XlatTable[XlatTableEntry->RefId] = pPointer; + pXlatTables->RefIdToPointer.StateTable[XlatTableEntry->RefId] = QueryType; + } + + return 0; +} + +int WINAPI NdrFullPointerQueryRefId(PFULL_PTR_XLAT_TABLES pXlatTables, + ULONG RefId, unsigned char QueryType, + void **ppPointer) +{ + TRACE("(%p, 0x%x, %d, %p)\n", pXlatTables, RefId, QueryType, ppPointer); + + expand_pointer_table_if_necessary(pXlatTables, RefId); + + pXlatTables->NextRefId = max(RefId + 1, pXlatTables->NextRefId); + + if (pXlatTables->RefIdToPointer.NumberOfEntries > RefId) + { + *ppPointer = pXlatTables->RefIdToPointer.XlatTable[RefId]; + if (QueryType) + { + if (pXlatTables->RefIdToPointer.StateTable[RefId] & QueryType) + return 1; + pXlatTables->RefIdToPointer.StateTable[RefId] |= QueryType; + return 0; + } + else + return 0; + } + *ppPointer = NULL; + return 0; +} + +void WINAPI NdrFullPointerInsertRefId(PFULL_PTR_XLAT_TABLES pXlatTables, + ULONG RefId, void *pPointer) +{ + ULONG Hash = 0; + int i; + PFULL_PTR_TO_REFID_ELEMENT XlatTableEntry; + + TRACE("(%p, 0x%x, %p)\n", pXlatTables, RefId, pPointer); + + /* simple hashing algorithm, don't know whether it matches native */ + for (i = 0; i < sizeof(pPointer); i++) + Hash = (Hash * 3) ^ ((unsigned char *)&pPointer)[i]; + + XlatTableEntry = HeapAlloc(GetProcessHeap(), 0, sizeof(*XlatTableEntry)); + XlatTableEntry->Next = pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask]; + XlatTableEntry->Pointer = pPointer; + XlatTableEntry->RefId = RefId; + XlatTableEntry->State = 0; + pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask] = XlatTableEntry; + + /* insert pointer into mapping table */ + expand_pointer_table_if_necessary(pXlatTables, RefId); + if (pXlatTables->RefIdToPointer.NumberOfEntries > RefId) + pXlatTables->RefIdToPointer.XlatTable[XlatTableEntry->RefId] = pPointer; +} + +int WINAPI NdrFullPointerFree(PFULL_PTR_XLAT_TABLES pXlatTables, void *Pointer) +{ + ULONG Hash = 0; + int i; + PFULL_PTR_TO_REFID_ELEMENT XlatTableEntry; + ULONG RefId = 0; + + TRACE("(%p, %p)\n", pXlatTables, Pointer); + + if (!Pointer) + return 1; + + /* simple hashing algorithm, don't know whether it matches native */ + for (i = 0; i < sizeof(Pointer); i++) + Hash = (Hash * 3) ^ ((unsigned char *)&Pointer)[i]; + + XlatTableEntry = pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask]; + for (; XlatTableEntry; XlatTableEntry = XlatTableEntry->Next) + if (Pointer == XlatTableEntry->Pointer) + { + if (XlatTableEntry->State & 0x20) + return 0; + XlatTableEntry->State |= 0x20; + RefId = XlatTableEntry->RefId; + break; + } + + if (!XlatTableEntry) + return 0; + + if (pXlatTables->RefIdToPointer.NumberOfEntries > RefId) + { + pXlatTables->RefIdToPointer.StateTable[RefId] |= 0x20; + return 1; + } + + return 0; +} diff --git a/reactos/dll/win32/rpcrt4_new/ndr_marshall.c b/reactos/dll/win32/rpcrt4_new/ndr_marshall.c index de84410d6a3..e1a4e417732 100644 --- a/reactos/dll/win32/rpcrt4_new/ndr_marshall.c +++ b/reactos/dll/win32/rpcrt4_new/ndr_marshall.c @@ -1,5946 +1,6334 @@ -/* - * NDR data marshalling - * - * Copyright 2002 Greg Turner - * Copyright 2003-2006 CodeWeavers - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - * - * TODO: - * - Non-conformant strings - * - String structs - * - Byte count pointers - * - transmit_as/represent as - * - Multi-dimensional arrays - * - Conversion functions (NdrConvert) - * - Checks for integer addition overflow - * - Checks for out-of-memory conditions - */ - -#include -#include -#include -#include -#include - -#include "windef.h" -#include "winbase.h" -#include "winerror.h" - -#include "ndr_misc.h" -#include "rpcndr.h" - -#include "wine/unicode.h" -#include "wine/rpcfc.h" - -#include "wine/debug.h" -#include "wine/list.h" - -WINE_DEFAULT_DEBUG_CHANNEL(ole); - -#if defined(__i386__) -# define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \ - (*((UINT32 *)(pchar)) = (uint32)) - -# define LITTLE_ENDIAN_UINT32_READ(pchar) \ - (*((UINT32 *)(pchar))) -#else - /* these would work for i386 too, but less efficient */ -# define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \ - (*(pchar) = LOBYTE(LOWORD(uint32)), \ - *((pchar)+1) = HIBYTE(LOWORD(uint32)), \ - *((pchar)+2) = LOBYTE(HIWORD(uint32)), \ - *((pchar)+3) = HIBYTE(HIWORD(uint32)), \ - (uint32)) /* allow as r-value */ - -# define LITTLE_ENDIAN_UINT32_READ(pchar) \ - (MAKELONG( \ - MAKEWORD(*(pchar), *((pchar)+1)), \ - MAKEWORD(*((pchar)+2), *((pchar)+3)))) -#endif - -#define BIG_ENDIAN_UINT32_WRITE(pchar, uint32) \ - (*((pchar)+3) = LOBYTE(LOWORD(uint32)), \ - *((pchar)+2) = HIBYTE(LOWORD(uint32)), \ - *((pchar)+1) = LOBYTE(HIWORD(uint32)), \ - *(pchar) = HIBYTE(HIWORD(uint32)), \ - (uint32)) /* allow as r-value */ - -#define BIG_ENDIAN_UINT32_READ(pchar) \ - (MAKELONG( \ - MAKEWORD(*((pchar)+3), *((pchar)+2)), \ - MAKEWORD(*((pchar)+1), *(pchar)))) - -#ifdef NDR_LOCAL_IS_BIG_ENDIAN -# define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \ - BIG_ENDIAN_UINT32_WRITE(pchar, uint32) -# define NDR_LOCAL_UINT32_READ(pchar) \ - BIG_ENDIAN_UINT32_READ(pchar) -#else -# define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \ - LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) -# define NDR_LOCAL_UINT32_READ(pchar) \ - LITTLE_ENDIAN_UINT32_READ(pchar) -#endif - -/* _Align must be the desired alignment, - * e.g. ALIGN_LENGTH(len, 4) to align on a dword boundary. */ -#define ALIGNED_LENGTH(_Len, _Align) (((_Len)+(_Align)-1)&~((_Align)-1)) -#define ALIGNED_POINTER(_Ptr, _Align) ((LPVOID)ALIGNED_LENGTH((ULONG_PTR)(_Ptr), _Align)) -#define ALIGN_LENGTH(_Len, _Align) _Len = ALIGNED_LENGTH(_Len, _Align) -#define ALIGN_POINTER(_Ptr, _Align) _Ptr = ALIGNED_POINTER(_Ptr, _Align) - -#define STD_OVERFLOW_CHECK(_Msg) do { \ - TRACE("buffer=%d/%d\n", _Msg->Buffer - (unsigned char *)_Msg->RpcMsg->Buffer, _Msg->BufferLength); \ - if (_Msg->Buffer > (unsigned char *)_Msg->RpcMsg->Buffer + _Msg->BufferLength) \ - ERR("buffer overflow %d bytes\n", _Msg->Buffer - ((unsigned char *)_Msg->RpcMsg->Buffer + _Msg->BufferLength)); \ - } while (0) - -#define NDR_TABLE_SIZE 128 -#define NDR_TABLE_MASK 127 - -static unsigned char *WINAPI NdrBaseTypeMarshall(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING); -static unsigned char *WINAPI NdrBaseTypeUnmarshall(PMIDL_STUB_MESSAGE, unsigned char **, PFORMAT_STRING, unsigned char); -static void WINAPI NdrBaseTypeBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING); -static void WINAPI NdrBaseTypeFree(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING); -static ULONG WINAPI NdrBaseTypeMemorySize(PMIDL_STUB_MESSAGE, PFORMAT_STRING); - -static unsigned char *WINAPI NdrContextHandleMarshall(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING); -static void WINAPI NdrContextHandleBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING); -static unsigned char *WINAPI NdrContextHandleUnmarshall(PMIDL_STUB_MESSAGE, unsigned char **, PFORMAT_STRING, unsigned char); - -const NDR_MARSHALL NdrMarshaller[NDR_TABLE_SIZE] = { - 0, - NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, - NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, - NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, - NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, - /* 0x10 */ - NdrBaseTypeMarshall, - /* 0x11 */ - NdrPointerMarshall, NdrPointerMarshall, - NdrPointerMarshall, NdrPointerMarshall, - /* 0x15 */ - NdrSimpleStructMarshall, NdrSimpleStructMarshall, - NdrConformantStructMarshall, NdrConformantStructMarshall, - NdrConformantVaryingStructMarshall, - NdrComplexStructMarshall, - /* 0x1b */ - NdrConformantArrayMarshall, - NdrConformantVaryingArrayMarshall, - NdrFixedArrayMarshall, NdrFixedArrayMarshall, - NdrVaryingArrayMarshall, NdrVaryingArrayMarshall, - NdrComplexArrayMarshall, - /* 0x22 */ - NdrConformantStringMarshall, 0, 0, - NdrConformantStringMarshall, - NdrNonConformantStringMarshall, 0, 0, 0, - /* 0x2a */ - NdrEncapsulatedUnionMarshall, - NdrNonEncapsulatedUnionMarshall, - NdrByteCountPointerMarshall, - NdrXmitOrRepAsMarshall, NdrXmitOrRepAsMarshall, - /* 0x2f */ - NdrInterfacePointerMarshall, - /* 0x30 */ - NdrContextHandleMarshall, - /* 0xb1 */ - 0, 0, 0, - NdrUserMarshalMarshall, - 0, 0, - /* 0xb7 */ - NdrRangeMarshall -}; -const NDR_UNMARSHALL NdrUnmarshaller[NDR_TABLE_SIZE] = { - 0, - NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, - NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, - NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, - NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, - /* 0x10 */ - NdrBaseTypeUnmarshall, - /* 0x11 */ - NdrPointerUnmarshall, NdrPointerUnmarshall, - NdrPointerUnmarshall, NdrPointerUnmarshall, - /* 0x15 */ - NdrSimpleStructUnmarshall, NdrSimpleStructUnmarshall, - NdrConformantStructUnmarshall, NdrConformantStructUnmarshall, - NdrConformantVaryingStructUnmarshall, - NdrComplexStructUnmarshall, - /* 0x1b */ - NdrConformantArrayUnmarshall, - NdrConformantVaryingArrayUnmarshall, - NdrFixedArrayUnmarshall, NdrFixedArrayUnmarshall, - NdrVaryingArrayUnmarshall, NdrVaryingArrayUnmarshall, - NdrComplexArrayUnmarshall, - /* 0x22 */ - NdrConformantStringUnmarshall, 0, 0, - NdrConformantStringUnmarshall, - NdrNonConformantStringUnmarshall, 0, 0, 0, - /* 0x2a */ - NdrEncapsulatedUnionUnmarshall, - NdrNonEncapsulatedUnionUnmarshall, - NdrByteCountPointerUnmarshall, - NdrXmitOrRepAsUnmarshall, NdrXmitOrRepAsUnmarshall, - /* 0x2f */ - NdrInterfacePointerUnmarshall, - /* 0x30 */ - NdrContextHandleUnmarshall, - /* 0xb1 */ - 0, 0, 0, - NdrUserMarshalUnmarshall, - 0, 0, - /* 0xb7 */ - NdrRangeUnmarshall -}; -const NDR_BUFFERSIZE NdrBufferSizer[NDR_TABLE_SIZE] = { - 0, - NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, - NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, - NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, - NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, - /* 0x10 */ - NdrBaseTypeBufferSize, - /* 0x11 */ - NdrPointerBufferSize, NdrPointerBufferSize, - NdrPointerBufferSize, NdrPointerBufferSize, - /* 0x15 */ - NdrSimpleStructBufferSize, NdrSimpleStructBufferSize, - NdrConformantStructBufferSize, NdrConformantStructBufferSize, - NdrConformantVaryingStructBufferSize, - NdrComplexStructBufferSize, - /* 0x1b */ - NdrConformantArrayBufferSize, - NdrConformantVaryingArrayBufferSize, - NdrFixedArrayBufferSize, NdrFixedArrayBufferSize, - NdrVaryingArrayBufferSize, NdrVaryingArrayBufferSize, - NdrComplexArrayBufferSize, - /* 0x22 */ - NdrConformantStringBufferSize, 0, 0, - NdrConformantStringBufferSize, - NdrNonConformantStringBufferSize, 0, 0, 0, - /* 0x2a */ - NdrEncapsulatedUnionBufferSize, - NdrNonEncapsulatedUnionBufferSize, - NdrByteCountPointerBufferSize, - NdrXmitOrRepAsBufferSize, NdrXmitOrRepAsBufferSize, - /* 0x2f */ - NdrInterfacePointerBufferSize, - /* 0x30 */ - NdrContextHandleBufferSize, - /* 0xb1 */ - 0, 0, 0, - NdrUserMarshalBufferSize, - 0, 0, - /* 0xb7 */ - NdrRangeBufferSize -}; -const NDR_MEMORYSIZE NdrMemorySizer[NDR_TABLE_SIZE] = { - 0, - NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, - NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, - NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, - NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, - /* 0x10 */ - NdrBaseTypeMemorySize, - /* 0x11 */ - NdrPointerMemorySize, NdrPointerMemorySize, - NdrPointerMemorySize, NdrPointerMemorySize, - /* 0x15 */ - NdrSimpleStructMemorySize, NdrSimpleStructMemorySize, - NdrConformantStructMemorySize, NdrConformantStructMemorySize, - NdrConformantVaryingStructMemorySize, - NdrComplexStructMemorySize, - /* 0x1b */ - NdrConformantArrayMemorySize, - NdrConformantVaryingArrayMemorySize, - NdrFixedArrayMemorySize, NdrFixedArrayMemorySize, - NdrVaryingArrayMemorySize, NdrVaryingArrayMemorySize, - NdrComplexArrayMemorySize, - /* 0x22 */ - NdrConformantStringMemorySize, 0, 0, - NdrConformantStringMemorySize, - NdrNonConformantStringMemorySize, 0, 0, 0, - /* 0x2a */ - NdrEncapsulatedUnionMemorySize, - NdrNonEncapsulatedUnionMemorySize, - NdrByteCountPointerMemorySize, - NdrXmitOrRepAsMemorySize, NdrXmitOrRepAsMemorySize, - /* 0x2f */ - NdrInterfacePointerMemorySize, - /* 0x30 */ - 0, - /* 0xb1 */ - 0, 0, 0, - NdrUserMarshalMemorySize, - 0, 0, - /* 0xb7 */ - NdrRangeMemorySize -}; -const NDR_FREE NdrFreer[NDR_TABLE_SIZE] = { - 0, - NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, - NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, - NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, - NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, - /* 0x10 */ - NdrBaseTypeFree, - /* 0x11 */ - NdrPointerFree, NdrPointerFree, - NdrPointerFree, NdrPointerFree, - /* 0x15 */ - NdrSimpleStructFree, NdrSimpleStructFree, - NdrConformantStructFree, NdrConformantStructFree, - NdrConformantVaryingStructFree, - NdrComplexStructFree, - /* 0x1b */ - NdrConformantArrayFree, - NdrConformantVaryingArrayFree, - NdrFixedArrayFree, NdrFixedArrayFree, - NdrVaryingArrayFree, NdrVaryingArrayFree, - NdrComplexArrayFree, - /* 0x22 */ - 0, 0, 0, - 0, 0, 0, 0, 0, - /* 0x2a */ - NdrEncapsulatedUnionFree, - NdrNonEncapsulatedUnionFree, - 0, - NdrXmitOrRepAsFree, NdrXmitOrRepAsFree, - /* 0x2f */ - NdrInterfacePointerFree, - /* 0x30 */ - 0, - /* 0xb1 */ - 0, 0, 0, - NdrUserMarshalFree, - 0, 0, - /* 0xb7 */ - NdrRangeFree -}; - -void * WINAPI NdrAllocate(MIDL_STUB_MESSAGE *pStubMsg, size_t len) -{ - /* hmm, this is probably supposed to do more? */ - return pStubMsg->pfnAllocate(len); -} - -static void WINAPI NdrFree(MIDL_STUB_MESSAGE *pStubMsg, unsigned char *Pointer) -{ - pStubMsg->pfnFree(Pointer); -} - -static inline BOOL IsConformanceOrVariancePresent(PFORMAT_STRING pFormat) -{ - return (*(const ULONG *)pFormat != -1); -} - -static PFORMAT_STRING ReadConformance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat) -{ - ALIGN_POINTER(pStubMsg->Buffer, 4); - if (pStubMsg->Buffer + 4 > pStubMsg->BufferEnd) - RpcRaiseException(RPC_X_BAD_STUB_DATA); - pStubMsg->MaxCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer); - pStubMsg->Buffer += 4; - TRACE("unmarshalled conformance is %ld\n", pStubMsg->MaxCount); - if (pStubMsg->fHasNewCorrDesc) - return pFormat+6; - else - return pFormat+4; -} - -static inline PFORMAT_STRING ReadVariance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat, ULONG MaxValue) -{ - if (pFormat && !IsConformanceOrVariancePresent(pFormat)) - { - pStubMsg->Offset = 0; - pStubMsg->ActualCount = pStubMsg->MaxCount; - goto done; - } - - ALIGN_POINTER(pStubMsg->Buffer, 4); - if (pStubMsg->Buffer + 8 > pStubMsg->BufferEnd) - RpcRaiseException(RPC_X_BAD_STUB_DATA); - pStubMsg->Offset = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer); - pStubMsg->Buffer += 4; - TRACE("offset is %d\n", pStubMsg->Offset); - pStubMsg->ActualCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer); - pStubMsg->Buffer += 4; - TRACE("variance is %d\n", pStubMsg->ActualCount); - - if ((pStubMsg->ActualCount > MaxValue) || - (pStubMsg->ActualCount + pStubMsg->Offset > MaxValue)) - { - ERR("invalid array bound(s): ActualCount = %d, Offset = %d, MaxValue = %d\n", - pStubMsg->ActualCount, pStubMsg->Offset, MaxValue); - RpcRaiseException(RPC_S_INVALID_BOUND); - return NULL; - } - -done: - if (pStubMsg->fHasNewCorrDesc) - return pFormat+6; - else - return pFormat+4; -} - -/* writes the conformance value to the buffer */ -static inline void WriteConformance(MIDL_STUB_MESSAGE *pStubMsg) -{ - ALIGN_POINTER(pStubMsg->Buffer, 4); - NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->MaxCount); - pStubMsg->Buffer += 4; -} - -/* writes the variance values to the buffer */ -static inline void WriteVariance(MIDL_STUB_MESSAGE *pStubMsg) -{ - ALIGN_POINTER(pStubMsg->Buffer, 4); - NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->Offset); - pStubMsg->Buffer += 4; - NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->ActualCount); - pStubMsg->Buffer += 4; -} - -/* requests buffer space for the conformance value */ -static inline void SizeConformance(MIDL_STUB_MESSAGE *pStubMsg) -{ - ALIGN_LENGTH(pStubMsg->BufferLength, 4); - pStubMsg->BufferLength += 4; -} - -/* requests buffer space for the variance values */ -static inline void SizeVariance(MIDL_STUB_MESSAGE *pStubMsg) -{ - ALIGN_LENGTH(pStubMsg->BufferLength, 4); - pStubMsg->BufferLength += 8; -} - -PFORMAT_STRING ComputeConformanceOrVariance( - MIDL_STUB_MESSAGE *pStubMsg, unsigned char *pMemory, - PFORMAT_STRING pFormat, ULONG_PTR def, ULONG_PTR *pCount) -{ - BYTE dtype = pFormat[0] & 0xf; - short ofs = *(const short *)&pFormat[2]; - LPVOID ptr = NULL; - DWORD data = 0; - - if (!IsConformanceOrVariancePresent(pFormat)) { - /* null descriptor */ - *pCount = def; - goto finish_conf; - } - - switch (pFormat[0] & 0xf0) { - case RPC_FC_NORMAL_CONFORMANCE: - TRACE("normal conformance, ofs=%d\n", ofs); - ptr = pMemory; - break; - case RPC_FC_POINTER_CONFORMANCE: - TRACE("pointer conformance, ofs=%d\n", ofs); - ptr = pStubMsg->Memory; - break; - case RPC_FC_TOP_LEVEL_CONFORMANCE: - TRACE("toplevel conformance, ofs=%d\n", ofs); - if (pStubMsg->StackTop) { - ptr = pStubMsg->StackTop; - } - else { - /* -Os mode, *pCount is already set */ - goto finish_conf; - } - break; - case RPC_FC_CONSTANT_CONFORMANCE: - data = ofs | ((DWORD)pFormat[1] << 16); - TRACE("constant conformance, val=%d\n", data); - *pCount = data; - goto finish_conf; - case RPC_FC_TOP_LEVEL_MULTID_CONFORMANCE: - FIXME("toplevel multidimensional conformance, ofs=%d\n", ofs); - if (pStubMsg->StackTop) { - ptr = pStubMsg->StackTop; - } - else { - /* ? */ - goto done_conf_grab; - } - break; - default: - FIXME("unknown conformance type %x\n", pFormat[0] & 0xf0); - } - - switch (pFormat[1]) { - case RPC_FC_DEREFERENCE: - ptr = *(LPVOID*)((char *)ptr + ofs); - break; - case RPC_FC_CALLBACK: - { - unsigned char *old_stack_top = pStubMsg->StackTop; - pStubMsg->StackTop = ptr; - - /* ofs is index into StubDesc->apfnExprEval */ - TRACE("callback conformance into apfnExprEval[%d]\n", ofs); - pStubMsg->StubDesc->apfnExprEval[ofs](pStubMsg); - - pStubMsg->StackTop = old_stack_top; - - /* the callback function always stores the computed value in MaxCount */ - *pCount = pStubMsg->MaxCount; - goto finish_conf; - } - default: - ptr = (char *)ptr + ofs; - break; - } - - switch (dtype) { - case RPC_FC_LONG: - case RPC_FC_ULONG: - data = *(DWORD*)ptr; - break; - case RPC_FC_SHORT: - data = *(SHORT*)ptr; - break; - case RPC_FC_USHORT: - data = *(USHORT*)ptr; - break; - case RPC_FC_CHAR: - case RPC_FC_SMALL: - data = *(CHAR*)ptr; - break; - case RPC_FC_BYTE: - case RPC_FC_USMALL: - data = *(UCHAR*)ptr; - break; - default: - FIXME("unknown conformance data type %x\n", dtype); - goto done_conf_grab; - } - TRACE("dereferenced data type %x at %p, got %d\n", dtype, ptr, data); - -done_conf_grab: - switch (pFormat[1]) { - case RPC_FC_DEREFERENCE: /* already handled */ - case 0: /* no op */ - *pCount = data; - break; - case RPC_FC_ADD_1: - *pCount = data + 1; - break; - case RPC_FC_SUB_1: - *pCount = data - 1; - break; - case RPC_FC_MULT_2: - *pCount = data * 2; - break; - case RPC_FC_DIV_2: - *pCount = data / 2; - break; - default: - FIXME("unknown conformance op %d\n", pFormat[1]); - goto finish_conf; - } - -finish_conf: - TRACE("resulting conformance is %ld\n", *pCount); - if (pStubMsg->fHasNewCorrDesc) - return pFormat+6; - else - return pFormat+4; -} - -/* multiply two numbers together, raising an RPC_S_INVALID_BOUND exception if - * the result overflows 32-bits */ -static inline ULONG safe_multiply(ULONG a, ULONG b) -{ - ULONGLONG ret = (ULONGLONG)a * b; - if (ret > 0xffffffff) - { - RpcRaiseException(RPC_S_INVALID_BOUND); - return 0; - } - return ret; -} - -static inline void safe_buffer_increment(MIDL_STUB_MESSAGE *pStubMsg, ULONG size) -{ - if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */ - (pStubMsg->Buffer + size > pStubMsg->BufferEnd)) - RpcRaiseException(RPC_X_BAD_STUB_DATA); - pStubMsg->Buffer += size; -} - -/* copies data from the buffer, checking that there is enough data in the buffer - * to do so */ -static inline void safe_buffer_copy(MIDL_STUB_MESSAGE *pStubMsg, void *p, ULONG size) -{ - if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */ - (pStubMsg->Buffer + size > pStubMsg->BufferEnd)) - RpcRaiseException(RPC_X_BAD_STUB_DATA); - memcpy(p, pStubMsg->Buffer, size); - pStubMsg->Buffer += size; -} - -/* - * NdrConformantString: - * - * What MS calls a ConformantString is, in DCE terminology, - * a Varying-Conformant String. - * [ - * maxlen: DWORD (max # of CHARTYPE characters, inclusive of '\0') - * offset: DWORD (actual string data begins at (offset) CHARTYPE's - * into unmarshalled string) - * length: DWORD (# of CHARTYPE characters, inclusive of '\0') - * [ - * data: CHARTYPE[maxlen] - * ] - * ], where CHARTYPE is the appropriate character type (specified externally) - * - */ - -/*********************************************************************** - * NdrConformantStringMarshall [RPCRT4.@] - */ -unsigned char *WINAPI NdrConformantStringMarshall(MIDL_STUB_MESSAGE *pStubMsg, - unsigned char *pszMessage, PFORMAT_STRING pFormat) -{ - ULONG esize, size; - - TRACE("(pStubMsg == ^%p, pszMessage == ^%p, pFormat == ^%p)\n", pStubMsg, pszMessage, pFormat); - - if (*pFormat == RPC_FC_C_CSTRING) { - TRACE("string=%s\n", debugstr_a((char*)pszMessage)); - pStubMsg->ActualCount = strlen((char*)pszMessage)+1; - esize = 1; - } - else if (*pFormat == RPC_FC_C_WSTRING) { - TRACE("string=%s\n", debugstr_w((LPWSTR)pszMessage)); - pStubMsg->ActualCount = strlenW((LPWSTR)pszMessage)+1; - esize = 2; - } - else { - ERR("Unhandled string type: %#x\n", *pFormat); - /* FIXME: raise an exception. */ - return NULL; - } - - if (pFormat[1] == RPC_FC_STRING_SIZED) - pFormat = ComputeConformance(pStubMsg, pszMessage, pFormat + 2, 0); - else - pStubMsg->MaxCount = pStubMsg->ActualCount; - pStubMsg->Offset = 0; - WriteConformance(pStubMsg); - WriteVariance(pStubMsg); - - size = safe_multiply(esize, pStubMsg->ActualCount); - memcpy(pStubMsg->Buffer, pszMessage, size); /* the string itself */ - pStubMsg->Buffer += size; - - STD_OVERFLOW_CHECK(pStubMsg); - - /* success */ - return NULL; /* is this always right? */ -} - -/*********************************************************************** - * NdrConformantStringBufferSize [RPCRT4.@] - */ -void WINAPI NdrConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char* pMemory, PFORMAT_STRING pFormat) -{ - ULONG esize; - - TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat); - - SizeConformance(pStubMsg); - SizeVariance(pStubMsg); - - if (*pFormat == RPC_FC_C_CSTRING) { - TRACE("string=%s\n", debugstr_a((char*)pMemory)); - pStubMsg->ActualCount = strlen((char*)pMemory)+1; - esize = 1; - } - else if (*pFormat == RPC_FC_C_WSTRING) { - TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory)); - pStubMsg->ActualCount = strlenW((LPWSTR)pMemory)+1; - esize = 2; - } - else { - ERR("Unhandled string type: %#x\n", *pFormat); - /* FIXME: raise an exception */ - return; - } - - if (pFormat[1] == RPC_FC_STRING_SIZED) - pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 2, 0); - else - pStubMsg->MaxCount = pStubMsg->ActualCount; - - pStubMsg->BufferLength += safe_multiply(esize, pStubMsg->ActualCount); -} - -/************************************************************************ - * NdrConformantStringMemorySize [RPCRT4.@] - */ -ULONG WINAPI NdrConformantStringMemorySize( PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat ) -{ - ULONG rslt = 0; - - FIXME("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat); - - assert(pStubMsg && pFormat); - - if (*pFormat == RPC_FC_C_CSTRING) { - rslt = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer); /* maxlen */ - } - else if (*pFormat == RPC_FC_C_WSTRING) { - rslt = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer)*2; /* maxlen */ - } - else { - ERR("Unhandled string type: %#x\n", *pFormat); - /* FIXME: raise an exception */ - } - - if (pFormat[1] != RPC_FC_PAD) { - FIXME("sized string format=%d\n", pFormat[1]); - } - - TRACE(" --> %u\n", rslt); - return rslt; -} - -/************************************************************************ - * NdrConformantStringUnmarshall [RPCRT4.@] - */ -unsigned char *WINAPI NdrConformantStringUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, - unsigned char** ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc ) -{ - ULONG bufsize, memsize, esize, i; - - TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n", - pStubMsg, *ppMemory, pFormat, fMustAlloc); - - assert(pFormat && ppMemory && pStubMsg); - - ReadConformance(pStubMsg, NULL); - ReadVariance(pStubMsg, NULL, pStubMsg->MaxCount); - - if (*pFormat == RPC_FC_C_CSTRING) esize = 1; - else if (*pFormat == RPC_FC_C_WSTRING) esize = 2; - else { - ERR("Unhandled string type: %#x\n", *pFormat); - /* FIXME: raise an exception */ - esize = 0; - } - - memsize = safe_multiply(esize, pStubMsg->MaxCount); - bufsize = safe_multiply(esize, pStubMsg->ActualCount); - - /* strings must always have null terminating bytes */ - if (bufsize < esize) - { - ERR("invalid string length of %d\n", pStubMsg->ActualCount); - RpcRaiseException(RPC_S_INVALID_BOUND); - return NULL; - } - - /* verify the buffer is safe to access */ - if ((pStubMsg->Buffer + bufsize < pStubMsg->Buffer) || - (pStubMsg->Buffer + bufsize > pStubMsg->BufferEnd)) - { - ERR("bufsize 0x%x exceeded buffer end %p of buffer %p\n", bufsize, - pStubMsg->BufferEnd, pStubMsg->Buffer); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - return NULL; - } - - for (i = bufsize - esize; i < bufsize; i++) - if (pStubMsg->Buffer[i] != 0) - { - ERR("string not null-terminated at byte position %d, data is 0x%x\n", - i, pStubMsg->Buffer[i]); - RpcRaiseException(RPC_S_INVALID_BOUND); - return NULL; - } - - if (fMustAlloc || !*ppMemory) - *ppMemory = NdrAllocate(pStubMsg, memsize); - - safe_buffer_copy(pStubMsg, *ppMemory, bufsize); - - if (*pFormat == RPC_FC_C_CSTRING) { - TRACE("string=%s\n", debugstr_a((char*)*ppMemory)); - } - else if (*pFormat == RPC_FC_C_WSTRING) { - TRACE("string=%s\n", debugstr_w((LPWSTR)*ppMemory)); - } - - return NULL; /* FIXME: is this always right? */ -} - -/*********************************************************************** - * NdrNonConformantStringMarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrNonConformantStringMarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - FIXME("stub\n"); - return NULL; -} - -/*********************************************************************** - * NdrNonConformantStringUnmarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrNonConformantStringUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char **ppMemory, - PFORMAT_STRING pFormat, - unsigned char fMustAlloc) -{ - FIXME("stub\n"); - return NULL; -} - -/*********************************************************************** - * NdrNonConformantStringBufferSize [RPCRT4.@] - */ -void WINAPI NdrNonConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - FIXME("stub\n"); -} - -/*********************************************************************** - * NdrNonConformantStringMemorySize [RPCRT4.@] - */ -ULONG WINAPI NdrNonConformantStringMemorySize(PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat) -{ - FIXME("stub\n"); - return 0; -} - -static inline void dump_pointer_attr(unsigned char attr) -{ - if (attr & RPC_FC_P_ALLOCALLNODES) - TRACE(" RPC_FC_P_ALLOCALLNODES"); - if (attr & RPC_FC_P_DONTFREE) - TRACE(" RPC_FC_P_DONTFREE"); - if (attr & RPC_FC_P_ONSTACK) - TRACE(" RPC_FC_P_ONSTACK"); - if (attr & RPC_FC_P_SIMPLEPOINTER) - TRACE(" RPC_FC_P_SIMPLEPOINTER"); - if (attr & RPC_FC_P_DEREF) - TRACE(" RPC_FC_P_DEREF"); - TRACE("\n"); -} - -/*********************************************************************** - * PointerMarshall [internal] - */ -static void PointerMarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *Buffer, - unsigned char *Pointer, - PFORMAT_STRING pFormat) -{ - unsigned type = pFormat[0], attr = pFormat[1]; - PFORMAT_STRING desc; - NDR_MARSHALL m; - ULONG pointer_id; - int pointer_needs_marshaling; - - TRACE("(%p,%p,%p,%p)\n", pStubMsg, Buffer, Pointer, pFormat); - TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr); - pFormat += 2; - if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat; - else desc = pFormat + *(const SHORT*)pFormat; - - switch (type) { - case RPC_FC_RP: /* ref pointer (always non-null) */ -#if 0 /* this causes problems for InstallShield so is disabled - we need more tests */ - if (!Pointer) - RpcRaiseException(RPC_X_NULL_REF_POINTER); -#endif - pointer_needs_marshaling = 1; - break; - case RPC_FC_UP: /* unique pointer */ - case RPC_FC_OP: /* object pointer - same as unique here */ - if (Pointer) - pointer_needs_marshaling = 1; - else - pointer_needs_marshaling = 0; - pointer_id = (ULONG)Pointer; - TRACE("writing 0x%08x to buffer\n", pointer_id); - NDR_LOCAL_UINT32_WRITE(Buffer, pointer_id); - break; - case RPC_FC_FP: - pointer_needs_marshaling = !NdrFullPointerQueryPointer( - pStubMsg->FullPtrXlatTables, Pointer, 1, &pointer_id); - TRACE("writing 0x%08x to buffer\n", pointer_id); - NDR_LOCAL_UINT32_WRITE(Buffer, pointer_id); - break; - default: - FIXME("unhandled ptr type=%02x\n", type); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - return; - } - - TRACE("calling marshaller for type 0x%x\n", (int)*desc); - - if (pointer_needs_marshaling) { - if (attr & RPC_FC_P_DEREF) { - Pointer = *(unsigned char**)Pointer; - TRACE("deref => %p\n", Pointer); - } - m = NdrMarshaller[*desc & NDR_TABLE_MASK]; - if (m) m(pStubMsg, Pointer, desc); - else FIXME("no marshaller for data type=%02x\n", *desc); - } - - STD_OVERFLOW_CHECK(pStubMsg); -} - -/*********************************************************************** - * PointerUnmarshall [internal] - */ -static void PointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *Buffer, - unsigned char **pPointer, - PFORMAT_STRING pFormat, - unsigned char fMustAlloc) -{ - unsigned type = pFormat[0], attr = pFormat[1]; - PFORMAT_STRING desc; - NDR_UNMARSHALL m; - DWORD pointer_id = 0; - int pointer_needs_unmarshaling; - - TRACE("(%p,%p,%p,%p,%d)\n", pStubMsg, Buffer, pPointer, pFormat, fMustAlloc); - TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr); - pFormat += 2; - if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat; - else desc = pFormat + *(const SHORT*)pFormat; - - switch (type) { - case RPC_FC_RP: /* ref pointer (always non-null) */ - pointer_needs_unmarshaling = 1; - break; - case RPC_FC_UP: /* unique pointer */ - pointer_id = NDR_LOCAL_UINT32_READ(Buffer); - TRACE("pointer_id is 0x%08x\n", pointer_id); - if (pointer_id) - pointer_needs_unmarshaling = 1; - else { - *pPointer = NULL; - pointer_needs_unmarshaling = 0; - } - break; - case RPC_FC_OP: /* object pointer - we must free data before overwriting it */ - pointer_id = NDR_LOCAL_UINT32_READ(Buffer); - TRACE("pointer_id is 0x%08x\n", pointer_id); - if (!fMustAlloc && *pPointer) - { - FIXME("free object pointer %p\n", *pPointer); - *pPointer = NULL; - } - if (pointer_id) - pointer_needs_unmarshaling = 1; - else - pointer_needs_unmarshaling = 0; - break; - case RPC_FC_FP: - pointer_id = NDR_LOCAL_UINT32_READ(Buffer); - TRACE("pointer_id is 0x%08x\n", pointer_id); - pointer_needs_unmarshaling = !NdrFullPointerQueryRefId( - pStubMsg->FullPtrXlatTables, pointer_id, 1, (void **)pPointer); - break; - default: - FIXME("unhandled ptr type=%02x\n", type); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - return; - } - - if (pointer_needs_unmarshaling) { - if (attr & RPC_FC_P_DEREF) { - if (!*pPointer || fMustAlloc) - *pPointer = NdrAllocate(pStubMsg, sizeof(void *)); - pPointer = *(unsigned char***)pPointer; - TRACE("deref => %p\n", pPointer); - } - m = NdrUnmarshaller[*desc & NDR_TABLE_MASK]; - if (m) m(pStubMsg, pPointer, desc, fMustAlloc); - else FIXME("no unmarshaller for data type=%02x\n", *desc); - - if (type == RPC_FC_FP) - NdrFullPointerInsertRefId(pStubMsg->FullPtrXlatTables, pointer_id, - *pPointer); - } - - TRACE("pointer=%p\n", *pPointer); -} - -/*********************************************************************** - * PointerBufferSize [internal] - */ -static void PointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *Pointer, - PFORMAT_STRING pFormat) -{ - unsigned type = pFormat[0], attr = pFormat[1]; - PFORMAT_STRING desc; - NDR_BUFFERSIZE m; - int pointer_needs_sizing; - ULONG pointer_id; - - TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat); - TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr); - pFormat += 2; - if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat; - else desc = pFormat + *(const SHORT*)pFormat; - - switch (type) { - case RPC_FC_RP: /* ref pointer (always non-null) */ - break; - case RPC_FC_OP: - case RPC_FC_UP: - /* NULL pointer has no further representation */ - if (!Pointer) - return; - break; - case RPC_FC_FP: - pointer_needs_sizing = !NdrFullPointerQueryPointer( - pStubMsg->FullPtrXlatTables, Pointer, 0, &pointer_id); - if (!pointer_needs_sizing) - return; - break; - default: - FIXME("unhandled ptr type=%02x\n", type); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - return; - } - - if (attr & RPC_FC_P_DEREF) { - Pointer = *(unsigned char**)Pointer; - TRACE("deref => %p\n", Pointer); - } - - m = NdrBufferSizer[*desc & NDR_TABLE_MASK]; - if (m) m(pStubMsg, Pointer, desc); - else FIXME("no buffersizer for data type=%02x\n", *desc); -} - -/*********************************************************************** - * PointerMemorySize [internal] - */ -static unsigned long PointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *Buffer, - PFORMAT_STRING pFormat) -{ - unsigned type = pFormat[0], attr = pFormat[1]; - PFORMAT_STRING desc; - NDR_MEMORYSIZE m; - - FIXME("(%p,%p,%p): stub\n", pStubMsg, Buffer, pFormat); - TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr); - pFormat += 2; - if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat; - else desc = pFormat + *(const SHORT*)pFormat; - - switch (type) { - case RPC_FC_RP: /* ref pointer (always non-null) */ - break; - default: - FIXME("unhandled ptr type=%02x\n", type); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - } - - if (attr & RPC_FC_P_DEREF) { - TRACE("deref\n"); - } - - m = NdrMemorySizer[*desc & NDR_TABLE_MASK]; - if (m) m(pStubMsg, desc); - else FIXME("no memorysizer for data type=%02x\n", *desc); - - return 0; -} - -/*********************************************************************** - * PointerFree [internal] - */ -static void PointerFree(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *Pointer, - PFORMAT_STRING pFormat) -{ - unsigned type = pFormat[0], attr = pFormat[1]; - PFORMAT_STRING desc; - NDR_FREE m; - - TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat); - TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr); - if (attr & RPC_FC_P_DONTFREE) return; - pFormat += 2; - if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat; - else desc = pFormat + *(const SHORT*)pFormat; - - if (!Pointer) return; - - if (type == RPC_FC_FP) { - int pointer_needs_freeing = NdrFullPointerFree( - pStubMsg->FullPtrXlatTables, Pointer); - if (!pointer_needs_freeing) - return; - } - - if (attr & RPC_FC_P_DEREF) { - Pointer = *(unsigned char**)Pointer; - TRACE("deref => %p\n", Pointer); - } - - m = NdrFreer[*desc & NDR_TABLE_MASK]; - if (m) m(pStubMsg, Pointer, desc); - - /* hmm... is this sensible? - * perhaps we should check if the memory comes from NdrAllocate, - * and deallocate only if so - checking if the pointer is between - * BufferStart and BufferEnd is probably no good since the buffer - * may be reallocated when the server wants to marshal the reply */ - switch (*desc) { - case RPC_FC_BOGUS_STRUCT: - case RPC_FC_BOGUS_ARRAY: - case RPC_FC_USER_MARSHAL: - case RPC_FC_CARRAY: - case RPC_FC_CVARRAY: - break; - default: - FIXME("unhandled data type=%02x\n", *desc); - break; - case RPC_FC_C_CSTRING: - case RPC_FC_C_WSTRING: - if (pStubMsg->ReuseBuffer) goto notfree; - break; - case RPC_FC_IP: - goto notfree; - } - - if (attr & RPC_FC_P_ONSTACK) { - TRACE("not freeing stack ptr %p\n", Pointer); - return; - } - TRACE("freeing %p\n", Pointer); - NdrFree(pStubMsg, Pointer); - return; -notfree: - TRACE("not freeing %p\n", Pointer); -} - -/*********************************************************************** - * EmbeddedPointerMarshall - */ -static unsigned char * EmbeddedPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - unsigned char *Mark = pStubMsg->BufferMark; - unsigned long Offset = pStubMsg->Offset; - unsigned ofs, rep, count, stride, xofs; - unsigned i; - unsigned char *saved_buffer = NULL; - - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - - if (*pFormat != RPC_FC_PP) return NULL; - pFormat += 2; - - if (pStubMsg->PointerBufferMark) - { - saved_buffer = pStubMsg->Buffer; - pStubMsg->Buffer = pStubMsg->PointerBufferMark; - pStubMsg->PointerBufferMark = NULL; - } - - while (pFormat[0] != RPC_FC_END) { - switch (pFormat[0]) { - default: - FIXME("unknown repeat type %d\n", pFormat[0]); - case RPC_FC_NO_REPEAT: - rep = 1; - stride = 0; - ofs = 0; - count = 1; - xofs = 0; - pFormat += 2; - break; - case RPC_FC_FIXED_REPEAT: - rep = *(const WORD*)&pFormat[2]; - stride = *(const WORD*)&pFormat[4]; - ofs = *(const WORD*)&pFormat[6]; - count = *(const WORD*)&pFormat[8]; - xofs = 0; - pFormat += 10; - break; - case RPC_FC_VARIABLE_REPEAT: - rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount; - stride = *(const WORD*)&pFormat[2]; - ofs = *(const WORD*)&pFormat[4]; - count = *(const WORD*)&pFormat[6]; - xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0; - pFormat += 8; - break; - } - for (i = 0; i < rep; i++) { - PFORMAT_STRING info = pFormat; - unsigned char *membase = pMemory + ofs + (i * stride); - unsigned char *bufbase = Mark + ofs + (i * stride); - unsigned u; - - for (u=0; uMemory; - - pStubMsg->Memory = pMemory; - PointerMarshall(pStubMsg, bufptr, *(unsigned char**)memptr, info+4); - pStubMsg->Memory = saved_memory; - } - } - pFormat += 8 * count; - } - - if (saved_buffer) - { - pStubMsg->PointerBufferMark = pStubMsg->Buffer; - pStubMsg->Buffer = saved_buffer; - } - - STD_OVERFLOW_CHECK(pStubMsg); - - return NULL; -} - -/*********************************************************************** - * EmbeddedPointerUnmarshall - */ -static unsigned char * EmbeddedPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char **ppMemory, - PFORMAT_STRING pFormat, - unsigned char fMustAlloc) -{ - unsigned char *Mark = pStubMsg->BufferMark; - unsigned long Offset = pStubMsg->Offset; - unsigned ofs, rep, count, stride, xofs; - unsigned i; - unsigned char *saved_buffer = NULL; - - TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); - - if (*pFormat != RPC_FC_PP) return NULL; - pFormat += 2; - - if (pStubMsg->PointerBufferMark) - { - saved_buffer = pStubMsg->Buffer; - pStubMsg->Buffer = pStubMsg->PointerBufferMark; - pStubMsg->PointerBufferMark = NULL; - } - - while (pFormat[0] != RPC_FC_END) { - TRACE("pFormat[0] = 0x%x\n", pFormat[0]); - switch (pFormat[0]) { - default: - FIXME("unknown repeat type %d\n", pFormat[0]); - case RPC_FC_NO_REPEAT: - rep = 1; - stride = 0; - ofs = 0; - count = 1; - xofs = 0; - pFormat += 2; - break; - case RPC_FC_FIXED_REPEAT: - rep = *(const WORD*)&pFormat[2]; - stride = *(const WORD*)&pFormat[4]; - ofs = *(const WORD*)&pFormat[6]; - count = *(const WORD*)&pFormat[8]; - xofs = 0; - pFormat += 10; - break; - case RPC_FC_VARIABLE_REPEAT: - rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount; - stride = *(const WORD*)&pFormat[2]; - ofs = *(const WORD*)&pFormat[4]; - count = *(const WORD*)&pFormat[6]; - xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0; - pFormat += 8; - break; - } - /* ofs doesn't seem to matter in this context */ - for (i = 0; i < rep; i++) { - PFORMAT_STRING info = pFormat; - unsigned char *membase = *ppMemory + ofs + (i * stride); - unsigned char *bufbase = Mark + ofs + (i * stride); - unsigned u; - - for (u=0; uPointerBufferMark = pStubMsg->Buffer; - pStubMsg->Buffer = saved_buffer; - } - - return NULL; -} - -/*********************************************************************** - * EmbeddedPointerBufferSize - */ -static void EmbeddedPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - unsigned long Offset = pStubMsg->Offset; - unsigned ofs, rep, count, stride, xofs; - unsigned i; - ULONG saved_buffer_length = 0; - - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - - if (pStubMsg->IgnoreEmbeddedPointers) return; - - if (*pFormat != RPC_FC_PP) return; - pFormat += 2; - - if (pStubMsg->PointerLength) - { - saved_buffer_length = pStubMsg->BufferLength; - pStubMsg->BufferLength = pStubMsg->PointerLength; - pStubMsg->PointerLength = 0; - } - - while (pFormat[0] != RPC_FC_END) { - switch (pFormat[0]) { - default: - FIXME("unknown repeat type %d\n", pFormat[0]); - case RPC_FC_NO_REPEAT: - rep = 1; - stride = 0; - ofs = 0; - count = 1; - xofs = 0; - pFormat += 2; - break; - case RPC_FC_FIXED_REPEAT: - rep = *(const WORD*)&pFormat[2]; - stride = *(const WORD*)&pFormat[4]; - ofs = *(const WORD*)&pFormat[6]; - count = *(const WORD*)&pFormat[8]; - xofs = 0; - pFormat += 10; - break; - case RPC_FC_VARIABLE_REPEAT: - rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount; - stride = *(const WORD*)&pFormat[2]; - ofs = *(const WORD*)&pFormat[4]; - count = *(const WORD*)&pFormat[6]; - xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0; - pFormat += 8; - break; - } - for (i = 0; i < rep; i++) { - PFORMAT_STRING info = pFormat; - unsigned char *membase = pMemory + ofs + (i * stride); - unsigned u; - - for (u=0; uMemory; - - pStubMsg->Memory = pMemory; - PointerBufferSize(pStubMsg, *(unsigned char**)memptr, info+4); - pStubMsg->Memory = saved_memory; - } - } - pFormat += 8 * count; - } - - if (saved_buffer_length) - { - pStubMsg->PointerLength = pStubMsg->BufferLength; - pStubMsg->BufferLength = saved_buffer_length; - } -} - -/*********************************************************************** - * EmbeddedPointerMemorySize [internal] - */ -static unsigned long EmbeddedPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat) -{ - unsigned long Offset = pStubMsg->Offset; - unsigned char *Mark = pStubMsg->BufferMark; - unsigned ofs, rep, count, stride, xofs; - unsigned i; - - TRACE("(%p,%p)\n", pStubMsg, pFormat); - - if (pStubMsg->IgnoreEmbeddedPointers) return 0; - - FIXME("(%p,%p): stub\n", pStubMsg, pFormat); - - if (*pFormat != RPC_FC_PP) return 0; - pFormat += 2; - - while (pFormat[0] != RPC_FC_END) { - switch (pFormat[0]) { - default: - FIXME("unknown repeat type %d\n", pFormat[0]); - case RPC_FC_NO_REPEAT: - rep = 1; - stride = 0; - ofs = 0; - count = 1; - xofs = 0; - pFormat += 2; - break; - case RPC_FC_FIXED_REPEAT: - rep = *(const WORD*)&pFormat[2]; - stride = *(const WORD*)&pFormat[4]; - ofs = *(const WORD*)&pFormat[6]; - count = *(const WORD*)&pFormat[8]; - xofs = 0; - pFormat += 10; - break; - case RPC_FC_VARIABLE_REPEAT: - rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount; - stride = *(const WORD*)&pFormat[2]; - ofs = *(const WORD*)&pFormat[4]; - count = *(const WORD*)&pFormat[6]; - xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0; - pFormat += 8; - break; - } - /* ofs doesn't seem to matter in this context */ - for (i = 0; i < rep; i++) { - PFORMAT_STRING info = pFormat; - unsigned char *bufbase = Mark + ofs + (i * stride); - unsigned u; - for (u=0; uOffset; - unsigned ofs, rep, count, stride, xofs; - unsigned i; - - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - if (*pFormat != RPC_FC_PP) return; - pFormat += 2; - - while (pFormat[0] != RPC_FC_END) { - switch (pFormat[0]) { - default: - FIXME("unknown repeat type %d\n", pFormat[0]); - case RPC_FC_NO_REPEAT: - rep = 1; - stride = 0; - ofs = 0; - count = 1; - xofs = 0; - pFormat += 2; - break; - case RPC_FC_FIXED_REPEAT: - rep = *(const WORD*)&pFormat[2]; - stride = *(const WORD*)&pFormat[4]; - ofs = *(const WORD*)&pFormat[6]; - count = *(const WORD*)&pFormat[8]; - xofs = 0; - pFormat += 10; - break; - case RPC_FC_VARIABLE_REPEAT: - rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount; - stride = *(const WORD*)&pFormat[2]; - ofs = *(const WORD*)&pFormat[4]; - count = *(const WORD*)&pFormat[6]; - xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0; - pFormat += 8; - break; - } - for (i = 0; i < rep; i++) { - PFORMAT_STRING info = pFormat; - unsigned char *membase = pMemory + (i * stride); - unsigned u; - - for (u=0; uMemory; - - pStubMsg->Memory = pMemory; - PointerFree(pStubMsg, *(unsigned char**)memptr, info+4); - pStubMsg->Memory = saved_memory; - } - } - pFormat += 8 * count; - } -} - -/*********************************************************************** - * NdrPointerMarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - unsigned char *Buffer; - - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - - /* incremement the buffer here instead of in PointerMarshall, - * as that is used by embedded pointers which already handle the incrementing - * the buffer, and shouldn't write any additional pointer data to the wire */ - if (*pFormat != RPC_FC_RP) - { - ALIGN_POINTER(pStubMsg->Buffer, 4); - Buffer = pStubMsg->Buffer; - pStubMsg->Buffer += 4; - } - else - Buffer = pStubMsg->Buffer; - - PointerMarshall(pStubMsg, Buffer, pMemory, pFormat); - - STD_OVERFLOW_CHECK(pStubMsg); - - return NULL; -} - -/*********************************************************************** - * NdrPointerUnmarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char **ppMemory, - PFORMAT_STRING pFormat, - unsigned char fMustAlloc) -{ - unsigned char *Buffer; - - TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); - - /* incremement the buffer here instead of in PointerUnmarshall, - * as that is used by embedded pointers which already handle the incrementing - * the buffer, and shouldn't read any additional pointer data from the - * buffer */ - if (*pFormat != RPC_FC_RP) - { - ALIGN_POINTER(pStubMsg->Buffer, 4); - Buffer = pStubMsg->Buffer; - safe_buffer_increment(pStubMsg, 4); - } - else - Buffer = pStubMsg->Buffer; - - PointerUnmarshall(pStubMsg, Buffer, ppMemory, pFormat, fMustAlloc); - - return NULL; -} - -/*********************************************************************** - * NdrPointerBufferSize [RPCRT4.@] - */ -void WINAPI NdrPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - - /* incremement the buffer length here instead of in PointerBufferSize, - * as that is used by embedded pointers which already handle the buffer - * length, and shouldn't write anything more to the wire */ - if (*pFormat != RPC_FC_RP) - { - ALIGN_LENGTH(pStubMsg->BufferLength, 4); - pStubMsg->BufferLength += 4; - } - - PointerBufferSize(pStubMsg, pMemory, pFormat); -} - -/*********************************************************************** - * NdrPointerMemorySize [RPCRT4.@] - */ -ULONG WINAPI NdrPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat) -{ - /* unsigned size = *(LPWORD)(pFormat+2); */ - FIXME("(%p,%p): stub\n", pStubMsg, pFormat); - PointerMemorySize(pStubMsg, pStubMsg->Buffer, pFormat); - return 0; -} - -/*********************************************************************** - * NdrPointerFree [RPCRT4.@] - */ -void WINAPI NdrPointerFree(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - PointerFree(pStubMsg, pMemory, pFormat); -} - -/*********************************************************************** - * NdrSimpleTypeMarshall [RPCRT4.@] - */ -void WINAPI NdrSimpleTypeMarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, - unsigned char FormatChar ) -{ - NdrBaseTypeMarshall(pStubMsg, pMemory, &FormatChar); -} - -/*********************************************************************** - * NdrSimpleTypeUnmarshall [RPCRT4.@] - */ -void WINAPI NdrSimpleTypeUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, - unsigned char FormatChar ) -{ - NdrBaseTypeUnmarshall(pStubMsg, &pMemory, &FormatChar, 0); -} - -/*********************************************************************** - * NdrSimpleStructMarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrSimpleStructMarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - unsigned size = *(const WORD*)(pFormat+2); - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - - ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1); - - memcpy(pStubMsg->Buffer, pMemory, size); - pStubMsg->BufferMark = pStubMsg->Buffer; - pStubMsg->Buffer += size; - - if (pFormat[0] != RPC_FC_STRUCT) - EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat+4); - - STD_OVERFLOW_CHECK(pStubMsg); - - return NULL; -} - -/*********************************************************************** - * NdrSimpleStructUnmarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrSimpleStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char **ppMemory, - PFORMAT_STRING pFormat, - unsigned char fMustAlloc) -{ - unsigned size = *(const WORD*)(pFormat+2); - TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); - - ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1); - - if (fMustAlloc) { - *ppMemory = NdrAllocate(pStubMsg, size); - memcpy(*ppMemory, pStubMsg->Buffer, size); - } else { - if (!pStubMsg->IsClient && !*ppMemory) - /* for servers, we just point straight into the RPC buffer */ - *ppMemory = pStubMsg->Buffer; - else - /* for clients, memory should be provided by caller */ - memcpy(*ppMemory, pStubMsg->Buffer, size); - } - - pStubMsg->BufferMark = pStubMsg->Buffer; - pStubMsg->Buffer += size; - - if (pFormat[0] != RPC_FC_STRUCT) - EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat+4, fMustAlloc); - - return NULL; -} - -/*********************************************************************** - * NdrSimpleStructBufferSize [RPCRT4.@] - */ -void WINAPI NdrSimpleStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - unsigned size = *(const WORD*)(pFormat+2); - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - - ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1); - - pStubMsg->BufferLength += size; - if (pFormat[0] != RPC_FC_STRUCT) - EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat+4); -} - -/*********************************************************************** - * NdrSimpleStructMemorySize [RPCRT4.@] - */ -ULONG WINAPI NdrSimpleStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat) -{ - unsigned short size = *(const WORD *)(pFormat+2); - - TRACE("(%p,%p)\n", pStubMsg, pFormat); - - ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1); - pStubMsg->MemorySize += size; - pStubMsg->Buffer += size; - - if (pFormat[0] != RPC_FC_STRUCT) - EmbeddedPointerMemorySize(pStubMsg, pFormat+4); - return size; -} - -/*********************************************************************** - * NdrSimpleStructFree [RPCRT4.@] - */ -void WINAPI NdrSimpleStructFree(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - if (pFormat[0] != RPC_FC_STRUCT) - EmbeddedPointerFree(pStubMsg, pMemory, pFormat+4); -} - - -static unsigned long EmbeddedComplexSize(const MIDL_STUB_MESSAGE *pStubMsg, - PFORMAT_STRING pFormat) -{ - switch (*pFormat) { - case RPC_FC_STRUCT: - case RPC_FC_PSTRUCT: - case RPC_FC_CSTRUCT: - case RPC_FC_BOGUS_STRUCT: - case RPC_FC_SMFARRAY: - case RPC_FC_SMVARRAY: - return *(const WORD*)&pFormat[2]; - case RPC_FC_USER_MARSHAL: - return *(const WORD*)&pFormat[4]; - case RPC_FC_NON_ENCAPSULATED_UNION: - pFormat += 2; - if (pStubMsg->fHasNewCorrDesc) - pFormat += 6; - else - pFormat += 4; - - pFormat += *(const SHORT*)pFormat; - return *(const SHORT*)pFormat; - case RPC_FC_IP: - return sizeof(void *); - default: - FIXME("unhandled embedded type %02x\n", *pFormat); - } - return 0; -} - - -static unsigned long EmbeddedComplexMemorySize(PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat) -{ - NDR_MEMORYSIZE m = NdrMemorySizer[*pFormat & NDR_TABLE_MASK]; - - if (!m) - { - FIXME("no memorysizer for data type=%02x\n", *pFormat); - return 0; - } - - return m(pStubMsg, pFormat); -} - - -static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat, - PFORMAT_STRING pPointer) -{ - PFORMAT_STRING desc; - NDR_MARSHALL m; - unsigned long size; - - while (*pFormat != RPC_FC_END) { - switch (*pFormat) { - case RPC_FC_BYTE: - case RPC_FC_CHAR: - case RPC_FC_SMALL: - case RPC_FC_USMALL: - TRACE("byte=%d <= %p\n", *(WORD*)pMemory, pMemory); - memcpy(pStubMsg->Buffer, pMemory, 1); - pStubMsg->Buffer += 1; - pMemory += 1; - break; - case RPC_FC_WCHAR: - case RPC_FC_SHORT: - case RPC_FC_USHORT: - TRACE("short=%d <= %p\n", *(WORD*)pMemory, pMemory); - memcpy(pStubMsg->Buffer, pMemory, 2); - pStubMsg->Buffer += 2; - pMemory += 2; - break; - case RPC_FC_LONG: - case RPC_FC_ULONG: - case RPC_FC_ENUM32: - TRACE("long=%d <= %p\n", *(DWORD*)pMemory, pMemory); - memcpy(pStubMsg->Buffer, pMemory, 4); - pStubMsg->Buffer += 4; - pMemory += 4; - break; - case RPC_FC_HYPER: - TRACE("longlong=%s <= %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory); - memcpy(pStubMsg->Buffer, pMemory, 8); - pStubMsg->Buffer += 8; - pMemory += 8; - break; - case RPC_FC_POINTER: - { - unsigned char *saved_buffer; - int pointer_buffer_mark_set = 0; - TRACE("pointer=%p <= %p\n", *(unsigned char**)pMemory, pMemory); - saved_buffer = pStubMsg->Buffer; - if (pStubMsg->PointerBufferMark) - { - pStubMsg->Buffer = pStubMsg->PointerBufferMark; - pStubMsg->PointerBufferMark = NULL; - pointer_buffer_mark_set = 1; - } - else - pStubMsg->Buffer += 4; /* for pointer ID */ - PointerMarshall(pStubMsg, saved_buffer, *(unsigned char**)pMemory, pPointer); - if (pointer_buffer_mark_set) - { - STD_OVERFLOW_CHECK(pStubMsg); - pStubMsg->PointerBufferMark = pStubMsg->Buffer; - pStubMsg->Buffer = saved_buffer + 4; - } - pPointer += 4; - pMemory += 4; - break; - } - case RPC_FC_ALIGNM4: - ALIGN_POINTER(pMemory, 4); - break; - case RPC_FC_ALIGNM8: - ALIGN_POINTER(pMemory, 8); - break; - case RPC_FC_STRUCTPAD1: - case RPC_FC_STRUCTPAD2: - case RPC_FC_STRUCTPAD3: - case RPC_FC_STRUCTPAD4: - case RPC_FC_STRUCTPAD5: - case RPC_FC_STRUCTPAD6: - case RPC_FC_STRUCTPAD7: - pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1; - break; - case RPC_FC_EMBEDDED_COMPLEX: - pMemory += pFormat[1]; - pFormat += 2; - desc = pFormat + *(const SHORT*)pFormat; - size = EmbeddedComplexSize(pStubMsg, desc); - TRACE("embedded complex (size=%ld) <= %p\n", size, pMemory); - m = NdrMarshaller[*desc & NDR_TABLE_MASK]; - if (m) - { - /* for some reason interface pointers aren't generated as - * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet - * they still need the derefencing treatment that pointers are - * given */ - if (*desc == RPC_FC_IP) - m(pStubMsg, *(unsigned char **)pMemory, desc); - else - m(pStubMsg, pMemory, desc); - } - else FIXME("no marshaller for embedded type %02x\n", *desc); - pMemory += size; - pFormat += 2; - continue; - case RPC_FC_PAD: - break; - default: - FIXME("unhandled format 0x%02x\n", *pFormat); - } - pFormat++; - } - - return pMemory; -} - -static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat, - PFORMAT_STRING pPointer) -{ - PFORMAT_STRING desc; - NDR_UNMARSHALL m; - unsigned long size; - - while (*pFormat != RPC_FC_END) { - switch (*pFormat) { - case RPC_FC_BYTE: - case RPC_FC_CHAR: - case RPC_FC_SMALL: - case RPC_FC_USMALL: - safe_buffer_copy(pStubMsg, pMemory, 1); - TRACE("byte=%d => %p\n", *(WORD*)pMemory, pMemory); - pMemory += 1; - break; - case RPC_FC_WCHAR: - case RPC_FC_SHORT: - case RPC_FC_USHORT: - safe_buffer_copy(pStubMsg, pMemory, 2); - TRACE("short=%d => %p\n", *(WORD*)pMemory, pMemory); - pMemory += 2; - break; - case RPC_FC_LONG: - case RPC_FC_ULONG: - case RPC_FC_ENUM32: - safe_buffer_copy(pStubMsg, pMemory, 4); - TRACE("long=%d => %p\n", *(DWORD*)pMemory, pMemory); - pMemory += 4; - break; - case RPC_FC_HYPER: - safe_buffer_copy(pStubMsg, pMemory, 8); - TRACE("longlong=%s => %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory); - pMemory += 8; - break; - case RPC_FC_POINTER: - { - unsigned char *saved_buffer; - int pointer_buffer_mark_set = 0; - TRACE("pointer => %p\n", pMemory); - ALIGN_POINTER(pStubMsg->Buffer, 4); - saved_buffer = pStubMsg->Buffer; - if (pStubMsg->PointerBufferMark) - { - pStubMsg->Buffer = pStubMsg->PointerBufferMark; - pStubMsg->PointerBufferMark = NULL; - pointer_buffer_mark_set = 1; - } - else - pStubMsg->Buffer += 4; /* for pointer ID */ - - PointerUnmarshall(pStubMsg, saved_buffer, (unsigned char**)pMemory, pPointer, TRUE); - if (pointer_buffer_mark_set) - { - STD_OVERFLOW_CHECK(pStubMsg); - pStubMsg->PointerBufferMark = pStubMsg->Buffer; - pStubMsg->Buffer = saved_buffer + 4; - } - pPointer += 4; - pMemory += 4; - break; - } - case RPC_FC_ALIGNM4: - ALIGN_POINTER(pMemory, 4); - break; - case RPC_FC_ALIGNM8: - ALIGN_POINTER(pMemory, 8); - break; - case RPC_FC_STRUCTPAD1: - case RPC_FC_STRUCTPAD2: - case RPC_FC_STRUCTPAD3: - case RPC_FC_STRUCTPAD4: - case RPC_FC_STRUCTPAD5: - case RPC_FC_STRUCTPAD6: - case RPC_FC_STRUCTPAD7: - pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1; - break; - case RPC_FC_EMBEDDED_COMPLEX: - pMemory += pFormat[1]; - pFormat += 2; - desc = pFormat + *(const SHORT*)pFormat; - size = EmbeddedComplexSize(pStubMsg, desc); - TRACE("embedded complex (size=%ld) => %p\n", size, pMemory); - m = NdrUnmarshaller[*desc & NDR_TABLE_MASK]; - memset(pMemory, 0, size); /* just in case */ - if (m) - { - /* for some reason interface pointers aren't generated as - * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet - * they still need the derefencing treatment that pointers are - * given */ - if (*desc == RPC_FC_IP) - m(pStubMsg, (unsigned char **)pMemory, desc, FALSE); - else - m(pStubMsg, &pMemory, desc, FALSE); - } - else FIXME("no unmarshaller for embedded type %02x\n", *desc); - pMemory += size; - pFormat += 2; - continue; - case RPC_FC_PAD: - break; - default: - FIXME("unhandled format %d\n", *pFormat); - } - pFormat++; - } - - return pMemory; -} - -static unsigned char * ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat, - PFORMAT_STRING pPointer) -{ - PFORMAT_STRING desc; - NDR_BUFFERSIZE m; - unsigned long size; - - while (*pFormat != RPC_FC_END) { - switch (*pFormat) { - case RPC_FC_BYTE: - case RPC_FC_CHAR: - case RPC_FC_SMALL: - case RPC_FC_USMALL: - pStubMsg->BufferLength += 1; - pMemory += 1; - break; - case RPC_FC_WCHAR: - case RPC_FC_SHORT: - case RPC_FC_USHORT: - pStubMsg->BufferLength += 2; - pMemory += 2; - break; - case RPC_FC_LONG: - case RPC_FC_ULONG: - case RPC_FC_ENUM32: - pStubMsg->BufferLength += 4; - pMemory += 4; - break; - case RPC_FC_HYPER: - pStubMsg->BufferLength += 8; - pMemory += 8; - break; - case RPC_FC_POINTER: - if (!pStubMsg->IgnoreEmbeddedPointers) - { - int saved_buffer_length = pStubMsg->BufferLength; - pStubMsg->BufferLength = pStubMsg->PointerLength; - pStubMsg->PointerLength = 0; - if(!pStubMsg->BufferLength) - ERR("BufferLength == 0??\n"); - PointerBufferSize(pStubMsg, *(unsigned char**)pMemory, pPointer); - pStubMsg->PointerLength = pStubMsg->BufferLength; - pStubMsg->BufferLength = saved_buffer_length; - } - pStubMsg->BufferLength += 4; - pPointer += 4; - pMemory += 4; - break; - case RPC_FC_ALIGNM4: - ALIGN_POINTER(pMemory, 4); - break; - case RPC_FC_ALIGNM8: - ALIGN_POINTER(pMemory, 8); - break; - case RPC_FC_STRUCTPAD1: - case RPC_FC_STRUCTPAD2: - case RPC_FC_STRUCTPAD3: - case RPC_FC_STRUCTPAD4: - case RPC_FC_STRUCTPAD5: - case RPC_FC_STRUCTPAD6: - case RPC_FC_STRUCTPAD7: - pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1; - break; - case RPC_FC_EMBEDDED_COMPLEX: - pMemory += pFormat[1]; - pFormat += 2; - desc = pFormat + *(const SHORT*)pFormat; - size = EmbeddedComplexSize(pStubMsg, desc); - m = NdrBufferSizer[*desc & NDR_TABLE_MASK]; - if (m) - { - /* for some reason interface pointers aren't generated as - * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet - * they still need the derefencing treatment that pointers are - * given */ - if (*desc == RPC_FC_IP) - m(pStubMsg, *(unsigned char **)pMemory, desc); - else - m(pStubMsg, pMemory, desc); - } - else FIXME("no buffersizer for embedded type %02x\n", *desc); - pMemory += size; - pFormat += 2; - continue; - case RPC_FC_PAD: - break; - default: - FIXME("unhandled format 0x%02x\n", *pFormat); - } - pFormat++; - } - - return pMemory; -} - -static unsigned char * ComplexFree(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat, - PFORMAT_STRING pPointer) -{ - PFORMAT_STRING desc; - NDR_FREE m; - unsigned long size; - - while (*pFormat != RPC_FC_END) { - switch (*pFormat) { - case RPC_FC_BYTE: - case RPC_FC_CHAR: - case RPC_FC_SMALL: - case RPC_FC_USMALL: - pMemory += 1; - break; - case RPC_FC_WCHAR: - case RPC_FC_SHORT: - case RPC_FC_USHORT: - pMemory += 2; - break; - case RPC_FC_LONG: - case RPC_FC_ULONG: - case RPC_FC_ENUM32: - pMemory += 4; - break; - case RPC_FC_HYPER: - pMemory += 8; - break; - case RPC_FC_POINTER: - NdrPointerFree(pStubMsg, *(unsigned char**)pMemory, pPointer); - pPointer += 4; - pMemory += 4; - break; - case RPC_FC_ALIGNM4: - ALIGN_POINTER(pMemory, 4); - break; - case RPC_FC_ALIGNM8: - ALIGN_POINTER(pMemory, 8); - break; - case RPC_FC_STRUCTPAD1: - case RPC_FC_STRUCTPAD2: - case RPC_FC_STRUCTPAD3: - case RPC_FC_STRUCTPAD4: - case RPC_FC_STRUCTPAD5: - case RPC_FC_STRUCTPAD6: - case RPC_FC_STRUCTPAD7: - pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1; - break; - case RPC_FC_EMBEDDED_COMPLEX: - pMemory += pFormat[1]; - pFormat += 2; - desc = pFormat + *(const SHORT*)pFormat; - size = EmbeddedComplexSize(pStubMsg, desc); - m = NdrFreer[*desc & NDR_TABLE_MASK]; - if (m) - { - /* for some reason interface pointers aren't generated as - * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet - * they still need the derefencing treatment that pointers are - * given */ - if (*desc == RPC_FC_IP) - m(pStubMsg, *(unsigned char **)pMemory, desc); - else - m(pStubMsg, pMemory, desc); - } - else FIXME("no freer for embedded type %02x\n", *desc); - pMemory += size; - pFormat += 2; - continue; - case RPC_FC_PAD: - break; - default: - FIXME("unhandled format 0x%02x\n", *pFormat); - } - pFormat++; - } - - return pMemory; -} - -static unsigned long ComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat) -{ - PFORMAT_STRING desc; - unsigned long size = 0; - - while (*pFormat != RPC_FC_END) { - switch (*pFormat) { - case RPC_FC_BYTE: - case RPC_FC_CHAR: - case RPC_FC_SMALL: - case RPC_FC_USMALL: - size += 1; - pStubMsg->Buffer += 1; - break; - case RPC_FC_WCHAR: - case RPC_FC_SHORT: - case RPC_FC_USHORT: - size += 2; - pStubMsg->Buffer += 2; - break; - case RPC_FC_LONG: - case RPC_FC_ULONG: - case RPC_FC_ENUM32: - size += 4; - pStubMsg->Buffer += 4; - break; - case RPC_FC_HYPER: - size += 8; - pStubMsg->Buffer += 8; - break; - case RPC_FC_POINTER: - size += 4; - pStubMsg->Buffer += 4; - if (!pStubMsg->IgnoreEmbeddedPointers) - FIXME("embedded pointers\n"); - break; - case RPC_FC_ALIGNM4: - ALIGN_LENGTH(size, 4); - ALIGN_POINTER(pStubMsg->Buffer, 4); - break; - case RPC_FC_ALIGNM8: - ALIGN_LENGTH(size, 8); - ALIGN_POINTER(pStubMsg->Buffer, 8); - break; - case RPC_FC_STRUCTPAD1: - case RPC_FC_STRUCTPAD2: - case RPC_FC_STRUCTPAD3: - case RPC_FC_STRUCTPAD4: - case RPC_FC_STRUCTPAD5: - case RPC_FC_STRUCTPAD6: - case RPC_FC_STRUCTPAD7: - size += *pFormat - RPC_FC_STRUCTPAD1 + 1; - break; - case RPC_FC_EMBEDDED_COMPLEX: - size += pFormat[1]; - pFormat += 2; - desc = pFormat + *(const SHORT*)pFormat; - size += EmbeddedComplexMemorySize(pStubMsg, desc); - pFormat += 2; - continue; - case RPC_FC_PAD: - break; - default: - FIXME("unhandled format 0x%02x\n", *pFormat); - } - pFormat++; - } - - return size; -} - -/*********************************************************************** - * NdrComplexStructMarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrComplexStructMarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - PFORMAT_STRING conf_array = NULL; - PFORMAT_STRING pointer_desc = NULL; - unsigned char *OldMemory = pStubMsg->Memory; - int pointer_buffer_mark_set = 0; - - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - - if (!pStubMsg->PointerBufferMark) - { - int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers; - /* save buffer length */ - unsigned long saved_buffer_length = pStubMsg->BufferLength; - - /* get the buffer pointer after complex array data, but before - * pointer data */ - pStubMsg->BufferLength = pStubMsg->Buffer - pStubMsg->BufferStart; - pStubMsg->IgnoreEmbeddedPointers = 1; - NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat); - pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded; - - /* save it for use by embedded pointer code later */ - pStubMsg->PointerBufferMark = pStubMsg->BufferStart + pStubMsg->BufferLength; - TRACE("difference = 0x%x\n", pStubMsg->PointerBufferMark - pStubMsg->Buffer); - pointer_buffer_mark_set = 1; - - /* restore the original buffer length */ - pStubMsg->BufferLength = saved_buffer_length; - } - - ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1); - - pFormat += 4; - if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat; - pFormat += 2; - if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat; - pFormat += 2; - - pStubMsg->Memory = pMemory; - - ComplexMarshall(pStubMsg, pMemory, pFormat, pointer_desc); - - if (conf_array) - NdrConformantArrayMarshall(pStubMsg, pMemory, conf_array); - - pStubMsg->Memory = OldMemory; - - if (pointer_buffer_mark_set) - { - pStubMsg->Buffer = pStubMsg->PointerBufferMark; - pStubMsg->PointerBufferMark = NULL; - } - - STD_OVERFLOW_CHECK(pStubMsg); - - return NULL; -} - -/*********************************************************************** - * NdrComplexStructUnmarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrComplexStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char **ppMemory, - PFORMAT_STRING pFormat, - unsigned char fMustAlloc) -{ - unsigned size = *(const WORD*)(pFormat+2); - PFORMAT_STRING conf_array = NULL; - PFORMAT_STRING pointer_desc = NULL; - unsigned char *pMemory; - int pointer_buffer_mark_set = 0; - - TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); - - if (!pStubMsg->PointerBufferMark) - { - int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers; - /* save buffer pointer */ - unsigned char *saved_buffer = pStubMsg->Buffer; - - /* get the buffer pointer after complex array data, but before - * pointer data */ - pStubMsg->IgnoreEmbeddedPointers = 1; - NdrComplexStructMemorySize(pStubMsg, pFormat); - pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded; - - /* save it for use by embedded pointer code later */ - pStubMsg->PointerBufferMark = pStubMsg->Buffer; - TRACE("difference = 0x%lx\n", (unsigned long)(pStubMsg->PointerBufferMark - saved_buffer)); - pointer_buffer_mark_set = 1; - - /* restore the original buffer */ - pStubMsg->Buffer = saved_buffer; - } - - ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1); - - if (fMustAlloc || !*ppMemory) - { - *ppMemory = NdrAllocate(pStubMsg, size); - memset(*ppMemory, 0, size); - } - - pFormat += 4; - if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat; - pFormat += 2; - if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat; - pFormat += 2; - - pMemory = ComplexUnmarshall(pStubMsg, *ppMemory, pFormat, pointer_desc); - - if (conf_array) - NdrConformantArrayUnmarshall(pStubMsg, &pMemory, conf_array, fMustAlloc); - - if (pointer_buffer_mark_set) - { - pStubMsg->Buffer = pStubMsg->PointerBufferMark; - pStubMsg->PointerBufferMark = NULL; - } - - return NULL; -} - -/*********************************************************************** - * NdrComplexStructBufferSize [RPCRT4.@] - */ -void WINAPI NdrComplexStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - PFORMAT_STRING conf_array = NULL; - PFORMAT_STRING pointer_desc = NULL; - unsigned char *OldMemory = pStubMsg->Memory; - int pointer_length_set = 0; - - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - - ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1); - - if(!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength) - { - int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers; - unsigned long saved_buffer_length = pStubMsg->BufferLength; - - /* get the buffer length after complex struct data, but before - * pointer data */ - pStubMsg->IgnoreEmbeddedPointers = 1; - NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat); - pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded; - - /* save it for use by embedded pointer code later */ - pStubMsg->PointerLength = pStubMsg->BufferLength; - pointer_length_set = 1; - TRACE("difference = 0x%lx\n", pStubMsg->PointerLength - saved_buffer_length); - - /* restore the original buffer length */ - pStubMsg->BufferLength = saved_buffer_length; - } - - pFormat += 4; - if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat; - pFormat += 2; - if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat; - pFormat += 2; - - pStubMsg->Memory = pMemory; - - pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, pointer_desc); - - if (conf_array) - NdrConformantArrayBufferSize(pStubMsg, pMemory, conf_array); - - pStubMsg->Memory = OldMemory; - - if(pointer_length_set) - { - pStubMsg->BufferLength = pStubMsg->PointerLength; - pStubMsg->PointerLength = 0; - } - -} - -/*********************************************************************** - * NdrComplexStructMemorySize [RPCRT4.@] - */ -ULONG WINAPI NdrComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat) -{ - unsigned size = *(const WORD*)(pFormat+2); - PFORMAT_STRING conf_array = NULL; - PFORMAT_STRING pointer_desc = NULL; - - TRACE("(%p,%p)\n", pStubMsg, pFormat); - - ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1); - - pFormat += 4; - if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat; - pFormat += 2; - if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat; - pFormat += 2; - - ComplexStructMemorySize(pStubMsg, pFormat); - - if (conf_array) - NdrConformantArrayMemorySize(pStubMsg, conf_array); - - return size; -} - -/*********************************************************************** - * NdrComplexStructFree [RPCRT4.@] - */ -void WINAPI NdrComplexStructFree(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - PFORMAT_STRING conf_array = NULL; - PFORMAT_STRING pointer_desc = NULL; - unsigned char *OldMemory = pStubMsg->Memory; - - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - - pFormat += 4; - if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat; - pFormat += 2; - if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat; - pFormat += 2; - - pStubMsg->Memory = pMemory; - - pMemory = ComplexFree(pStubMsg, pMemory, pFormat, pointer_desc); - - if (conf_array) - NdrConformantArrayFree(pStubMsg, pMemory, conf_array); - - pStubMsg->Memory = OldMemory; -} - -/*********************************************************************** - * NdrConformantArrayMarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrConformantArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - DWORD size = 0, esize = *(const WORD*)(pFormat+2); - unsigned char alignment = pFormat[1] + 1; - - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]); - - pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0); - - WriteConformance(pStubMsg); - - ALIGN_POINTER(pStubMsg->Buffer, alignment); - - size = safe_multiply(esize, pStubMsg->MaxCount); - memcpy(pStubMsg->Buffer, pMemory, size); - pStubMsg->BufferMark = pStubMsg->Buffer; - pStubMsg->Buffer += size; - - EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat); - - STD_OVERFLOW_CHECK(pStubMsg); - - return NULL; -} - -/*********************************************************************** - * NdrConformantArrayUnmarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrConformantArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char **ppMemory, - PFORMAT_STRING pFormat, - unsigned char fMustAlloc) -{ - DWORD size, esize = *(const WORD*)(pFormat+2); - unsigned char alignment = pFormat[1] + 1; - - TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); - if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]); - - pFormat = ReadConformance(pStubMsg, pFormat+4); - - size = safe_multiply(esize, pStubMsg->MaxCount); - - if (fMustAlloc || !*ppMemory) - *ppMemory = NdrAllocate(pStubMsg, size); - - ALIGN_POINTER(pStubMsg->Buffer, alignment); - - pStubMsg->BufferMark = pStubMsg->Buffer; - safe_buffer_copy(pStubMsg, *ppMemory, size); - - EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc); - - return NULL; -} - -/*********************************************************************** - * NdrConformantArrayBufferSize [RPCRT4.@] - */ -void WINAPI NdrConformantArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - DWORD size, esize = *(const WORD*)(pFormat+2); - unsigned char alignment = pFormat[1] + 1; - - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]); - - pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0); - - SizeConformance(pStubMsg); - - ALIGN_LENGTH(pStubMsg->BufferLength, alignment); - - size = safe_multiply(esize, pStubMsg->MaxCount); - /* conformance value plus array */ - pStubMsg->BufferLength += size; - - EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat); -} - -/*********************************************************************** - * NdrConformantArrayMemorySize [RPCRT4.@] - */ -ULONG WINAPI NdrConformantArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat) -{ - DWORD size = 0, esize = *(const WORD*)(pFormat+2); - unsigned char alignment = pFormat[1] + 1; - - TRACE("(%p,%p)\n", pStubMsg, pFormat); - if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]); - - pFormat = ReadConformance(pStubMsg, pFormat+4); - size = safe_multiply(esize, pStubMsg->MaxCount); - pStubMsg->MemorySize += size; - - ALIGN_POINTER(pStubMsg->Buffer, alignment); - pStubMsg->BufferMark = pStubMsg->Buffer; - pStubMsg->Buffer += size; - - EmbeddedPointerMemorySize(pStubMsg, pFormat); - - return pStubMsg->MemorySize; -} - -/*********************************************************************** - * NdrConformantArrayFree [RPCRT4.@] - */ -void WINAPI NdrConformantArrayFree(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]); - - pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0); - - EmbeddedPointerFree(pStubMsg, pMemory, pFormat); -} - - -/*********************************************************************** - * NdrConformantVaryingArrayMarshall [RPCRT4.@] - */ -unsigned char* WINAPI NdrConformantVaryingArrayMarshall( PMIDL_STUB_MESSAGE pStubMsg, - unsigned char* pMemory, - PFORMAT_STRING pFormat ) -{ - ULONG bufsize; - unsigned char alignment = pFormat[1] + 1; - DWORD esize = *(const WORD*)(pFormat+2); - - TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); - - if (pFormat[0] != RPC_FC_CVARRAY) - { - ERR("invalid format type %x\n", pFormat[0]); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return NULL; - } - - pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0); - pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0); - - WriteConformance(pStubMsg); - WriteVariance(pStubMsg); - - ALIGN_POINTER(pStubMsg->Buffer, alignment); - - bufsize = safe_multiply(esize, pStubMsg->ActualCount); - - memcpy(pStubMsg->Buffer, pMemory + pStubMsg->Offset, bufsize); - pStubMsg->BufferMark = pStubMsg->Buffer; - pStubMsg->Buffer += bufsize; - - EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat); - - STD_OVERFLOW_CHECK(pStubMsg); - - return NULL; -} - - -/*********************************************************************** - * NdrConformantVaryingArrayUnmarshall [RPCRT4.@] - */ -unsigned char* WINAPI NdrConformantVaryingArrayUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, - unsigned char** ppMemory, - PFORMAT_STRING pFormat, - unsigned char fMustAlloc ) -{ - ULONG bufsize, memsize; - unsigned char alignment = pFormat[1] + 1; - DWORD esize = *(const WORD*)(pFormat+2); - - TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); - - if (pFormat[0] != RPC_FC_CVARRAY) - { - ERR("invalid format type %x\n", pFormat[0]); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return NULL; - } - - pFormat = ReadConformance(pStubMsg, pFormat+4); - pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount); - - ALIGN_POINTER(pStubMsg->Buffer, alignment); - - bufsize = safe_multiply(esize, pStubMsg->ActualCount); - memsize = safe_multiply(esize, pStubMsg->MaxCount); - - if (!*ppMemory || fMustAlloc) - *ppMemory = NdrAllocate(pStubMsg, memsize); - safe_buffer_copy(pStubMsg, *ppMemory + pStubMsg->Offset, bufsize); - - EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc); - - return NULL; -} - - -/*********************************************************************** - * NdrConformantVaryingArrayFree [RPCRT4.@] - */ -void WINAPI NdrConformantVaryingArrayFree( PMIDL_STUB_MESSAGE pStubMsg, - unsigned char* pMemory, - PFORMAT_STRING pFormat ) -{ - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - - if (pFormat[0] != RPC_FC_CVARRAY) - { - ERR("invalid format type %x\n", pFormat[0]); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return; - } - - pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0); - pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0); - - EmbeddedPointerFree(pStubMsg, pMemory, pFormat); -} - - -/*********************************************************************** - * NdrConformantVaryingArrayBufferSize [RPCRT4.@] - */ -void WINAPI NdrConformantVaryingArrayBufferSize( PMIDL_STUB_MESSAGE pStubMsg, - unsigned char* pMemory, PFORMAT_STRING pFormat ) -{ - unsigned char alignment = pFormat[1] + 1; - DWORD esize = *(const WORD*)(pFormat+2); - - TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); - - if (pFormat[0] != RPC_FC_CVARRAY) - { - ERR("invalid format type %x\n", pFormat[0]); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return; - } - - /* compute size */ - pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0); - /* compute length */ - pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0); - - SizeConformance(pStubMsg); - SizeVariance(pStubMsg); - - ALIGN_LENGTH(pStubMsg->BufferLength, alignment); - - pStubMsg->BufferLength += safe_multiply(esize, pStubMsg->ActualCount); - - EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat); -} - - -/*********************************************************************** - * NdrConformantVaryingArrayMemorySize [RPCRT4.@] - */ -ULONG WINAPI NdrConformantVaryingArrayMemorySize( PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat ) -{ - FIXME( "stub\n" ); - return 0; -} - - -/*********************************************************************** - * NdrComplexArrayMarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrComplexArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - ULONG i, count, def; - BOOL variance_present; - unsigned char alignment; - int pointer_buffer_mark_set = 0; - - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - - if (pFormat[0] != RPC_FC_BOGUS_ARRAY) - { - ERR("invalid format type %x\n", pFormat[0]); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return NULL; - } - - alignment = pFormat[1] + 1; - - if (!pStubMsg->PointerBufferMark) - { - /* save buffer fields that may be changed by buffer sizer functions - * and that may be needed later on */ - int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers; - unsigned long saved_buffer_length = pStubMsg->BufferLength; - unsigned long saved_max_count = pStubMsg->MaxCount; - unsigned long saved_offset = pStubMsg->Offset; - unsigned long saved_actual_count = pStubMsg->ActualCount; - - /* get the buffer pointer after complex array data, but before - * pointer data */ - pStubMsg->BufferLength = pStubMsg->Buffer - pStubMsg->BufferStart; - pStubMsg->IgnoreEmbeddedPointers = 1; - NdrComplexArrayBufferSize(pStubMsg, pMemory, pFormat); - pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded; - - /* save it for use by embedded pointer code later */ - pStubMsg->PointerBufferMark = pStubMsg->BufferStart + pStubMsg->BufferLength; - TRACE("difference = 0x%x\n", pStubMsg->Buffer - pStubMsg->BufferStart); - pointer_buffer_mark_set = 1; - - /* restore fields */ - pStubMsg->ActualCount = saved_actual_count; - pStubMsg->Offset = saved_offset; - pStubMsg->MaxCount = saved_max_count; - pStubMsg->BufferLength = saved_buffer_length; - } - - def = *(const WORD*)&pFormat[2]; - pFormat += 4; - - pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def); - TRACE("conformance = %ld\n", pStubMsg->MaxCount); - - variance_present = IsConformanceOrVariancePresent(pFormat); - pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount); - TRACE("variance = %d\n", pStubMsg->ActualCount); - - WriteConformance(pStubMsg); - if (variance_present) - WriteVariance(pStubMsg); - - ALIGN_POINTER(pStubMsg->Buffer, alignment); - - count = pStubMsg->ActualCount; - for (i = 0; i < count; i++) - pMemory = ComplexMarshall(pStubMsg, pMemory, pFormat, NULL); - - STD_OVERFLOW_CHECK(pStubMsg); - - if (pointer_buffer_mark_set) - { - pStubMsg->Buffer = pStubMsg->PointerBufferMark; - pStubMsg->PointerBufferMark = NULL; - } - - return NULL; -} - -/*********************************************************************** - * NdrComplexArrayUnmarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrComplexArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char **ppMemory, - PFORMAT_STRING pFormat, - unsigned char fMustAlloc) -{ - ULONG i, count, size; - unsigned char alignment; - unsigned char *pMemory; - unsigned char *saved_buffer; - int pointer_buffer_mark_set = 0; - int saved_ignore_embedded; - - TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); - - if (pFormat[0] != RPC_FC_BOGUS_ARRAY) - { - ERR("invalid format type %x\n", pFormat[0]); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return NULL; - } - - alignment = pFormat[1] + 1; - - saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers; - /* save buffer pointer */ - saved_buffer = pStubMsg->Buffer; - /* get the buffer pointer after complex array data, but before - * pointer data */ - pStubMsg->IgnoreEmbeddedPointers = 1; - pStubMsg->MemorySize = 0; - NdrComplexArrayMemorySize(pStubMsg, pFormat); - size = pStubMsg->MemorySize; - pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded; - - TRACE("difference = 0x%lx\n", (unsigned long)(pStubMsg->Buffer - saved_buffer)); - if (!pStubMsg->PointerBufferMark) - { - /* save it for use by embedded pointer code later */ - pStubMsg->PointerBufferMark = pStubMsg->Buffer; - pointer_buffer_mark_set = 1; - } - /* restore the original buffer */ - pStubMsg->Buffer = saved_buffer; - - pFormat += 4; - - pFormat = ReadConformance(pStubMsg, pFormat); - pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount); - - if (fMustAlloc || !*ppMemory) - { - *ppMemory = NdrAllocate(pStubMsg, size); - memset(*ppMemory, 0, size); - } - - ALIGN_POINTER(pStubMsg->Buffer, alignment); - - pMemory = *ppMemory; - count = pStubMsg->ActualCount; - for (i = 0; i < count; i++) - pMemory = ComplexUnmarshall(pStubMsg, pMemory, pFormat, NULL); - - if (pointer_buffer_mark_set) - { - pStubMsg->Buffer = pStubMsg->PointerBufferMark; - pStubMsg->PointerBufferMark = NULL; - } - - return NULL; -} - -/*********************************************************************** - * NdrComplexArrayBufferSize [RPCRT4.@] - */ -void WINAPI NdrComplexArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - ULONG i, count, def; - unsigned char alignment; - BOOL variance_present; - int pointer_length_set = 0; - - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - - if (pFormat[0] != RPC_FC_BOGUS_ARRAY) - { - ERR("invalid format type %x\n", pFormat[0]); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return; - } - - alignment = pFormat[1] + 1; - - if (!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength) - { - /* save buffer fields that may be changed by buffer sizer functions - * and that may be needed later on */ - int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers; - unsigned long saved_buffer_length = pStubMsg->BufferLength; - unsigned long saved_max_count = pStubMsg->MaxCount; - unsigned long saved_offset = pStubMsg->Offset; - unsigned long saved_actual_count = pStubMsg->ActualCount; - - /* get the buffer pointer after complex array data, but before - * pointer data */ - pStubMsg->IgnoreEmbeddedPointers = 1; - NdrComplexArrayBufferSize(pStubMsg, pMemory, pFormat); - pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded; - - /* save it for use by embedded pointer code later */ - pStubMsg->PointerLength = pStubMsg->BufferLength; - pointer_length_set = 1; - - /* restore fields */ - pStubMsg->ActualCount = saved_actual_count; - pStubMsg->Offset = saved_offset; - pStubMsg->MaxCount = saved_max_count; - pStubMsg->BufferLength = saved_buffer_length; - } - def = *(const WORD*)&pFormat[2]; - pFormat += 4; - - pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def); - TRACE("conformance = %ld\n", pStubMsg->MaxCount); - SizeConformance(pStubMsg); - - variance_present = IsConformanceOrVariancePresent(pFormat); - pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount); - TRACE("variance = %d\n", pStubMsg->ActualCount); - - if (variance_present) - SizeVariance(pStubMsg); - - ALIGN_LENGTH(pStubMsg->BufferLength, alignment); - - count = pStubMsg->ActualCount; - for (i = 0; i < count; i++) - pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, NULL); - - if(pointer_length_set) - { - pStubMsg->BufferLength = pStubMsg->PointerLength; - pStubMsg->PointerLength = 0; - } -} - -/*********************************************************************** - * NdrComplexArrayMemorySize [RPCRT4.@] - */ -ULONG WINAPI NdrComplexArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat) -{ - ULONG i, count, esize, SavedMemorySize, MemorySize; - unsigned char alignment; - unsigned char *Buffer; - - TRACE("(%p,%p)\n", pStubMsg, pFormat); - - if (pFormat[0] != RPC_FC_BOGUS_ARRAY) - { - ERR("invalid format type %x\n", pFormat[0]); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return 0; - } - - alignment = pFormat[1] + 1; - - pFormat += 4; - - pFormat = ReadConformance(pStubMsg, pFormat); - pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount); - - ALIGN_POINTER(pStubMsg->Buffer, alignment); - - SavedMemorySize = pStubMsg->MemorySize; - - Buffer = pStubMsg->Buffer; - pStubMsg->MemorySize = 0; - esize = ComplexStructMemorySize(pStubMsg, pFormat); - pStubMsg->Buffer = Buffer; - - MemorySize = safe_multiply(pStubMsg->MaxCount, esize); - - count = pStubMsg->ActualCount; - for (i = 0; i < count; i++) - ComplexStructMemorySize(pStubMsg, pFormat); - - pStubMsg->MemorySize = SavedMemorySize; - - pStubMsg->MemorySize += MemorySize; - return MemorySize; -} - -/*********************************************************************** - * NdrComplexArrayFree [RPCRT4.@] - */ -void WINAPI NdrComplexArrayFree(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - ULONG i, count, def; - - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - - if (pFormat[0] != RPC_FC_BOGUS_ARRAY) - { - ERR("invalid format type %x\n", pFormat[0]); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return; - } - - def = *(const WORD*)&pFormat[2]; - pFormat += 4; - - pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def); - TRACE("conformance = %ld\n", pStubMsg->MaxCount); - - pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount); - TRACE("variance = %d\n", pStubMsg->ActualCount); - - count = pStubMsg->ActualCount; - for (i = 0; i < count; i++) - pMemory = ComplexFree(pStubMsg, pMemory, pFormat, NULL); -} - -static ULONG UserMarshalFlags(const MIDL_STUB_MESSAGE *pStubMsg) -{ - return MAKELONG(pStubMsg->dwDestContext, - pStubMsg->RpcMsg->DataRepresentation); -} - -#define USER_MARSHAL_PTR_PREFIX \ - ( (DWORD)'U' | ( (DWORD)'s' << 8 ) | \ - ( (DWORD)'e' << 16 ) | ( (DWORD)'r' << 24 ) ) - -/*********************************************************************** - * NdrUserMarshalMarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrUserMarshalMarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - unsigned flags = pFormat[1]; - unsigned index = *(const WORD*)&pFormat[2]; - unsigned char *saved_buffer = NULL; - ULONG uflag = UserMarshalFlags(pStubMsg); - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - TRACE("index=%d\n", index); - - if (flags & USER_MARSHAL_POINTER) - { - ALIGN_POINTER(pStubMsg->Buffer, 4); - NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, USER_MARSHAL_PTR_PREFIX); - pStubMsg->Buffer += 4; - if (pStubMsg->PointerBufferMark) - { - saved_buffer = pStubMsg->Buffer; - pStubMsg->Buffer = pStubMsg->PointerBufferMark; - pStubMsg->PointerBufferMark = NULL; - } - ALIGN_POINTER(pStubMsg->Buffer, 8); - } - else - ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1); - - pStubMsg->Buffer = - pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnMarshall( - &uflag, pStubMsg->Buffer, pMemory); - - if (saved_buffer) - { - STD_OVERFLOW_CHECK(pStubMsg); - pStubMsg->PointerBufferMark = pStubMsg->Buffer; - pStubMsg->Buffer = saved_buffer; - } - - STD_OVERFLOW_CHECK(pStubMsg); - - return NULL; -} - -/*********************************************************************** - * NdrUserMarshalUnmarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrUserMarshalUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char **ppMemory, - PFORMAT_STRING pFormat, - unsigned char fMustAlloc) -{ - unsigned flags = pFormat[1]; - unsigned index = *(const WORD*)&pFormat[2]; - DWORD memsize = *(const WORD*)&pFormat[4]; - unsigned char *saved_buffer = NULL; - ULONG uflag = UserMarshalFlags(pStubMsg); - TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); - TRACE("index=%d\n", index); - - if (flags & USER_MARSHAL_POINTER) - { - ALIGN_POINTER(pStubMsg->Buffer, 4); - /* skip pointer prefix */ - pStubMsg->Buffer += 4; - if (pStubMsg->PointerBufferMark) - { - saved_buffer = pStubMsg->Buffer; - pStubMsg->Buffer = pStubMsg->PointerBufferMark; - pStubMsg->PointerBufferMark = NULL; - } - ALIGN_POINTER(pStubMsg->Buffer, 8); - } - else - ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1); - - if (fMustAlloc || !*ppMemory) - *ppMemory = NdrAllocate(pStubMsg, memsize); - - pStubMsg->Buffer = - pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnUnmarshall( - &uflag, pStubMsg->Buffer, *ppMemory); - - if (saved_buffer) - { - STD_OVERFLOW_CHECK(pStubMsg); - pStubMsg->PointerBufferMark = pStubMsg->Buffer; - pStubMsg->Buffer = saved_buffer; - } - - return NULL; -} - -/*********************************************************************** - * NdrUserMarshalBufferSize [RPCRT4.@] - */ -void WINAPI NdrUserMarshalBufferSize(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - unsigned flags = pFormat[1]; - unsigned index = *(const WORD*)&pFormat[2]; - DWORD bufsize = *(const WORD*)&pFormat[6]; - ULONG uflag = UserMarshalFlags(pStubMsg); - unsigned long saved_buffer_length = 0; - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - TRACE("index=%d\n", index); - - if (flags & USER_MARSHAL_POINTER) - { - ALIGN_LENGTH(pStubMsg->BufferLength, 4); - /* skip pointer prefix */ - pStubMsg->BufferLength += 4; - if (pStubMsg->IgnoreEmbeddedPointers) - return; - if (pStubMsg->PointerLength) - { - saved_buffer_length = pStubMsg->BufferLength; - pStubMsg->BufferLength = pStubMsg->PointerLength; - pStubMsg->PointerLength = 0; - } - ALIGN_LENGTH(pStubMsg->BufferLength, 8); - } - else - ALIGN_LENGTH(pStubMsg->BufferLength, (flags & 0xf) + 1); - - if (bufsize) { - TRACE("size=%d\n", bufsize); - pStubMsg->BufferLength += bufsize; - } - else - pStubMsg->BufferLength = - pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnBufferSize( - &uflag, pStubMsg->BufferLength, pMemory); - - if (saved_buffer_length) - { - pStubMsg->PointerLength = pStubMsg->BufferLength; - pStubMsg->BufferLength = saved_buffer_length; - } - -} - -/*********************************************************************** - * NdrUserMarshalMemorySize [RPCRT4.@] - */ -ULONG WINAPI NdrUserMarshalMemorySize(PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat) -{ - unsigned flags = pFormat[1]; - unsigned index = *(const WORD*)&pFormat[2]; - DWORD memsize = *(const WORD*)&pFormat[4]; - DWORD bufsize = *(const WORD*)&pFormat[6]; - - TRACE("(%p,%p)\n", pStubMsg, pFormat); - TRACE("index=%d\n", index); - - pStubMsg->MemorySize += memsize; - - if (flags & USER_MARSHAL_POINTER) - { - ALIGN_POINTER(pStubMsg->Buffer, 4); - /* skip pointer prefix */ - pStubMsg->Buffer += 4; - if (pStubMsg->IgnoreEmbeddedPointers) - return pStubMsg->MemorySize; - ALIGN_POINTER(pStubMsg->Buffer, 8); - } - else - ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1); - - if (!bufsize) - FIXME("not implemented for varying buffer size\n"); - - pStubMsg->Buffer += bufsize; - - return pStubMsg->MemorySize; -} - -/*********************************************************************** - * NdrUserMarshalFree [RPCRT4.@] - */ -void WINAPI NdrUserMarshalFree(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ -/* unsigned flags = pFormat[1]; */ - unsigned index = *(const WORD*)&pFormat[2]; - ULONG uflag = UserMarshalFlags(pStubMsg); - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - TRACE("index=%d\n", index); - - pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnFree( - &uflag, pMemory); -} - -/*********************************************************************** - * NdrClearOutParameters [RPCRT4.@] - */ -void WINAPI NdrClearOutParameters(PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat, - void *ArgAddr) -{ - FIXME("(%p,%p,%p): stub\n", pStubMsg, pFormat, ArgAddr); -} - -/*********************************************************************** - * NdrConvert [RPCRT4.@] - */ -void WINAPI NdrConvert( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat ) -{ - FIXME("(pStubMsg == ^%p, pFormat == ^%p): stub.\n", pStubMsg, pFormat); - /* FIXME: since this stub doesn't do any converting, the proper behavior - is to raise an exception */ -} - -/*********************************************************************** - * NdrConvert2 [RPCRT4.@] - */ -void WINAPI NdrConvert2( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, LONG NumberParams ) -{ - FIXME("(pStubMsg == ^%p, pFormat == ^%p, NumberParams == %d): stub.\n", - pStubMsg, pFormat, NumberParams); - /* FIXME: since this stub doesn't do any converting, the proper behavior - is to raise an exception */ -} - -#include "pshpack1.h" -typedef struct _NDR_CSTRUCT_FORMAT -{ - unsigned char type; - unsigned char alignment; - unsigned short memory_size; - short offset_to_array_description; -} NDR_CSTRUCT_FORMAT, NDR_CVSTRUCT_FORMAT; -#include "poppack.h" - -/*********************************************************************** - * NdrConformantStructMarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrConformantStructMarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat; - PFORMAT_STRING pCArrayFormat; - ULONG esize, bufsize; - - TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); - - pFormat += sizeof(NDR_CSTRUCT_FORMAT); - if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT)) - { - ERR("invalid format type %x\n", pCStructFormat->type); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return NULL; - } - - pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description + - pCStructFormat->offset_to_array_description; - if (*pCArrayFormat != RPC_FC_CARRAY) - { - ERR("invalid array format type %x\n", pCStructFormat->type); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return NULL; - } - esize = *(const WORD*)(pCArrayFormat+2); - - ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size, - pCArrayFormat + 4, 0); - - WriteConformance(pStubMsg); - - ALIGN_POINTER(pStubMsg->Buffer, pCStructFormat->alignment + 1); - - TRACE("memory_size = %d\n", pCStructFormat->memory_size); - - bufsize = safe_multiply(esize, pStubMsg->MaxCount); - /* copy constant sized part of struct */ - pStubMsg->BufferMark = pStubMsg->Buffer; - memcpy(pStubMsg->Buffer, pMemory, pCStructFormat->memory_size + bufsize); - pStubMsg->Buffer += pCStructFormat->memory_size + bufsize; - - if (pCStructFormat->type == RPC_FC_CPSTRUCT) - EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat); - - STD_OVERFLOW_CHECK(pStubMsg); - - return NULL; -} - -/*********************************************************************** - * NdrConformantStructUnmarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrConformantStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char **ppMemory, - PFORMAT_STRING pFormat, - unsigned char fMustAlloc) -{ - const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat; - PFORMAT_STRING pCArrayFormat; - ULONG esize, bufsize; - - TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); - - pFormat += sizeof(NDR_CSTRUCT_FORMAT); - if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT)) - { - ERR("invalid format type %x\n", pCStructFormat->type); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return NULL; - } - pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description + - pCStructFormat->offset_to_array_description; - if (*pCArrayFormat != RPC_FC_CARRAY) - { - ERR("invalid array format type %x\n", pCStructFormat->type); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return NULL; - } - esize = *(const WORD*)(pCArrayFormat+2); - - pCArrayFormat = ReadConformance(pStubMsg, pCArrayFormat + 4); - - ALIGN_POINTER(pStubMsg->Buffer, pCStructFormat->alignment + 1); - - TRACE("memory_size = %d\n", pCStructFormat->memory_size); - - bufsize = safe_multiply(esize, pStubMsg->MaxCount); - /* work out how much memory to allocate if we need to do so */ - if (!*ppMemory || fMustAlloc) - { - SIZE_T size = pCStructFormat->memory_size + bufsize; - *ppMemory = NdrAllocate(pStubMsg, size); - } - - /* now copy the data */ - pStubMsg->BufferMark = pStubMsg->Buffer; - safe_buffer_copy(pStubMsg, *ppMemory, pCStructFormat->memory_size + bufsize); - - if (pCStructFormat->type == RPC_FC_CPSTRUCT) - EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc); - - return NULL; -} - -/*********************************************************************** - * NdrConformantStructBufferSize [RPCRT4.@] - */ -void WINAPI NdrConformantStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - const NDR_CSTRUCT_FORMAT * pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat; - PFORMAT_STRING pCArrayFormat; - ULONG esize; - - TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); - - pFormat += sizeof(NDR_CSTRUCT_FORMAT); - if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT)) - { - ERR("invalid format type %x\n", pCStructFormat->type); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return; - } - pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description + - pCStructFormat->offset_to_array_description; - if (*pCArrayFormat != RPC_FC_CARRAY) - { - ERR("invalid array format type %x\n", pCStructFormat->type); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return; - } - esize = *(const WORD*)(pCArrayFormat+2); - - pCArrayFormat = ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size, pCArrayFormat+4, 0); - SizeConformance(pStubMsg); - - ALIGN_LENGTH(pStubMsg->BufferLength, pCStructFormat->alignment + 1); - - TRACE("memory_size = %d\n", pCStructFormat->memory_size); - - pStubMsg->BufferLength += pCStructFormat->memory_size + - safe_multiply(pStubMsg->MaxCount, esize); - - if (pCStructFormat->type == RPC_FC_CPSTRUCT) - EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat); -} - -/*********************************************************************** - * NdrConformantStructMemorySize [RPCRT4.@] - */ -ULONG WINAPI NdrConformantStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat) -{ - FIXME("stub\n"); - return 0; -} - -/*********************************************************************** - * NdrConformantStructFree [RPCRT4.@] - */ -void WINAPI NdrConformantStructFree(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - FIXME("stub\n"); -} - -/*********************************************************************** - * NdrConformantVaryingStructMarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrConformantVaryingStructMarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat; - PFORMAT_STRING pCVArrayFormat; - ULONG esize, bufsize; - - TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); - - pFormat += sizeof(NDR_CVSTRUCT_FORMAT); - if (pCVStructFormat->type != RPC_FC_CVSTRUCT) - { - ERR("invalid format type %x\n", pCVStructFormat->type); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return NULL; - } - - pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description + - pCVStructFormat->offset_to_array_description; - switch (*pCVArrayFormat) - { - case RPC_FC_CVARRAY: - esize = *(const WORD*)(pCVArrayFormat+2); - - pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size, - pCVArrayFormat + 4, 0); - pCVArrayFormat = ComputeVariance(pStubMsg, pMemory + pCVStructFormat->memory_size, - pCVArrayFormat, 0); - break; - case RPC_FC_C_CSTRING: - TRACE("string=%s\n", debugstr_a((char*)pMemory + pCVStructFormat->memory_size)); - pStubMsg->ActualCount = strlen((char*)pMemory + pCVStructFormat->memory_size)+1; - esize = sizeof(char); - if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) - pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size, - pCVArrayFormat + 2, 0); - else - pStubMsg->MaxCount = pStubMsg->ActualCount; - break; - case RPC_FC_C_WSTRING: - TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory + pCVStructFormat->memory_size)); - pStubMsg->ActualCount = strlenW((LPWSTR)pMemory + pCVStructFormat->memory_size)+1; - esize = sizeof(WCHAR); - if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) - pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size, - pCVArrayFormat + 2, 0); - else - pStubMsg->MaxCount = pStubMsg->ActualCount; - break; - default: - ERR("invalid array format type %x\n", *pCVArrayFormat); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return NULL; - } - - WriteConformance(pStubMsg); - - ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1); - - TRACE("memory_size = %d\n", pCVStructFormat->memory_size); - - /* write constant sized part */ - pStubMsg->BufferMark = pStubMsg->Buffer; - memcpy(pStubMsg->Buffer, pMemory, pCVStructFormat->memory_size); - pStubMsg->Buffer += pCVStructFormat->memory_size; - - WriteVariance(pStubMsg); - - bufsize = safe_multiply(esize, pStubMsg->ActualCount); - - /* write array part */ - memcpy(pStubMsg->Buffer, pMemory + pCVStructFormat->memory_size, bufsize); - pStubMsg->Buffer += bufsize; - - EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat); - - STD_OVERFLOW_CHECK(pStubMsg); - - return NULL; -} - -/*********************************************************************** - * NdrConformantVaryingStructUnmarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrConformantVaryingStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char **ppMemory, - PFORMAT_STRING pFormat, - unsigned char fMustAlloc) -{ - const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat; - PFORMAT_STRING pCVArrayFormat; - ULONG esize, bufsize; - unsigned char cvarray_type; - - TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); - - pFormat += sizeof(NDR_CVSTRUCT_FORMAT); - if (pCVStructFormat->type != RPC_FC_CVSTRUCT) - { - ERR("invalid format type %x\n", pCVStructFormat->type); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return NULL; - } - - pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description + - pCVStructFormat->offset_to_array_description; - cvarray_type = *pCVArrayFormat; - switch (cvarray_type) - { - case RPC_FC_CVARRAY: - esize = *(const WORD*)(pCVArrayFormat+2); - pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 4); - break; - case RPC_FC_C_CSTRING: - esize = sizeof(char); - if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) - pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2); - else - pCVArrayFormat = ReadConformance(pStubMsg, NULL); - break; - case RPC_FC_C_WSTRING: - esize = sizeof(WCHAR); - if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) - pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2); - else - pCVArrayFormat = ReadConformance(pStubMsg, NULL); - break; - default: - ERR("invalid array format type %x\n", *pCVArrayFormat); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return NULL; - } - - ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1); - - TRACE("memory_size = %d\n", pCVStructFormat->memory_size); - - /* work out how much memory to allocate if we need to do so */ - if (!*ppMemory || fMustAlloc) - { - SIZE_T size = pCVStructFormat->memory_size + safe_multiply(esize, pStubMsg->MaxCount); - *ppMemory = NdrAllocate(pStubMsg, size); - } - - /* copy the constant data */ - pStubMsg->BufferMark = pStubMsg->Buffer; - safe_buffer_copy(pStubMsg, *ppMemory, pCVStructFormat->memory_size); - - pCVArrayFormat = ReadVariance(pStubMsg, pCVArrayFormat, pStubMsg->MaxCount); - - bufsize = safe_multiply(esize, pStubMsg->ActualCount); - - if ((cvarray_type == RPC_FC_C_CSTRING) || - (cvarray_type == RPC_FC_C_WSTRING)) - { - ULONG i; - /* strings must always have null terminating bytes */ - if (bufsize < esize) - { - ERR("invalid string length of %d\n", pStubMsg->ActualCount); - RpcRaiseException(RPC_S_INVALID_BOUND); - return NULL; - } - for (i = bufsize - esize; i < bufsize; i++) - if (pStubMsg->Buffer[i] != 0) - { - ERR("string not null-terminated at byte position %d, data is 0x%x\n", - i, pStubMsg->Buffer[i]); - RpcRaiseException(RPC_S_INVALID_BOUND); - return NULL; - } - } - - /* copy the array data */ - safe_buffer_copy(pStubMsg, *ppMemory + pCVStructFormat->memory_size, bufsize); - - if (cvarray_type == RPC_FC_C_CSTRING) - TRACE("string=%s\n", debugstr_a((char *)(*ppMemory + pCVStructFormat->memory_size))); - else if (cvarray_type == RPC_FC_C_WSTRING) - TRACE("string=%s\n", debugstr_w((WCHAR *)(*ppMemory + pCVStructFormat->memory_size))); - - EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc); - - return NULL; -} - -/*********************************************************************** - * NdrConformantVaryingStructBufferSize [RPCRT4.@] - */ -void WINAPI NdrConformantVaryingStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat; - PFORMAT_STRING pCVArrayFormat; - ULONG esize; - - TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); - - pFormat += sizeof(NDR_CVSTRUCT_FORMAT); - if (pCVStructFormat->type != RPC_FC_CVSTRUCT) - { - ERR("invalid format type %x\n", pCVStructFormat->type); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return; - } - - pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description + - pCVStructFormat->offset_to_array_description; - switch (*pCVArrayFormat) - { - case RPC_FC_CVARRAY: - esize = *(const WORD*)(pCVArrayFormat+2); - - pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size, - pCVArrayFormat + 4, 0); - pCVArrayFormat = ComputeVariance(pStubMsg, pMemory + pCVStructFormat->memory_size, - pCVArrayFormat, 0); - break; - case RPC_FC_C_CSTRING: - TRACE("string=%s\n", debugstr_a((char*)pMemory + pCVStructFormat->memory_size)); - pStubMsg->ActualCount = strlen((char*)pMemory + pCVStructFormat->memory_size)+1; - esize = sizeof(char); - if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) - pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size, - pCVArrayFormat + 2, 0); - else - pStubMsg->MaxCount = pStubMsg->ActualCount; - break; - case RPC_FC_C_WSTRING: - TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory + pCVStructFormat->memory_size)); - pStubMsg->ActualCount = strlenW((LPWSTR)pMemory + pCVStructFormat->memory_size)+1; - esize = sizeof(WCHAR); - if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) - pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size, - pCVArrayFormat + 2, 0); - else - pStubMsg->MaxCount = pStubMsg->ActualCount; - break; - default: - ERR("invalid array format type %x\n", *pCVArrayFormat); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return; - } - - SizeConformance(pStubMsg); - - ALIGN_LENGTH(pStubMsg->BufferLength, pCVStructFormat->alignment + 1); - - TRACE("memory_size = %d\n", pCVStructFormat->memory_size); - - pStubMsg->BufferLength += pCVStructFormat->memory_size; - SizeVariance(pStubMsg); - pStubMsg->BufferLength += safe_multiply(pStubMsg->MaxCount, esize); - - EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat); -} - -/*********************************************************************** - * NdrConformantVaryingStructMemorySize [RPCRT4.@] - */ -ULONG WINAPI NdrConformantVaryingStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat) -{ - const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat; - PFORMAT_STRING pCVArrayFormat; - ULONG esize; - unsigned char cvarray_type; - - TRACE("(%p, %p)\n", pStubMsg, pFormat); - - pFormat += sizeof(NDR_CVSTRUCT_FORMAT); - if (pCVStructFormat->type != RPC_FC_CVSTRUCT) - { - ERR("invalid format type %x\n", pCVStructFormat->type); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return 0; - } - - pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description + - pCVStructFormat->offset_to_array_description; - cvarray_type = *pCVArrayFormat; - switch (cvarray_type) - { - case RPC_FC_CVARRAY: - esize = *(const WORD*)(pCVArrayFormat+2); - pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 4); - break; - case RPC_FC_C_CSTRING: - esize = sizeof(char); - if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) - pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2); - else - pCVArrayFormat = ReadConformance(pStubMsg, NULL); - break; - case RPC_FC_C_WSTRING: - esize = sizeof(WCHAR); - if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) - pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2); - else - pCVArrayFormat = ReadConformance(pStubMsg, NULL); - break; - default: - ERR("invalid array format type %x\n", *pCVArrayFormat); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return 0; - } - - ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1); - - TRACE("memory_size = %d\n", pCVStructFormat->memory_size); - - pStubMsg->Buffer += pCVStructFormat->memory_size; - pCVArrayFormat = ReadVariance(pStubMsg, pCVArrayFormat, pStubMsg->MaxCount); - pStubMsg->Buffer += pCVStructFormat->memory_size + safe_multiply(esize, pStubMsg->ActualCount); - - pStubMsg->MemorySize += pCVStructFormat->memory_size + safe_multiply(esize, pStubMsg->MaxCount); - - EmbeddedPointerMemorySize(pStubMsg, pFormat); - - return pCVStructFormat->memory_size + pStubMsg->MaxCount * esize; -} - -/*********************************************************************** - * NdrConformantVaryingStructFree [RPCRT4.@] - */ -void WINAPI NdrConformantVaryingStructFree(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat; - PFORMAT_STRING pCVArrayFormat; - ULONG esize; - - TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); - - pFormat += sizeof(NDR_CVSTRUCT_FORMAT); - if (pCVStructFormat->type != RPC_FC_CVSTRUCT) - { - ERR("invalid format type %x\n", pCVStructFormat->type); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return; - } - - pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description + - pCVStructFormat->offset_to_array_description; - switch (*pCVArrayFormat) - { - case RPC_FC_CVARRAY: - esize = *(const WORD*)(pCVArrayFormat+2); - - pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size, - pCVArrayFormat + 4, 0); - pCVArrayFormat = ComputeVariance(pStubMsg, pMemory + pCVStructFormat->memory_size, - pCVArrayFormat, 0); - break; - case RPC_FC_C_CSTRING: - TRACE("string=%s\n", debugstr_a((char*)pMemory + pCVStructFormat->memory_size)); - pStubMsg->ActualCount = strlen((char*)pMemory + pCVStructFormat->memory_size)+1; - esize = sizeof(char); - if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) - pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size, - pCVArrayFormat + 2, 0); - else - pStubMsg->MaxCount = pStubMsg->ActualCount; - break; - case RPC_FC_C_WSTRING: - TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory + pCVStructFormat->memory_size)); - pStubMsg->ActualCount = strlenW((LPWSTR)pMemory + pCVStructFormat->memory_size)+1; - esize = sizeof(WCHAR); - if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) - pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size, - pCVArrayFormat + 2, 0); - else - pStubMsg->MaxCount = pStubMsg->ActualCount; - break; - default: - ERR("invalid array format type %x\n", *pCVArrayFormat); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return; - } - - TRACE("memory_size = %d\n", pCVStructFormat->memory_size); - - EmbeddedPointerFree(pStubMsg, pMemory, pFormat); -} - -#include "pshpack1.h" -typedef struct -{ - unsigned char type; - unsigned char alignment; - unsigned short total_size; -} NDR_SMFARRAY_FORMAT; - -typedef struct -{ - unsigned char type; - unsigned char alignment; - unsigned long total_size; -} NDR_LGFARRAY_FORMAT; -#include "poppack.h" - -/*********************************************************************** - * NdrFixedArrayMarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrFixedArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat; - unsigned long total_size; - - TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); - - if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) && - (pSmFArrayFormat->type != RPC_FC_LGFARRAY)) - { - ERR("invalid format type %x\n", pSmFArrayFormat->type); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return NULL; - } - - ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1); - - if (pSmFArrayFormat->type == RPC_FC_SMFARRAY) - { - total_size = pSmFArrayFormat->total_size; - pFormat = (const unsigned char *)(pSmFArrayFormat + 1); - } - else - { - const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat; - total_size = pLgFArrayFormat->total_size; - pFormat = (const unsigned char *)(pLgFArrayFormat + 1); - } - - memcpy(pStubMsg->Buffer, pMemory, total_size); - pStubMsg->BufferMark = pStubMsg->Buffer; - pStubMsg->Buffer += total_size; - - pFormat = EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat); - - return NULL; -} - -/*********************************************************************** - * NdrFixedArrayUnmarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrFixedArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char **ppMemory, - PFORMAT_STRING pFormat, - unsigned char fMustAlloc) -{ - const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat; - unsigned long total_size; - - TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); - - if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) && - (pSmFArrayFormat->type != RPC_FC_LGFARRAY)) - { - ERR("invalid format type %x\n", pSmFArrayFormat->type); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return NULL; - } - - ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1); - - if (pSmFArrayFormat->type == RPC_FC_SMFARRAY) - { - total_size = pSmFArrayFormat->total_size; - pFormat = (const unsigned char *)(pSmFArrayFormat + 1); - } - else - { - const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat; - total_size = pLgFArrayFormat->total_size; - pFormat = (const unsigned char *)(pLgFArrayFormat + 1); - } - - if (fMustAlloc || !*ppMemory) - *ppMemory = NdrAllocate(pStubMsg, total_size); - pStubMsg->BufferMark = pStubMsg->Buffer; - safe_buffer_copy(pStubMsg, *ppMemory, total_size); - - pFormat = EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc); - - return NULL; -} - -/*********************************************************************** - * NdrFixedArrayBufferSize [RPCRT4.@] - */ -void WINAPI NdrFixedArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat; - unsigned long total_size; - - TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); - - if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) && - (pSmFArrayFormat->type != RPC_FC_LGFARRAY)) - { - ERR("invalid format type %x\n", pSmFArrayFormat->type); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return; - } - - ALIGN_LENGTH(pStubMsg->BufferLength, pSmFArrayFormat->alignment + 1); - - if (pSmFArrayFormat->type == RPC_FC_SMFARRAY) - { - total_size = pSmFArrayFormat->total_size; - pFormat = (const unsigned char *)(pSmFArrayFormat + 1); - } - else - { - const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat; - total_size = pLgFArrayFormat->total_size; - pFormat = (const unsigned char *)(pLgFArrayFormat + 1); - } - pStubMsg->BufferLength += total_size; - - EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat); -} - -/*********************************************************************** - * NdrFixedArrayMemorySize [RPCRT4.@] - */ -ULONG WINAPI NdrFixedArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat) -{ - const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat; - ULONG total_size; - - TRACE("(%p, %p)\n", pStubMsg, pFormat); - - if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) && - (pSmFArrayFormat->type != RPC_FC_LGFARRAY)) - { - ERR("invalid format type %x\n", pSmFArrayFormat->type); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return 0; - } - - ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1); - - if (pSmFArrayFormat->type == RPC_FC_SMFARRAY) - { - total_size = pSmFArrayFormat->total_size; - pFormat = (const unsigned char *)(pSmFArrayFormat + 1); - } - else - { - const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat; - total_size = pLgFArrayFormat->total_size; - pFormat = (const unsigned char *)(pLgFArrayFormat + 1); - } - pStubMsg->BufferMark = pStubMsg->Buffer; - pStubMsg->Buffer += total_size; - pStubMsg->MemorySize += total_size; - - EmbeddedPointerMemorySize(pStubMsg, pFormat); - - return total_size; -} - -/*********************************************************************** - * NdrFixedArrayFree [RPCRT4.@] - */ -void WINAPI NdrFixedArrayFree(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat; - - TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); - - if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) && - (pSmFArrayFormat->type != RPC_FC_LGFARRAY)) - { - ERR("invalid format type %x\n", pSmFArrayFormat->type); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return; - } - - if (pSmFArrayFormat->type == RPC_FC_SMFARRAY) - pFormat = (const unsigned char *)(pSmFArrayFormat + 1); - else - { - const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat; - pFormat = (const unsigned char *)(pLgFArrayFormat + 1); - } - - EmbeddedPointerFree(pStubMsg, pMemory, pFormat); -} - -/*********************************************************************** - * NdrVaryingArrayMarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrVaryingArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - unsigned char alignment; - DWORD elements, esize; - ULONG bufsize; - - TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); - - if ((pFormat[0] != RPC_FC_SMVARRAY) && - (pFormat[0] != RPC_FC_LGVARRAY)) - { - ERR("invalid format type %x\n", pFormat[0]); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return NULL; - } - - alignment = pFormat[1] + 1; - - if (pFormat[0] == RPC_FC_SMVARRAY) - { - pFormat += 2; - pFormat += sizeof(WORD); - elements = *(const WORD*)pFormat; - pFormat += sizeof(WORD); - } - else - { - pFormat += 2; - pFormat += sizeof(DWORD); - elements = *(const DWORD*)pFormat; - pFormat += sizeof(DWORD); - } - - esize = *(const WORD*)pFormat; - pFormat += sizeof(WORD); - - pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0); - if ((pStubMsg->ActualCount > elements) || - (pStubMsg->ActualCount + pStubMsg->Offset > elements)) - { - RpcRaiseException(RPC_S_INVALID_BOUND); - return NULL; - } - - WriteVariance(pStubMsg); - - ALIGN_POINTER(pStubMsg->Buffer, alignment); - - bufsize = safe_multiply(esize, pStubMsg->ActualCount); - memcpy(pStubMsg->Buffer, pMemory + pStubMsg->Offset, bufsize); - pStubMsg->BufferMark = pStubMsg->Buffer; - pStubMsg->Buffer += bufsize; - - EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat); - - STD_OVERFLOW_CHECK(pStubMsg); - - return NULL; -} - -/*********************************************************************** - * NdrVaryingArrayUnmarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrVaryingArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char **ppMemory, - PFORMAT_STRING pFormat, - unsigned char fMustAlloc) -{ - unsigned char alignment; - DWORD size, elements, esize; - ULONG bufsize; - - TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); - - if ((pFormat[0] != RPC_FC_SMVARRAY) && - (pFormat[0] != RPC_FC_LGVARRAY)) - { - ERR("invalid format type %x\n", pFormat[0]); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return NULL; - } - - alignment = pFormat[1] + 1; - - if (pFormat[0] == RPC_FC_SMVARRAY) - { - pFormat += 2; - size = *(const WORD*)pFormat; - pFormat += sizeof(WORD); - elements = *(const WORD*)pFormat; - pFormat += sizeof(WORD); - } - else - { - pFormat += 2; - size = *(const DWORD*)pFormat; - pFormat += sizeof(DWORD); - elements = *(const DWORD*)pFormat; - pFormat += sizeof(DWORD); - } - - esize = *(const WORD*)pFormat; - pFormat += sizeof(WORD); - - pFormat = ReadVariance(pStubMsg, pFormat, elements); - - ALIGN_POINTER(pStubMsg->Buffer, alignment); - - bufsize = safe_multiply(esize, pStubMsg->ActualCount); - - if (!*ppMemory || fMustAlloc) - *ppMemory = NdrAllocate(pStubMsg, size); - safe_buffer_copy(pStubMsg, *ppMemory + pStubMsg->Offset, bufsize); - - EmbeddedPointerUnmarshall(pStubMsg, ppMemory, pFormat, fMustAlloc); - - return NULL; -} - -/*********************************************************************** - * NdrVaryingArrayBufferSize [RPCRT4.@] - */ -void WINAPI NdrVaryingArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - unsigned char alignment; - DWORD elements, esize; - - TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); - - if ((pFormat[0] != RPC_FC_SMVARRAY) && - (pFormat[0] != RPC_FC_LGVARRAY)) - { - ERR("invalid format type %x\n", pFormat[0]); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return; - } - - alignment = pFormat[1] + 1; - - if (pFormat[0] == RPC_FC_SMVARRAY) - { - pFormat += 2; - pFormat += sizeof(WORD); - elements = *(const WORD*)pFormat; - pFormat += sizeof(WORD); - } - else - { - pFormat += 2; - pFormat += sizeof(DWORD); - elements = *(const DWORD*)pFormat; - pFormat += sizeof(DWORD); - } - - esize = *(const WORD*)pFormat; - pFormat += sizeof(WORD); - - pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0); - if ((pStubMsg->ActualCount > elements) || - (pStubMsg->ActualCount + pStubMsg->Offset > elements)) - { - RpcRaiseException(RPC_S_INVALID_BOUND); - return; - } - - SizeVariance(pStubMsg); - - ALIGN_LENGTH(pStubMsg->BufferLength, alignment); - - pStubMsg->BufferLength += safe_multiply(esize, pStubMsg->ActualCount); - - EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat); -} - -/*********************************************************************** - * NdrVaryingArrayMemorySize [RPCRT4.@] - */ -ULONG WINAPI NdrVaryingArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat) -{ - unsigned char alignment; - DWORD size, elements, esize; - - TRACE("(%p, %p)\n", pStubMsg, pFormat); - - if ((pFormat[0] != RPC_FC_SMVARRAY) && - (pFormat[0] != RPC_FC_LGVARRAY)) - { - ERR("invalid format type %x\n", pFormat[0]); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return 0; - } - - alignment = pFormat[1] + 1; - - if (pFormat[0] == RPC_FC_SMVARRAY) - { - pFormat += 2; - size = *(const WORD*)pFormat; - pFormat += sizeof(WORD); - elements = *(const WORD*)pFormat; - pFormat += sizeof(WORD); - } - else - { - pFormat += 2; - size = *(const DWORD*)pFormat; - pFormat += sizeof(DWORD); - elements = *(const DWORD*)pFormat; - pFormat += sizeof(DWORD); - } - - esize = *(const WORD*)pFormat; - pFormat += sizeof(WORD); - - pFormat = ReadVariance(pStubMsg, pFormat, elements); - - ALIGN_POINTER(pStubMsg->Buffer, alignment); - - pStubMsg->Buffer += safe_multiply(esize, pStubMsg->ActualCount); - pStubMsg->MemorySize += size; - - EmbeddedPointerMemorySize(pStubMsg, pFormat); - - return pStubMsg->MemorySize; -} - -/*********************************************************************** - * NdrVaryingArrayFree [RPCRT4.@] - */ -void WINAPI NdrVaryingArrayFree(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - unsigned char alignment; - DWORD elements; - - TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); - - if ((pFormat[0] != RPC_FC_SMVARRAY) && - (pFormat[0] != RPC_FC_LGVARRAY)) - { - ERR("invalid format type %x\n", pFormat[0]); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return; - } - - alignment = pFormat[1] + 1; - - if (pFormat[0] == RPC_FC_SMVARRAY) - { - pFormat += 2; - pFormat += sizeof(WORD); - elements = *(const WORD*)pFormat; - pFormat += sizeof(WORD); - } - else - { - pFormat += 2; - pFormat += sizeof(DWORD); - elements = *(const DWORD*)pFormat; - pFormat += sizeof(DWORD); - } - - pFormat += sizeof(WORD); - - pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0); - if ((pStubMsg->ActualCount > elements) || - (pStubMsg->ActualCount + pStubMsg->Offset > elements)) - { - RpcRaiseException(RPC_S_INVALID_BOUND); - return; - } - - EmbeddedPointerFree(pStubMsg, pMemory, pFormat); -} - -static ULONG get_discriminant(unsigned char fc, const unsigned char *pMemory) -{ - switch (fc) - { - case RPC_FC_BYTE: - case RPC_FC_CHAR: - case RPC_FC_SMALL: - case RPC_FC_USMALL: - return *(const UCHAR *)pMemory; - case RPC_FC_WCHAR: - case RPC_FC_SHORT: - case RPC_FC_USHORT: - case RPC_FC_ENUM16: - return *(const USHORT *)pMemory; - case RPC_FC_LONG: - case RPC_FC_ULONG: - case RPC_FC_ENUM32: - return *(const ULONG *)pMemory; - default: - FIXME("Unhandled base type: 0x%02x\n", fc); - return 0; - } -} - -static PFORMAT_STRING get_arm_offset_from_union_arm_selector(PMIDL_STUB_MESSAGE pStubMsg, - unsigned long discriminant, - PFORMAT_STRING pFormat) -{ - unsigned short num_arms, arm, type; - - num_arms = *(const SHORT*)pFormat & 0x0fff; - pFormat += 2; - for(arm = 0; arm < num_arms; arm++) - { - if(discriminant == *(const ULONG*)pFormat) - { - pFormat += 4; - break; - } - pFormat += 6; - } - - type = *(const unsigned short*)pFormat; - TRACE("type %04x\n", type); - if(arm == num_arms) /* default arm extras */ - { - if(type == 0xffff) - { - ERR("no arm for 0x%lx and no default case\n", discriminant); - RpcRaiseException(RPC_S_INVALID_TAG); - return NULL; - } - if(type == 0) - { - TRACE("falling back to empty default case for 0x%lx\n", discriminant); - return NULL; - } - } - return pFormat; -} - -static unsigned char *union_arm_marshall(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, ULONG discriminant, PFORMAT_STRING pFormat) -{ - unsigned short type; - - pFormat += 2; - - pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat); - if(!pFormat) - return NULL; - - type = *(const unsigned short*)pFormat; - if((type & 0xff00) == 0x8000) - { - unsigned char basetype = LOBYTE(type); - return NdrBaseTypeMarshall(pStubMsg, pMemory, &basetype); - } - else - { - PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat; - NDR_MARSHALL m = NdrMarshaller[*desc & NDR_TABLE_MASK]; - if (m) - { - unsigned char *saved_buffer = NULL; - int pointer_buffer_mark_set = 0; - switch(*desc) - { - case RPC_FC_RP: - case RPC_FC_UP: - case RPC_FC_OP: - case RPC_FC_FP: - ALIGN_POINTER(pStubMsg->Buffer, 4); - saved_buffer = pStubMsg->Buffer; - if (pStubMsg->PointerBufferMark) - { - pStubMsg->Buffer = pStubMsg->PointerBufferMark; - pStubMsg->PointerBufferMark = NULL; - pointer_buffer_mark_set = 1; - } - else - pStubMsg->Buffer += 4; /* for pointer ID */ - - PointerMarshall(pStubMsg, saved_buffer, *(unsigned char **)pMemory, desc); - if (pointer_buffer_mark_set) - { - STD_OVERFLOW_CHECK(pStubMsg); - pStubMsg->PointerBufferMark = pStubMsg->Buffer; - pStubMsg->Buffer = saved_buffer + 4; - } - break; - default: - m(pStubMsg, pMemory, desc); - } - } - else FIXME("no marshaller for embedded type %02x\n", *desc); - } - return NULL; -} - -static unsigned char *union_arm_unmarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char **ppMemory, - ULONG discriminant, - PFORMAT_STRING pFormat, - unsigned char fMustAlloc) -{ - unsigned short type; - - pFormat += 2; - - pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat); - if(!pFormat) - return NULL; - - type = *(const unsigned short*)pFormat; - if((type & 0xff00) == 0x8000) - { - unsigned char basetype = LOBYTE(type); - return NdrBaseTypeUnmarshall(pStubMsg, ppMemory, &basetype, FALSE); - } - else - { - PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat; - NDR_UNMARSHALL m = NdrUnmarshaller[*desc & NDR_TABLE_MASK]; - if (m) - { - unsigned char *saved_buffer = NULL; - int pointer_buffer_mark_set = 0; - switch(*desc) - { - case RPC_FC_RP: - case RPC_FC_UP: - case RPC_FC_OP: - case RPC_FC_FP: - **(void***)ppMemory = NULL; - ALIGN_POINTER(pStubMsg->Buffer, 4); - saved_buffer = pStubMsg->Buffer; - if (pStubMsg->PointerBufferMark) - { - pStubMsg->Buffer = pStubMsg->PointerBufferMark; - pStubMsg->PointerBufferMark = NULL; - pointer_buffer_mark_set = 1; - } - else - pStubMsg->Buffer += 4; /* for pointer ID */ - - if (saved_buffer + 4 > pStubMsg->BufferEnd) - RpcRaiseException(RPC_X_BAD_STUB_DATA); - - PointerUnmarshall(pStubMsg, saved_buffer, *(unsigned char ***)ppMemory, desc, fMustAlloc); - if (pointer_buffer_mark_set) - { - STD_OVERFLOW_CHECK(pStubMsg); - pStubMsg->PointerBufferMark = pStubMsg->Buffer; - pStubMsg->Buffer = saved_buffer + 4; - } - break; - default: - m(pStubMsg, ppMemory, desc, fMustAlloc); - } - } - else FIXME("no marshaller for embedded type %02x\n", *desc); - } - return NULL; -} - -static void union_arm_buffer_size(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - ULONG discriminant, - PFORMAT_STRING pFormat) -{ - unsigned short type; - - pFormat += 2; - - pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat); - if(!pFormat) - return; - - type = *(const unsigned short*)pFormat; - if((type & 0xff00) == 0x8000) - { - unsigned char basetype = LOBYTE(type); - NdrBaseTypeBufferSize(pStubMsg, pMemory, &basetype); - } - else - { - PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat; - NDR_BUFFERSIZE m = NdrBufferSizer[*desc & NDR_TABLE_MASK]; - if (m) - { - switch(*desc) - { - case RPC_FC_RP: - case RPC_FC_UP: - case RPC_FC_OP: - case RPC_FC_FP: - ALIGN_LENGTH(pStubMsg->BufferLength, 4); - pStubMsg->BufferLength += 4; /* for pointer ID */ - if (!pStubMsg->IgnoreEmbeddedPointers) - { - int saved_buffer_length = pStubMsg->BufferLength; - pStubMsg->BufferLength = pStubMsg->PointerLength; - pStubMsg->PointerLength = 0; - if(!pStubMsg->BufferLength) - ERR("BufferLength == 0??\n"); - PointerBufferSize(pStubMsg, *(unsigned char **)pMemory, desc); - pStubMsg->PointerLength = pStubMsg->BufferLength; - pStubMsg->BufferLength = saved_buffer_length; - } - break; - default: - m(pStubMsg, pMemory, desc); - } - } - else FIXME("no buffersizer for embedded type %02x\n", *desc); - } -} - -static ULONG union_arm_memory_size(PMIDL_STUB_MESSAGE pStubMsg, - ULONG discriminant, - PFORMAT_STRING pFormat) -{ - unsigned short type, size; - - size = *(const unsigned short*)pFormat; - pStubMsg->Memory += size; - pFormat += 2; - - pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat); - if(!pFormat) - return 0; - - type = *(const unsigned short*)pFormat; - if((type & 0xff00) == 0x8000) - { - return NdrBaseTypeMemorySize(pStubMsg, pFormat); - } - else - { - PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat; - NDR_MEMORYSIZE m = NdrMemorySizer[*desc & NDR_TABLE_MASK]; - unsigned char *saved_buffer; - if (m) - { - switch(*desc) - { - case RPC_FC_RP: - case RPC_FC_UP: - case RPC_FC_OP: - case RPC_FC_FP: - ALIGN_POINTER(pStubMsg->Buffer, 4); - saved_buffer = pStubMsg->Buffer; - pStubMsg->Buffer += 4; - ALIGN_LENGTH(pStubMsg->MemorySize, 4); - pStubMsg->MemorySize += 4; - if (!pStubMsg->IgnoreEmbeddedPointers) - PointerMemorySize(pStubMsg, saved_buffer, pFormat); - break; - default: - return m(pStubMsg, desc); - } - } - else FIXME("no marshaller for embedded type %02x\n", *desc); - } - - TRACE("size %d\n", size); - return size; -} - -static void union_arm_free(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - ULONG discriminant, - PFORMAT_STRING pFormat) -{ - unsigned short type; - - pFormat += 2; - - pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat); - if(!pFormat) - return; - - type = *(const unsigned short*)pFormat; - if((type & 0xff00) != 0x8000) - { - PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat; - NDR_FREE m = NdrFreer[*desc & NDR_TABLE_MASK]; - if (m) - { - switch(*desc) - { - case RPC_FC_RP: - case RPC_FC_UP: - case RPC_FC_OP: - case RPC_FC_FP: - PointerFree(pStubMsg, *(unsigned char **)pMemory, desc); - break; - default: - m(pStubMsg, pMemory, desc); - } - } - else FIXME("no freer for embedded type %02x\n", *desc); - } -} - -/*********************************************************************** - * NdrEncapsulatedUnionMarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - unsigned char switch_type; - unsigned char increment; - ULONG switch_value; - - TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); - pFormat++; - - switch_type = *pFormat & 0xf; - increment = (*pFormat & 0xf0) >> 4; - pFormat++; - - ALIGN_POINTER(pStubMsg->Buffer, increment); - - switch_value = get_discriminant(switch_type, pMemory); - TRACE("got switch value 0x%x\n", switch_value); - - NdrBaseTypeMarshall(pStubMsg, pMemory, &switch_type); - pMemory += increment; - - return union_arm_marshall(pStubMsg, pMemory, switch_value, pFormat); -} - -/*********************************************************************** - * NdrEncapsulatedUnionUnmarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char **ppMemory, - PFORMAT_STRING pFormat, - unsigned char fMustAlloc) -{ - unsigned char switch_type; - unsigned char increment; - ULONG switch_value; - unsigned short size; - unsigned char *pMemoryArm; - - TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); - pFormat++; - - switch_type = *pFormat & 0xf; - increment = (*pFormat & 0xf0) >> 4; - pFormat++; - - ALIGN_POINTER(pStubMsg->Buffer, increment); - switch_value = get_discriminant(switch_type, pStubMsg->Buffer); - TRACE("got switch value 0x%x\n", switch_value); - - size = *(const unsigned short*)pFormat + increment; - if(!*ppMemory || fMustAlloc) - *ppMemory = NdrAllocate(pStubMsg, size); - - NdrBaseTypeUnmarshall(pStubMsg, ppMemory, &switch_type, FALSE); - pMemoryArm = *ppMemory + increment; - - return union_arm_unmarshall(pStubMsg, &pMemoryArm, switch_value, pFormat, fMustAlloc); -} - -/*********************************************************************** - * NdrEncapsulatedUnionBufferSize [RPCRT4.@] - */ -void WINAPI NdrEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - unsigned char switch_type; - unsigned char increment; - ULONG switch_value; - - TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); - pFormat++; - - switch_type = *pFormat & 0xf; - increment = (*pFormat & 0xf0) >> 4; - pFormat++; - - ALIGN_LENGTH(pStubMsg->BufferLength, increment); - switch_value = get_discriminant(switch_type, pMemory); - TRACE("got switch value 0x%x\n", switch_value); - - /* Add discriminant size */ - NdrBaseTypeBufferSize(pStubMsg, (unsigned char *)&switch_value, &switch_type); - pMemory += increment; - - union_arm_buffer_size(pStubMsg, pMemory, switch_value, pFormat); -} - -/*********************************************************************** - * NdrEncapsulatedUnionMemorySize [RPCRT4.@] - */ -ULONG WINAPI NdrEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat) -{ - unsigned char switch_type; - unsigned char increment; - ULONG switch_value; - - switch_type = *pFormat & 0xf; - increment = (*pFormat & 0xf0) >> 4; - pFormat++; - - ALIGN_POINTER(pStubMsg->Buffer, increment); - switch_value = get_discriminant(switch_type, pStubMsg->Buffer); - TRACE("got switch value 0x%x\n", switch_value); - - pStubMsg->Memory += increment; - - return increment + union_arm_memory_size(pStubMsg, switch_value, pFormat + *(const SHORT*)pFormat); -} - -/*********************************************************************** - * NdrEncapsulatedUnionFree [RPCRT4.@] - */ -void WINAPI NdrEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - unsigned char switch_type; - unsigned char increment; - ULONG switch_value; - - TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); - pFormat++; - - switch_type = *pFormat & 0xf; - increment = (*pFormat & 0xf0) >> 4; - pFormat++; - - switch_value = get_discriminant(switch_type, pMemory); - TRACE("got switch value 0x%x\n", switch_value); - - pMemory += increment; - - return union_arm_free(pStubMsg, pMemory, switch_value, pFormat); -} - -/*********************************************************************** - * NdrNonEncapsulatedUnionMarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrNonEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - unsigned char switch_type; - - TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); - pFormat++; - - switch_type = *pFormat; - pFormat++; - - pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0); - TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount); - /* Marshall discriminant */ - NdrBaseTypeMarshall(pStubMsg, (unsigned char *)&pStubMsg->MaxCount, &switch_type); - - return union_arm_marshall(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat); -} - -static long unmarshall_discriminant(PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING *ppFormat) -{ - long discriminant = 0; - - switch(**ppFormat) - { - case RPC_FC_BYTE: - case RPC_FC_CHAR: - case RPC_FC_SMALL: - case RPC_FC_USMALL: - { - UCHAR d; - safe_buffer_copy(pStubMsg, &d, sizeof(d)); - discriminant = d; - break; - } - case RPC_FC_WCHAR: - case RPC_FC_SHORT: - case RPC_FC_USHORT: - { - USHORT d; - ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT)); - safe_buffer_copy(pStubMsg, &d, sizeof(d)); - discriminant = d; - break; - } - case RPC_FC_LONG: - case RPC_FC_ULONG: - { - ULONG d; - ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONG)); - safe_buffer_copy(pStubMsg, &d, sizeof(d)); - discriminant = d; - break; - } - default: - FIXME("Unhandled base type: 0x%02x\n", **ppFormat); - } - (*ppFormat)++; - - if (pStubMsg->fHasNewCorrDesc) - *ppFormat += 6; - else - *ppFormat += 4; - return discriminant; -} - -/********************************************************************** - * NdrNonEncapsulatedUnionUnmarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrNonEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char **ppMemory, - PFORMAT_STRING pFormat, - unsigned char fMustAlloc) -{ - long discriminant; - unsigned short size; - - TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); - pFormat++; - - /* Unmarshall discriminant */ - discriminant = unmarshall_discriminant(pStubMsg, &pFormat); - TRACE("unmarshalled discriminant %lx\n", discriminant); - - pFormat += *(const SHORT*)pFormat; - - size = *(const unsigned short*)pFormat; - - if(!*ppMemory || fMustAlloc) - *ppMemory = NdrAllocate(pStubMsg, size); - - return union_arm_unmarshall(pStubMsg, ppMemory, discriminant, pFormat, fMustAlloc); -} - -/*********************************************************************** - * NdrNonEncapsulatedUnionBufferSize [RPCRT4.@] - */ -void WINAPI NdrNonEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - unsigned char switch_type; - - TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); - pFormat++; - - switch_type = *pFormat; - pFormat++; - - pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0); - TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount); - /* Add discriminant size */ - NdrBaseTypeBufferSize(pStubMsg, (unsigned char *)&pStubMsg->MaxCount, &switch_type); - - union_arm_buffer_size(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat); -} - -/*********************************************************************** - * NdrNonEncapsulatedUnionMemorySize [RPCRT4.@] - */ -ULONG WINAPI NdrNonEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat) -{ - ULONG discriminant; - - pFormat++; - /* Unmarshall discriminant */ - discriminant = unmarshall_discriminant(pStubMsg, &pFormat); - TRACE("unmarshalled discriminant 0x%x\n", discriminant); - - return union_arm_memory_size(pStubMsg, discriminant, pFormat + *(const SHORT*)pFormat); -} - -/*********************************************************************** - * NdrNonEncapsulatedUnionFree [RPCRT4.@] - */ -void WINAPI NdrNonEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); - pFormat++; - pFormat++; - - pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0); - TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount); - - return union_arm_free(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat); -} - -/*********************************************************************** - * NdrByteCountPointerMarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrByteCountPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - FIXME("stub\n"); - return NULL; -} - -/*********************************************************************** - * NdrByteCountPointerUnmarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrByteCountPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char **ppMemory, - PFORMAT_STRING pFormat, - unsigned char fMustAlloc) -{ - FIXME("stub\n"); - return NULL; -} - -/*********************************************************************** - * NdrByteCountPointerBufferSize [RPCRT4.@] - */ -void WINAPI NdrByteCountPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - FIXME("stub\n"); -} - -/*********************************************************************** - * NdrByteCountPointerMemorySize [RPCRT4.@] - */ -ULONG WINAPI NdrByteCountPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat) -{ - FIXME("stub\n"); - return 0; -} - -/*********************************************************************** - * NdrByteCountPointerFree [RPCRT4.@] - */ -void WINAPI NdrByteCountPointerFree(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - FIXME("stub\n"); -} - -/*********************************************************************** - * NdrXmitOrRepAsMarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrXmitOrRepAsMarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - FIXME("stub\n"); - return NULL; -} - -/*********************************************************************** - * NdrXmitOrRepAsUnmarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrXmitOrRepAsUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char **ppMemory, - PFORMAT_STRING pFormat, - unsigned char fMustAlloc) -{ - FIXME("stub\n"); - return NULL; -} - -/*********************************************************************** - * NdrXmitOrRepAsBufferSize [RPCRT4.@] - */ -void WINAPI NdrXmitOrRepAsBufferSize(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - FIXME("stub\n"); -} - -/*********************************************************************** - * NdrXmitOrRepAsMemorySize [RPCRT4.@] - */ -ULONG WINAPI NdrXmitOrRepAsMemorySize(PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat) -{ - FIXME("stub\n"); - return 0; -} - -/*********************************************************************** - * NdrXmitOrRepAsFree [RPCRT4.@] - */ -void WINAPI NdrXmitOrRepAsFree(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - FIXME("stub\n"); -} - -#include "pshpack1.h" -typedef struct -{ - unsigned char type; - unsigned char flags_type; /* flags in upper nibble, type in lower nibble */ - ULONG low_value; - ULONG high_value; -} NDR_RANGE; -#include "poppack.h" - -/*********************************************************************** - * NdrRangeMarshall [internal] - */ -unsigned char *WINAPI NdrRangeMarshall( - PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - NDR_RANGE *pRange = (NDR_RANGE *)pFormat; - unsigned char base_type; - - TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat); - - if (pRange->type != RPC_FC_RANGE) - { - ERR("invalid format type %x\n", pRange->type); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return NULL; - } - - base_type = pRange->flags_type & 0xf; - - return NdrBaseTypeMarshall(pStubMsg, pMemory, &base_type); -} - -/*********************************************************************** - * NdrRangeUnmarshall - */ -unsigned char *WINAPI NdrRangeUnmarshall( - PMIDL_STUB_MESSAGE pStubMsg, - unsigned char **ppMemory, - PFORMAT_STRING pFormat, - unsigned char fMustAlloc) -{ - NDR_RANGE *pRange = (NDR_RANGE *)pFormat; - unsigned char base_type; - - TRACE("pStubMsg: %p, ppMemory: %p, type: 0x%02x, fMustAlloc: %s\n", pStubMsg, ppMemory, *pFormat, fMustAlloc ? "true" : "false"); - - if (pRange->type != RPC_FC_RANGE) - { - ERR("invalid format type %x\n", pRange->type); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return NULL; - } - base_type = pRange->flags_type & 0xf; - - TRACE("base_type = 0x%02x, low_value = %d, high_value = %d\n", - base_type, pRange->low_value, pRange->high_value); - -#define RANGE_UNMARSHALL(type, format_spec) \ - do \ - { \ - ALIGN_POINTER(pStubMsg->Buffer, sizeof(type)); \ - if (fMustAlloc || !*ppMemory) \ - *ppMemory = NdrAllocate(pStubMsg, sizeof(type)); \ - if ((*(type *)pStubMsg->Buffer < (type)pRange->low_value) || \ - (*(type *)pStubMsg->Buffer > (type)pRange->high_value)) \ - { \ - ERR("value exceeded bounds: " format_spec ", low: " format_spec ", high: " format_spec "\n", \ - *(type *)pStubMsg->Buffer, (type)pRange->low_value, \ - (type)pRange->high_value); \ - RpcRaiseException(RPC_S_INVALID_BOUND); \ - return NULL; \ - } \ - TRACE("*ppMemory: %p\n", *ppMemory); \ - **(type **)ppMemory = *(type *)pStubMsg->Buffer; \ - pStubMsg->Buffer += sizeof(type); \ - } while (0) - - switch(base_type) - { - case RPC_FC_CHAR: - case RPC_FC_SMALL: - RANGE_UNMARSHALL(UCHAR, "%d"); - TRACE("value: 0x%02x\n", **(UCHAR **)ppMemory); - break; - case RPC_FC_BYTE: - case RPC_FC_USMALL: - RANGE_UNMARSHALL(CHAR, "%u"); - TRACE("value: 0x%02x\n", **(UCHAR **)ppMemory); - break; - case RPC_FC_WCHAR: /* FIXME: valid? */ - case RPC_FC_USHORT: - RANGE_UNMARSHALL(USHORT, "%u"); - TRACE("value: 0x%04x\n", **(USHORT **)ppMemory); - break; - case RPC_FC_SHORT: - RANGE_UNMARSHALL(SHORT, "%d"); - TRACE("value: 0x%04x\n", **(USHORT **)ppMemory); - break; - case RPC_FC_LONG: - RANGE_UNMARSHALL(LONG, "%d"); - TRACE("value: 0x%08x\n", **(ULONG **)ppMemory); - break; - case RPC_FC_ULONG: - RANGE_UNMARSHALL(ULONG, "%u"); - TRACE("value: 0x%08x\n", **(ULONG **)ppMemory); - break; - case RPC_FC_ENUM16: - case RPC_FC_ENUM32: - FIXME("Unhandled enum type\n"); - break; - case RPC_FC_ERROR_STATUS_T: /* FIXME: valid? */ - case RPC_FC_FLOAT: - case RPC_FC_DOUBLE: - case RPC_FC_HYPER: - default: - ERR("invalid range base type: 0x%02x\n", base_type); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - } - - return NULL; -} - -/*********************************************************************** - * NdrRangeBufferSize [internal] - */ -void WINAPI NdrRangeBufferSize( - PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - NDR_RANGE *pRange = (NDR_RANGE *)pFormat; - unsigned char base_type; - - TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat); - - if (pRange->type != RPC_FC_RANGE) - { - ERR("invalid format type %x\n", pRange->type); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - } - base_type = pRange->flags_type & 0xf; - - NdrBaseTypeBufferSize(pStubMsg, pMemory, &base_type); -} - -/*********************************************************************** - * NdrRangeMemorySize [internal] - */ -ULONG WINAPI NdrRangeMemorySize( - PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat) -{ - NDR_RANGE *pRange = (NDR_RANGE *)pFormat; - unsigned char base_type; - - if (pRange->type != RPC_FC_RANGE) - { - ERR("invalid format type %x\n", pRange->type); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return 0; - } - base_type = pRange->flags_type & 0xf; - - return NdrBaseTypeMemorySize(pStubMsg, &base_type); -} - -/*********************************************************************** - * NdrRangeFree [internal] - */ -void WINAPI NdrRangeFree(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - TRACE("pStubMsg %p pMemory %p type 0x%02x\n", pStubMsg, pMemory, *pFormat); - - /* nothing to do */ -} - -/*********************************************************************** - * NdrBaseTypeMarshall [internal] - */ -static unsigned char *WINAPI NdrBaseTypeMarshall( - PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat); - - switch(*pFormat) - { - case RPC_FC_BYTE: - case RPC_FC_CHAR: - case RPC_FC_SMALL: - case RPC_FC_USMALL: - *(UCHAR *)pStubMsg->Buffer = *(UCHAR *)pMemory; - pStubMsg->Buffer += sizeof(UCHAR); - TRACE("value: 0x%02x\n", *(UCHAR *)pMemory); - break; - case RPC_FC_WCHAR: - case RPC_FC_SHORT: - case RPC_FC_USHORT: - ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT)); - *(USHORT *)pStubMsg->Buffer = *(USHORT *)pMemory; - pStubMsg->Buffer += sizeof(USHORT); - TRACE("value: 0x%04x\n", *(USHORT *)pMemory); - break; - case RPC_FC_LONG: - case RPC_FC_ULONG: - case RPC_FC_ERROR_STATUS_T: - case RPC_FC_ENUM32: - ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONG)); - *(ULONG *)pStubMsg->Buffer = *(ULONG *)pMemory; - pStubMsg->Buffer += sizeof(ULONG); - TRACE("value: 0x%08x\n", *(ULONG *)pMemory); - break; - case RPC_FC_FLOAT: - ALIGN_POINTER(pStubMsg->Buffer, sizeof(float)); - *(float *)pStubMsg->Buffer = *(float *)pMemory; - pStubMsg->Buffer += sizeof(float); - break; - case RPC_FC_DOUBLE: - ALIGN_POINTER(pStubMsg->Buffer, sizeof(double)); - *(double *)pStubMsg->Buffer = *(double *)pMemory; - pStubMsg->Buffer += sizeof(double); - break; - case RPC_FC_HYPER: - ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONGLONG)); - *(ULONGLONG *)pStubMsg->Buffer = *(ULONGLONG *)pMemory; - pStubMsg->Buffer += sizeof(ULONGLONG); - TRACE("value: %s\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory)); - break; - case RPC_FC_ENUM16: - /* only 16-bits on the wire, so do a sanity check */ - if (*(UINT *)pMemory > SHRT_MAX) - RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE); - ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT)); - *(USHORT *)pStubMsg->Buffer = *(UINT *)pMemory; - pStubMsg->Buffer += sizeof(USHORT); - TRACE("value: 0x%04x\n", *(UINT *)pMemory); - break; - default: - FIXME("Unhandled base type: 0x%02x\n", *pFormat); - } - - STD_OVERFLOW_CHECK(pStubMsg); - - /* FIXME: what is the correct return value? */ - return NULL; -} - -/*********************************************************************** - * NdrBaseTypeUnmarshall [internal] - */ -static unsigned char *WINAPI NdrBaseTypeUnmarshall( - PMIDL_STUB_MESSAGE pStubMsg, - unsigned char **ppMemory, - PFORMAT_STRING pFormat, - unsigned char fMustAlloc) -{ - TRACE("pStubMsg: %p, ppMemory: %p, type: 0x%02x, fMustAlloc: %s\n", pStubMsg, ppMemory, *pFormat, fMustAlloc ? "true" : "false"); - -#define BASE_TYPE_UNMARSHALL(type) \ - ALIGN_POINTER(pStubMsg->Buffer, sizeof(type)); \ - if (fMustAlloc || !*ppMemory) \ - *ppMemory = NdrAllocate(pStubMsg, sizeof(type)); \ - TRACE("*ppMemory: %p\n", *ppMemory); \ - **(type **)ppMemory = *(type *)pStubMsg->Buffer; \ - pStubMsg->Buffer += sizeof(type); - - switch(*pFormat) - { - case RPC_FC_BYTE: - case RPC_FC_CHAR: - case RPC_FC_SMALL: - case RPC_FC_USMALL: - BASE_TYPE_UNMARSHALL(UCHAR); - TRACE("value: 0x%02x\n", **(UCHAR **)ppMemory); - break; - case RPC_FC_WCHAR: - case RPC_FC_SHORT: - case RPC_FC_USHORT: - BASE_TYPE_UNMARSHALL(USHORT); - TRACE("value: 0x%04x\n", **(USHORT **)ppMemory); - break; - case RPC_FC_LONG: - case RPC_FC_ULONG: - case RPC_FC_ERROR_STATUS_T: - case RPC_FC_ENUM32: - BASE_TYPE_UNMARSHALL(ULONG); - TRACE("value: 0x%08x\n", **(ULONG **)ppMemory); - break; - case RPC_FC_FLOAT: - BASE_TYPE_UNMARSHALL(float); - TRACE("value: %f\n", **(float **)ppMemory); - break; - case RPC_FC_DOUBLE: - BASE_TYPE_UNMARSHALL(double); - TRACE("value: %f\n", **(double **)ppMemory); - break; - case RPC_FC_HYPER: - BASE_TYPE_UNMARSHALL(ULONGLONG); - TRACE("value: %s\n", wine_dbgstr_longlong(**(ULONGLONG **)ppMemory)); - break; - case RPC_FC_ENUM16: - ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT)); - if (fMustAlloc || !*ppMemory) - *ppMemory = NdrAllocate(pStubMsg, sizeof(UINT)); - TRACE("*ppMemory: %p\n", *ppMemory); - /* 16-bits on the wire, but int in memory */ - **(UINT **)ppMemory = *(USHORT *)pStubMsg->Buffer; - pStubMsg->Buffer += sizeof(USHORT); - TRACE("value: 0x%08x\n", **(UINT **)ppMemory); - break; - default: - FIXME("Unhandled base type: 0x%02x\n", *pFormat); - } -#undef BASE_TYPE_UNMARSHALL - - /* FIXME: what is the correct return value? */ - - return NULL; -} - -/*********************************************************************** - * NdrBaseTypeBufferSize [internal] - */ -static void WINAPI NdrBaseTypeBufferSize( - PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat); - - switch(*pFormat) - { - case RPC_FC_BYTE: - case RPC_FC_CHAR: - case RPC_FC_SMALL: - case RPC_FC_USMALL: - pStubMsg->BufferLength += sizeof(UCHAR); - break; - case RPC_FC_WCHAR: - case RPC_FC_SHORT: - case RPC_FC_USHORT: - case RPC_FC_ENUM16: - ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(USHORT)); - pStubMsg->BufferLength += sizeof(USHORT); - break; - case RPC_FC_LONG: - case RPC_FC_ULONG: - case RPC_FC_ENUM32: - ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(ULONG)); - pStubMsg->BufferLength += sizeof(ULONG); - break; - case RPC_FC_FLOAT: - ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(float)); - pStubMsg->BufferLength += sizeof(float); - break; - case RPC_FC_DOUBLE: - ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(double)); - pStubMsg->BufferLength += sizeof(double); - break; - case RPC_FC_HYPER: - ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(ULONGLONG)); - pStubMsg->BufferLength += sizeof(ULONGLONG); - break; - case RPC_FC_ERROR_STATUS_T: - ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(error_status_t)); - pStubMsg->BufferLength += sizeof(error_status_t); - break; - default: - FIXME("Unhandled base type: 0x%02x\n", *pFormat); - } -} - -/*********************************************************************** - * NdrBaseTypeMemorySize [internal] - */ -static ULONG WINAPI NdrBaseTypeMemorySize( - PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat) -{ - switch(*pFormat) - { - case RPC_FC_BYTE: - case RPC_FC_CHAR: - case RPC_FC_SMALL: - case RPC_FC_USMALL: - pStubMsg->Buffer += sizeof(UCHAR); - pStubMsg->MemorySize += sizeof(UCHAR); - return sizeof(UCHAR); - case RPC_FC_WCHAR: - case RPC_FC_SHORT: - case RPC_FC_USHORT: - pStubMsg->Buffer += sizeof(USHORT); - pStubMsg->MemorySize += sizeof(USHORT); - return sizeof(USHORT); - case RPC_FC_LONG: - case RPC_FC_ULONG: - pStubMsg->Buffer += sizeof(ULONG); - pStubMsg->MemorySize += sizeof(ULONG); - return sizeof(ULONG); - case RPC_FC_FLOAT: - pStubMsg->Buffer += sizeof(float); - pStubMsg->MemorySize += sizeof(float); - return sizeof(float); - case RPC_FC_DOUBLE: - pStubMsg->Buffer += sizeof(double); - pStubMsg->MemorySize += sizeof(double); - return sizeof(double); - case RPC_FC_HYPER: - pStubMsg->Buffer += sizeof(ULONGLONG); - pStubMsg->MemorySize += sizeof(ULONGLONG); - return sizeof(ULONGLONG); - case RPC_FC_ERROR_STATUS_T: - pStubMsg->Buffer += sizeof(error_status_t); - pStubMsg->MemorySize += sizeof(error_status_t); - return sizeof(error_status_t); - case RPC_FC_ENUM16: - case RPC_FC_ENUM32: - pStubMsg->Buffer += sizeof(INT); - pStubMsg->MemorySize += sizeof(INT); - return sizeof(INT); - default: - FIXME("Unhandled base type: 0x%02x\n", *pFormat); - return 0; - } -} - -/*********************************************************************** - * NdrBaseTypeFree [internal] - */ -static void WINAPI NdrBaseTypeFree(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - TRACE("pStubMsg %p pMemory %p type 0x%02x\n", pStubMsg, pMemory, *pFormat); - - /* nothing to do */ -} - -/*********************************************************************** - * NdrContextHandleBufferSize [internal] - */ -static void WINAPI NdrContextHandleBufferSize( - PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat); - - if (*pFormat != RPC_FC_BIND_CONTEXT) - { - ERR("invalid format type %x\n", *pFormat); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - } - ALIGN_LENGTH(pStubMsg->BufferLength, 4); - pStubMsg->BufferLength += cbNDRContext; -} - -/*********************************************************************** - * NdrContextHandleMarshall [internal] - */ -static unsigned char *WINAPI NdrContextHandleMarshall( - PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat); - - if (*pFormat != RPC_FC_BIND_CONTEXT) - { - ERR("invalid format type %x\n", *pFormat); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - } - - if (pFormat[1] & 0x80) - NdrClientContextMarshall(pStubMsg, *(NDR_CCONTEXT **)pMemory, FALSE); - else - NdrClientContextMarshall(pStubMsg, (NDR_CCONTEXT *)pMemory, FALSE); - - return NULL; -} - -/*********************************************************************** - * NdrContextHandleUnmarshall [internal] - */ -static unsigned char *WINAPI NdrContextHandleUnmarshall( - PMIDL_STUB_MESSAGE pStubMsg, - unsigned char **ppMemory, - PFORMAT_STRING pFormat, - unsigned char fMustAlloc) -{ - if (*pFormat != RPC_FC_BIND_CONTEXT) - { - ERR("invalid format type %x\n", *pFormat); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - } - - **(NDR_CCONTEXT **)ppMemory = NULL; - NdrClientContextUnmarshall(pStubMsg, *(NDR_CCONTEXT **)ppMemory, pStubMsg->RpcMsg->Handle); - - return NULL; -} - -/*********************************************************************** - * NdrClientContextMarshall [RPCRT4.@] - */ -void WINAPI NdrClientContextMarshall(PMIDL_STUB_MESSAGE pStubMsg, - NDR_CCONTEXT ContextHandle, - int fCheck) -{ - TRACE("(%p, %p, %d)\n", pStubMsg, ContextHandle, fCheck); - - ALIGN_POINTER(pStubMsg->Buffer, 4); - - /* FIXME: what does fCheck do? */ - NDRCContextMarshall(ContextHandle, - pStubMsg->Buffer); - - pStubMsg->Buffer += cbNDRContext; -} - -/*********************************************************************** - * NdrClientContextUnmarshall [RPCRT4.@] - */ -void WINAPI NdrClientContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, - NDR_CCONTEXT * pContextHandle, - RPC_BINDING_HANDLE BindHandle) -{ - TRACE("(%p, %p, %p)\n", pStubMsg, pContextHandle, BindHandle); - - ALIGN_POINTER(pStubMsg->Buffer, 4); - - if (pStubMsg->Buffer + cbNDRContext > pStubMsg->BufferEnd) - RpcRaiseException(RPC_X_BAD_STUB_DATA); - - NDRCContextUnmarshall(pContextHandle, - BindHandle, - pStubMsg->Buffer, - pStubMsg->RpcMsg->DataRepresentation); - - pStubMsg->Buffer += cbNDRContext; -} - -void WINAPI NdrServerContextMarshall(PMIDL_STUB_MESSAGE pStubMsg, - NDR_SCONTEXT ContextHandle, - NDR_RUNDOWN RundownRoutine ) -{ - FIXME("(%p, %p, %p): stub\n", pStubMsg, ContextHandle, RundownRoutine); -} - -NDR_SCONTEXT WINAPI NdrServerContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg) -{ - FIXME("(%p): stub\n", pStubMsg); - return NULL; -} - -void WINAPI NdrContextHandleSize(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char* pMemory, - PFORMAT_STRING pFormat) -{ - FIXME("(%p, %p, %p): stub\n", pStubMsg, pMemory, pFormat); -} - -NDR_SCONTEXT WINAPI NdrContextHandleInitialize(PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat) -{ - FIXME("(%p, %p): stub\n", pStubMsg, pFormat); - return NULL; -} - -void WINAPI NdrServerContextNewMarshall(PMIDL_STUB_MESSAGE pStubMsg, - NDR_SCONTEXT ContextHandle, - NDR_RUNDOWN RundownRoutine, - PFORMAT_STRING pFormat) -{ - FIXME("(%p, %p, %p, %p): stub\n", pStubMsg, ContextHandle, RundownRoutine, pFormat); -} - -NDR_SCONTEXT WINAPI NdrServerContextNewUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat) -{ - FIXME("(%p, %p): stub\n", pStubMsg, pFormat); - return NULL; -} - -#define NDR_CONTEXT_HANDLE_MAGIC 0x4352444e - -typedef struct ndr_context_handle -{ - DWORD attributes; - GUID uuid; -} ndr_context_handle; - -struct context_handle_entry -{ - struct list entry; - DWORD magic; - RPC_BINDING_HANDLE handle; - ndr_context_handle wire_data; -}; - -static struct list context_handle_list = LIST_INIT(context_handle_list); - -static CRITICAL_SECTION ndr_context_cs; -static CRITICAL_SECTION_DEBUG ndr_context_debug = -{ - 0, 0, &ndr_context_cs, - { &ndr_context_debug.ProcessLocksList, &ndr_context_debug.ProcessLocksList }, - 0, 0, { (DWORD_PTR)(__FILE__ ": ndr_context") } -}; -static CRITICAL_SECTION ndr_context_cs = { &ndr_context_debug, -1, 0, 0, 0, 0 }; - -static struct context_handle_entry *get_context_entry(NDR_CCONTEXT CContext) -{ - struct context_handle_entry *che = (struct context_handle_entry*) CContext; - - if (che->magic != NDR_CONTEXT_HANDLE_MAGIC) - return NULL; - return che; -} - -static struct context_handle_entry *context_entry_from_guid(LPCGUID uuid) -{ - struct context_handle_entry *che; - LIST_FOR_EACH_ENTRY(che, &context_handle_list, struct context_handle_entry, entry) - if (IsEqualGUID(&che->wire_data.uuid, uuid)) - return che; - return NULL; -} - -RPC_BINDING_HANDLE WINAPI NDRCContextBinding(NDR_CCONTEXT CContext) -{ - struct context_handle_entry *che; - RPC_BINDING_HANDLE handle = NULL; - - TRACE("%p\n", CContext); - - EnterCriticalSection(&ndr_context_cs); - che = get_context_entry(CContext); - if (che) - handle = che->handle; - LeaveCriticalSection(&ndr_context_cs); - - if (!handle) - RpcRaiseException(ERROR_INVALID_HANDLE); - return handle; -} - -void WINAPI NDRCContextMarshall(NDR_CCONTEXT CContext, void *pBuff) -{ - struct context_handle_entry *che; - - TRACE("%p %p\n", CContext, pBuff); - - if (CContext) - { - EnterCriticalSection(&ndr_context_cs); - che = get_context_entry(CContext); - memcpy(pBuff, &che->wire_data, sizeof (ndr_context_handle)); - LeaveCriticalSection(&ndr_context_cs); - } - else - { - ndr_context_handle *wire_data = (ndr_context_handle *)pBuff; - wire_data->attributes = 0; - wire_data->uuid = GUID_NULL; - } -} - -static UINT ndr_update_context_handle(NDR_CCONTEXT *CContext, - RPC_BINDING_HANDLE hBinding, - const ndr_context_handle *chi) -{ - struct context_handle_entry *che = NULL; - - /* a null UUID means we should free the context handle */ - if (IsEqualGUID(&chi->uuid, &GUID_NULL)) - { - if (*CContext) - { - che = get_context_entry(*CContext); - if (!che) - return ERROR_INVALID_HANDLE; - list_remove(&che->entry); - RpcBindingFree(&che->handle); - HeapFree(GetProcessHeap(), 0, che); - che = NULL; - } - } - /* if there's no existing entry matching the GUID, allocate one */ - else if (!(che = context_entry_from_guid(&chi->uuid))) - { - che = HeapAlloc(GetProcessHeap(), 0, sizeof *che); - if (!che) - return ERROR_NOT_ENOUGH_MEMORY; - che->magic = NDR_CONTEXT_HANDLE_MAGIC; - RpcBindingCopy(hBinding, &che->handle); - list_add_tail(&context_handle_list, &che->entry); - memcpy(&che->wire_data, chi, sizeof *chi); - } - - *CContext = che; - - return ERROR_SUCCESS; -} - -/*********************************************************************** - * NDRCContextUnmarshall [RPCRT4.@] - */ -void WINAPI NDRCContextUnmarshall(NDR_CCONTEXT *CContext, - RPC_BINDING_HANDLE hBinding, - void *pBuff, ULONG DataRepresentation) -{ - UINT r; - - TRACE("*%p=(%p) %p %p %08x\n", - CContext, *CContext, hBinding, pBuff, DataRepresentation); - - EnterCriticalSection(&ndr_context_cs); - r = ndr_update_context_handle(CContext, hBinding, pBuff); - LeaveCriticalSection(&ndr_context_cs); - if (r) - RpcRaiseException(r); -} - -/*********************************************************************** - * NDRSContextMarshall [RPCRT4.@] - */ -void WINAPI NDRSContextMarshall(NDR_SCONTEXT CContext, - void *pBuff, - NDR_RUNDOWN userRunDownIn) -{ - FIXME("(%p %p %p): stub\n", CContext, pBuff, userRunDownIn); -} - -/*********************************************************************** - * NDRSContextMarshallEx [RPCRT4.@] - */ -void WINAPI NDRSContextMarshallEx(RPC_BINDING_HANDLE hBinding, - NDR_SCONTEXT CContext, - void *pBuff, - NDR_RUNDOWN userRunDownIn) -{ - FIXME("(%p %p %p %p): stub\n", hBinding, CContext, pBuff, userRunDownIn); -} - -/*********************************************************************** - * NDRSContextMarshall2 [RPCRT4.@] - */ -void WINAPI NDRSContextMarshall2(RPC_BINDING_HANDLE hBinding, - NDR_SCONTEXT CContext, - void *pBuff, - NDR_RUNDOWN userRunDownIn, - void *CtxGuard, ULONG Flags) -{ - FIXME("(%p %p %p %p %p %u): stub\n", - hBinding, CContext, pBuff, userRunDownIn, CtxGuard, Flags); -} - -/*********************************************************************** - * NDRSContextUnmarshall [RPCRT4.@] - */ -NDR_SCONTEXT WINAPI NDRSContextUnmarshall(void *pBuff, - ULONG DataRepresentation) -{ - FIXME("(%p %08x): stub\n", pBuff, DataRepresentation); - return NULL; -} - -/*********************************************************************** - * NDRSContextUnmarshallEx [RPCRT4.@] - */ -NDR_SCONTEXT WINAPI NDRSContextUnmarshallEx(RPC_BINDING_HANDLE hBinding, - void *pBuff, - ULONG DataRepresentation) -{ - FIXME("(%p %p %08x): stub\n", hBinding, pBuff, DataRepresentation); - return NULL; -} - -/*********************************************************************** - * NDRSContextUnmarshall2 [RPCRT4.@] - */ -NDR_SCONTEXT WINAPI NDRSContextUnmarshall2(RPC_BINDING_HANDLE hBinding, - void *pBuff, - ULONG DataRepresentation, - void *CtxGuard, ULONG Flags) -{ - FIXME("(%p %p %08x %p %u): stub\n", - hBinding, pBuff, DataRepresentation, CtxGuard, Flags); - return NULL; -} +/* + * NDR data marshalling + * + * Copyright 2002 Greg Turner + * Copyright 2003-2006 CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + * + * TODO: + * - Non-conformant strings + * - String structs + * - Byte count pointers + * - transmit_as/represent as + * - Multi-dimensional arrays + * - Conversion functions (NdrConvert) + * - Checks for integer addition overflow in base type and user marshall functions + */ + +#include +#include +#include +#include +#include + +#include "windef.h" +#include "winbase.h" +#include "winerror.h" + +#include "ndr_misc.h" +#include "rpcndr.h" + +#include "wine/unicode.h" +#include "wine/rpcfc.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(ole); + +#if defined(__i386__) +# define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \ + (*((UINT32 *)(pchar)) = (uint32)) + +# define LITTLE_ENDIAN_UINT32_READ(pchar) \ + (*((UINT32 *)(pchar))) +#else + /* these would work for i386 too, but less efficient */ +# define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \ + (*(pchar) = LOBYTE(LOWORD(uint32)), \ + *((pchar)+1) = HIBYTE(LOWORD(uint32)), \ + *((pchar)+2) = LOBYTE(HIWORD(uint32)), \ + *((pchar)+3) = HIBYTE(HIWORD(uint32)), \ + (uint32)) /* allow as r-value */ + +# define LITTLE_ENDIAN_UINT32_READ(pchar) \ + (MAKELONG( \ + MAKEWORD(*(pchar), *((pchar)+1)), \ + MAKEWORD(*((pchar)+2), *((pchar)+3)))) +#endif + +#define BIG_ENDIAN_UINT32_WRITE(pchar, uint32) \ + (*((pchar)+3) = LOBYTE(LOWORD(uint32)), \ + *((pchar)+2) = HIBYTE(LOWORD(uint32)), \ + *((pchar)+1) = LOBYTE(HIWORD(uint32)), \ + *(pchar) = HIBYTE(HIWORD(uint32)), \ + (uint32)) /* allow as r-value */ + +#define BIG_ENDIAN_UINT32_READ(pchar) \ + (MAKELONG( \ + MAKEWORD(*((pchar)+3), *((pchar)+2)), \ + MAKEWORD(*((pchar)+1), *(pchar)))) + +#ifdef NDR_LOCAL_IS_BIG_ENDIAN +# define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \ + BIG_ENDIAN_UINT32_WRITE(pchar, uint32) +# define NDR_LOCAL_UINT32_READ(pchar) \ + BIG_ENDIAN_UINT32_READ(pchar) +#else +# define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \ + LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) +# define NDR_LOCAL_UINT32_READ(pchar) \ + LITTLE_ENDIAN_UINT32_READ(pchar) +#endif + +/* _Align must be the desired alignment, + * e.g. ALIGN_LENGTH(len, 4) to align on a dword boundary. */ +#define ALIGNED_LENGTH(_Len, _Align) (((_Len)+(_Align)-1)&~((_Align)-1)) +#define ALIGNED_POINTER(_Ptr, _Align) ((LPVOID)ALIGNED_LENGTH((ULONG_PTR)(_Ptr), _Align)) +#define ALIGN_LENGTH(_Len, _Align) _Len = ALIGNED_LENGTH(_Len, _Align) +#define ALIGN_POINTER(_Ptr, _Align) _Ptr = ALIGNED_POINTER(_Ptr, _Align) +#define ALIGN_POINTER_CLEAR(_Ptr, _Align) \ + do { \ + memset((_Ptr), 0, ((_Align) - (ULONG_PTR)(_Ptr)) & ((_Align) - 1)); \ + ALIGN_POINTER(_Ptr, _Align); \ + } while(0) + +#define STD_OVERFLOW_CHECK(_Msg) do { \ + TRACE("buffer=%d/%d\n", _Msg->Buffer - (unsigned char *)_Msg->RpcMsg->Buffer, _Msg->BufferLength); \ + if (_Msg->Buffer > (unsigned char *)_Msg->RpcMsg->Buffer + _Msg->BufferLength) \ + ERR("buffer overflow %d bytes\n", _Msg->Buffer - ((unsigned char *)_Msg->RpcMsg->Buffer + _Msg->BufferLength)); \ + } while (0) + +#define NDR_TABLE_SIZE 128 +#define NDR_TABLE_MASK 127 + +static unsigned char *WINAPI NdrBaseTypeMarshall(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING); +static unsigned char *WINAPI NdrBaseTypeUnmarshall(PMIDL_STUB_MESSAGE, unsigned char **, PFORMAT_STRING, unsigned char); +static void WINAPI NdrBaseTypeBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING); +static void WINAPI NdrBaseTypeFree(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING); +static ULONG WINAPI NdrBaseTypeMemorySize(PMIDL_STUB_MESSAGE, PFORMAT_STRING); + +static unsigned char *WINAPI NdrContextHandleMarshall(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING); +static void WINAPI NdrContextHandleBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING); +static unsigned char *WINAPI NdrContextHandleUnmarshall(PMIDL_STUB_MESSAGE, unsigned char **, PFORMAT_STRING, unsigned char); + +const NDR_MARSHALL NdrMarshaller[NDR_TABLE_SIZE] = { + 0, + NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, + NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, + NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, + NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, + /* 0x10 */ + NdrBaseTypeMarshall, + /* 0x11 */ + NdrPointerMarshall, NdrPointerMarshall, + NdrPointerMarshall, NdrPointerMarshall, + /* 0x15 */ + NdrSimpleStructMarshall, NdrSimpleStructMarshall, + NdrConformantStructMarshall, NdrConformantStructMarshall, + NdrConformantVaryingStructMarshall, + NdrComplexStructMarshall, + /* 0x1b */ + NdrConformantArrayMarshall, + NdrConformantVaryingArrayMarshall, + NdrFixedArrayMarshall, NdrFixedArrayMarshall, + NdrVaryingArrayMarshall, NdrVaryingArrayMarshall, + NdrComplexArrayMarshall, + /* 0x22 */ + NdrConformantStringMarshall, 0, 0, + NdrConformantStringMarshall, + NdrNonConformantStringMarshall, 0, 0, 0, + /* 0x2a */ + NdrEncapsulatedUnionMarshall, + NdrNonEncapsulatedUnionMarshall, + NdrByteCountPointerMarshall, + NdrXmitOrRepAsMarshall, NdrXmitOrRepAsMarshall, + /* 0x2f */ + NdrInterfacePointerMarshall, + /* 0x30 */ + NdrContextHandleMarshall, + /* 0xb1 */ + 0, 0, 0, + NdrUserMarshalMarshall, + 0, 0, + /* 0xb7 */ + NdrRangeMarshall +}; +const NDR_UNMARSHALL NdrUnmarshaller[NDR_TABLE_SIZE] = { + 0, + NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, + NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, + NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, + NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, + /* 0x10 */ + NdrBaseTypeUnmarshall, + /* 0x11 */ + NdrPointerUnmarshall, NdrPointerUnmarshall, + NdrPointerUnmarshall, NdrPointerUnmarshall, + /* 0x15 */ + NdrSimpleStructUnmarshall, NdrSimpleStructUnmarshall, + NdrConformantStructUnmarshall, NdrConformantStructUnmarshall, + NdrConformantVaryingStructUnmarshall, + NdrComplexStructUnmarshall, + /* 0x1b */ + NdrConformantArrayUnmarshall, + NdrConformantVaryingArrayUnmarshall, + NdrFixedArrayUnmarshall, NdrFixedArrayUnmarshall, + NdrVaryingArrayUnmarshall, NdrVaryingArrayUnmarshall, + NdrComplexArrayUnmarshall, + /* 0x22 */ + NdrConformantStringUnmarshall, 0, 0, + NdrConformantStringUnmarshall, + NdrNonConformantStringUnmarshall, 0, 0, 0, + /* 0x2a */ + NdrEncapsulatedUnionUnmarshall, + NdrNonEncapsulatedUnionUnmarshall, + NdrByteCountPointerUnmarshall, + NdrXmitOrRepAsUnmarshall, NdrXmitOrRepAsUnmarshall, + /* 0x2f */ + NdrInterfacePointerUnmarshall, + /* 0x30 */ + NdrContextHandleUnmarshall, + /* 0xb1 */ + 0, 0, 0, + NdrUserMarshalUnmarshall, + 0, 0, + /* 0xb7 */ + NdrRangeUnmarshall +}; +const NDR_BUFFERSIZE NdrBufferSizer[NDR_TABLE_SIZE] = { + 0, + NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, + NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, + NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, + NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, + /* 0x10 */ + NdrBaseTypeBufferSize, + /* 0x11 */ + NdrPointerBufferSize, NdrPointerBufferSize, + NdrPointerBufferSize, NdrPointerBufferSize, + /* 0x15 */ + NdrSimpleStructBufferSize, NdrSimpleStructBufferSize, + NdrConformantStructBufferSize, NdrConformantStructBufferSize, + NdrConformantVaryingStructBufferSize, + NdrComplexStructBufferSize, + /* 0x1b */ + NdrConformantArrayBufferSize, + NdrConformantVaryingArrayBufferSize, + NdrFixedArrayBufferSize, NdrFixedArrayBufferSize, + NdrVaryingArrayBufferSize, NdrVaryingArrayBufferSize, + NdrComplexArrayBufferSize, + /* 0x22 */ + NdrConformantStringBufferSize, 0, 0, + NdrConformantStringBufferSize, + NdrNonConformantStringBufferSize, 0, 0, 0, + /* 0x2a */ + NdrEncapsulatedUnionBufferSize, + NdrNonEncapsulatedUnionBufferSize, + NdrByteCountPointerBufferSize, + NdrXmitOrRepAsBufferSize, NdrXmitOrRepAsBufferSize, + /* 0x2f */ + NdrInterfacePointerBufferSize, + /* 0x30 */ + NdrContextHandleBufferSize, + /* 0xb1 */ + 0, 0, 0, + NdrUserMarshalBufferSize, + 0, 0, + /* 0xb7 */ + NdrRangeBufferSize +}; +const NDR_MEMORYSIZE NdrMemorySizer[NDR_TABLE_SIZE] = { + 0, + NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, + NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, + NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, + NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, + /* 0x10 */ + NdrBaseTypeMemorySize, + /* 0x11 */ + NdrPointerMemorySize, NdrPointerMemorySize, + NdrPointerMemorySize, NdrPointerMemorySize, + /* 0x15 */ + NdrSimpleStructMemorySize, NdrSimpleStructMemorySize, + NdrConformantStructMemorySize, NdrConformantStructMemorySize, + NdrConformantVaryingStructMemorySize, + NdrComplexStructMemorySize, + /* 0x1b */ + NdrConformantArrayMemorySize, + NdrConformantVaryingArrayMemorySize, + NdrFixedArrayMemorySize, NdrFixedArrayMemorySize, + NdrVaryingArrayMemorySize, NdrVaryingArrayMemorySize, + NdrComplexArrayMemorySize, + /* 0x22 */ + NdrConformantStringMemorySize, 0, 0, + NdrConformantStringMemorySize, + NdrNonConformantStringMemorySize, 0, 0, 0, + /* 0x2a */ + NdrEncapsulatedUnionMemorySize, + NdrNonEncapsulatedUnionMemorySize, + NdrByteCountPointerMemorySize, + NdrXmitOrRepAsMemorySize, NdrXmitOrRepAsMemorySize, + /* 0x2f */ + NdrInterfacePointerMemorySize, + /* 0x30 */ + 0, + /* 0xb1 */ + 0, 0, 0, + NdrUserMarshalMemorySize, + 0, 0, + /* 0xb7 */ + NdrRangeMemorySize +}; +const NDR_FREE NdrFreer[NDR_TABLE_SIZE] = { + 0, + NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, + NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, + NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, + NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, + /* 0x10 */ + NdrBaseTypeFree, + /* 0x11 */ + NdrPointerFree, NdrPointerFree, + NdrPointerFree, NdrPointerFree, + /* 0x15 */ + NdrSimpleStructFree, NdrSimpleStructFree, + NdrConformantStructFree, NdrConformantStructFree, + NdrConformantVaryingStructFree, + NdrComplexStructFree, + /* 0x1b */ + NdrConformantArrayFree, + NdrConformantVaryingArrayFree, + NdrFixedArrayFree, NdrFixedArrayFree, + NdrVaryingArrayFree, NdrVaryingArrayFree, + NdrComplexArrayFree, + /* 0x22 */ + 0, 0, 0, + 0, 0, 0, 0, 0, + /* 0x2a */ + NdrEncapsulatedUnionFree, + NdrNonEncapsulatedUnionFree, + 0, + NdrXmitOrRepAsFree, NdrXmitOrRepAsFree, + /* 0x2f */ + NdrInterfacePointerFree, + /* 0x30 */ + 0, + /* 0xb1 */ + 0, 0, 0, + NdrUserMarshalFree, + 0, 0, + /* 0xb7 */ + NdrRangeFree +}; + +typedef struct _NDR_MEMORY_LIST +{ + ULONG magic; + ULONG size; + ULONG reserved; + struct _NDR_MEMORY_LIST *next; +} NDR_MEMORY_LIST; + +#define MEML_MAGIC ('M' << 24 | 'E' << 16 | 'M' << 8 | 'L') + +/*********************************************************************** + * NdrAllocate [RPCRT4.@] + * + * Allocates a block of memory using pStubMsg->pfnAllocate. + * + * PARAMS + * pStubMsg [I/O] MIDL_STUB_MESSAGE structure. + * len [I] Size of memory block to allocate. + * + * RETURNS + * The memory block of size len that was allocated. + * + * NOTES + * The memory block is always 8-byte aligned. + * If the function is unable to allocate memory an ERROR_OUTOFMEMORY + * exception is raised. + */ +void * WINAPI NdrAllocate(MIDL_STUB_MESSAGE *pStubMsg, size_t len) +{ + size_t aligned_len; + size_t adjusted_len; + void *p; + NDR_MEMORY_LIST *mem_list; + + aligned_len = ALIGNED_LENGTH(len, 8); + adjusted_len = aligned_len + sizeof(NDR_MEMORY_LIST); + /* check for overflow */ + if (adjusted_len < len) + { + ERR("overflow of adjusted_len %d, len %d\n", adjusted_len, len); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + + p = pStubMsg->pfnAllocate(adjusted_len); + if (!p) RpcRaiseException(ERROR_OUTOFMEMORY); + + mem_list = (NDR_MEMORY_LIST *)((char *)p + aligned_len); + mem_list->magic = MEML_MAGIC; + mem_list->size = aligned_len; + mem_list->reserved = 0; + mem_list->next = pStubMsg->pMemoryList; + pStubMsg->pMemoryList = mem_list; + + TRACE("-- %p\n", p); + return p; +} + +static void WINAPI NdrFree(MIDL_STUB_MESSAGE *pStubMsg, unsigned char *Pointer) +{ + TRACE("(%p, %p)\n", pStubMsg, Pointer); + + pStubMsg->pfnFree(Pointer); +} + +static inline BOOL IsConformanceOrVariancePresent(PFORMAT_STRING pFormat) +{ + return (*(const ULONG *)pFormat != -1); +} + +static PFORMAT_STRING ReadConformance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat) +{ + ALIGN_POINTER(pStubMsg->Buffer, 4); + if (pStubMsg->Buffer + 4 > pStubMsg->BufferEnd) + RpcRaiseException(RPC_X_BAD_STUB_DATA); + pStubMsg->MaxCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer); + pStubMsg->Buffer += 4; + TRACE("unmarshalled conformance is %ld\n", pStubMsg->MaxCount); + if (pStubMsg->fHasNewCorrDesc) + return pFormat+6; + else + return pFormat+4; +} + +static inline PFORMAT_STRING ReadVariance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat, ULONG MaxValue) +{ + if (pFormat && !IsConformanceOrVariancePresent(pFormat)) + { + pStubMsg->Offset = 0; + pStubMsg->ActualCount = pStubMsg->MaxCount; + goto done; + } + + ALIGN_POINTER(pStubMsg->Buffer, 4); + if (pStubMsg->Buffer + 8 > pStubMsg->BufferEnd) + RpcRaiseException(RPC_X_BAD_STUB_DATA); + pStubMsg->Offset = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer); + pStubMsg->Buffer += 4; + TRACE("offset is %d\n", pStubMsg->Offset); + pStubMsg->ActualCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer); + pStubMsg->Buffer += 4; + TRACE("variance is %d\n", pStubMsg->ActualCount); + + if ((pStubMsg->ActualCount > MaxValue) || + (pStubMsg->ActualCount + pStubMsg->Offset > MaxValue)) + { + ERR("invalid array bound(s): ActualCount = %d, Offset = %d, MaxValue = %d\n", + pStubMsg->ActualCount, pStubMsg->Offset, MaxValue); + RpcRaiseException(RPC_S_INVALID_BOUND); + return NULL; + } + +done: + if (pStubMsg->fHasNewCorrDesc) + return pFormat+6; + else + return pFormat+4; +} + +/* writes the conformance value to the buffer */ +static inline void WriteConformance(MIDL_STUB_MESSAGE *pStubMsg) +{ + ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4); + if (pStubMsg->Buffer + 4 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) + RpcRaiseException(RPC_X_BAD_STUB_DATA); + NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->MaxCount); + pStubMsg->Buffer += 4; +} + +/* writes the variance values to the buffer */ +static inline void WriteVariance(MIDL_STUB_MESSAGE *pStubMsg) +{ + ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4); + if (pStubMsg->Buffer + 8 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) + RpcRaiseException(RPC_X_BAD_STUB_DATA); + NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->Offset); + pStubMsg->Buffer += 4; + NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->ActualCount); + pStubMsg->Buffer += 4; +} + +/* requests buffer space for the conformance value */ +static inline void SizeConformance(MIDL_STUB_MESSAGE *pStubMsg) +{ + ALIGN_LENGTH(pStubMsg->BufferLength, 4); + if (pStubMsg->BufferLength + 4 < pStubMsg->BufferLength) + RpcRaiseException(RPC_X_BAD_STUB_DATA); + pStubMsg->BufferLength += 4; +} + +/* requests buffer space for the variance values */ +static inline void SizeVariance(MIDL_STUB_MESSAGE *pStubMsg) +{ + ALIGN_LENGTH(pStubMsg->BufferLength, 4); + if (pStubMsg->BufferLength + 8 < pStubMsg->BufferLength) + RpcRaiseException(RPC_X_BAD_STUB_DATA); + pStubMsg->BufferLength += 8; +} + +PFORMAT_STRING ComputeConformanceOrVariance( + MIDL_STUB_MESSAGE *pStubMsg, unsigned char *pMemory, + PFORMAT_STRING pFormat, ULONG_PTR def, ULONG_PTR *pCount) +{ + BYTE dtype = pFormat[0] & 0xf; + short ofs = *(const short *)&pFormat[2]; + LPVOID ptr = NULL; + DWORD data = 0; + + if (!IsConformanceOrVariancePresent(pFormat)) { + /* null descriptor */ + *pCount = def; + goto finish_conf; + } + + switch (pFormat[0] & 0xf0) { + case RPC_FC_NORMAL_CONFORMANCE: + TRACE("normal conformance, ofs=%d\n", ofs); + ptr = pMemory; + break; + case RPC_FC_POINTER_CONFORMANCE: + TRACE("pointer conformance, ofs=%d\n", ofs); + ptr = pStubMsg->Memory; + break; + case RPC_FC_TOP_LEVEL_CONFORMANCE: + TRACE("toplevel conformance, ofs=%d\n", ofs); + if (pStubMsg->StackTop) { + ptr = pStubMsg->StackTop; + } + else { + /* -Os mode, *pCount is already set */ + goto finish_conf; + } + break; + case RPC_FC_CONSTANT_CONFORMANCE: + data = ofs | ((DWORD)pFormat[1] << 16); + TRACE("constant conformance, val=%d\n", data); + *pCount = data; + goto finish_conf; + case RPC_FC_TOP_LEVEL_MULTID_CONFORMANCE: + FIXME("toplevel multidimensional conformance, ofs=%d\n", ofs); + if (pStubMsg->StackTop) { + ptr = pStubMsg->StackTop; + } + else { + /* ? */ + goto done_conf_grab; + } + break; + default: + FIXME("unknown conformance type %x\n", pFormat[0] & 0xf0); + } + + switch (pFormat[1]) { + case RPC_FC_DEREFERENCE: + ptr = *(LPVOID*)((char *)ptr + ofs); + break; + case RPC_FC_CALLBACK: + { + unsigned char *old_stack_top = pStubMsg->StackTop; + pStubMsg->StackTop = ptr; + + /* ofs is index into StubDesc->apfnExprEval */ + TRACE("callback conformance into apfnExprEval[%d]\n", ofs); + pStubMsg->StubDesc->apfnExprEval[ofs](pStubMsg); + + pStubMsg->StackTop = old_stack_top; + + /* the callback function always stores the computed value in MaxCount */ + *pCount = pStubMsg->MaxCount; + goto finish_conf; + } + default: + ptr = (char *)ptr + ofs; + break; + } + + switch (dtype) { + case RPC_FC_LONG: + case RPC_FC_ULONG: + data = *(DWORD*)ptr; + break; + case RPC_FC_SHORT: + data = *(SHORT*)ptr; + break; + case RPC_FC_USHORT: + data = *(USHORT*)ptr; + break; + case RPC_FC_CHAR: + case RPC_FC_SMALL: + data = *(CHAR*)ptr; + break; + case RPC_FC_BYTE: + case RPC_FC_USMALL: + data = *(UCHAR*)ptr; + break; + default: + FIXME("unknown conformance data type %x\n", dtype); + goto done_conf_grab; + } + TRACE("dereferenced data type %x at %p, got %d\n", dtype, ptr, data); + +done_conf_grab: + switch (pFormat[1]) { + case RPC_FC_DEREFERENCE: /* already handled */ + case 0: /* no op */ + *pCount = data; + break; + case RPC_FC_ADD_1: + *pCount = data + 1; + break; + case RPC_FC_SUB_1: + *pCount = data - 1; + break; + case RPC_FC_MULT_2: + *pCount = data * 2; + break; + case RPC_FC_DIV_2: + *pCount = data / 2; + break; + default: + FIXME("unknown conformance op %d\n", pFormat[1]); + goto finish_conf; + } + +finish_conf: + TRACE("resulting conformance is %ld\n", *pCount); + if (pStubMsg->fHasNewCorrDesc) + return pFormat+6; + else + return pFormat+4; +} + +/* multiply two numbers together, raising an RPC_S_INVALID_BOUND exception if + * the result overflows 32-bits */ +static inline ULONG safe_multiply(ULONG a, ULONG b) +{ + ULONGLONG ret = (ULONGLONG)a * b; + if (ret > 0xffffffff) + { + RpcRaiseException(RPC_S_INVALID_BOUND); + return 0; + } + return ret; +} + +static inline void safe_buffer_increment(MIDL_STUB_MESSAGE *pStubMsg, ULONG size) +{ + if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */ + (pStubMsg->Buffer + size > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)) + RpcRaiseException(RPC_X_BAD_STUB_DATA); + pStubMsg->Buffer += size; +} + +static inline void safe_buffer_length_increment(MIDL_STUB_MESSAGE *pStubMsg, ULONG size) +{ + if (pStubMsg->BufferLength + size < pStubMsg->BufferLength) /* integer overflow of pStubMsg->BufferSize */ + { + ERR("buffer length overflow - BufferLength = %u, size = %u\n", + pStubMsg->BufferLength, size); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + pStubMsg->BufferLength += size; +} + +/* copies data from the buffer, checking that there is enough data in the buffer + * to do so */ +static inline void safe_copy_from_buffer(MIDL_STUB_MESSAGE *pStubMsg, void *p, ULONG size) +{ + if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */ + (pStubMsg->Buffer + size > pStubMsg->BufferEnd)) + { + ERR("buffer overflow - Buffer = %p, BufferEnd = %p, size = %u\n", + pStubMsg->Buffer, pStubMsg->BufferEnd, size); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + if (p == pStubMsg->Buffer) + ERR("pointer is the same as the buffer\n"); + memcpy(p, pStubMsg->Buffer, size); + pStubMsg->Buffer += size; +} + +/* copies data to the buffer, checking that there is enough space to do so */ +static inline void safe_copy_to_buffer(MIDL_STUB_MESSAGE *pStubMsg, const void *p, ULONG size) +{ + if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */ + (pStubMsg->Buffer + size > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)) + { + ERR("buffer overflow - Buffer = %p, BufferEnd = %p, size = %u\n", + pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength, + size); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + memcpy(pStubMsg->Buffer, p, size); + pStubMsg->Buffer += size; +} + +/* + * NdrConformantString: + * + * What MS calls a ConformantString is, in DCE terminology, + * a Varying-Conformant String. + * [ + * maxlen: DWORD (max # of CHARTYPE characters, inclusive of '\0') + * offset: DWORD (actual string data begins at (offset) CHARTYPE's + * into unmarshalled string) + * length: DWORD (# of CHARTYPE characters, inclusive of '\0') + * [ + * data: CHARTYPE[maxlen] + * ] + * ], where CHARTYPE is the appropriate character type (specified externally) + * + */ + +/*********************************************************************** + * NdrConformantStringMarshall [RPCRT4.@] + */ +unsigned char *WINAPI NdrConformantStringMarshall(MIDL_STUB_MESSAGE *pStubMsg, + unsigned char *pszMessage, PFORMAT_STRING pFormat) +{ + ULONG esize, size; + + TRACE("(pStubMsg == ^%p, pszMessage == ^%p, pFormat == ^%p)\n", pStubMsg, pszMessage, pFormat); + + if (*pFormat == RPC_FC_C_CSTRING) { + TRACE("string=%s\n", debugstr_a((char*)pszMessage)); + pStubMsg->ActualCount = strlen((char*)pszMessage)+1; + esize = 1; + } + else if (*pFormat == RPC_FC_C_WSTRING) { + TRACE("string=%s\n", debugstr_w((LPWSTR)pszMessage)); + pStubMsg->ActualCount = strlenW((LPWSTR)pszMessage)+1; + esize = 2; + } + else { + ERR("Unhandled string type: %#x\n", *pFormat); + /* FIXME: raise an exception. */ + return NULL; + } + + if (pFormat[1] == RPC_FC_STRING_SIZED) + pFormat = ComputeConformance(pStubMsg, pszMessage, pFormat + 2, 0); + else + pStubMsg->MaxCount = pStubMsg->ActualCount; + pStubMsg->Offset = 0; + WriteConformance(pStubMsg); + WriteVariance(pStubMsg); + + size = safe_multiply(esize, pStubMsg->ActualCount); + safe_copy_to_buffer(pStubMsg, pszMessage, size); /* the string itself */ + + /* success */ + return NULL; /* is this always right? */ +} + +/*********************************************************************** + * NdrConformantStringBufferSize [RPCRT4.@] + */ +void WINAPI NdrConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char* pMemory, PFORMAT_STRING pFormat) +{ + ULONG esize; + + TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat); + + SizeConformance(pStubMsg); + SizeVariance(pStubMsg); + + if (*pFormat == RPC_FC_C_CSTRING) { + TRACE("string=%s\n", debugstr_a((char*)pMemory)); + pStubMsg->ActualCount = strlen((char*)pMemory)+1; + esize = 1; + } + else if (*pFormat == RPC_FC_C_WSTRING) { + TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory)); + pStubMsg->ActualCount = strlenW((LPWSTR)pMemory)+1; + esize = 2; + } + else { + ERR("Unhandled string type: %#x\n", *pFormat); + /* FIXME: raise an exception */ + return; + } + + if (pFormat[1] == RPC_FC_STRING_SIZED) + pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 2, 0); + else + pStubMsg->MaxCount = pStubMsg->ActualCount; + + safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount)); +} + +/************************************************************************ + * NdrConformantStringMemorySize [RPCRT4.@] + */ +ULONG WINAPI NdrConformantStringMemorySize( PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat ) +{ + ULONG bufsize, memsize, esize, i; + + TRACE("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat); + + ReadConformance(pStubMsg, NULL); + ReadVariance(pStubMsg, NULL, pStubMsg->MaxCount); + + if (pFormat[1] != RPC_FC_STRING_SIZED && (pStubMsg->MaxCount != pStubMsg->ActualCount)) + { + ERR("buffer size %d must equal memory size %ld for non-sized conformant strings\n", + pStubMsg->ActualCount, pStubMsg->MaxCount); + RpcRaiseException(RPC_S_INVALID_BOUND); + } + if (pStubMsg->Offset) + { + ERR("conformant strings can't have Offset (%d)\n", pStubMsg->Offset); + RpcRaiseException(RPC_S_INVALID_BOUND); + } + + if (*pFormat == RPC_FC_C_CSTRING) esize = 1; + else if (*pFormat == RPC_FC_C_WSTRING) esize = 2; + else { + ERR("Unhandled string type: %#x\n", *pFormat); + /* FIXME: raise an exception */ + esize = 0; + } + + memsize = safe_multiply(esize, pStubMsg->MaxCount); + bufsize = safe_multiply(esize, pStubMsg->ActualCount); + + /* strings must always have null terminating bytes */ + if (bufsize < esize) + { + ERR("invalid string length of %d\n", pStubMsg->ActualCount); + RpcRaiseException(RPC_S_INVALID_BOUND); + } + + /* verify the buffer is safe to access */ + if ((pStubMsg->Buffer + bufsize < pStubMsg->Buffer) || + (pStubMsg->Buffer + bufsize > pStubMsg->BufferEnd)) + { + ERR("bufsize 0x%x exceeded buffer end %p of buffer %p\n", bufsize, + pStubMsg->BufferEnd, pStubMsg->Buffer); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + + for (i = bufsize - esize; i < bufsize; i++) + if (pStubMsg->Buffer[i] != 0) + { + ERR("string not null-terminated at byte position %d, data is 0x%x\n", + i, pStubMsg->Buffer[i]); + RpcRaiseException(RPC_S_INVALID_BOUND); + } + + safe_buffer_increment(pStubMsg, bufsize); + pStubMsg->MemorySize += memsize; + + return pStubMsg->MemorySize; +} + +/************************************************************************ + * NdrConformantStringUnmarshall [RPCRT4.@] + */ +unsigned char *WINAPI NdrConformantStringUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, + unsigned char** ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc ) +{ + ULONG bufsize, memsize, esize, i; + + TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n", + pStubMsg, *ppMemory, pFormat, fMustAlloc); + + assert(pFormat && ppMemory && pStubMsg); + + ReadConformance(pStubMsg, NULL); + ReadVariance(pStubMsg, NULL, pStubMsg->MaxCount); + + if (pFormat[1] != RPC_FC_STRING_SIZED && (pStubMsg->MaxCount != pStubMsg->ActualCount)) + { + ERR("buffer size %d must equal memory size %ld for non-sized conformant strings\n", + pStubMsg->ActualCount, pStubMsg->MaxCount); + RpcRaiseException(RPC_S_INVALID_BOUND); + return NULL; + } + if (pStubMsg->Offset) + { + ERR("conformant strings can't have Offset (%d)\n", pStubMsg->Offset); + RpcRaiseException(RPC_S_INVALID_BOUND); + return NULL; + } + + if (*pFormat == RPC_FC_C_CSTRING) esize = 1; + else if (*pFormat == RPC_FC_C_WSTRING) esize = 2; + else { + ERR("Unhandled string type: %#x\n", *pFormat); + /* FIXME: raise an exception */ + esize = 0; + } + + memsize = safe_multiply(esize, pStubMsg->MaxCount); + bufsize = safe_multiply(esize, pStubMsg->ActualCount); + + /* strings must always have null terminating bytes */ + if (bufsize < esize) + { + ERR("invalid string length of %d\n", pStubMsg->ActualCount); + RpcRaiseException(RPC_S_INVALID_BOUND); + return NULL; + } + + /* verify the buffer is safe to access */ + if ((pStubMsg->Buffer + bufsize < pStubMsg->Buffer) || + (pStubMsg->Buffer + bufsize > pStubMsg->BufferEnd)) + { + ERR("bufsize 0x%x exceeded buffer end %p of buffer %p\n", bufsize, + pStubMsg->BufferEnd, pStubMsg->Buffer); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + return NULL; + } + + for (i = bufsize - esize; i < bufsize; i++) + if (pStubMsg->Buffer[i] != 0) + { + ERR("string not null-terminated at byte position %d, data is 0x%x\n", + i, pStubMsg->Buffer[i]); + RpcRaiseException(RPC_S_INVALID_BOUND); + return NULL; + } + + if (fMustAlloc) + *ppMemory = NdrAllocate(pStubMsg, memsize); + else + { + if (!pStubMsg->IsClient && !*ppMemory && (pStubMsg->MaxCount == pStubMsg->ActualCount)) + /* if the data in the RPC buffer is big enough, we just point straight + * into it */ + *ppMemory = pStubMsg->Buffer; + else if (!*ppMemory) + *ppMemory = NdrAllocate(pStubMsg, memsize); + } + + if (*ppMemory == pStubMsg->Buffer) + safe_buffer_increment(pStubMsg, bufsize); + else + safe_copy_from_buffer(pStubMsg, *ppMemory, bufsize); + + if (*pFormat == RPC_FC_C_CSTRING) { + TRACE("string=%s\n", debugstr_a((char*)*ppMemory)); + } + else if (*pFormat == RPC_FC_C_WSTRING) { + TRACE("string=%s\n", debugstr_w((LPWSTR)*ppMemory)); + } + + return NULL; /* FIXME: is this always right? */ +} + +/*********************************************************************** + * NdrNonConformantStringMarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrNonConformantStringMarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + ULONG esize, size, maxsize; + + TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat); + + maxsize = *(USHORT *)&pFormat[2]; + + if (*pFormat == RPC_FC_CSTRING) + { + ULONG i; + const char *str = (const char *)pMemory; + for (i = 0; i < maxsize && *str; i++, str++) + ; + TRACE("string=%s\n", debugstr_an(str, i)); + pStubMsg->ActualCount = i + 1; + esize = 1; + } + else if (*pFormat == RPC_FC_WSTRING) + { + ULONG i; + const WCHAR *str = (const WCHAR *)pMemory; + for (i = 0; i < maxsize && *str; i++, str++) + ; + TRACE("string=%s\n", debugstr_wn(str, i)); + pStubMsg->ActualCount = i + 1; + esize = 2; + } + else + { + ERR("Unhandled string type: %#x\n", *pFormat); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + + pStubMsg->Offset = 0; + WriteVariance(pStubMsg); + + size = safe_multiply(esize, pStubMsg->ActualCount); + safe_copy_to_buffer(pStubMsg, pMemory, size); /* the string itself */ + + return NULL; +} + +/*********************************************************************** + * NdrNonConformantStringUnmarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrNonConformantStringUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char **ppMemory, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) +{ + ULONG bufsize, memsize, esize, i, maxsize; + + TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n", + pStubMsg, *ppMemory, pFormat, fMustAlloc); + + maxsize = *(USHORT *)&pFormat[2]; + + ReadVariance(pStubMsg, NULL, maxsize); + if (pStubMsg->Offset) + { + ERR("non-conformant strings can't have Offset (%d)\n", pStubMsg->Offset); + RpcRaiseException(RPC_S_INVALID_BOUND); + } + + if (*pFormat == RPC_FC_CSTRING) esize = 1; + else if (*pFormat == RPC_FC_WSTRING) esize = 2; + else + { + ERR("Unhandled string type: %#x\n", *pFormat); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + + memsize = esize * maxsize; + bufsize = safe_multiply(esize, pStubMsg->ActualCount); + + if (bufsize < esize) + { + ERR("invalid string length of %d\n", pStubMsg->ActualCount); + RpcRaiseException(RPC_S_INVALID_BOUND); + return NULL; + } + + /* verify the buffer is safe to access */ + if ((pStubMsg->Buffer + bufsize < pStubMsg->Buffer) || + (pStubMsg->Buffer + bufsize > pStubMsg->BufferEnd)) + { + ERR("bufsize 0x%x exceeded buffer end %p of buffer %p\n", bufsize, + pStubMsg->BufferEnd, pStubMsg->Buffer); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + return NULL; + } + + /* strings must always have null terminating bytes */ + for (i = bufsize - esize; i < bufsize; i++) + if (pStubMsg->Buffer[i] != 0) + { + ERR("string not null-terminated at byte position %d, data is 0x%x\n", + i, pStubMsg->Buffer[i]); + RpcRaiseException(RPC_S_INVALID_BOUND); + } + + if (fMustAlloc || !*ppMemory) + *ppMemory = NdrAllocate(pStubMsg, memsize); + + safe_copy_from_buffer(pStubMsg, *ppMemory, bufsize); + + if (*pFormat == RPC_FC_CSTRING) { + TRACE("string=%s\n", debugstr_an((char*)*ppMemory, pStubMsg->ActualCount)); + } + else if (*pFormat == RPC_FC_WSTRING) { + TRACE("string=%s\n", debugstr_wn((LPWSTR)*ppMemory, pStubMsg->ActualCount)); + } + + return NULL; +} + +/*********************************************************************** + * NdrNonConformantStringBufferSize [RPCRT4.@] + */ +void WINAPI NdrNonConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + ULONG esize, maxsize; + + TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat); + + maxsize = *(USHORT *)&pFormat[2]; + + SizeVariance(pStubMsg); + + if (*pFormat == RPC_FC_CSTRING) + { + ULONG i; + const char *str = (const char *)pMemory; + for (i = 0; i < maxsize && *str; i++, str++) + ; + TRACE("string=%s\n", debugstr_an(str, i)); + pStubMsg->ActualCount = i + 1; + esize = 1; + } + else if (*pFormat == RPC_FC_WSTRING) + { + ULONG i; + const WCHAR *str = (const WCHAR *)pMemory; + for (i = 0; i < maxsize && *str; i++, str++) + ; + TRACE("string=%s\n", debugstr_wn(str, i)); + pStubMsg->ActualCount = i + 1; + esize = 2; + } + else + { + ERR("Unhandled string type: %#x\n", *pFormat); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + + safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount)); +} + +/*********************************************************************** + * NdrNonConformantStringMemorySize [RPCRT4.@] + */ +ULONG WINAPI NdrNonConformantStringMemorySize(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + ULONG bufsize, memsize, esize, i, maxsize; + + TRACE("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat); + + maxsize = *(USHORT *)&pFormat[2]; + + ReadVariance(pStubMsg, NULL, maxsize); + + if (pStubMsg->Offset) + { + ERR("non-conformant strings can't have Offset (%d)\n", pStubMsg->Offset); + RpcRaiseException(RPC_S_INVALID_BOUND); + } + + if (*pFormat == RPC_FC_CSTRING) esize = 1; + else if (*pFormat == RPC_FC_WSTRING) esize = 2; + else + { + ERR("Unhandled string type: %#x\n", *pFormat); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + + memsize = esize * maxsize; + bufsize = safe_multiply(esize, pStubMsg->ActualCount); + + /* strings must always have null terminating bytes */ + if (bufsize < esize) + { + ERR("invalid string length of %d\n", pStubMsg->ActualCount); + RpcRaiseException(RPC_S_INVALID_BOUND); + } + + /* verify the buffer is safe to access */ + if ((pStubMsg->Buffer + bufsize < pStubMsg->Buffer) || + (pStubMsg->Buffer + bufsize > pStubMsg->BufferEnd)) + { + ERR("bufsize 0x%x exceeded buffer end %p of buffer %p\n", bufsize, + pStubMsg->BufferEnd, pStubMsg->Buffer); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + + for (i = bufsize - esize; i < bufsize; i++) + if (pStubMsg->Buffer[i] != 0) + { + ERR("string not null-terminated at byte position %d, data is 0x%x\n", + i, pStubMsg->Buffer[i]); + RpcRaiseException(RPC_S_INVALID_BOUND); + } + + safe_buffer_increment(pStubMsg, bufsize); + pStubMsg->MemorySize += memsize; + + return pStubMsg->MemorySize; +} + +static inline void dump_pointer_attr(unsigned char attr) +{ + if (attr & RPC_FC_P_ALLOCALLNODES) + TRACE(" RPC_FC_P_ALLOCALLNODES"); + if (attr & RPC_FC_P_DONTFREE) + TRACE(" RPC_FC_P_DONTFREE"); + if (attr & RPC_FC_P_ONSTACK) + TRACE(" RPC_FC_P_ONSTACK"); + if (attr & RPC_FC_P_SIMPLEPOINTER) + TRACE(" RPC_FC_P_SIMPLEPOINTER"); + if (attr & RPC_FC_P_DEREF) + TRACE(" RPC_FC_P_DEREF"); + TRACE("\n"); +} + +/*********************************************************************** + * PointerMarshall [internal] + */ +static void PointerMarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *Buffer, + unsigned char *Pointer, + PFORMAT_STRING pFormat) +{ + unsigned type = pFormat[0], attr = pFormat[1]; + PFORMAT_STRING desc; + NDR_MARSHALL m; + ULONG pointer_id; + int pointer_needs_marshaling; + + TRACE("(%p,%p,%p,%p)\n", pStubMsg, Buffer, Pointer, pFormat); + TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr); + pFormat += 2; + if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat; + else desc = pFormat + *(const SHORT*)pFormat; + + switch (type) { + case RPC_FC_RP: /* ref pointer (always non-null) */ + if (!Pointer) + { + ERR("NULL ref pointer is not allowed\n"); + RpcRaiseException(RPC_X_NULL_REF_POINTER); + } + pointer_needs_marshaling = 1; + break; + case RPC_FC_UP: /* unique pointer */ + case RPC_FC_OP: /* object pointer - same as unique here */ + if (Pointer) + pointer_needs_marshaling = 1; + else + pointer_needs_marshaling = 0; + pointer_id = (ULONG)Pointer; + TRACE("writing 0x%08x to buffer\n", pointer_id); + NDR_LOCAL_UINT32_WRITE(Buffer, pointer_id); + break; + case RPC_FC_FP: + pointer_needs_marshaling = !NdrFullPointerQueryPointer( + pStubMsg->FullPtrXlatTables, Pointer, 1, &pointer_id); + TRACE("writing 0x%08x to buffer\n", pointer_id); + NDR_LOCAL_UINT32_WRITE(Buffer, pointer_id); + break; + default: + FIXME("unhandled ptr type=%02x\n", type); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + return; + } + + TRACE("calling marshaller for type 0x%x\n", (int)*desc); + + if (pointer_needs_marshaling) { + if (attr & RPC_FC_P_DEREF) { + Pointer = *(unsigned char**)Pointer; + TRACE("deref => %p\n", Pointer); + } + m = NdrMarshaller[*desc & NDR_TABLE_MASK]; + if (m) m(pStubMsg, Pointer, desc); + else FIXME("no marshaller for data type=%02x\n", *desc); + } + + STD_OVERFLOW_CHECK(pStubMsg); +} + +/*********************************************************************** + * PointerUnmarshall [internal] + */ +static void PointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *Buffer, + unsigned char **pPointer, + unsigned char *pSrcPointer, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) +{ + unsigned type = pFormat[0], attr = pFormat[1]; + PFORMAT_STRING desc; + NDR_UNMARSHALL m; + DWORD pointer_id = 0; + int pointer_needs_unmarshaling; + + TRACE("(%p,%p,%p,%p,%p,%d)\n", pStubMsg, Buffer, pPointer, pSrcPointer, pFormat, fMustAlloc); + TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr); + pFormat += 2; + if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat; + else desc = pFormat + *(const SHORT*)pFormat; + + switch (type) { + case RPC_FC_RP: /* ref pointer (always non-null) */ + pointer_needs_unmarshaling = 1; + break; + case RPC_FC_UP: /* unique pointer */ + pointer_id = NDR_LOCAL_UINT32_READ(Buffer); + TRACE("pointer_id is 0x%08x\n", pointer_id); + if (pointer_id) + pointer_needs_unmarshaling = 1; + else { + *pPointer = NULL; + pointer_needs_unmarshaling = 0; + } + break; + case RPC_FC_OP: /* object pointer - we must free data before overwriting it */ + pointer_id = NDR_LOCAL_UINT32_READ(Buffer); + TRACE("pointer_id is 0x%08x\n", pointer_id); + if (!fMustAlloc && pSrcPointer) + { + FIXME("free object pointer %p\n", pSrcPointer); + fMustAlloc = TRUE; + } + if (pointer_id) + pointer_needs_unmarshaling = 1; + else + pointer_needs_unmarshaling = 0; + break; + case RPC_FC_FP: + pointer_id = NDR_LOCAL_UINT32_READ(Buffer); + TRACE("pointer_id is 0x%08x\n", pointer_id); + pointer_needs_unmarshaling = !NdrFullPointerQueryRefId( + pStubMsg->FullPtrXlatTables, pointer_id, 1, (void **)pPointer); + break; + default: + FIXME("unhandled ptr type=%02x\n", type); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + return; + } + + if (pointer_needs_unmarshaling) { + unsigned char *base_ptr_val = *pPointer; + unsigned char **current_ptr = pPointer; + if (pStubMsg->IsClient) { + TRACE("client\n"); + /* if we aren't forcing allocation of memory then try to use the existing + * (source) pointer to unmarshall the data into so that [in,out] + * parameters behave correctly. it doesn't matter if the parameter is + * [out] only since in that case the pointer will be NULL. we force + * allocation when the source pointer is NULL here instead of in the type + * unmarshalling routine for the benefit of the deref code below */ + if (!fMustAlloc) { + if (pSrcPointer) { + TRACE("setting *pPointer to %p\n", pSrcPointer); + *pPointer = base_ptr_val = pSrcPointer; + } else + fMustAlloc = TRUE; + } + } else { + TRACE("server\n"); + /* the memory in a stub is never initialised, so we have to work out here + * whether we have to initialise it so we can use the optimisation of + * setting the pointer to the buffer, if possible, or set fMustAlloc to + * TRUE. */ + if (attr & RPC_FC_P_DEREF) { + fMustAlloc = TRUE; + } else { + base_ptr_val = NULL; + *current_ptr = NULL; + } + } + + if (attr & RPC_FC_P_ALLOCALLNODES) + FIXME("RPC_FC_P_ALLOCALLNODES not implemented\n"); + + if (attr & RPC_FC_P_DEREF) { + if (fMustAlloc) { + base_ptr_val = NdrAllocate(pStubMsg, sizeof(void *)); + *pPointer = base_ptr_val; + current_ptr = (unsigned char **)base_ptr_val; + } else + current_ptr = *(unsigned char***)current_ptr; + TRACE("deref => %p\n", current_ptr); + if (!fMustAlloc && !*current_ptr) fMustAlloc = TRUE; + } + m = NdrUnmarshaller[*desc & NDR_TABLE_MASK]; + if (m) m(pStubMsg, current_ptr, desc, fMustAlloc); + else FIXME("no unmarshaller for data type=%02x\n", *desc); + + if (type == RPC_FC_FP) + NdrFullPointerInsertRefId(pStubMsg->FullPtrXlatTables, pointer_id, + base_ptr_val); + } + + TRACE("pointer=%p\n", *pPointer); +} + +/*********************************************************************** + * PointerBufferSize [internal] + */ +static void PointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *Pointer, + PFORMAT_STRING pFormat) +{ + unsigned type = pFormat[0], attr = pFormat[1]; + PFORMAT_STRING desc; + NDR_BUFFERSIZE m; + int pointer_needs_sizing; + ULONG pointer_id; + + TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat); + TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr); + pFormat += 2; + if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat; + else desc = pFormat + *(const SHORT*)pFormat; + + switch (type) { + case RPC_FC_RP: /* ref pointer (always non-null) */ + if (!Pointer) + { + ERR("NULL ref pointer is not allowed\n"); + RpcRaiseException(RPC_X_NULL_REF_POINTER); + } + break; + case RPC_FC_OP: + case RPC_FC_UP: + /* NULL pointer has no further representation */ + if (!Pointer) + return; + break; + case RPC_FC_FP: + pointer_needs_sizing = !NdrFullPointerQueryPointer( + pStubMsg->FullPtrXlatTables, Pointer, 0, &pointer_id); + if (!pointer_needs_sizing) + return; + break; + default: + FIXME("unhandled ptr type=%02x\n", type); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + return; + } + + if (attr & RPC_FC_P_DEREF) { + Pointer = *(unsigned char**)Pointer; + TRACE("deref => %p\n", Pointer); + } + + m = NdrBufferSizer[*desc & NDR_TABLE_MASK]; + if (m) m(pStubMsg, Pointer, desc); + else FIXME("no buffersizer for data type=%02x\n", *desc); +} + +/*********************************************************************** + * PointerMemorySize [internal] + */ +static unsigned long PointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *Buffer, + PFORMAT_STRING pFormat) +{ + unsigned type = pFormat[0], attr = pFormat[1]; + PFORMAT_STRING desc; + NDR_MEMORYSIZE m; + DWORD pointer_id = 0; + int pointer_needs_sizing; + + TRACE("(%p,%p,%p)\n", pStubMsg, Buffer, pFormat); + TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr); + pFormat += 2; + if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat; + else desc = pFormat + *(const SHORT*)pFormat; + + switch (type) { + case RPC_FC_RP: /* ref pointer (always non-null) */ + pointer_needs_sizing = 1; + break; + case RPC_FC_UP: /* unique pointer */ + case RPC_FC_OP: /* object pointer - we must free data before overwriting it */ + pointer_id = NDR_LOCAL_UINT32_READ(Buffer); + TRACE("pointer_id is 0x%08x\n", pointer_id); + if (pointer_id) + pointer_needs_sizing = 1; + else + pointer_needs_sizing = 0; + break; + case RPC_FC_FP: + { + void *pointer; + pointer_id = NDR_LOCAL_UINT32_READ(Buffer); + TRACE("pointer_id is 0x%08x\n", pointer_id); + pointer_needs_sizing = !NdrFullPointerQueryRefId( + pStubMsg->FullPtrXlatTables, pointer_id, 1, &pointer); + break; + } + default: + FIXME("unhandled ptr type=%02x\n", type); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + return 0; + } + + if (attr & RPC_FC_P_DEREF) { + TRACE("deref\n"); + } + + if (pointer_needs_sizing) { + m = NdrMemorySizer[*desc & NDR_TABLE_MASK]; + if (m) m(pStubMsg, desc); + else FIXME("no memorysizer for data type=%02x\n", *desc); + } + + return pStubMsg->MemorySize; +} + +/*********************************************************************** + * PointerFree [internal] + */ +static void PointerFree(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *Pointer, + PFORMAT_STRING pFormat) +{ + unsigned type = pFormat[0], attr = pFormat[1]; + PFORMAT_STRING desc; + NDR_FREE m; + unsigned char *current_pointer = Pointer; + + TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat); + TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr); + if (attr & RPC_FC_P_DONTFREE) return; + pFormat += 2; + if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat; + else desc = pFormat + *(const SHORT*)pFormat; + + if (!Pointer) return; + + if (type == RPC_FC_FP) { + int pointer_needs_freeing = NdrFullPointerFree( + pStubMsg->FullPtrXlatTables, Pointer); + if (!pointer_needs_freeing) + return; + } + + if (attr & RPC_FC_P_DEREF) { + current_pointer = *(unsigned char**)Pointer; + TRACE("deref => %p\n", current_pointer); + } + + m = NdrFreer[*desc & NDR_TABLE_MASK]; + if (m) m(pStubMsg, current_pointer, desc); + + /* this check stops us from trying to free buffer memory. we don't have to + * worry about clients, since they won't call this function. + * we don't have to check for the buffer being reallocated because + * BufferStart and BufferEnd won't be reset when allocating memory for + * sending the response. we don't have to check for the new buffer here as + * it won't be used a type memory, only for buffer memory */ + if (Pointer >= (unsigned char *)pStubMsg->BufferStart && + Pointer < (unsigned char *)pStubMsg->BufferEnd) + goto notfree; + + if (attr & RPC_FC_P_ONSTACK) { + TRACE("not freeing stack ptr %p\n", Pointer); + return; + } + TRACE("freeing %p\n", Pointer); + NdrFree(pStubMsg, Pointer); + return; +notfree: + TRACE("not freeing %p\n", Pointer); +} + +/*********************************************************************** + * EmbeddedPointerMarshall + */ +static unsigned char * EmbeddedPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + unsigned char *Mark = pStubMsg->BufferMark; + unsigned rep, count, stride; + unsigned i; + unsigned char *saved_buffer = NULL; + + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + + if (*pFormat != RPC_FC_PP) return NULL; + pFormat += 2; + + if (pStubMsg->PointerBufferMark) + { + saved_buffer = pStubMsg->Buffer; + pStubMsg->Buffer = pStubMsg->PointerBufferMark; + pStubMsg->PointerBufferMark = NULL; + } + + while (pFormat[0] != RPC_FC_END) { + switch (pFormat[0]) { + default: + FIXME("unknown repeat type %d\n", pFormat[0]); + case RPC_FC_NO_REPEAT: + rep = 1; + stride = 0; + count = 1; + pFormat += 2; + break; + case RPC_FC_FIXED_REPEAT: + rep = *(const WORD*)&pFormat[2]; + stride = *(const WORD*)&pFormat[4]; + count = *(const WORD*)&pFormat[8]; + pFormat += 10; + break; + case RPC_FC_VARIABLE_REPEAT: + rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount; + stride = *(const WORD*)&pFormat[2]; + count = *(const WORD*)&pFormat[6]; + pFormat += 8; + break; + } + for (i = 0; i < rep; i++) { + PFORMAT_STRING info = pFormat; + unsigned char *membase = pMemory + (i * stride); + unsigned char *bufbase = Mark + (i * stride); + unsigned u; + + for (u=0; uMemory; + + pStubMsg->Memory = pMemory; + PointerMarshall(pStubMsg, bufptr, *(unsigned char**)memptr, info+4); + pStubMsg->Memory = saved_memory; + } + } + pFormat += 8 * count; + } + + if (saved_buffer) + { + pStubMsg->PointerBufferMark = pStubMsg->Buffer; + pStubMsg->Buffer = saved_buffer; + } + + STD_OVERFLOW_CHECK(pStubMsg); + + return NULL; +} + +/*********************************************************************** + * EmbeddedPointerUnmarshall + */ +static unsigned char * EmbeddedPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pDstMemoryPtrs, + unsigned char *pSrcMemoryPtrs, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) +{ + unsigned char *Mark = pStubMsg->BufferMark; + unsigned rep, count, stride; + unsigned i; + unsigned char *saved_buffer = NULL; + + TRACE("(%p,%p,%p,%p,%d)\n", pStubMsg, pDstMemoryPtrs, pSrcMemoryPtrs, pFormat, fMustAlloc); + + if (*pFormat != RPC_FC_PP) return NULL; + pFormat += 2; + + if (pStubMsg->PointerBufferMark) + { + saved_buffer = pStubMsg->Buffer; + pStubMsg->Buffer = pStubMsg->PointerBufferMark; + pStubMsg->PointerBufferMark = NULL; + } + + while (pFormat[0] != RPC_FC_END) { + TRACE("pFormat[0] = 0x%x\n", pFormat[0]); + switch (pFormat[0]) { + default: + FIXME("unknown repeat type %d\n", pFormat[0]); + case RPC_FC_NO_REPEAT: + rep = 1; + stride = 0; + count = 1; + pFormat += 2; + break; + case RPC_FC_FIXED_REPEAT: + rep = *(const WORD*)&pFormat[2]; + stride = *(const WORD*)&pFormat[4]; + count = *(const WORD*)&pFormat[8]; + pFormat += 10; + break; + case RPC_FC_VARIABLE_REPEAT: + rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount; + stride = *(const WORD*)&pFormat[2]; + count = *(const WORD*)&pFormat[6]; + pFormat += 8; + break; + } + for (i = 0; i < rep; i++) { + PFORMAT_STRING info = pFormat; + unsigned char *memdstbase = pDstMemoryPtrs + (i * stride); + unsigned char *memsrcbase = pSrcMemoryPtrs + (i * stride); + unsigned char *bufbase = Mark + (i * stride); + unsigned u; + + for (u=0; uPointerBufferMark = pStubMsg->Buffer; + pStubMsg->Buffer = saved_buffer; + } + + return NULL; +} + +/*********************************************************************** + * EmbeddedPointerBufferSize + */ +static void EmbeddedPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + unsigned rep, count, stride; + unsigned i; + ULONG saved_buffer_length = 0; + + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + + if (pStubMsg->IgnoreEmbeddedPointers) return; + + if (*pFormat != RPC_FC_PP) return; + pFormat += 2; + + if (pStubMsg->PointerLength) + { + saved_buffer_length = pStubMsg->BufferLength; + pStubMsg->BufferLength = pStubMsg->PointerLength; + pStubMsg->PointerLength = 0; + } + + while (pFormat[0] != RPC_FC_END) { + switch (pFormat[0]) { + default: + FIXME("unknown repeat type %d\n", pFormat[0]); + case RPC_FC_NO_REPEAT: + rep = 1; + stride = 0; + count = 1; + pFormat += 2; + break; + case RPC_FC_FIXED_REPEAT: + rep = *(const WORD*)&pFormat[2]; + stride = *(const WORD*)&pFormat[4]; + count = *(const WORD*)&pFormat[8]; + pFormat += 10; + break; + case RPC_FC_VARIABLE_REPEAT: + rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount; + stride = *(const WORD*)&pFormat[2]; + count = *(const WORD*)&pFormat[6]; + pFormat += 8; + break; + } + for (i = 0; i < rep; i++) { + PFORMAT_STRING info = pFormat; + unsigned char *membase = pMemory + (i * stride); + unsigned u; + + for (u=0; uMemory; + + pStubMsg->Memory = pMemory; + PointerBufferSize(pStubMsg, *(unsigned char**)memptr, info+4); + pStubMsg->Memory = saved_memory; + } + } + pFormat += 8 * count; + } + + if (saved_buffer_length) + { + pStubMsg->PointerLength = pStubMsg->BufferLength; + pStubMsg->BufferLength = saved_buffer_length; + } +} + +/*********************************************************************** + * EmbeddedPointerMemorySize [internal] + */ +static unsigned long EmbeddedPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + unsigned char *Mark = pStubMsg->BufferMark; + unsigned rep, count, stride; + unsigned i; + unsigned char *saved_buffer = NULL; + + TRACE("(%p,%p)\n", pStubMsg, pFormat); + + if (pStubMsg->IgnoreEmbeddedPointers) return 0; + + if (pStubMsg->PointerBufferMark) + { + saved_buffer = pStubMsg->Buffer; + pStubMsg->Buffer = pStubMsg->PointerBufferMark; + pStubMsg->PointerBufferMark = NULL; + } + + if (*pFormat != RPC_FC_PP) return 0; + pFormat += 2; + + while (pFormat[0] != RPC_FC_END) { + switch (pFormat[0]) { + default: + FIXME("unknown repeat type %d\n", pFormat[0]); + case RPC_FC_NO_REPEAT: + rep = 1; + stride = 0; + count = 1; + pFormat += 2; + break; + case RPC_FC_FIXED_REPEAT: + rep = *(const WORD*)&pFormat[2]; + stride = *(const WORD*)&pFormat[4]; + count = *(const WORD*)&pFormat[8]; + pFormat += 10; + break; + case RPC_FC_VARIABLE_REPEAT: + rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount; + stride = *(const WORD*)&pFormat[2]; + count = *(const WORD*)&pFormat[6]; + pFormat += 8; + break; + } + for (i = 0; i < rep; i++) { + PFORMAT_STRING info = pFormat; + unsigned char *bufbase = Mark + (i * stride); + unsigned u; + for (u=0; uPointerBufferMark = pStubMsg->Buffer; + pStubMsg->Buffer = saved_buffer; + } + + return 0; +} + +/*********************************************************************** + * EmbeddedPointerFree [internal] + */ +static void EmbeddedPointerFree(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + unsigned rep, count, stride; + unsigned i; + + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + if (*pFormat != RPC_FC_PP) return; + pFormat += 2; + + while (pFormat[0] != RPC_FC_END) { + switch (pFormat[0]) { + default: + FIXME("unknown repeat type %d\n", pFormat[0]); + case RPC_FC_NO_REPEAT: + rep = 1; + stride = 0; + count = 1; + pFormat += 2; + break; + case RPC_FC_FIXED_REPEAT: + rep = *(const WORD*)&pFormat[2]; + stride = *(const WORD*)&pFormat[4]; + count = *(const WORD*)&pFormat[8]; + pFormat += 10; + break; + case RPC_FC_VARIABLE_REPEAT: + rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount; + stride = *(const WORD*)&pFormat[2]; + count = *(const WORD*)&pFormat[6]; + pFormat += 8; + break; + } + for (i = 0; i < rep; i++) { + PFORMAT_STRING info = pFormat; + unsigned char *membase = pMemory + (i * stride); + unsigned u; + + for (u=0; uMemory; + + pStubMsg->Memory = pMemory; + PointerFree(pStubMsg, *(unsigned char**)memptr, info+4); + pStubMsg->Memory = saved_memory; + } + } + pFormat += 8 * count; + } +} + +/*********************************************************************** + * NdrPointerMarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + unsigned char *Buffer; + + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + + /* incremement the buffer here instead of in PointerMarshall, + * as that is used by embedded pointers which already handle the incrementing + * the buffer, and shouldn't write any additional pointer data to the wire */ + if (*pFormat != RPC_FC_RP) + { + ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4); + Buffer = pStubMsg->Buffer; + safe_buffer_increment(pStubMsg, 4); + } + else + Buffer = pStubMsg->Buffer; + + PointerMarshall(pStubMsg, Buffer, pMemory, pFormat); + + return NULL; +} + +/*********************************************************************** + * NdrPointerUnmarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char **ppMemory, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) +{ + unsigned char *Buffer; + + TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); + + /* incremement the buffer here instead of in PointerUnmarshall, + * as that is used by embedded pointers which already handle the incrementing + * the buffer, and shouldn't read any additional pointer data from the + * buffer */ + if (*pFormat != RPC_FC_RP) + { + ALIGN_POINTER(pStubMsg->Buffer, 4); + Buffer = pStubMsg->Buffer; + safe_buffer_increment(pStubMsg, 4); + } + else + Buffer = pStubMsg->Buffer; + + PointerUnmarshall(pStubMsg, Buffer, ppMemory, *ppMemory, pFormat, fMustAlloc); + + return NULL; +} + +/*********************************************************************** + * NdrPointerBufferSize [RPCRT4.@] + */ +void WINAPI NdrPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + + /* incremement the buffer length here instead of in PointerBufferSize, + * as that is used by embedded pointers which already handle the buffer + * length, and shouldn't write anything more to the wire */ + if (*pFormat != RPC_FC_RP) + { + ALIGN_LENGTH(pStubMsg->BufferLength, 4); + safe_buffer_length_increment(pStubMsg, 4); + } + + PointerBufferSize(pStubMsg, pMemory, pFormat); +} + +/*********************************************************************** + * NdrPointerMemorySize [RPCRT4.@] + */ +ULONG WINAPI NdrPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + /* unsigned size = *(LPWORD)(pFormat+2); */ + FIXME("(%p,%p): stub\n", pStubMsg, pFormat); + PointerMemorySize(pStubMsg, pStubMsg->Buffer, pFormat); + return 0; +} + +/*********************************************************************** + * NdrPointerFree [RPCRT4.@] + */ +void WINAPI NdrPointerFree(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + PointerFree(pStubMsg, pMemory, pFormat); +} + +/*********************************************************************** + * NdrSimpleTypeMarshall [RPCRT4.@] + */ +void WINAPI NdrSimpleTypeMarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, + unsigned char FormatChar ) +{ + NdrBaseTypeMarshall(pStubMsg, pMemory, &FormatChar); +} + +/*********************************************************************** + * NdrSimpleTypeUnmarshall [RPCRT4.@] + */ +void WINAPI NdrSimpleTypeUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, + unsigned char FormatChar ) +{ + NdrBaseTypeUnmarshall(pStubMsg, &pMemory, &FormatChar, 0); +} + +/*********************************************************************** + * NdrSimpleStructMarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrSimpleStructMarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + unsigned size = *(const WORD*)(pFormat+2); + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + + ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pFormat[1] + 1); + + pStubMsg->BufferMark = pStubMsg->Buffer; + safe_copy_to_buffer(pStubMsg, pMemory, size); + + if (pFormat[0] != RPC_FC_STRUCT) + EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat+4); + + return NULL; +} + +/*********************************************************************** + * NdrSimpleStructUnmarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrSimpleStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char **ppMemory, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) +{ + unsigned size = *(const WORD*)(pFormat+2); + unsigned char *saved_buffer; + TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); + + ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1); + + if (fMustAlloc) + *ppMemory = NdrAllocate(pStubMsg, size); + else + { + if (!pStubMsg->IsClient && !*ppMemory) + /* for servers, we just point straight into the RPC buffer */ + *ppMemory = pStubMsg->Buffer; + } + + saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer; + safe_buffer_increment(pStubMsg, size); + if (pFormat[0] == RPC_FC_PSTRUCT) + EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat+4, fMustAlloc); + + TRACE("copying %p to %p\n", saved_buffer, *ppMemory); + if (*ppMemory != saved_buffer) + memcpy(*ppMemory, saved_buffer, size); + + return NULL; +} + +/*********************************************************************** + * NdrSimpleStructBufferSize [RPCRT4.@] + */ +void WINAPI NdrSimpleStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + unsigned size = *(const WORD*)(pFormat+2); + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + + ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1); + + safe_buffer_length_increment(pStubMsg, size); + if (pFormat[0] != RPC_FC_STRUCT) + EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat+4); +} + +/*********************************************************************** + * NdrSimpleStructMemorySize [RPCRT4.@] + */ +ULONG WINAPI NdrSimpleStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + unsigned short size = *(const WORD *)(pFormat+2); + + TRACE("(%p,%p)\n", pStubMsg, pFormat); + + ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1); + pStubMsg->MemorySize += size; + safe_buffer_increment(pStubMsg, size); + + if (pFormat[0] != RPC_FC_STRUCT) + EmbeddedPointerMemorySize(pStubMsg, pFormat+4); + return pStubMsg->MemorySize; +} + +/*********************************************************************** + * NdrSimpleStructFree [RPCRT4.@] + */ +void WINAPI NdrSimpleStructFree(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + if (pFormat[0] != RPC_FC_STRUCT) + EmbeddedPointerFree(pStubMsg, pMemory, pFormat+4); +} + + +static unsigned long EmbeddedComplexSize(const MIDL_STUB_MESSAGE *pStubMsg, + PFORMAT_STRING pFormat) +{ + switch (*pFormat) { + case RPC_FC_STRUCT: + case RPC_FC_PSTRUCT: + case RPC_FC_CSTRUCT: + case RPC_FC_BOGUS_STRUCT: + case RPC_FC_SMFARRAY: + case RPC_FC_SMVARRAY: + return *(const WORD*)&pFormat[2]; + case RPC_FC_USER_MARSHAL: + return *(const WORD*)&pFormat[4]; + case RPC_FC_NON_ENCAPSULATED_UNION: + pFormat += 2; + if (pStubMsg->fHasNewCorrDesc) + pFormat += 6; + else + pFormat += 4; + + pFormat += *(const SHORT*)pFormat; + return *(const SHORT*)pFormat; + case RPC_FC_IP: + return sizeof(void *); + default: + FIXME("unhandled embedded type %02x\n", *pFormat); + } + return 0; +} + + +static unsigned long EmbeddedComplexMemorySize(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + NDR_MEMORYSIZE m = NdrMemorySizer[*pFormat & NDR_TABLE_MASK]; + + if (!m) + { + FIXME("no memorysizer for data type=%02x\n", *pFormat); + return 0; + } + + return m(pStubMsg, pFormat); +} + + +static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat, + PFORMAT_STRING pPointer) +{ + PFORMAT_STRING desc; + NDR_MARSHALL m; + unsigned long size; + + while (*pFormat != RPC_FC_END) { + switch (*pFormat) { + case RPC_FC_BYTE: + case RPC_FC_CHAR: + case RPC_FC_SMALL: + case RPC_FC_USMALL: + TRACE("byte=%d <= %p\n", *(WORD*)pMemory, pMemory); + safe_copy_to_buffer(pStubMsg, pMemory, 1); + pMemory += 1; + break; + case RPC_FC_WCHAR: + case RPC_FC_SHORT: + case RPC_FC_USHORT: + TRACE("short=%d <= %p\n", *(WORD*)pMemory, pMemory); + safe_copy_to_buffer(pStubMsg, pMemory, 2); + pMemory += 2; + break; + case RPC_FC_LONG: + case RPC_FC_ULONG: + case RPC_FC_ENUM32: + TRACE("long=%d <= %p\n", *(DWORD*)pMemory, pMemory); + safe_copy_to_buffer(pStubMsg, pMemory, 4); + pMemory += 4; + break; + case RPC_FC_HYPER: + TRACE("longlong=%s <= %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory); + safe_copy_to_buffer(pStubMsg, pMemory, 8); + pMemory += 8; + break; + case RPC_FC_POINTER: + { + unsigned char *saved_buffer; + int pointer_buffer_mark_set = 0; + TRACE("pointer=%p <= %p\n", *(unsigned char**)pMemory, pMemory); + ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4); + saved_buffer = pStubMsg->Buffer; + if (pStubMsg->PointerBufferMark) + { + pStubMsg->Buffer = pStubMsg->PointerBufferMark; + pStubMsg->PointerBufferMark = NULL; + pointer_buffer_mark_set = 1; + } + else + safe_buffer_increment(pStubMsg, 4); /* for pointer ID */ + PointerMarshall(pStubMsg, saved_buffer, *(unsigned char**)pMemory, pPointer); + if (pointer_buffer_mark_set) + { + STD_OVERFLOW_CHECK(pStubMsg); + pStubMsg->PointerBufferMark = pStubMsg->Buffer; + if (saved_buffer + 4 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) + { + ERR("buffer overflow - saved_buffer = %p, BufferEnd = %p\n", + saved_buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + pStubMsg->Buffer = saved_buffer + 4; + } + pPointer += 4; + pMemory += 4; + break; + } + case RPC_FC_ALIGNM4: + ALIGN_POINTER(pMemory, 4); + break; + case RPC_FC_ALIGNM8: + ALIGN_POINTER(pMemory, 8); + break; + case RPC_FC_STRUCTPAD1: + case RPC_FC_STRUCTPAD2: + case RPC_FC_STRUCTPAD3: + case RPC_FC_STRUCTPAD4: + case RPC_FC_STRUCTPAD5: + case RPC_FC_STRUCTPAD6: + case RPC_FC_STRUCTPAD7: + pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1; + break; + case RPC_FC_EMBEDDED_COMPLEX: + pMemory += pFormat[1]; + pFormat += 2; + desc = pFormat + *(const SHORT*)pFormat; + size = EmbeddedComplexSize(pStubMsg, desc); + TRACE("embedded complex (size=%ld) <= %p\n", size, pMemory); + m = NdrMarshaller[*desc & NDR_TABLE_MASK]; + if (m) + { + /* for some reason interface pointers aren't generated as + * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet + * they still need the derefencing treatment that pointers are + * given */ + if (*desc == RPC_FC_IP) + m(pStubMsg, *(unsigned char **)pMemory, desc); + else + m(pStubMsg, pMemory, desc); + } + else FIXME("no marshaller for embedded type %02x\n", *desc); + pMemory += size; + pFormat += 2; + continue; + case RPC_FC_PAD: + break; + default: + FIXME("unhandled format 0x%02x\n", *pFormat); + } + pFormat++; + } + + return pMemory; +} + +static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat, + PFORMAT_STRING pPointer) +{ + PFORMAT_STRING desc; + NDR_UNMARSHALL m; + unsigned long size; + + while (*pFormat != RPC_FC_END) { + switch (*pFormat) { + case RPC_FC_BYTE: + case RPC_FC_CHAR: + case RPC_FC_SMALL: + case RPC_FC_USMALL: + safe_copy_from_buffer(pStubMsg, pMemory, 1); + TRACE("byte=%d => %p\n", *(WORD*)pMemory, pMemory); + pMemory += 1; + break; + case RPC_FC_WCHAR: + case RPC_FC_SHORT: + case RPC_FC_USHORT: + safe_copy_from_buffer(pStubMsg, pMemory, 2); + TRACE("short=%d => %p\n", *(WORD*)pMemory, pMemory); + pMemory += 2; + break; + case RPC_FC_LONG: + case RPC_FC_ULONG: + case RPC_FC_ENUM32: + safe_copy_from_buffer(pStubMsg, pMemory, 4); + TRACE("long=%d => %p\n", *(DWORD*)pMemory, pMemory); + pMemory += 4; + break; + case RPC_FC_HYPER: + safe_copy_from_buffer(pStubMsg, pMemory, 8); + TRACE("longlong=%s => %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory); + pMemory += 8; + break; + case RPC_FC_POINTER: + { + unsigned char *saved_buffer; + int pointer_buffer_mark_set = 0; + TRACE("pointer => %p\n", pMemory); + ALIGN_POINTER(pStubMsg->Buffer, 4); + saved_buffer = pStubMsg->Buffer; + if (pStubMsg->PointerBufferMark) + { + pStubMsg->Buffer = pStubMsg->PointerBufferMark; + pStubMsg->PointerBufferMark = NULL; + pointer_buffer_mark_set = 1; + } + else + safe_buffer_increment(pStubMsg, 4); /* for pointer ID */ + + PointerUnmarshall(pStubMsg, saved_buffer, (unsigned char**)pMemory, *(unsigned char**)pMemory, pPointer, TRUE); + if (pointer_buffer_mark_set) + { + STD_OVERFLOW_CHECK(pStubMsg); + pStubMsg->PointerBufferMark = pStubMsg->Buffer; + if (saved_buffer + 4 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) + { + ERR("buffer overflow - saved_buffer = %p, BufferEnd = %p\n", + saved_buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + pStubMsg->Buffer = saved_buffer + 4; + } + pPointer += 4; + pMemory += 4; + break; + } + case RPC_FC_ALIGNM4: + ALIGN_POINTER_CLEAR(pMemory, 4); + break; + case RPC_FC_ALIGNM8: + ALIGN_POINTER_CLEAR(pMemory, 8); + break; + case RPC_FC_STRUCTPAD1: + case RPC_FC_STRUCTPAD2: + case RPC_FC_STRUCTPAD3: + case RPC_FC_STRUCTPAD4: + case RPC_FC_STRUCTPAD5: + case RPC_FC_STRUCTPAD6: + case RPC_FC_STRUCTPAD7: + memset(pMemory, 0, *pFormat - RPC_FC_STRUCTPAD1 + 1); + pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1; + break; + case RPC_FC_EMBEDDED_COMPLEX: + pMemory += pFormat[1]; + pFormat += 2; + desc = pFormat + *(const SHORT*)pFormat; + size = EmbeddedComplexSize(pStubMsg, desc); + TRACE("embedded complex (size=%ld) => %p\n", size, pMemory); + m = NdrUnmarshaller[*desc & NDR_TABLE_MASK]; + memset(pMemory, 0, size); /* just in case */ + if (m) + { + /* for some reason interface pointers aren't generated as + * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet + * they still need the derefencing treatment that pointers are + * given */ + if (*desc == RPC_FC_IP) + m(pStubMsg, (unsigned char **)pMemory, desc, FALSE); + else + m(pStubMsg, &pMemory, desc, FALSE); + } + else FIXME("no unmarshaller for embedded type %02x\n", *desc); + pMemory += size; + pFormat += 2; + continue; + case RPC_FC_PAD: + break; + default: + FIXME("unhandled format %d\n", *pFormat); + } + pFormat++; + } + + return pMemory; +} + +static unsigned char * ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat, + PFORMAT_STRING pPointer) +{ + PFORMAT_STRING desc; + NDR_BUFFERSIZE m; + unsigned long size; + + while (*pFormat != RPC_FC_END) { + switch (*pFormat) { + case RPC_FC_BYTE: + case RPC_FC_CHAR: + case RPC_FC_SMALL: + case RPC_FC_USMALL: + safe_buffer_length_increment(pStubMsg, 1); + pMemory += 1; + break; + case RPC_FC_WCHAR: + case RPC_FC_SHORT: + case RPC_FC_USHORT: + safe_buffer_length_increment(pStubMsg, 2); + pMemory += 2; + break; + case RPC_FC_LONG: + case RPC_FC_ULONG: + case RPC_FC_ENUM32: + safe_buffer_length_increment(pStubMsg, 4); + pMemory += 4; + break; + case RPC_FC_HYPER: + safe_buffer_length_increment(pStubMsg, 8); + pMemory += 8; + break; + case RPC_FC_POINTER: + if (!pStubMsg->IgnoreEmbeddedPointers) + { + int saved_buffer_length = pStubMsg->BufferLength; + pStubMsg->BufferLength = pStubMsg->PointerLength; + pStubMsg->PointerLength = 0; + if(!pStubMsg->BufferLength) + ERR("BufferLength == 0??\n"); + PointerBufferSize(pStubMsg, *(unsigned char**)pMemory, pPointer); + pStubMsg->PointerLength = pStubMsg->BufferLength; + pStubMsg->BufferLength = saved_buffer_length; + } + safe_buffer_length_increment(pStubMsg, 4); + pPointer += 4; + pMemory += 4; + break; + case RPC_FC_ALIGNM4: + ALIGN_POINTER(pMemory, 4); + break; + case RPC_FC_ALIGNM8: + ALIGN_POINTER(pMemory, 8); + break; + case RPC_FC_STRUCTPAD1: + case RPC_FC_STRUCTPAD2: + case RPC_FC_STRUCTPAD3: + case RPC_FC_STRUCTPAD4: + case RPC_FC_STRUCTPAD5: + case RPC_FC_STRUCTPAD6: + case RPC_FC_STRUCTPAD7: + pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1; + break; + case RPC_FC_EMBEDDED_COMPLEX: + pMemory += pFormat[1]; + pFormat += 2; + desc = pFormat + *(const SHORT*)pFormat; + size = EmbeddedComplexSize(pStubMsg, desc); + m = NdrBufferSizer[*desc & NDR_TABLE_MASK]; + if (m) + { + /* for some reason interface pointers aren't generated as + * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet + * they still need the derefencing treatment that pointers are + * given */ + if (*desc == RPC_FC_IP) + m(pStubMsg, *(unsigned char **)pMemory, desc); + else + m(pStubMsg, pMemory, desc); + } + else FIXME("no buffersizer for embedded type %02x\n", *desc); + pMemory += size; + pFormat += 2; + continue; + case RPC_FC_PAD: + break; + default: + FIXME("unhandled format 0x%02x\n", *pFormat); + } + pFormat++; + } + + return pMemory; +} + +static unsigned char * ComplexFree(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat, + PFORMAT_STRING pPointer) +{ + PFORMAT_STRING desc; + NDR_FREE m; + unsigned long size; + + while (*pFormat != RPC_FC_END) { + switch (*pFormat) { + case RPC_FC_BYTE: + case RPC_FC_CHAR: + case RPC_FC_SMALL: + case RPC_FC_USMALL: + pMemory += 1; + break; + case RPC_FC_WCHAR: + case RPC_FC_SHORT: + case RPC_FC_USHORT: + pMemory += 2; + break; + case RPC_FC_LONG: + case RPC_FC_ULONG: + case RPC_FC_ENUM32: + pMemory += 4; + break; + case RPC_FC_HYPER: + pMemory += 8; + break; + case RPC_FC_POINTER: + NdrPointerFree(pStubMsg, *(unsigned char**)pMemory, pPointer); + pPointer += 4; + pMemory += 4; + break; + case RPC_FC_ALIGNM4: + ALIGN_POINTER(pMemory, 4); + break; + case RPC_FC_ALIGNM8: + ALIGN_POINTER(pMemory, 8); + break; + case RPC_FC_STRUCTPAD1: + case RPC_FC_STRUCTPAD2: + case RPC_FC_STRUCTPAD3: + case RPC_FC_STRUCTPAD4: + case RPC_FC_STRUCTPAD5: + case RPC_FC_STRUCTPAD6: + case RPC_FC_STRUCTPAD7: + pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1; + break; + case RPC_FC_EMBEDDED_COMPLEX: + pMemory += pFormat[1]; + pFormat += 2; + desc = pFormat + *(const SHORT*)pFormat; + size = EmbeddedComplexSize(pStubMsg, desc); + m = NdrFreer[*desc & NDR_TABLE_MASK]; + if (m) + { + /* for some reason interface pointers aren't generated as + * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet + * they still need the derefencing treatment that pointers are + * given */ + if (*desc == RPC_FC_IP) + m(pStubMsg, *(unsigned char **)pMemory, desc); + else + m(pStubMsg, pMemory, desc); + } + else FIXME("no freer for embedded type %02x\n", *desc); + pMemory += size; + pFormat += 2; + continue; + case RPC_FC_PAD: + break; + default: + FIXME("unhandled format 0x%02x\n", *pFormat); + } + pFormat++; + } + + return pMemory; +} + +static unsigned long ComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + PFORMAT_STRING desc; + unsigned long size = 0; + + while (*pFormat != RPC_FC_END) { + switch (*pFormat) { + case RPC_FC_BYTE: + case RPC_FC_CHAR: + case RPC_FC_SMALL: + case RPC_FC_USMALL: + size += 1; + safe_buffer_increment(pStubMsg, 1); + break; + case RPC_FC_WCHAR: + case RPC_FC_SHORT: + case RPC_FC_USHORT: + size += 2; + safe_buffer_increment(pStubMsg, 2); + break; + case RPC_FC_LONG: + case RPC_FC_ULONG: + case RPC_FC_ENUM32: + size += 4; + safe_buffer_increment(pStubMsg, 4); + break; + case RPC_FC_HYPER: + size += 8; + safe_buffer_increment(pStubMsg, 8); + break; + case RPC_FC_POINTER: + size += 4; + safe_buffer_increment(pStubMsg, 4); + if (!pStubMsg->IgnoreEmbeddedPointers) + FIXME("embedded pointers\n"); + break; + case RPC_FC_ALIGNM4: + ALIGN_LENGTH(size, 4); + ALIGN_POINTER(pStubMsg->Buffer, 4); + break; + case RPC_FC_ALIGNM8: + ALIGN_LENGTH(size, 8); + ALIGN_POINTER(pStubMsg->Buffer, 8); + break; + case RPC_FC_STRUCTPAD1: + case RPC_FC_STRUCTPAD2: + case RPC_FC_STRUCTPAD3: + case RPC_FC_STRUCTPAD4: + case RPC_FC_STRUCTPAD5: + case RPC_FC_STRUCTPAD6: + case RPC_FC_STRUCTPAD7: + size += *pFormat - RPC_FC_STRUCTPAD1 + 1; + break; + case RPC_FC_EMBEDDED_COMPLEX: + size += pFormat[1]; + pFormat += 2; + desc = pFormat + *(const SHORT*)pFormat; + size += EmbeddedComplexMemorySize(pStubMsg, desc); + pFormat += 2; + continue; + case RPC_FC_PAD: + break; + default: + FIXME("unhandled format 0x%02x\n", *pFormat); + } + pFormat++; + } + + return size; +} + +/*********************************************************************** + * NdrComplexStructMarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrComplexStructMarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + PFORMAT_STRING conf_array = NULL; + PFORMAT_STRING pointer_desc = NULL; + unsigned char *OldMemory = pStubMsg->Memory; + int pointer_buffer_mark_set = 0; + + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + + if (!pStubMsg->PointerBufferMark) + { + int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers; + /* save buffer length */ + unsigned long saved_buffer_length = pStubMsg->BufferLength; + + /* get the buffer pointer after complex array data, but before + * pointer data */ + pStubMsg->BufferLength = pStubMsg->Buffer - pStubMsg->BufferStart; + pStubMsg->IgnoreEmbeddedPointers = 1; + NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat); + pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded; + + /* save it for use by embedded pointer code later */ + pStubMsg->PointerBufferMark = pStubMsg->BufferStart + pStubMsg->BufferLength; + TRACE("difference = 0x%x\n", pStubMsg->PointerBufferMark - pStubMsg->Buffer); + pointer_buffer_mark_set = 1; + + /* restore the original buffer length */ + pStubMsg->BufferLength = saved_buffer_length; + } + + ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pFormat[1] + 1); + + pFormat += 4; + if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat; + pFormat += 2; + if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat; + pFormat += 2; + + pStubMsg->Memory = pMemory; + + ComplexMarshall(pStubMsg, pMemory, pFormat, pointer_desc); + + if (conf_array) + NdrConformantArrayMarshall(pStubMsg, pMemory, conf_array); + + pStubMsg->Memory = OldMemory; + + if (pointer_buffer_mark_set) + { + pStubMsg->Buffer = pStubMsg->PointerBufferMark; + pStubMsg->PointerBufferMark = NULL; + } + + STD_OVERFLOW_CHECK(pStubMsg); + + return NULL; +} + +/*********************************************************************** + * NdrComplexStructUnmarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrComplexStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char **ppMemory, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) +{ + unsigned size = *(const WORD*)(pFormat+2); + PFORMAT_STRING conf_array = NULL; + PFORMAT_STRING pointer_desc = NULL; + unsigned char *pMemory; + int pointer_buffer_mark_set = 0; + + TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); + + if (!pStubMsg->PointerBufferMark) + { + int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers; + /* save buffer pointer */ + unsigned char *saved_buffer = pStubMsg->Buffer; + + /* get the buffer pointer after complex array data, but before + * pointer data */ + pStubMsg->IgnoreEmbeddedPointers = 1; + NdrComplexStructMemorySize(pStubMsg, pFormat); + pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded; + + /* save it for use by embedded pointer code later */ + pStubMsg->PointerBufferMark = pStubMsg->Buffer; + TRACE("difference = 0x%lx\n", (unsigned long)(pStubMsg->PointerBufferMark - saved_buffer)); + pointer_buffer_mark_set = 1; + + /* restore the original buffer */ + pStubMsg->Buffer = saved_buffer; + } + + ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1); + + if (fMustAlloc || !*ppMemory) + { + *ppMemory = NdrAllocate(pStubMsg, size); + memset(*ppMemory, 0, size); + } + + pFormat += 4; + if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat; + pFormat += 2; + if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat; + pFormat += 2; + + pMemory = ComplexUnmarshall(pStubMsg, *ppMemory, pFormat, pointer_desc); + + if (conf_array) + NdrConformantArrayUnmarshall(pStubMsg, &pMemory, conf_array, fMustAlloc); + + if (pointer_buffer_mark_set) + { + pStubMsg->Buffer = pStubMsg->PointerBufferMark; + pStubMsg->PointerBufferMark = NULL; + } + + return NULL; +} + +/*********************************************************************** + * NdrComplexStructBufferSize [RPCRT4.@] + */ +void WINAPI NdrComplexStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + PFORMAT_STRING conf_array = NULL; + PFORMAT_STRING pointer_desc = NULL; + unsigned char *OldMemory = pStubMsg->Memory; + int pointer_length_set = 0; + + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + + ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1); + + if(!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength) + { + int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers; + unsigned long saved_buffer_length = pStubMsg->BufferLength; + + /* get the buffer length after complex struct data, but before + * pointer data */ + pStubMsg->IgnoreEmbeddedPointers = 1; + NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat); + pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded; + + /* save it for use by embedded pointer code later */ + pStubMsg->PointerLength = pStubMsg->BufferLength; + pointer_length_set = 1; + TRACE("difference = 0x%lx\n", pStubMsg->PointerLength - saved_buffer_length); + + /* restore the original buffer length */ + pStubMsg->BufferLength = saved_buffer_length; + } + + pFormat += 4; + if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat; + pFormat += 2; + if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat; + pFormat += 2; + + pStubMsg->Memory = pMemory; + + pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, pointer_desc); + + if (conf_array) + NdrConformantArrayBufferSize(pStubMsg, pMemory, conf_array); + + pStubMsg->Memory = OldMemory; + + if(pointer_length_set) + { + pStubMsg->BufferLength = pStubMsg->PointerLength; + pStubMsg->PointerLength = 0; + } + +} + +/*********************************************************************** + * NdrComplexStructMemorySize [RPCRT4.@] + */ +ULONG WINAPI NdrComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + unsigned size = *(const WORD*)(pFormat+2); + PFORMAT_STRING conf_array = NULL; + PFORMAT_STRING pointer_desc = NULL; + + TRACE("(%p,%p)\n", pStubMsg, pFormat); + + ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1); + + pFormat += 4; + if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat; + pFormat += 2; + if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat; + pFormat += 2; + + ComplexStructMemorySize(pStubMsg, pFormat); + + if (conf_array) + NdrConformantArrayMemorySize(pStubMsg, conf_array); + + return size; +} + +/*********************************************************************** + * NdrComplexStructFree [RPCRT4.@] + */ +void WINAPI NdrComplexStructFree(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + PFORMAT_STRING conf_array = NULL; + PFORMAT_STRING pointer_desc = NULL; + unsigned char *OldMemory = pStubMsg->Memory; + + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + + pFormat += 4; + if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat; + pFormat += 2; + if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat; + pFormat += 2; + + pStubMsg->Memory = pMemory; + + pMemory = ComplexFree(pStubMsg, pMemory, pFormat, pointer_desc); + + if (conf_array) + NdrConformantArrayFree(pStubMsg, pMemory, conf_array); + + pStubMsg->Memory = OldMemory; +} + +/*********************************************************************** + * NdrConformantArrayMarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrConformantArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + DWORD size = 0, esize = *(const WORD*)(pFormat+2); + unsigned char alignment = pFormat[1] + 1; + + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]); + + pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0); + + WriteConformance(pStubMsg); + + ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment); + + size = safe_multiply(esize, pStubMsg->MaxCount); + pStubMsg->BufferMark = pStubMsg->Buffer; + safe_copy_to_buffer(pStubMsg, pMemory, size); + + EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat); + + return NULL; +} + +/*********************************************************************** + * NdrConformantArrayUnmarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrConformantArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char **ppMemory, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) +{ + DWORD size, esize = *(const WORD*)(pFormat+2); + unsigned char alignment = pFormat[1] + 1; + unsigned char *saved_buffer; + + TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); + if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]); + + pFormat = ReadConformance(pStubMsg, pFormat+4); + + size = safe_multiply(esize, pStubMsg->MaxCount); + ALIGN_POINTER(pStubMsg->Buffer, alignment); + + if (fMustAlloc) + *ppMemory = NdrAllocate(pStubMsg, size); + else + { + if (!pStubMsg->IsClient && !*ppMemory) + /* for servers, we just point straight into the RPC buffer */ + *ppMemory = pStubMsg->Buffer; + } + + saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer; + safe_buffer_increment(pStubMsg, size); + EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc); + + TRACE("copying %p to %p\n", saved_buffer, *ppMemory); + if (*ppMemory != saved_buffer) + memcpy(*ppMemory, saved_buffer, size); + + return NULL; +} + +/*********************************************************************** + * NdrConformantArrayBufferSize [RPCRT4.@] + */ +void WINAPI NdrConformantArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + DWORD size, esize = *(const WORD*)(pFormat+2); + unsigned char alignment = pFormat[1] + 1; + + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]); + + pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0); + + SizeConformance(pStubMsg); + + ALIGN_LENGTH(pStubMsg->BufferLength, alignment); + + size = safe_multiply(esize, pStubMsg->MaxCount); + /* conformance value plus array */ + safe_buffer_length_increment(pStubMsg, size); + + EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat); +} + +/*********************************************************************** + * NdrConformantArrayMemorySize [RPCRT4.@] + */ +ULONG WINAPI NdrConformantArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + DWORD size = 0, esize = *(const WORD*)(pFormat+2); + unsigned char alignment = pFormat[1] + 1; + + TRACE("(%p,%p)\n", pStubMsg, pFormat); + if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]); + + pFormat = ReadConformance(pStubMsg, pFormat+4); + size = safe_multiply(esize, pStubMsg->MaxCount); + pStubMsg->MemorySize += size; + + ALIGN_POINTER(pStubMsg->Buffer, alignment); + pStubMsg->BufferMark = pStubMsg->Buffer; + safe_buffer_increment(pStubMsg, size); + + EmbeddedPointerMemorySize(pStubMsg, pFormat); + + return pStubMsg->MemorySize; +} + +/*********************************************************************** + * NdrConformantArrayFree [RPCRT4.@] + */ +void WINAPI NdrConformantArrayFree(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]); + + pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0); + + EmbeddedPointerFree(pStubMsg, pMemory, pFormat); +} + + +/*********************************************************************** + * NdrConformantVaryingArrayMarshall [RPCRT4.@] + */ +unsigned char* WINAPI NdrConformantVaryingArrayMarshall( PMIDL_STUB_MESSAGE pStubMsg, + unsigned char* pMemory, + PFORMAT_STRING pFormat ) +{ + ULONG bufsize; + unsigned char alignment = pFormat[1] + 1; + DWORD esize = *(const WORD*)(pFormat+2); + + TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); + + if (pFormat[0] != RPC_FC_CVARRAY) + { + ERR("invalid format type %x\n", pFormat[0]); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return NULL; + } + + pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0); + pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0); + + WriteConformance(pStubMsg); + WriteVariance(pStubMsg); + + ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment); + + bufsize = safe_multiply(esize, pStubMsg->ActualCount); + + pStubMsg->BufferMark = pStubMsg->Buffer; + safe_copy_to_buffer(pStubMsg, pMemory + pStubMsg->Offset, bufsize); + + EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat); + + return NULL; +} + + +/*********************************************************************** + * NdrConformantVaryingArrayUnmarshall [RPCRT4.@] + */ +unsigned char* WINAPI NdrConformantVaryingArrayUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, + unsigned char** ppMemory, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc ) +{ + ULONG bufsize, memsize; + unsigned char alignment = pFormat[1] + 1; + DWORD esize = *(const WORD*)(pFormat+2); + unsigned char *saved_buffer; + ULONG offset; + + TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); + + if (pFormat[0] != RPC_FC_CVARRAY) + { + ERR("invalid format type %x\n", pFormat[0]); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return NULL; + } + + pFormat = ReadConformance(pStubMsg, pFormat+4); + pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount); + + ALIGN_POINTER(pStubMsg->Buffer, alignment); + + bufsize = safe_multiply(esize, pStubMsg->ActualCount); + memsize = safe_multiply(esize, pStubMsg->MaxCount); + offset = pStubMsg->Offset; + + if (!*ppMemory || fMustAlloc) + *ppMemory = NdrAllocate(pStubMsg, memsize); + saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer; + safe_buffer_increment(pStubMsg, bufsize); + + EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc); + + memcpy(*ppMemory + offset, saved_buffer, bufsize); + + return NULL; +} + + +/*********************************************************************** + * NdrConformantVaryingArrayFree [RPCRT4.@] + */ +void WINAPI NdrConformantVaryingArrayFree( PMIDL_STUB_MESSAGE pStubMsg, + unsigned char* pMemory, + PFORMAT_STRING pFormat ) +{ + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + + if (pFormat[0] != RPC_FC_CVARRAY) + { + ERR("invalid format type %x\n", pFormat[0]); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return; + } + + pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0); + pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0); + + EmbeddedPointerFree(pStubMsg, pMemory, pFormat); +} + + +/*********************************************************************** + * NdrConformantVaryingArrayBufferSize [RPCRT4.@] + */ +void WINAPI NdrConformantVaryingArrayBufferSize( PMIDL_STUB_MESSAGE pStubMsg, + unsigned char* pMemory, PFORMAT_STRING pFormat ) +{ + unsigned char alignment = pFormat[1] + 1; + DWORD esize = *(const WORD*)(pFormat+2); + + TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); + + if (pFormat[0] != RPC_FC_CVARRAY) + { + ERR("invalid format type %x\n", pFormat[0]); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return; + } + + /* compute size */ + pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0); + /* compute length */ + pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0); + + SizeConformance(pStubMsg); + SizeVariance(pStubMsg); + + ALIGN_LENGTH(pStubMsg->BufferLength, alignment); + + safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount)); + + EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat); +} + + +/*********************************************************************** + * NdrConformantVaryingArrayMemorySize [RPCRT4.@] + */ +ULONG WINAPI NdrConformantVaryingArrayMemorySize( PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat ) +{ + ULONG bufsize, memsize; + unsigned char alignment = pFormat[1] + 1; + DWORD esize = *(const WORD*)(pFormat+2); + + TRACE("(%p, %p)\n", pStubMsg, pFormat); + + if (pFormat[0] != RPC_FC_CVARRAY) + { + ERR("invalid format type %x\n", pFormat[0]); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return pStubMsg->MemorySize; + } + + pFormat = ReadConformance(pStubMsg, pFormat+4); + pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount); + + ALIGN_POINTER(pStubMsg->Buffer, alignment); + + bufsize = safe_multiply(esize, pStubMsg->ActualCount); + memsize = safe_multiply(esize, pStubMsg->MaxCount); + + safe_buffer_increment(pStubMsg, bufsize); + pStubMsg->MemorySize += memsize; + + EmbeddedPointerMemorySize(pStubMsg, pFormat); + + return pStubMsg->MemorySize; +} + + +/*********************************************************************** + * NdrComplexArrayMarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrComplexArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + ULONG i, count, def; + BOOL variance_present; + unsigned char alignment; + int pointer_buffer_mark_set = 0; + + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + + if (pFormat[0] != RPC_FC_BOGUS_ARRAY) + { + ERR("invalid format type %x\n", pFormat[0]); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return NULL; + } + + alignment = pFormat[1] + 1; + + if (!pStubMsg->PointerBufferMark) + { + /* save buffer fields that may be changed by buffer sizer functions + * and that may be needed later on */ + int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers; + unsigned long saved_buffer_length = pStubMsg->BufferLength; + unsigned long saved_max_count = pStubMsg->MaxCount; + unsigned long saved_offset = pStubMsg->Offset; + unsigned long saved_actual_count = pStubMsg->ActualCount; + + /* get the buffer pointer after complex array data, but before + * pointer data */ + pStubMsg->BufferLength = pStubMsg->Buffer - pStubMsg->BufferStart; + pStubMsg->IgnoreEmbeddedPointers = 1; + NdrComplexArrayBufferSize(pStubMsg, pMemory, pFormat); + pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded; + + /* save it for use by embedded pointer code later */ + pStubMsg->PointerBufferMark = pStubMsg->BufferStart + pStubMsg->BufferLength; + TRACE("difference = 0x%x\n", pStubMsg->Buffer - pStubMsg->BufferStart); + pointer_buffer_mark_set = 1; + + /* restore fields */ + pStubMsg->ActualCount = saved_actual_count; + pStubMsg->Offset = saved_offset; + pStubMsg->MaxCount = saved_max_count; + pStubMsg->BufferLength = saved_buffer_length; + } + + def = *(const WORD*)&pFormat[2]; + pFormat += 4; + + pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def); + TRACE("conformance = %ld\n", pStubMsg->MaxCount); + + variance_present = IsConformanceOrVariancePresent(pFormat); + pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount); + TRACE("variance = %d\n", pStubMsg->ActualCount); + + WriteConformance(pStubMsg); + if (variance_present) + WriteVariance(pStubMsg); + + ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment); + + count = pStubMsg->ActualCount; + for (i = 0; i < count; i++) + pMemory = ComplexMarshall(pStubMsg, pMemory, pFormat, NULL); + + STD_OVERFLOW_CHECK(pStubMsg); + + if (pointer_buffer_mark_set) + { + pStubMsg->Buffer = pStubMsg->PointerBufferMark; + pStubMsg->PointerBufferMark = NULL; + } + + return NULL; +} + +/*********************************************************************** + * NdrComplexArrayUnmarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrComplexArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char **ppMemory, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) +{ + ULONG i, count, size; + unsigned char alignment; + unsigned char *pMemory; + unsigned char *saved_buffer; + int pointer_buffer_mark_set = 0; + int saved_ignore_embedded; + + TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); + + if (pFormat[0] != RPC_FC_BOGUS_ARRAY) + { + ERR("invalid format type %x\n", pFormat[0]); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return NULL; + } + + alignment = pFormat[1] + 1; + + saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers; + /* save buffer pointer */ + saved_buffer = pStubMsg->Buffer; + /* get the buffer pointer after complex array data, but before + * pointer data */ + pStubMsg->IgnoreEmbeddedPointers = 1; + pStubMsg->MemorySize = 0; + NdrComplexArrayMemorySize(pStubMsg, pFormat); + size = pStubMsg->MemorySize; + pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded; + + TRACE("difference = 0x%lx\n", (unsigned long)(pStubMsg->Buffer - saved_buffer)); + if (!pStubMsg->PointerBufferMark) + { + /* save it for use by embedded pointer code later */ + pStubMsg->PointerBufferMark = pStubMsg->Buffer; + pointer_buffer_mark_set = 1; + } + /* restore the original buffer */ + pStubMsg->Buffer = saved_buffer; + + pFormat += 4; + + pFormat = ReadConformance(pStubMsg, pFormat); + pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount); + + if (fMustAlloc || !*ppMemory) + { + *ppMemory = NdrAllocate(pStubMsg, size); + memset(*ppMemory, 0, size); + } + + ALIGN_POINTER(pStubMsg->Buffer, alignment); + + pMemory = *ppMemory; + count = pStubMsg->ActualCount; + for (i = 0; i < count; i++) + pMemory = ComplexUnmarshall(pStubMsg, pMemory, pFormat, NULL); + + if (pointer_buffer_mark_set) + { + pStubMsg->Buffer = pStubMsg->PointerBufferMark; + pStubMsg->PointerBufferMark = NULL; + } + + return NULL; +} + +/*********************************************************************** + * NdrComplexArrayBufferSize [RPCRT4.@] + */ +void WINAPI NdrComplexArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + ULONG i, count, def; + unsigned char alignment; + BOOL variance_present; + int pointer_length_set = 0; + + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + + if (pFormat[0] != RPC_FC_BOGUS_ARRAY) + { + ERR("invalid format type %x\n", pFormat[0]); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return; + } + + alignment = pFormat[1] + 1; + + if (!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength) + { + /* save buffer fields that may be changed by buffer sizer functions + * and that may be needed later on */ + int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers; + unsigned long saved_buffer_length = pStubMsg->BufferLength; + unsigned long saved_max_count = pStubMsg->MaxCount; + unsigned long saved_offset = pStubMsg->Offset; + unsigned long saved_actual_count = pStubMsg->ActualCount; + + /* get the buffer pointer after complex array data, but before + * pointer data */ + pStubMsg->IgnoreEmbeddedPointers = 1; + NdrComplexArrayBufferSize(pStubMsg, pMemory, pFormat); + pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded; + + /* save it for use by embedded pointer code later */ + pStubMsg->PointerLength = pStubMsg->BufferLength; + pointer_length_set = 1; + + /* restore fields */ + pStubMsg->ActualCount = saved_actual_count; + pStubMsg->Offset = saved_offset; + pStubMsg->MaxCount = saved_max_count; + pStubMsg->BufferLength = saved_buffer_length; + } + def = *(const WORD*)&pFormat[2]; + pFormat += 4; + + pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def); + TRACE("conformance = %ld\n", pStubMsg->MaxCount); + SizeConformance(pStubMsg); + + variance_present = IsConformanceOrVariancePresent(pFormat); + pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount); + TRACE("variance = %d\n", pStubMsg->ActualCount); + + if (variance_present) + SizeVariance(pStubMsg); + + ALIGN_LENGTH(pStubMsg->BufferLength, alignment); + + count = pStubMsg->ActualCount; + for (i = 0; i < count; i++) + pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, NULL); + + if(pointer_length_set) + { + pStubMsg->BufferLength = pStubMsg->PointerLength; + pStubMsg->PointerLength = 0; + } +} + +/*********************************************************************** + * NdrComplexArrayMemorySize [RPCRT4.@] + */ +ULONG WINAPI NdrComplexArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + ULONG i, count, esize, SavedMemorySize, MemorySize; + unsigned char alignment; + unsigned char *Buffer; + + TRACE("(%p,%p)\n", pStubMsg, pFormat); + + if (pFormat[0] != RPC_FC_BOGUS_ARRAY) + { + ERR("invalid format type %x\n", pFormat[0]); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return 0; + } + + alignment = pFormat[1] + 1; + + pFormat += 4; + + pFormat = ReadConformance(pStubMsg, pFormat); + pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount); + + ALIGN_POINTER(pStubMsg->Buffer, alignment); + + SavedMemorySize = pStubMsg->MemorySize; + + Buffer = pStubMsg->Buffer; + pStubMsg->MemorySize = 0; + esize = ComplexStructMemorySize(pStubMsg, pFormat); + pStubMsg->Buffer = Buffer; + + MemorySize = safe_multiply(pStubMsg->MaxCount, esize); + + count = pStubMsg->ActualCount; + for (i = 0; i < count; i++) + ComplexStructMemorySize(pStubMsg, pFormat); + + pStubMsg->MemorySize = SavedMemorySize; + + pStubMsg->MemorySize += MemorySize; + return MemorySize; +} + +/*********************************************************************** + * NdrComplexArrayFree [RPCRT4.@] + */ +void WINAPI NdrComplexArrayFree(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + ULONG i, count, def; + + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + + if (pFormat[0] != RPC_FC_BOGUS_ARRAY) + { + ERR("invalid format type %x\n", pFormat[0]); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return; + } + + def = *(const WORD*)&pFormat[2]; + pFormat += 4; + + pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def); + TRACE("conformance = %ld\n", pStubMsg->MaxCount); + + pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount); + TRACE("variance = %d\n", pStubMsg->ActualCount); + + count = pStubMsg->ActualCount; + for (i = 0; i < count; i++) + pMemory = ComplexFree(pStubMsg, pMemory, pFormat, NULL); +} + +static void UserMarshalCB(PMIDL_STUB_MESSAGE pStubMsg, + USER_MARSHAL_CB_TYPE cbtype, PFORMAT_STRING pFormat, + USER_MARSHAL_CB *umcb) +{ + umcb->Flags = MAKELONG(pStubMsg->dwDestContext, + pStubMsg->RpcMsg->DataRepresentation); + umcb->pStubMsg = pStubMsg; + umcb->pReserve = NULL; + umcb->Signature = USER_MARSHAL_CB_SIGNATURE; + umcb->CBType = cbtype; + umcb->pFormat = pFormat; + umcb->pTypeFormat = NULL /* FIXME */; +} + +#define USER_MARSHAL_PTR_PREFIX \ + ( (DWORD)'U' | ( (DWORD)'s' << 8 ) | \ + ( (DWORD)'e' << 16 ) | ( (DWORD)'r' << 24 ) ) + +/*********************************************************************** + * NdrUserMarshalMarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrUserMarshalMarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + unsigned flags = pFormat[1]; + unsigned index = *(const WORD*)&pFormat[2]; + unsigned char *saved_buffer = NULL; + USER_MARSHAL_CB umcb; + + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + TRACE("index=%d\n", index); + + UserMarshalCB(pStubMsg, USER_MARSHAL_CB_MARSHALL, pFormat, &umcb); + + if (flags & USER_MARSHAL_POINTER) + { + ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4); + NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, USER_MARSHAL_PTR_PREFIX); + pStubMsg->Buffer += 4; + if (pStubMsg->PointerBufferMark) + { + saved_buffer = pStubMsg->Buffer; + pStubMsg->Buffer = pStubMsg->PointerBufferMark; + pStubMsg->PointerBufferMark = NULL; + } + ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 8); + } + else + ALIGN_POINTER_CLEAR(pStubMsg->Buffer, (flags & 0xf) + 1); + + pStubMsg->Buffer = + pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnMarshall( + &umcb.Flags, pStubMsg->Buffer, pMemory); + + if (saved_buffer) + { + STD_OVERFLOW_CHECK(pStubMsg); + pStubMsg->PointerBufferMark = pStubMsg->Buffer; + pStubMsg->Buffer = saved_buffer; + } + + STD_OVERFLOW_CHECK(pStubMsg); + + return NULL; +} + +/*********************************************************************** + * NdrUserMarshalUnmarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrUserMarshalUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char **ppMemory, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) +{ + unsigned flags = pFormat[1]; + unsigned index = *(const WORD*)&pFormat[2]; + DWORD memsize = *(const WORD*)&pFormat[4]; + unsigned char *saved_buffer = NULL; + USER_MARSHAL_CB umcb; + + TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); + TRACE("index=%d\n", index); + + UserMarshalCB(pStubMsg, USER_MARSHAL_CB_UNMARSHALL, pFormat, &umcb); + + if (flags & USER_MARSHAL_POINTER) + { + ALIGN_POINTER(pStubMsg->Buffer, 4); + /* skip pointer prefix */ + pStubMsg->Buffer += 4; + if (pStubMsg->PointerBufferMark) + { + saved_buffer = pStubMsg->Buffer; + pStubMsg->Buffer = pStubMsg->PointerBufferMark; + pStubMsg->PointerBufferMark = NULL; + } + ALIGN_POINTER(pStubMsg->Buffer, 8); + } + else + ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1); + + if (fMustAlloc || !*ppMemory) + *ppMemory = NdrAllocate(pStubMsg, memsize); + + pStubMsg->Buffer = + pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnUnmarshall( + &umcb.Flags, pStubMsg->Buffer, *ppMemory); + + if (saved_buffer) + { + STD_OVERFLOW_CHECK(pStubMsg); + pStubMsg->PointerBufferMark = pStubMsg->Buffer; + pStubMsg->Buffer = saved_buffer; + } + + return NULL; +} + +/*********************************************************************** + * NdrUserMarshalBufferSize [RPCRT4.@] + */ +void WINAPI NdrUserMarshalBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + unsigned flags = pFormat[1]; + unsigned index = *(const WORD*)&pFormat[2]; + DWORD bufsize = *(const WORD*)&pFormat[6]; + USER_MARSHAL_CB umcb; + unsigned long saved_buffer_length = 0; + + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + TRACE("index=%d\n", index); + + UserMarshalCB(pStubMsg, USER_MARSHAL_CB_BUFFER_SIZE, pFormat, &umcb); + + if (flags & USER_MARSHAL_POINTER) + { + ALIGN_LENGTH(pStubMsg->BufferLength, 4); + /* skip pointer prefix */ + safe_buffer_length_increment(pStubMsg, 4); + if (pStubMsg->IgnoreEmbeddedPointers) + return; + if (pStubMsg->PointerLength) + { + saved_buffer_length = pStubMsg->BufferLength; + pStubMsg->BufferLength = pStubMsg->PointerLength; + pStubMsg->PointerLength = 0; + } + ALIGN_LENGTH(pStubMsg->BufferLength, 8); + } + else + ALIGN_LENGTH(pStubMsg->BufferLength, (flags & 0xf) + 1); + + if (bufsize) { + TRACE("size=%d\n", bufsize); + safe_buffer_length_increment(pStubMsg, bufsize); + } + else + pStubMsg->BufferLength = + pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnBufferSize( + &umcb.Flags, pStubMsg->BufferLength, pMemory); + + if (saved_buffer_length) + { + pStubMsg->PointerLength = pStubMsg->BufferLength; + pStubMsg->BufferLength = saved_buffer_length; + } + +} + +/*********************************************************************** + * NdrUserMarshalMemorySize [RPCRT4.@] + */ +ULONG WINAPI NdrUserMarshalMemorySize(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + unsigned flags = pFormat[1]; + unsigned index = *(const WORD*)&pFormat[2]; + DWORD memsize = *(const WORD*)&pFormat[4]; + DWORD bufsize = *(const WORD*)&pFormat[6]; + + TRACE("(%p,%p)\n", pStubMsg, pFormat); + TRACE("index=%d\n", index); + + pStubMsg->MemorySize += memsize; + + if (flags & USER_MARSHAL_POINTER) + { + ALIGN_POINTER(pStubMsg->Buffer, 4); + /* skip pointer prefix */ + pStubMsg->Buffer += 4; + if (pStubMsg->IgnoreEmbeddedPointers) + return pStubMsg->MemorySize; + ALIGN_POINTER(pStubMsg->Buffer, 8); + } + else + ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1); + + if (!bufsize) + FIXME("not implemented for varying buffer size\n"); + + pStubMsg->Buffer += bufsize; + + return pStubMsg->MemorySize; +} + +/*********************************************************************** + * NdrUserMarshalFree [RPCRT4.@] + */ +void WINAPI NdrUserMarshalFree(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ +/* unsigned flags = pFormat[1]; */ + unsigned index = *(const WORD*)&pFormat[2]; + USER_MARSHAL_CB umcb; + + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + TRACE("index=%d\n", index); + + UserMarshalCB(pStubMsg, USER_MARSHAL_CB_FREE, pFormat, &umcb); + + pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnFree( + &umcb.Flags, pMemory); +} + +/*********************************************************************** + * NdrClearOutParameters [RPCRT4.@] + */ +void WINAPI NdrClearOutParameters(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat, + void *ArgAddr) +{ + FIXME("(%p,%p,%p): stub\n", pStubMsg, pFormat, ArgAddr); +} + +/*********************************************************************** + * NdrConvert [RPCRT4.@] + */ +void WINAPI NdrConvert( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat ) +{ + FIXME("(pStubMsg == ^%p, pFormat == ^%p): stub.\n", pStubMsg, pFormat); + /* FIXME: since this stub doesn't do any converting, the proper behavior + is to raise an exception */ +} + +/*********************************************************************** + * NdrConvert2 [RPCRT4.@] + */ +void WINAPI NdrConvert2( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, LONG NumberParams ) +{ + FIXME("(pStubMsg == ^%p, pFormat == ^%p, NumberParams == %d): stub.\n", + pStubMsg, pFormat, NumberParams); + /* FIXME: since this stub doesn't do any converting, the proper behavior + is to raise an exception */ +} + +#include "pshpack1.h" +typedef struct _NDR_CSTRUCT_FORMAT +{ + unsigned char type; + unsigned char alignment; + unsigned short memory_size; + short offset_to_array_description; +} NDR_CSTRUCT_FORMAT, NDR_CVSTRUCT_FORMAT; +#include "poppack.h" + +/*********************************************************************** + * NdrConformantStructMarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrConformantStructMarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat; + PFORMAT_STRING pCArrayFormat; + ULONG esize, bufsize; + + TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); + + pFormat += sizeof(NDR_CSTRUCT_FORMAT); + if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT)) + { + ERR("invalid format type %x\n", pCStructFormat->type); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return NULL; + } + + pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description + + pCStructFormat->offset_to_array_description; + if (*pCArrayFormat != RPC_FC_CARRAY) + { + ERR("invalid array format type %x\n", pCStructFormat->type); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return NULL; + } + esize = *(const WORD*)(pCArrayFormat+2); + + ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size, + pCArrayFormat + 4, 0); + + WriteConformance(pStubMsg); + + ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pCStructFormat->alignment + 1); + + TRACE("memory_size = %d\n", pCStructFormat->memory_size); + + bufsize = safe_multiply(esize, pStubMsg->MaxCount); + if (pCStructFormat->memory_size + bufsize < pCStructFormat->memory_size) /* integer overflow */ + { + ERR("integer overflow of memory_size %u with bufsize %u\n", + pCStructFormat->memory_size, bufsize); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + /* copy constant sized part of struct */ + pStubMsg->BufferMark = pStubMsg->Buffer; + safe_copy_to_buffer(pStubMsg, pMemory, pCStructFormat->memory_size + bufsize); + + if (pCStructFormat->type == RPC_FC_CPSTRUCT) + EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat); + + return NULL; +} + +/*********************************************************************** + * NdrConformantStructUnmarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrConformantStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char **ppMemory, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) +{ + const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat; + PFORMAT_STRING pCArrayFormat; + ULONG esize, bufsize; + unsigned char *saved_buffer; + + TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); + + pFormat += sizeof(NDR_CSTRUCT_FORMAT); + if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT)) + { + ERR("invalid format type %x\n", pCStructFormat->type); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return NULL; + } + pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description + + pCStructFormat->offset_to_array_description; + if (*pCArrayFormat != RPC_FC_CARRAY) + { + ERR("invalid array format type %x\n", pCStructFormat->type); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return NULL; + } + esize = *(const WORD*)(pCArrayFormat+2); + + pCArrayFormat = ReadConformance(pStubMsg, pCArrayFormat + 4); + + ALIGN_POINTER(pStubMsg->Buffer, pCStructFormat->alignment + 1); + + TRACE("memory_size = %d\n", pCStructFormat->memory_size); + + bufsize = safe_multiply(esize, pStubMsg->MaxCount); + if (pCStructFormat->memory_size + bufsize < pCStructFormat->memory_size) /* integer overflow */ + { + ERR("integer overflow of memory_size %u with bufsize %u\n", + pCStructFormat->memory_size, bufsize); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + + if (fMustAlloc) + { + SIZE_T size = pCStructFormat->memory_size + bufsize; + *ppMemory = NdrAllocate(pStubMsg, size); + } + else + { + if (!pStubMsg->IsClient && !*ppMemory) + /* for servers, we just point straight into the RPC buffer */ + *ppMemory = pStubMsg->Buffer; + } + + saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer; + safe_buffer_increment(pStubMsg, pCStructFormat->memory_size + bufsize); + if (pCStructFormat->type == RPC_FC_CPSTRUCT) + EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc); + + TRACE("copying %p to %p\n", saved_buffer, *ppMemory); + if (*ppMemory != saved_buffer) + memcpy(*ppMemory, saved_buffer, pCStructFormat->memory_size + bufsize); + + return NULL; +} + +/*********************************************************************** + * NdrConformantStructBufferSize [RPCRT4.@] + */ +void WINAPI NdrConformantStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + const NDR_CSTRUCT_FORMAT * pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat; + PFORMAT_STRING pCArrayFormat; + ULONG esize; + + TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); + + pFormat += sizeof(NDR_CSTRUCT_FORMAT); + if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT)) + { + ERR("invalid format type %x\n", pCStructFormat->type); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return; + } + pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description + + pCStructFormat->offset_to_array_description; + if (*pCArrayFormat != RPC_FC_CARRAY) + { + ERR("invalid array format type %x\n", pCStructFormat->type); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return; + } + esize = *(const WORD*)(pCArrayFormat+2); + + pCArrayFormat = ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size, pCArrayFormat+4, 0); + SizeConformance(pStubMsg); + + ALIGN_LENGTH(pStubMsg->BufferLength, pCStructFormat->alignment + 1); + + TRACE("memory_size = %d\n", pCStructFormat->memory_size); + + safe_buffer_length_increment(pStubMsg, pCStructFormat->memory_size); + safe_buffer_length_increment(pStubMsg, safe_multiply(pStubMsg->MaxCount, esize)); + + if (pCStructFormat->type == RPC_FC_CPSTRUCT) + EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat); +} + +/*********************************************************************** + * NdrConformantStructMemorySize [RPCRT4.@] + */ +ULONG WINAPI NdrConformantStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + FIXME("stub\n"); + return 0; +} + +/*********************************************************************** + * NdrConformantStructFree [RPCRT4.@] + */ +void WINAPI NdrConformantStructFree(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat; + PFORMAT_STRING pCArrayFormat; + ULONG esize; + + TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); + + pFormat += sizeof(NDR_CSTRUCT_FORMAT); + if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT)) + { + ERR("invalid format type %x\n", pCStructFormat->type); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return; + } + + pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description + + pCStructFormat->offset_to_array_description; + if (*pCArrayFormat != RPC_FC_CARRAY) + { + ERR("invalid array format type %x\n", pCStructFormat->type); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return; + } + esize = *(const WORD*)(pCArrayFormat+2); + + ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size, + pCArrayFormat + 4, 0); + + TRACE("memory_size = %d\n", pCStructFormat->memory_size); + + /* copy constant sized part of struct */ + pStubMsg->BufferMark = pStubMsg->Buffer; + + if (pCStructFormat->type == RPC_FC_CPSTRUCT) + EmbeddedPointerFree(pStubMsg, pMemory, pFormat); +} + +/*********************************************************************** + * NdrConformantVaryingStructMarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrConformantVaryingStructMarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat; + PFORMAT_STRING pCVArrayFormat; + ULONG esize, bufsize; + + TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); + + pFormat += sizeof(NDR_CVSTRUCT_FORMAT); + if (pCVStructFormat->type != RPC_FC_CVSTRUCT) + { + ERR("invalid format type %x\n", pCVStructFormat->type); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return NULL; + } + + pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description + + pCVStructFormat->offset_to_array_description; + switch (*pCVArrayFormat) + { + case RPC_FC_CVARRAY: + esize = *(const WORD*)(pCVArrayFormat+2); + + pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size, + pCVArrayFormat + 4, 0); + pCVArrayFormat = ComputeVariance(pStubMsg, pMemory + pCVStructFormat->memory_size, + pCVArrayFormat, 0); + break; + case RPC_FC_C_CSTRING: + TRACE("string=%s\n", debugstr_a((char*)pMemory + pCVStructFormat->memory_size)); + pStubMsg->ActualCount = strlen((char*)pMemory + pCVStructFormat->memory_size)+1; + esize = sizeof(char); + if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) + pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size, + pCVArrayFormat + 2, 0); + else + pStubMsg->MaxCount = pStubMsg->ActualCount; + break; + case RPC_FC_C_WSTRING: + TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory + pCVStructFormat->memory_size)); + pStubMsg->ActualCount = strlenW((LPWSTR)pMemory + pCVStructFormat->memory_size)+1; + esize = sizeof(WCHAR); + if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) + pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size, + pCVArrayFormat + 2, 0); + else + pStubMsg->MaxCount = pStubMsg->ActualCount; + break; + default: + ERR("invalid array format type %x\n", *pCVArrayFormat); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return NULL; + } + + WriteConformance(pStubMsg); + + ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pCVStructFormat->alignment + 1); + + TRACE("memory_size = %d\n", pCVStructFormat->memory_size); + + /* write constant sized part */ + pStubMsg->BufferMark = pStubMsg->Buffer; + safe_copy_to_buffer(pStubMsg, pMemory, pCVStructFormat->memory_size); + + WriteVariance(pStubMsg); + + bufsize = safe_multiply(esize, pStubMsg->ActualCount); + + /* write array part */ + safe_copy_to_buffer(pStubMsg, pMemory + pCVStructFormat->memory_size, bufsize); + + EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat); + + return NULL; +} + +/*********************************************************************** + * NdrConformantVaryingStructUnmarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrConformantVaryingStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char **ppMemory, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) +{ + const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat; + PFORMAT_STRING pCVArrayFormat; + ULONG esize, bufsize; + unsigned char cvarray_type; + + TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); + + pFormat += sizeof(NDR_CVSTRUCT_FORMAT); + if (pCVStructFormat->type != RPC_FC_CVSTRUCT) + { + ERR("invalid format type %x\n", pCVStructFormat->type); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return NULL; + } + + pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description + + pCVStructFormat->offset_to_array_description; + cvarray_type = *pCVArrayFormat; + switch (cvarray_type) + { + case RPC_FC_CVARRAY: + esize = *(const WORD*)(pCVArrayFormat+2); + pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 4); + break; + case RPC_FC_C_CSTRING: + esize = sizeof(char); + if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) + pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2); + else + pCVArrayFormat = ReadConformance(pStubMsg, NULL); + break; + case RPC_FC_C_WSTRING: + esize = sizeof(WCHAR); + if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) + pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2); + else + pCVArrayFormat = ReadConformance(pStubMsg, NULL); + break; + default: + ERR("invalid array format type %x\n", *pCVArrayFormat); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return NULL; + } + + ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1); + + TRACE("memory_size = %d\n", pCVStructFormat->memory_size); + + /* work out how much memory to allocate if we need to do so */ + if (!*ppMemory || fMustAlloc) + { + SIZE_T size = pCVStructFormat->memory_size + safe_multiply(esize, pStubMsg->MaxCount); + *ppMemory = NdrAllocate(pStubMsg, size); + } + + /* copy the constant data */ + pStubMsg->BufferMark = pStubMsg->Buffer; + safe_copy_from_buffer(pStubMsg, *ppMemory, pCVStructFormat->memory_size); + + pCVArrayFormat = ReadVariance(pStubMsg, pCVArrayFormat, pStubMsg->MaxCount); + + bufsize = safe_multiply(esize, pStubMsg->ActualCount); + + if ((cvarray_type == RPC_FC_C_CSTRING) || + (cvarray_type == RPC_FC_C_WSTRING)) + { + ULONG i; + /* strings must always have null terminating bytes */ + if (bufsize < esize) + { + ERR("invalid string length of %d\n", pStubMsg->ActualCount); + RpcRaiseException(RPC_S_INVALID_BOUND); + return NULL; + } + for (i = bufsize - esize; i < bufsize; i++) + if (pStubMsg->Buffer[i] != 0) + { + ERR("string not null-terminated at byte position %d, data is 0x%x\n", + i, pStubMsg->Buffer[i]); + RpcRaiseException(RPC_S_INVALID_BOUND); + return NULL; + } + } + + /* copy the array data */ + safe_copy_from_buffer(pStubMsg, *ppMemory + pCVStructFormat->memory_size, bufsize); + + if (cvarray_type == RPC_FC_C_CSTRING) + TRACE("string=%s\n", debugstr_a((char *)(*ppMemory + pCVStructFormat->memory_size))); + else if (cvarray_type == RPC_FC_C_WSTRING) + TRACE("string=%s\n", debugstr_w((WCHAR *)(*ppMemory + pCVStructFormat->memory_size))); + + EmbeddedPointerUnmarshall(pStubMsg, *ppMemory, *ppMemory, pFormat, TRUE /* FIXME */); + + return NULL; +} + +/*********************************************************************** + * NdrConformantVaryingStructBufferSize [RPCRT4.@] + */ +void WINAPI NdrConformantVaryingStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat; + PFORMAT_STRING pCVArrayFormat; + ULONG esize; + + TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); + + pFormat += sizeof(NDR_CVSTRUCT_FORMAT); + if (pCVStructFormat->type != RPC_FC_CVSTRUCT) + { + ERR("invalid format type %x\n", pCVStructFormat->type); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return; + } + + pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description + + pCVStructFormat->offset_to_array_description; + switch (*pCVArrayFormat) + { + case RPC_FC_CVARRAY: + esize = *(const WORD*)(pCVArrayFormat+2); + + pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size, + pCVArrayFormat + 4, 0); + pCVArrayFormat = ComputeVariance(pStubMsg, pMemory + pCVStructFormat->memory_size, + pCVArrayFormat, 0); + break; + case RPC_FC_C_CSTRING: + TRACE("string=%s\n", debugstr_a((char*)pMemory + pCVStructFormat->memory_size)); + pStubMsg->ActualCount = strlen((char*)pMemory + pCVStructFormat->memory_size)+1; + esize = sizeof(char); + if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) + pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size, + pCVArrayFormat + 2, 0); + else + pStubMsg->MaxCount = pStubMsg->ActualCount; + break; + case RPC_FC_C_WSTRING: + TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory + pCVStructFormat->memory_size)); + pStubMsg->ActualCount = strlenW((LPWSTR)pMemory + pCVStructFormat->memory_size)+1; + esize = sizeof(WCHAR); + if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) + pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size, + pCVArrayFormat + 2, 0); + else + pStubMsg->MaxCount = pStubMsg->ActualCount; + break; + default: + ERR("invalid array format type %x\n", *pCVArrayFormat); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return; + } + + SizeConformance(pStubMsg); + + ALIGN_LENGTH(pStubMsg->BufferLength, pCVStructFormat->alignment + 1); + + TRACE("memory_size = %d\n", pCVStructFormat->memory_size); + + safe_buffer_length_increment(pStubMsg, pCVStructFormat->memory_size); + SizeVariance(pStubMsg); + safe_buffer_length_increment(pStubMsg, safe_multiply(pStubMsg->MaxCount, esize)); + + EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat); +} + +/*********************************************************************** + * NdrConformantVaryingStructMemorySize [RPCRT4.@] + */ +ULONG WINAPI NdrConformantVaryingStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat; + PFORMAT_STRING pCVArrayFormat; + ULONG esize; + unsigned char cvarray_type; + + TRACE("(%p, %p)\n", pStubMsg, pFormat); + + pFormat += sizeof(NDR_CVSTRUCT_FORMAT); + if (pCVStructFormat->type != RPC_FC_CVSTRUCT) + { + ERR("invalid format type %x\n", pCVStructFormat->type); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return 0; + } + + pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description + + pCVStructFormat->offset_to_array_description; + cvarray_type = *pCVArrayFormat; + switch (cvarray_type) + { + case RPC_FC_CVARRAY: + esize = *(const WORD*)(pCVArrayFormat+2); + pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 4); + break; + case RPC_FC_C_CSTRING: + esize = sizeof(char); + if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) + pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2); + else + pCVArrayFormat = ReadConformance(pStubMsg, NULL); + break; + case RPC_FC_C_WSTRING: + esize = sizeof(WCHAR); + if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) + pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2); + else + pCVArrayFormat = ReadConformance(pStubMsg, NULL); + break; + default: + ERR("invalid array format type %x\n", *pCVArrayFormat); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return 0; + } + + ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1); + + TRACE("memory_size = %d\n", pCVStructFormat->memory_size); + + safe_buffer_increment(pStubMsg, pCVStructFormat->memory_size); + pCVArrayFormat = ReadVariance(pStubMsg, pCVArrayFormat, pStubMsg->MaxCount); + safe_buffer_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount)); + + pStubMsg->MemorySize += pCVStructFormat->memory_size + safe_multiply(esize, pStubMsg->MaxCount); + + EmbeddedPointerMemorySize(pStubMsg, pFormat); + + return pCVStructFormat->memory_size + pStubMsg->MaxCount * esize; +} + +/*********************************************************************** + * NdrConformantVaryingStructFree [RPCRT4.@] + */ +void WINAPI NdrConformantVaryingStructFree(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat; + PFORMAT_STRING pCVArrayFormat; + ULONG esize; + + TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); + + pFormat += sizeof(NDR_CVSTRUCT_FORMAT); + if (pCVStructFormat->type != RPC_FC_CVSTRUCT) + { + ERR("invalid format type %x\n", pCVStructFormat->type); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return; + } + + pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description + + pCVStructFormat->offset_to_array_description; + switch (*pCVArrayFormat) + { + case RPC_FC_CVARRAY: + esize = *(const WORD*)(pCVArrayFormat+2); + + pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size, + pCVArrayFormat + 4, 0); + pCVArrayFormat = ComputeVariance(pStubMsg, pMemory + pCVStructFormat->memory_size, + pCVArrayFormat, 0); + break; + case RPC_FC_C_CSTRING: + TRACE("string=%s\n", debugstr_a((char*)pMemory + pCVStructFormat->memory_size)); + pStubMsg->ActualCount = strlen((char*)pMemory + pCVStructFormat->memory_size)+1; + esize = sizeof(char); + if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) + pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size, + pCVArrayFormat + 2, 0); + else + pStubMsg->MaxCount = pStubMsg->ActualCount; + break; + case RPC_FC_C_WSTRING: + TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory + pCVStructFormat->memory_size)); + pStubMsg->ActualCount = strlenW((LPWSTR)pMemory + pCVStructFormat->memory_size)+1; + esize = sizeof(WCHAR); + if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) + pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size, + pCVArrayFormat + 2, 0); + else + pStubMsg->MaxCount = pStubMsg->ActualCount; + break; + default: + ERR("invalid array format type %x\n", *pCVArrayFormat); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return; + } + + TRACE("memory_size = %d\n", pCVStructFormat->memory_size); + + EmbeddedPointerFree(pStubMsg, pMemory, pFormat); +} + +#include "pshpack1.h" +typedef struct +{ + unsigned char type; + unsigned char alignment; + unsigned short total_size; +} NDR_SMFARRAY_FORMAT; + +typedef struct +{ + unsigned char type; + unsigned char alignment; + unsigned long total_size; +} NDR_LGFARRAY_FORMAT; +#include "poppack.h" + +/*********************************************************************** + * NdrFixedArrayMarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrFixedArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat; + unsigned long total_size; + + TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); + + if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) && + (pSmFArrayFormat->type != RPC_FC_LGFARRAY)) + { + ERR("invalid format type %x\n", pSmFArrayFormat->type); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return NULL; + } + + ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1); + + if (pSmFArrayFormat->type == RPC_FC_SMFARRAY) + { + total_size = pSmFArrayFormat->total_size; + pFormat = (const unsigned char *)(pSmFArrayFormat + 1); + } + else + { + const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat; + total_size = pLgFArrayFormat->total_size; + pFormat = (const unsigned char *)(pLgFArrayFormat + 1); + } + + pStubMsg->BufferMark = pStubMsg->Buffer; + safe_copy_to_buffer(pStubMsg, pMemory, total_size); + + pFormat = EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat); + + return NULL; +} + +/*********************************************************************** + * NdrFixedArrayUnmarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrFixedArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char **ppMemory, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) +{ + const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat; + unsigned long total_size; + unsigned char *saved_buffer; + + TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); + + if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) && + (pSmFArrayFormat->type != RPC_FC_LGFARRAY)) + { + ERR("invalid format type %x\n", pSmFArrayFormat->type); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return NULL; + } + + ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1); + + if (pSmFArrayFormat->type == RPC_FC_SMFARRAY) + { + total_size = pSmFArrayFormat->total_size; + pFormat = (const unsigned char *)(pSmFArrayFormat + 1); + } + else + { + const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat; + total_size = pLgFArrayFormat->total_size; + pFormat = (const unsigned char *)(pLgFArrayFormat + 1); + } + + if (fMustAlloc) + *ppMemory = NdrAllocate(pStubMsg, total_size); + else + { + if (!pStubMsg->IsClient && !*ppMemory) + /* for servers, we just point straight into the RPC buffer */ + *ppMemory = pStubMsg->Buffer; + } + + saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer; + safe_buffer_increment(pStubMsg, total_size); + pFormat = EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc); + + TRACE("copying %p to %p\n", saved_buffer, *ppMemory); + if (*ppMemory != saved_buffer) + memcpy(*ppMemory, saved_buffer, total_size); + + return NULL; +} + +/*********************************************************************** + * NdrFixedArrayBufferSize [RPCRT4.@] + */ +void WINAPI NdrFixedArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat; + unsigned long total_size; + + TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); + + if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) && + (pSmFArrayFormat->type != RPC_FC_LGFARRAY)) + { + ERR("invalid format type %x\n", pSmFArrayFormat->type); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return; + } + + ALIGN_LENGTH(pStubMsg->BufferLength, pSmFArrayFormat->alignment + 1); + + if (pSmFArrayFormat->type == RPC_FC_SMFARRAY) + { + total_size = pSmFArrayFormat->total_size; + pFormat = (const unsigned char *)(pSmFArrayFormat + 1); + } + else + { + const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat; + total_size = pLgFArrayFormat->total_size; + pFormat = (const unsigned char *)(pLgFArrayFormat + 1); + } + safe_buffer_length_increment(pStubMsg, total_size); + + EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat); +} + +/*********************************************************************** + * NdrFixedArrayMemorySize [RPCRT4.@] + */ +ULONG WINAPI NdrFixedArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat; + ULONG total_size; + + TRACE("(%p, %p)\n", pStubMsg, pFormat); + + if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) && + (pSmFArrayFormat->type != RPC_FC_LGFARRAY)) + { + ERR("invalid format type %x\n", pSmFArrayFormat->type); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return 0; + } + + ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1); + + if (pSmFArrayFormat->type == RPC_FC_SMFARRAY) + { + total_size = pSmFArrayFormat->total_size; + pFormat = (const unsigned char *)(pSmFArrayFormat + 1); + } + else + { + const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat; + total_size = pLgFArrayFormat->total_size; + pFormat = (const unsigned char *)(pLgFArrayFormat + 1); + } + pStubMsg->BufferMark = pStubMsg->Buffer; + safe_buffer_increment(pStubMsg, total_size); + pStubMsg->MemorySize += total_size; + + EmbeddedPointerMemorySize(pStubMsg, pFormat); + + return total_size; +} + +/*********************************************************************** + * NdrFixedArrayFree [RPCRT4.@] + */ +void WINAPI NdrFixedArrayFree(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat; + + TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); + + if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) && + (pSmFArrayFormat->type != RPC_FC_LGFARRAY)) + { + ERR("invalid format type %x\n", pSmFArrayFormat->type); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return; + } + + if (pSmFArrayFormat->type == RPC_FC_SMFARRAY) + pFormat = (const unsigned char *)(pSmFArrayFormat + 1); + else + { + const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat; + pFormat = (const unsigned char *)(pLgFArrayFormat + 1); + } + + EmbeddedPointerFree(pStubMsg, pMemory, pFormat); +} + +/*********************************************************************** + * NdrVaryingArrayMarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrVaryingArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + unsigned char alignment; + DWORD elements, esize; + ULONG bufsize; + + TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); + + if ((pFormat[0] != RPC_FC_SMVARRAY) && + (pFormat[0] != RPC_FC_LGVARRAY)) + { + ERR("invalid format type %x\n", pFormat[0]); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return NULL; + } + + alignment = pFormat[1] + 1; + + if (pFormat[0] == RPC_FC_SMVARRAY) + { + pFormat += 2; + pFormat += sizeof(WORD); + elements = *(const WORD*)pFormat; + pFormat += sizeof(WORD); + } + else + { + pFormat += 2; + pFormat += sizeof(DWORD); + elements = *(const DWORD*)pFormat; + pFormat += sizeof(DWORD); + } + + esize = *(const WORD*)pFormat; + pFormat += sizeof(WORD); + + pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0); + if ((pStubMsg->ActualCount > elements) || + (pStubMsg->ActualCount + pStubMsg->Offset > elements)) + { + RpcRaiseException(RPC_S_INVALID_BOUND); + return NULL; + } + + WriteVariance(pStubMsg); + + ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment); + + bufsize = safe_multiply(esize, pStubMsg->ActualCount); + pStubMsg->BufferMark = pStubMsg->Buffer; + safe_copy_to_buffer(pStubMsg, pMemory + pStubMsg->Offset, bufsize); + + EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat); + + return NULL; +} + +/*********************************************************************** + * NdrVaryingArrayUnmarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrVaryingArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char **ppMemory, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) +{ + unsigned char alignment; + DWORD size, elements, esize; + ULONG bufsize; + unsigned char *saved_buffer; + ULONG offset; + + TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); + + if ((pFormat[0] != RPC_FC_SMVARRAY) && + (pFormat[0] != RPC_FC_LGVARRAY)) + { + ERR("invalid format type %x\n", pFormat[0]); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return NULL; + } + + alignment = pFormat[1] + 1; + + if (pFormat[0] == RPC_FC_SMVARRAY) + { + pFormat += 2; + size = *(const WORD*)pFormat; + pFormat += sizeof(WORD); + elements = *(const WORD*)pFormat; + pFormat += sizeof(WORD); + } + else + { + pFormat += 2; + size = *(const DWORD*)pFormat; + pFormat += sizeof(DWORD); + elements = *(const DWORD*)pFormat; + pFormat += sizeof(DWORD); + } + + esize = *(const WORD*)pFormat; + pFormat += sizeof(WORD); + + pFormat = ReadVariance(pStubMsg, pFormat, elements); + + ALIGN_POINTER(pStubMsg->Buffer, alignment); + + bufsize = safe_multiply(esize, pStubMsg->ActualCount); + offset = pStubMsg->Offset; + + if (!*ppMemory || fMustAlloc) + *ppMemory = NdrAllocate(pStubMsg, size); + saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer; + safe_buffer_increment(pStubMsg, bufsize); + + EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc); + + memcpy(*ppMemory + offset, saved_buffer, bufsize); + + return NULL; +} + +/*********************************************************************** + * NdrVaryingArrayBufferSize [RPCRT4.@] + */ +void WINAPI NdrVaryingArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + unsigned char alignment; + DWORD elements, esize; + + TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); + + if ((pFormat[0] != RPC_FC_SMVARRAY) && + (pFormat[0] != RPC_FC_LGVARRAY)) + { + ERR("invalid format type %x\n", pFormat[0]); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return; + } + + alignment = pFormat[1] + 1; + + if (pFormat[0] == RPC_FC_SMVARRAY) + { + pFormat += 2; + pFormat += sizeof(WORD); + elements = *(const WORD*)pFormat; + pFormat += sizeof(WORD); + } + else + { + pFormat += 2; + pFormat += sizeof(DWORD); + elements = *(const DWORD*)pFormat; + pFormat += sizeof(DWORD); + } + + esize = *(const WORD*)pFormat; + pFormat += sizeof(WORD); + + pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0); + if ((pStubMsg->ActualCount > elements) || + (pStubMsg->ActualCount + pStubMsg->Offset > elements)) + { + RpcRaiseException(RPC_S_INVALID_BOUND); + return; + } + + SizeVariance(pStubMsg); + + ALIGN_LENGTH(pStubMsg->BufferLength, alignment); + + safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount)); + + EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat); +} + +/*********************************************************************** + * NdrVaryingArrayMemorySize [RPCRT4.@] + */ +ULONG WINAPI NdrVaryingArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + unsigned char alignment; + DWORD size, elements, esize; + + TRACE("(%p, %p)\n", pStubMsg, pFormat); + + if ((pFormat[0] != RPC_FC_SMVARRAY) && + (pFormat[0] != RPC_FC_LGVARRAY)) + { + ERR("invalid format type %x\n", pFormat[0]); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return 0; + } + + alignment = pFormat[1] + 1; + + if (pFormat[0] == RPC_FC_SMVARRAY) + { + pFormat += 2; + size = *(const WORD*)pFormat; + pFormat += sizeof(WORD); + elements = *(const WORD*)pFormat; + pFormat += sizeof(WORD); + } + else + { + pFormat += 2; + size = *(const DWORD*)pFormat; + pFormat += sizeof(DWORD); + elements = *(const DWORD*)pFormat; + pFormat += sizeof(DWORD); + } + + esize = *(const WORD*)pFormat; + pFormat += sizeof(WORD); + + pFormat = ReadVariance(pStubMsg, pFormat, elements); + + ALIGN_POINTER(pStubMsg->Buffer, alignment); + + safe_buffer_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount)); + pStubMsg->MemorySize += size; + + EmbeddedPointerMemorySize(pStubMsg, pFormat); + + return pStubMsg->MemorySize; +} + +/*********************************************************************** + * NdrVaryingArrayFree [RPCRT4.@] + */ +void WINAPI NdrVaryingArrayFree(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + unsigned char alignment; + DWORD elements; + + TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); + + if ((pFormat[0] != RPC_FC_SMVARRAY) && + (pFormat[0] != RPC_FC_LGVARRAY)) + { + ERR("invalid format type %x\n", pFormat[0]); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return; + } + + alignment = pFormat[1] + 1; + + if (pFormat[0] == RPC_FC_SMVARRAY) + { + pFormat += 2; + pFormat += sizeof(WORD); + elements = *(const WORD*)pFormat; + pFormat += sizeof(WORD); + } + else + { + pFormat += 2; + pFormat += sizeof(DWORD); + elements = *(const DWORD*)pFormat; + pFormat += sizeof(DWORD); + } + + pFormat += sizeof(WORD); + + pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0); + if ((pStubMsg->ActualCount > elements) || + (pStubMsg->ActualCount + pStubMsg->Offset > elements)) + { + RpcRaiseException(RPC_S_INVALID_BOUND); + return; + } + + EmbeddedPointerFree(pStubMsg, pMemory, pFormat); +} + +static ULONG get_discriminant(unsigned char fc, const unsigned char *pMemory) +{ + switch (fc) + { + case RPC_FC_BYTE: + case RPC_FC_CHAR: + case RPC_FC_SMALL: + case RPC_FC_USMALL: + return *(const UCHAR *)pMemory; + case RPC_FC_WCHAR: + case RPC_FC_SHORT: + case RPC_FC_USHORT: + case RPC_FC_ENUM16: + return *(const USHORT *)pMemory; + case RPC_FC_LONG: + case RPC_FC_ULONG: + case RPC_FC_ENUM32: + return *(const ULONG *)pMemory; + default: + FIXME("Unhandled base type: 0x%02x\n", fc); + return 0; + } +} + +static PFORMAT_STRING get_arm_offset_from_union_arm_selector(PMIDL_STUB_MESSAGE pStubMsg, + unsigned long discriminant, + PFORMAT_STRING pFormat) +{ + unsigned short num_arms, arm, type; + + num_arms = *(const SHORT*)pFormat & 0x0fff; + pFormat += 2; + for(arm = 0; arm < num_arms; arm++) + { + if(discriminant == *(const ULONG*)pFormat) + { + pFormat += 4; + break; + } + pFormat += 6; + } + + type = *(const unsigned short*)pFormat; + TRACE("type %04x\n", type); + if(arm == num_arms) /* default arm extras */ + { + if(type == 0xffff) + { + ERR("no arm for 0x%lx and no default case\n", discriminant); + RpcRaiseException(RPC_S_INVALID_TAG); + return NULL; + } + if(type == 0) + { + TRACE("falling back to empty default case for 0x%lx\n", discriminant); + return NULL; + } + } + return pFormat; +} + +static unsigned char *union_arm_marshall(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, ULONG discriminant, PFORMAT_STRING pFormat) +{ + unsigned short type; + + pFormat += 2; + + pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat); + if(!pFormat) + return NULL; + + type = *(const unsigned short*)pFormat; + if((type & 0xff00) == 0x8000) + { + unsigned char basetype = LOBYTE(type); + return NdrBaseTypeMarshall(pStubMsg, pMemory, &basetype); + } + else + { + PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat; + NDR_MARSHALL m = NdrMarshaller[*desc & NDR_TABLE_MASK]; + if (m) + { + unsigned char *saved_buffer = NULL; + int pointer_buffer_mark_set = 0; + switch(*desc) + { + case RPC_FC_RP: + case RPC_FC_UP: + case RPC_FC_OP: + case RPC_FC_FP: + ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4); + saved_buffer = pStubMsg->Buffer; + if (pStubMsg->PointerBufferMark) + { + pStubMsg->Buffer = pStubMsg->PointerBufferMark; + pStubMsg->PointerBufferMark = NULL; + pointer_buffer_mark_set = 1; + } + else + safe_buffer_increment(pStubMsg, 4); /* for pointer ID */ + + PointerMarshall(pStubMsg, saved_buffer, *(unsigned char **)pMemory, desc); + if (pointer_buffer_mark_set) + { + STD_OVERFLOW_CHECK(pStubMsg); + pStubMsg->PointerBufferMark = pStubMsg->Buffer; + if (saved_buffer + 4 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) + { + ERR("buffer overflow - saved_buffer = %p, BufferEnd = %p\n", + saved_buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + pStubMsg->Buffer = saved_buffer + 4; + } + break; + default: + m(pStubMsg, pMemory, desc); + } + } + else FIXME("no marshaller for embedded type %02x\n", *desc); + } + return NULL; +} + +static unsigned char *union_arm_unmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char **ppMemory, + ULONG discriminant, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) +{ + unsigned short type; + + pFormat += 2; + + pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat); + if(!pFormat) + return NULL; + + type = *(const unsigned short*)pFormat; + if((type & 0xff00) == 0x8000) + { + unsigned char basetype = LOBYTE(type); + return NdrBaseTypeUnmarshall(pStubMsg, ppMemory, &basetype, FALSE); + } + else + { + PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat; + NDR_UNMARSHALL m = NdrUnmarshaller[*desc & NDR_TABLE_MASK]; + if (m) + { + unsigned char *saved_buffer = NULL; + int pointer_buffer_mark_set = 0; + switch(*desc) + { + case RPC_FC_RP: + case RPC_FC_UP: + case RPC_FC_OP: + case RPC_FC_FP: + **(void***)ppMemory = NULL; + ALIGN_POINTER(pStubMsg->Buffer, 4); + saved_buffer = pStubMsg->Buffer; + if (pStubMsg->PointerBufferMark) + { + pStubMsg->Buffer = pStubMsg->PointerBufferMark; + pStubMsg->PointerBufferMark = NULL; + pointer_buffer_mark_set = 1; + } + else + pStubMsg->Buffer += 4; /* for pointer ID */ + + if (saved_buffer + 4 > pStubMsg->BufferEnd) + { + ERR("buffer overflow - saved_buffer = %p, BufferEnd = %p\n", + saved_buffer, pStubMsg->BufferEnd); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + + PointerUnmarshall(pStubMsg, saved_buffer, *(unsigned char ***)ppMemory, **(unsigned char ***)ppMemory, desc, fMustAlloc); + if (pointer_buffer_mark_set) + { + STD_OVERFLOW_CHECK(pStubMsg); + pStubMsg->PointerBufferMark = pStubMsg->Buffer; + pStubMsg->Buffer = saved_buffer + 4; + } + break; + default: + m(pStubMsg, ppMemory, desc, fMustAlloc); + } + } + else FIXME("no marshaller for embedded type %02x\n", *desc); + } + return NULL; +} + +static void union_arm_buffer_size(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + ULONG discriminant, + PFORMAT_STRING pFormat) +{ + unsigned short type; + + pFormat += 2; + + pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat); + if(!pFormat) + return; + + type = *(const unsigned short*)pFormat; + if((type & 0xff00) == 0x8000) + { + unsigned char basetype = LOBYTE(type); + NdrBaseTypeBufferSize(pStubMsg, pMemory, &basetype); + } + else + { + PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat; + NDR_BUFFERSIZE m = NdrBufferSizer[*desc & NDR_TABLE_MASK]; + if (m) + { + switch(*desc) + { + case RPC_FC_RP: + case RPC_FC_UP: + case RPC_FC_OP: + case RPC_FC_FP: + ALIGN_LENGTH(pStubMsg->BufferLength, 4); + safe_buffer_length_increment(pStubMsg, 4); /* for pointer ID */ + if (!pStubMsg->IgnoreEmbeddedPointers) + { + int saved_buffer_length = pStubMsg->BufferLength; + pStubMsg->BufferLength = pStubMsg->PointerLength; + pStubMsg->PointerLength = 0; + if(!pStubMsg->BufferLength) + ERR("BufferLength == 0??\n"); + PointerBufferSize(pStubMsg, *(unsigned char **)pMemory, desc); + pStubMsg->PointerLength = pStubMsg->BufferLength; + pStubMsg->BufferLength = saved_buffer_length; + } + break; + default: + m(pStubMsg, pMemory, desc); + } + } + else FIXME("no buffersizer for embedded type %02x\n", *desc); + } +} + +static ULONG union_arm_memory_size(PMIDL_STUB_MESSAGE pStubMsg, + ULONG discriminant, + PFORMAT_STRING pFormat) +{ + unsigned short type, size; + + size = *(const unsigned short*)pFormat; + pStubMsg->Memory += size; + pFormat += 2; + + pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat); + if(!pFormat) + return 0; + + type = *(const unsigned short*)pFormat; + if((type & 0xff00) == 0x8000) + { + return NdrBaseTypeMemorySize(pStubMsg, pFormat); + } + else + { + PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat; + NDR_MEMORYSIZE m = NdrMemorySizer[*desc & NDR_TABLE_MASK]; + unsigned char *saved_buffer; + if (m) + { + switch(*desc) + { + case RPC_FC_RP: + case RPC_FC_UP: + case RPC_FC_OP: + case RPC_FC_FP: + ALIGN_POINTER(pStubMsg->Buffer, 4); + saved_buffer = pStubMsg->Buffer; + safe_buffer_increment(pStubMsg, 4); + ALIGN_LENGTH(pStubMsg->MemorySize, 4); + pStubMsg->MemorySize += 4; + if (!pStubMsg->IgnoreEmbeddedPointers) + PointerMemorySize(pStubMsg, saved_buffer, pFormat); + break; + default: + return m(pStubMsg, desc); + } + } + else FIXME("no marshaller for embedded type %02x\n", *desc); + } + + TRACE("size %d\n", size); + return size; +} + +static void union_arm_free(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + ULONG discriminant, + PFORMAT_STRING pFormat) +{ + unsigned short type; + + pFormat += 2; + + pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat); + if(!pFormat) + return; + + type = *(const unsigned short*)pFormat; + if((type & 0xff00) != 0x8000) + { + PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat; + NDR_FREE m = NdrFreer[*desc & NDR_TABLE_MASK]; + if (m) + { + switch(*desc) + { + case RPC_FC_RP: + case RPC_FC_UP: + case RPC_FC_OP: + case RPC_FC_FP: + PointerFree(pStubMsg, *(unsigned char **)pMemory, desc); + break; + default: + m(pStubMsg, pMemory, desc); + } + } + else FIXME("no freer for embedded type %02x\n", *desc); + } +} + +/*********************************************************************** + * NdrEncapsulatedUnionMarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + unsigned char switch_type; + unsigned char increment; + ULONG switch_value; + + TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); + pFormat++; + + switch_type = *pFormat & 0xf; + increment = (*pFormat & 0xf0) >> 4; + pFormat++; + + ALIGN_POINTER_CLEAR(pStubMsg->Buffer, increment); + + switch_value = get_discriminant(switch_type, pMemory); + TRACE("got switch value 0x%x\n", switch_value); + + NdrBaseTypeMarshall(pStubMsg, pMemory, &switch_type); + pMemory += increment; + + return union_arm_marshall(pStubMsg, pMemory, switch_value, pFormat); +} + +/*********************************************************************** + * NdrEncapsulatedUnionUnmarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char **ppMemory, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) +{ + unsigned char switch_type; + unsigned char increment; + ULONG switch_value; + unsigned short size; + unsigned char *pMemoryArm; + + TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); + pFormat++; + + switch_type = *pFormat & 0xf; + increment = (*pFormat & 0xf0) >> 4; + pFormat++; + + ALIGN_POINTER(pStubMsg->Buffer, increment); + switch_value = get_discriminant(switch_type, pStubMsg->Buffer); + TRACE("got switch value 0x%x\n", switch_value); + + size = *(const unsigned short*)pFormat + increment; + if(!*ppMemory || fMustAlloc) + *ppMemory = NdrAllocate(pStubMsg, size); + + NdrBaseTypeUnmarshall(pStubMsg, ppMemory, &switch_type, FALSE); + pMemoryArm = *ppMemory + increment; + + return union_arm_unmarshall(pStubMsg, &pMemoryArm, switch_value, pFormat, fMustAlloc); +} + +/*********************************************************************** + * NdrEncapsulatedUnionBufferSize [RPCRT4.@] + */ +void WINAPI NdrEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + unsigned char switch_type; + unsigned char increment; + ULONG switch_value; + + TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); + pFormat++; + + switch_type = *pFormat & 0xf; + increment = (*pFormat & 0xf0) >> 4; + pFormat++; + + ALIGN_LENGTH(pStubMsg->BufferLength, increment); + switch_value = get_discriminant(switch_type, pMemory); + TRACE("got switch value 0x%x\n", switch_value); + + /* Add discriminant size */ + NdrBaseTypeBufferSize(pStubMsg, (unsigned char *)&switch_value, &switch_type); + pMemory += increment; + + union_arm_buffer_size(pStubMsg, pMemory, switch_value, pFormat); +} + +/*********************************************************************** + * NdrEncapsulatedUnionMemorySize [RPCRT4.@] + */ +ULONG WINAPI NdrEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + unsigned char switch_type; + unsigned char increment; + ULONG switch_value; + + switch_type = *pFormat & 0xf; + increment = (*pFormat & 0xf0) >> 4; + pFormat++; + + ALIGN_POINTER(pStubMsg->Buffer, increment); + switch_value = get_discriminant(switch_type, pStubMsg->Buffer); + TRACE("got switch value 0x%x\n", switch_value); + + pStubMsg->Memory += increment; + + return increment + union_arm_memory_size(pStubMsg, switch_value, pFormat + *(const SHORT*)pFormat); +} + +/*********************************************************************** + * NdrEncapsulatedUnionFree [RPCRT4.@] + */ +void WINAPI NdrEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + unsigned char switch_type; + unsigned char increment; + ULONG switch_value; + + TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); + pFormat++; + + switch_type = *pFormat & 0xf; + increment = (*pFormat & 0xf0) >> 4; + pFormat++; + + switch_value = get_discriminant(switch_type, pMemory); + TRACE("got switch value 0x%x\n", switch_value); + + pMemory += increment; + + return union_arm_free(pStubMsg, pMemory, switch_value, pFormat); +} + +/*********************************************************************** + * NdrNonEncapsulatedUnionMarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrNonEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + unsigned char switch_type; + + TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); + pFormat++; + + switch_type = *pFormat; + pFormat++; + + pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0); + TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount); + /* Marshall discriminant */ + NdrBaseTypeMarshall(pStubMsg, (unsigned char *)&pStubMsg->MaxCount, &switch_type); + + return union_arm_marshall(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat); +} + +static long unmarshall_discriminant(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING *ppFormat) +{ + long discriminant = 0; + + switch(**ppFormat) + { + case RPC_FC_BYTE: + case RPC_FC_CHAR: + case RPC_FC_SMALL: + case RPC_FC_USMALL: + { + UCHAR d; + safe_copy_from_buffer(pStubMsg, &d, sizeof(d)); + discriminant = d; + break; + } + case RPC_FC_WCHAR: + case RPC_FC_SHORT: + case RPC_FC_USHORT: + { + USHORT d; + ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT)); + safe_copy_from_buffer(pStubMsg, &d, sizeof(d)); + discriminant = d; + break; + } + case RPC_FC_LONG: + case RPC_FC_ULONG: + { + ULONG d; + ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONG)); + safe_copy_from_buffer(pStubMsg, &d, sizeof(d)); + discriminant = d; + break; + } + default: + FIXME("Unhandled base type: 0x%02x\n", **ppFormat); + } + (*ppFormat)++; + + if (pStubMsg->fHasNewCorrDesc) + *ppFormat += 6; + else + *ppFormat += 4; + return discriminant; +} + +/********************************************************************** + * NdrNonEncapsulatedUnionUnmarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrNonEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char **ppMemory, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) +{ + long discriminant; + unsigned short size; + + TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); + pFormat++; + + /* Unmarshall discriminant */ + discriminant = unmarshall_discriminant(pStubMsg, &pFormat); + TRACE("unmarshalled discriminant %lx\n", discriminant); + + pFormat += *(const SHORT*)pFormat; + + size = *(const unsigned short*)pFormat; + + if(!*ppMemory || fMustAlloc) + *ppMemory = NdrAllocate(pStubMsg, size); + + return union_arm_unmarshall(pStubMsg, ppMemory, discriminant, pFormat, fMustAlloc); +} + +/*********************************************************************** + * NdrNonEncapsulatedUnionBufferSize [RPCRT4.@] + */ +void WINAPI NdrNonEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + unsigned char switch_type; + + TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); + pFormat++; + + switch_type = *pFormat; + pFormat++; + + pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0); + TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount); + /* Add discriminant size */ + NdrBaseTypeBufferSize(pStubMsg, (unsigned char *)&pStubMsg->MaxCount, &switch_type); + + union_arm_buffer_size(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat); +} + +/*********************************************************************** + * NdrNonEncapsulatedUnionMemorySize [RPCRT4.@] + */ +ULONG WINAPI NdrNonEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + ULONG discriminant; + + pFormat++; + /* Unmarshall discriminant */ + discriminant = unmarshall_discriminant(pStubMsg, &pFormat); + TRACE("unmarshalled discriminant 0x%x\n", discriminant); + + return union_arm_memory_size(pStubMsg, discriminant, pFormat + *(const SHORT*)pFormat); +} + +/*********************************************************************** + * NdrNonEncapsulatedUnionFree [RPCRT4.@] + */ +void WINAPI NdrNonEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); + pFormat++; + pFormat++; + + pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0); + TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount); + + return union_arm_free(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat); +} + +/*********************************************************************** + * NdrByteCountPointerMarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrByteCountPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + FIXME("stub\n"); + return NULL; +} + +/*********************************************************************** + * NdrByteCountPointerUnmarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrByteCountPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char **ppMemory, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) +{ + FIXME("stub\n"); + return NULL; +} + +/*********************************************************************** + * NdrByteCountPointerBufferSize [RPCRT4.@] + */ +void WINAPI NdrByteCountPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + FIXME("stub\n"); +} + +/*********************************************************************** + * NdrByteCountPointerMemorySize [RPCRT4.@] + */ +ULONG WINAPI NdrByteCountPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + FIXME("stub\n"); + return 0; +} + +/*********************************************************************** + * NdrByteCountPointerFree [RPCRT4.@] + */ +void WINAPI NdrByteCountPointerFree(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + FIXME("stub\n"); +} + +/*********************************************************************** + * NdrXmitOrRepAsMarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrXmitOrRepAsMarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + FIXME("stub\n"); + return NULL; +} + +/*********************************************************************** + * NdrXmitOrRepAsUnmarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrXmitOrRepAsUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char **ppMemory, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) +{ + FIXME("stub\n"); + return NULL; +} + +/*********************************************************************** + * NdrXmitOrRepAsBufferSize [RPCRT4.@] + */ +void WINAPI NdrXmitOrRepAsBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + FIXME("stub\n"); +} + +/*********************************************************************** + * NdrXmitOrRepAsMemorySize [RPCRT4.@] + */ +ULONG WINAPI NdrXmitOrRepAsMemorySize(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + FIXME("stub\n"); + return 0; +} + +/*********************************************************************** + * NdrXmitOrRepAsFree [RPCRT4.@] + */ +void WINAPI NdrXmitOrRepAsFree(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + FIXME("stub\n"); +} + +#include "pshpack1.h" +typedef struct +{ + unsigned char type; + unsigned char flags_type; /* flags in upper nibble, type in lower nibble */ + ULONG low_value; + ULONG high_value; +} NDR_RANGE; +#include "poppack.h" + +/*********************************************************************** + * NdrRangeMarshall [internal] + */ +unsigned char *WINAPI NdrRangeMarshall( + PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + NDR_RANGE *pRange = (NDR_RANGE *)pFormat; + unsigned char base_type; + + TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat); + + if (pRange->type != RPC_FC_RANGE) + { + ERR("invalid format type %x\n", pRange->type); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return NULL; + } + + base_type = pRange->flags_type & 0xf; + + return NdrBaseTypeMarshall(pStubMsg, pMemory, &base_type); +} + +/*********************************************************************** + * NdrRangeUnmarshall + */ +unsigned char *WINAPI NdrRangeUnmarshall( + PMIDL_STUB_MESSAGE pStubMsg, + unsigned char **ppMemory, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) +{ + NDR_RANGE *pRange = (NDR_RANGE *)pFormat; + unsigned char base_type; + + TRACE("pStubMsg: %p, ppMemory: %p, type: 0x%02x, fMustAlloc: %s\n", pStubMsg, ppMemory, *pFormat, fMustAlloc ? "true" : "false"); + + if (pRange->type != RPC_FC_RANGE) + { + ERR("invalid format type %x\n", pRange->type); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return NULL; + } + base_type = pRange->flags_type & 0xf; + + TRACE("base_type = 0x%02x, low_value = %d, high_value = %d\n", + base_type, pRange->low_value, pRange->high_value); + +#define RANGE_UNMARSHALL(type, format_spec) \ + do \ + { \ + ALIGN_POINTER(pStubMsg->Buffer, sizeof(type)); \ + if (fMustAlloc || !*ppMemory) \ + *ppMemory = NdrAllocate(pStubMsg, sizeof(type)); \ + if (pStubMsg->Buffer + sizeof(type) > pStubMsg->BufferEnd) \ + { \ + ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n", \ + pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength); \ + RpcRaiseException(RPC_X_BAD_STUB_DATA); \ + } \ + if ((*(type *)pStubMsg->Buffer < (type)pRange->low_value) || \ + (*(type *)pStubMsg->Buffer > (type)pRange->high_value)) \ + { \ + ERR("value exceeded bounds: " format_spec ", low: " format_spec ", high: " format_spec "\n", \ + *(type *)pStubMsg->Buffer, (type)pRange->low_value, \ + (type)pRange->high_value); \ + RpcRaiseException(RPC_S_INVALID_BOUND); \ + return NULL; \ + } \ + TRACE("*ppMemory: %p\n", *ppMemory); \ + **(type **)ppMemory = *(type *)pStubMsg->Buffer; \ + pStubMsg->Buffer += sizeof(type); \ + } while (0) + + switch(base_type) + { + case RPC_FC_CHAR: + case RPC_FC_SMALL: + RANGE_UNMARSHALL(UCHAR, "%d"); + TRACE("value: 0x%02x\n", **(UCHAR **)ppMemory); + break; + case RPC_FC_BYTE: + case RPC_FC_USMALL: + RANGE_UNMARSHALL(CHAR, "%u"); + TRACE("value: 0x%02x\n", **(UCHAR **)ppMemory); + break; + case RPC_FC_WCHAR: /* FIXME: valid? */ + case RPC_FC_USHORT: + RANGE_UNMARSHALL(USHORT, "%u"); + TRACE("value: 0x%04x\n", **(USHORT **)ppMemory); + break; + case RPC_FC_SHORT: + RANGE_UNMARSHALL(SHORT, "%d"); + TRACE("value: 0x%04x\n", **(USHORT **)ppMemory); + break; + case RPC_FC_LONG: + RANGE_UNMARSHALL(LONG, "%d"); + TRACE("value: 0x%08x\n", **(ULONG **)ppMemory); + break; + case RPC_FC_ULONG: + RANGE_UNMARSHALL(ULONG, "%u"); + TRACE("value: 0x%08x\n", **(ULONG **)ppMemory); + break; + case RPC_FC_ENUM16: + case RPC_FC_ENUM32: + FIXME("Unhandled enum type\n"); + break; + case RPC_FC_ERROR_STATUS_T: /* FIXME: valid? */ + case RPC_FC_FLOAT: + case RPC_FC_DOUBLE: + case RPC_FC_HYPER: + default: + ERR("invalid range base type: 0x%02x\n", base_type); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + } + + return NULL; +} + +/*********************************************************************** + * NdrRangeBufferSize [internal] + */ +void WINAPI NdrRangeBufferSize( + PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + NDR_RANGE *pRange = (NDR_RANGE *)pFormat; + unsigned char base_type; + + TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat); + + if (pRange->type != RPC_FC_RANGE) + { + ERR("invalid format type %x\n", pRange->type); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + } + base_type = pRange->flags_type & 0xf; + + NdrBaseTypeBufferSize(pStubMsg, pMemory, &base_type); +} + +/*********************************************************************** + * NdrRangeMemorySize [internal] + */ +ULONG WINAPI NdrRangeMemorySize( + PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + NDR_RANGE *pRange = (NDR_RANGE *)pFormat; + unsigned char base_type; + + if (pRange->type != RPC_FC_RANGE) + { + ERR("invalid format type %x\n", pRange->type); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return 0; + } + base_type = pRange->flags_type & 0xf; + + return NdrBaseTypeMemorySize(pStubMsg, &base_type); +} + +/*********************************************************************** + * NdrRangeFree [internal] + */ +void WINAPI NdrRangeFree(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + TRACE("pStubMsg %p pMemory %p type 0x%02x\n", pStubMsg, pMemory, *pFormat); + + /* nothing to do */ +} + +/*********************************************************************** + * NdrBaseTypeMarshall [internal] + */ +static unsigned char *WINAPI NdrBaseTypeMarshall( + PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat); + + switch(*pFormat) + { + case RPC_FC_BYTE: + case RPC_FC_CHAR: + case RPC_FC_SMALL: + case RPC_FC_USMALL: + safe_copy_to_buffer(pStubMsg, pMemory, sizeof(UCHAR)); + TRACE("value: 0x%02x\n", *(UCHAR *)pMemory); + break; + case RPC_FC_WCHAR: + case RPC_FC_SHORT: + case RPC_FC_USHORT: + ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(USHORT)); + safe_copy_to_buffer(pStubMsg, pMemory, sizeof(USHORT)); + TRACE("value: 0x%04x\n", *(USHORT *)pMemory); + break; + case RPC_FC_LONG: + case RPC_FC_ULONG: + case RPC_FC_ERROR_STATUS_T: + case RPC_FC_ENUM32: + ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(ULONG)); + safe_copy_to_buffer(pStubMsg, pMemory, sizeof(ULONG)); + TRACE("value: 0x%08x\n", *(ULONG *)pMemory); + break; + case RPC_FC_FLOAT: + ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(float)); + safe_copy_to_buffer(pStubMsg, pMemory, sizeof(float)); + break; + case RPC_FC_DOUBLE: + ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(double)); + safe_copy_to_buffer(pStubMsg, pMemory, sizeof(double)); + break; + case RPC_FC_HYPER: + ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(ULONGLONG)); + safe_copy_to_buffer(pStubMsg, pMemory, sizeof(ULONGLONG)); + TRACE("value: %s\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory)); + break; + case RPC_FC_ENUM16: + /* only 16-bits on the wire, so do a sanity check */ + if (*(UINT *)pMemory > SHRT_MAX) + RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE); + ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(USHORT)); + if (pStubMsg->Buffer + sizeof(USHORT) > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) + RpcRaiseException(RPC_X_BAD_STUB_DATA); + *(USHORT *)pStubMsg->Buffer = *(UINT *)pMemory; + pStubMsg->Buffer += sizeof(USHORT); + TRACE("value: 0x%04x\n", *(UINT *)pMemory); + break; + case RPC_FC_IGNORE: + break; + default: + FIXME("Unhandled base type: 0x%02x\n", *pFormat); + } + + /* FIXME: what is the correct return value? */ + return NULL; +} + +/*********************************************************************** + * NdrBaseTypeUnmarshall [internal] + */ +static unsigned char *WINAPI NdrBaseTypeUnmarshall( + PMIDL_STUB_MESSAGE pStubMsg, + unsigned char **ppMemory, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) +{ + TRACE("pStubMsg: %p, ppMemory: %p, type: 0x%02x, fMustAlloc: %s\n", pStubMsg, ppMemory, *pFormat, fMustAlloc ? "true" : "false"); + +#define BASE_TYPE_UNMARSHALL(type) \ + ALIGN_POINTER(pStubMsg->Buffer, sizeof(type)); \ + if (!fMustAlloc && !pStubMsg->IsClient && !*ppMemory) \ + { \ + *ppMemory = pStubMsg->Buffer; \ + TRACE("*ppMemory: %p\n", *ppMemory); \ + } \ + else \ + { \ + if (fMustAlloc) \ + *ppMemory = NdrAllocate(pStubMsg, sizeof(type)); \ + TRACE("*ppMemory: %p\n", *ppMemory); \ + **(type **)ppMemory = *(type *)pStubMsg->Buffer; \ + } \ + pStubMsg->Buffer += sizeof(type); + + switch(*pFormat) + { + case RPC_FC_BYTE: + case RPC_FC_CHAR: + case RPC_FC_SMALL: + case RPC_FC_USMALL: + BASE_TYPE_UNMARSHALL(UCHAR); + TRACE("value: 0x%02x\n", **(UCHAR **)ppMemory); + break; + case RPC_FC_WCHAR: + case RPC_FC_SHORT: + case RPC_FC_USHORT: + BASE_TYPE_UNMARSHALL(USHORT); + TRACE("value: 0x%04x\n", **(USHORT **)ppMemory); + break; + case RPC_FC_LONG: + case RPC_FC_ULONG: + case RPC_FC_ERROR_STATUS_T: + case RPC_FC_ENUM32: + BASE_TYPE_UNMARSHALL(ULONG); + TRACE("value: 0x%08x\n", **(ULONG **)ppMemory); + break; + case RPC_FC_FLOAT: + BASE_TYPE_UNMARSHALL(float); + TRACE("value: %f\n", **(float **)ppMemory); + break; + case RPC_FC_DOUBLE: + BASE_TYPE_UNMARSHALL(double); + TRACE("value: %f\n", **(double **)ppMemory); + break; + case RPC_FC_HYPER: + BASE_TYPE_UNMARSHALL(ULONGLONG); + TRACE("value: %s\n", wine_dbgstr_longlong(**(ULONGLONG **)ppMemory)); + break; + case RPC_FC_ENUM16: + ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT)); + if (fMustAlloc || !*ppMemory) + *ppMemory = NdrAllocate(pStubMsg, sizeof(UINT)); + if (pStubMsg->Buffer + sizeof(USHORT) > pStubMsg->BufferEnd) + RpcRaiseException(RPC_X_BAD_STUB_DATA); + TRACE("*ppMemory: %p\n", *ppMemory); + /* 16-bits on the wire, but int in memory */ + **(UINT **)ppMemory = *(USHORT *)pStubMsg->Buffer; + pStubMsg->Buffer += sizeof(USHORT); + TRACE("value: 0x%08x\n", **(UINT **)ppMemory); + break; + case RPC_FC_IGNORE: + break; + default: + FIXME("Unhandled base type: 0x%02x\n", *pFormat); + } +#undef BASE_TYPE_UNMARSHALL + + /* FIXME: what is the correct return value? */ + + return NULL; +} + +/*********************************************************************** + * NdrBaseTypeBufferSize [internal] + */ +static void WINAPI NdrBaseTypeBufferSize( + PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat); + + switch(*pFormat) + { + case RPC_FC_BYTE: + case RPC_FC_CHAR: + case RPC_FC_SMALL: + case RPC_FC_USMALL: + safe_buffer_length_increment(pStubMsg, sizeof(UCHAR)); + break; + case RPC_FC_WCHAR: + case RPC_FC_SHORT: + case RPC_FC_USHORT: + case RPC_FC_ENUM16: + ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(USHORT)); + safe_buffer_length_increment(pStubMsg, sizeof(USHORT)); + break; + case RPC_FC_LONG: + case RPC_FC_ULONG: + case RPC_FC_ENUM32: + ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(ULONG)); + safe_buffer_length_increment(pStubMsg, sizeof(ULONG)); + break; + case RPC_FC_FLOAT: + ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(float)); + safe_buffer_length_increment(pStubMsg, sizeof(float)); + break; + case RPC_FC_DOUBLE: + ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(double)); + safe_buffer_length_increment(pStubMsg, sizeof(double)); + break; + case RPC_FC_HYPER: + ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(ULONGLONG)); + safe_buffer_length_increment(pStubMsg, sizeof(ULONGLONG)); + break; + case RPC_FC_ERROR_STATUS_T: + ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(error_status_t)); + safe_buffer_length_increment(pStubMsg, sizeof(error_status_t)); + break; + case RPC_FC_IGNORE: + break; + default: + FIXME("Unhandled base type: 0x%02x\n", *pFormat); + } +} + +/*********************************************************************** + * NdrBaseTypeMemorySize [internal] + */ +static ULONG WINAPI NdrBaseTypeMemorySize( + PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + TRACE("pStubMsg %p, type 0x%02x\n", pStubMsg, *pFormat); + + switch(*pFormat) + { + case RPC_FC_BYTE: + case RPC_FC_CHAR: + case RPC_FC_SMALL: + case RPC_FC_USMALL: + safe_buffer_increment(pStubMsg, sizeof(UCHAR)); + pStubMsg->MemorySize += sizeof(UCHAR); + return sizeof(UCHAR); + case RPC_FC_WCHAR: + case RPC_FC_SHORT: + case RPC_FC_USHORT: + safe_buffer_increment(pStubMsg, sizeof(USHORT)); + pStubMsg->MemorySize += sizeof(USHORT); + return sizeof(USHORT); + case RPC_FC_LONG: + case RPC_FC_ULONG: + case RPC_FC_ENUM32: + safe_buffer_increment(pStubMsg, sizeof(ULONG)); + pStubMsg->MemorySize += sizeof(ULONG); + return sizeof(ULONG); + case RPC_FC_FLOAT: + safe_buffer_increment(pStubMsg, sizeof(float)); + pStubMsg->MemorySize += sizeof(float); + return sizeof(float); + case RPC_FC_DOUBLE: + safe_buffer_increment(pStubMsg, sizeof(double)); + pStubMsg->MemorySize += sizeof(double); + return sizeof(double); + case RPC_FC_HYPER: + safe_buffer_increment(pStubMsg, sizeof(ULONGLONG)); + pStubMsg->MemorySize += sizeof(ULONGLONG); + return sizeof(ULONGLONG); + case RPC_FC_ERROR_STATUS_T: + safe_buffer_increment(pStubMsg, sizeof(error_status_t)); + pStubMsg->MemorySize += sizeof(error_status_t); + return sizeof(error_status_t); + case RPC_FC_ENUM16: + safe_buffer_increment(pStubMsg, sizeof(USHORT)); + pStubMsg->MemorySize += sizeof(UINT); + return sizeof(UINT); + case RPC_FC_IGNORE: + pStubMsg->MemorySize += sizeof(void *); + return sizeof(void *); + default: + FIXME("Unhandled base type: 0x%02x\n", *pFormat); + return 0; + } +} + +/*********************************************************************** + * NdrBaseTypeFree [internal] + */ +static void WINAPI NdrBaseTypeFree(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + TRACE("pStubMsg %p pMemory %p type 0x%02x\n", pStubMsg, pMemory, *pFormat); + + /* nothing to do */ +} + +/*********************************************************************** + * NdrContextHandleBufferSize [internal] + */ +static void WINAPI NdrContextHandleBufferSize( + PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat); + + if (*pFormat != RPC_FC_BIND_CONTEXT) + { + ERR("invalid format type %x\n", *pFormat); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + } + ALIGN_LENGTH(pStubMsg->BufferLength, 4); + safe_buffer_length_increment(pStubMsg, cbNDRContext); +} + +/*********************************************************************** + * NdrContextHandleMarshall [internal] + */ +static unsigned char *WINAPI NdrContextHandleMarshall( + PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat); + + if (*pFormat != RPC_FC_BIND_CONTEXT) + { + ERR("invalid format type %x\n", *pFormat); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + } + + if (pFormat[1] & 0x80) + NdrClientContextMarshall(pStubMsg, *(NDR_CCONTEXT **)pMemory, FALSE); + else + NdrClientContextMarshall(pStubMsg, (NDR_CCONTEXT *)pMemory, FALSE); + + return NULL; +} + +/*********************************************************************** + * NdrContextHandleUnmarshall [internal] + */ +static unsigned char *WINAPI NdrContextHandleUnmarshall( + PMIDL_STUB_MESSAGE pStubMsg, + unsigned char **ppMemory, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) +{ + if (*pFormat != RPC_FC_BIND_CONTEXT) + { + ERR("invalid format type %x\n", *pFormat); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + } + + **(NDR_CCONTEXT **)ppMemory = NULL; + NdrClientContextUnmarshall(pStubMsg, *(NDR_CCONTEXT **)ppMemory, pStubMsg->RpcMsg->Handle); + + return NULL; +} + +/*********************************************************************** + * NdrClientContextMarshall [RPCRT4.@] + */ +void WINAPI NdrClientContextMarshall(PMIDL_STUB_MESSAGE pStubMsg, + NDR_CCONTEXT ContextHandle, + int fCheck) +{ + TRACE("(%p, %p, %d)\n", pStubMsg, ContextHandle, fCheck); + + ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4); + + if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) + { + ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n", + pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + + /* FIXME: what does fCheck do? */ + NDRCContextMarshall(ContextHandle, + pStubMsg->Buffer); + + pStubMsg->Buffer += cbNDRContext; +} + +/*********************************************************************** + * NdrClientContextUnmarshall [RPCRT4.@] + */ +void WINAPI NdrClientContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + NDR_CCONTEXT * pContextHandle, + RPC_BINDING_HANDLE BindHandle) +{ + TRACE("(%p, %p, %p)\n", pStubMsg, pContextHandle, BindHandle); + + ALIGN_POINTER(pStubMsg->Buffer, 4); + + if (pStubMsg->Buffer + cbNDRContext > pStubMsg->BufferEnd) + RpcRaiseException(RPC_X_BAD_STUB_DATA); + + NDRCContextUnmarshall(pContextHandle, + BindHandle, + pStubMsg->Buffer, + pStubMsg->RpcMsg->DataRepresentation); + + pStubMsg->Buffer += cbNDRContext; +} + +void WINAPI NdrServerContextMarshall(PMIDL_STUB_MESSAGE pStubMsg, + NDR_SCONTEXT ContextHandle, + NDR_RUNDOWN RundownRoutine ) +{ + TRACE("(%p, %p, %p)\n", pStubMsg, ContextHandle, RundownRoutine); + + ALIGN_POINTER(pStubMsg->Buffer, 4); + + if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) + { + ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n", + pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + + NDRSContextMarshall2(pStubMsg->RpcMsg->Handle, ContextHandle, + pStubMsg->Buffer, RundownRoutine, NULL, 0); + pStubMsg->Buffer += cbNDRContext; +} + +NDR_SCONTEXT WINAPI NdrServerContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg) +{ + NDR_SCONTEXT ContextHandle; + + TRACE("(%p)\n", pStubMsg); + + ALIGN_POINTER(pStubMsg->Buffer, 4); + + if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) + { + ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n", + pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + + ContextHandle = NDRSContextUnmarshall2(pStubMsg->RpcMsg->Handle, + pStubMsg->Buffer, + pStubMsg->RpcMsg->DataRepresentation, + NULL, 0); + pStubMsg->Buffer += cbNDRContext; + + return ContextHandle; +} + +void WINAPI NdrContextHandleSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char* pMemory, + PFORMAT_STRING pFormat) +{ + FIXME("(%p, %p, %p): stub\n", pStubMsg, pMemory, pFormat); +} + +NDR_SCONTEXT WINAPI NdrContextHandleInitialize(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + TRACE("(%p, %p)\n", pStubMsg, pFormat); + return NDRSContextUnmarshall2(pStubMsg->RpcMsg->Handle, NULL, + pStubMsg->RpcMsg->DataRepresentation, NULL, 0); +} + +void WINAPI NdrServerContextNewMarshall(PMIDL_STUB_MESSAGE pStubMsg, + NDR_SCONTEXT ContextHandle, + NDR_RUNDOWN RundownRoutine, + PFORMAT_STRING pFormat) +{ + TRACE("(%p, %p, %p, %p)\n", pStubMsg, ContextHandle, RundownRoutine, pFormat); + + ALIGN_POINTER(pStubMsg->Buffer, 4); + + if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) + { + ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n", + pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + + /* FIXME: do something with pFormat */ + NDRSContextMarshall2(pStubMsg->RpcMsg->Handle, ContextHandle, + pStubMsg->Buffer, RundownRoutine, NULL, 0); + pStubMsg->Buffer += cbNDRContext; +} + +NDR_SCONTEXT WINAPI NdrServerContextNewUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + NDR_SCONTEXT ContextHandle; + + TRACE("(%p, %p)\n", pStubMsg, pFormat); + + ALIGN_POINTER(pStubMsg->Buffer, 4); + + if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) + { + ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n", + pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + + /* FIXME: do something with pFormat */ + ContextHandle = NDRSContextUnmarshall2(pStubMsg->RpcMsg->Handle, + pStubMsg->Buffer, + pStubMsg->RpcMsg->DataRepresentation, + NULL, 0); + pStubMsg->Buffer += cbNDRContext; + + return ContextHandle; +} diff --git a/reactos/dll/win32/rpcrt4_new/ndr_misc.h b/reactos/dll/win32/rpcrt4_new/ndr_misc.h index ebd70b8d826..45dbd87624b 100644 --- a/reactos/dll/win32/rpcrt4_new/ndr_misc.h +++ b/reactos/dll/win32/rpcrt4_new/ndr_misc.h @@ -1,65 +1,65 @@ -/* - * NDR definitions - * - * Copyright 2001 Ove Kåven, TransGaming Technologies - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#ifndef __WINE_NDR_MISC_H -#define __WINE_NDR_MISC_H - -#include - -#include "windef.h" -#include "winbase.h" -#include "rpc.h" -#include "rpcndr.h" - -struct IPSFactoryBuffer; - -PFORMAT_STRING ComputeConformanceOrVariance( - MIDL_STUB_MESSAGE *pStubMsg, unsigned char *pMemory, - PFORMAT_STRING pFormat, ULONG_PTR def, ULONG_PTR *pCount); - -static inline PFORMAT_STRING ComputeConformance(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat, ULONG def) -{ - return ComputeConformanceOrVariance(pStubMsg, pMemory, pFormat, def, &pStubMsg->MaxCount); -} - -static inline PFORMAT_STRING ComputeVariance(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat, ULONG def) -{ - PFORMAT_STRING ret; - ULONG_PTR ActualCount = pStubMsg->ActualCount; - - pStubMsg->Offset = 0; - ret = ComputeConformanceOrVariance(pStubMsg, pMemory, pFormat, def, &ActualCount); - pStubMsg->ActualCount = (ULONG)ActualCount; - return ret; -} - -typedef unsigned char* (WINAPI *NDR_MARSHALL) (PMIDL_STUB_MESSAGE, unsigned char*, PFORMAT_STRING); -typedef unsigned char* (WINAPI *NDR_UNMARSHALL)(PMIDL_STUB_MESSAGE, unsigned char**,PFORMAT_STRING, unsigned char); -typedef void (WINAPI *NDR_BUFFERSIZE)(PMIDL_STUB_MESSAGE, unsigned char*, PFORMAT_STRING); -typedef ULONG (WINAPI *NDR_MEMORYSIZE)(PMIDL_STUB_MESSAGE, PFORMAT_STRING); -typedef void (WINAPI *NDR_FREE) (PMIDL_STUB_MESSAGE, unsigned char*, PFORMAT_STRING); - -extern const NDR_MARSHALL NdrMarshaller[]; -extern const NDR_UNMARSHALL NdrUnmarshaller[]; -extern const NDR_BUFFERSIZE NdrBufferSizer[]; -extern const NDR_MEMORYSIZE NdrMemorySizer[]; -extern const NDR_FREE NdrFreer[]; - -#endif /* __WINE_NDR_MISC_H */ +/* + * NDR definitions + * + * Copyright 2001 Ove Kåven, TransGaming Technologies + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __WINE_NDR_MISC_H +#define __WINE_NDR_MISC_H + +#include + +#include "windef.h" +#include "winbase.h" +#include "rpc.h" +#include "rpcndr.h" + +struct IPSFactoryBuffer; + +PFORMAT_STRING ComputeConformanceOrVariance( + MIDL_STUB_MESSAGE *pStubMsg, unsigned char *pMemory, + PFORMAT_STRING pFormat, ULONG_PTR def, ULONG_PTR *pCount); + +static inline PFORMAT_STRING ComputeConformance(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat, ULONG def) +{ + return ComputeConformanceOrVariance(pStubMsg, pMemory, pFormat, def, &pStubMsg->MaxCount); +} + +static inline PFORMAT_STRING ComputeVariance(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat, ULONG def) +{ + PFORMAT_STRING ret; + ULONG_PTR ActualCount = pStubMsg->ActualCount; + + pStubMsg->Offset = 0; + ret = ComputeConformanceOrVariance(pStubMsg, pMemory, pFormat, def, &ActualCount); + pStubMsg->ActualCount = (ULONG)ActualCount; + return ret; +} + +typedef unsigned char* (WINAPI *NDR_MARSHALL) (PMIDL_STUB_MESSAGE, unsigned char*, PFORMAT_STRING); +typedef unsigned char* (WINAPI *NDR_UNMARSHALL)(PMIDL_STUB_MESSAGE, unsigned char**,PFORMAT_STRING, unsigned char); +typedef void (WINAPI *NDR_BUFFERSIZE)(PMIDL_STUB_MESSAGE, unsigned char*, PFORMAT_STRING); +typedef ULONG (WINAPI *NDR_MEMORYSIZE)(PMIDL_STUB_MESSAGE, PFORMAT_STRING); +typedef void (WINAPI *NDR_FREE) (PMIDL_STUB_MESSAGE, unsigned char*, PFORMAT_STRING); + +extern const NDR_MARSHALL NdrMarshaller[]; +extern const NDR_UNMARSHALL NdrUnmarshaller[]; +extern const NDR_BUFFERSIZE NdrBufferSizer[]; +extern const NDR_MEMORYSIZE NdrMemorySizer[]; +extern const NDR_FREE NdrFreer[]; + +#endif /* __WINE_NDR_MISC_H */ diff --git a/reactos/dll/win32/rpcrt4_new/ndr_ole.c b/reactos/dll/win32/rpcrt4_new/ndr_ole.c index 0a8c1f22797..8b37432e1e7 100644 --- a/reactos/dll/win32/rpcrt4_new/ndr_ole.c +++ b/reactos/dll/win32/rpcrt4_new/ndr_ole.c @@ -1,393 +1,393 @@ -/* - * OLE32 callouts, COM interface marshalling - * - * Copyright 2001 Ove Kåven, TransGaming Technologies - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - * - * TODO: - * - fix the wire-protocol to match MS/RPC - * - finish RpcStream_Vtbl - */ - -#include -#include -#include - -#define COBJMACROS -#define NONAMELESSUNION -#define NONAMELESSSTRUCT - -#include "windef.h" -#include "winbase.h" -#include "winerror.h" - -#include "objbase.h" - -#include "ndr_misc.h" -#include "rpcndr.h" -#include "rpcproxy.h" -#include "wine/rpcfc.h" -#include "cpsf.h" - -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(ole); - -static HMODULE hOLE; - -static HRESULT (WINAPI *COM_GetMarshalSizeMax)(ULONG *,REFIID,LPUNKNOWN,DWORD,LPVOID,DWORD); -static HRESULT (WINAPI *COM_MarshalInterface)(LPSTREAM,REFIID,LPUNKNOWN,DWORD,LPVOID,DWORD); -static HRESULT (WINAPI *COM_UnmarshalInterface)(LPSTREAM,REFIID,LPVOID*); -static HRESULT (WINAPI *COM_ReleaseMarshalData)(LPSTREAM); -static HRESULT (WINAPI *COM_GetClassObject)(REFCLSID,DWORD,COSERVERINFO *,REFIID,LPVOID *); -static HRESULT (WINAPI *COM_GetPSClsid)(REFIID,CLSID *); -static LPVOID (WINAPI *COM_MemAlloc)(ULONG); -static void (WINAPI *COM_MemFree)(LPVOID); - -static HMODULE LoadCOM(void) -{ - if (hOLE) return hOLE; - hOLE = LoadLibraryA("OLE32.DLL"); - if (!hOLE) return 0; - COM_GetMarshalSizeMax = (LPVOID)GetProcAddress(hOLE, "CoGetMarshalSizeMax"); - COM_MarshalInterface = (LPVOID)GetProcAddress(hOLE, "CoMarshalInterface"); - COM_UnmarshalInterface = (LPVOID)GetProcAddress(hOLE, "CoUnmarshalInterface"); - COM_ReleaseMarshalData = (LPVOID)GetProcAddress(hOLE, "CoReleaseMarshalData"); - COM_GetClassObject = (LPVOID)GetProcAddress(hOLE, "CoGetClassObject"); - COM_GetPSClsid = (LPVOID)GetProcAddress(hOLE, "CoGetPSClsid"); - COM_MemAlloc = (LPVOID)GetProcAddress(hOLE, "CoTaskMemAlloc"); - COM_MemFree = (LPVOID)GetProcAddress(hOLE, "CoTaskMemFree"); - return hOLE; -} - -/* CoMarshalInterface/CoUnmarshalInterface works on streams, - * so implement a simple stream on top of the RPC buffer - * (which also implements the MInterfacePointer structure) */ -typedef struct RpcStreamImpl -{ - const IStreamVtbl *lpVtbl; - DWORD RefCount; - PMIDL_STUB_MESSAGE pMsg; - LPDWORD size; - char *data; - DWORD pos; -} RpcStreamImpl; - -static HRESULT WINAPI RpcStream_QueryInterface(LPSTREAM iface, - REFIID riid, - LPVOID *obj) -{ - RpcStreamImpl *This = (RpcStreamImpl *)iface; - if (IsEqualGUID(&IID_IUnknown, riid) || - IsEqualGUID(&IID_ISequentialStream, riid) || - IsEqualGUID(&IID_IStream, riid)) { - *obj = This; - This->RefCount++; - return S_OK; - } - return E_NOINTERFACE; -} - -static ULONG WINAPI RpcStream_AddRef(LPSTREAM iface) -{ - RpcStreamImpl *This = (RpcStreamImpl *)iface; - return ++(This->RefCount); -} - -static ULONG WINAPI RpcStream_Release(LPSTREAM iface) -{ - RpcStreamImpl *This = (RpcStreamImpl *)iface; - if (!--(This->RefCount)) { - TRACE("size=%d\n", *This->size); - This->pMsg->Buffer = (unsigned char*)This->data + *This->size; - HeapFree(GetProcessHeap(),0,This); - return 0; - } - return This->RefCount; -} - -static HRESULT WINAPI RpcStream_Read(LPSTREAM iface, - void *pv, - ULONG cb, - ULONG *pcbRead) -{ - RpcStreamImpl *This = (RpcStreamImpl *)iface; - HRESULT hr = S_OK; - if (This->pos + cb > *This->size) - { - cb = *This->size - This->pos; - hr = S_FALSE; - } - if (cb) { - memcpy(pv, This->data + This->pos, cb); - This->pos += cb; - } - if (pcbRead) *pcbRead = cb; - return hr; -} - -static HRESULT WINAPI RpcStream_Write(LPSTREAM iface, - const void *pv, - ULONG cb, - ULONG *pcbWritten) -{ - RpcStreamImpl *This = (RpcStreamImpl *)iface; - if (This->data + cb > (char *)This->pMsg->BufferEnd) - return STG_E_MEDIUMFULL; - memcpy(This->data + This->pos, pv, cb); - This->pos += cb; - if (This->pos > *This->size) *This->size = This->pos; - if (pcbWritten) *pcbWritten = cb; - return S_OK; -} - -static HRESULT WINAPI RpcStream_Seek(LPSTREAM iface, - LARGE_INTEGER move, - DWORD origin, - ULARGE_INTEGER *newPos) -{ - RpcStreamImpl *This = (RpcStreamImpl *)iface; - switch (origin) { - case STREAM_SEEK_SET: - This->pos = move.u.LowPart; - break; - case STREAM_SEEK_CUR: - This->pos = This->pos + move.u.LowPart; - break; - case STREAM_SEEK_END: - This->pos = *This->size + move.u.LowPart; - break; - default: - return STG_E_INVALIDFUNCTION; - } - if (newPos) { - newPos->u.LowPart = This->pos; - newPos->u.HighPart = 0; - } - return S_OK; -} - -static HRESULT WINAPI RpcStream_SetSize(LPSTREAM iface, - ULARGE_INTEGER newSize) -{ - RpcStreamImpl *This = (RpcStreamImpl *)iface; - *This->size = newSize.u.LowPart; - return S_OK; -} - -static const IStreamVtbl RpcStream_Vtbl = -{ - RpcStream_QueryInterface, - RpcStream_AddRef, - RpcStream_Release, - RpcStream_Read, - RpcStream_Write, - RpcStream_Seek, - RpcStream_SetSize, - NULL, /* CopyTo */ - NULL, /* Commit */ - NULL, /* Revert */ - NULL, /* LockRegion */ - NULL, /* UnlockRegion */ - NULL, /* Stat */ - NULL /* Clone */ -}; - -static LPSTREAM RpcStream_Create(PMIDL_STUB_MESSAGE pStubMsg, BOOL init) -{ - RpcStreamImpl *This; - This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(RpcStreamImpl)); - if (!This) return NULL; - This->lpVtbl = &RpcStream_Vtbl; - This->RefCount = 1; - This->pMsg = pStubMsg; - This->size = (LPDWORD)pStubMsg->Buffer; - This->data = (char*)(This->size + 1); - This->pos = 0; - if (init) *This->size = 0; - TRACE("init size=%d\n", *This->size); - return (LPSTREAM)This; -} - -static const IID* get_ip_iid(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat) -{ - const IID *riid; - if (!pFormat) return &IID_IUnknown; - TRACE("format=%02x %02x\n", pFormat[0], pFormat[1]); - if (pFormat[0] != RPC_FC_IP) FIXME("format=%d\n", pFormat[0]); - if (pFormat[1] == RPC_FC_CONSTANT_IID) { - riid = (const IID *)&pFormat[2]; - } else { - ComputeConformance(pStubMsg, pMemory, pFormat+2, 0); - riid = (const IID *)pStubMsg->MaxCount; - } - if (!riid) riid = &IID_IUnknown; - TRACE("got %s\n", debugstr_guid(riid)); - return riid; -} - -/*********************************************************************** - * NdrInterfacePointerMarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrInterfacePointerMarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - const IID *riid = get_ip_iid(pStubMsg, pMemory, pFormat); - LPSTREAM stream; - HRESULT hr; - - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - pStubMsg->MaxCount = 0; - if (!LoadCOM()) return NULL; - if (pStubMsg->Buffer + sizeof(DWORD) <= (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) { - stream = RpcStream_Create(pStubMsg, TRUE); - if (stream) { - if (pMemory) - hr = COM_MarshalInterface(stream, riid, (LPUNKNOWN)pMemory, - pStubMsg->dwDestContext, pStubMsg->pvDestContext, - MSHLFLAGS_NORMAL); - else - hr = S_OK; - - IStream_Release(stream); - if (FAILED(hr)) - RpcRaiseException(hr); - } - } - return NULL; -} - -/*********************************************************************** - * NdrInterfacePointerUnmarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrInterfacePointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char **ppMemory, - PFORMAT_STRING pFormat, - unsigned char fMustAlloc) -{ - LPSTREAM stream; - HRESULT hr; - - TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); - if (!LoadCOM()) return NULL; - *(LPVOID*)ppMemory = NULL; - if (pStubMsg->Buffer + sizeof(DWORD) < (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) { - stream = RpcStream_Create(pStubMsg, FALSE); - if (!stream) RpcRaiseException(E_OUTOFMEMORY); - if (*((RpcStreamImpl *)stream)->size != 0) - hr = COM_UnmarshalInterface(stream, &IID_NULL, (LPVOID*)ppMemory); - else - hr = S_OK; - IStream_Release(stream); - if (FAILED(hr)) - RpcRaiseException(hr); - } - return NULL; -} - -/*********************************************************************** - * NdrInterfacePointerBufferSize [RPCRT4.@] - */ -void WINAPI NdrInterfacePointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - const IID *riid = get_ip_iid(pStubMsg, pMemory, pFormat); - ULONG size = 0; - HRESULT hr; - - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - if (!LoadCOM()) return; - hr = COM_GetMarshalSizeMax(&size, riid, (LPUNKNOWN)pMemory, - pStubMsg->dwDestContext, pStubMsg->pvDestContext, - MSHLFLAGS_NORMAL); - TRACE("size=%d\n", size); - pStubMsg->BufferLength += sizeof(DWORD) + size; -} - -/*********************************************************************** - * NdrInterfacePointerMemorySize [RPCRT4.@] - */ -ULONG WINAPI NdrInterfacePointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat) -{ - ULONG size; - - TRACE("(%p,%p)\n", pStubMsg, pFormat); - - size = *(ULONG *)pStubMsg->Buffer; - pStubMsg->Buffer += 4; - pStubMsg->MemorySize += 4; - - pStubMsg->Buffer += size; - - return pStubMsg->MemorySize; -} - -/*********************************************************************** - * NdrInterfacePointerFree [RPCRT4.@] - */ -void WINAPI NdrInterfacePointerFree(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - LPUNKNOWN pUnk = (LPUNKNOWN)pMemory; - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - if (pUnk) IUnknown_Release(pUnk); -} - -/*********************************************************************** - * NdrOleAllocate [RPCRT4.@] - */ -void * WINAPI NdrOleAllocate(size_t Size) -{ - if (!LoadCOM()) return NULL; - return COM_MemAlloc(Size); -} - -/*********************************************************************** - * NdrOleFree [RPCRT4.@] - */ -void WINAPI NdrOleFree(void *NodeToFree) -{ - if (!LoadCOM()) return; - COM_MemFree(NodeToFree); -} - -/*********************************************************************** - * Helper function to create a stub. - * This probably looks very much like NdrpCreateStub. - */ -HRESULT create_stub(REFIID iid, IUnknown *pUnk, IRpcStubBuffer **ppstub) -{ - CLSID clsid; - IPSFactoryBuffer *psfac; - HRESULT r; - - if(!LoadCOM()) return E_FAIL; - - r = COM_GetPSClsid( iid, &clsid ); - if(FAILED(r)) return r; - - r = COM_GetClassObject( &clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IPSFactoryBuffer, (void**)&psfac ); - if(FAILED(r)) return r; - - r = IPSFactoryBuffer_CreateStub(psfac, iid, pUnk, ppstub); - - IPSFactoryBuffer_Release(psfac); - return r; -} +/* + * OLE32 callouts, COM interface marshalling + * + * Copyright 2001 Ove Kåven, TransGaming Technologies + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + * + * TODO: + * - fix the wire-protocol to match MS/RPC + * - finish RpcStream_Vtbl + */ + +#include +#include +#include + +#define COBJMACROS +#define NONAMELESSUNION +#define NONAMELESSSTRUCT + +#include "windef.h" +#include "winbase.h" +#include "winerror.h" + +#include "objbase.h" + +#include "ndr_misc.h" +#include "rpcndr.h" +#include "rpcproxy.h" +#include "wine/rpcfc.h" +#include "cpsf.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(ole); + +static HMODULE hOLE; + +static HRESULT (WINAPI *COM_GetMarshalSizeMax)(ULONG *,REFIID,LPUNKNOWN,DWORD,LPVOID,DWORD); +static HRESULT (WINAPI *COM_MarshalInterface)(LPSTREAM,REFIID,LPUNKNOWN,DWORD,LPVOID,DWORD); +static HRESULT (WINAPI *COM_UnmarshalInterface)(LPSTREAM,REFIID,LPVOID*); +static HRESULT (WINAPI *COM_ReleaseMarshalData)(LPSTREAM); +static HRESULT (WINAPI *COM_GetClassObject)(REFCLSID,DWORD,COSERVERINFO *,REFIID,LPVOID *); +static HRESULT (WINAPI *COM_GetPSClsid)(REFIID,CLSID *); +static LPVOID (WINAPI *COM_MemAlloc)(ULONG); +static void (WINAPI *COM_MemFree)(LPVOID); + +static HMODULE LoadCOM(void) +{ + if (hOLE) return hOLE; + hOLE = LoadLibraryA("OLE32.DLL"); + if (!hOLE) return 0; + COM_GetMarshalSizeMax = (LPVOID)GetProcAddress(hOLE, "CoGetMarshalSizeMax"); + COM_MarshalInterface = (LPVOID)GetProcAddress(hOLE, "CoMarshalInterface"); + COM_UnmarshalInterface = (LPVOID)GetProcAddress(hOLE, "CoUnmarshalInterface"); + COM_ReleaseMarshalData = (LPVOID)GetProcAddress(hOLE, "CoReleaseMarshalData"); + COM_GetClassObject = (LPVOID)GetProcAddress(hOLE, "CoGetClassObject"); + COM_GetPSClsid = (LPVOID)GetProcAddress(hOLE, "CoGetPSClsid"); + COM_MemAlloc = (LPVOID)GetProcAddress(hOLE, "CoTaskMemAlloc"); + COM_MemFree = (LPVOID)GetProcAddress(hOLE, "CoTaskMemFree"); + return hOLE; +} + +/* CoMarshalInterface/CoUnmarshalInterface works on streams, + * so implement a simple stream on top of the RPC buffer + * (which also implements the MInterfacePointer structure) */ +typedef struct RpcStreamImpl +{ + const IStreamVtbl *lpVtbl; + DWORD RefCount; + PMIDL_STUB_MESSAGE pMsg; + LPDWORD size; + unsigned char *data; + DWORD pos; +} RpcStreamImpl; + +static HRESULT WINAPI RpcStream_QueryInterface(LPSTREAM iface, + REFIID riid, + LPVOID *obj) +{ + RpcStreamImpl *This = (RpcStreamImpl *)iface; + if (IsEqualGUID(&IID_IUnknown, riid) || + IsEqualGUID(&IID_ISequentialStream, riid) || + IsEqualGUID(&IID_IStream, riid)) { + *obj = This; + This->RefCount++; + return S_OK; + } + return E_NOINTERFACE; +} + +static ULONG WINAPI RpcStream_AddRef(LPSTREAM iface) +{ + RpcStreamImpl *This = (RpcStreamImpl *)iface; + return ++(This->RefCount); +} + +static ULONG WINAPI RpcStream_Release(LPSTREAM iface) +{ + RpcStreamImpl *This = (RpcStreamImpl *)iface; + if (!--(This->RefCount)) { + TRACE("size=%d\n", *This->size); + This->pMsg->Buffer = (unsigned char*)This->data + *This->size; + HeapFree(GetProcessHeap(),0,This); + return 0; + } + return This->RefCount; +} + +static HRESULT WINAPI RpcStream_Read(LPSTREAM iface, + void *pv, + ULONG cb, + ULONG *pcbRead) +{ + RpcStreamImpl *This = (RpcStreamImpl *)iface; + HRESULT hr = S_OK; + if (This->pos + cb > *This->size) + { + cb = *This->size - This->pos; + hr = S_FALSE; + } + if (cb) { + memcpy(pv, This->data + This->pos, cb); + This->pos += cb; + } + if (pcbRead) *pcbRead = cb; + return hr; +} + +static HRESULT WINAPI RpcStream_Write(LPSTREAM iface, + const void *pv, + ULONG cb, + ULONG *pcbWritten) +{ + RpcStreamImpl *This = (RpcStreamImpl *)iface; + if (This->data + cb > (unsigned char *)This->pMsg->RpcMsg->Buffer + This->pMsg->BufferLength) + return STG_E_MEDIUMFULL; + memcpy(This->data + This->pos, pv, cb); + This->pos += cb; + if (This->pos > *This->size) *This->size = This->pos; + if (pcbWritten) *pcbWritten = cb; + return S_OK; +} + +static HRESULT WINAPI RpcStream_Seek(LPSTREAM iface, + LARGE_INTEGER move, + DWORD origin, + ULARGE_INTEGER *newPos) +{ + RpcStreamImpl *This = (RpcStreamImpl *)iface; + switch (origin) { + case STREAM_SEEK_SET: + This->pos = move.u.LowPart; + break; + case STREAM_SEEK_CUR: + This->pos = This->pos + move.u.LowPart; + break; + case STREAM_SEEK_END: + This->pos = *This->size + move.u.LowPart; + break; + default: + return STG_E_INVALIDFUNCTION; + } + if (newPos) { + newPos->u.LowPart = This->pos; + newPos->u.HighPart = 0; + } + return S_OK; +} + +static HRESULT WINAPI RpcStream_SetSize(LPSTREAM iface, + ULARGE_INTEGER newSize) +{ + RpcStreamImpl *This = (RpcStreamImpl *)iface; + *This->size = newSize.u.LowPart; + return S_OK; +} + +static const IStreamVtbl RpcStream_Vtbl = +{ + RpcStream_QueryInterface, + RpcStream_AddRef, + RpcStream_Release, + RpcStream_Read, + RpcStream_Write, + RpcStream_Seek, + RpcStream_SetSize, + NULL, /* CopyTo */ + NULL, /* Commit */ + NULL, /* Revert */ + NULL, /* LockRegion */ + NULL, /* UnlockRegion */ + NULL, /* Stat */ + NULL /* Clone */ +}; + +static LPSTREAM RpcStream_Create(PMIDL_STUB_MESSAGE pStubMsg, BOOL init) +{ + RpcStreamImpl *This; + This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(RpcStreamImpl)); + if (!This) return NULL; + This->lpVtbl = &RpcStream_Vtbl; + This->RefCount = 1; + This->pMsg = pStubMsg; + This->size = (LPDWORD)pStubMsg->Buffer; + This->data = (unsigned char*)(This->size + 1); + This->pos = 0; + if (init) *This->size = 0; + TRACE("init size=%d\n", *This->size); + return (LPSTREAM)This; +} + +static const IID* get_ip_iid(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat) +{ + const IID *riid; + if (!pFormat) return &IID_IUnknown; + TRACE("format=%02x %02x\n", pFormat[0], pFormat[1]); + if (pFormat[0] != RPC_FC_IP) FIXME("format=%d\n", pFormat[0]); + if (pFormat[1] == RPC_FC_CONSTANT_IID) { + riid = (const IID *)&pFormat[2]; + } else { + ComputeConformance(pStubMsg, pMemory, pFormat+2, 0); + riid = (const IID *)pStubMsg->MaxCount; + } + if (!riid) riid = &IID_IUnknown; + TRACE("got %s\n", debugstr_guid(riid)); + return riid; +} + +/*********************************************************************** + * NdrInterfacePointerMarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrInterfacePointerMarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + const IID *riid = get_ip_iid(pStubMsg, pMemory, pFormat); + LPSTREAM stream; + HRESULT hr; + + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + pStubMsg->MaxCount = 0; + if (!LoadCOM()) return NULL; + if (pStubMsg->Buffer + sizeof(DWORD) <= (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) { + stream = RpcStream_Create(pStubMsg, TRUE); + if (stream) { + if (pMemory) + hr = COM_MarshalInterface(stream, riid, (LPUNKNOWN)pMemory, + pStubMsg->dwDestContext, pStubMsg->pvDestContext, + MSHLFLAGS_NORMAL); + else + hr = S_OK; + + IStream_Release(stream); + if (FAILED(hr)) + RpcRaiseException(hr); + } + } + return NULL; +} + +/*********************************************************************** + * NdrInterfacePointerUnmarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrInterfacePointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char **ppMemory, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) +{ + LPSTREAM stream; + HRESULT hr; + + TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); + if (!LoadCOM()) return NULL; + *(LPVOID*)ppMemory = NULL; + if (pStubMsg->Buffer + sizeof(DWORD) < (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) { + stream = RpcStream_Create(pStubMsg, FALSE); + if (!stream) RpcRaiseException(E_OUTOFMEMORY); + if (*((RpcStreamImpl *)stream)->size != 0) + hr = COM_UnmarshalInterface(stream, &IID_NULL, (LPVOID*)ppMemory); + else + hr = S_OK; + IStream_Release(stream); + if (FAILED(hr)) + RpcRaiseException(hr); + } + return NULL; +} + +/*********************************************************************** + * NdrInterfacePointerBufferSize [RPCRT4.@] + */ +void WINAPI NdrInterfacePointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + const IID *riid = get_ip_iid(pStubMsg, pMemory, pFormat); + ULONG size = 0; + HRESULT hr; + + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + if (!LoadCOM()) return; + hr = COM_GetMarshalSizeMax(&size, riid, (LPUNKNOWN)pMemory, + pStubMsg->dwDestContext, pStubMsg->pvDestContext, + MSHLFLAGS_NORMAL); + TRACE("size=%d\n", size); + pStubMsg->BufferLength += sizeof(DWORD) + size; +} + +/*********************************************************************** + * NdrInterfacePointerMemorySize [RPCRT4.@] + */ +ULONG WINAPI NdrInterfacePointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + ULONG size; + + TRACE("(%p,%p)\n", pStubMsg, pFormat); + + size = *(ULONG *)pStubMsg->Buffer; + pStubMsg->Buffer += 4; + pStubMsg->MemorySize += 4; + + pStubMsg->Buffer += size; + + return pStubMsg->MemorySize; +} + +/*********************************************************************** + * NdrInterfacePointerFree [RPCRT4.@] + */ +void WINAPI NdrInterfacePointerFree(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + LPUNKNOWN pUnk = (LPUNKNOWN)pMemory; + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + if (pUnk) IUnknown_Release(pUnk); +} + +/*********************************************************************** + * NdrOleAllocate [RPCRT4.@] + */ +void * WINAPI NdrOleAllocate(size_t Size) +{ + if (!LoadCOM()) return NULL; + return COM_MemAlloc(Size); +} + +/*********************************************************************** + * NdrOleFree [RPCRT4.@] + */ +void WINAPI NdrOleFree(void *NodeToFree) +{ + if (!LoadCOM()) return; + COM_MemFree(NodeToFree); +} + +/*********************************************************************** + * Helper function to create a stub. + * This probably looks very much like NdrpCreateStub. + */ +HRESULT create_stub(REFIID iid, IUnknown *pUnk, IRpcStubBuffer **ppstub) +{ + CLSID clsid; + IPSFactoryBuffer *psfac; + HRESULT r; + + if(!LoadCOM()) return E_FAIL; + + r = COM_GetPSClsid( iid, &clsid ); + if(FAILED(r)) return r; + + r = COM_GetClassObject( &clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IPSFactoryBuffer, (void**)&psfac ); + if(FAILED(r)) return r; + + r = IPSFactoryBuffer_CreateStub(psfac, iid, pUnk, ppstub); + + IPSFactoryBuffer_Release(psfac); + return r; +} diff --git a/reactos/dll/win32/rpcrt4_new/ndr_stubless.c b/reactos/dll/win32/rpcrt4_new/ndr_stubless.c index 9eb25effa97..0ca78c554f0 100644 --- a/reactos/dll/win32/rpcrt4_new/ndr_stubless.c +++ b/reactos/dll/win32/rpcrt4_new/ndr_stubless.c @@ -1,1628 +1,1452 @@ -/* - * NDR -Oi,-Oif,-Oicf Interpreter - * - * Copyright 2001 Ove Kåven, TransGaming Technologies - * Copyright 2003-5 Robert Shearman (for CodeWeavers) - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - * - * TODO: - * - Pipes - * - Some types of binding handles - */ - -#include "config.h" -#include "wine/port.h" - -#include -#include -#include - -#include "windef.h" -#include "winbase.h" -#include "winerror.h" - -#include "objbase.h" -#include "rpc.h" -#include "rpcproxy.h" -#include "ndrtypes.h" - -#include "wine/debug.h" -#include "wine/rpcfc.h" - -#include "ndr_misc.h" -#include "cpsf.h" - -WINE_DEFAULT_DEBUG_CHANNEL(rpc); - -#define NDR_TABLE_MASK 127 - -static inline void call_buffer_sizer(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat) -{ - NDR_BUFFERSIZE m = NdrBufferSizer[pFormat[0] & NDR_TABLE_MASK]; - if (m) m(pStubMsg, pMemory, pFormat); - else - { - FIXME("format type 0x%x not implemented\n", pFormat[0]); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - } -} - -static inline unsigned char *call_marshaller(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat) -{ - NDR_MARSHALL m = NdrMarshaller[pFormat[0] & NDR_TABLE_MASK]; - if (m) return m(pStubMsg, pMemory, pFormat); - else - { - FIXME("format type 0x%x not implemented\n", pFormat[0]); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - return NULL; - } -} - -static inline unsigned char *call_unmarshaller(PMIDL_STUB_MESSAGE pStubMsg, unsigned char **ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc) -{ - NDR_UNMARSHALL m = NdrUnmarshaller[pFormat[0] & NDR_TABLE_MASK]; - if (m) return m(pStubMsg, ppMemory, pFormat, fMustAlloc); - else - { - FIXME("format type 0x%x not implemented\n", pFormat[0]); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - return NULL; - } -} - -static inline void call_freer(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat) -{ - NDR_FREE m = NdrFreer[pFormat[0] & NDR_TABLE_MASK]; - if (m) m(pStubMsg, pMemory, pFormat); -} - -static inline unsigned long call_memory_sizer(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat) -{ - NDR_MEMORYSIZE m = NdrMemorySizer[pFormat[0] & NDR_TABLE_MASK]; - if (m) - { - unsigned char *saved_buffer = pStubMsg->Buffer; - unsigned long ret; - int saved_ignore_embedded_pointers = pStubMsg->IgnoreEmbeddedPointers; - pStubMsg->MemorySize = 0; - pStubMsg->IgnoreEmbeddedPointers = 1; - ret = m(pStubMsg, pFormat); - pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded_pointers; - pStubMsg->Buffer = saved_buffer; - return ret; - } - else - { - FIXME("format type 0x%x not implemented\n", pFormat[0]); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - return 0; - } -} - -/* there can't be any alignment with the structures in this file */ -#include "pshpack1.h" - -#define STUBLESS_UNMARSHAL 1 -#define STUBLESS_CALLSERVER 2 -#define STUBLESS_CALCSIZE 3 -#define STUBLESS_GETBUFFER 4 -#define STUBLESS_MARSHAL 5 -#define STUBLESS_FREE 6 - -/* From http://msdn.microsoft.com/library/default.asp?url=/library/en-us/rpc/rpc/parameter_descriptors.asp */ -typedef struct _NDR_PROC_HEADER -{ - /* type of handle to use: - * RPC_FC_BIND_EXPLICIT = 0 - Explicit handle. - * Handle is passed as a parameter to the function. - * Indicates that explicit handle information follows the header, - * which actually describes the handle. - * RPC_FC_BIND_GENERIC = 31 - Implicit handle with custom binding routines - * (MIDL_STUB_DESC::IMPLICIT_HANDLE_INFO::pGenericBindingInfo) - * RPC_FC_BIND_PRIMITIVE = 32 - Implicit handle using handle_t created by - * calling application - * RPC_FC_AUTO_HANDLE = 33 - Automatic handle - * RPC_FC_CALLBACK_HANDLE = 34 - undocmented - */ - unsigned char handle_type; - - /* procedure flags: - * Oi_FULL_PTR_USED = 0x01 - A full pointer can have the value NULL and can - * change during the call from NULL to non-NULL and supports aliasing - * and cycles. Indicates that the NdrFullPointerXlatInit function - * should be called. - * Oi_RPCSS_ALLOC_USED = 0x02 - Use RpcSS allocate/free routines instead of - * normal allocate/free routines - * Oi_OBJECT_PROC = 0x04 - Indicates a procedure that is part of an OLE - * interface, rather than a DCE RPC interface. - * Oi_HAS_RPCFLAGS = 0x08 - Indicates that the rpc_flags element is - * present in the header. - * Oi_HAS_COMM_OR_FAULT = 0x20 - If Oi_OBJECT_PROC not present only then - * indicates that the procedure has the comm_status or fault_status - * MIDL attribute. - * Oi_OBJ_USE_V2_INTERPRETER = 0x20 - If Oi_OBJECT_PROC present only - * then indicates that the format string is in -Oif or -Oicf format - * Oi_USE_NEW_INIT_ROUTINES = 0x40 - Use NdrXInitializeNew instead of - * NdrXInitialize? - */ - unsigned char Oi_flags; - - /* the zero-based index of the procedure */ - unsigned short proc_num; - - /* total size of all parameters on the stack, including any "this" - * pointer and/or return value */ - unsigned short stack_size; -} NDR_PROC_HEADER; - -/* same as above struct except additional element rpc_flags */ -typedef struct _NDR_PROC_HEADER_RPC -{ - unsigned char handle_type; - unsigned char Oi_flags; - - /* - * RPCF_Idempotent = 0x0001 - [idempotent] MIDL attribute - * RPCF_Broadcast = 0x0002 - [broadcast] MIDL attribute - * RPCF_Maybe = 0x0004 - [maybe] MIDL attribute - * Reserved = 0x0008 - 0x0080 - * RPCF_Message = 0x0100 - [message] MIDL attribute - * Reserved = 0x0200 - 0x1000 - * RPCF_InputSynchronous = 0x2000 - unknown - * RPCF_Asynchronous = 0x4000 - [async] MIDL attribute - * Reserved = 0x8000 - */ - unsigned long rpc_flags; - unsigned short proc_num; - unsigned short stack_size; - -} NDR_PROC_HEADER_RPC; - -typedef struct _NDR_PROC_PARTIAL_OIF_HEADER -{ - /* the pre-computed client buffer size so that interpreter can skip all - * or some (if the flag RPC_FC_PROC_OI2F_CLTMUSTSIZE is specified) of the - * sizing pass */ - unsigned short constant_client_buffer_size; - - /* the pre-computed server buffer size so that interpreter can skip all - * or some (if the flag RPC_FC_PROC_OI2F_SRVMUSTSIZE is specified) of the - * sizing pass */ - unsigned short constant_server_buffer_size; - - INTERPRETER_OPT_FLAGS Oi2Flags; - - /* number of params */ - unsigned char number_of_params; -} NDR_PROC_PARTIAL_OIF_HEADER; - -typedef struct _NDR_PARAM_OI_BASETYPE -{ - /* parameter direction. One of: - * FC_IN_PARAM_BASETYPE = 0x4e - an in param - * FC_RETURN_PARAM_BASETYPE = 0x53 - a return param - */ - unsigned char param_direction; - - /* One of: FC_BYTE,FC_CHAR,FC_SMALL,FC_USMALL,FC_WCHAR,FC_SHORT,FC_USHORT, - * FC_LONG,FC_ULONG,FC_FLOAT,FC_HYPER,FC_DOUBLE,FC_ENUM16,FC_ENUM32, - * FC_ERROR_STATUS_T,FC_INT3264,FC_UINT3264 */ - unsigned char type_format_char; -} NDR_PARAM_OI_BASETYPE; - -typedef struct _NDR_PARAM_OI_OTHER -{ - /* One of: - * FC_IN_PARAM = 0x4d - An in param - * FC_IN_OUT_PARAM = 0x50 - An in/out param - * FC_OUT_PARAM = 0x51 - An out param - * FC_RETURN_PARAM = 0x52 - A return value - * FC_IN_PARAM_NO_FREE_INST = 0x4f - A param for which no freeing is done - */ - unsigned char param_direction; - - /* Size of param on stack in NUMBERS OF INTS */ - unsigned char stack_size; - - /* offset in the type format string table */ - unsigned short type_offset; -} NDR_PARAM_OI_OTHER; - -typedef struct _NDR_PARAM_OIF_BASETYPE -{ - PARAM_ATTRIBUTES param_attributes; - - /* the offset on the calling stack where the parameter is located */ - unsigned short stack_offset; - - /* see NDR_PARAM_OI_BASETYPE::type_format_char */ - unsigned char type_format_char; - - /* always FC_PAD */ - unsigned char unused; -} NDR_PARAM_OIF_BASETYPE; - -typedef struct _NDR_PARAM_OIF_OTHER -{ - PARAM_ATTRIBUTES param_attributes; - - /* see NDR_PARAM_OIF_BASETYPE::stack_offset */ - unsigned short stack_offset; - - /* offset into the provided type format string where the type for this - * parameter starts */ - unsigned short type_offset; -} NDR_PARAM_OIF_OTHER; - -/* explicit handle description for FC_BIND_PRIMITIVE type */ -typedef struct _NDR_EHD_PRIMITIVE -{ - /* FC_BIND_PRIMITIVE */ - unsigned char handle_type; - - /* is the handle passed in via a pointer? */ - unsigned char flag; - - /* offset from the beginning of the stack to the handle in bytes */ - unsigned short offset; -} NDR_EHD_PRIMITIVE; - -/* explicit handle description for FC_BIND_GENERIC type */ -typedef struct _NDR_EHD_GENERIC -{ - /* FC_BIND_GENERIC */ - unsigned char handle_type; - - /* upper 4bits is a flag indicating whether the handle is passed in - * via a pointer. lower 4bits is the size of the user defined generic - * handle type. the size must be less than or equal to the machine - * register size */ - unsigned char flag_and_size; - - /* offset from the beginning of the stack to the handle in bytes */ - unsigned short offset; - - /* the index into the aGenericBindingRoutinesPairs field of MIDL_STUB_DESC - * giving the bind and unbind routines for the handle */ - unsigned char binding_routine_pair_index; - - /* FC_PAD */ - unsigned char unused; -} NDR_EHD_GENERIC; - -/* explicit handle description for FC_BIND_CONTEXT type */ -typedef struct _NDR_EHD_CONTEXT -{ - /* FC_BIND_CONTEXT */ - unsigned char handle_type; - - /* Any of the following flags: - * NDR_CONTEXT_HANDLE_CANNOT_BE_NULL = 0x01 - * NDR_CONTEXT_HANDLE_SERIALIZE = 0x02 - * NDR_CONTEXT_HANDLE_NO_SERIALIZE = 0x04 - * NDR_STRICT_CONTEXT_HANDLE = 0x08 - * HANDLE_PARAM_IS_OUT = 0x20 - * HANDLE_PARAM_IS_RETURN = 0x21 - * HANDLE_PARAM_IS_IN = 0x40 - * HANDLE_PARAM_IS_VIA_PTR = 0x80 - */ - unsigned char flags; - - /* offset from the beginning of the stack to the handle in bytes */ - unsigned short offset; - - /* zero-based index on rundown routine in apfnNdrRundownRoutines field - * of MIDL_STUB_DESC */ - unsigned char context_rundown_routine_index; - - /* varies depending on NDR version used. - * V1: zero-based index into parameters - * V2: zero-based index into handles that are parameters */ - unsigned char param_num; -} NDR_EHD_CONTEXT; - -#include "poppack.h" - -void WINAPI NdrRpcSmSetClientToOsf(PMIDL_STUB_MESSAGE pMessage) -{ -#if 0 /* these functions are not defined yet */ - pMessage->pfnAllocate = NdrRpcSmClientAllocate; - pMessage->pfnFree = NdrRpcSmClientFree; -#endif -} - -static void WINAPI dump_RPC_FC_PROC_PF(PARAM_ATTRIBUTES param_attributes) -{ - if (param_attributes.MustSize) TRACE(" MustSize"); - if (param_attributes.MustFree) TRACE(" MustFree"); - if (param_attributes.IsPipe) TRACE(" IsPipe"); - if (param_attributes.IsIn) TRACE(" IsIn"); - if (param_attributes.IsOut) TRACE(" IsOut"); - if (param_attributes.IsReturn) TRACE(" IsReturn"); - if (param_attributes.IsBasetype) TRACE(" IsBasetype"); - if (param_attributes.IsByValue) TRACE(" IsByValue"); - if (param_attributes.IsSimpleRef) TRACE(" IsSimpleRef"); - if (param_attributes.IsDontCallFreeInst) TRACE(" IsDontCallFreeInst"); - if (param_attributes.SaveForAsyncFinish) TRACE(" SaveForAsyncFinish"); - if (param_attributes.ServerAllocSize) TRACE(" ServerAllocSize = %d", param_attributes.ServerAllocSize * 8); -} - -static void WINAPI dump_INTERPRETER_OPT_FLAGS(INTERPRETER_OPT_FLAGS Oi2Flags) -{ - if (Oi2Flags.ServerMustSize) TRACE(" ServerMustSize"); - if (Oi2Flags.ClientMustSize) TRACE(" ClientMustSize"); - if (Oi2Flags.HasReturn) TRACE(" HasReturn"); - if (Oi2Flags.HasPipes) TRACE(" HasPipes"); - if (Oi2Flags.Unused) TRACE(" Unused"); - if (Oi2Flags.HasAsyncUuid) TRACE(" HasAsyncUuid"); - if (Oi2Flags.HasExtensions) TRACE(" HasExtensions"); - if (Oi2Flags.HasAsyncHandle) TRACE(" HasAsyncHandle"); - TRACE("\n"); -} - -#define ARG_FROM_OFFSET(stubMsg, offset) ((stubMsg).StackTop + (offset)) - -static PFORMAT_STRING client_get_handle( - PMIDL_STUB_MESSAGE pStubMsg, const NDR_PROC_HEADER *pProcHeader, - PFORMAT_STRING pFormat, handle_t *phBinding) -{ - /* binding */ - switch (pProcHeader->handle_type) - { - /* explicit binding: parse additional section */ - case RPC_FC_BIND_EXPLICIT: - switch (*pFormat) /* handle_type */ - { - case RPC_FC_BIND_PRIMITIVE: /* explicit primitive */ - { - const NDR_EHD_PRIMITIVE *pDesc = (const NDR_EHD_PRIMITIVE *)pFormat; - - TRACE("Explicit primitive handle @ %d\n", pDesc->offset); - - if (pDesc->flag) /* pointer to binding */ - *phBinding = **(handle_t **)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset); - else - *phBinding = *(handle_t *)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset); - return pFormat + sizeof(NDR_EHD_PRIMITIVE); - } - case RPC_FC_BIND_GENERIC: /* explicit generic */ - { - const NDR_EHD_GENERIC *pDesc = (const NDR_EHD_GENERIC *)pFormat; - void *pObject = NULL; - void *pArg; - const GENERIC_BINDING_ROUTINE_PAIR *pGenPair; - - TRACE("Explicit generic binding handle #%d\n", pDesc->binding_routine_pair_index); - - if (pDesc->flag_and_size & HANDLE_PARAM_IS_VIA_PTR) - pArg = *(void **)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset); - else - pArg = (void *)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset); - memcpy(&pObject, pArg, pDesc->flag_and_size & 0xf); - pGenPair = &pStubMsg->StubDesc->aGenericBindingRoutinePairs[pDesc->binding_routine_pair_index]; - *phBinding = pGenPair->pfnBind(pObject); - return pFormat + sizeof(NDR_EHD_GENERIC); - } - case RPC_FC_BIND_CONTEXT: /* explicit context */ - { - const NDR_EHD_CONTEXT *pDesc = (const NDR_EHD_CONTEXT *)pFormat; - NDR_CCONTEXT context_handle; - TRACE("Explicit bind context\n"); - if (pDesc->flags & HANDLE_PARAM_IS_VIA_PTR) - { - TRACE("\tHANDLE_PARAM_IS_VIA_PTR\n"); - context_handle = **(NDR_CCONTEXT **)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset); - } - else - context_handle = *(NDR_CCONTEXT *)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset); - if ((pDesc->flags & NDR_CONTEXT_HANDLE_CANNOT_BE_NULL) && - !context_handle) - { - ERR("null context handle isn't allowed\n"); - RpcRaiseException(RPC_X_SS_IN_NULL_CONTEXT); - return NULL; - } - *phBinding = NDRCContextBinding(context_handle); - /* FIXME: should we store this structure in stubMsg.pContext? */ - return pFormat + sizeof(NDR_EHD_CONTEXT); - } - default: - ERR("bad explicit binding handle type (0x%02x)\n", pProcHeader->handle_type); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - } - break; - case RPC_FC_BIND_GENERIC: /* implicit generic */ - FIXME("RPC_FC_BIND_GENERIC\n"); - RpcRaiseException(RPC_X_BAD_STUB_DATA); /* FIXME: remove when implemented */ - break; - case RPC_FC_BIND_PRIMITIVE: /* implicit primitive */ - TRACE("Implicit primitive handle\n"); - *phBinding = *pStubMsg->StubDesc->IMPLICIT_HANDLE_INFO.pPrimitiveHandle; - break; - case RPC_FC_CALLBACK_HANDLE: /* implicit callback */ - FIXME("RPC_FC_CALLBACK_HANDLE\n"); - break; - case RPC_FC_AUTO_HANDLE: /* implicit auto handle */ - /* strictly speaking, it isn't necessary to set hBinding here - * since it isn't actually used (hence the automatic in its name), - * but then why does MIDL generate a valid entry in the - * MIDL_STUB_DESC for it? */ - TRACE("Implicit auto handle\n"); - *phBinding = *pStubMsg->StubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle; - break; - default: - ERR("bad implicit binding handle type (0x%02x)\n", pProcHeader->handle_type); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - } - return pFormat; -} - -static void client_free_handle( - PMIDL_STUB_MESSAGE pStubMsg, const NDR_PROC_HEADER *pProcHeader, - PFORMAT_STRING pFormat, handle_t hBinding) -{ - /* binding */ - switch (pProcHeader->handle_type) - { - /* explicit binding: parse additional section */ - case RPC_FC_BIND_EXPLICIT: - switch (*pFormat) /* handle_type */ - { - case RPC_FC_BIND_GENERIC: /* explicit generic */ - { - const NDR_EHD_GENERIC *pDesc = (const NDR_EHD_GENERIC *)pFormat; - void *pObject = NULL; - void *pArg; - const GENERIC_BINDING_ROUTINE_PAIR *pGenPair; - - TRACE("Explicit generic binding handle #%d\n", pDesc->binding_routine_pair_index); - - if (pDesc->flag_and_size & HANDLE_PARAM_IS_VIA_PTR) - pArg = *(void **)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset); - else - pArg = (void *)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset); - memcpy(&pObject, pArg, pDesc->flag_and_size & 0xf); - pGenPair = &pStubMsg->StubDesc->aGenericBindingRoutinePairs[pDesc->binding_routine_pair_index]; - pGenPair->pfnUnbind(pObject, hBinding); - break; - } - case RPC_FC_BIND_CONTEXT: /* explicit context */ - case RPC_FC_BIND_PRIMITIVE: /* explicit primitive */ - break; - default: - ERR("bad explicit binding handle type (0x%02x)\n", pProcHeader->handle_type); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - } - break; - case RPC_FC_BIND_GENERIC: /* implicit generic */ - FIXME("RPC_FC_BIND_GENERIC\n"); - RpcRaiseException(RPC_X_BAD_STUB_DATA); /* FIXME: remove when implemented */ - break; - case RPC_FC_CALLBACK_HANDLE: /* implicit callback */ - case RPC_FC_BIND_PRIMITIVE: /* implicit primitive */ - case RPC_FC_AUTO_HANDLE: /* implicit auto handle */ - break; - default: - ERR("bad implicit binding handle type (0x%02x)\n", pProcHeader->handle_type); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - } -} - -static void client_do_args(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, - int phase, unsigned short number_of_params, unsigned char *pRetVal) -{ - /* current format string offset */ - int current_offset = 0; - /* current stack offset */ - unsigned short current_stack_offset = 0; - /* counter */ - unsigned short i; - - for (i = 0; i < number_of_params; i++) - { - const NDR_PARAM_OIF_BASETYPE *pParam = - (const NDR_PARAM_OIF_BASETYPE *)&pFormat[current_offset]; - unsigned char * pArg; - - current_stack_offset = pParam->stack_offset; - pArg = ARG_FROM_OFFSET(*pStubMsg, current_stack_offset); - - TRACE("param[%d]: new format\n", i); - TRACE("\tparam_attributes:"); dump_RPC_FC_PROC_PF(pParam->param_attributes); TRACE("\n"); - TRACE("\tstack_offset: 0x%x\n", current_stack_offset); - TRACE("\tmemory addr (before): %p\n", pArg); - - if (pParam->param_attributes.IsBasetype) - { - const unsigned char * pTypeFormat = - &pParam->type_format_char; - - if (pParam->param_attributes.IsSimpleRef) - pArg = *(unsigned char **)pArg; - - TRACE("\tbase type: 0x%02x\n", *pTypeFormat); - - switch (phase) - { - case PROXY_CALCSIZE: - if (pParam->param_attributes.IsIn) - call_buffer_sizer(pStubMsg, pArg, pTypeFormat); - break; - case PROXY_MARSHAL: - if (pParam->param_attributes.IsIn) - call_marshaller(pStubMsg, pArg, pTypeFormat); - break; - case PROXY_UNMARSHAL: - if (pParam->param_attributes.IsOut) - { - if (pParam->param_attributes.IsReturn) - call_unmarshaller(pStubMsg, &pRetVal, pTypeFormat, 0); - else - call_unmarshaller(pStubMsg, &pArg, pTypeFormat, 0); - TRACE("pRetVal = %p\n", pRetVal); - } - break; - default: - RpcRaiseException(RPC_S_INTERNAL_ERROR); - } - - current_offset += sizeof(NDR_PARAM_OIF_BASETYPE); - } - else - { - const NDR_PARAM_OIF_OTHER *pParamOther = - (const NDR_PARAM_OIF_OTHER *)&pFormat[current_offset]; - - const unsigned char * pTypeFormat = - &(pStubMsg->StubDesc->pFormatTypes[pParamOther->type_offset]); - - /* if a simple ref pointer then we have to do the - * check for the pointer being non-NULL. */ - if (pParam->param_attributes.IsSimpleRef) - { - if (!*(unsigned char **)pArg) - RpcRaiseException(RPC_X_NULL_REF_POINTER); - } - - TRACE("\tcomplex type: 0x%02x\n", *pTypeFormat); - - switch (phase) - { - case PROXY_CALCSIZE: - if (pParam->param_attributes.IsIn) - { - if (pParam->param_attributes.IsByValue) - call_buffer_sizer(pStubMsg, pArg, pTypeFormat); - else - call_buffer_sizer(pStubMsg, *(unsigned char **)pArg, pTypeFormat); - } - break; - case PROXY_MARSHAL: - if (pParam->param_attributes.IsIn) - { - if (pParam->param_attributes.IsByValue) - call_marshaller(pStubMsg, pArg, pTypeFormat); - else - call_marshaller(pStubMsg, *(unsigned char **)pArg, pTypeFormat); - } - break; - case PROXY_UNMARSHAL: - if (pParam->param_attributes.IsOut) - { - if (pParam->param_attributes.IsReturn) - call_unmarshaller(pStubMsg, &pRetVal, pTypeFormat, 0); - else if (pParam->param_attributes.IsByValue) - call_unmarshaller(pStubMsg, &pArg, pTypeFormat, 0); - else - call_unmarshaller(pStubMsg, (unsigned char **)pArg, pTypeFormat, 0); - } - break; - default: - RpcRaiseException(RPC_S_INTERNAL_ERROR); - } - - current_offset += sizeof(NDR_PARAM_OIF_OTHER); - } - TRACE("\tmemory addr (after): %p\n", pArg); - } -} - -static void client_do_args_old_format(PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat, int phase, unsigned short stack_size, - unsigned char *pRetVal, BOOL object_proc) -{ - /* current format string offset */ - int current_offset = 0; - /* current stack offset */ - unsigned short current_stack_offset = 0; - /* counter */ - unsigned short i; - - /* NOTE: V1 style format does't terminate on the number_of_params - * condition as it doesn't have this attribute. Instead it - * terminates when the stack size given in the header is exceeded. - */ - for (i = 0; TRUE; i++) - { - const NDR_PARAM_OI_BASETYPE *pParam = - (const NDR_PARAM_OI_BASETYPE *)&pFormat[current_offset]; - /* note: current_stack_offset starts after the This pointer - * if present, so adjust this */ - unsigned short current_stack_offset_adjusted = current_stack_offset + - (object_proc ? sizeof(void *) : 0); - unsigned char * pArg = ARG_FROM_OFFSET(*pStubMsg, current_stack_offset_adjusted); - - /* no more parameters; exit loop */ - if (current_stack_offset_adjusted >= stack_size) - break; - - TRACE("param[%d]: old format\n", i); - TRACE("\tparam_direction: 0x%x\n", pParam->param_direction); - TRACE("\tstack_offset: 0x%x\n", current_stack_offset_adjusted); - TRACE("\tmemory addr (before): %p\n", pArg); - - if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE || - pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE) - { - const unsigned char * pTypeFormat = - &pParam->type_format_char; - - TRACE("\tbase type 0x%02x\n", *pTypeFormat); - - switch (phase) - { - case PROXY_CALCSIZE: - if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE) - call_buffer_sizer(pStubMsg, pArg, pTypeFormat); - break; - case PROXY_MARSHAL: - if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE) - call_marshaller(pStubMsg, pArg, pTypeFormat); - break; - case PROXY_UNMARSHAL: - if (pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE) - { - if (pParam->param_direction & RPC_FC_RETURN_PARAM) - call_unmarshaller(pStubMsg, (unsigned char **)pRetVal, pTypeFormat, 0); - else - call_unmarshaller(pStubMsg, &pArg, pTypeFormat, 0); - } - break; - default: - RpcRaiseException(RPC_S_INTERNAL_ERROR); - } - - current_stack_offset += call_memory_sizer(pStubMsg, pTypeFormat); - current_offset += sizeof(NDR_PARAM_OI_BASETYPE); - } - else - { - const NDR_PARAM_OI_OTHER *pParamOther = - (const NDR_PARAM_OI_OTHER *)&pFormat[current_offset]; - - const unsigned char *pTypeFormat = - &pStubMsg->StubDesc->pFormatTypes[pParamOther->type_offset]; - - TRACE("\tcomplex type 0x%02x\n", *pTypeFormat); - - switch (phase) - { - case PROXY_CALCSIZE: - if (pParam->param_direction == RPC_FC_IN_PARAM || - pParam->param_direction & RPC_FC_IN_OUT_PARAM) - call_buffer_sizer(pStubMsg, *(unsigned char **)pArg, pTypeFormat); - break; - case PROXY_MARSHAL: - if (pParam->param_direction == RPC_FC_IN_PARAM || - pParam->param_direction & RPC_FC_IN_OUT_PARAM) - call_marshaller(pStubMsg, *(unsigned char **)pArg, pTypeFormat); - break; - case PROXY_UNMARSHAL: - if (pParam->param_direction == RPC_FC_IN_OUT_PARAM || - pParam->param_direction == RPC_FC_OUT_PARAM) - call_unmarshaller(pStubMsg, (unsigned char **)pArg, pTypeFormat, 0); - else if (pParam->param_direction == RPC_FC_RETURN_PARAM) - call_unmarshaller(pStubMsg, (unsigned char **)pRetVal, pTypeFormat, 0); - break; - default: - RpcRaiseException(RPC_S_INTERNAL_ERROR); - } - - current_stack_offset += pParamOther->stack_size * sizeof(INT); - current_offset += sizeof(NDR_PARAM_OI_OTHER); - } - TRACE("\tmemory addr (after): %p\n", pArg); - } -} - -/* the return type should be CLIENT_CALL_RETURN, but this is incompatible - * with the way gcc returns structures. "void *" should be the largest type - * that MIDL should allow you to return anyway */ -LONG_PTR WINAPIV NdrClientCall2(PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pFormat, ...) -{ - /* pointer to start of stack where arguments start */ - RPC_MESSAGE rpcMsg; - MIDL_STUB_MESSAGE stubMsg; - handle_t hBinding = NULL; - /* procedure number */ - unsigned short procedure_number; - /* size of stack */ - unsigned short stack_size; - /* number of parameters. optional for client to give it to us */ - unsigned char number_of_params = ~0; - /* cache of Oif_flags from v2 procedure header */ - INTERPRETER_OPT_FLAGS Oif_flags = { 0 }; - /* cache of extension flags from NDR_PROC_HEADER_EXTS */ - INTERPRETER_OPT_FLAGS2 ext_flags = { 0 }; - /* the type of pass we are currently doing */ - int phase; - /* header for procedure string */ - const NDR_PROC_HEADER * pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0]; - /* -Oif or -Oicf generated format */ - BOOL bV2Format = FALSE; - /* the value to return to the client from the remote procedure */ - LONG_PTR RetVal = 0; - /* the pointer to the object when in OLE mode */ - void * This = NULL; - PFORMAT_STRING pHandleFormat; - - TRACE("pStubDesc %p, pFormat %p, ...\n", pStubDesc, pFormat); - - /* Later NDR language versions probably won't be backwards compatible */ - if (pStubDesc->Version > 0x50002) - { - FIXME("Incompatible stub description version: 0x%x\n", pStubDesc->Version); - RpcRaiseException(RPC_X_WRONG_STUB_VERSION); - } - - if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS) - { - const NDR_PROC_HEADER_RPC *pProcHeader = (const NDR_PROC_HEADER_RPC *)&pFormat[0]; - stack_size = pProcHeader->stack_size; - procedure_number = pProcHeader->proc_num; - pFormat += sizeof(NDR_PROC_HEADER_RPC); - } - else - { - stack_size = pProcHeader->stack_size; - procedure_number = pProcHeader->proc_num; - pFormat += sizeof(NDR_PROC_HEADER); - } - TRACE("stack size: 0x%x\n", stack_size); - TRACE("proc num: %d\n", procedure_number); - - /* create the full pointer translation tables, if requested */ - if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR) - stubMsg.FullPtrXlatTables = NdrFullPointerXlatInit(0,XLAT_CLIENT); - - if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT) - { - /* object is always the first argument */ - This = **(void *const **)(&pFormat+1); - NdrProxyInitialize(This, &rpcMsg, &stubMsg, pStubDesc, procedure_number); - } - else - NdrClientInitializeNew(&rpcMsg, &stubMsg, pStubDesc, procedure_number); - - TRACE("Oi_flags = 0x%02x\n", pProcHeader->Oi_flags); - TRACE("MIDL stub version = 0x%x\n", pStubDesc->MIDLVersion); - - /* needed for conformance of top-level objects */ -#ifdef __i386__ - stubMsg.StackTop = *(unsigned char **)(&pFormat+1); -#else -# warning Stack not retrieved for your CPU architecture -#endif - - pHandleFormat = pFormat; - - /* we only need a handle if this isn't an object method */ - if (!(pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)) - { - pFormat = client_get_handle(&stubMsg, pProcHeader, pHandleFormat, &hBinding); - if (!pFormat) return 0; - } - - bV2Format = (pStubDesc->Version >= 0x20000); - - if (bV2Format) - { - const NDR_PROC_PARTIAL_OIF_HEADER *pOIFHeader = - (const NDR_PROC_PARTIAL_OIF_HEADER *)pFormat; - - Oif_flags = pOIFHeader->Oi2Flags; - number_of_params = pOIFHeader->number_of_params; - - pFormat += sizeof(NDR_PROC_PARTIAL_OIF_HEADER); - } - - TRACE("Oif_flags = "); dump_INTERPRETER_OPT_FLAGS(Oif_flags); - - if (Oif_flags.HasExtensions) - { - const NDR_PROC_HEADER_EXTS *pExtensions = - (const NDR_PROC_HEADER_EXTS *)pFormat; - ext_flags = pExtensions->Flags2; - pFormat += pExtensions->Size; - } - - stubMsg.BufferLength = 0; - - /* store the RPC flags away */ - if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS) - rpcMsg.RpcFlags = ((const NDR_PROC_HEADER_RPC *)pProcHeader)->rpc_flags; - - /* use alternate memory allocation routines */ - if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCSSALLOC) - NdrRpcSmSetClientToOsf(&stubMsg); - - if (Oif_flags.HasPipes) - { - FIXME("pipes not supported yet\n"); - RpcRaiseException(RPC_X_WRONG_STUB_VERSION); /* FIXME: remove when implemented */ - /* init pipes package */ - /* NdrPipesInitialize(...) */ - } - if (ext_flags.HasNewCorrDesc) - { - /* initialize extra correlation package */ - FIXME("new correlation description not implemented\n"); - stubMsg.fHasNewCorrDesc = TRUE; - } - - /* order of phases: - * 1. PROXY_CALCSIZE - calculate the buffer size - * 2. PROXY_GETBUFFER - allocate the buffer - * 3. PROXY_MARHSAL - marshal [in] params into the buffer - * 4. PROXY_SENDRECEIVE - send/receive buffer - * 5. PROXY_UNMARHSAL - unmarshal [out] params from buffer - */ - for (phase = PROXY_CALCSIZE; phase <= PROXY_UNMARSHAL; phase++) - { - TRACE("phase = %d\n", phase); - switch (phase) - { - case PROXY_GETBUFFER: - /* allocate the buffer */ - if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT) - NdrProxyGetBuffer(This, &stubMsg); - else if (Oif_flags.HasPipes) - /* NdrGetPipeBuffer(...) */ - FIXME("pipes not supported yet\n"); - else - { - if (pProcHeader->handle_type == RPC_FC_AUTO_HANDLE) -#if 0 - NdrNsGetBuffer(&stubMsg, stubMsg.BufferLength, hBinding); -#else - FIXME("using auto handle - call NdrNsGetBuffer when it gets implemented\n"); -#endif - else - NdrGetBuffer(&stubMsg, stubMsg.BufferLength, hBinding); - } - break; - case PROXY_SENDRECEIVE: - /* send the [in] params and receive the [out] and [retval] - * params */ - if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT) - NdrProxySendReceive(This, &stubMsg); - else if (Oif_flags.HasPipes) - /* NdrPipesSendReceive(...) */ - FIXME("pipes not supported yet\n"); - else - { - if (pProcHeader->handle_type == RPC_FC_AUTO_HANDLE) -#if 0 - NdrNsSendReceive(&stubMsg, stubMsg.Buffer, pStubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle); -#else - FIXME("using auto handle - call NdrNsSendReceive when it gets implemented\n"); -#endif - else - NdrSendReceive(&stubMsg, stubMsg.Buffer); - } - - /* convert strings, floating point values and endianess into our - * preferred format */ - if ((rpcMsg.DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION) - NdrConvert(&stubMsg, pFormat); - - break; - case PROXY_CALCSIZE: - case PROXY_MARSHAL: - case PROXY_UNMARSHAL: - if (bV2Format) - client_do_args(&stubMsg, pFormat, phase, number_of_params, - (unsigned char *)&RetVal); - else - client_do_args_old_format(&stubMsg, pFormat, phase, stack_size, - (unsigned char *)&RetVal, - (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)); - break; - default: - ERR("shouldn't reach here. phase %d\n", phase); - break; - } - } - - if (ext_flags.HasNewCorrDesc) - { - /* free extra correlation package */ - /* NdrCorrelationFree(&stubMsg); */ - } - - if (Oif_flags.HasPipes) - { - /* NdrPipesDone(...) */ - } - - /* free the full pointer translation tables */ - if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR) - NdrFullPointerXlatFree(stubMsg.FullPtrXlatTables); - - /* free marshalling buffer */ - if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT) - NdrProxyFreeBuffer(This, &stubMsg); - else - { - NdrFreeBuffer(&stubMsg); - client_free_handle(&stubMsg, pProcHeader, pHandleFormat, hBinding); - } - - TRACE("RetVal = 0x%lx\n", RetVal); - - return RetVal; -} - -/* calls a function with the specificed arguments, restoring the stack - * properly afterwards as we don't know the calling convention of the - * function */ -#if defined __i386__ && defined _MSC_VER -__declspec(naked) LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned int stack_size) -{ - __asm - { - push ebp - push edi ; Save registers - push esi - mov ebp, esp - mov eax, [ebp+16] ; Get stack size - sub esp, eax ; Make room in stack for arguments - mov edi, esp - mov ecx, eax - mov esi, [ebp+12] - shr ecx, 2 - cld - rep movsd ; Copy dword blocks - call [ebp+8] ; Call function - lea esp, [ebp-8] ; Restore stack - pop esi ; Restore registers - pop edi - pop ebp - ret - } -} -#elif defined __i386__ && defined __GNUC__ -LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned int stack_size); -__ASM_GLOBAL_FUNC(call_server_func, - "pushl %ebp\n\t" - "movl %esp, %ebp\n\t" - "pushl %edi\n\t" /* Save registers */ - "pushl %esi\n\t" - "movl 16(%ebp), %eax\n\t" /* Get stack size */ - "subl %eax, %esp\n\t" /* Make room in stack for arguments */ - "andl $~15, %esp\n\t" /* Make sure stack has 16-byte alignment for Mac OS X */ - "movl %esp, %edi\n\t" - "movl %eax, %ecx\n\t" - "movl 12(%ebp), %esi\n\t" - "shrl $2, %ecx\n\t" /* divide by 4 */ - "cld\n\t" - "rep; movsl\n\t" /* Copy dword blocks */ - "call *8(%ebp)\n\t" /* Call function */ - "leal -8(%ebp), %esp\n\t" /* Restore stack */ - "popl %esi\n\t" /* Restore registers */ - "popl %edi\n\t" - "popl %ebp\n\t" - "ret\n" ) -#else -#warning call_server_func not implemented for your architecture -LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned short stack_size) -{ - FIXME("Not implemented for your architecture\n"); - return 0; -} -#endif - -static DWORD calc_arg_size(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat) -{ - DWORD size; - switch(*pFormat) - { - case RPC_FC_STRUCT: - size = *(const WORD*)(pFormat + 2); - break; - case RPC_FC_CARRAY: - size = *(const WORD*)(pFormat + 2); - ComputeConformance(pStubMsg, NULL, pFormat + 4, 0); - size *= pStubMsg->MaxCount; - break; - case RPC_FC_SMFARRAY: - size = *(const WORD*)(pFormat + 2); - break; - case RPC_FC_LGFARRAY: - size = *(const DWORD*)(pFormat + 2); - break; - default: - FIXME("Unhandled type %02x\n", *pFormat); - /* fallthrough */ - case RPC_FC_RP: - size = sizeof(void *); - break; - } - return size; -} - -/* FIXME: need to free some stuff in here too */ -LONG WINAPI NdrStubCall2( - struct IRpcStubBuffer * pThis, - struct IRpcChannelBuffer * pChannel, - PRPC_MESSAGE pRpcMsg, - DWORD * pdwStubPhase) -{ - const MIDL_SERVER_INFO *pServerInfo; - const MIDL_STUB_DESC *pStubDesc; - PFORMAT_STRING pFormat; - MIDL_STUB_MESSAGE stubMsg; - /* pointer to start of stack to pass into stub implementation */ - unsigned char * args; - /* size of stack */ - unsigned short stack_size; - /* current stack offset */ - unsigned short current_stack_offset; - /* number of parameters. optional for client to give it to us */ - unsigned char number_of_params = ~0; - /* counter */ - unsigned short i; - /* cache of Oif_flags from v2 procedure header */ - INTERPRETER_OPT_FLAGS Oif_flags = { 0 }; - /* cache of extension flags from NDR_PROC_HEADER_EXTS */ - INTERPRETER_OPT_FLAGS2 ext_flags = { 0 }; - /* the type of pass we are currently doing */ - int phase; - /* header for procedure string */ - const NDR_PROC_HEADER *pProcHeader; - /* offset in format string for start of params */ - int parameter_start_offset; - /* current format string offset */ - int current_offset; - /* -Oif or -Oicf generated format */ - BOOL bV2Format = FALSE; - /* location to put retval into */ - LONG_PTR *retval_ptr = NULL; - - TRACE("pThis %p, pChannel %p, pRpcMsg %p, pdwStubPhase %p\n", pThis, pChannel, pRpcMsg, pdwStubPhase); - - if (pThis) - pServerInfo = CStdStubBuffer_GetServerInfo(pThis); - else - pServerInfo = ((RPC_SERVER_INTERFACE *)pRpcMsg->RpcInterfaceInformation)->InterpreterInfo; - - pStubDesc = pServerInfo->pStubDesc; - pFormat = pServerInfo->ProcString + pServerInfo->FmtStringOffset[pRpcMsg->ProcNum]; - pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0]; - - /* Later NDR language versions probably won't be backwards compatible */ - if (pStubDesc->Version > 0x50002) - { - FIXME("Incompatible stub description version: 0x%x\n", pStubDesc->Version); - RpcRaiseException(RPC_X_WRONG_STUB_VERSION); - } - - /* create the full pointer translation tables, if requested */ - if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR) - stubMsg.FullPtrXlatTables = NdrFullPointerXlatInit(0,XLAT_SERVER); - - if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS) - { - const NDR_PROC_HEADER_RPC *pProcHeader = (const NDR_PROC_HEADER_RPC *)&pFormat[0]; - stack_size = pProcHeader->stack_size; - current_offset = sizeof(NDR_PROC_HEADER_RPC); - - } - else - { - stack_size = pProcHeader->stack_size; - current_offset = sizeof(NDR_PROC_HEADER); - } - - TRACE("Oi_flags = 0x%02x\n", pProcHeader->Oi_flags); - - /* binding */ - switch (pProcHeader->handle_type) - { - /* explicit binding: parse additional section */ - case RPC_FC_BIND_EXPLICIT: - switch (pFormat[current_offset]) /* handle_type */ - { - case RPC_FC_BIND_PRIMITIVE: /* explicit primitive */ - current_offset += sizeof(NDR_EHD_PRIMITIVE); - break; - case RPC_FC_BIND_GENERIC: /* explicit generic */ - current_offset += sizeof(NDR_EHD_GENERIC); - break; - case RPC_FC_BIND_CONTEXT: /* explicit context */ - current_offset += sizeof(NDR_EHD_CONTEXT); - break; - default: - ERR("bad explicit binding handle type (0x%02x)\n", pProcHeader->handle_type); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - } - break; - case RPC_FC_BIND_GENERIC: /* implicit generic */ - case RPC_FC_BIND_PRIMITIVE: /* implicit primitive */ - case RPC_FC_CALLBACK_HANDLE: /* implicit callback */ - case RPC_FC_AUTO_HANDLE: /* implicit auto handle */ - break; - default: - ERR("bad implicit binding handle type (0x%02x)\n", pProcHeader->handle_type); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - } - - bV2Format = (pStubDesc->Version >= 0x20000); - - if (bV2Format) - { - const NDR_PROC_PARTIAL_OIF_HEADER *pOIFHeader = - (const NDR_PROC_PARTIAL_OIF_HEADER *)&pFormat[current_offset]; - - Oif_flags = pOIFHeader->Oi2Flags; - number_of_params = pOIFHeader->number_of_params; - - current_offset += sizeof(NDR_PROC_PARTIAL_OIF_HEADER); - } - - TRACE("Oif_flags = "); dump_INTERPRETER_OPT_FLAGS(Oif_flags); - - if (Oif_flags.HasExtensions) - { - const NDR_PROC_HEADER_EXTS *pExtensions = - (const NDR_PROC_HEADER_EXTS *)&pFormat[current_offset]; - ext_flags = pExtensions->Flags2; - current_offset += pExtensions->Size; - } - - if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT) - NdrStubInitialize(pRpcMsg, &stubMsg, pStubDesc, pChannel); - else - NdrServerInitializeNew(pRpcMsg, &stubMsg, pStubDesc); - - /* store the RPC flags away */ - if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS) - pRpcMsg->RpcFlags = ((const NDR_PROC_HEADER_RPC *)pProcHeader)->rpc_flags; - - /* use alternate memory allocation routines */ - if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCSSALLOC) -#if 0 - NdrRpcSsEnableAllocate(&stubMsg); -#else - FIXME("Set RPCSS memory allocation routines\n"); -#endif - - if (Oif_flags.HasPipes) - { - FIXME("pipes not supported yet\n"); - RpcRaiseException(RPC_X_WRONG_STUB_VERSION); /* FIXME: remove when implemented */ - /* init pipes package */ - /* NdrPipesInitialize(...) */ - } - if (ext_flags.HasNewCorrDesc) - { - /* initialize extra correlation package */ - FIXME("new correlation description not implemented\n"); - stubMsg.fHasNewCorrDesc = TRUE; - } - - /* convert strings, floating point values and endianess into our - * preferred format */ - if ((pRpcMsg->DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION) - NdrConvert(&stubMsg, pFormat); - - parameter_start_offset = current_offset; - - TRACE("allocating memory for stack of size %x\n", stack_size); - - args = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, stack_size); - stubMsg.StackTop = args; /* used by conformance of top-level objects */ - - /* add the implicit This pointer as the first arg to the function if we - * are calling an object method */ - if (pThis) - *(void **)args = ((CStdStubBuffer *)pThis)->pvServerObject; - - /* order of phases: - * 1. STUBLESS_UNMARHSAL - unmarshal [in] params from buffer - * 2. STUBLESS_CALLSERVER - send/receive buffer - * 3. STUBLESS_CALCSIZE - get [out] buffer size - * 4. STUBLESS_GETBUFFER - allocate [out] buffer - * 5. STUBLESS_MARHSAL - marshal [out] params to buffer - */ - for (phase = STUBLESS_UNMARSHAL; phase <= STUBLESS_FREE; phase++) - { - TRACE("phase = %d\n", phase); - switch (phase) - { - case STUBLESS_CALLSERVER: - /* call the server function */ - if (pServerInfo->ThunkTable && pServerInfo->ThunkTable[pRpcMsg->ProcNum]) - pServerInfo->ThunkTable[pRpcMsg->ProcNum](&stubMsg); - else - { - SERVER_ROUTINE func; - LONG_PTR retval; - - if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT) - { - SERVER_ROUTINE *vtbl = *(SERVER_ROUTINE **)((CStdStubBuffer *)pThis)->pvServerObject; - func = vtbl[pRpcMsg->ProcNum]; - } - else - func = pServerInfo->DispatchTable[pRpcMsg->ProcNum]; - - /* FIXME: what happens with return values that don't fit into a single register on x86? */ - retval = call_server_func(func, args, stack_size); - - if (retval_ptr) - { - TRACE("stub implementation returned 0x%lx\n", retval); - *retval_ptr = retval; - } - else - TRACE("void stub implementation\n"); - } - - stubMsg.Buffer = NULL; - stubMsg.BufferLength = 0; - - break; - case STUBLESS_GETBUFFER: - if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT) - NdrStubGetBuffer(pThis, pChannel, &stubMsg); - else - { - RPC_STATUS Status; - - pRpcMsg->BufferLength = stubMsg.BufferLength; - /* allocate buffer for [out] and [ret] params */ - Status = I_RpcGetBuffer(pRpcMsg); - if (Status) - RpcRaiseException(Status); - stubMsg.BufferStart = pRpcMsg->Buffer; - stubMsg.BufferEnd = stubMsg.BufferStart + stubMsg.BufferLength; - stubMsg.Buffer = stubMsg.BufferStart; - } - break; - case STUBLESS_MARSHAL: - case STUBLESS_UNMARSHAL: - case STUBLESS_CALCSIZE: - case STUBLESS_FREE: - current_offset = parameter_start_offset; - current_stack_offset = 0; - - /* NOTE: V1 style format does't terminate on the number_of_params - * condition as it doesn't have this attribute. Instead it - * terminates when the stack size given in the header is exceeded. - */ - for (i = 0; i < number_of_params; i++) - { - if (bV2Format) /* new parameter format */ - { - const NDR_PARAM_OIF_BASETYPE *pParam = - (const NDR_PARAM_OIF_BASETYPE *)&pFormat[current_offset]; - unsigned char *pArg; - - current_stack_offset = pParam->stack_offset; - pArg = (unsigned char *)(args+current_stack_offset); - - TRACE("param[%d]: new format\n", i); - TRACE("\tparam_attributes:"); dump_RPC_FC_PROC_PF(pParam->param_attributes); TRACE("\n"); - TRACE("\tstack_offset: 0x%x\n", current_stack_offset); - TRACE("\tmemory addr (before): %p -> %p\n", pArg, *(unsigned char **)pArg); - - if (pParam->param_attributes.IsBasetype) - { - const unsigned char *pTypeFormat = - &pParam->type_format_char; - - TRACE("\tbase type: 0x%02x\n", *pTypeFormat); - - switch (phase) - { - case STUBLESS_MARSHAL: - if (pParam->param_attributes.IsOut || pParam->param_attributes.IsReturn) - { - if (pParam->param_attributes.IsSimpleRef) - call_marshaller(&stubMsg, *(unsigned char **)pArg, pTypeFormat); - else - call_marshaller(&stubMsg, pArg, pTypeFormat); - } - break; - case STUBLESS_FREE: - if (pParam->param_attributes.ServerAllocSize) - HeapFree(GetProcessHeap(), 0, *(void **)pArg); - break; - case STUBLESS_UNMARSHAL: - if (pParam->param_attributes.ServerAllocSize) - *(void **)pArg = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, - pParam->param_attributes.ServerAllocSize * 8); - - if (pParam->param_attributes.IsIn) - { - if (pParam->param_attributes.IsSimpleRef) - call_unmarshaller(&stubMsg, (unsigned char **)pArg, pTypeFormat, 0); - else - call_unmarshaller(&stubMsg, &pArg, pTypeFormat, 0); - } - - /* make a note of the address of the return value parameter for later */ - if (pParam->param_attributes.IsReturn) - retval_ptr = (LONG_PTR *)pArg; - - break; - case STUBLESS_CALCSIZE: - if (pParam->param_attributes.IsOut || pParam->param_attributes.IsReturn) - { - if (pParam->param_attributes.IsSimpleRef) - call_buffer_sizer(&stubMsg, *(unsigned char **)pArg, pTypeFormat); - else - call_buffer_sizer(&stubMsg, pArg, pTypeFormat); - } - break; - default: - RpcRaiseException(RPC_S_INTERNAL_ERROR); - } - - current_offset += sizeof(NDR_PARAM_OIF_BASETYPE); - } - else - { - const NDR_PARAM_OIF_OTHER *pParamOther = - (const NDR_PARAM_OIF_OTHER *)&pFormat[current_offset]; - - const unsigned char * pTypeFormat = - &(pStubDesc->pFormatTypes[pParamOther->type_offset]); - - TRACE("\tcomplex type 0x%02x\n", *pTypeFormat); - - switch (phase) - { - case STUBLESS_MARSHAL: - if (pParam->param_attributes.IsOut || pParam->param_attributes.IsReturn) - { - if (pParam->param_attributes.IsByValue) - call_marshaller(&stubMsg, pArg, pTypeFormat); - else - call_marshaller(&stubMsg, *(unsigned char **)pArg, pTypeFormat); - } - break; - case STUBLESS_FREE: - if (pParam->param_attributes.MustFree) - { - if (pParam->param_attributes.IsByValue) - call_freer(&stubMsg, pArg, pTypeFormat); - else - call_freer(&stubMsg, *(unsigned char **)pArg, pTypeFormat); - } - - if (pParam->param_attributes.IsOut && - !pParam->param_attributes.IsIn && - !pParam->param_attributes.IsByValue && - !pParam->param_attributes.ServerAllocSize) - { - stubMsg.pfnFree(*(void **)pArg); - } - - if (pParam->param_attributes.ServerAllocSize) - HeapFree(GetProcessHeap(), 0, *(void **)pArg); - /* FIXME: call call_freer here for IN types with MustFree set */ - break; - case STUBLESS_UNMARSHAL: - if (pParam->param_attributes.ServerAllocSize) - *(void **)pArg = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, - pParam->param_attributes.ServerAllocSize * 8); - - if (pParam->param_attributes.IsIn) - { - if (pParam->param_attributes.IsByValue) - call_unmarshaller(&stubMsg, &pArg, pTypeFormat, 0); - else - call_unmarshaller(&stubMsg, (unsigned char **)pArg, pTypeFormat, 0); - } - else if (pParam->param_attributes.IsOut && - !pParam->param_attributes.ServerAllocSize && - !pParam->param_attributes.IsByValue) - { - DWORD size = calc_arg_size(&stubMsg, pTypeFormat); - - if(size) - { - *(void **)pArg = NdrAllocate(&stubMsg, size); - memset(*(void **)pArg, 0, size); - } - } - break; - case STUBLESS_CALCSIZE: - if (pParam->param_attributes.IsOut || pParam->param_attributes.IsReturn) - { - if (pParam->param_attributes.IsByValue) - call_buffer_sizer(&stubMsg, pArg, pTypeFormat); - else - call_buffer_sizer(&stubMsg, *(unsigned char **)pArg, pTypeFormat); - } - break; - default: - RpcRaiseException(RPC_S_INTERNAL_ERROR); - } - - current_offset += sizeof(NDR_PARAM_OIF_OTHER); - } - TRACE("\tmemory addr (after): %p -> %p\n", pArg, *(unsigned char **)pArg); - } - else /* old parameter format */ - { - const NDR_PARAM_OI_BASETYPE *pParam = - (const NDR_PARAM_OI_BASETYPE *)&pFormat[current_offset]; - /* note: current_stack_offset starts after the This pointer - * if present, so adjust this */ - unsigned short current_stack_offset_adjusted = current_stack_offset + - ((pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT) ? sizeof(void *) : 0); - unsigned char *pArg = (unsigned char *)(args+current_stack_offset_adjusted); - - /* no more parameters; exit loop */ - if (current_stack_offset_adjusted >= stack_size) - break; - - TRACE("param[%d]: old format\n", i); - TRACE("\tparam_direction: 0x%x\n", pParam->param_direction); - TRACE("\tstack_offset: 0x%x\n", current_stack_offset_adjusted); - - if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE || - pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE) - { - const unsigned char *pTypeFormat = - &pParam->type_format_char; - - TRACE("\tbase type 0x%02x\n", *pTypeFormat); - - switch (phase) - { - case STUBLESS_MARSHAL: - if (pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE) - call_marshaller(&stubMsg, pArg, pTypeFormat); - break; - case STUBLESS_FREE: - if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE) - call_freer(&stubMsg, pArg, pTypeFormat); - break; - case STUBLESS_UNMARSHAL: - if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE) - call_unmarshaller(&stubMsg, &pArg, pTypeFormat, 0); - else if (pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE) - retval_ptr = (LONG_PTR *)pArg; - break; - case STUBLESS_CALCSIZE: - if (pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE) - call_buffer_sizer(&stubMsg, pArg, pTypeFormat); - break; - default: - RpcRaiseException(RPC_S_INTERNAL_ERROR); - } - - current_stack_offset += call_memory_sizer(&stubMsg, pTypeFormat); - current_offset += sizeof(NDR_PARAM_OI_BASETYPE); - } - else - { - const NDR_PARAM_OI_OTHER *pParamOther = - (const NDR_PARAM_OI_OTHER *)&pFormat[current_offset]; - - const unsigned char * pTypeFormat = - &pStubDesc->pFormatTypes[pParamOther->type_offset]; - - TRACE("\tcomplex type 0x%02x\n", *pTypeFormat); - - switch (phase) - { - case STUBLESS_MARSHAL: - if (pParam->param_direction == RPC_FC_OUT_PARAM || - pParam->param_direction == RPC_FC_IN_OUT_PARAM || - pParam->param_direction == RPC_FC_RETURN_PARAM) - call_marshaller(&stubMsg, *(unsigned char **)pArg, pTypeFormat); - break; - case STUBLESS_FREE: - if (pParam->param_direction == RPC_FC_IN_OUT_PARAM || - pParam->param_direction == RPC_FC_IN_PARAM) - call_freer(&stubMsg, *(unsigned char **)pArg, pTypeFormat); - else if (pParam->param_direction == RPC_FC_OUT_PARAM) - stubMsg.pfnFree(*(void **)pArg); - break; - case STUBLESS_UNMARSHAL: - if (pParam->param_direction == RPC_FC_IN_OUT_PARAM || - pParam->param_direction == RPC_FC_IN_PARAM) - call_unmarshaller(&stubMsg, (unsigned char **)pArg, pTypeFormat, 0); - else if (pParam->param_direction == RPC_FC_RETURN_PARAM) - retval_ptr = (LONG_PTR *)pArg; - else if (pParam->param_direction == RPC_FC_OUT_PARAM) - { - DWORD size = calc_arg_size(&stubMsg, pTypeFormat); - - if(size) - { - *(void **)pArg = NdrAllocate(&stubMsg, size); - memset(*(void **)pArg, 0, size); - } - } - break; - case STUBLESS_CALCSIZE: - if (pParam->param_direction == RPC_FC_OUT_PARAM || - pParam->param_direction == RPC_FC_IN_OUT_PARAM || - pParam->param_direction == RPC_FC_RETURN_PARAM) - call_buffer_sizer(&stubMsg, *(unsigned char **)pArg, pTypeFormat); - break; - default: - RpcRaiseException(RPC_S_INTERNAL_ERROR); - } - - current_stack_offset += pParamOther->stack_size * sizeof(INT); - current_offset += sizeof(NDR_PARAM_OI_OTHER); - } - } - } - - break; - default: - ERR("shouldn't reach here. phase %d\n", phase); - break; - } - } - - pRpcMsg->BufferLength = (unsigned int)(stubMsg.Buffer - (unsigned char *)pRpcMsg->Buffer); - - if (ext_flags.HasNewCorrDesc) - { - /* free extra correlation package */ - /* NdrCorrelationFree(&stubMsg); */ - } - - if (Oif_flags.HasPipes) - { - /* NdrPipesDone(...) */ - } - - /* free the full pointer translation tables */ - if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR) - NdrFullPointerXlatFree(stubMsg.FullPtrXlatTables); - - /* free server function stack */ - HeapFree(GetProcessHeap(), 0, args); - - return S_OK; -} - -void WINAPI NdrServerCall2(PRPC_MESSAGE pRpcMsg) -{ - DWORD dwPhase; - NdrStubCall2(NULL, NULL, pRpcMsg, &dwPhase); -} +/* + * NDR -Oi,-Oif,-Oicf Interpreter + * + * Copyright 2001 Ove Kåven, TransGaming Technologies + * Copyright 2003-5 Robert Shearman (for CodeWeavers) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + * + * TODO: + * - Pipes + * - Some types of binding handles + */ + +#include "config.h" +#include "wine/port.h" + +#include +#include +#include + +#include "windef.h" +#include "winbase.h" +#include "winerror.h" + +#include "objbase.h" +#include "rpc.h" +#include "rpcproxy.h" +#include "ndrtypes.h" + +#include "wine/debug.h" +#include "wine/rpcfc.h" + +#include "cpsf.h" +#include "ndr_misc.h" +#include "ndr_stubless.h" + +WINE_DEFAULT_DEBUG_CHANNEL(rpc); + +#define NDR_TABLE_MASK 127 + +static inline void call_buffer_sizer(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat) +{ + NDR_BUFFERSIZE m = NdrBufferSizer[pFormat[0] & NDR_TABLE_MASK]; + if (m) m(pStubMsg, pMemory, pFormat); + else + { + FIXME("format type 0x%x not implemented\n", pFormat[0]); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } +} + +static inline unsigned char *call_marshaller(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat) +{ + NDR_MARSHALL m = NdrMarshaller[pFormat[0] & NDR_TABLE_MASK]; + if (m) return m(pStubMsg, pMemory, pFormat); + else + { + FIXME("format type 0x%x not implemented\n", pFormat[0]); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + return NULL; + } +} + +static inline unsigned char *call_unmarshaller(PMIDL_STUB_MESSAGE pStubMsg, unsigned char **ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc) +{ + NDR_UNMARSHALL m = NdrUnmarshaller[pFormat[0] & NDR_TABLE_MASK]; + if (m) return m(pStubMsg, ppMemory, pFormat, fMustAlloc); + else + { + FIXME("format type 0x%x not implemented\n", pFormat[0]); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + return NULL; + } +} + +static inline void call_freer(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat) +{ + NDR_FREE m = NdrFreer[pFormat[0] & NDR_TABLE_MASK]; + if (m) m(pStubMsg, pMemory, pFormat); +} + +static inline unsigned long call_memory_sizer(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat) +{ + NDR_MEMORYSIZE m = NdrMemorySizer[pFormat[0] & NDR_TABLE_MASK]; + if (m) + { + unsigned char *saved_buffer = pStubMsg->Buffer; + unsigned long ret; + int saved_ignore_embedded_pointers = pStubMsg->IgnoreEmbeddedPointers; + pStubMsg->MemorySize = 0; + pStubMsg->IgnoreEmbeddedPointers = 1; + ret = m(pStubMsg, pFormat); + pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded_pointers; + pStubMsg->Buffer = saved_buffer; + return ret; + } + else + { + FIXME("format type 0x%x not implemented\n", pFormat[0]); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + return 0; + } +} + +#define STUBLESS_UNMARSHAL 1 +#define STUBLESS_CALLSERVER 2 +#define STUBLESS_CALCSIZE 3 +#define STUBLESS_GETBUFFER 4 +#define STUBLESS_MARSHAL 5 +#define STUBLESS_FREE 6 + +void WINAPI NdrRpcSmSetClientToOsf(PMIDL_STUB_MESSAGE pMessage) +{ +#if 0 /* these functions are not defined yet */ + pMessage->pfnAllocate = NdrRpcSmClientAllocate; + pMessage->pfnFree = NdrRpcSmClientFree; +#endif +} + +static void WINAPI dump_RPC_FC_PROC_PF(PARAM_ATTRIBUTES param_attributes) +{ + if (param_attributes.MustSize) TRACE(" MustSize"); + if (param_attributes.MustFree) TRACE(" MustFree"); + if (param_attributes.IsPipe) TRACE(" IsPipe"); + if (param_attributes.IsIn) TRACE(" IsIn"); + if (param_attributes.IsOut) TRACE(" IsOut"); + if (param_attributes.IsReturn) TRACE(" IsReturn"); + if (param_attributes.IsBasetype) TRACE(" IsBasetype"); + if (param_attributes.IsByValue) TRACE(" IsByValue"); + if (param_attributes.IsSimpleRef) TRACE(" IsSimpleRef"); + if (param_attributes.IsDontCallFreeInst) TRACE(" IsDontCallFreeInst"); + if (param_attributes.SaveForAsyncFinish) TRACE(" SaveForAsyncFinish"); + if (param_attributes.ServerAllocSize) TRACE(" ServerAllocSize = %d", param_attributes.ServerAllocSize * 8); +} + +static void WINAPI dump_INTERPRETER_OPT_FLAGS(INTERPRETER_OPT_FLAGS Oi2Flags) +{ + if (Oi2Flags.ServerMustSize) TRACE(" ServerMustSize"); + if (Oi2Flags.ClientMustSize) TRACE(" ClientMustSize"); + if (Oi2Flags.HasReturn) TRACE(" HasReturn"); + if (Oi2Flags.HasPipes) TRACE(" HasPipes"); + if (Oi2Flags.Unused) TRACE(" Unused"); + if (Oi2Flags.HasAsyncUuid) TRACE(" HasAsyncUuid"); + if (Oi2Flags.HasExtensions) TRACE(" HasExtensions"); + if (Oi2Flags.HasAsyncHandle) TRACE(" HasAsyncHandle"); + TRACE("\n"); +} + +#define ARG_FROM_OFFSET(stubMsg, offset) ((stubMsg).StackTop + (offset)) + +static PFORMAT_STRING client_get_handle( + PMIDL_STUB_MESSAGE pStubMsg, const NDR_PROC_HEADER *pProcHeader, + PFORMAT_STRING pFormat, handle_t *phBinding) +{ + /* binding */ + switch (pProcHeader->handle_type) + { + /* explicit binding: parse additional section */ + case RPC_FC_BIND_EXPLICIT: + switch (*pFormat) /* handle_type */ + { + case RPC_FC_BIND_PRIMITIVE: /* explicit primitive */ + { + const NDR_EHD_PRIMITIVE *pDesc = (const NDR_EHD_PRIMITIVE *)pFormat; + + TRACE("Explicit primitive handle @ %d\n", pDesc->offset); + + if (pDesc->flag) /* pointer to binding */ + *phBinding = **(handle_t **)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset); + else + *phBinding = *(handle_t *)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset); + return pFormat + sizeof(NDR_EHD_PRIMITIVE); + } + case RPC_FC_BIND_GENERIC: /* explicit generic */ + { + const NDR_EHD_GENERIC *pDesc = (const NDR_EHD_GENERIC *)pFormat; + void *pObject = NULL; + void *pArg; + const GENERIC_BINDING_ROUTINE_PAIR *pGenPair; + + TRACE("Explicit generic binding handle #%d\n", pDesc->binding_routine_pair_index); + + if (pDesc->flag_and_size & HANDLE_PARAM_IS_VIA_PTR) + pArg = *(void **)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset); + else + pArg = (void *)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset); + memcpy(&pObject, pArg, pDesc->flag_and_size & 0xf); + pGenPair = &pStubMsg->StubDesc->aGenericBindingRoutinePairs[pDesc->binding_routine_pair_index]; + *phBinding = pGenPair->pfnBind(pObject); + return pFormat + sizeof(NDR_EHD_GENERIC); + } + case RPC_FC_BIND_CONTEXT: /* explicit context */ + { + const NDR_EHD_CONTEXT *pDesc = (const NDR_EHD_CONTEXT *)pFormat; + NDR_CCONTEXT context_handle; + TRACE("Explicit bind context\n"); + if (pDesc->flags & HANDLE_PARAM_IS_VIA_PTR) + { + TRACE("\tHANDLE_PARAM_IS_VIA_PTR\n"); + context_handle = **(NDR_CCONTEXT **)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset); + } + else + context_handle = *(NDR_CCONTEXT *)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset); + if ((pDesc->flags & NDR_CONTEXT_HANDLE_CANNOT_BE_NULL) && + !context_handle) + { + ERR("null context handle isn't allowed\n"); + RpcRaiseException(RPC_X_SS_IN_NULL_CONTEXT); + return NULL; + } + *phBinding = NDRCContextBinding(context_handle); + /* FIXME: should we store this structure in stubMsg.pContext? */ + return pFormat + sizeof(NDR_EHD_CONTEXT); + } + default: + ERR("bad explicit binding handle type (0x%02x)\n", pProcHeader->handle_type); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + break; + case RPC_FC_BIND_GENERIC: /* implicit generic */ + FIXME("RPC_FC_BIND_GENERIC\n"); + RpcRaiseException(RPC_X_BAD_STUB_DATA); /* FIXME: remove when implemented */ + break; + case RPC_FC_BIND_PRIMITIVE: /* implicit primitive */ + TRACE("Implicit primitive handle\n"); + *phBinding = *pStubMsg->StubDesc->IMPLICIT_HANDLE_INFO.pPrimitiveHandle; + break; + case RPC_FC_CALLBACK_HANDLE: /* implicit callback */ + FIXME("RPC_FC_CALLBACK_HANDLE\n"); + break; + case RPC_FC_AUTO_HANDLE: /* implicit auto handle */ + /* strictly speaking, it isn't necessary to set hBinding here + * since it isn't actually used (hence the automatic in its name), + * but then why does MIDL generate a valid entry in the + * MIDL_STUB_DESC for it? */ + TRACE("Implicit auto handle\n"); + *phBinding = *pStubMsg->StubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle; + break; + default: + ERR("bad implicit binding handle type (0x%02x)\n", pProcHeader->handle_type); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + return pFormat; +} + +static void client_free_handle( + PMIDL_STUB_MESSAGE pStubMsg, const NDR_PROC_HEADER *pProcHeader, + PFORMAT_STRING pFormat, handle_t hBinding) +{ + /* binding */ + switch (pProcHeader->handle_type) + { + /* explicit binding: parse additional section */ + case RPC_FC_BIND_EXPLICIT: + switch (*pFormat) /* handle_type */ + { + case RPC_FC_BIND_GENERIC: /* explicit generic */ + { + const NDR_EHD_GENERIC *pDesc = (const NDR_EHD_GENERIC *)pFormat; + void *pObject = NULL; + void *pArg; + const GENERIC_BINDING_ROUTINE_PAIR *pGenPair; + + TRACE("Explicit generic binding handle #%d\n", pDesc->binding_routine_pair_index); + + if (pDesc->flag_and_size & HANDLE_PARAM_IS_VIA_PTR) + pArg = *(void **)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset); + else + pArg = (void *)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset); + memcpy(&pObject, pArg, pDesc->flag_and_size & 0xf); + pGenPair = &pStubMsg->StubDesc->aGenericBindingRoutinePairs[pDesc->binding_routine_pair_index]; + pGenPair->pfnUnbind(pObject, hBinding); + break; + } + case RPC_FC_BIND_CONTEXT: /* explicit context */ + case RPC_FC_BIND_PRIMITIVE: /* explicit primitive */ + break; + default: + ERR("bad explicit binding handle type (0x%02x)\n", pProcHeader->handle_type); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + break; + case RPC_FC_BIND_GENERIC: /* implicit generic */ + FIXME("RPC_FC_BIND_GENERIC\n"); + RpcRaiseException(RPC_X_BAD_STUB_DATA); /* FIXME: remove when implemented */ + break; + case RPC_FC_CALLBACK_HANDLE: /* implicit callback */ + case RPC_FC_BIND_PRIMITIVE: /* implicit primitive */ + case RPC_FC_AUTO_HANDLE: /* implicit auto handle */ + break; + default: + ERR("bad implicit binding handle type (0x%02x)\n", pProcHeader->handle_type); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } +} + +static void client_do_args(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, + int phase, unsigned short number_of_params, unsigned char *pRetVal) +{ + /* current format string offset */ + int current_offset = 0; + /* current stack offset */ + unsigned short current_stack_offset = 0; + /* counter */ + unsigned short i; + + for (i = 0; i < number_of_params; i++) + { + const NDR_PARAM_OIF_BASETYPE *pParam = + (const NDR_PARAM_OIF_BASETYPE *)&pFormat[current_offset]; + unsigned char * pArg; + + current_stack_offset = pParam->stack_offset; + pArg = ARG_FROM_OFFSET(*pStubMsg, current_stack_offset); + + TRACE("param[%d]: new format\n", i); + TRACE("\tparam_attributes:"); dump_RPC_FC_PROC_PF(pParam->param_attributes); TRACE("\n"); + TRACE("\tstack_offset: 0x%x\n", current_stack_offset); + TRACE("\tmemory addr (before): %p\n", pArg); + + if (pParam->param_attributes.IsBasetype) + { + const unsigned char * pTypeFormat = + &pParam->type_format_char; + + if (pParam->param_attributes.IsSimpleRef) + pArg = *(unsigned char **)pArg; + + TRACE("\tbase type: 0x%02x\n", *pTypeFormat); + + switch (phase) + { + case PROXY_CALCSIZE: + if (pParam->param_attributes.IsIn) + call_buffer_sizer(pStubMsg, pArg, pTypeFormat); + break; + case PROXY_MARSHAL: + if (pParam->param_attributes.IsIn) + call_marshaller(pStubMsg, pArg, pTypeFormat); + break; + case PROXY_UNMARSHAL: + if (pParam->param_attributes.IsOut) + { + if (pParam->param_attributes.IsReturn) + call_unmarshaller(pStubMsg, &pRetVal, pTypeFormat, 0); + else + call_unmarshaller(pStubMsg, &pArg, pTypeFormat, 0); + TRACE("pRetVal = %p\n", pRetVal); + } + break; + default: + RpcRaiseException(RPC_S_INTERNAL_ERROR); + } + + current_offset += sizeof(NDR_PARAM_OIF_BASETYPE); + } + else + { + const NDR_PARAM_OIF_OTHER *pParamOther = + (const NDR_PARAM_OIF_OTHER *)&pFormat[current_offset]; + + const unsigned char * pTypeFormat = + &(pStubMsg->StubDesc->pFormatTypes[pParamOther->type_offset]); + + /* if a simple ref pointer then we have to do the + * check for the pointer being non-NULL. */ + if (pParam->param_attributes.IsSimpleRef) + { + if (!*(unsigned char **)pArg) + RpcRaiseException(RPC_X_NULL_REF_POINTER); + } + + TRACE("\tcomplex type: 0x%02x\n", *pTypeFormat); + + switch (phase) + { + case PROXY_CALCSIZE: + if (pParam->param_attributes.IsIn) + { + if (pParam->param_attributes.IsByValue) + call_buffer_sizer(pStubMsg, pArg, pTypeFormat); + else + call_buffer_sizer(pStubMsg, *(unsigned char **)pArg, pTypeFormat); + } + break; + case PROXY_MARSHAL: + if (pParam->param_attributes.IsIn) + { + if (pParam->param_attributes.IsByValue) + call_marshaller(pStubMsg, pArg, pTypeFormat); + else + call_marshaller(pStubMsg, *(unsigned char **)pArg, pTypeFormat); + } + break; + case PROXY_UNMARSHAL: + if (pParam->param_attributes.IsOut) + { + if (pParam->param_attributes.IsReturn) + call_unmarshaller(pStubMsg, &pRetVal, pTypeFormat, 0); + else if (pParam->param_attributes.IsByValue) + call_unmarshaller(pStubMsg, &pArg, pTypeFormat, 0); + else + call_unmarshaller(pStubMsg, (unsigned char **)pArg, pTypeFormat, 0); + } + break; + default: + RpcRaiseException(RPC_S_INTERNAL_ERROR); + } + + current_offset += sizeof(NDR_PARAM_OIF_OTHER); + } + TRACE("\tmemory addr (after): %p\n", pArg); + } +} + +static void client_do_args_old_format(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat, int phase, unsigned short stack_size, + unsigned char *pRetVal, BOOL object_proc) +{ + /* current format string offset */ + int current_offset = 0; + /* current stack offset */ + unsigned short current_stack_offset = 0; + /* counter */ + unsigned short i; + + /* NOTE: V1 style format does't terminate on the number_of_params + * condition as it doesn't have this attribute. Instead it + * terminates when the stack size given in the header is exceeded. + */ + for (i = 0; TRUE; i++) + { + const NDR_PARAM_OI_BASETYPE *pParam = + (const NDR_PARAM_OI_BASETYPE *)&pFormat[current_offset]; + /* note: current_stack_offset starts after the This pointer + * if present, so adjust this */ + unsigned short current_stack_offset_adjusted = current_stack_offset + + (object_proc ? sizeof(void *) : 0); + unsigned char * pArg = ARG_FROM_OFFSET(*pStubMsg, current_stack_offset_adjusted); + + /* no more parameters; exit loop */ + if (current_stack_offset_adjusted >= stack_size) + break; + + TRACE("param[%d]: old format\n", i); + TRACE("\tparam_direction: 0x%x\n", pParam->param_direction); + TRACE("\tstack_offset: 0x%x\n", current_stack_offset_adjusted); + TRACE("\tmemory addr (before): %p\n", pArg); + + if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE || + pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE) + { + const unsigned char * pTypeFormat = + &pParam->type_format_char; + + TRACE("\tbase type 0x%02x\n", *pTypeFormat); + + switch (phase) + { + case PROXY_CALCSIZE: + if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE) + call_buffer_sizer(pStubMsg, pArg, pTypeFormat); + break; + case PROXY_MARSHAL: + if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE) + call_marshaller(pStubMsg, pArg, pTypeFormat); + break; + case PROXY_UNMARSHAL: + if (pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE) + { + if (pParam->param_direction & RPC_FC_RETURN_PARAM) + call_unmarshaller(pStubMsg, (unsigned char **)pRetVal, pTypeFormat, 0); + else + call_unmarshaller(pStubMsg, &pArg, pTypeFormat, 0); + } + break; + default: + RpcRaiseException(RPC_S_INTERNAL_ERROR); + } + + current_stack_offset += call_memory_sizer(pStubMsg, pTypeFormat); + current_offset += sizeof(NDR_PARAM_OI_BASETYPE); + } + else + { + const NDR_PARAM_OI_OTHER *pParamOther = + (const NDR_PARAM_OI_OTHER *)&pFormat[current_offset]; + + const unsigned char *pTypeFormat = + &pStubMsg->StubDesc->pFormatTypes[pParamOther->type_offset]; + + TRACE("\tcomplex type 0x%02x\n", *pTypeFormat); + + switch (phase) + { + case PROXY_CALCSIZE: + if (pParam->param_direction == RPC_FC_IN_PARAM || + pParam->param_direction & RPC_FC_IN_OUT_PARAM) + call_buffer_sizer(pStubMsg, *(unsigned char **)pArg, pTypeFormat); + break; + case PROXY_MARSHAL: + if (pParam->param_direction == RPC_FC_IN_PARAM || + pParam->param_direction & RPC_FC_IN_OUT_PARAM) + call_marshaller(pStubMsg, *(unsigned char **)pArg, pTypeFormat); + break; + case PROXY_UNMARSHAL: + if (pParam->param_direction == RPC_FC_IN_OUT_PARAM || + pParam->param_direction == RPC_FC_OUT_PARAM) + call_unmarshaller(pStubMsg, (unsigned char **)pArg, pTypeFormat, 0); + else if (pParam->param_direction == RPC_FC_RETURN_PARAM) + call_unmarshaller(pStubMsg, (unsigned char **)pRetVal, pTypeFormat, 0); + break; + default: + RpcRaiseException(RPC_S_INTERNAL_ERROR); + } + + current_stack_offset += pParamOther->stack_size * sizeof(INT); + current_offset += sizeof(NDR_PARAM_OI_OTHER); + } + TRACE("\tmemory addr (after): %p\n", pArg); + } +} + +/* the return type should be CLIENT_CALL_RETURN, but this is incompatible + * with the way gcc returns structures. "void *" should be the largest type + * that MIDL should allow you to return anyway */ +LONG_PTR WINAPIV NdrClientCall2(PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pFormat, ...) +{ + /* pointer to start of stack where arguments start */ + RPC_MESSAGE rpcMsg; + MIDL_STUB_MESSAGE stubMsg; + handle_t hBinding = NULL; + /* procedure number */ + unsigned short procedure_number; + /* size of stack */ + unsigned short stack_size; + /* number of parameters. optional for client to give it to us */ + unsigned char number_of_params = ~0; + /* cache of Oif_flags from v2 procedure header */ + INTERPRETER_OPT_FLAGS Oif_flags = { 0 }; + /* cache of extension flags from NDR_PROC_HEADER_EXTS */ + INTERPRETER_OPT_FLAGS2 ext_flags = { 0 }; + /* the type of pass we are currently doing */ + int phase; + /* header for procedure string */ + const NDR_PROC_HEADER * pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0]; + /* -Oif or -Oicf generated format */ + BOOL bV2Format = FALSE; + /* the value to return to the client from the remote procedure */ + LONG_PTR RetVal = 0; + /* the pointer to the object when in OLE mode */ + void * This = NULL; + PFORMAT_STRING pHandleFormat; + + TRACE("pStubDesc %p, pFormat %p, ...\n", pStubDesc, pFormat); + + /* Later NDR language versions probably won't be backwards compatible */ + if (pStubDesc->Version > 0x50002) + { + FIXME("Incompatible stub description version: 0x%x\n", pStubDesc->Version); + RpcRaiseException(RPC_X_WRONG_STUB_VERSION); + } + + if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS) + { + const NDR_PROC_HEADER_RPC *pProcHeader = (const NDR_PROC_HEADER_RPC *)&pFormat[0]; + stack_size = pProcHeader->stack_size; + procedure_number = pProcHeader->proc_num; + pFormat += sizeof(NDR_PROC_HEADER_RPC); + } + else + { + stack_size = pProcHeader->stack_size; + procedure_number = pProcHeader->proc_num; + pFormat += sizeof(NDR_PROC_HEADER); + } + TRACE("stack size: 0x%x\n", stack_size); + TRACE("proc num: %d\n", procedure_number); + + /* create the full pointer translation tables, if requested */ + if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR) + stubMsg.FullPtrXlatTables = NdrFullPointerXlatInit(0,XLAT_CLIENT); + + if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT) + { + /* object is always the first argument */ + This = **(void *const **)(&pFormat+1); + NdrProxyInitialize(This, &rpcMsg, &stubMsg, pStubDesc, procedure_number); + } + else + NdrClientInitializeNew(&rpcMsg, &stubMsg, pStubDesc, procedure_number); + + TRACE("Oi_flags = 0x%02x\n", pProcHeader->Oi_flags); + TRACE("MIDL stub version = 0x%x\n", pStubDesc->MIDLVersion); + + /* needed for conformance of top-level objects */ +#ifdef __i386__ + stubMsg.StackTop = *(unsigned char **)(&pFormat+1); +#else +# warning Stack not retrieved for your CPU architecture +#endif + + pHandleFormat = pFormat; + + /* we only need a handle if this isn't an object method */ + if (!(pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)) + { + pFormat = client_get_handle(&stubMsg, pProcHeader, pHandleFormat, &hBinding); + if (!pFormat) return 0; + } + + bV2Format = (pStubDesc->Version >= 0x20000); + + if (bV2Format) + { + const NDR_PROC_PARTIAL_OIF_HEADER *pOIFHeader = + (const NDR_PROC_PARTIAL_OIF_HEADER *)pFormat; + + Oif_flags = pOIFHeader->Oi2Flags; + number_of_params = pOIFHeader->number_of_params; + + pFormat += sizeof(NDR_PROC_PARTIAL_OIF_HEADER); + } + + TRACE("Oif_flags = "); dump_INTERPRETER_OPT_FLAGS(Oif_flags); + + if (Oif_flags.HasExtensions) + { + const NDR_PROC_HEADER_EXTS *pExtensions = + (const NDR_PROC_HEADER_EXTS *)pFormat; + ext_flags = pExtensions->Flags2; + pFormat += pExtensions->Size; + } + + stubMsg.BufferLength = 0; + + /* store the RPC flags away */ + if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS) + rpcMsg.RpcFlags = ((const NDR_PROC_HEADER_RPC *)pProcHeader)->rpc_flags; + + /* use alternate memory allocation routines */ + if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCSSALLOC) + NdrRpcSmSetClientToOsf(&stubMsg); + + if (Oif_flags.HasPipes) + { + FIXME("pipes not supported yet\n"); + RpcRaiseException(RPC_X_WRONG_STUB_VERSION); /* FIXME: remove when implemented */ + /* init pipes package */ + /* NdrPipesInitialize(...) */ + } + if (ext_flags.HasNewCorrDesc) + { + /* initialize extra correlation package */ + FIXME("new correlation description not implemented\n"); + stubMsg.fHasNewCorrDesc = TRUE; + } + + /* order of phases: + * 1. PROXY_CALCSIZE - calculate the buffer size + * 2. PROXY_GETBUFFER - allocate the buffer + * 3. PROXY_MARHSAL - marshal [in] params into the buffer + * 4. PROXY_SENDRECEIVE - send/receive buffer + * 5. PROXY_UNMARHSAL - unmarshal [out] params from buffer + */ + for (phase = PROXY_CALCSIZE; phase <= PROXY_UNMARSHAL; phase++) + { + TRACE("phase = %d\n", phase); + switch (phase) + { + case PROXY_GETBUFFER: + /* allocate the buffer */ + if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT) + NdrProxyGetBuffer(This, &stubMsg); + else if (Oif_flags.HasPipes) + /* NdrGetPipeBuffer(...) */ + FIXME("pipes not supported yet\n"); + else + { + if (pProcHeader->handle_type == RPC_FC_AUTO_HANDLE) +#if 0 + NdrNsGetBuffer(&stubMsg, stubMsg.BufferLength, hBinding); +#else + FIXME("using auto handle - call NdrNsGetBuffer when it gets implemented\n"); +#endif + else + NdrGetBuffer(&stubMsg, stubMsg.BufferLength, hBinding); + } + break; + case PROXY_SENDRECEIVE: + /* send the [in] params and receive the [out] and [retval] + * params */ + if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT) + NdrProxySendReceive(This, &stubMsg); + else if (Oif_flags.HasPipes) + /* NdrPipesSendReceive(...) */ + FIXME("pipes not supported yet\n"); + else + { + if (pProcHeader->handle_type == RPC_FC_AUTO_HANDLE) +#if 0 + NdrNsSendReceive(&stubMsg, stubMsg.Buffer, pStubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle); +#else + FIXME("using auto handle - call NdrNsSendReceive when it gets implemented\n"); +#endif + else + NdrSendReceive(&stubMsg, stubMsg.Buffer); + } + + /* convert strings, floating point values and endianess into our + * preferred format */ + if ((rpcMsg.DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION) + NdrConvert(&stubMsg, pFormat); + + break; + case PROXY_CALCSIZE: + case PROXY_MARSHAL: + case PROXY_UNMARSHAL: + if (bV2Format) + client_do_args(&stubMsg, pFormat, phase, number_of_params, + (unsigned char *)&RetVal); + else + client_do_args_old_format(&stubMsg, pFormat, phase, stack_size, + (unsigned char *)&RetVal, + (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)); + break; + default: + ERR("shouldn't reach here. phase %d\n", phase); + break; + } + } + + if (ext_flags.HasNewCorrDesc) + { + /* free extra correlation package */ + /* NdrCorrelationFree(&stubMsg); */ + } + + if (Oif_flags.HasPipes) + { + /* NdrPipesDone(...) */ + } + + /* free the full pointer translation tables */ + if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR) + NdrFullPointerXlatFree(stubMsg.FullPtrXlatTables); + + /* free marshalling buffer */ + if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT) + NdrProxyFreeBuffer(This, &stubMsg); + else + { + NdrFreeBuffer(&stubMsg); + client_free_handle(&stubMsg, pProcHeader, pHandleFormat, hBinding); + } + + TRACE("RetVal = 0x%lx\n", RetVal); + + return RetVal; +} + +/* calls a function with the specificed arguments, restoring the stack + * properly afterwards as we don't know the calling convention of the + * function */ +#if defined __i386__ && defined _MSC_VER +__declspec(naked) LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned int stack_size) +{ + __asm + { + push ebp + push edi ; Save registers + push esi + mov ebp, esp + mov eax, [ebp+16] ; Get stack size + sub esp, eax ; Make room in stack for arguments + mov edi, esp + mov ecx, eax + mov esi, [ebp+12] + shr ecx, 2 + cld + rep movsd ; Copy dword blocks + call [ebp+8] ; Call function + lea esp, [ebp-8] ; Restore stack + pop esi ; Restore registers + pop edi + pop ebp + ret + } +} +#elif defined __i386__ && defined __GNUC__ +LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned int stack_size); +__ASM_GLOBAL_FUNC(call_server_func, + "pushl %ebp\n\t" + "movl %esp, %ebp\n\t" + "pushl %edi\n\t" /* Save registers */ + "pushl %esi\n\t" + "movl 16(%ebp), %eax\n\t" /* Get stack size */ + "subl %eax, %esp\n\t" /* Make room in stack for arguments */ + "andl $~15, %esp\n\t" /* Make sure stack has 16-byte alignment for Mac OS X */ + "movl %esp, %edi\n\t" + "movl %eax, %ecx\n\t" + "movl 12(%ebp), %esi\n\t" + "shrl $2, %ecx\n\t" /* divide by 4 */ + "cld\n\t" + "rep; movsl\n\t" /* Copy dword blocks */ + "call *8(%ebp)\n\t" /* Call function */ + "leal -8(%ebp), %esp\n\t" /* Restore stack */ + "popl %esi\n\t" /* Restore registers */ + "popl %edi\n\t" + "popl %ebp\n\t" + "ret\n" ) +#else +#warning call_server_func not implemented for your architecture +LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned short stack_size) +{ + FIXME("Not implemented for your architecture\n"); + return 0; +} +#endif + +static DWORD calc_arg_size(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat) +{ + DWORD size; + switch(*pFormat) + { + case RPC_FC_STRUCT: + size = *(const WORD*)(pFormat + 2); + break; + case RPC_FC_CARRAY: + size = *(const WORD*)(pFormat + 2); + ComputeConformance(pStubMsg, NULL, pFormat + 4, 0); + size *= pStubMsg->MaxCount; + break; + case RPC_FC_SMFARRAY: + size = *(const WORD*)(pFormat + 2); + break; + case RPC_FC_LGFARRAY: + size = *(const DWORD*)(pFormat + 2); + break; + default: + FIXME("Unhandled type %02x\n", *pFormat); + /* fallthrough */ + case RPC_FC_RP: + size = sizeof(void *); + break; + } + return size; +} + +static LONG_PTR *stub_do_args(MIDL_STUB_MESSAGE *pStubMsg, + PFORMAT_STRING pFormat, int phase, + unsigned char *args, + unsigned short number_of_params) +{ + /* counter */ + unsigned short i; + /* current format string offset */ + int current_offset = 0; + /* current stack offset */ + unsigned short current_stack_offset = 0; + /* location to put retval into */ + LONG_PTR *retval_ptr = NULL; + + for (i = 0; i < number_of_params; i++) + { + const NDR_PARAM_OIF_BASETYPE *pParam = + (const NDR_PARAM_OIF_BASETYPE *)&pFormat[current_offset]; + unsigned char *pArg; + + current_stack_offset = pParam->stack_offset; + pArg = (unsigned char *)(args+current_stack_offset); + + TRACE("param[%d]: new format\n", i); + TRACE("\tparam_attributes:"); dump_RPC_FC_PROC_PF(pParam->param_attributes); TRACE("\n"); + TRACE("\tstack_offset: 0x%x\n", current_stack_offset); + TRACE("\tmemory addr (before): %p -> %p\n", pArg, *(unsigned char **)pArg); + + if (pParam->param_attributes.IsBasetype) + { + const unsigned char *pTypeFormat = + &pParam->type_format_char; + + TRACE("\tbase type: 0x%02x\n", *pTypeFormat); + + switch (phase) + { + case STUBLESS_MARSHAL: + if (pParam->param_attributes.IsOut || pParam->param_attributes.IsReturn) + { + if (pParam->param_attributes.IsSimpleRef) + call_marshaller(pStubMsg, *(unsigned char **)pArg, pTypeFormat); + else + call_marshaller(pStubMsg, pArg, pTypeFormat); + } + break; + case STUBLESS_FREE: + if (pParam->param_attributes.ServerAllocSize) + HeapFree(GetProcessHeap(), 0, *(void **)pArg); + break; + case STUBLESS_UNMARSHAL: + if (pParam->param_attributes.ServerAllocSize) + *(void **)pArg = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + pParam->param_attributes.ServerAllocSize * 8); + + if (pParam->param_attributes.IsIn) + { + if (pParam->param_attributes.IsSimpleRef) + call_unmarshaller(pStubMsg, (unsigned char **)pArg, pTypeFormat, 0); + else + call_unmarshaller(pStubMsg, &pArg, pTypeFormat, 0); + } + + /* make a note of the address of the return value parameter for later */ + if (pParam->param_attributes.IsReturn) + retval_ptr = (LONG_PTR *)pArg; + + break; + case STUBLESS_CALCSIZE: + if (pParam->param_attributes.IsOut || pParam->param_attributes.IsReturn) + { + if (pParam->param_attributes.IsSimpleRef) + call_buffer_sizer(pStubMsg, *(unsigned char **)pArg, pTypeFormat); + else + call_buffer_sizer(pStubMsg, pArg, pTypeFormat); + } + break; + default: + RpcRaiseException(RPC_S_INTERNAL_ERROR); + } + + current_offset += sizeof(NDR_PARAM_OIF_BASETYPE); + } + else + { + const NDR_PARAM_OIF_OTHER *pParamOther = + (const NDR_PARAM_OIF_OTHER *)&pFormat[current_offset]; + + const unsigned char * pTypeFormat = + &(pStubMsg->StubDesc->pFormatTypes[pParamOther->type_offset]); + + TRACE("\tcomplex type 0x%02x\n", *pTypeFormat); + + switch (phase) + { + case STUBLESS_MARSHAL: + if (pParam->param_attributes.IsOut || pParam->param_attributes.IsReturn) + { + if (pParam->param_attributes.IsByValue) + call_marshaller(pStubMsg, pArg, pTypeFormat); + else + call_marshaller(pStubMsg, *(unsigned char **)pArg, pTypeFormat); + } + break; + case STUBLESS_FREE: + if (pParam->param_attributes.MustFree) + { + if (pParam->param_attributes.IsByValue) + call_freer(pStubMsg, pArg, pTypeFormat); + else + call_freer(pStubMsg, *(unsigned char **)pArg, pTypeFormat); + } + + if (pParam->param_attributes.IsOut && + !pParam->param_attributes.IsIn && + !pParam->param_attributes.IsByValue && + !pParam->param_attributes.ServerAllocSize) + { + pStubMsg->pfnFree(*(void **)pArg); + } + + if (pParam->param_attributes.ServerAllocSize) + HeapFree(GetProcessHeap(), 0, *(void **)pArg); + /* FIXME: call call_freer here for IN types with MustFree set */ + break; + case STUBLESS_UNMARSHAL: + if (pParam->param_attributes.ServerAllocSize) + *(void **)pArg = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + pParam->param_attributes.ServerAllocSize * 8); + + if (pParam->param_attributes.IsIn) + { + if (pParam->param_attributes.IsByValue) + call_unmarshaller(pStubMsg, &pArg, pTypeFormat, 0); + else + call_unmarshaller(pStubMsg, (unsigned char **)pArg, pTypeFormat, 0); + } + else if (pParam->param_attributes.IsOut && + !pParam->param_attributes.ServerAllocSize && + !pParam->param_attributes.IsByValue) + { + DWORD size = calc_arg_size(pStubMsg, pTypeFormat); + + if(size) + { + *(void **)pArg = NdrAllocate(pStubMsg, size); + memset(*(void **)pArg, 0, size); + } + } + break; + case STUBLESS_CALCSIZE: + if (pParam->param_attributes.IsOut || pParam->param_attributes.IsReturn) + { + if (pParam->param_attributes.IsByValue) + call_buffer_sizer(pStubMsg, pArg, pTypeFormat); + else + call_buffer_sizer(pStubMsg, *(unsigned char **)pArg, pTypeFormat); + } + break; + default: + RpcRaiseException(RPC_S_INTERNAL_ERROR); + } + + current_offset += sizeof(NDR_PARAM_OIF_OTHER); + } + TRACE("\tmemory addr (after): %p -> %p\n", pArg, *(unsigned char **)pArg); + } + + return retval_ptr; +} + +static LONG_PTR *stub_do_old_args(MIDL_STUB_MESSAGE *pStubMsg, + PFORMAT_STRING pFormat, int phase, + unsigned char *args, + unsigned short stack_size, BOOL object) +{ + /* counter */ + unsigned short i; + /* current format string offset */ + int current_offset = 0; + /* current stack offset */ + unsigned short current_stack_offset = 0; + /* location to put retval into */ + LONG_PTR *retval_ptr = NULL; + + for (i = 0; TRUE; i++) + { + const NDR_PARAM_OI_BASETYPE *pParam = + (const NDR_PARAM_OI_BASETYPE *)&pFormat[current_offset]; + /* note: current_stack_offset starts after the This pointer + * if present, so adjust this */ + unsigned short current_stack_offset_adjusted = current_stack_offset + + (object ? sizeof(void *) : 0); + unsigned char *pArg = (unsigned char *)(args+current_stack_offset_adjusted); + + /* no more parameters; exit loop */ + if (current_stack_offset_adjusted >= stack_size) + break; + + TRACE("param[%d]: old format\n", i); + TRACE("\tparam_direction: 0x%x\n", pParam->param_direction); + TRACE("\tstack_offset: 0x%x\n", current_stack_offset_adjusted); + + if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE || + pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE) + { + const unsigned char *pTypeFormat = + &pParam->type_format_char; + + TRACE("\tbase type 0x%02x\n", *pTypeFormat); + + switch (phase) + { + case STUBLESS_MARSHAL: + if (pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE) + call_marshaller(pStubMsg, pArg, pTypeFormat); + break; + case STUBLESS_FREE: + if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE) + call_freer(pStubMsg, pArg, pTypeFormat); + break; + case STUBLESS_UNMARSHAL: + if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE) + call_unmarshaller(pStubMsg, &pArg, pTypeFormat, 0); + else if (pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE) + retval_ptr = (LONG_PTR *)pArg; + break; + case STUBLESS_CALCSIZE: + if (pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE) + call_buffer_sizer(pStubMsg, pArg, pTypeFormat); + break; + default: + RpcRaiseException(RPC_S_INTERNAL_ERROR); + } + + current_stack_offset += call_memory_sizer(pStubMsg, pTypeFormat); + current_offset += sizeof(NDR_PARAM_OI_BASETYPE); + } + else + { + const NDR_PARAM_OI_OTHER *pParamOther = + (const NDR_PARAM_OI_OTHER *)&pFormat[current_offset]; + + const unsigned char * pTypeFormat = + &pStubMsg->StubDesc->pFormatTypes[pParamOther->type_offset]; + + TRACE("\tcomplex type 0x%02x\n", *pTypeFormat); + + switch (phase) + { + case STUBLESS_MARSHAL: + if (pParam->param_direction == RPC_FC_OUT_PARAM || + pParam->param_direction == RPC_FC_IN_OUT_PARAM || + pParam->param_direction == RPC_FC_RETURN_PARAM) + call_marshaller(pStubMsg, *(unsigned char **)pArg, pTypeFormat); + break; + case STUBLESS_FREE: + if (pParam->param_direction == RPC_FC_IN_OUT_PARAM || + pParam->param_direction == RPC_FC_IN_PARAM) + call_freer(pStubMsg, *(unsigned char **)pArg, pTypeFormat); + else if (pParam->param_direction == RPC_FC_OUT_PARAM) + pStubMsg->pfnFree(*(void **)pArg); + break; + case STUBLESS_UNMARSHAL: + if (pParam->param_direction == RPC_FC_IN_OUT_PARAM || + pParam->param_direction == RPC_FC_IN_PARAM) + call_unmarshaller(pStubMsg, (unsigned char **)pArg, pTypeFormat, 0); + else if (pParam->param_direction == RPC_FC_RETURN_PARAM) + retval_ptr = (LONG_PTR *)pArg; + else if (pParam->param_direction == RPC_FC_OUT_PARAM) + { + DWORD size = calc_arg_size(pStubMsg, pTypeFormat); + + if(size) + { + *(void **)pArg = NdrAllocate(pStubMsg, size); + memset(*(void **)pArg, 0, size); + } + } + break; + case STUBLESS_CALCSIZE: + if (pParam->param_direction == RPC_FC_OUT_PARAM || + pParam->param_direction == RPC_FC_IN_OUT_PARAM || + pParam->param_direction == RPC_FC_RETURN_PARAM) + call_buffer_sizer(pStubMsg, *(unsigned char **)pArg, pTypeFormat); + break; + default: + RpcRaiseException(RPC_S_INTERNAL_ERROR); + } + + current_stack_offset += pParamOther->stack_size * sizeof(INT); + current_offset += sizeof(NDR_PARAM_OI_OTHER); + } + } + + return retval_ptr; +} + +/*********************************************************************** + * NdrStubCall2 [RPCRT4.@] + * + * Unmarshals [in] parameters, calls either a method in an object or a server + * function, marshals any [out] parameters and frees any allocated data. + * + * NOTES + * Used by stubless MIDL-generated code. + */ +LONG WINAPI NdrStubCall2( + struct IRpcStubBuffer * pThis, + struct IRpcChannelBuffer * pChannel, + PRPC_MESSAGE pRpcMsg, + DWORD * pdwStubPhase) +{ + const MIDL_SERVER_INFO *pServerInfo; + const MIDL_STUB_DESC *pStubDesc; + PFORMAT_STRING pFormat; + MIDL_STUB_MESSAGE stubMsg; + /* pointer to start of stack to pass into stub implementation */ + unsigned char * args; + /* size of stack */ + unsigned short stack_size; + /* number of parameters. optional for client to give it to us */ + unsigned char number_of_params = ~0; + /* cache of Oif_flags from v2 procedure header */ + INTERPRETER_OPT_FLAGS Oif_flags = { 0 }; + /* cache of extension flags from NDR_PROC_HEADER_EXTS */ + INTERPRETER_OPT_FLAGS2 ext_flags = { 0 }; + /* the type of pass we are currently doing */ + int phase; + /* header for procedure string */ + const NDR_PROC_HEADER *pProcHeader; + /* offset in format string for start of params */ + int parameter_start_offset; + /* current format string offset */ + int current_offset; + /* -Oif or -Oicf generated format */ + BOOL bV2Format = FALSE; + /* location to put retval into */ + LONG_PTR *retval_ptr = NULL; + + TRACE("pThis %p, pChannel %p, pRpcMsg %p, pdwStubPhase %p\n", pThis, pChannel, pRpcMsg, pdwStubPhase); + + if (pThis) + pServerInfo = CStdStubBuffer_GetServerInfo(pThis); + else + pServerInfo = ((RPC_SERVER_INTERFACE *)pRpcMsg->RpcInterfaceInformation)->InterpreterInfo; + + pStubDesc = pServerInfo->pStubDesc; + pFormat = pServerInfo->ProcString + pServerInfo->FmtStringOffset[pRpcMsg->ProcNum]; + pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0]; + + /* Later NDR language versions probably won't be backwards compatible */ + if (pStubDesc->Version > 0x50002) + { + FIXME("Incompatible stub description version: 0x%x\n", pStubDesc->Version); + RpcRaiseException(RPC_X_WRONG_STUB_VERSION); + } + + /* create the full pointer translation tables, if requested */ + if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR) + stubMsg.FullPtrXlatTables = NdrFullPointerXlatInit(0,XLAT_SERVER); + + if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS) + { + const NDR_PROC_HEADER_RPC *pProcHeader = (const NDR_PROC_HEADER_RPC *)&pFormat[0]; + stack_size = pProcHeader->stack_size; + current_offset = sizeof(NDR_PROC_HEADER_RPC); + + } + else + { + stack_size = pProcHeader->stack_size; + current_offset = sizeof(NDR_PROC_HEADER); + } + + TRACE("Oi_flags = 0x%02x\n", pProcHeader->Oi_flags); + + /* binding */ + switch (pProcHeader->handle_type) + { + /* explicit binding: parse additional section */ + case RPC_FC_BIND_EXPLICIT: + switch (pFormat[current_offset]) /* handle_type */ + { + case RPC_FC_BIND_PRIMITIVE: /* explicit primitive */ + current_offset += sizeof(NDR_EHD_PRIMITIVE); + break; + case RPC_FC_BIND_GENERIC: /* explicit generic */ + current_offset += sizeof(NDR_EHD_GENERIC); + break; + case RPC_FC_BIND_CONTEXT: /* explicit context */ + current_offset += sizeof(NDR_EHD_CONTEXT); + break; + default: + ERR("bad explicit binding handle type (0x%02x)\n", pProcHeader->handle_type); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + break; + case RPC_FC_BIND_GENERIC: /* implicit generic */ + case RPC_FC_BIND_PRIMITIVE: /* implicit primitive */ + case RPC_FC_CALLBACK_HANDLE: /* implicit callback */ + case RPC_FC_AUTO_HANDLE: /* implicit auto handle */ + break; + default: + ERR("bad implicit binding handle type (0x%02x)\n", pProcHeader->handle_type); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + + bV2Format = (pStubDesc->Version >= 0x20000); + + if (bV2Format) + { + const NDR_PROC_PARTIAL_OIF_HEADER *pOIFHeader = + (const NDR_PROC_PARTIAL_OIF_HEADER *)&pFormat[current_offset]; + + Oif_flags = pOIFHeader->Oi2Flags; + number_of_params = pOIFHeader->number_of_params; + + current_offset += sizeof(NDR_PROC_PARTIAL_OIF_HEADER); + } + + TRACE("Oif_flags = "); dump_INTERPRETER_OPT_FLAGS(Oif_flags); + + if (Oif_flags.HasExtensions) + { + const NDR_PROC_HEADER_EXTS *pExtensions = + (const NDR_PROC_HEADER_EXTS *)&pFormat[current_offset]; + ext_flags = pExtensions->Flags2; + current_offset += pExtensions->Size; + } + + if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT) + NdrStubInitialize(pRpcMsg, &stubMsg, pStubDesc, pChannel); + else + NdrServerInitializeNew(pRpcMsg, &stubMsg, pStubDesc); + + /* store the RPC flags away */ + if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS) + pRpcMsg->RpcFlags = ((const NDR_PROC_HEADER_RPC *)pProcHeader)->rpc_flags; + + /* use alternate memory allocation routines */ + if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCSSALLOC) +#if 0 + NdrRpcSsEnableAllocate(&stubMsg); +#else + FIXME("Set RPCSS memory allocation routines\n"); +#endif + + if (Oif_flags.HasPipes) + { + FIXME("pipes not supported yet\n"); + RpcRaiseException(RPC_X_WRONG_STUB_VERSION); /* FIXME: remove when implemented */ + /* init pipes package */ + /* NdrPipesInitialize(...) */ + } + if (ext_flags.HasNewCorrDesc) + { + /* initialize extra correlation package */ + FIXME("new correlation description not implemented\n"); + stubMsg.fHasNewCorrDesc = TRUE; + } + + /* convert strings, floating point values and endianess into our + * preferred format */ + if ((pRpcMsg->DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION) + NdrConvert(&stubMsg, pFormat); + + parameter_start_offset = current_offset; + + TRACE("allocating memory for stack of size %x\n", stack_size); + + args = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, stack_size); + stubMsg.StackTop = args; /* used by conformance of top-level objects */ + + /* add the implicit This pointer as the first arg to the function if we + * are calling an object method */ + if (pThis) + *(void **)args = ((CStdStubBuffer *)pThis)->pvServerObject; + + /* order of phases: + * 1. STUBLESS_UNMARHSAL - unmarshal [in] params from buffer + * 2. STUBLESS_CALLSERVER - send/receive buffer + * 3. STUBLESS_CALCSIZE - get [out] buffer size + * 4. STUBLESS_GETBUFFER - allocate [out] buffer + * 5. STUBLESS_MARHSAL - marshal [out] params to buffer + */ + for (phase = STUBLESS_UNMARSHAL; phase <= STUBLESS_FREE; phase++) + { + TRACE("phase = %d\n", phase); + switch (phase) + { + case STUBLESS_CALLSERVER: + /* call the server function */ + if (pServerInfo->ThunkTable && pServerInfo->ThunkTable[pRpcMsg->ProcNum]) + pServerInfo->ThunkTable[pRpcMsg->ProcNum](&stubMsg); + else + { + SERVER_ROUTINE func; + LONG_PTR retval; + + if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT) + { + SERVER_ROUTINE *vtbl = *(SERVER_ROUTINE **)((CStdStubBuffer *)pThis)->pvServerObject; + func = vtbl[pRpcMsg->ProcNum]; + } + else + func = pServerInfo->DispatchTable[pRpcMsg->ProcNum]; + + /* FIXME: what happens with return values that don't fit into a single register on x86? */ + retval = call_server_func(func, args, stack_size); + + if (retval_ptr) + { + TRACE("stub implementation returned 0x%lx\n", retval); + *retval_ptr = retval; + } + else + TRACE("void stub implementation\n"); + } + + stubMsg.Buffer = NULL; + stubMsg.BufferLength = 0; + + break; + case STUBLESS_GETBUFFER: + if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT) + NdrStubGetBuffer(pThis, pChannel, &stubMsg); + else + { + RPC_STATUS Status; + + pRpcMsg->BufferLength = stubMsg.BufferLength; + /* allocate buffer for [out] and [ret] params */ + Status = I_RpcGetBuffer(pRpcMsg); + if (Status) + RpcRaiseException(Status); + stubMsg.BufferStart = pRpcMsg->Buffer; + stubMsg.BufferEnd = stubMsg.BufferStart + stubMsg.BufferLength; + stubMsg.Buffer = stubMsg.BufferStart; + } + break; + case STUBLESS_MARSHAL: + case STUBLESS_UNMARSHAL: + case STUBLESS_CALCSIZE: + case STUBLESS_FREE: + if (bV2Format) + retval_ptr = stub_do_args(&stubMsg, &pFormat[parameter_start_offset], + phase, args, number_of_params); + else + retval_ptr = stub_do_old_args(&stubMsg, &pFormat[parameter_start_offset], + phase, args, stack_size, + (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)); + + break; + default: + ERR("shouldn't reach here. phase %d\n", phase); + break; + } + } + + pRpcMsg->BufferLength = (unsigned int)(stubMsg.Buffer - (unsigned char *)pRpcMsg->Buffer); + + if (ext_flags.HasNewCorrDesc) + { + /* free extra correlation package */ + /* NdrCorrelationFree(&stubMsg); */ + } + + if (Oif_flags.HasPipes) + { + /* NdrPipesDone(...) */ + } + + /* free the full pointer translation tables */ + if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR) + NdrFullPointerXlatFree(stubMsg.FullPtrXlatTables); + + /* free server function stack */ + HeapFree(GetProcessHeap(), 0, args); + + return S_OK; +} + +/*********************************************************************** + * NdrServerCall2 [RPCRT4.@] + */ +void WINAPI NdrServerCall2(PRPC_MESSAGE pRpcMsg) +{ + DWORD dwPhase; + NdrStubCall2(NULL, NULL, pRpcMsg, &dwPhase); +} diff --git a/reactos/dll/win32/rpcrt4_new/ndr_stubless.h b/reactos/dll/win32/rpcrt4_new/ndr_stubless.h new file mode 100644 index 00000000000..1bd3a952d74 --- /dev/null +++ b/reactos/dll/win32/rpcrt4_new/ndr_stubless.h @@ -0,0 +1,236 @@ +/* + * NDR -Oi,-Oif,-Oicf Interpreter + * + * Copyright 2007 Robert Shearman (for CodeWeavers) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/* there can't be any alignment with the structures in this file */ +#include "pshpack1.h" + +/* From http://msdn.microsoft.com/library/default.asp?url=/library/en-us/rpc/rpc/parameter_descriptors.asp */ +typedef struct _NDR_PROC_HEADER +{ + /* type of handle to use: + * RPC_FC_BIND_EXPLICIT = 0 - Explicit handle. + * Handle is passed as a parameter to the function. + * Indicates that explicit handle information follows the header, + * which actually describes the handle. + * RPC_FC_BIND_GENERIC = 31 - Implicit handle with custom binding routines + * (MIDL_STUB_DESC::IMPLICIT_HANDLE_INFO::pGenericBindingInfo) + * RPC_FC_BIND_PRIMITIVE = 32 - Implicit handle using handle_t created by + * calling application + * RPC_FC_AUTO_HANDLE = 33 - Automatic handle + * RPC_FC_CALLBACK_HANDLE = 34 - undocmented + */ + unsigned char handle_type; + + /* procedure flags: + * Oi_FULL_PTR_USED = 0x01 - A full pointer can have the value NULL and can + * change during the call from NULL to non-NULL and supports aliasing + * and cycles. Indicates that the NdrFullPointerXlatInit function + * should be called. + * Oi_RPCSS_ALLOC_USED = 0x02 - Use RpcSS allocate/free routines instead of + * normal allocate/free routines + * Oi_OBJECT_PROC = 0x04 - Indicates a procedure that is part of an OLE + * interface, rather than a DCE RPC interface. + * Oi_HAS_RPCFLAGS = 0x08 - Indicates that the rpc_flags element is + * present in the header. + * Oi_HAS_COMM_OR_FAULT = 0x20 - If Oi_OBJECT_PROC not present only then + * indicates that the procedure has the comm_status or fault_status + * MIDL attribute. + * Oi_OBJ_USE_V2_INTERPRETER = 0x20 - If Oi_OBJECT_PROC present only + * then indicates that the format string is in -Oif or -Oicf format + * Oi_USE_NEW_INIT_ROUTINES = 0x40 - Use NdrXInitializeNew instead of + * NdrXInitialize? + */ + unsigned char Oi_flags; + + /* the zero-based index of the procedure */ + unsigned short proc_num; + + /* total size of all parameters on the stack, including any "this" + * pointer and/or return value */ + unsigned short stack_size; +} NDR_PROC_HEADER; + +/* same as above struct except additional element rpc_flags */ +typedef struct _NDR_PROC_HEADER_RPC +{ + unsigned char handle_type; + unsigned char Oi_flags; + + /* + * RPCF_Idempotent = 0x0001 - [idempotent] MIDL attribute + * RPCF_Broadcast = 0x0002 - [broadcast] MIDL attribute + * RPCF_Maybe = 0x0004 - [maybe] MIDL attribute + * Reserved = 0x0008 - 0x0080 + * RPCF_Message = 0x0100 - [message] MIDL attribute + * Reserved = 0x0200 - 0x1000 + * RPCF_InputSynchronous = 0x2000 - unknown + * RPCF_Asynchronous = 0x4000 - [async] MIDL attribute + * Reserved = 0x8000 + */ + unsigned long rpc_flags; + unsigned short proc_num; + unsigned short stack_size; + +} NDR_PROC_HEADER_RPC; + +typedef struct _NDR_PROC_PARTIAL_OIF_HEADER +{ + /* the pre-computed client buffer size so that interpreter can skip all + * or some (if the flag RPC_FC_PROC_OI2F_CLTMUSTSIZE is specified) of the + * sizing pass */ + unsigned short constant_client_buffer_size; + + /* the pre-computed server buffer size so that interpreter can skip all + * or some (if the flag RPC_FC_PROC_OI2F_SRVMUSTSIZE is specified) of the + * sizing pass */ + unsigned short constant_server_buffer_size; + + INTERPRETER_OPT_FLAGS Oi2Flags; + + /* number of params */ + unsigned char number_of_params; +} NDR_PROC_PARTIAL_OIF_HEADER; + +typedef struct _NDR_PARAM_OI_BASETYPE +{ + /* parameter direction. One of: + * FC_IN_PARAM_BASETYPE = 0x4e - an in param + * FC_RETURN_PARAM_BASETYPE = 0x53 - a return param + */ + unsigned char param_direction; + + /* One of: FC_BYTE,FC_CHAR,FC_SMALL,FC_USMALL,FC_WCHAR,FC_SHORT,FC_USHORT, + * FC_LONG,FC_ULONG,FC_FLOAT,FC_HYPER,FC_DOUBLE,FC_ENUM16,FC_ENUM32, + * FC_ERROR_STATUS_T,FC_INT3264,FC_UINT3264 */ + unsigned char type_format_char; +} NDR_PARAM_OI_BASETYPE; + +typedef struct _NDR_PARAM_OI_OTHER +{ + /* One of: + * FC_IN_PARAM = 0x4d - An in param + * FC_IN_OUT_PARAM = 0x50 - An in/out param + * FC_OUT_PARAM = 0x51 - An out param + * FC_RETURN_PARAM = 0x52 - A return value + * FC_IN_PARAM_NO_FREE_INST = 0x4f - A param for which no freeing is done + */ + unsigned char param_direction; + + /* Size of param on stack in NUMBERS OF INTS */ + unsigned char stack_size; + + /* offset in the type format string table */ + unsigned short type_offset; +} NDR_PARAM_OI_OTHER; + +typedef struct _NDR_PARAM_OIF_BASETYPE +{ + PARAM_ATTRIBUTES param_attributes; + + /* the offset on the calling stack where the parameter is located */ + unsigned short stack_offset; + + /* see NDR_PARAM_OI_BASETYPE::type_format_char */ + unsigned char type_format_char; + + /* always FC_PAD */ + unsigned char unused; +} NDR_PARAM_OIF_BASETYPE; + +typedef struct _NDR_PARAM_OIF_OTHER +{ + PARAM_ATTRIBUTES param_attributes; + + /* see NDR_PARAM_OIF_BASETYPE::stack_offset */ + unsigned short stack_offset; + + /* offset into the provided type format string where the type for this + * parameter starts */ + unsigned short type_offset; +} NDR_PARAM_OIF_OTHER; + +/* explicit handle description for FC_BIND_PRIMITIVE type */ +typedef struct _NDR_EHD_PRIMITIVE +{ + /* FC_BIND_PRIMITIVE */ + unsigned char handle_type; + + /* is the handle passed in via a pointer? */ + unsigned char flag; + + /* offset from the beginning of the stack to the handle in bytes */ + unsigned short offset; +} NDR_EHD_PRIMITIVE; + +/* explicit handle description for FC_BIND_GENERIC type */ +typedef struct _NDR_EHD_GENERIC +{ + /* FC_BIND_GENERIC */ + unsigned char handle_type; + + /* upper 4bits is a flag indicating whether the handle is passed in + * via a pointer. lower 4bits is the size of the user defined generic + * handle type. the size must be less than or equal to the machine + * register size */ + unsigned char flag_and_size; + + /* offset from the beginning of the stack to the handle in bytes */ + unsigned short offset; + + /* the index into the aGenericBindingRoutinesPairs field of MIDL_STUB_DESC + * giving the bind and unbind routines for the handle */ + unsigned char binding_routine_pair_index; + + /* FC_PAD */ + unsigned char unused; +} NDR_EHD_GENERIC; + +/* explicit handle description for FC_BIND_CONTEXT type */ +typedef struct _NDR_EHD_CONTEXT +{ + /* FC_BIND_CONTEXT */ + unsigned char handle_type; + + /* Any of the following flags: + * NDR_CONTEXT_HANDLE_CANNOT_BE_NULL = 0x01 + * NDR_CONTEXT_HANDLE_SERIALIZE = 0x02 + * NDR_CONTEXT_HANDLE_NO_SERIALIZE = 0x04 + * NDR_STRICT_CONTEXT_HANDLE = 0x08 + * HANDLE_PARAM_IS_OUT = 0x20 + * HANDLE_PARAM_IS_RETURN = 0x21 + * HANDLE_PARAM_IS_IN = 0x40 + * HANDLE_PARAM_IS_VIA_PTR = 0x80 + */ + unsigned char flags; + + /* offset from the beginning of the stack to the handle in bytes */ + unsigned short offset; + + /* zero-based index on rundown routine in apfnNdrRundownRoutines field + * of MIDL_STUB_DESC */ + unsigned char context_rundown_routine_index; + + /* varies depending on NDR version used. + * V1: zero-based index into parameters + * V2: zero-based index into handles that are parameters */ + unsigned char param_num; +} NDR_EHD_CONTEXT; + +#include "poppack.h" diff --git a/reactos/dll/win32/rpcrt4_new/rpc_assoc.c b/reactos/dll/win32/rpcrt4_new/rpc_assoc.c new file mode 100644 index 00000000000..1bffb8564ed --- /dev/null +++ b/reactos/dll/win32/rpcrt4_new/rpc_assoc.c @@ -0,0 +1,539 @@ +/* + * Associations + * + * Copyright 2007 Robert Shearman (for CodeWeavers) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + * + */ + +#include +#include + +#include "rpc.h" +#include "rpcndr.h" +#include "winternl.h" + +#include "wine/unicode.h" +#include "wine/debug.h" + +#include "rpc_binding.h" +#include "rpc_assoc.h" +#include "rpc_message.h" + +WINE_DEFAULT_DEBUG_CHANNEL(rpc); + +static CRITICAL_SECTION assoc_list_cs; +static CRITICAL_SECTION_DEBUG assoc_list_cs_debug = +{ + 0, 0, &assoc_list_cs, + { &assoc_list_cs_debug.ProcessLocksList, &assoc_list_cs_debug.ProcessLocksList }, + 0, 0, { (DWORD_PTR)(__FILE__ ": assoc_list_cs") } +}; +static CRITICAL_SECTION assoc_list_cs = { &assoc_list_cs_debug, -1, 0, 0, 0, 0 }; + +static struct list client_assoc_list = LIST_INIT(client_assoc_list); +static struct list server_assoc_list = LIST_INIT(server_assoc_list); + +static LONG last_assoc_group_id; + +typedef struct _RpcContextHandle +{ + struct list entry; + void *user_context; + NDR_RUNDOWN rundown_routine; + void *ctx_guard; + UUID uuid; + RTL_RWLOCK rw_lock; + unsigned int refs; +} RpcContextHandle; + +static void RpcContextHandle_Destroy(RpcContextHandle *context_handle); + +static RPC_STATUS RpcAssoc_Alloc(LPCSTR Protseq, LPCSTR NetworkAddr, + LPCSTR Endpoint, LPCWSTR NetworkOptions, + RpcAssoc **assoc_out) +{ + RpcAssoc *assoc; + assoc = HeapAlloc(GetProcessHeap(), 0, sizeof(*assoc)); + if (!assoc) + return RPC_S_OUT_OF_RESOURCES; + assoc->refs = 1; + list_init(&assoc->free_connection_pool); + list_init(&assoc->context_handle_list); + InitializeCriticalSection(&assoc->cs); + assoc->Protseq = RPCRT4_strdupA(Protseq); + assoc->NetworkAddr = RPCRT4_strdupA(NetworkAddr); + assoc->Endpoint = RPCRT4_strdupA(Endpoint); + assoc->NetworkOptions = NetworkOptions ? RPCRT4_strdupW(NetworkOptions) : NULL; + assoc->assoc_group_id = 0; + list_init(&assoc->entry); + *assoc_out = assoc; + return RPC_S_OK; +} + +RPC_STATUS RPCRT4_GetAssociation(LPCSTR Protseq, LPCSTR NetworkAddr, + LPCSTR Endpoint, LPCWSTR NetworkOptions, + RpcAssoc **assoc_out) +{ + RpcAssoc *assoc; + RPC_STATUS status; + + EnterCriticalSection(&assoc_list_cs); + LIST_FOR_EACH_ENTRY(assoc, &client_assoc_list, RpcAssoc, entry) + { + if (!strcmp(Protseq, assoc->Protseq) && + !strcmp(NetworkAddr, assoc->NetworkAddr) && + !strcmp(Endpoint, assoc->Endpoint) && + ((!assoc->NetworkOptions && !NetworkOptions) || !strcmpW(NetworkOptions, assoc->NetworkOptions))) + { + assoc->refs++; + *assoc_out = assoc; + LeaveCriticalSection(&assoc_list_cs); + TRACE("using existing assoc %p\n", assoc); + return RPC_S_OK; + } + } + + status = RpcAssoc_Alloc(Protseq, NetworkAddr, Endpoint, NetworkOptions, &assoc); + if (status != RPC_S_OK) + { + LeaveCriticalSection(&assoc_list_cs); + return status; + } + list_add_head(&client_assoc_list, &assoc->entry); + *assoc_out = assoc; + + LeaveCriticalSection(&assoc_list_cs); + + TRACE("new assoc %p\n", assoc); + + return RPC_S_OK; +} + +RPC_STATUS RpcServerAssoc_GetAssociation(LPCSTR Protseq, LPCSTR NetworkAddr, + LPCSTR Endpoint, LPCWSTR NetworkOptions, + unsigned long assoc_gid, + RpcAssoc **assoc_out) +{ + RpcAssoc *assoc; + RPC_STATUS status; + + EnterCriticalSection(&assoc_list_cs); + if (assoc_gid) + { + LIST_FOR_EACH_ENTRY(assoc, &server_assoc_list, RpcAssoc, entry) + { + /* FIXME: NetworkAddr shouldn't be NULL */ + if (assoc->assoc_group_id == assoc_gid && + !strcmp(Protseq, assoc->Protseq) && + (!NetworkAddr || !assoc->NetworkAddr || !strcmp(NetworkAddr, assoc->NetworkAddr)) && + !strcmp(Endpoint, assoc->Endpoint) && + ((!assoc->NetworkOptions == !NetworkOptions) && + (!NetworkOptions || !strcmpW(NetworkOptions, assoc->NetworkOptions)))) + { + assoc->refs++; + *assoc_out = assoc; + LeaveCriticalSection(&assoc_list_cs); + TRACE("using existing assoc %p\n", assoc); + return RPC_S_OK; + } + } + *assoc_out = NULL; + LeaveCriticalSection(&assoc_list_cs); + return RPC_S_NO_CONTEXT_AVAILABLE; + } + + status = RpcAssoc_Alloc(Protseq, NetworkAddr, Endpoint, NetworkOptions, &assoc); + if (status != RPC_S_OK) + { + LeaveCriticalSection(&assoc_list_cs); + return status; + } + assoc->assoc_group_id = InterlockedIncrement(&last_assoc_group_id); + list_add_head(&server_assoc_list, &assoc->entry); + *assoc_out = assoc; + + LeaveCriticalSection(&assoc_list_cs); + + TRACE("new assoc %p\n", assoc); + + return RPC_S_OK; +} + +ULONG RpcAssoc_Release(RpcAssoc *assoc) +{ + ULONG refs; + + EnterCriticalSection(&assoc_list_cs); + refs = --assoc->refs; + if (!refs) + list_remove(&assoc->entry); + LeaveCriticalSection(&assoc_list_cs); + + if (!refs) + { + RpcConnection *Connection, *cursor2; + RpcContextHandle *context_handle, *context_handle_cursor; + + TRACE("destroying assoc %p\n", assoc); + + LIST_FOR_EACH_ENTRY_SAFE(Connection, cursor2, &assoc->free_connection_pool, RpcConnection, conn_pool_entry) + { + list_remove(&Connection->conn_pool_entry); + RPCRT4_DestroyConnection(Connection); + } + + LIST_FOR_EACH_ENTRY_SAFE(context_handle, context_handle_cursor, &assoc->context_handle_list, RpcContextHandle, entry) + RpcContextHandle_Destroy(context_handle); + + HeapFree(GetProcessHeap(), 0, assoc->NetworkOptions); + HeapFree(GetProcessHeap(), 0, assoc->Endpoint); + HeapFree(GetProcessHeap(), 0, assoc->NetworkAddr); + HeapFree(GetProcessHeap(), 0, assoc->Protseq); + + DeleteCriticalSection(&assoc->cs); + + HeapFree(GetProcessHeap(), 0, assoc); + } + + return refs; +} + +#define ROUND_UP(value, alignment) (((value) + ((alignment) - 1)) & ~((alignment)-1)) + +static RPC_STATUS RpcAssoc_BindConnection(const RpcAssoc *assoc, RpcConnection *conn, + const RPC_SYNTAX_IDENTIFIER *InterfaceId, + const RPC_SYNTAX_IDENTIFIER *TransferSyntax) +{ + RpcPktHdr *hdr; + RpcPktHdr *response_hdr; + RPC_MESSAGE msg; + RPC_STATUS status; + + TRACE("sending bind request to server\n"); + + hdr = RPCRT4_BuildBindHeader(NDR_LOCAL_DATA_REPRESENTATION, + RPC_MAX_PACKET_SIZE, RPC_MAX_PACKET_SIZE, + assoc->assoc_group_id, + InterfaceId, TransferSyntax); + + status = RPCRT4_Send(conn, hdr, NULL, 0); + RPCRT4_FreeHeader(hdr); + if (status != RPC_S_OK) + return status; + + status = RPCRT4_Receive(conn, &response_hdr, &msg); + if (status != RPC_S_OK) + { + ERR("receive failed\n"); + return status; + } + + switch (response_hdr->common.ptype) + { + case PKT_BIND_ACK: + { + RpcAddressString *server_address = msg.Buffer; + if ((msg.BufferLength >= FIELD_OFFSET(RpcAddressString, string[0])) || + (msg.BufferLength >= ROUND_UP(FIELD_OFFSET(RpcAddressString, string[server_address->length]), 4))) + { + unsigned short remaining = msg.BufferLength - + ROUND_UP(FIELD_OFFSET(RpcAddressString, string[server_address->length]), 4); + RpcResults *results = (RpcResults*)((ULONG_PTR)server_address + + ROUND_UP(FIELD_OFFSET(RpcAddressString, string[server_address->length]), 4)); + if ((results->num_results == 1) && (remaining >= sizeof(*results))) + { + switch (results->results[0].result) + { + case RESULT_ACCEPT: + conn->assoc_group_id = response_hdr->bind_ack.assoc_gid; + conn->MaxTransmissionSize = response_hdr->bind_ack.max_tsize; + conn->ActiveInterface = *InterfaceId; + break; + case RESULT_PROVIDER_REJECTION: + switch (results->results[0].reason) + { + case REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED: + ERR("syntax %s, %d.%d not supported\n", + debugstr_guid(&InterfaceId->SyntaxGUID), + InterfaceId->SyntaxVersion.MajorVersion, + InterfaceId->SyntaxVersion.MinorVersion); + status = RPC_S_UNKNOWN_IF; + break; + case REASON_TRANSFER_SYNTAXES_NOT_SUPPORTED: + ERR("transfer syntax not supported\n"); + status = RPC_S_SERVER_UNAVAILABLE; + break; + case REASON_NONE: + default: + status = RPC_S_CALL_FAILED_DNE; + } + break; + case RESULT_USER_REJECTION: + default: + ERR("rejection result %d\n", results->results[0].result); + status = RPC_S_CALL_FAILED_DNE; + } + } + else + { + ERR("incorrect results size\n"); + status = RPC_S_CALL_FAILED_DNE; + } + } + else + { + ERR("bind ack packet too small (%d)\n", msg.BufferLength); + status = RPC_S_PROTOCOL_ERROR; + } + break; + } + case PKT_BIND_NACK: + switch (response_hdr->bind_nack.reject_reason) + { + case REJECT_LOCAL_LIMIT_EXCEEDED: + case REJECT_TEMPORARY_CONGESTION: + ERR("server too busy\n"); + status = RPC_S_SERVER_TOO_BUSY; + break; + case REJECT_PROTOCOL_VERSION_NOT_SUPPORTED: + ERR("protocol version not supported\n"); + status = RPC_S_PROTOCOL_ERROR; + break; + case REJECT_UNKNOWN_AUTHN_SERVICE: + ERR("unknown authentication service\n"); + status = RPC_S_UNKNOWN_AUTHN_SERVICE; + break; + case REJECT_INVALID_CHECKSUM: + ERR("invalid checksum\n"); + status = ERROR_ACCESS_DENIED; + break; + default: + ERR("rejected bind for reason %d\n", response_hdr->bind_nack.reject_reason); + status = RPC_S_CALL_FAILED_DNE; + } + break; + default: + ERR("wrong packet type received %d\n", response_hdr->common.ptype); + status = RPC_S_PROTOCOL_ERROR; + break; + } + + I_RpcFreeBuffer(&msg); + RPCRT4_FreeHeader(response_hdr); + return status; +} + +static RpcConnection *RpcAssoc_GetIdleConnection(RpcAssoc *assoc, + const RPC_SYNTAX_IDENTIFIER *InterfaceId, + const RPC_SYNTAX_IDENTIFIER *TransferSyntax, const RpcAuthInfo *AuthInfo, + const RpcQualityOfService *QOS) +{ + RpcConnection *Connection; + EnterCriticalSection(&assoc->cs); + /* try to find a compatible connection from the connection pool */ + LIST_FOR_EACH_ENTRY(Connection, &assoc->free_connection_pool, RpcConnection, conn_pool_entry) + { + if (!memcmp(&Connection->ActiveInterface, InterfaceId, + sizeof(RPC_SYNTAX_IDENTIFIER)) && + RpcAuthInfo_IsEqual(Connection->AuthInfo, AuthInfo) && + RpcQualityOfService_IsEqual(Connection->QOS, QOS)) + { + list_remove(&Connection->conn_pool_entry); + LeaveCriticalSection(&assoc->cs); + TRACE("got connection from pool %p\n", Connection); + return Connection; + } + } + + LeaveCriticalSection(&assoc->cs); + return NULL; +} + +RPC_STATUS RpcAssoc_GetClientConnection(RpcAssoc *assoc, + const RPC_SYNTAX_IDENTIFIER *InterfaceId, + const RPC_SYNTAX_IDENTIFIER *TransferSyntax, RpcAuthInfo *AuthInfo, + RpcQualityOfService *QOS, RpcConnection **Connection) +{ + RpcConnection *NewConnection; + RPC_STATUS status; + + *Connection = RpcAssoc_GetIdleConnection(assoc, InterfaceId, TransferSyntax, AuthInfo, QOS); + if (*Connection) + return RPC_S_OK; + + /* create a new connection */ + status = RPCRT4_CreateConnection(&NewConnection, FALSE /* is this a server connection? */, + assoc->Protseq, assoc->NetworkAddr, + assoc->Endpoint, assoc->NetworkOptions, + AuthInfo, QOS); + if (status != RPC_S_OK) + return status; + + status = RPCRT4_OpenClientConnection(NewConnection); + if (status != RPC_S_OK) + { + RPCRT4_DestroyConnection(NewConnection); + return status; + } + + status = RpcAssoc_BindConnection(assoc, NewConnection, InterfaceId, TransferSyntax); + if (status != RPC_S_OK) + { + RPCRT4_DestroyConnection(NewConnection); + return status; + } + + *Connection = NewConnection; + + return RPC_S_OK; +} + +void RpcAssoc_ReleaseIdleConnection(RpcAssoc *assoc, RpcConnection *Connection) +{ + assert(!Connection->server); + EnterCriticalSection(&assoc->cs); + if (!assoc->assoc_group_id) assoc->assoc_group_id = Connection->assoc_group_id; + list_add_head(&assoc->free_connection_pool, &Connection->conn_pool_entry); + LeaveCriticalSection(&assoc->cs); +} + +RPC_STATUS RpcServerAssoc_AllocateContextHandle(RpcAssoc *assoc, void *CtxGuard, + NDR_SCONTEXT *SContext) +{ + RpcContextHandle *context_handle; + + context_handle = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*context_handle)); + if (!context_handle) + return ERROR_OUTOFMEMORY; + + context_handle->ctx_guard = CtxGuard; + RtlInitializeResource(&context_handle->rw_lock); + context_handle->refs = 1; + + /* lock here to mirror unmarshall, so we don't need to special-case the + * freeing of a non-marshalled context handle */ + RtlAcquireResourceExclusive(&context_handle->rw_lock, TRUE); + + EnterCriticalSection(&assoc->cs); + list_add_tail(&assoc->context_handle_list, &context_handle->entry); + LeaveCriticalSection(&assoc->cs); + + *SContext = (NDR_SCONTEXT)context_handle; + return RPC_S_OK; +} + +BOOL RpcContextHandle_IsGuardCorrect(NDR_SCONTEXT SContext, void *CtxGuard) +{ + RpcContextHandle *context_handle = (RpcContextHandle *)SContext; + return context_handle->ctx_guard == CtxGuard; +} + +RPC_STATUS RpcServerAssoc_FindContextHandle(RpcAssoc *assoc, const UUID *uuid, + void *CtxGuard, ULONG Flags, NDR_SCONTEXT *SContext) +{ + RpcContextHandle *context_handle; + + EnterCriticalSection(&assoc->cs); + LIST_FOR_EACH_ENTRY(context_handle, &assoc->context_handle_list, RpcContextHandle, entry) + { + if (RpcContextHandle_IsGuardCorrect((NDR_SCONTEXT)context_handle, CtxGuard) && + !memcmp(&context_handle->uuid, uuid, sizeof(*uuid))) + { + *SContext = (NDR_SCONTEXT)context_handle; + if (context_handle->refs++) + { + LeaveCriticalSection(&assoc->cs); + TRACE("found %p\n", context_handle); + RtlAcquireResourceExclusive(&context_handle->rw_lock, TRUE); + return RPC_S_OK; + } + } + } + LeaveCriticalSection(&assoc->cs); + + ERR("no context handle found for uuid %s, guard %p\n", + debugstr_guid(uuid), CtxGuard); + return ERROR_INVALID_HANDLE; +} + +RPC_STATUS RpcServerAssoc_UpdateContextHandle(RpcAssoc *assoc, + NDR_SCONTEXT SContext, + void *CtxGuard, + NDR_RUNDOWN rundown_routine) +{ + RpcContextHandle *context_handle = (RpcContextHandle *)SContext; + RPC_STATUS status; + + if (!RpcContextHandle_IsGuardCorrect((NDR_SCONTEXT)context_handle, CtxGuard)) + return ERROR_INVALID_HANDLE; + + EnterCriticalSection(&assoc->cs); + if (UuidIsNil(&context_handle->uuid, &status)) + { + /* add a ref for the data being valid */ + context_handle->refs++; + UuidCreate(&context_handle->uuid); + context_handle->rundown_routine = rundown_routine; + TRACE("allocated uuid %s for context handle %p\n", + debugstr_guid(&context_handle->uuid), context_handle); + } + LeaveCriticalSection(&assoc->cs); + + return RPC_S_OK; +} + +void RpcContextHandle_GetUuid(NDR_SCONTEXT SContext, UUID *uuid) +{ + RpcContextHandle *context_handle = (RpcContextHandle *)SContext; + *uuid = context_handle->uuid; +} + +static void RpcContextHandle_Destroy(RpcContextHandle *context_handle) +{ + TRACE("freeing %p\n", context_handle); + + if (context_handle->user_context && context_handle->rundown_routine) + { + TRACE("calling rundown routine %p with user context %p\n", + context_handle->rundown_routine, context_handle->user_context); + context_handle->rundown_routine(context_handle->user_context); + } + + RtlDeleteResource(&context_handle->rw_lock); + + HeapFree(GetProcessHeap(), 0, context_handle); +} + +unsigned int RpcServerAssoc_ReleaseContextHandle(RpcAssoc *assoc, NDR_SCONTEXT SContext, BOOL release_lock) +{ + RpcContextHandle *context_handle = (RpcContextHandle *)SContext; + unsigned int refs; + + if (release_lock) + RtlReleaseResource(&context_handle->rw_lock); + + EnterCriticalSection(&assoc->cs); + refs = --context_handle->refs; + if (!refs) + list_remove(&context_handle->entry); + LeaveCriticalSection(&assoc->cs); + + if (!refs) + RpcContextHandle_Destroy(context_handle); + + return refs; +} diff --git a/reactos/dll/win32/rpcrt4_new/rpc_assoc.h b/reactos/dll/win32/rpcrt4_new/rpc_assoc.h new file mode 100644 index 00000000000..1ce1f135638 --- /dev/null +++ b/reactos/dll/win32/rpcrt4_new/rpc_assoc.h @@ -0,0 +1,58 @@ +/* + * Associations + * + * Copyright 2007 Robert Shearman (for CodeWeavers) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + * + */ + +#include "rpc_binding.h" +#include "wine/list.h" + +typedef struct _RpcAssoc +{ + struct list entry; /* entry in the global list of associations */ + LONG refs; + + LPSTR Protseq; + LPSTR NetworkAddr; + LPSTR Endpoint; + LPWSTR NetworkOptions; + + /* id of this association group */ + ULONG assoc_group_id; + + CRITICAL_SECTION cs; + + /* client-only */ + /* connections available to be used (protected by cs) */ + struct list free_connection_pool; + + /* server-only */ + struct list context_handle_list; /* protected by cs */ +} RpcAssoc; + +RPC_STATUS RPCRT4_GetAssociation(LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint, LPCWSTR NetworkOptions, RpcAssoc **assoc); +RPC_STATUS RpcAssoc_GetClientConnection(RpcAssoc *assoc, const RPC_SYNTAX_IDENTIFIER *InterfaceId, const RPC_SYNTAX_IDENTIFIER *TransferSyntax, RpcAuthInfo *AuthInfo, RpcQualityOfService *QOS, RpcConnection **Connection); +void RpcAssoc_ReleaseIdleConnection(RpcAssoc *assoc, RpcConnection *Connection); +ULONG RpcAssoc_Release(RpcAssoc *assoc); +RPC_STATUS RpcServerAssoc_GetAssociation(LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint, LPCWSTR NetworkOptions, unsigned long assoc_gid, RpcAssoc **assoc_out); +RPC_STATUS RpcServerAssoc_AllocateContextHandle(RpcAssoc *assoc, void *CtxGuard, NDR_SCONTEXT *SContext); +RPC_STATUS RpcServerAssoc_FindContextHandle(RpcAssoc *assoc, const UUID *uuid, void *CtxGuard, ULONG Flags, NDR_SCONTEXT *SContext); +RPC_STATUS RpcServerAssoc_UpdateContextHandle(RpcAssoc *assoc, NDR_SCONTEXT SContext, void *CtxGuard, NDR_RUNDOWN rundown_routine); +unsigned int RpcServerAssoc_ReleaseContextHandle(RpcAssoc *assoc, NDR_SCONTEXT SContext, BOOL release_lock); +void RpcContextHandle_GetUuid(NDR_SCONTEXT SContext, UUID *uuid); +BOOL RpcContextHandle_IsGuardCorrect(NDR_SCONTEXT SContext, void *CtxGuard); diff --git a/reactos/dll/win32/rpcrt4_new/rpc_binding.c b/reactos/dll/win32/rpcrt4_new/rpc_binding.c index 063be45b252..e1d06f95736 100644 --- a/reactos/dll/win32/rpcrt4_new/rpc_binding.c +++ b/reactos/dll/win32/rpcrt4_new/rpc_binding.c @@ -39,7 +39,7 @@ #include "wine/debug.h" #include "rpc_binding.h" -#include "rpc_message.h" +#include "rpc_assoc.h" WINE_DEFAULT_DEBUG_CHANNEL(rpc); @@ -180,7 +180,7 @@ static RPC_STATUS RPCRT4_CompleteBindingW(RpcBinding* Binding, LPCWSTR NetworkAd { RPC_STATUS status; - TRACE("(RpcBinding == ^%p, NetworkAddr == %s, EndPoint == %s, NetworkOptions == %s)\n", Binding, + TRACE("(RpcBinding == ^%p, NetworkAddr == %s, EndPoint == %s, NetworkOptions == %s)\n", Binding, debugstr_w(NetworkAddr), debugstr_w(Endpoint), debugstr_w(NetworkOptions)); RPCRT4_strfree(Binding->NetworkAddr); @@ -226,7 +226,7 @@ RPC_STATUS RPCRT4_ResolveBinding(RpcBinding* Binding, LPCSTR Endpoint) RPC_STATUS RPCRT4_SetBindingObject(RpcBinding* Binding, const UUID* ObjectUuid) { - TRACE("(*RpcBinding == ^%p, UUID == %s)\n", Binding, debugstr_guid(ObjectUuid)); + TRACE("(*RpcBinding == ^%p, UUID == %s)\n", Binding, debugstr_guid(ObjectUuid)); if (ObjectUuid) memcpy(&Binding->ObjectUuid, ObjectUuid, sizeof(UUID)); else UuidCreateNil(&Binding->ObjectUuid); return RPC_S_OK; @@ -343,7 +343,7 @@ static LPWSTR RPCRT4_strconcatW(LPWSTR dst, LPCWSTR src) { DWORD len = strlenW(dst), slen = strlenW(src); LPWSTR ndst = HeapReAlloc(GetProcessHeap(), 0, dst, (len+slen+2)*sizeof(WCHAR)); - if (!ndst) + if (!ndst) { HeapFree(GetProcessHeap(), 0, dst); return NULL; @@ -527,7 +527,7 @@ RPC_STATUS WINAPI RpcStringBindingParseA( RPC_CSTR StringBinding, RPC_CSTR *ObjU /* FIXME: this is kind of inefficient */ *Options = (unsigned char*) RPCRT4_strconcatA( (char*)*Options, opt); HeapFree(GetProcessHeap(), 0, opt); - } else + } else *Options = (unsigned char*) opt; } } @@ -536,7 +536,7 @@ RPC_STATUS WINAPI RpcStringBindingParseA( RPC_CSTR StringBinding, RPC_CSTR *ObjU data = close+1; if (*data) goto fail; } - else if (NetworkAddr) + else if (NetworkAddr) *NetworkAddr = (unsigned char*)RPCRT4_strdupA(data); return RPC_S_OK; @@ -618,7 +618,7 @@ RPC_STATUS WINAPI RpcStringBindingParseW( RPC_WSTR StringBinding, RPC_WSTR *ObjU /* FIXME: this is kind of inefficient */ *Options = RPCRT4_strconcatW(*Options, opt); HeapFree(GetProcessHeap(), 0, opt); - } else + } else *Options = opt; } } @@ -626,7 +626,7 @@ RPC_STATUS WINAPI RpcStringBindingParseW( RPC_WSTR StringBinding, RPC_WSTR *ObjU data = close+1; if (*data) goto fail; - } else if (NetworkAddr) + } else if (NetworkAddr) *NetworkAddr = RPCRT4_strdupW(data); return RPC_S_OK; @@ -651,7 +651,7 @@ RPC_STATUS WINAPI RpcBindingFree( RPC_BINDING_HANDLE* Binding ) if (status == RPC_S_OK) *Binding = 0; return status; } - + /*********************************************************************** * RpcBindingVectorFree (RPCRT4.@) */ @@ -668,7 +668,7 @@ RPC_STATUS WINAPI RpcBindingVectorFree( RPC_BINDING_VECTOR** BindingVector ) *BindingVector = NULL; return RPC_S_OK; } - + /*********************************************************************** * RpcBindingInqObject (RPCRT4.@) */ @@ -680,7 +680,7 @@ RPC_STATUS WINAPI RpcBindingInqObject( RPC_BINDING_HANDLE Binding, UUID* ObjectU memcpy(ObjectUuid, &bind->ObjectUuid, sizeof(UUID)); return RPC_S_OK; } - + /*********************************************************************** * RpcBindingSetObject (RPCRT4.@) */ @@ -724,9 +724,9 @@ RPC_STATUS WINAPI RpcBindingFromStringBindingA( RPC_CSTR StringBinding, RPC_BIND RpcStringFreeA((unsigned char**)&Protseq); RpcStringFreeA((unsigned char**)&ObjectUuid); - if (ret == RPC_S_OK) + if (ret == RPC_S_OK) *Binding = (RPC_BINDING_HANDLE)bind; - else + else RPCRT4_DestroyBinding(bind); return ret; @@ -770,7 +770,7 @@ RPC_STATUS WINAPI RpcBindingFromStringBindingW( RPC_WSTR StringBinding, RPC_BIND return ret; } - + /*********************************************************************** * RpcBindingToStringBindingA (RPCRT4.@) */ @@ -792,7 +792,7 @@ RPC_STATUS WINAPI RpcBindingToStringBindingA( RPC_BINDING_HANDLE Binding, RPC_CS return ret; } - + /*********************************************************************** * RpcBindingToStringBindingW (RPCRT4.@) */ @@ -1001,7 +1001,7 @@ ULONG RpcAuthInfo_Release(RpcAuthInfo *AuthInfo) { HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->User); HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->Domain); - HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->User); + HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->Password); HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity); } HeapFree(GetProcessHeap(), 0, AuthInfo); diff --git a/reactos/dll/win32/rpcrt4_new/rpc_binding.h b/reactos/dll/win32/rpcrt4_new/rpc_binding.h index a8721a72549..050c0e62925 100644 --- a/reactos/dll/win32/rpcrt4_new/rpc_binding.h +++ b/reactos/dll/win32/rpcrt4_new/rpc_binding.h @@ -22,6 +22,7 @@ #define __WINE_RPC_BINDING_H #include "wine/rpcss_shared.h" +#include "rpcndr.h" #include "security.h" #include "wine/list.h" @@ -49,37 +50,16 @@ typedef struct _RpcQualityOfService RPC_SECURITY_QOS_V2_W *qos; } RpcQualityOfService; -typedef struct _RpcAssoc -{ - struct list entry; /* entry in the global list of associations */ - LONG refs; - - LPSTR Protseq; - LPSTR NetworkAddr; - LPSTR Endpoint; - LPWSTR NetworkOptions; - - /* id of this association group */ - ULONG assoc_group_id; - - CRITICAL_SECTION cs; - struct list connection_pool; -} RpcAssoc; - struct connection_ops; typedef struct _RpcConnection { - struct _RpcConnection* Next; BOOL server; LPSTR NetworkAddr; LPSTR Endpoint; LPWSTR NetworkOptions; const struct connection_ops *ops; USHORT MaxTransmissionSize; - /* The active interface bound to server. */ - RPC_SYNTAX_IDENTIFIER ActiveInterface; - USHORT NextCallId; /* authentication */ CtxtHandle ctx; @@ -93,6 +73,13 @@ typedef struct _RpcConnection /* client-only */ struct list conn_pool_entry; ULONG assoc_group_id; /* association group returned during binding */ + + /* server-only */ + /* The active interface bound to server. */ + RPC_SYNTAX_IDENTIFIER ActiveInterface; + USHORT NextCallId; + struct _RpcConnection* Next; + struct _RpcBinding *server_binding; } RpcConnection; struct connection_ops { @@ -104,6 +91,7 @@ struct connection_ops { int (*read)(RpcConnection *conn, void *buffer, unsigned int len); int (*write)(RpcConnection *conn, const void *buffer, unsigned int len); int (*close)(RpcConnection *conn); + void (*cancel_call)(RpcConnection *conn); size_t (*get_top_of_tower)(unsigned char *tower_data, const char *networkaddr, const char *endpoint); RPC_STATUS (*parse_top_of_tower)(const unsigned char *tower_data, size_t tower_size, char **networkaddr, char **endpoint); }; @@ -122,7 +110,7 @@ typedef struct _RpcBinding RPC_BLOCKING_FN BlockingFn; ULONG ServerTid; RpcConnection* FromConn; - RpcAssoc *Assoc; + struct _RpcAssoc *Assoc; /* authentication */ RpcAuthInfo *AuthInfo; @@ -145,11 +133,6 @@ ULONG RpcQualityOfService_AddRef(RpcQualityOfService *qos); ULONG RpcQualityOfService_Release(RpcQualityOfService *qos); BOOL RpcQualityOfService_IsEqual(const RpcQualityOfService *qos1, const RpcQualityOfService *qos2); -RPC_STATUS RPCRT4_GetAssociation(LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint, LPCWSTR NetworkOptions, RpcAssoc **assoc); -RPC_STATUS RpcAssoc_GetClientConnection(RpcAssoc *assoc, const RPC_SYNTAX_IDENTIFIER *InterfaceId, const RPC_SYNTAX_IDENTIFIER *TransferSyntax, RpcAuthInfo *AuthInfo, RpcQualityOfService *QOS, RpcConnection **Connection); -void RpcAssoc_ReleaseIdleConnection(RpcAssoc *assoc, RpcConnection *Connection); -ULONG RpcAssoc_Release(RpcAssoc *assoc); - RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server, LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint, LPCWSTR NetworkOptions, RpcAuthInfo* AuthInfo, RpcQualityOfService *QOS); RPC_STATUS RPCRT4_DestroyConnection(RpcConnection* Connection); RPC_STATUS RPCRT4_OpenClientConnection(RpcConnection* Connection); @@ -190,6 +173,11 @@ static inline int rpcrt4_conn_close(RpcConnection *Connection) return Connection->ops->close(Connection); } +static inline void rpcrt4_conn_cancel_call(RpcConnection *Connection) +{ + Connection->ops->cancel_call(Connection); +} + static inline RPC_STATUS rpcrt4_conn_handoff(RpcConnection *old_conn, RpcConnection *new_conn) { return old_conn->ops->handoff(old_conn, new_conn); @@ -199,4 +187,11 @@ static inline RPC_STATUS rpcrt4_conn_handoff(RpcConnection *old_conn, RpcConnect RPC_STATUS RpcTransport_GetTopOfTower(unsigned char *tower_data, size_t *tower_size, const char *protseq, const char *networkaddr, const char *endpoint); RPC_STATUS RpcTransport_ParseTopOfTower(const unsigned char *tower_data, size_t tower_size, char **protseq, char **networkaddr, char **endpoint); +void RPCRT4_SetThreadCurrentConnection(RpcConnection *Connection); +void RPCRT4_SetThreadCurrentCallHandle(RpcBinding *Binding); +RpcBinding *RPCRT4_GetThreadCurrentCallHandle(void); +void RPCRT4_PushThreadContextHandle(NDR_SCONTEXT SContext); +void RPCRT4_RemoveThreadContextHandle(NDR_SCONTEXT SContext); +NDR_SCONTEXT RPCRT4_PopThreadContextHandle(void); + #endif diff --git a/reactos/dll/win32/rpcrt4_new/rpc_defs.h b/reactos/dll/win32/rpcrt4_new/rpc_defs.h index dd702b06e1d..12b63eeb1ad 100644 --- a/reactos/dll/win32/rpcrt4_new/rpc_defs.h +++ b/reactos/dll/win32/rpcrt4_new/rpc_defs.h @@ -102,7 +102,7 @@ typedef struct unsigned short max_tsize; /* Maximum transmission fragment size */ unsigned short max_rsize; /* Maximum receive fragment size */ unsigned long assoc_gid; /* Associated group id */ - /* + /* * Following this header are these fields: * RpcAddressString server_address; * [0 - 3 bytes of padding so that results is 4-byte aligned] diff --git a/reactos/dll/win32/rpcrt4_new/rpc_epmap.c b/reactos/dll/win32/rpcrt4_new/rpc_epmap.c index 7da16753c82..19dda66c18c 100644 --- a/reactos/dll/win32/rpcrt4_new/rpc_epmap.c +++ b/reactos/dll/win32/rpcrt4_new/rpc_epmap.c @@ -231,7 +231,7 @@ RPC_STATUS WINAPI RpcEpResolveBinding( RPC_BINDING_HANDLE Binding, RPC_IF_HANDLE msg.message_type = RPCSS_NP_MESSAGE_TYPEID_RESOLVEEPMSG; msg.message.resolveepmsg.iface = If->InterfaceId; msg.message.resolveepmsg.object = bind->ObjectUuid; - + msg.vardata_payload_size = strlen(bind->Protseq) + 1; /* send the message */ @@ -241,7 +241,7 @@ RPC_STATUS WINAPI RpcEpResolveBinding( RPC_BINDING_HANDLE Binding, RPC_IF_HANDLE /* empty-string result means not registered */ if (reply.as_string[0] == '\0') return EPT_S_NOT_REGISTERED; - + /* otherwise we fully bind the handle & return RPC_S_OK */ return RPCRT4_ResolveBinding(Binding, reply.as_string); } diff --git a/reactos/dll/win32/rpcrt4_new/rpc_message.c b/reactos/dll/win32/rpcrt4_new/rpc_message.c index 53bf65d8b25..8cb0d2c5813 100644 --- a/reactos/dll/win32/rpcrt4_new/rpc_message.c +++ b/reactos/dll/win32/rpcrt4_new/rpc_message.c @@ -67,7 +67,7 @@ static DWORD RPCRT4_GetHeaderSize(const RpcPktHdr *Header) 0, 0, 0, 0, 0 }; ULONG ret = 0; - + if (Header->common.ptype < sizeof(header_sizes) / sizeof(header_sizes[0])) { ret = header_sizes[Header->common.ptype]; if (ret == 0) @@ -108,7 +108,7 @@ static VOID RPCRT4_BuildCommonHeader(RpcPktHdr *Header, unsigned char PacketType Header->common.call_id = 1; Header->common.flags = 0; /* Flags and fragment length are computed in RPCRT4_Send. */ -} +} static RpcPktHdr *RPCRT4_BuildRequestHeader(unsigned long DataRepresentation, unsigned long BufferLength, @@ -241,6 +241,7 @@ RpcPktHdr *RPCRT4_BuildBindNackHeader(unsigned long DataRepresentation, RpcPktHdr *RPCRT4_BuildBindAckHeader(unsigned long DataRepresentation, unsigned short MaxTransmissionSize, unsigned short MaxReceiveSize, + unsigned long AssocGroupId, LPCSTR ServerAddress, unsigned long Result, unsigned long Reason, @@ -266,6 +267,7 @@ RpcPktHdr *RPCRT4_BuildBindAckHeader(unsigned long DataRepresentation, header->common.frag_len = header_size; header->bind_ack.max_tsize = MaxTransmissionSize; header->bind_ack.max_rsize = MaxReceiveSize; + header->bind_ack.assoc_gid = AssocGroupId; server_address = (RpcAddressString*)(&header->bind_ack + 1); server_address->length = strlen(ServerAddress) + 1; strcpy(server_address->string, ServerAddress); @@ -415,7 +417,7 @@ static RPC_STATUS RPCRT4_SecurePacket(RpcConnection *Connection, sec_status = DecryptMessage(&Connection->ctx, &message, 0 /* FIXME */, 0); if (sec_status != SEC_E_OK) { - ERR("EncryptMessage failed with 0x%08x\n", sec_status); + ERR("DecryptMessage failed with 0x%08x\n", sec_status); return RPC_S_SEC_PKG_ERROR; } } @@ -432,10 +434,10 @@ static RPC_STATUS RPCRT4_SecurePacket(RpcConnection *Connection, return RPC_S_OK; } - + /*********************************************************************** * RPCRT4_SendAuth (internal) - * + * * Transmit a packet with authorization data over connection in acceptable fragments. */ static RPC_STATUS RPCRT4_SendAuth(RpcConnection *Connection, RpcPktHdr *Header, @@ -449,6 +451,8 @@ static RPC_STATUS RPCRT4_SendAuth(RpcConnection *Connection, RpcPktHdr *Header, LONG alen; RPC_STATUS status; + RPCRT4_SetThreadCurrentConnection(Connection); + buffer_pos = Buffer; /* The packet building functions save the packet header size, so we can use it. */ hdr_size = Header->common.frag_len; @@ -518,6 +522,7 @@ static RPC_STATUS RPCRT4_SendAuth(RpcConnection *Connection, RpcPktHdr *Header, if (status != RPC_S_OK) { HeapFree(GetProcessHeap(), 0, pkt); + RPCRT4_SetThreadCurrentConnection(NULL); return status; } } @@ -528,7 +533,8 @@ write: HeapFree(GetProcessHeap(), 0, pkt); if (count<0) { WARN("rpcrt4_conn_write failed (auth)\n"); - return RPC_S_PROTOCOL_ERROR; + RPCRT4_SetThreadCurrentConnection(NULL); + return RPC_S_CALL_FAILED; } buffer_pos += Header->common.frag_len - hdr_size - alen - auth_pad_len; @@ -536,6 +542,7 @@ write: Header->common.flags &= ~RPC_FLG_FIRST; } + RPCRT4_SetThreadCurrentConnection(NULL); return RPC_S_OK; } @@ -653,7 +660,7 @@ static RPC_STATUS RPCRT_AuthorizeConnection(RpcConnection* conn, /*********************************************************************** * RPCRT4_Send (internal) - * + * * Transmit a packet over connection in acceptable fragments. */ RPC_STATUS RPCRT4_Send(RpcConnection *Connection, RpcPktHdr *Header, @@ -677,7 +684,7 @@ RPC_STATUS RPCRT4_Send(RpcConnection *Connection, RpcPktHdr *Header, /*********************************************************************** * RPCRT4_Receive (internal) - * + * * Receive a packet from connection and merge the fragments. */ RPC_STATUS RPCRT4_Receive(RpcConnection *Connection, RpcPktHdr **Header, @@ -697,11 +704,13 @@ RPC_STATUS RPCRT4_Receive(RpcConnection *Connection, RpcPktHdr **Header, TRACE("(%p, %p, %p)\n", Connection, Header, pMsg); + RPCRT4_SetThreadCurrentConnection(Connection); + /* read packet common header */ dwRead = rpcrt4_conn_read(Connection, &common_hdr, sizeof(common_hdr)); if (dwRead != sizeof(common_hdr)) { WARN("Short read of header, %d bytes\n", dwRead); - status = RPC_S_PROTOCOL_ERROR; + status = RPC_S_CALL_FAILED; goto fail; } @@ -727,7 +736,7 @@ RPC_STATUS RPCRT4_Receive(RpcConnection *Connection, RpcPktHdr **Header, dwRead = rpcrt4_conn_read(Connection, &(*Header)->common + 1, hdr_length - sizeof(common_hdr)); if (dwRead != hdr_length - sizeof(common_hdr)) { WARN("bad header length, %d bytes, hdr_length %d\n", dwRead, hdr_length); - status = RPC_S_PROTOCOL_ERROR; + status = RPC_S_CALL_FAILED; goto fail; } @@ -753,7 +762,7 @@ RPC_STATUS RPCRT4_Receive(RpcConnection *Connection, RpcPktHdr **Header, if (auth_length) { auth_data = HeapAlloc(GetProcessHeap(), 0, RPC_AUTH_VERIFIER_LEN(&common_hdr)); if (!auth_data) { - status = RPC_S_PROTOCOL_ERROR; + status = RPC_S_OUT_OF_RESOURCES; goto fail; } } @@ -799,7 +808,7 @@ RPC_STATUS RPCRT4_Receive(RpcConnection *Connection, RpcPktHdr **Header, (unsigned char *)pMsg->Buffer + buffer_length, data_length); if (dwRead != data_length) { WARN("bad data length, %d/%ld\n", dwRead, data_length); - status = RPC_S_PROTOCOL_ERROR; + status = RPC_S_CALL_FAILED; goto fail; } @@ -819,7 +828,7 @@ RPC_STATUS RPCRT4_Receive(RpcConnection *Connection, RpcPktHdr **Header, if (dwRead != header_auth_len) { WARN("bad authentication data length, %d/%d\n", dwRead, header_auth_len); - status = RPC_S_PROTOCOL_ERROR; + status = RPC_S_CALL_FAILED; goto fail; } @@ -828,12 +837,15 @@ RPC_STATUS RPCRT4_Receive(RpcConnection *Connection, RpcPktHdr **Header, if ((common_hdr.ptype != PKT_BIND) && (common_hdr.ptype != PKT_BIND_ACK) && (common_hdr.ptype != PKT_AUTH3)) + { status = RPCRT4_SecurePacket(Connection, SECURE_PACKET_RECEIVE, *Header, hdr_length, (unsigned char *)pMsg->Buffer + buffer_length, data_length, (RpcAuthVerifier *)auth_data, (unsigned char *)auth_data + sizeof(RpcAuthVerifier), header_auth_len - sizeof(RpcAuthVerifier)); + if (status != RPC_S_OK) goto fail; + } } buffer_length += data_length; @@ -844,7 +856,7 @@ RPC_STATUS RPCRT4_Receive(RpcConnection *Connection, RpcPktHdr **Header, dwRead = rpcrt4_conn_read(Connection, *Header, hdr_length); if (dwRead != hdr_length) { WARN("invalid packet header size (%d)\n", dwRead); - status = RPC_S_PROTOCOL_ERROR; + status = RPC_S_CALL_FAILED; goto fail; } @@ -869,6 +881,7 @@ RPC_STATUS RPCRT4_Receive(RpcConnection *Connection, RpcPktHdr **Header, status = RPC_S_OK; fail: + RPCRT4_SetThreadCurrentConnection(NULL); if (status != RPC_S_OK) { RPCRT4_FreeHeader(*Header); *Header = NULL; diff --git a/reactos/dll/win32/rpcrt4_new/rpc_message.h b/reactos/dll/win32/rpcrt4_new/rpc_message.h index 4eb0d54d15e..eab30608b7e 100644 --- a/reactos/dll/win32/rpcrt4_new/rpc_message.h +++ b/reactos/dll/win32/rpcrt4_new/rpc_message.h @@ -30,7 +30,7 @@ RpcPktHdr *RPCRT4_BuildFaultHeader(unsigned long DataRepresentation, RPC_STATUS RpcPktHdr *RPCRT4_BuildResponseHeader(unsigned long DataRepresentation, unsigned long BufferLength); RpcPktHdr *RPCRT4_BuildBindHeader(unsigned long DataRepresentation, unsigned short MaxTransmissionSize, unsigned short MaxReceiveSize, unsigned long AssocGroupId, const RPC_SYNTAX_IDENTIFIER *AbstractId, const RPC_SYNTAX_IDENTIFIER *TransferId); RpcPktHdr *RPCRT4_BuildBindNackHeader(unsigned long DataRepresentation, unsigned char RpcVersion, unsigned char RpcVersionMinor); -RpcPktHdr *RPCRT4_BuildBindAckHeader(unsigned long DataRepresentation, unsigned short MaxTransmissionSize, unsigned short MaxReceiveSize, LPCSTR ServerAddress, unsigned long Result, unsigned long Reason, const RPC_SYNTAX_IDENTIFIER *TransferId); +RpcPktHdr *RPCRT4_BuildBindAckHeader(unsigned long DataRepresentation, unsigned short MaxTransmissionSize, unsigned short MaxReceiveSize, unsigned long AssocGroupId, LPCSTR ServerAddress, unsigned long Result, unsigned long Reason, const RPC_SYNTAX_IDENTIFIER *TransferId); VOID RPCRT4_FreeHeader(RpcPktHdr *Header); RPC_STATUS RPCRT4_Send(RpcConnection *Connection, RpcPktHdr *Header, void *Buffer, unsigned int BufferLength); RPC_STATUS RPCRT4_Receive(RpcConnection *Connection, RpcPktHdr **Header, PRPC_MESSAGE pMsg); diff --git a/reactos/dll/win32/rpcrt4_new/rpc_server.c b/reactos/dll/win32/rpcrt4_new/rpc_server.c index bc60868ba6e..880d8e5a14b 100644 --- a/reactos/dll/win32/rpcrt4_new/rpc_server.c +++ b/reactos/dll/win32/rpcrt4_new/rpc_server.c @@ -42,6 +42,7 @@ #include "wine/exception.h" #include "rpc_server.h" +#include "rpc_assoc.h" #include "rpc_message.h" #include "rpc_defs.h" #include "ncastatus.h" @@ -167,10 +168,13 @@ static void RPCRT4_process_packet(RpcConnection* conn, RpcPktHdr* hdr, RPC_MESSA RpcServerInterface* sif; RPC_DISPATCH_FUNCTION func; UUID *object_uuid; - RpcPktHdr *response; + RpcPktHdr *response = NULL; void *buf = msg->Buffer; RPC_STATUS status; BOOL exception; + NDR_SCONTEXT context_handle; + + msg->Handle = (RPC_BINDING_HANDLE)conn->server_binding; switch (hdr->common.ptype) { case PKT_BIND: @@ -178,11 +182,21 @@ static void RPCRT4_process_packet(RpcConnection* conn, RpcPktHdr* hdr, RPC_MESSA /* FIXME: do more checks! */ if (hdr->bind.max_tsize < RPC_MIN_PACKET_SIZE || - !UuidIsNil(&conn->ActiveInterface.SyntaxGUID, &status)) { + !UuidIsNil(&conn->ActiveInterface.SyntaxGUID, &status) || + conn->server_binding) { TRACE("packet size less than min size, or active interface syntax guid non-null\n"); sif = NULL; } else { - sif = RPCRT4_find_interface(NULL, &hdr->bind.abstract, FALSE); + /* create temporary binding */ + if (RPCRT4_MakeBinding(&conn->server_binding, conn) == RPC_S_OK && + RpcServerAssoc_GetAssociation(rpcrt4_conn_get_name(conn), + conn->NetworkAddr, conn->Endpoint, + conn->NetworkOptions, + hdr->bind.assoc_gid, + &conn->server_binding->Assoc) == RPC_S_OK) + sif = RPCRT4_find_interface(NULL, &hdr->bind.abstract, FALSE); + else + sif = NULL; } if (sif == NULL) { TRACE("rejecting bind request on connection %p\n", conn); @@ -197,6 +211,7 @@ static void RPCRT4_process_packet(RpcConnection* conn, RpcPktHdr* hdr, RPC_MESSA response = RPCRT4_BuildBindAckHeader(NDR_LOCAL_DATA_REPRESENTATION, RPC_MAX_PACKET_SIZE, RPC_MAX_PACKET_SIZE, + conn->server_binding->Assoc->assoc_group_id, conn->Endpoint, RESULT_ACCEPT, REASON_NONE, &sif->If->TransferSyntax); @@ -272,13 +287,14 @@ static void RPCRT4_process_packet(RpcConnection* conn, RpcPktHdr* hdr, RPC_MESSA /* put in the drep. FIXME: is this more universally applicable? perhaps we should move this outward... */ - msg->DataRepresentation = + msg->DataRepresentation = MAKELONG( MAKEWORD(hdr->common.drep[0], hdr->common.drep[1]), MAKEWORD(hdr->common.drep[2], hdr->common.drep[3])); exception = FALSE; /* dispatch */ + RPCRT4_SetThreadCurrentCallHandle(msg->Handle); __TRY { if (func) func(msg); } __EXCEPT(rpc_filter) { @@ -290,6 +306,11 @@ static void RPCRT4_process_packet(RpcConnection* conn, RpcPktHdr* hdr, RPC_MESSA response = RPCRT4_BuildFaultHeader(msg->DataRepresentation, RPC2NCA_STATUS(status)); } __ENDTRY + RPCRT4_SetThreadCurrentCallHandle(NULL); + + /* release any unmarshalled context handles */ + while ((context_handle = RPCRT4_PopThreadContextHandle()) != NULL) + RpcServerAssoc_ReleaseContextHandle(conn->server_binding->Assoc, context_handle, TRUE); if (!exception) response = RPCRT4_BuildResponseHeader(msg->DataRepresentation, @@ -318,7 +339,6 @@ fail: if (msg->Buffer == buf) msg->Buffer = NULL; TRACE("freeing Buffer=%p\n", buf); HeapFree(GetProcessHeap(), 0, buf); - RPCRT4_DestroyBinding(msg->Handle); msg->Handle = 0; I_RpcFreeBuffer(msg); msg->Buffer = NULL; @@ -338,7 +358,6 @@ static DWORD CALLBACK RPCRT4_io_thread(LPVOID the_arg) { RpcConnection* conn = (RpcConnection*)the_arg; RpcPktHdr *hdr; - RpcBinding *pbind; RPC_MESSAGE *msg; RPC_STATUS status; RpcPacket *packet; @@ -348,11 +367,6 @@ static DWORD CALLBACK RPCRT4_io_thread(LPVOID the_arg) for (;;) { msg = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RPC_MESSAGE)); - /* create temporary binding for dispatch, it will be freed in - * RPCRT4_process_packet */ - RPCRT4_MakeBinding(&pbind, conn); - msg->Handle = (RPC_BINDING_HANDLE)pbind; - status = RPCRT4_Receive(conn, &hdr, msg); if (status != RPC_S_OK) { WARN("receive failed with error %lx\n", status); @@ -503,7 +517,7 @@ static RPC_STATUS RPCRT4_start_listen(BOOL auto_listen) status = RPCRT4_start_listen_protseq(cps, TRUE); if (status != RPC_S_OK) break; - + /* make sure server is actually listening on the interface before * returning */ RPCRT4_sync_with_server_thread(cps); @@ -613,14 +627,14 @@ RPC_STATUS WINAPI RpcServerInqBindings( RPC_BINDING_VECTOR** BindingVector ) RPC_STATUS WINAPI RpcServerUseProtseqEpA( RPC_CSTR Protseq, UINT MaxCalls, RPC_CSTR Endpoint, LPVOID SecurityDescriptor ) { RPC_POLICY policy; - + TRACE( "(%s,%u,%s,%p)\n", Protseq, MaxCalls, Endpoint, SecurityDescriptor ); - + /* This should provide the default behaviour */ policy.Length = sizeof( policy ); policy.EndpointFlags = 0; policy.NICFlags = 0; - + return RpcServerUseProtseqEpExA( Protseq, MaxCalls, Endpoint, SecurityDescriptor, &policy ); } @@ -630,14 +644,14 @@ RPC_STATUS WINAPI RpcServerUseProtseqEpA( RPC_CSTR Protseq, UINT MaxCalls, RPC_C RPC_STATUS WINAPI RpcServerUseProtseqEpW( RPC_WSTR Protseq, UINT MaxCalls, RPC_WSTR Endpoint, LPVOID SecurityDescriptor ) { RPC_POLICY policy; - + TRACE( "(%s,%u,%s,%p)\n", debugstr_w( Protseq ), MaxCalls, debugstr_w( Endpoint ), SecurityDescriptor ); - + /* This should provide the default behaviour */ policy.Length = sizeof( policy ); policy.EndpointFlags = 0; policy.NICFlags = 0; - + return RpcServerUseProtseqEpExW( Protseq, MaxCalls, Endpoint, SecurityDescriptor, &policy ); } @@ -935,7 +949,7 @@ RPC_STATUS WINAPI RpcObjectSetType( UUID* ObjUuid, UUID* TypeUuid ) if ((! TypeUuid) || UuidIsNil(TypeUuid, &dummy)) { /* ... and drop it from the list */ if (map) { - if (prev) + if (prev) prev->next = map->next; else RpcObjTypeMaps = map->next; @@ -966,7 +980,7 @@ RPC_STATUS WINAPI RpcServerRegisterAuthInfoA( RPC_CSTR ServerPrincName, ULONG Au LPVOID Arg ) { FIXME( "(%s,%u,%p,%p): stub\n", ServerPrincName, AuthnSvc, GetKeyFn, Arg ); - + return RPC_S_UNKNOWN_AUTHN_SERVICE; /* We don't know any authentication services */ } @@ -977,7 +991,7 @@ RPC_STATUS WINAPI RpcServerRegisterAuthInfoW( RPC_WSTR ServerPrincName, ULONG Au LPVOID Arg ) { FIXME( "(%s,%u,%p,%p): stub\n", debugstr_w( ServerPrincName ), AuthnSvc, GetKeyFn, Arg ); - + return RPC_S_UNKNOWN_AUTHN_SERVICE; /* We don't know any authentication services */ } @@ -1013,7 +1027,7 @@ RPC_STATUS WINAPI RpcMgmtWaitServerListen( void ) LeaveCriticalSection(&listen_cs); return RPC_S_NOT_LISTENING; } - + LeaveCriticalSection(&listen_cs); FIXME("not waiting for server calls to finish\n"); @@ -1032,7 +1046,7 @@ RPC_STATUS WINAPI RpcMgmtStopServerListening ( RPC_BINDING_HANDLE Binding ) FIXME("client-side invocation not implemented.\n"); return RPC_S_WRONG_KIND_OF_BINDING; } - + RPCRT4_stop_listen(FALSE); return RPC_S_OK; @@ -1114,3 +1128,12 @@ RPC_STATUS WINAPI RpcMgmtSetServerStackSize(ULONG ThreadStackSize) FIXME("(0x%x): stub\n", ThreadStackSize); return RPC_S_OK; } + +/*********************************************************************** + * I_RpcGetCurrentCallHandle (RPCRT4.@) + */ +RPC_BINDING_HANDLE WINAPI I_RpcGetCurrentCallHandle(void) +{ + TRACE("\n"); + return RPCRT4_GetThreadCurrentCallHandle(); +} diff --git a/reactos/dll/win32/rpcrt4_new/rpc_transport.c b/reactos/dll/win32/rpcrt4_new/rpc_transport.c index 6e2a699cece..5bc26ffd297 100644 --- a/reactos/dll/win32/rpcrt4_new/rpc_transport.c +++ b/reactos/dll/win32/rpcrt4_new/rpc_transport.c @@ -1,1837 +1,1642 @@ -/* - * RPC transport layer - * - * Copyright 2001 Ove Kåven, TransGaming Technologies - * Copyright 2003 Mike Hearn - * Copyright 2004 Filip Navara - * Copyright 2006 Mike McCormack - * Copyright 2006 Damjan Jovanovic - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - * - */ - -#include "config.h" - -#include -#include -#include -#include -#include - -#ifdef HAVE_UNISTD_H -# include -#endif -#include -#include -#include -#ifdef HAVE_SYS_SOCKET_H -# include -#endif -#ifdef HAVE_NETINET_IN_H -# include -#endif -#ifdef HAVE_NETINET_TCP_H -# include -#endif -#ifdef HAVE_ARPA_INET_H -# include -#endif -#ifdef HAVE_NETDB_H -#include -#endif -#ifdef HAVE_SYS_POLL_H -#include -#endif - -#include -#include - -#include "windef.h" -#include "winbase.h" -#include "winnls.h" -#include "winerror.h" -#include "winternl.h" -#include "wine/unicode.h" - -#include "rpc.h" -#include "rpcndr.h" - -#include "wine/debug.h" - -#include "rpc_binding.h" -#include "rpc_message.h" -#include "rpc_server.h" -#include "epm_towers.h" - -#include "unix_func.h" - -#ifndef SOL_TCP -# define SOL_TCP IPPROTO_TCP -#endif - -WINE_DEFAULT_DEBUG_CHANNEL(rpc); - -static CRITICAL_SECTION assoc_list_cs; -static CRITICAL_SECTION_DEBUG assoc_list_cs_debug = -{ - 0, 0, &assoc_list_cs, - { &assoc_list_cs_debug.ProcessLocksList, &assoc_list_cs_debug.ProcessLocksList }, - 0, 0, { (DWORD_PTR)(__FILE__ ": assoc_list_cs") } -}; -static CRITICAL_SECTION assoc_list_cs = { &assoc_list_cs_debug, -1, 0, 0, 0, 0 }; - -static struct list assoc_list = LIST_INIT(assoc_list); - -/**** ncacn_np support ****/ - -typedef struct _RpcConnection_np -{ - RpcConnection common; - HANDLE pipe; - OVERLAPPED ovl; - BOOL listening; -} RpcConnection_np; - -static RpcConnection *rpcrt4_conn_np_alloc(void) -{ - RpcConnection_np *npc = HeapAlloc(GetProcessHeap(), 0, sizeof(RpcConnection_np)); - if (npc) - { - npc->pipe = NULL; - memset(&npc->ovl, 0, sizeof(npc->ovl)); - npc->listening = FALSE; - } - return &npc->common; -} - -static RPC_STATUS rpcrt4_conn_listen_pipe(RpcConnection_np *npc) -{ - if (npc->listening) - return RPC_S_OK; - - npc->listening = TRUE; - if (ConnectNamedPipe(npc->pipe, &npc->ovl)) - return RPC_S_OK; - - if (GetLastError() == ERROR_PIPE_CONNECTED) { - SetEvent(npc->ovl.hEvent); - return RPC_S_OK; - } - if (GetLastError() == ERROR_IO_PENDING) { - /* will be completed in rpcrt4_protseq_np_wait_for_new_connection */ - return RPC_S_OK; - } - npc->listening = FALSE; - WARN("Couldn't ConnectNamedPipe (error was %d)\n", GetLastError()); - return RPC_S_OUT_OF_RESOURCES; -} - -static RPC_STATUS rpcrt4_conn_create_pipe(RpcConnection *Connection, LPCSTR pname) -{ - RpcConnection_np *npc = (RpcConnection_np *) Connection; - TRACE("listening on %s\n", pname); - - npc->pipe = CreateNamedPipeA(pname, PIPE_ACCESS_DUPLEX, - PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, - PIPE_UNLIMITED_INSTANCES, - RPC_MAX_PACKET_SIZE, RPC_MAX_PACKET_SIZE, 5000, NULL); - if (npc->pipe == INVALID_HANDLE_VALUE) { - WARN("CreateNamedPipe failed with error %d\n", GetLastError()); - if (GetLastError() == ERROR_FILE_EXISTS) - return RPC_S_DUPLICATE_ENDPOINT; - else - return RPC_S_CANT_CREATE_ENDPOINT; - } - - memset(&npc->ovl, 0, sizeof(npc->ovl)); - npc->ovl.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL); - - /* Note: we don't call ConnectNamedPipe here because it must be done in the - * server thread as the thread must be alertable */ - return RPC_S_OK; -} - -static RPC_STATUS rpcrt4_conn_open_pipe(RpcConnection *Connection, LPCSTR pname, BOOL wait) -{ - RpcConnection_np *npc = (RpcConnection_np *) Connection; - HANDLE pipe; - DWORD err, dwMode; - - TRACE("connecting to %s\n", pname); - - while (TRUE) { - DWORD dwFlags = 0; - if (Connection->QOS) - { - dwFlags = SECURITY_SQOS_PRESENT; - switch (Connection->QOS->qos->ImpersonationType) - { - case RPC_C_IMP_LEVEL_DEFAULT: - /* FIXME: what to do here? */ - break; - case RPC_C_IMP_LEVEL_ANONYMOUS: - dwFlags |= SECURITY_ANONYMOUS; - break; - case RPC_C_IMP_LEVEL_IDENTIFY: - dwFlags |= SECURITY_IDENTIFICATION; - break; - case RPC_C_IMP_LEVEL_IMPERSONATE: - dwFlags |= SECURITY_IMPERSONATION; - break; - case RPC_C_IMP_LEVEL_DELEGATE: - dwFlags |= SECURITY_DELEGATION; - break; - } - if (Connection->QOS->qos->IdentityTracking == RPC_C_QOS_IDENTIFY_DYNAMIC) - dwFlags |= SECURITY_CONTEXT_TRACKING; - } - pipe = CreateFileA(pname, GENERIC_READ|GENERIC_WRITE, 0, NULL, - OPEN_EXISTING, dwFlags, 0); - if (pipe != INVALID_HANDLE_VALUE) break; - err = GetLastError(); - if (err == ERROR_PIPE_BUSY) { - TRACE("connection failed, error=%x\n", err); - return RPC_S_SERVER_TOO_BUSY; - } - if (!wait) - return RPC_S_SERVER_UNAVAILABLE; - if (!WaitNamedPipeA(pname, NMPWAIT_WAIT_FOREVER)) { - err = GetLastError(); - WARN("connection failed, error=%x\n", err); - return RPC_S_SERVER_UNAVAILABLE; - } - } - - /* success */ - memset(&npc->ovl, 0, sizeof(npc->ovl)); - /* pipe is connected; change to message-read mode. */ - dwMode = PIPE_READMODE_MESSAGE; - SetNamedPipeHandleState(pipe, &dwMode, NULL, NULL); - npc->ovl.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL); - npc->pipe = pipe; - - return RPC_S_OK; -} - -static RPC_STATUS rpcrt4_ncalrpc_open(RpcConnection* Connection) -{ - RpcConnection_np *npc = (RpcConnection_np *) Connection; - static const char prefix[] = "\\\\.\\pipe\\lrpc\\"; - RPC_STATUS r; - LPSTR pname; - - /* already connected? */ - if (npc->pipe) - return RPC_S_OK; - - /* protseq=ncalrpc: supposed to use NT LPC ports, - * but we'll implement it with named pipes for now */ - pname = I_RpcAllocate(strlen(prefix) + strlen(Connection->Endpoint) + 1); - strcat(strcpy(pname, prefix), Connection->Endpoint); - r = rpcrt4_conn_open_pipe(Connection, pname, TRUE); - I_RpcFree(pname); - - return r; -} - -static RPC_STATUS rpcrt4_protseq_ncalrpc_open_endpoint(RpcServerProtseq* protseq, LPSTR endpoint) -{ - static const char prefix[] = "\\\\.\\pipe\\lrpc\\"; - RPC_STATUS r; - LPSTR pname; - RpcConnection *Connection; - - r = RPCRT4_CreateConnection(&Connection, TRUE, protseq->Protseq, NULL, - endpoint, NULL, NULL, NULL); - if (r != RPC_S_OK) - return r; - - /* protseq=ncalrpc: supposed to use NT LPC ports, - * but we'll implement it with named pipes for now */ - pname = I_RpcAllocate(strlen(prefix) + strlen(Connection->Endpoint) + 1); - strcat(strcpy(pname, prefix), Connection->Endpoint); - r = rpcrt4_conn_create_pipe(Connection, pname); - I_RpcFree(pname); - - EnterCriticalSection(&protseq->cs); - Connection->Next = protseq->conn; - protseq->conn = Connection; - LeaveCriticalSection(&protseq->cs); - - return r; -} - -static RPC_STATUS rpcrt4_ncacn_np_open(RpcConnection* Connection) -{ - RpcConnection_np *npc = (RpcConnection_np *) Connection; - static const char prefix[] = "\\\\."; - RPC_STATUS r; - LPSTR pname; - - /* already connected? */ - if (npc->pipe) - return RPC_S_OK; - - /* protseq=ncacn_np: named pipes */ - pname = I_RpcAllocate(strlen(prefix) + strlen(Connection->Endpoint) + 1); - strcat(strcpy(pname, prefix), Connection->Endpoint); - r = rpcrt4_conn_open_pipe(Connection, pname, FALSE); - I_RpcFree(pname); - - return r; -} - -static RPC_STATUS rpcrt4_protseq_ncacn_np_open_endpoint(RpcServerProtseq *protseq, LPSTR endpoint) -{ - static const char prefix[] = "\\\\."; - RPC_STATUS r; - LPSTR pname; - RpcConnection *Connection; - - r = RPCRT4_CreateConnection(&Connection, TRUE, protseq->Protseq, NULL, - endpoint, NULL, NULL, NULL); - if (r != RPC_S_OK) - return r; - - /* protseq=ncacn_np: named pipes */ - pname = I_RpcAllocate(strlen(prefix) + strlen(Connection->Endpoint) + 1); - strcat(strcpy(pname, prefix), Connection->Endpoint); - r = rpcrt4_conn_create_pipe(Connection, pname); - I_RpcFree(pname); - - EnterCriticalSection(&protseq->cs); - Connection->Next = protseq->conn; - protseq->conn = Connection; - LeaveCriticalSection(&protseq->cs); - - return r; -} - -static void rpcrt4_conn_np_handoff(RpcConnection_np *old_npc, RpcConnection_np *new_npc) -{ - /* because of the way named pipes work, we'll transfer the connected pipe - * to the child, then reopen the server binding to continue listening */ - - new_npc->pipe = old_npc->pipe; - new_npc->ovl = old_npc->ovl; - old_npc->pipe = 0; - memset(&old_npc->ovl, 0, sizeof(old_npc->ovl)); - old_npc->listening = FALSE; -} - -static RPC_STATUS rpcrt4_ncacn_np_handoff(RpcConnection *old_conn, RpcConnection *new_conn) -{ - RPC_STATUS status; - LPSTR pname; - static const char prefix[] = "\\\\."; - - rpcrt4_conn_np_handoff((RpcConnection_np *)old_conn, (RpcConnection_np *)new_conn); - - pname = I_RpcAllocate(strlen(prefix) + strlen(old_conn->Endpoint) + 1); - strcat(strcpy(pname, prefix), old_conn->Endpoint); - status = rpcrt4_conn_create_pipe(old_conn, pname); - I_RpcFree(pname); - - return status; -} - -static RPC_STATUS rpcrt4_ncalrpc_handoff(RpcConnection *old_conn, RpcConnection *new_conn) -{ - RPC_STATUS status; - LPSTR pname; - static const char prefix[] = "\\\\.\\pipe\\lrpc\\"; - - TRACE("%s\n", old_conn->Endpoint); - - rpcrt4_conn_np_handoff((RpcConnection_np *)old_conn, (RpcConnection_np *)new_conn); - - pname = I_RpcAllocate(strlen(prefix) + strlen(old_conn->Endpoint) + 1); - strcat(strcpy(pname, prefix), old_conn->Endpoint); - status = rpcrt4_conn_create_pipe(old_conn, pname); - I_RpcFree(pname); - - return status; -} - -static int rpcrt4_conn_np_read(RpcConnection *Connection, - void *buffer, unsigned int count) -{ - RpcConnection_np *npc = (RpcConnection_np *) Connection; - char *buf = buffer; - BOOL ret = TRUE; - unsigned int bytes_left = count; - - while (bytes_left) - { - DWORD bytes_read; - ret = ReadFile(npc->pipe, buf, bytes_left, &bytes_read, NULL); - if (!ret || !bytes_read) - break; - bytes_left -= bytes_read; - buf += bytes_read; - } - return ret ? count : -1; -} - -static int rpcrt4_conn_np_write(RpcConnection *Connection, - const void *buffer, unsigned int count) -{ - RpcConnection_np *npc = (RpcConnection_np *) Connection; - const char *buf = buffer; - BOOL ret = TRUE; - unsigned int bytes_left = count; - - while (bytes_left) - { - DWORD bytes_written; - ret = WriteFile(npc->pipe, buf, count, &bytes_written, NULL); - if (!ret || !bytes_written) - break; - bytes_left -= bytes_written; - buf += bytes_written; - } - return ret ? count : -1; -} - -static int rpcrt4_conn_np_close(RpcConnection *Connection) -{ - RpcConnection_np *npc = (RpcConnection_np *) Connection; - if (npc->pipe) { - FlushFileBuffers(npc->pipe); - CloseHandle(npc->pipe); - npc->pipe = 0; - } - if (npc->ovl.hEvent) { - CloseHandle(npc->ovl.hEvent); - npc->ovl.hEvent = 0; - } - return 0; -} - -static size_t rpcrt4_ncacn_np_get_top_of_tower(unsigned char *tower_data, - const char *networkaddr, - const char *endpoint) -{ - twr_empty_floor_t *smb_floor; - twr_empty_floor_t *nb_floor; - size_t size; - size_t networkaddr_size; - size_t endpoint_size; - - TRACE("(%p, %s, %s)\n", tower_data, networkaddr, endpoint); - - networkaddr_size = strlen(networkaddr) + 1; - endpoint_size = strlen(endpoint) + 1; - size = sizeof(*smb_floor) + endpoint_size + sizeof(*nb_floor) + networkaddr_size; - - if (!tower_data) - return size; - - smb_floor = (twr_empty_floor_t *)tower_data; - - tower_data += sizeof(*smb_floor); - - smb_floor->count_lhs = sizeof(smb_floor->protid); - smb_floor->protid = EPM_PROTOCOL_SMB; - smb_floor->count_rhs = endpoint_size; - - memcpy(tower_data, endpoint, endpoint_size); - tower_data += endpoint_size; - - nb_floor = (twr_empty_floor_t *)tower_data; - - tower_data += sizeof(*nb_floor); - - nb_floor->count_lhs = sizeof(nb_floor->protid); - nb_floor->protid = EPM_PROTOCOL_NETBIOS; - nb_floor->count_rhs = networkaddr_size; - - memcpy(tower_data, networkaddr, networkaddr_size); - tower_data += networkaddr_size; - - return size; -} - -static RPC_STATUS rpcrt4_ncacn_np_parse_top_of_tower(const unsigned char *tower_data, - size_t tower_size, - char **networkaddr, - char **endpoint) -{ - const twr_empty_floor_t *smb_floor = (const twr_empty_floor_t *)tower_data; - const twr_empty_floor_t *nb_floor; - - TRACE("(%p, %d, %p, %p)\n", tower_data, (int)tower_size, networkaddr, endpoint); - - if (tower_size < sizeof(*smb_floor)) - return EPT_S_NOT_REGISTERED; - - tower_data += sizeof(*smb_floor); - tower_size -= sizeof(*smb_floor); - - if ((smb_floor->count_lhs != sizeof(smb_floor->protid)) || - (smb_floor->protid != EPM_PROTOCOL_SMB) || - (smb_floor->count_rhs > tower_size)) - return EPT_S_NOT_REGISTERED; - - if (endpoint) - { - *endpoint = I_RpcAllocate(smb_floor->count_rhs); - if (!*endpoint) - return RPC_S_OUT_OF_RESOURCES; - memcpy(*endpoint, tower_data, smb_floor->count_rhs); - } - tower_data += smb_floor->count_rhs; - tower_size -= smb_floor->count_rhs; - - if (tower_size < sizeof(*nb_floor)) - return EPT_S_NOT_REGISTERED; - - nb_floor = (const twr_empty_floor_t *)tower_data; - - tower_data += sizeof(*nb_floor); - tower_size -= sizeof(*nb_floor); - - if ((nb_floor->count_lhs != sizeof(nb_floor->protid)) || - (nb_floor->protid != EPM_PROTOCOL_NETBIOS) || - (nb_floor->count_rhs > tower_size)) - return EPT_S_NOT_REGISTERED; - - if (networkaddr) - { - *networkaddr = I_RpcAllocate(nb_floor->count_rhs); - if (!*networkaddr) - { - if (endpoint) - { - I_RpcFree(*endpoint); - *endpoint = NULL; - } - return RPC_S_OUT_OF_RESOURCES; - } - memcpy(*networkaddr, tower_data, nb_floor->count_rhs); - } - - return RPC_S_OK; -} - -typedef struct _RpcServerProtseq_np -{ - RpcServerProtseq common; - HANDLE mgr_event; -} RpcServerProtseq_np; - -static RpcServerProtseq *rpcrt4_protseq_np_alloc(void) -{ - RpcServerProtseq_np *ps = HeapAlloc(GetProcessHeap(), 0, sizeof(*ps)); - if (ps) - ps->mgr_event = CreateEventW(NULL, FALSE, FALSE, NULL); - return &ps->common; -} - -static void rpcrt4_protseq_np_signal_state_changed(RpcServerProtseq *protseq) -{ - RpcServerProtseq_np *npps = CONTAINING_RECORD(protseq, RpcServerProtseq_np, common); - SetEvent(npps->mgr_event); -} - -static void *rpcrt4_protseq_np_get_wait_array(RpcServerProtseq *protseq, void *prev_array, unsigned int *count) -{ - HANDLE *objs = prev_array; - RpcConnection_np *conn; - RpcServerProtseq_np *npps = CONTAINING_RECORD(protseq, RpcServerProtseq_np, common); - - EnterCriticalSection(&protseq->cs); - - /* open and count connections */ - *count = 1; - conn = CONTAINING_RECORD(protseq->conn, RpcConnection_np, common); - while (conn) { - rpcrt4_conn_listen_pipe(conn); - if (conn->ovl.hEvent) - (*count)++; - conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_np, common); - } - - /* make array of connections */ - if (objs) - objs = HeapReAlloc(GetProcessHeap(), 0, objs, *count*sizeof(HANDLE)); - else - objs = HeapAlloc(GetProcessHeap(), 0, *count*sizeof(HANDLE)); - if (!objs) - { - ERR("couldn't allocate objs\n"); - LeaveCriticalSection(&protseq->cs); - return NULL; - } - - objs[0] = npps->mgr_event; - *count = 1; - conn = CONTAINING_RECORD(protseq->conn, RpcConnection_np, common); - while (conn) { - if ((objs[*count] = conn->ovl.hEvent)) - (*count)++; - conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_np, common); - } - LeaveCriticalSection(&protseq->cs); - return objs; -} - -static void rpcrt4_protseq_np_free_wait_array(RpcServerProtseq *protseq, void *array) -{ - HeapFree(GetProcessHeap(), 0, array); -} - -static int rpcrt4_protseq_np_wait_for_new_connection(RpcServerProtseq *protseq, unsigned int count, void *wait_array) -{ - HANDLE b_handle; - HANDLE *objs = wait_array; - DWORD res; - RpcConnection *cconn; - RpcConnection_np *conn; - - if (!objs) - return -1; - - res = WaitForMultipleObjects(count, objs, FALSE, INFINITE); - if (res == WAIT_OBJECT_0) - return 0; - else if (res == WAIT_FAILED) - { - ERR("wait failed with error %d\n", GetLastError()); - return -1; - } - else - { - b_handle = objs[res - WAIT_OBJECT_0]; - /* find which connection got a RPC */ - EnterCriticalSection(&protseq->cs); - conn = CONTAINING_RECORD(protseq->conn, RpcConnection_np, common); - while (conn) { - if (b_handle == conn->ovl.hEvent) break; - conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_np, common); - } - cconn = NULL; - if (conn) - RPCRT4_SpawnConnection(&cconn, &conn->common); - else - ERR("failed to locate connection for handle %p\n", b_handle); - LeaveCriticalSection(&protseq->cs); - if (cconn) - { - RPCRT4_new_client(cconn); - return 1; - } - else return -1; - } -} - -static size_t rpcrt4_ncalrpc_get_top_of_tower(unsigned char *tower_data, - const char *networkaddr, - const char *endpoint) -{ - twr_empty_floor_t *pipe_floor; - size_t size; - size_t endpoint_size; - - TRACE("(%p, %s, %s)\n", tower_data, networkaddr, endpoint); - - endpoint_size = strlen(networkaddr) + 1; - size = sizeof(*pipe_floor) + endpoint_size; - - if (!tower_data) - return size; - - pipe_floor = (twr_empty_floor_t *)tower_data; - - tower_data += sizeof(*pipe_floor); - - pipe_floor->count_lhs = sizeof(pipe_floor->protid); - pipe_floor->protid = EPM_PROTOCOL_SMB; - pipe_floor->count_rhs = endpoint_size; - - memcpy(tower_data, endpoint, endpoint_size); - tower_data += endpoint_size; - - return size; -} - -static RPC_STATUS rpcrt4_ncalrpc_parse_top_of_tower(const unsigned char *tower_data, - size_t tower_size, - char **networkaddr, - char **endpoint) -{ - const twr_empty_floor_t *pipe_floor = (const twr_empty_floor_t *)tower_data; - - TRACE("(%p, %d, %p, %p)\n", tower_data, (int)tower_size, networkaddr, endpoint); - - *networkaddr = NULL; - *endpoint = NULL; - - if (tower_size < sizeof(*pipe_floor)) - return EPT_S_NOT_REGISTERED; - - tower_data += sizeof(*pipe_floor); - tower_size -= sizeof(*pipe_floor); - - if ((pipe_floor->count_lhs != sizeof(pipe_floor->protid)) || - (pipe_floor->protid != EPM_PROTOCOL_SMB) || - (pipe_floor->count_rhs > tower_size)) - return EPT_S_NOT_REGISTERED; - - if (endpoint) - { - *endpoint = I_RpcAllocate(pipe_floor->count_rhs); - if (!*endpoint) - return RPC_S_OUT_OF_RESOURCES; - memcpy(*endpoint, tower_data, pipe_floor->count_rhs); - } - - return RPC_S_OK; -} - -/**** ncacn_ip_tcp support ****/ - -typedef struct _RpcConnection_tcp -{ - RpcConnection common; - int sock; -} RpcConnection_tcp; - -static RpcConnection *rpcrt4_conn_tcp_alloc(void) -{ - RpcConnection_tcp *tcpc; - tcpc = HeapAlloc(GetProcessHeap(), 0, sizeof(RpcConnection_tcp)); - if (tcpc == NULL) - return NULL; - tcpc->sock = -1; - return &tcpc->common; -} - -static RPC_STATUS rpcrt4_ncacn_ip_tcp_open(RpcConnection* Connection) -{ - RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection; - int sock; - int ret; - struct addrinfo *ai; - struct addrinfo *ai_cur; - struct addrinfo hints; - - TRACE("(%s, %s)\n", Connection->NetworkAddr, Connection->Endpoint); - - if (tcpc->sock != -1) - return RPC_S_OK; - - hints.ai_flags = 0; - hints.ai_family = PF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; - hints.ai_addrlen = 0; - hints.ai_addr = NULL; - hints.ai_canonname = NULL; - hints.ai_next = NULL; - - ret = getaddrinfo(Connection->NetworkAddr, Connection->Endpoint, &hints, &ai); - if (ret) - { - ERR("getaddrinfo for %s:%s failed: %s\n", Connection->NetworkAddr, - Connection->Endpoint, gai_strerror(ret)); - return RPC_S_SERVER_UNAVAILABLE; - } - - for (ai_cur = ai; ai_cur; ai_cur = ai_cur->ai_next) - { - int val; - - if (TRACE_ON(rpc)) - { - char host[256]; - char service[256]; - getnameinfo(ai_cur->ai_addr, ai_cur->ai_addrlen, - host, sizeof(host), service, sizeof(service), - NI_NUMERICHOST | NI_NUMERICSERV); - TRACE("trying %s:%s\n", host, service); - } - - sock = socket(ai_cur->ai_family, ai_cur->ai_socktype, ai_cur->ai_protocol); - if (sock < 0) - { - WARN("socket() failed: %s\n", strerror(errno)); - continue; - } - - if (0>connect(sock, ai_cur->ai_addr, ai_cur->ai_addrlen)) - { - WARN("connect() failed: %s\n", strerror(errno)); - close(sock); - continue; - } - - /* RPC depends on having minimal latency so disable the Nagle algorithm */ - val = 1; - setsockopt(sock, SOL_TCP, TCP_NODELAY, (char *)&val, sizeof(val)); - - tcpc->sock = sock; - - freeaddrinfo(ai); - TRACE("connected\n"); - return RPC_S_OK; - } - - freeaddrinfo(ai); - ERR("couldn't connect to %s:%s\n", Connection->NetworkAddr, Connection->Endpoint); - return RPC_S_SERVER_UNAVAILABLE; -} - -static RPC_STATUS rpcrt4_protseq_ncacn_ip_tcp_open_endpoint(RpcServerProtseq *protseq, LPSTR endpoint) -{ - RPC_STATUS status = RPC_S_CANT_CREATE_ENDPOINT; - int sock; - int ret; - struct addrinfo *ai; - struct addrinfo *ai_cur; - struct addrinfo hints; - RpcConnection *first_connection = NULL; - u_long blocking; - - TRACE("(%p, %s)\n", protseq, endpoint); - - hints.ai_flags = AI_PASSIVE /* for non-localhost addresses */; - hints.ai_family = PF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; - hints.ai_addrlen = 0; - hints.ai_addr = NULL; - hints.ai_canonname = NULL; - hints.ai_next = NULL; - - ret = getaddrinfo(NULL, endpoint, &hints, &ai); - if (ret) - { - ERR("getaddrinfo for port %s failed: %s\n", endpoint, - gai_strerror(ret)); - if ((ret == EAI_SERVICE) || (ret == EAI_NONAME)) - return RPC_S_INVALID_ENDPOINT_FORMAT; - return RPC_S_CANT_CREATE_ENDPOINT; - } - - for (ai_cur = ai; ai_cur; ai_cur = ai_cur->ai_next) - { - RpcConnection_tcp *tcpc; - RPC_STATUS create_status; - - if (TRACE_ON(rpc)) - { - char host[256]; - char service[256]; - getnameinfo(ai_cur->ai_addr, ai_cur->ai_addrlen, - host, sizeof(host), service, sizeof(service), - NI_NUMERICHOST | NI_NUMERICSERV); - TRACE("trying %s:%s\n", host, service); - } - - sock = socket(ai_cur->ai_family, ai_cur->ai_socktype, ai_cur->ai_protocol); - if (sock < 0) - { - WARN("socket() failed: %s\n", strerror(errno)); - status = RPC_S_CANT_CREATE_ENDPOINT; - continue; - } - - ret = bind(sock, ai_cur->ai_addr, ai_cur->ai_addrlen); - if (ret < 0) - { - WARN("bind failed: %s\n", strerror(errno)); - close(sock); - if (errno == WSAEADDRINUSE) - status = RPC_S_DUPLICATE_ENDPOINT; - else - status = RPC_S_CANT_CREATE_ENDPOINT; - continue; - } - create_status = RPCRT4_CreateConnection((RpcConnection **)&tcpc, TRUE, - protseq->Protseq, NULL, - endpoint, NULL, NULL, NULL); - if (create_status != RPC_S_OK) - { - close(sock); - status = create_status; - continue; - } - - tcpc->sock = sock; - ret = listen(sock, protseq->MaxCalls); - if (ret < 0) - { - WARN("listen failed: %s\n", strerror(errno)); - RPCRT4_DestroyConnection(&tcpc->common); - status = RPC_S_OUT_OF_RESOURCES; - continue; - } - /* need a non-blocking socket, otherwise accept() has a potential - * race-condition (poll() says it is readable, connection drops, - * and accept() blocks until the next connection comes...) - */ - blocking = 1; - ret = ioctlsocket(sock, FIONBIO, &blocking); - if (ret < 0) - { - WARN("couldn't make socket non-blocking, error %d\n", ret); - RPCRT4_DestroyConnection(&tcpc->common); - status = RPC_S_OUT_OF_RESOURCES; - continue; - } - - tcpc->common.Next = first_connection; - first_connection = &tcpc->common; - } - - freeaddrinfo(ai); - - /* if at least one connection was created for an endpoint then - * return success */ - if (first_connection) - { - RpcConnection *conn; - - /* find last element in list */ - for (conn = first_connection; conn->Next; conn = conn->Next) - ; - - EnterCriticalSection(&protseq->cs); - conn->Next = protseq->conn; - protseq->conn = first_connection; - LeaveCriticalSection(&protseq->cs); - - TRACE("listening on %s\n", endpoint); - return RPC_S_OK; - } - - ERR("couldn't listen on port %s\n", endpoint); - return status; -} - -static RPC_STATUS rpcrt4_conn_tcp_handoff(RpcConnection *old_conn, RpcConnection *new_conn) -{ - int ret; - struct sockaddr_in address; - socklen_t addrsize; - u_long blocking; - RpcConnection_tcp *server = (RpcConnection_tcp*) old_conn; - RpcConnection_tcp *client = (RpcConnection_tcp*) new_conn; - - addrsize = sizeof(address); - ret = accept(server->sock, (struct sockaddr*) &address, &addrsize); - if (ret < 0) - { - ERR("Failed to accept a TCP connection: error %d\n", ret); - return RPC_S_OUT_OF_RESOURCES; - } - /* reset to blocking behaviour */ +/* + * RPC transport layer + * + * Copyright 2001 Ove Kåven, TransGaming Technologies + * Copyright 2003 Mike Hearn + * Copyright 2004 Filip Navara + * Copyright 2006 Mike McCormack + * Copyright 2006 Damjan Jovanovic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + * + */ + +#include "config.h" + +#include +#include +#include +#include +#include + +#ifdef HAVE_UNISTD_H +# include +#endif +#include +#include +#include +#ifdef HAVE_SYS_SOCKET_H +# include +#endif +#ifdef HAVE_NETINET_IN_H +# include +#endif +#ifdef HAVE_NETINET_TCP_H +# include +#endif +#ifdef HAVE_ARPA_INET_H +# include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_SYS_POLL_H +#include +#endif + +#include +#include + +#include "windef.h" +#include "winbase.h" +#include "winnls.h" +#include "winerror.h" +#include "winternl.h" +#include "wine/unicode.h" + +#include "rpc.h" +#include "rpcndr.h" + +#include "wine/debug.h" + +#include "rpc_binding.h" +#include "rpc_message.h" +#include "rpc_server.h" +#include "epm_towers.h" + +#include "unix_func.h" + +#ifndef SOL_TCP +# define SOL_TCP IPPROTO_TCP +#endif + +WINE_DEFAULT_DEBUG_CHANNEL(rpc); + +/**** ncacn_np support ****/ + +typedef struct _RpcConnection_np +{ + RpcConnection common; + HANDLE pipe; + OVERLAPPED ovl; + BOOL listening; +} RpcConnection_np; + +static RpcConnection *rpcrt4_conn_np_alloc(void) +{ + RpcConnection_np *npc = HeapAlloc(GetProcessHeap(), 0, sizeof(RpcConnection_np)); + if (npc) + { + npc->pipe = NULL; + memset(&npc->ovl, 0, sizeof(npc->ovl)); + npc->listening = FALSE; + } + return &npc->common; +} + +static RPC_STATUS rpcrt4_conn_listen_pipe(RpcConnection_np *npc) +{ + if (npc->listening) + return RPC_S_OK; + + npc->listening = TRUE; + if (ConnectNamedPipe(npc->pipe, &npc->ovl)) + return RPC_S_OK; + + if (GetLastError() == ERROR_PIPE_CONNECTED) { + SetEvent(npc->ovl.hEvent); + return RPC_S_OK; + } + if (GetLastError() == ERROR_IO_PENDING) { + /* will be completed in rpcrt4_protseq_np_wait_for_new_connection */ + return RPC_S_OK; + } + npc->listening = FALSE; + WARN("Couldn't ConnectNamedPipe (error was %d)\n", GetLastError()); + return RPC_S_OUT_OF_RESOURCES; +} + +static RPC_STATUS rpcrt4_conn_create_pipe(RpcConnection *Connection, LPCSTR pname) +{ + RpcConnection_np *npc = (RpcConnection_np *) Connection; + TRACE("listening on %s\n", pname); + + npc->pipe = CreateNamedPipeA(pname, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, + PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, + PIPE_UNLIMITED_INSTANCES, + RPC_MAX_PACKET_SIZE, RPC_MAX_PACKET_SIZE, 5000, NULL); + if (npc->pipe == INVALID_HANDLE_VALUE) { + WARN("CreateNamedPipe failed with error %d\n", GetLastError()); + if (GetLastError() == ERROR_FILE_EXISTS) + return RPC_S_DUPLICATE_ENDPOINT; + else + return RPC_S_CANT_CREATE_ENDPOINT; + } + + memset(&npc->ovl, 0, sizeof(npc->ovl)); + npc->ovl.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL); + + /* Note: we don't call ConnectNamedPipe here because it must be done in the + * server thread as the thread must be alertable */ + return RPC_S_OK; +} + +static RPC_STATUS rpcrt4_conn_open_pipe(RpcConnection *Connection, LPCSTR pname, BOOL wait) +{ + RpcConnection_np *npc = (RpcConnection_np *) Connection; + HANDLE pipe; + DWORD err, dwMode; + + TRACE("connecting to %s\n", pname); + + while (TRUE) { + DWORD dwFlags = 0; + if (Connection->QOS) + { + dwFlags = SECURITY_SQOS_PRESENT; + switch (Connection->QOS->qos->ImpersonationType) + { + case RPC_C_IMP_LEVEL_DEFAULT: + /* FIXME: what to do here? */ + break; + case RPC_C_IMP_LEVEL_ANONYMOUS: + dwFlags |= SECURITY_ANONYMOUS; + break; + case RPC_C_IMP_LEVEL_IDENTIFY: + dwFlags |= SECURITY_IDENTIFICATION; + break; + case RPC_C_IMP_LEVEL_IMPERSONATE: + dwFlags |= SECURITY_IMPERSONATION; + break; + case RPC_C_IMP_LEVEL_DELEGATE: + dwFlags |= SECURITY_DELEGATION; + break; + } + if (Connection->QOS->qos->IdentityTracking == RPC_C_QOS_IDENTIFY_DYNAMIC) + dwFlags |= SECURITY_CONTEXT_TRACKING; + } + pipe = CreateFileA(pname, GENERIC_READ|GENERIC_WRITE, 0, NULL, + OPEN_EXISTING, dwFlags, 0); + if (pipe != INVALID_HANDLE_VALUE) break; + err = GetLastError(); + if (err == ERROR_PIPE_BUSY) { + TRACE("connection failed, error=%x\n", err); + return RPC_S_SERVER_TOO_BUSY; + } + if (!wait) + return RPC_S_SERVER_UNAVAILABLE; + if (!WaitNamedPipeA(pname, NMPWAIT_WAIT_FOREVER)) { + err = GetLastError(); + WARN("connection failed, error=%x\n", err); + return RPC_S_SERVER_UNAVAILABLE; + } + } + + /* success */ + memset(&npc->ovl, 0, sizeof(npc->ovl)); + /* pipe is connected; change to message-read mode. */ + dwMode = PIPE_READMODE_MESSAGE; + SetNamedPipeHandleState(pipe, &dwMode, NULL, NULL); + npc->ovl.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL); + npc->pipe = pipe; + + return RPC_S_OK; +} + +static RPC_STATUS rpcrt4_ncalrpc_open(RpcConnection* Connection) +{ + RpcConnection_np *npc = (RpcConnection_np *) Connection; + static const char prefix[] = "\\\\.\\pipe\\lrpc\\"; + RPC_STATUS r; + LPSTR pname; + + /* already connected? */ + if (npc->pipe) + return RPC_S_OK; + + /* protseq=ncalrpc: supposed to use NT LPC ports, + * but we'll implement it with named pipes for now */ + pname = I_RpcAllocate(strlen(prefix) + strlen(Connection->Endpoint) + 1); + strcat(strcpy(pname, prefix), Connection->Endpoint); + r = rpcrt4_conn_open_pipe(Connection, pname, TRUE); + I_RpcFree(pname); + + return r; +} + +static RPC_STATUS rpcrt4_protseq_ncalrpc_open_endpoint(RpcServerProtseq* protseq, LPSTR endpoint) +{ + static const char prefix[] = "\\\\.\\pipe\\lrpc\\"; + RPC_STATUS r; + LPSTR pname; + RpcConnection *Connection; + + r = RPCRT4_CreateConnection(&Connection, TRUE, protseq->Protseq, NULL, + endpoint, NULL, NULL, NULL); + if (r != RPC_S_OK) + return r; + + /* protseq=ncalrpc: supposed to use NT LPC ports, + * but we'll implement it with named pipes for now */ + pname = I_RpcAllocate(strlen(prefix) + strlen(Connection->Endpoint) + 1); + strcat(strcpy(pname, prefix), Connection->Endpoint); + r = rpcrt4_conn_create_pipe(Connection, pname); + I_RpcFree(pname); + + EnterCriticalSection(&protseq->cs); + Connection->Next = protseq->conn; + protseq->conn = Connection; + LeaveCriticalSection(&protseq->cs); + + return r; +} + +static RPC_STATUS rpcrt4_ncacn_np_open(RpcConnection* Connection) +{ + RpcConnection_np *npc = (RpcConnection_np *) Connection; + static const char prefix[] = "\\\\."; + RPC_STATUS r; + LPSTR pname; + + /* already connected? */ + if (npc->pipe) + return RPC_S_OK; + + /* protseq=ncacn_np: named pipes */ + pname = I_RpcAllocate(strlen(prefix) + strlen(Connection->Endpoint) + 1); + strcat(strcpy(pname, prefix), Connection->Endpoint); + r = rpcrt4_conn_open_pipe(Connection, pname, FALSE); + I_RpcFree(pname); + + return r; +} + +static RPC_STATUS rpcrt4_protseq_ncacn_np_open_endpoint(RpcServerProtseq *protseq, LPSTR endpoint) +{ + static const char prefix[] = "\\\\."; + RPC_STATUS r; + LPSTR pname; + RpcConnection *Connection; + + r = RPCRT4_CreateConnection(&Connection, TRUE, protseq->Protseq, NULL, + endpoint, NULL, NULL, NULL); + if (r != RPC_S_OK) + return r; + + /* protseq=ncacn_np: named pipes */ + pname = I_RpcAllocate(strlen(prefix) + strlen(Connection->Endpoint) + 1); + strcat(strcpy(pname, prefix), Connection->Endpoint); + r = rpcrt4_conn_create_pipe(Connection, pname); + I_RpcFree(pname); + + EnterCriticalSection(&protseq->cs); + Connection->Next = protseq->conn; + protseq->conn = Connection; + LeaveCriticalSection(&protseq->cs); + + return r; +} + +static void rpcrt4_conn_np_handoff(RpcConnection_np *old_npc, RpcConnection_np *new_npc) +{ + /* because of the way named pipes work, we'll transfer the connected pipe + * to the child, then reopen the server binding to continue listening */ + + new_npc->pipe = old_npc->pipe; + new_npc->ovl = old_npc->ovl; + old_npc->pipe = 0; + memset(&old_npc->ovl, 0, sizeof(old_npc->ovl)); + old_npc->listening = FALSE; +} + +static RPC_STATUS rpcrt4_ncacn_np_handoff(RpcConnection *old_conn, RpcConnection *new_conn) +{ + RPC_STATUS status; + LPSTR pname; + static const char prefix[] = "\\\\."; + + rpcrt4_conn_np_handoff((RpcConnection_np *)old_conn, (RpcConnection_np *)new_conn); + + pname = I_RpcAllocate(strlen(prefix) + strlen(old_conn->Endpoint) + 1); + strcat(strcpy(pname, prefix), old_conn->Endpoint); + status = rpcrt4_conn_create_pipe(old_conn, pname); + I_RpcFree(pname); + + return status; +} + +static RPC_STATUS rpcrt4_ncalrpc_handoff(RpcConnection *old_conn, RpcConnection *new_conn) +{ + RPC_STATUS status; + LPSTR pname; + static const char prefix[] = "\\\\.\\pipe\\lrpc\\"; + + TRACE("%s\n", old_conn->Endpoint); + + rpcrt4_conn_np_handoff((RpcConnection_np *)old_conn, (RpcConnection_np *)new_conn); + + pname = I_RpcAllocate(strlen(prefix) + strlen(old_conn->Endpoint) + 1); + strcat(strcpy(pname, prefix), old_conn->Endpoint); + status = rpcrt4_conn_create_pipe(old_conn, pname); + I_RpcFree(pname); + + return status; +} + +static int rpcrt4_conn_np_read(RpcConnection *Connection, + void *buffer, unsigned int count) +{ + RpcConnection_np *npc = (RpcConnection_np *) Connection; + char *buf = buffer; + BOOL ret = TRUE; + unsigned int bytes_left = count; + + while (bytes_left) + { + DWORD bytes_read; + ret = ReadFile(npc->pipe, buf, bytes_left, &bytes_read, NULL); + if (!ret || !bytes_read) + break; + bytes_left -= bytes_read; + buf += bytes_read; + } + return ret ? count : -1; +} + +static int rpcrt4_conn_np_write(RpcConnection *Connection, + const void *buffer, unsigned int count) +{ + RpcConnection_np *npc = (RpcConnection_np *) Connection; + const char *buf = buffer; + BOOL ret = TRUE; + unsigned int bytes_left = count; + + while (bytes_left) + { + DWORD bytes_written; + ret = WriteFile(npc->pipe, buf, count, &bytes_written, NULL); + if (!ret || !bytes_written) + break; + bytes_left -= bytes_written; + buf += bytes_written; + } + return ret ? count : -1; +} + +static int rpcrt4_conn_np_close(RpcConnection *Connection) +{ + RpcConnection_np *npc = (RpcConnection_np *) Connection; + if (npc->pipe) { + FlushFileBuffers(npc->pipe); + CloseHandle(npc->pipe); + npc->pipe = 0; + } + if (npc->ovl.hEvent) { + CloseHandle(npc->ovl.hEvent); + npc->ovl.hEvent = 0; + } + return 0; +} + +static void rpcrt4_conn_np_cancel_call(RpcConnection *Connection) +{ + /* FIXME: implement when named pipe writes use overlapped I/O */ +} + +static size_t rpcrt4_ncacn_np_get_top_of_tower(unsigned char *tower_data, + const char *networkaddr, + const char *endpoint) +{ + twr_empty_floor_t *smb_floor; + twr_empty_floor_t *nb_floor; + size_t size; + size_t networkaddr_size; + size_t endpoint_size; + + TRACE("(%p, %s, %s)\n", tower_data, networkaddr, endpoint); + + networkaddr_size = strlen(networkaddr) + 1; + endpoint_size = strlen(endpoint) + 1; + size = sizeof(*smb_floor) + endpoint_size + sizeof(*nb_floor) + networkaddr_size; + + if (!tower_data) + return size; + + smb_floor = (twr_empty_floor_t *)tower_data; + + tower_data += sizeof(*smb_floor); + + smb_floor->count_lhs = sizeof(smb_floor->protid); + smb_floor->protid = EPM_PROTOCOL_SMB; + smb_floor->count_rhs = endpoint_size; + + memcpy(tower_data, endpoint, endpoint_size); + tower_data += endpoint_size; + + nb_floor = (twr_empty_floor_t *)tower_data; + + tower_data += sizeof(*nb_floor); + + nb_floor->count_lhs = sizeof(nb_floor->protid); + nb_floor->protid = EPM_PROTOCOL_NETBIOS; + nb_floor->count_rhs = networkaddr_size; + + memcpy(tower_data, networkaddr, networkaddr_size); + tower_data += networkaddr_size; + + return size; +} + +static RPC_STATUS rpcrt4_ncacn_np_parse_top_of_tower(const unsigned char *tower_data, + size_t tower_size, + char **networkaddr, + char **endpoint) +{ + const twr_empty_floor_t *smb_floor = (const twr_empty_floor_t *)tower_data; + const twr_empty_floor_t *nb_floor; + + TRACE("(%p, %d, %p, %p)\n", tower_data, (int)tower_size, networkaddr, endpoint); + + if (tower_size < sizeof(*smb_floor)) + return EPT_S_NOT_REGISTERED; + + tower_data += sizeof(*smb_floor); + tower_size -= sizeof(*smb_floor); + + if ((smb_floor->count_lhs != sizeof(smb_floor->protid)) || + (smb_floor->protid != EPM_PROTOCOL_SMB) || + (smb_floor->count_rhs > tower_size)) + return EPT_S_NOT_REGISTERED; + + if (endpoint) + { + *endpoint = I_RpcAllocate(smb_floor->count_rhs); + if (!*endpoint) + return RPC_S_OUT_OF_RESOURCES; + memcpy(*endpoint, tower_data, smb_floor->count_rhs); + } + tower_data += smb_floor->count_rhs; + tower_size -= smb_floor->count_rhs; + + if (tower_size < sizeof(*nb_floor)) + return EPT_S_NOT_REGISTERED; + + nb_floor = (const twr_empty_floor_t *)tower_data; + + tower_data += sizeof(*nb_floor); + tower_size -= sizeof(*nb_floor); + + if ((nb_floor->count_lhs != sizeof(nb_floor->protid)) || + (nb_floor->protid != EPM_PROTOCOL_NETBIOS) || + (nb_floor->count_rhs > tower_size)) + return EPT_S_NOT_REGISTERED; + + if (networkaddr) + { + *networkaddr = I_RpcAllocate(nb_floor->count_rhs); + if (!*networkaddr) + { + if (endpoint) + { + I_RpcFree(*endpoint); + *endpoint = NULL; + } + return RPC_S_OUT_OF_RESOURCES; + } + memcpy(*networkaddr, tower_data, nb_floor->count_rhs); + } + + return RPC_S_OK; +} + +typedef struct _RpcServerProtseq_np +{ + RpcServerProtseq common; + HANDLE mgr_event; +} RpcServerProtseq_np; + +static RpcServerProtseq *rpcrt4_protseq_np_alloc(void) +{ + RpcServerProtseq_np *ps = HeapAlloc(GetProcessHeap(), 0, sizeof(*ps)); + if (ps) + ps->mgr_event = CreateEventW(NULL, FALSE, FALSE, NULL); + return &ps->common; +} + +static void rpcrt4_protseq_np_signal_state_changed(RpcServerProtseq *protseq) +{ + RpcServerProtseq_np *npps = CONTAINING_RECORD(protseq, RpcServerProtseq_np, common); + SetEvent(npps->mgr_event); +} + +static void *rpcrt4_protseq_np_get_wait_array(RpcServerProtseq *protseq, void *prev_array, unsigned int *count) +{ + HANDLE *objs = prev_array; + RpcConnection_np *conn; + RpcServerProtseq_np *npps = CONTAINING_RECORD(protseq, RpcServerProtseq_np, common); + + EnterCriticalSection(&protseq->cs); + + /* open and count connections */ + *count = 1; + conn = CONTAINING_RECORD(protseq->conn, RpcConnection_np, common); + while (conn) { + rpcrt4_conn_listen_pipe(conn); + if (conn->ovl.hEvent) + (*count)++; + conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_np, common); + } + + /* make array of connections */ + if (objs) + objs = HeapReAlloc(GetProcessHeap(), 0, objs, *count*sizeof(HANDLE)); + else + objs = HeapAlloc(GetProcessHeap(), 0, *count*sizeof(HANDLE)); + if (!objs) + { + ERR("couldn't allocate objs\n"); + LeaveCriticalSection(&protseq->cs); + return NULL; + } + + objs[0] = npps->mgr_event; + *count = 1; + conn = CONTAINING_RECORD(protseq->conn, RpcConnection_np, common); + while (conn) { + if ((objs[*count] = conn->ovl.hEvent)) + (*count)++; + conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_np, common); + } + LeaveCriticalSection(&protseq->cs); + return objs; +} + +static void rpcrt4_protseq_np_free_wait_array(RpcServerProtseq *protseq, void *array) +{ + HeapFree(GetProcessHeap(), 0, array); +} + +static int rpcrt4_protseq_np_wait_for_new_connection(RpcServerProtseq *protseq, unsigned int count, void *wait_array) +{ + HANDLE b_handle; + HANDLE *objs = wait_array; + DWORD res; + RpcConnection *cconn; + RpcConnection_np *conn; + + if (!objs) + return -1; + + do + { + /* an alertable wait isn't strictly necessary, but due to our + * overlapped I/O implementation in Wine we need to free some memory + * by the file user APC being called, even if no completion routine was + * specified at the time of starting the async operation */ + res = WaitForMultipleObjectsEx(count, objs, FALSE, INFINITE, TRUE); + } while (res == WAIT_IO_COMPLETION); + + if (res == WAIT_OBJECT_0) + return 0; + else if (res == WAIT_FAILED) + { + ERR("wait failed with error %d\n", GetLastError()); + return -1; + } + else + { + b_handle = objs[res - WAIT_OBJECT_0]; + /* find which connection got a RPC */ + EnterCriticalSection(&protseq->cs); + conn = CONTAINING_RECORD(protseq->conn, RpcConnection_np, common); + while (conn) { + if (b_handle == conn->ovl.hEvent) break; + conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_np, common); + } + cconn = NULL; + if (conn) + RPCRT4_SpawnConnection(&cconn, &conn->common); + else + ERR("failed to locate connection for handle %p\n", b_handle); + LeaveCriticalSection(&protseq->cs); + if (cconn) + { + RPCRT4_new_client(cconn); + return 1; + } + else return -1; + } +} + +static size_t rpcrt4_ncalrpc_get_top_of_tower(unsigned char *tower_data, + const char *networkaddr, + const char *endpoint) +{ + twr_empty_floor_t *pipe_floor; + size_t size; + size_t endpoint_size; + + TRACE("(%p, %s, %s)\n", tower_data, networkaddr, endpoint); + + endpoint_size = strlen(networkaddr) + 1; + size = sizeof(*pipe_floor) + endpoint_size; + + if (!tower_data) + return size; + + pipe_floor = (twr_empty_floor_t *)tower_data; + + tower_data += sizeof(*pipe_floor); + + pipe_floor->count_lhs = sizeof(pipe_floor->protid); + pipe_floor->protid = EPM_PROTOCOL_SMB; + pipe_floor->count_rhs = endpoint_size; + + memcpy(tower_data, endpoint, endpoint_size); + tower_data += endpoint_size; + + return size; +} + +static RPC_STATUS rpcrt4_ncalrpc_parse_top_of_tower(const unsigned char *tower_data, + size_t tower_size, + char **networkaddr, + char **endpoint) +{ + const twr_empty_floor_t *pipe_floor = (const twr_empty_floor_t *)tower_data; + + TRACE("(%p, %d, %p, %p)\n", tower_data, (int)tower_size, networkaddr, endpoint); + + *networkaddr = NULL; + *endpoint = NULL; + + if (tower_size < sizeof(*pipe_floor)) + return EPT_S_NOT_REGISTERED; + + tower_data += sizeof(*pipe_floor); + tower_size -= sizeof(*pipe_floor); + + if ((pipe_floor->count_lhs != sizeof(pipe_floor->protid)) || + (pipe_floor->protid != EPM_PROTOCOL_SMB) || + (pipe_floor->count_rhs > tower_size)) + return EPT_S_NOT_REGISTERED; + + if (endpoint) + { + *endpoint = I_RpcAllocate(pipe_floor->count_rhs); + if (!*endpoint) + return RPC_S_OUT_OF_RESOURCES; + memcpy(*endpoint, tower_data, pipe_floor->count_rhs); + } + + return RPC_S_OK; +} + +/**** ncacn_ip_tcp support ****/ + +typedef struct _RpcConnection_tcp +{ + RpcConnection common; + int sock; + int cancel_fds[2]; +} RpcConnection_tcp; + +static RpcConnection *rpcrt4_conn_tcp_alloc(void) +{ + RpcConnection_tcp *tcpc; + tcpc = HeapAlloc(GetProcessHeap(), 0, sizeof(RpcConnection_tcp)); + if (tcpc == NULL) + return NULL; + tcpc->sock = -1; +#ifndef __REACTOS__ + if (socketpair(PF_UNIX, SOCK_STREAM, 0, tcpc->cancel_fds) < 0) + { + ERR("socketpair() failed: %s\n", strerror(errno)); + HeapFree(GetProcessHeap(), 0, tcpc); + return NULL; + } +#endif + return &tcpc->common; +} + +static RPC_STATUS rpcrt4_ncacn_ip_tcp_open(RpcConnection* Connection) +{ + RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection; + int sock; + int ret; + struct addrinfo *ai; + struct addrinfo *ai_cur; + struct addrinfo hints; + + TRACE("(%s, %s)\n", Connection->NetworkAddr, Connection->Endpoint); + + if (tcpc->sock != -1) + return RPC_S_OK; + + hints.ai_flags = 0; + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + hints.ai_addrlen = 0; + hints.ai_addr = NULL; + hints.ai_canonname = NULL; + hints.ai_next = NULL; + + ret = getaddrinfo(Connection->NetworkAddr, Connection->Endpoint, &hints, &ai); + if (ret) + { + ERR("getaddrinfo for %s:%s failed: %s\n", Connection->NetworkAddr, + Connection->Endpoint, gai_strerror(ret)); + return RPC_S_SERVER_UNAVAILABLE; + } + + for (ai_cur = ai; ai_cur; ai_cur = ai_cur->ai_next) + { + int val; + + if (TRACE_ON(rpc)) + { + char host[256]; + char service[256]; + getnameinfo(ai_cur->ai_addr, ai_cur->ai_addrlen, + host, sizeof(host), service, sizeof(service), + NI_NUMERICHOST | NI_NUMERICSERV); + TRACE("trying %s:%s\n", host, service); + } + + sock = socket(ai_cur->ai_family, ai_cur->ai_socktype, ai_cur->ai_protocol); + if (sock == -1) + { + WARN("socket() failed: %s\n", strerror(errno)); + continue; + } + + if (0>connect(sock, ai_cur->ai_addr, ai_cur->ai_addrlen)) + { + WARN("connect() failed: %s\n", strerror(errno)); + close(sock); + continue; + } + + /* RPC depends on having minimal latency so disable the Nagle algorithm */ + val = 1; + setsockopt(sock, SOL_TCP, TCP_NODELAY, (char *)&val, sizeof(val)); + + tcpc->sock = sock; + + freeaddrinfo(ai); + TRACE("connected\n"); + return RPC_S_OK; + } + + freeaddrinfo(ai); + ERR("couldn't connect to %s:%s\n", Connection->NetworkAddr, Connection->Endpoint); + return RPC_S_SERVER_UNAVAILABLE; +} + +static RPC_STATUS rpcrt4_protseq_ncacn_ip_tcp_open_endpoint(RpcServerProtseq *protseq, LPSTR endpoint) +{ + RPC_STATUS status = RPC_S_CANT_CREATE_ENDPOINT; + int sock; + int ret; + struct addrinfo *ai; + struct addrinfo *ai_cur; + struct addrinfo hints; + u_long blocking; + RpcConnection *first_connection = NULL; + + TRACE("(%p, %s)\n", protseq, endpoint); + + hints.ai_flags = AI_PASSIVE /* for non-localhost addresses */; + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + hints.ai_addrlen = 0; + hints.ai_addr = NULL; + hints.ai_canonname = NULL; + hints.ai_next = NULL; + + ret = getaddrinfo(NULL, endpoint, &hints, &ai); + if (ret) + { + ERR("getaddrinfo for port %s failed: %s\n", endpoint, + gai_strerror(ret)); + if ((ret == EAI_SERVICE) || (ret == EAI_NONAME)) + return RPC_S_INVALID_ENDPOINT_FORMAT; + return RPC_S_CANT_CREATE_ENDPOINT; + } + + for (ai_cur = ai; ai_cur; ai_cur = ai_cur->ai_next) + { + RpcConnection_tcp *tcpc; + RPC_STATUS create_status; + + if (TRACE_ON(rpc)) + { + char host[256]; + char service[256]; + getnameinfo(ai_cur->ai_addr, ai_cur->ai_addrlen, + host, sizeof(host), service, sizeof(service), + NI_NUMERICHOST | NI_NUMERICSERV); + TRACE("trying %s:%s\n", host, service); + } + + sock = socket(ai_cur->ai_family, ai_cur->ai_socktype, ai_cur->ai_protocol); + if (sock == -1) + { + WARN("socket() failed: %s\n", strerror(errno)); + status = RPC_S_CANT_CREATE_ENDPOINT; + continue; + } + + ret = bind(sock, ai_cur->ai_addr, ai_cur->ai_addrlen); + if (ret < 0) + { + WARN("bind failed: %s\n", strerror(errno)); + close(sock); + if (errno == WSAEADDRINUSE) + status = RPC_S_DUPLICATE_ENDPOINT; + else + status = RPC_S_CANT_CREATE_ENDPOINT; + continue; + } + create_status = RPCRT4_CreateConnection((RpcConnection **)&tcpc, TRUE, + protseq->Protseq, NULL, + endpoint, NULL, NULL, NULL); + if (create_status != RPC_S_OK) + { + close(sock); + status = create_status; + continue; + } + + tcpc->sock = sock; + ret = listen(sock, protseq->MaxCalls); + if (ret < 0) + { + WARN("listen failed: %s\n", strerror(errno)); + RPCRT4_DestroyConnection(&tcpc->common); + status = RPC_S_OUT_OF_RESOURCES; + continue; + } + /* need a non-blocking socket, otherwise accept() has a potential + * race-condition (poll() says it is readable, connection drops, + * and accept() blocks until the next connection comes...) + */ + blocking = 1; + ret = ioctlsocket(sock, FIONBIO, &blocking); + if (ret < 0) + { + WARN("couldn't make socket non-blocking, error %d\n", ret); + RPCRT4_DestroyConnection(&tcpc->common); + status = RPC_S_OUT_OF_RESOURCES; + continue; + } + + tcpc->common.Next = first_connection; + first_connection = &tcpc->common; + } + + freeaddrinfo(ai); + + /* if at least one connection was created for an endpoint then + * return success */ + if (first_connection) + { + RpcConnection *conn; + + /* find last element in list */ + for (conn = first_connection; conn->Next; conn = conn->Next) + ; + + EnterCriticalSection(&protseq->cs); + conn->Next = protseq->conn; + protseq->conn = first_connection; + LeaveCriticalSection(&protseq->cs); + + TRACE("listening on %s\n", endpoint); + return RPC_S_OK; + } + + ERR("couldn't listen on port %s\n", endpoint); + return status; +} + +static RPC_STATUS rpcrt4_conn_tcp_handoff(RpcConnection *old_conn, RpcConnection *new_conn) +{ + int ret; + struct sockaddr_in address; + socklen_t addrsize; + u_long blocking; + RpcConnection_tcp *server = (RpcConnection_tcp*) old_conn; + RpcConnection_tcp *client = (RpcConnection_tcp*) new_conn; + + addrsize = sizeof(address); + ret = accept(server->sock, (struct sockaddr*) &address, &addrsize); + if (ret < 0) + { + ERR("Failed to accept a TCP connection: error %d\n", ret); + return RPC_S_OUT_OF_RESOURCES; + } + /* reset to blocking behaviour */ blocking = 0; ret = ioctlsocket(ret, FIONBIO, &blocking); - client->sock = ret; - TRACE("Accepted a new TCP connection\n"); - return RPC_S_OK; -} - -static int rpcrt4_conn_tcp_read(RpcConnection *Connection, - void *buffer, unsigned int count) -{ - RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection; - int r = recv(tcpc->sock, buffer, count, MSG_WAITALL); - TRACE("%d %p %u -> %d\n", tcpc->sock, buffer, count, r); - return r; -} - -static int rpcrt4_conn_tcp_write(RpcConnection *Connection, - const void *buffer, unsigned int count) -{ - RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection; - int r = write(tcpc->sock, buffer, count); - TRACE("%d %p %u -> %d\n", tcpc->sock, buffer, count, r); - return r; -} - -static int rpcrt4_conn_tcp_close(RpcConnection *Connection) -{ - RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection; - - TRACE("%d\n", tcpc->sock); - - if (tcpc->sock != -1) - close(tcpc->sock); - tcpc->sock = -1; - return 0; -} - -static size_t rpcrt4_ncacn_ip_tcp_get_top_of_tower(unsigned char *tower_data, - const char *networkaddr, - const char *endpoint) -{ - twr_tcp_floor_t *tcp_floor; - twr_ipv4_floor_t *ipv4_floor; - struct addrinfo *ai; - struct addrinfo hints; - int ret; - size_t size = sizeof(*tcp_floor) + sizeof(*ipv4_floor); - - TRACE("(%p, %s, %s)\n", tower_data, networkaddr, endpoint); - - if (!tower_data) - return size; - - tcp_floor = (twr_tcp_floor_t *)tower_data; - tower_data += sizeof(*tcp_floor); - - ipv4_floor = (twr_ipv4_floor_t *)tower_data; - - tcp_floor->count_lhs = sizeof(tcp_floor->protid); - tcp_floor->protid = EPM_PROTOCOL_TCP; - tcp_floor->count_rhs = sizeof(tcp_floor->port); - - ipv4_floor->count_lhs = sizeof(ipv4_floor->protid); - ipv4_floor->protid = EPM_PROTOCOL_IP; - ipv4_floor->count_rhs = sizeof(ipv4_floor->ipv4addr); - - hints.ai_flags = AI_NUMERICHOST; - /* FIXME: only support IPv4 at the moment. how is IPv6 represented by the EPM? */ - hints.ai_family = PF_INET; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; - hints.ai_addrlen = 0; - hints.ai_addr = NULL; - hints.ai_canonname = NULL; - hints.ai_next = NULL; - - ret = getaddrinfo(networkaddr, endpoint, &hints, &ai); - if (ret) - { - ret = getaddrinfo("0.0.0.0", endpoint, &hints, &ai); - if (ret) - { - ERR("getaddrinfo failed: %s\n", gai_strerror(ret)); - return 0; - } - } - - if (ai->ai_family == PF_INET) - { - const struct sockaddr_in *sin = (const struct sockaddr_in *)ai->ai_addr; - tcp_floor->port = sin->sin_port; - ipv4_floor->ipv4addr = sin->sin_addr.s_addr; - } - else - { - ERR("unexpected protocol family %d\n", ai->ai_family); - return 0; - } - - freeaddrinfo(ai); - - return size; -} - -static RPC_STATUS rpcrt4_ncacn_ip_tcp_parse_top_of_tower(const unsigned char *tower_data, - size_t tower_size, - char **networkaddr, - char **endpoint) -{ - const twr_tcp_floor_t *tcp_floor = (const twr_tcp_floor_t *)tower_data; - const twr_ipv4_floor_t *ipv4_floor; - struct in_addr in_addr; - - TRACE("(%p, %d, %p, %p)\n", tower_data, (int)tower_size, networkaddr, endpoint); - - if (tower_size < sizeof(*tcp_floor)) - return EPT_S_NOT_REGISTERED; - - tower_data += sizeof(*tcp_floor); - tower_size -= sizeof(*tcp_floor); - - if (tower_size < sizeof(*ipv4_floor)) - return EPT_S_NOT_REGISTERED; - - ipv4_floor = (const twr_ipv4_floor_t *)tower_data; - - if ((tcp_floor->count_lhs != sizeof(tcp_floor->protid)) || - (tcp_floor->protid != EPM_PROTOCOL_TCP) || - (tcp_floor->count_rhs != sizeof(tcp_floor->port)) || - (ipv4_floor->count_lhs != sizeof(ipv4_floor->protid)) || - (ipv4_floor->protid != EPM_PROTOCOL_IP) || - (ipv4_floor->count_rhs != sizeof(ipv4_floor->ipv4addr))) - return EPT_S_NOT_REGISTERED; - - if (endpoint) - { - *endpoint = I_RpcAllocate(6 /* sizeof("65535") + 1 */); - if (!*endpoint) - return RPC_S_OUT_OF_RESOURCES; - sprintf(*endpoint, "%u", ntohs(tcp_floor->port)); - } - - if (networkaddr) - { - *networkaddr = I_RpcAllocate(INET_ADDRSTRLEN); - if (!*networkaddr) - { - if (endpoint) - { - I_RpcFree(*endpoint); - *endpoint = NULL; - } - return RPC_S_OUT_OF_RESOURCES; - } - in_addr.s_addr = ipv4_floor->ipv4addr; - if (!inet_ntop(AF_INET, &in_addr, *networkaddr, INET_ADDRSTRLEN)) - { - ERR("inet_ntop: %s\n", strerror(errno)); - I_RpcFree(*networkaddr); - *networkaddr = NULL; - if (endpoint) - { - I_RpcFree(*endpoint); - *endpoint = NULL; - } - return EPT_S_NOT_REGISTERED; - } - } - - return RPC_S_OK; -} - -typedef struct _RpcServerProtseq_sock -{ - RpcServerProtseq common; - int mgr_event_rcv; - int mgr_event_snd; -} RpcServerProtseq_sock; - -static RpcServerProtseq *rpcrt4_protseq_sock_alloc(void) -{ - RpcServerProtseq_sock *ps = HeapAlloc(GetProcessHeap(), 0, sizeof(*ps)); - if (ps) - { - int fds[2]; - u_long blocking; - if (!socketpair(PF_UNIX, SOCK_DGRAM, 0, fds)) - { - blocking = 1; + client->sock = ret; + TRACE("Accepted a new TCP connection\n"); + return RPC_S_OK; +} + +static int rpcrt4_conn_tcp_read(RpcConnection *Connection, + void *buffer, unsigned int count) +{ + RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection; + int bytes_read = 0; + do + { + int r = recv(tcpc->sock, (char *)buffer + bytes_read, count - bytes_read, 0); + if (!r) + return -1; + else if (r > 0) + bytes_read += r; + else if (errno != EAGAIN) + { + WARN("recv() failed: %s\n", strerror(errno)); + return -1; + } + else + { + struct pollfd pfds[2]; + pfds[0].fd = tcpc->sock; + pfds[0].events = POLLIN; + pfds[1].fd = tcpc->cancel_fds[0]; + pfds[1].events = POLLIN; + if (poll(pfds, 2, -1 /* infinite */) == -1 && errno != EINTR) + { + ERR("poll() failed: %s\n", strerror(errno)); + return -1; + } + if (pfds[1].revents & POLLIN) /* canceled */ + { + char dummy; + read(pfds[1].fd, &dummy, sizeof(dummy)); + return -1; + } + } + } while (bytes_read != count); + TRACE("%d %p %u -> %d\n", tcpc->sock, buffer, count, bytes_read); + return bytes_read; +} + +static int rpcrt4_conn_tcp_write(RpcConnection *Connection, + const void *buffer, unsigned int count) +{ + RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection; + int bytes_written = 0; + do + { + int r = write(tcpc->sock, (const char *)buffer + bytes_written, count - bytes_written); + if (r >= 0) + bytes_written += r; + else if (errno != EAGAIN) + return -1; + else + { + struct pollfd pfd; + pfd.fd = tcpc->sock; + pfd.events = POLLOUT; + if (poll(&pfd, 1, -1 /* infinite */) == -1 && errno != EINTR) + { + ERR("poll() failed: %s\n", strerror(errno)); + return -1; + } + } + } while (bytes_written != count); + TRACE("%d %p %u -> %d\n", tcpc->sock, buffer, count, bytes_written); + return bytes_written; +} + +static int rpcrt4_conn_tcp_close(RpcConnection *Connection) +{ + RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection; + + TRACE("%d\n", tcpc->sock); + + if (tcpc->sock != -1) + close(tcpc->sock); + tcpc->sock = -1; + close(tcpc->cancel_fds[0]); + close(tcpc->cancel_fds[1]); + return 0; +} + +static void rpcrt4_conn_tcp_cancel_call(RpcConnection *Connection) +{ + RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection; + char dummy = 1; + + TRACE("%p\n", Connection); + + write(tcpc->cancel_fds[1], &dummy, 1); +} + +static size_t rpcrt4_ncacn_ip_tcp_get_top_of_tower(unsigned char *tower_data, + const char *networkaddr, + const char *endpoint) +{ + twr_tcp_floor_t *tcp_floor; + twr_ipv4_floor_t *ipv4_floor; + struct addrinfo *ai; + struct addrinfo hints; + int ret; + size_t size = sizeof(*tcp_floor) + sizeof(*ipv4_floor); + + TRACE("(%p, %s, %s)\n", tower_data, networkaddr, endpoint); + + if (!tower_data) + return size; + + tcp_floor = (twr_tcp_floor_t *)tower_data; + tower_data += sizeof(*tcp_floor); + + ipv4_floor = (twr_ipv4_floor_t *)tower_data; + + tcp_floor->count_lhs = sizeof(tcp_floor->protid); + tcp_floor->protid = EPM_PROTOCOL_TCP; + tcp_floor->count_rhs = sizeof(tcp_floor->port); + + ipv4_floor->count_lhs = sizeof(ipv4_floor->protid); + ipv4_floor->protid = EPM_PROTOCOL_IP; + ipv4_floor->count_rhs = sizeof(ipv4_floor->ipv4addr); + + hints.ai_flags = AI_NUMERICHOST; + /* FIXME: only support IPv4 at the moment. how is IPv6 represented by the EPM? */ + hints.ai_family = PF_INET; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + hints.ai_addrlen = 0; + hints.ai_addr = NULL; + hints.ai_canonname = NULL; + hints.ai_next = NULL; + + ret = getaddrinfo(networkaddr, endpoint, &hints, &ai); + if (ret) + { + ret = getaddrinfo("0.0.0.0", endpoint, &hints, &ai); + if (ret) + { + ERR("getaddrinfo failed: %s\n", gai_strerror(ret)); + return 0; + } + } + + if (ai->ai_family == PF_INET) + { + const struct sockaddr_in *sin = (const struct sockaddr_in *)ai->ai_addr; + tcp_floor->port = sin->sin_port; + ipv4_floor->ipv4addr = sin->sin_addr.s_addr; + } + else + { + ERR("unexpected protocol family %d\n", ai->ai_family); + return 0; + } + + freeaddrinfo(ai); + + return size; +} + +static RPC_STATUS rpcrt4_ncacn_ip_tcp_parse_top_of_tower(const unsigned char *tower_data, + size_t tower_size, + char **networkaddr, + char **endpoint) +{ + const twr_tcp_floor_t *tcp_floor = (const twr_tcp_floor_t *)tower_data; + const twr_ipv4_floor_t *ipv4_floor; + struct in_addr in_addr; + + TRACE("(%p, %d, %p, %p)\n", tower_data, (int)tower_size, networkaddr, endpoint); + + if (tower_size < sizeof(*tcp_floor)) + return EPT_S_NOT_REGISTERED; + + tower_data += sizeof(*tcp_floor); + tower_size -= sizeof(*tcp_floor); + + if (tower_size < sizeof(*ipv4_floor)) + return EPT_S_NOT_REGISTERED; + + ipv4_floor = (const twr_ipv4_floor_t *)tower_data; + + if ((tcp_floor->count_lhs != sizeof(tcp_floor->protid)) || + (tcp_floor->protid != EPM_PROTOCOL_TCP) || + (tcp_floor->count_rhs != sizeof(tcp_floor->port)) || + (ipv4_floor->count_lhs != sizeof(ipv4_floor->protid)) || + (ipv4_floor->protid != EPM_PROTOCOL_IP) || + (ipv4_floor->count_rhs != sizeof(ipv4_floor->ipv4addr))) + return EPT_S_NOT_REGISTERED; + + if (endpoint) + { + *endpoint = I_RpcAllocate(6 /* sizeof("65535") + 1 */); + if (!*endpoint) + return RPC_S_OUT_OF_RESOURCES; + sprintf(*endpoint, "%u", ntohs(tcp_floor->port)); + } + + if (networkaddr) + { + *networkaddr = I_RpcAllocate(INET_ADDRSTRLEN); + if (!*networkaddr) + { + if (endpoint) + { + I_RpcFree(*endpoint); + *endpoint = NULL; + } + return RPC_S_OUT_OF_RESOURCES; + } + in_addr.s_addr = ipv4_floor->ipv4addr; + if (!inet_ntop(AF_INET, &in_addr, *networkaddr, INET_ADDRSTRLEN)) + { + ERR("inet_ntop: %s\n", strerror(errno)); + I_RpcFree(*networkaddr); + *networkaddr = NULL; + if (endpoint) + { + I_RpcFree(*endpoint); + *endpoint = NULL; + } + return EPT_S_NOT_REGISTERED; + } + } + + return RPC_S_OK; +} + +typedef struct _RpcServerProtseq_sock +{ + RpcServerProtseq common; + int mgr_event_rcv; + int mgr_event_snd; +} RpcServerProtseq_sock; + +static RpcServerProtseq *rpcrt4_protseq_sock_alloc(void) +{ + RpcServerProtseq_sock *ps = HeapAlloc(GetProcessHeap(), 0, sizeof(*ps)); + if (ps) + { + int fds[2]; + u_long blocking; + if (!socketpair(PF_UNIX, SOCK_DGRAM, 0, fds)) + { + blocking = 1; ioctlsocket(fds[0], FIONBIO, &blocking); ioctlsocket(fds[1], FIONBIO, &blocking); - ps->mgr_event_rcv = fds[0]; - ps->mgr_event_snd = fds[1]; - } - else - { - ERR("socketpair failed with error %s\n", strerror(errno)); - HeapFree(GetProcessHeap(), 0, ps); - return NULL; - } - } - return &ps->common; -} - -static void rpcrt4_protseq_sock_signal_state_changed(RpcServerProtseq *protseq) -{ - RpcServerProtseq_sock *sockps = CONTAINING_RECORD(protseq, RpcServerProtseq_sock, common); - char dummy = 1; - write(sockps->mgr_event_snd, &dummy, sizeof(dummy)); -} - -static void *rpcrt4_protseq_sock_get_wait_array(RpcServerProtseq *protseq, void *prev_array, unsigned int *count) -{ - struct pollfd *poll_info = prev_array; - RpcConnection_tcp *conn; - RpcServerProtseq_sock *sockps = CONTAINING_RECORD(protseq, RpcServerProtseq_sock, common); - - EnterCriticalSection(&protseq->cs); - - /* open and count connections */ - *count = 1; - conn = (RpcConnection_tcp *)protseq->conn; - while (conn) { - if (conn->sock != -1) - (*count)++; - conn = (RpcConnection_tcp *)conn->common.Next; - } - - /* make array of connections */ - if (poll_info) - poll_info = HeapReAlloc(GetProcessHeap(), 0, poll_info, *count*sizeof(*poll_info)); - else - poll_info = HeapAlloc(GetProcessHeap(), 0, *count*sizeof(*poll_info)); - if (!poll_info) - { - ERR("couldn't allocate poll_info\n"); - LeaveCriticalSection(&protseq->cs); - return NULL; - } - - poll_info[0].fd = sockps->mgr_event_rcv; - poll_info[0].events = POLLIN; - *count = 1; - conn = CONTAINING_RECORD(protseq->conn, RpcConnection_tcp, common); - while (conn) { - if (conn->sock != -1) - { - poll_info[*count].fd = conn->sock; - poll_info[*count].events = POLLIN; - (*count)++; - } - conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_tcp, common); - } - LeaveCriticalSection(&protseq->cs); - return poll_info; -} - -static void rpcrt4_protseq_sock_free_wait_array(RpcServerProtseq *protseq, void *array) -{ - HeapFree(GetProcessHeap(), 0, array); -} - -static int rpcrt4_protseq_sock_wait_for_new_connection(RpcServerProtseq *protseq, unsigned int count, void *wait_array) -{ - struct pollfd *poll_info = wait_array; - int ret, i; - RpcConnection *cconn; - RpcConnection_tcp *conn; - - if (!poll_info) - return -1; - - ret = poll(poll_info, count, -1); - if (ret < 0) - { - ERR("poll failed with error %d\n", ret); - return -1; - } - - for (i = 0; i < count; i++) - if (poll_info[i].revents & POLLIN) - { - /* RPC server event */ - if (i == 0) - { - char dummy; - read(poll_info[0].fd, &dummy, sizeof(dummy)); - return 0; - } - - /* find which connection got a RPC */ - EnterCriticalSection(&protseq->cs); - conn = CONTAINING_RECORD(protseq->conn, RpcConnection_tcp, common); - while (conn) { - if (poll_info[i].fd == conn->sock) break; - conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_tcp, common); - } - cconn = NULL; - if (conn) - RPCRT4_SpawnConnection(&cconn, &conn->common); - else - ERR("failed to locate connection for fd %d\n", poll_info[i].fd); - LeaveCriticalSection(&protseq->cs); - if (cconn) - RPCRT4_new_client(cconn); - else - return -1; - } - - return 1; -} - -static const struct connection_ops conn_protseq_list[] = { - { "ncacn_np", - { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_SMB }, - rpcrt4_conn_np_alloc, - rpcrt4_ncacn_np_open, - rpcrt4_ncacn_np_handoff, - rpcrt4_conn_np_read, - rpcrt4_conn_np_write, - rpcrt4_conn_np_close, - rpcrt4_ncacn_np_get_top_of_tower, - rpcrt4_ncacn_np_parse_top_of_tower, - }, - { "ncalrpc", - { EPM_PROTOCOL_NCALRPC, EPM_PROTOCOL_PIPE }, - rpcrt4_conn_np_alloc, - rpcrt4_ncalrpc_open, - rpcrt4_ncalrpc_handoff, - rpcrt4_conn_np_read, - rpcrt4_conn_np_write, - rpcrt4_conn_np_close, - rpcrt4_ncalrpc_get_top_of_tower, - rpcrt4_ncalrpc_parse_top_of_tower, - }, - { "ncacn_ip_tcp", - { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_TCP }, - rpcrt4_conn_tcp_alloc, - rpcrt4_ncacn_ip_tcp_open, - rpcrt4_conn_tcp_handoff, - rpcrt4_conn_tcp_read, - rpcrt4_conn_tcp_write, - rpcrt4_conn_tcp_close, - rpcrt4_ncacn_ip_tcp_get_top_of_tower, - rpcrt4_ncacn_ip_tcp_parse_top_of_tower, - } -}; - - -static const struct protseq_ops protseq_list[] = -{ - { - "ncacn_np", - rpcrt4_protseq_np_alloc, - rpcrt4_protseq_np_signal_state_changed, - rpcrt4_protseq_np_get_wait_array, - rpcrt4_protseq_np_free_wait_array, - rpcrt4_protseq_np_wait_for_new_connection, - rpcrt4_protseq_ncacn_np_open_endpoint, - }, - { - "ncalrpc", - rpcrt4_protseq_np_alloc, - rpcrt4_protseq_np_signal_state_changed, - rpcrt4_protseq_np_get_wait_array, - rpcrt4_protseq_np_free_wait_array, - rpcrt4_protseq_np_wait_for_new_connection, - rpcrt4_protseq_ncalrpc_open_endpoint, - }, - { - "ncacn_ip_tcp", - rpcrt4_protseq_sock_alloc, - rpcrt4_protseq_sock_signal_state_changed, - rpcrt4_protseq_sock_get_wait_array, - rpcrt4_protseq_sock_free_wait_array, - rpcrt4_protseq_sock_wait_for_new_connection, - rpcrt4_protseq_ncacn_ip_tcp_open_endpoint, - }, -}; - -#define ARRAYSIZE(a) (sizeof((a)) / sizeof((a)[0])) - -const struct protseq_ops *rpcrt4_get_protseq_ops(const char *protseq) -{ - int i; - for(i=0; iserver); - return Connection->ops->open_connection_client(Connection); -} - -RPC_STATUS RPCRT4_CloseConnection(RpcConnection* Connection) -{ - TRACE("(Connection == ^%p)\n", Connection); - if (SecIsValidHandle(&Connection->ctx)) - { - DeleteSecurityContext(&Connection->ctx); - SecInvalidateHandle(&Connection->ctx); - } - rpcrt4_conn_close(Connection); - return RPC_S_OK; -} - -RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server, - LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint, - LPCWSTR NetworkOptions, RpcAuthInfo* AuthInfo, RpcQualityOfService *QOS) -{ - const struct connection_ops *ops; - RpcConnection* NewConnection; - - ops = rpcrt4_get_conn_protseq_ops(Protseq); - if (!ops) - { - FIXME("not supported for protseq %s\n", Protseq); - return RPC_S_PROTSEQ_NOT_SUPPORTED; - } - - NewConnection = ops->alloc(); - NewConnection->Next = NULL; - NewConnection->server = server; - NewConnection->ops = ops; - NewConnection->NetworkAddr = RPCRT4_strdupA(NetworkAddr); - NewConnection->Endpoint = RPCRT4_strdupA(Endpoint); - NewConnection->NetworkOptions = RPCRT4_strdupW(NetworkOptions); - NewConnection->MaxTransmissionSize = RPC_MAX_PACKET_SIZE; - memset(&NewConnection->ActiveInterface, 0, sizeof(NewConnection->ActiveInterface)); - NewConnection->NextCallId = 1; - - SecInvalidateHandle(&NewConnection->ctx); - memset(&NewConnection->exp, 0, sizeof(NewConnection->exp)); - NewConnection->attr = 0; - if (AuthInfo) RpcAuthInfo_AddRef(AuthInfo); - NewConnection->AuthInfo = AuthInfo; - NewConnection->encryption_auth_len = 0; - NewConnection->signature_auth_len = 0; - if (QOS) RpcQualityOfService_AddRef(QOS); - NewConnection->QOS = QOS; - - list_init(&NewConnection->conn_pool_entry); - - TRACE("connection: %p\n", NewConnection); - *Connection = NewConnection; - - return RPC_S_OK; -} - -RPC_STATUS RPCRT4_GetAssociation(LPCSTR Protseq, LPCSTR NetworkAddr, - LPCSTR Endpoint, LPCWSTR NetworkOptions, - RpcAssoc **assoc_out) -{ - RpcAssoc *assoc; - - EnterCriticalSection(&assoc_list_cs); - LIST_FOR_EACH_ENTRY(assoc, &assoc_list, RpcAssoc, entry) - { - if (!strcmp(Protseq, assoc->Protseq) && - !strcmp(NetworkAddr, assoc->NetworkAddr) && - !strcmp(Endpoint, assoc->Endpoint) && - ((!assoc->NetworkOptions && !NetworkOptions) || !strcmpW(NetworkOptions, assoc->NetworkOptions))) - { - assoc->refs++; - *assoc_out = assoc; - LeaveCriticalSection(&assoc_list_cs); - TRACE("using existing assoc %p\n", assoc); - return RPC_S_OK; - } - } - - assoc = HeapAlloc(GetProcessHeap(), 0, sizeof(*assoc)); - if (!assoc) - { - LeaveCriticalSection(&assoc_list_cs); - return RPC_S_OUT_OF_RESOURCES; - } - assoc->refs = 1; - list_init(&assoc->connection_pool); - InitializeCriticalSection(&assoc->cs); - assoc->Protseq = RPCRT4_strdupA(Protseq); - assoc->NetworkAddr = RPCRT4_strdupA(NetworkAddr); - assoc->Endpoint = RPCRT4_strdupA(Endpoint); - assoc->NetworkOptions = NetworkOptions ? RPCRT4_strdupW(NetworkOptions) : NULL; - assoc->assoc_group_id = 0; - list_add_head(&assoc_list, &assoc->entry); - *assoc_out = assoc; - - LeaveCriticalSection(&assoc_list_cs); - - TRACE("new assoc %p\n", assoc); - - return RPC_S_OK; -} - -ULONG RpcAssoc_Release(RpcAssoc *assoc) -{ - ULONG refs; - - EnterCriticalSection(&assoc_list_cs); - refs = --assoc->refs; - if (!refs) - list_remove(&assoc->entry); - LeaveCriticalSection(&assoc_list_cs); - - if (!refs) - { - RpcConnection *Connection, *cursor2; - - TRACE("destroying assoc %p\n", assoc); - - LIST_FOR_EACH_ENTRY_SAFE(Connection, cursor2, &assoc->connection_pool, RpcConnection, conn_pool_entry) - { - list_remove(&Connection->conn_pool_entry); - RPCRT4_DestroyConnection(Connection); - } - - HeapFree(GetProcessHeap(), 0, assoc->NetworkOptions); - HeapFree(GetProcessHeap(), 0, assoc->Endpoint); - HeapFree(GetProcessHeap(), 0, assoc->NetworkAddr); - HeapFree(GetProcessHeap(), 0, assoc->Protseq); - - HeapFree(GetProcessHeap(), 0, assoc); - } - - return refs; -} - -#define ROUND_UP(value, alignment) (((value) + ((alignment) - 1)) & ~((alignment)-1)) - -static RPC_STATUS RpcAssoc_BindConnection(const RpcAssoc *assoc, RpcConnection *conn, - const RPC_SYNTAX_IDENTIFIER *InterfaceId, - const RPC_SYNTAX_IDENTIFIER *TransferSyntax) -{ - RpcPktHdr *hdr; - RpcPktHdr *response_hdr; - RPC_MESSAGE msg; - RPC_STATUS status; - - TRACE("sending bind request to server\n"); - - hdr = RPCRT4_BuildBindHeader(NDR_LOCAL_DATA_REPRESENTATION, - RPC_MAX_PACKET_SIZE, RPC_MAX_PACKET_SIZE, - assoc->assoc_group_id, - InterfaceId, TransferSyntax); - - status = RPCRT4_Send(conn, hdr, NULL, 0); - RPCRT4_FreeHeader(hdr); - if (status != RPC_S_OK) - return status; - - status = RPCRT4_Receive(conn, &response_hdr, &msg); - if (status != RPC_S_OK) - { - ERR("receive failed\n"); - return status; - } - - switch (response_hdr->common.ptype) - { - case PKT_BIND_ACK: - { - RpcAddressString *server_address = msg.Buffer; - if ((msg.BufferLength >= FIELD_OFFSET(RpcAddressString, string[0])) || - (msg.BufferLength >= ROUND_UP(FIELD_OFFSET(RpcAddressString, string[server_address->length]), 4))) - { - unsigned short remaining = msg.BufferLength - - ROUND_UP(FIELD_OFFSET(RpcAddressString, string[server_address->length]), 4); - RpcResults *results = (RpcResults*)((ULONG_PTR)server_address + - ROUND_UP(FIELD_OFFSET(RpcAddressString, string[server_address->length]), 4)); - if ((results->num_results == 1) && (remaining >= sizeof(*results))) - { - switch (results->results[0].result) - { - case RESULT_ACCEPT: - conn->assoc_group_id = response_hdr->bind_ack.assoc_gid; - conn->MaxTransmissionSize = response_hdr->bind_ack.max_tsize; - conn->ActiveInterface = *InterfaceId; - break; - case RESULT_PROVIDER_REJECTION: - switch (results->results[0].reason) - { - case REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED: - ERR("syntax %s, %d.%d not supported\n", - debugstr_guid(&InterfaceId->SyntaxGUID), - InterfaceId->SyntaxVersion.MajorVersion, - InterfaceId->SyntaxVersion.MinorVersion); - status = RPC_S_UNKNOWN_IF; - break; - case REASON_TRANSFER_SYNTAXES_NOT_SUPPORTED: - ERR("transfer syntax not supported\n"); - status = RPC_S_SERVER_UNAVAILABLE; - break; - case REASON_NONE: - default: - status = RPC_S_CALL_FAILED_DNE; - } - break; - case RESULT_USER_REJECTION: - default: - ERR("rejection result %d\n", results->results[0].result); - status = RPC_S_CALL_FAILED_DNE; - } - } - else - { - ERR("incorrect results size\n"); - status = RPC_S_CALL_FAILED_DNE; - } - } - else - { - ERR("bind ack packet too small (%d)\n", msg.BufferLength); - status = RPC_S_PROTOCOL_ERROR; - } - break; - } - case PKT_BIND_NACK: - switch (response_hdr->bind_nack.reject_reason) - { - case REJECT_LOCAL_LIMIT_EXCEEDED: - case REJECT_TEMPORARY_CONGESTION: - ERR("server too busy\n"); - status = RPC_S_SERVER_TOO_BUSY; - break; - case REJECT_PROTOCOL_VERSION_NOT_SUPPORTED: - ERR("protocol version not supported\n"); - status = RPC_S_PROTOCOL_ERROR; - break; - case REJECT_UNKNOWN_AUTHN_SERVICE: - ERR("unknown authentication service\n"); - status = RPC_S_UNKNOWN_AUTHN_SERVICE; - break; - case REJECT_INVALID_CHECKSUM: - ERR("invalid checksum\n"); - status = ERROR_ACCESS_DENIED; - break; - default: - ERR("rejected bind for reason %d\n", response_hdr->bind_nack.reject_reason); - status = RPC_S_CALL_FAILED_DNE; - } - break; - default: - ERR("wrong packet type received %d\n", response_hdr->common.ptype); - status = RPC_S_PROTOCOL_ERROR; - break; - } - - RPCRT4_FreeHeader(response_hdr); - return status; -} - -static RpcConnection *RpcAssoc_GetIdleConnection(RpcAssoc *assoc, - const RPC_SYNTAX_IDENTIFIER *InterfaceId, - const RPC_SYNTAX_IDENTIFIER *TransferSyntax, const RpcAuthInfo *AuthInfo, - const RpcQualityOfService *QOS) -{ - RpcConnection *Connection; - EnterCriticalSection(&assoc->cs); - /* try to find a compatible connection from the connection pool */ - LIST_FOR_EACH_ENTRY(Connection, &assoc->connection_pool, RpcConnection, conn_pool_entry) - { - if (!memcmp(&Connection->ActiveInterface, InterfaceId, - sizeof(RPC_SYNTAX_IDENTIFIER)) && - RpcAuthInfo_IsEqual(Connection->AuthInfo, AuthInfo) && - RpcQualityOfService_IsEqual(Connection->QOS, QOS)) - { - list_remove(&Connection->conn_pool_entry); - LeaveCriticalSection(&assoc->cs); - TRACE("got connection from pool %p\n", Connection); - return Connection; - } - } - - LeaveCriticalSection(&assoc->cs); - return NULL; -} - -RPC_STATUS RpcAssoc_GetClientConnection(RpcAssoc *assoc, - const RPC_SYNTAX_IDENTIFIER *InterfaceId, - const RPC_SYNTAX_IDENTIFIER *TransferSyntax, RpcAuthInfo *AuthInfo, - RpcQualityOfService *QOS, RpcConnection **Connection) -{ - RpcConnection *NewConnection; - RPC_STATUS status; - - *Connection = RpcAssoc_GetIdleConnection(assoc, InterfaceId, TransferSyntax, AuthInfo, QOS); - if (*Connection) - return RPC_S_OK; - - /* create a new connection */ - status = RPCRT4_CreateConnection(&NewConnection, FALSE /* is this a server connection? */, - assoc->Protseq, assoc->NetworkAddr, - assoc->Endpoint, assoc->NetworkOptions, - AuthInfo, QOS); - if (status != RPC_S_OK) - return status; - - status = RPCRT4_OpenClientConnection(NewConnection); - if (status != RPC_S_OK) - { - RPCRT4_DestroyConnection(NewConnection); - return status; - } - - status = RpcAssoc_BindConnection(assoc, NewConnection, InterfaceId, TransferSyntax); - if (status != RPC_S_OK) - { - RPCRT4_DestroyConnection(NewConnection); - return status; - } - - *Connection = NewConnection; - - return RPC_S_OK; -} - -void RpcAssoc_ReleaseIdleConnection(RpcAssoc *assoc, RpcConnection *Connection) -{ - assert(!Connection->server); - EnterCriticalSection(&assoc->cs); - if (!assoc->assoc_group_id) assoc->assoc_group_id = Connection->assoc_group_id; - list_add_head(&assoc->connection_pool, &Connection->conn_pool_entry); - LeaveCriticalSection(&assoc->cs); -} - - -RPC_STATUS RPCRT4_SpawnConnection(RpcConnection** Connection, RpcConnection* OldConnection) -{ - RPC_STATUS err; - - err = RPCRT4_CreateConnection(Connection, OldConnection->server, - rpcrt4_conn_get_name(OldConnection), - OldConnection->NetworkAddr, - OldConnection->Endpoint, NULL, - OldConnection->AuthInfo, OldConnection->QOS); - if (err == RPC_S_OK) - rpcrt4_conn_handoff(OldConnection, *Connection); - return err; -} - -RPC_STATUS RPCRT4_DestroyConnection(RpcConnection* Connection) -{ - TRACE("connection: %p\n", Connection); - - RPCRT4_CloseConnection(Connection); - RPCRT4_strfree(Connection->Endpoint); - RPCRT4_strfree(Connection->NetworkAddr); - HeapFree(GetProcessHeap(), 0, Connection->NetworkOptions); - if (Connection->AuthInfo) RpcAuthInfo_Release(Connection->AuthInfo); - if (Connection->QOS) RpcQualityOfService_Release(Connection->QOS); - HeapFree(GetProcessHeap(), 0, Connection); - return RPC_S_OK; -} - -RPC_STATUS RpcTransport_GetTopOfTower(unsigned char *tower_data, - size_t *tower_size, - const char *protseq, - const char *networkaddr, - const char *endpoint) -{ - twr_empty_floor_t *protocol_floor; - const struct connection_ops *protseq_ops = rpcrt4_get_conn_protseq_ops(protseq); - - *tower_size = 0; - - if (!protseq_ops) - return RPC_S_INVALID_RPC_PROTSEQ; - - if (!tower_data) - { - *tower_size = sizeof(*protocol_floor); - *tower_size += protseq_ops->get_top_of_tower(NULL, networkaddr, endpoint); - return RPC_S_OK; - } - - protocol_floor = (twr_empty_floor_t *)tower_data; - protocol_floor->count_lhs = sizeof(protocol_floor->protid); - protocol_floor->protid = protseq_ops->epm_protocols[0]; - protocol_floor->count_rhs = 0; - - tower_data += sizeof(*protocol_floor); - - *tower_size = protseq_ops->get_top_of_tower(tower_data, networkaddr, endpoint); - if (!*tower_size) - return EPT_S_NOT_REGISTERED; - - *tower_size += sizeof(*protocol_floor); - - return RPC_S_OK; -} - -RPC_STATUS RpcTransport_ParseTopOfTower(const unsigned char *tower_data, - size_t tower_size, - char **protseq, - char **networkaddr, - char **endpoint) -{ - const twr_empty_floor_t *protocol_floor; - const twr_empty_floor_t *floor4; - const struct connection_ops *protseq_ops = NULL; - RPC_STATUS status; - int i; - - if (tower_size < sizeof(*protocol_floor)) - return EPT_S_NOT_REGISTERED; - - protocol_floor = (const twr_empty_floor_t *)tower_data; - tower_data += sizeof(*protocol_floor); - tower_size -= sizeof(*protocol_floor); - if ((protocol_floor->count_lhs != sizeof(protocol_floor->protid)) || - (protocol_floor->count_rhs > tower_size)) - return EPT_S_NOT_REGISTERED; - tower_data += protocol_floor->count_rhs; - tower_size -= protocol_floor->count_rhs; - - floor4 = (const twr_empty_floor_t *)tower_data; - if ((tower_size < sizeof(*floor4)) || - (floor4->count_lhs != sizeof(floor4->protid))) - return EPT_S_NOT_REGISTERED; - - for(i = 0; i < ARRAYSIZE(conn_protseq_list); i++) - if ((protocol_floor->protid == conn_protseq_list[i].epm_protocols[0]) && - (floor4->protid == conn_protseq_list[i].epm_protocols[1])) - { - protseq_ops = &conn_protseq_list[i]; - break; - } - - if (!protseq_ops) - return EPT_S_NOT_REGISTERED; - - status = protseq_ops->parse_top_of_tower(tower_data, tower_size, networkaddr, endpoint); - - if ((status == RPC_S_OK) && protseq) - { - *protseq = I_RpcAllocate(strlen(protseq_ops->name) + 1); - strcpy(*protseq, protseq_ops->name); - } - - return status; -} - -/*********************************************************************** - * RpcNetworkIsProtseqValidW (RPCRT4.@) - * - * Checks if the given protocol sequence is known by the RPC system. - * If it is, returns RPC_S_OK, otherwise RPC_S_PROTSEQ_NOT_SUPPORTED. - * - */ -RPC_STATUS WINAPI RpcNetworkIsProtseqValidW(RPC_WSTR protseq) -{ - char ps[0x10]; - - WideCharToMultiByte(CP_ACP, 0, protseq, -1, - ps, sizeof ps, NULL, NULL); - if (rpcrt4_get_conn_protseq_ops(ps)) - return RPC_S_OK; - - FIXME("Unknown protseq %s\n", debugstr_w(protseq)); - - return RPC_S_INVALID_RPC_PROTSEQ; -} - -/*********************************************************************** - * RpcNetworkIsProtseqValidA (RPCRT4.@) - */ -RPC_STATUS WINAPI RpcNetworkIsProtseqValidA(RPC_CSTR protseq) -{ - UNICODE_STRING protseqW; - - if (RtlCreateUnicodeStringFromAsciiz(&protseqW, (char*)protseq)) - { - RPC_STATUS ret = RpcNetworkIsProtseqValidW(protseqW.Buffer); - RtlFreeUnicodeString(&protseqW); - return ret; - } - return RPC_S_OUT_OF_MEMORY; -} + ps->mgr_event_rcv = fds[0]; + ps->mgr_event_snd = fds[1]; + } + else + { + ERR("socketpair failed with error %s\n", strerror(errno)); + HeapFree(GetProcessHeap(), 0, ps); + return NULL; + } + } + return &ps->common; +} + +static void rpcrt4_protseq_sock_signal_state_changed(RpcServerProtseq *protseq) +{ + RpcServerProtseq_sock *sockps = CONTAINING_RECORD(protseq, RpcServerProtseq_sock, common); + char dummy = 1; + write(sockps->mgr_event_snd, &dummy, sizeof(dummy)); +} + +static void *rpcrt4_protseq_sock_get_wait_array(RpcServerProtseq *protseq, void *prev_array, unsigned int *count) +{ + struct pollfd *poll_info = prev_array; + RpcConnection_tcp *conn; + RpcServerProtseq_sock *sockps = CONTAINING_RECORD(protseq, RpcServerProtseq_sock, common); + + EnterCriticalSection(&protseq->cs); + + /* open and count connections */ + *count = 1; + conn = (RpcConnection_tcp *)protseq->conn; + while (conn) { + if (conn->sock != -1) + (*count)++; + conn = (RpcConnection_tcp *)conn->common.Next; + } + + /* make array of connections */ + if (poll_info) + poll_info = HeapReAlloc(GetProcessHeap(), 0, poll_info, *count*sizeof(*poll_info)); + else + poll_info = HeapAlloc(GetProcessHeap(), 0, *count*sizeof(*poll_info)); + if (!poll_info) + { + ERR("couldn't allocate poll_info\n"); + LeaveCriticalSection(&protseq->cs); + return NULL; + } + + poll_info[0].fd = sockps->mgr_event_rcv; + poll_info[0].events = POLLIN; + *count = 1; + conn = CONTAINING_RECORD(protseq->conn, RpcConnection_tcp, common); + while (conn) { + if (conn->sock != -1) + { + poll_info[*count].fd = conn->sock; + poll_info[*count].events = POLLIN; + (*count)++; + } + conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_tcp, common); + } + LeaveCriticalSection(&protseq->cs); + return poll_info; +} + +static void rpcrt4_protseq_sock_free_wait_array(RpcServerProtseq *protseq, void *array) +{ + HeapFree(GetProcessHeap(), 0, array); +} + +static int rpcrt4_protseq_sock_wait_for_new_connection(RpcServerProtseq *protseq, unsigned int count, void *wait_array) +{ + struct pollfd *poll_info = wait_array; + int ret, i; + RpcConnection *cconn; + RpcConnection_tcp *conn; + + if (!poll_info) + return -1; + + ret = poll(poll_info, count, -1); + if (ret < 0) + { + ERR("poll failed with error %d\n", ret); + return -1; + } + + for (i = 0; i < count; i++) + if (poll_info[i].revents & POLLIN) + { + /* RPC server event */ + if (i == 0) + { + char dummy; + read(poll_info[0].fd, &dummy, sizeof(dummy)); + return 0; + } + + /* find which connection got a RPC */ + EnterCriticalSection(&protseq->cs); + conn = CONTAINING_RECORD(protseq->conn, RpcConnection_tcp, common); + while (conn) { + if (poll_info[i].fd == conn->sock) break; + conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_tcp, common); + } + cconn = NULL; + if (conn) + RPCRT4_SpawnConnection(&cconn, &conn->common); + else + ERR("failed to locate connection for fd %d\n", poll_info[i].fd); + LeaveCriticalSection(&protseq->cs); + if (cconn) + RPCRT4_new_client(cconn); + else + return -1; + } + + return 1; +} + +static const struct connection_ops conn_protseq_list[] = { + { "ncacn_np", + { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_SMB }, + rpcrt4_conn_np_alloc, + rpcrt4_ncacn_np_open, + rpcrt4_ncacn_np_handoff, + rpcrt4_conn_np_read, + rpcrt4_conn_np_write, + rpcrt4_conn_np_close, + rpcrt4_conn_np_cancel_call, + rpcrt4_ncacn_np_get_top_of_tower, + rpcrt4_ncacn_np_parse_top_of_tower, + }, + { "ncalrpc", + { EPM_PROTOCOL_NCALRPC, EPM_PROTOCOL_PIPE }, + rpcrt4_conn_np_alloc, + rpcrt4_ncalrpc_open, + rpcrt4_ncalrpc_handoff, + rpcrt4_conn_np_read, + rpcrt4_conn_np_write, + rpcrt4_conn_np_close, + rpcrt4_conn_np_cancel_call, + rpcrt4_ncalrpc_get_top_of_tower, + rpcrt4_ncalrpc_parse_top_of_tower, + }, + { "ncacn_ip_tcp", + { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_TCP }, + rpcrt4_conn_tcp_alloc, + rpcrt4_ncacn_ip_tcp_open, + rpcrt4_conn_tcp_handoff, + rpcrt4_conn_tcp_read, + rpcrt4_conn_tcp_write, + rpcrt4_conn_tcp_close, + rpcrt4_conn_tcp_cancel_call, + rpcrt4_ncacn_ip_tcp_get_top_of_tower, + rpcrt4_ncacn_ip_tcp_parse_top_of_tower, + } +}; + + +static const struct protseq_ops protseq_list[] = +{ + { + "ncacn_np", + rpcrt4_protseq_np_alloc, + rpcrt4_protseq_np_signal_state_changed, + rpcrt4_protseq_np_get_wait_array, + rpcrt4_protseq_np_free_wait_array, + rpcrt4_protseq_np_wait_for_new_connection, + rpcrt4_protseq_ncacn_np_open_endpoint, + }, + { + "ncalrpc", + rpcrt4_protseq_np_alloc, + rpcrt4_protseq_np_signal_state_changed, + rpcrt4_protseq_np_get_wait_array, + rpcrt4_protseq_np_free_wait_array, + rpcrt4_protseq_np_wait_for_new_connection, + rpcrt4_protseq_ncalrpc_open_endpoint, + }, + { + "ncacn_ip_tcp", + rpcrt4_protseq_sock_alloc, + rpcrt4_protseq_sock_signal_state_changed, + rpcrt4_protseq_sock_get_wait_array, + rpcrt4_protseq_sock_free_wait_array, + rpcrt4_protseq_sock_wait_for_new_connection, + rpcrt4_protseq_ncacn_ip_tcp_open_endpoint, + }, +}; + +#define ARRAYSIZE(a) (sizeof((a)) / sizeof((a)[0])) + +const struct protseq_ops *rpcrt4_get_protseq_ops(const char *protseq) +{ + int i; + for(i=0; iserver); + return Connection->ops->open_connection_client(Connection); +} + +RPC_STATUS RPCRT4_CloseConnection(RpcConnection* Connection) +{ + TRACE("(Connection == ^%p)\n", Connection); + if (SecIsValidHandle(&Connection->ctx)) + { + DeleteSecurityContext(&Connection->ctx); + SecInvalidateHandle(&Connection->ctx); + } + rpcrt4_conn_close(Connection); + return RPC_S_OK; +} + +RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server, + LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint, + LPCWSTR NetworkOptions, RpcAuthInfo* AuthInfo, RpcQualityOfService *QOS) +{ + const struct connection_ops *ops; + RpcConnection* NewConnection; + + ops = rpcrt4_get_conn_protseq_ops(Protseq); + if (!ops) + { + FIXME("not supported for protseq %s\n", Protseq); + return RPC_S_PROTSEQ_NOT_SUPPORTED; + } + + NewConnection = ops->alloc(); + NewConnection->Next = NULL; + NewConnection->server_binding = NULL; + NewConnection->server = server; + NewConnection->ops = ops; + NewConnection->NetworkAddr = RPCRT4_strdupA(NetworkAddr); + NewConnection->Endpoint = RPCRT4_strdupA(Endpoint); + NewConnection->NetworkOptions = RPCRT4_strdupW(NetworkOptions); + NewConnection->MaxTransmissionSize = RPC_MAX_PACKET_SIZE; + memset(&NewConnection->ActiveInterface, 0, sizeof(NewConnection->ActiveInterface)); + NewConnection->NextCallId = 1; + + SecInvalidateHandle(&NewConnection->ctx); + memset(&NewConnection->exp, 0, sizeof(NewConnection->exp)); + NewConnection->attr = 0; + if (AuthInfo) RpcAuthInfo_AddRef(AuthInfo); + NewConnection->AuthInfo = AuthInfo; + NewConnection->encryption_auth_len = 0; + NewConnection->signature_auth_len = 0; + if (QOS) RpcQualityOfService_AddRef(QOS); + NewConnection->QOS = QOS; + + list_init(&NewConnection->conn_pool_entry); + + TRACE("connection: %p\n", NewConnection); + *Connection = NewConnection; + + return RPC_S_OK; +} + + +RPC_STATUS RPCRT4_SpawnConnection(RpcConnection** Connection, RpcConnection* OldConnection) +{ + RPC_STATUS err; + + err = RPCRT4_CreateConnection(Connection, OldConnection->server, + rpcrt4_conn_get_name(OldConnection), + OldConnection->NetworkAddr, + OldConnection->Endpoint, NULL, + OldConnection->AuthInfo, OldConnection->QOS); + if (err == RPC_S_OK) + rpcrt4_conn_handoff(OldConnection, *Connection); + return err; +} + +RPC_STATUS RPCRT4_DestroyConnection(RpcConnection* Connection) +{ + TRACE("connection: %p\n", Connection); + + RPCRT4_CloseConnection(Connection); + RPCRT4_strfree(Connection->Endpoint); + RPCRT4_strfree(Connection->NetworkAddr); + HeapFree(GetProcessHeap(), 0, Connection->NetworkOptions); + if (Connection->AuthInfo) RpcAuthInfo_Release(Connection->AuthInfo); + if (Connection->QOS) RpcQualityOfService_Release(Connection->QOS); + + /* server-only */ + if (Connection->server_binding) RPCRT4_DestroyBinding(Connection->server_binding); + + HeapFree(GetProcessHeap(), 0, Connection); + return RPC_S_OK; +} + +RPC_STATUS RpcTransport_GetTopOfTower(unsigned char *tower_data, + size_t *tower_size, + const char *protseq, + const char *networkaddr, + const char *endpoint) +{ + twr_empty_floor_t *protocol_floor; + const struct connection_ops *protseq_ops = rpcrt4_get_conn_protseq_ops(protseq); + + *tower_size = 0; + + if (!protseq_ops) + return RPC_S_INVALID_RPC_PROTSEQ; + + if (!tower_data) + { + *tower_size = sizeof(*protocol_floor); + *tower_size += protseq_ops->get_top_of_tower(NULL, networkaddr, endpoint); + return RPC_S_OK; + } + + protocol_floor = (twr_empty_floor_t *)tower_data; + protocol_floor->count_lhs = sizeof(protocol_floor->protid); + protocol_floor->protid = protseq_ops->epm_protocols[0]; + protocol_floor->count_rhs = 0; + + tower_data += sizeof(*protocol_floor); + + *tower_size = protseq_ops->get_top_of_tower(tower_data, networkaddr, endpoint); + if (!*tower_size) + return EPT_S_NOT_REGISTERED; + + *tower_size += sizeof(*protocol_floor); + + return RPC_S_OK; +} + +RPC_STATUS RpcTransport_ParseTopOfTower(const unsigned char *tower_data, + size_t tower_size, + char **protseq, + char **networkaddr, + char **endpoint) +{ + const twr_empty_floor_t *protocol_floor; + const twr_empty_floor_t *floor4; + const struct connection_ops *protseq_ops = NULL; + RPC_STATUS status; + int i; + + if (tower_size < sizeof(*protocol_floor)) + return EPT_S_NOT_REGISTERED; + + protocol_floor = (const twr_empty_floor_t *)tower_data; + tower_data += sizeof(*protocol_floor); + tower_size -= sizeof(*protocol_floor); + if ((protocol_floor->count_lhs != sizeof(protocol_floor->protid)) || + (protocol_floor->count_rhs > tower_size)) + return EPT_S_NOT_REGISTERED; + tower_data += protocol_floor->count_rhs; + tower_size -= protocol_floor->count_rhs; + + floor4 = (const twr_empty_floor_t *)tower_data; + if ((tower_size < sizeof(*floor4)) || + (floor4->count_lhs != sizeof(floor4->protid))) + return EPT_S_NOT_REGISTERED; + + for(i = 0; i < ARRAYSIZE(conn_protseq_list); i++) + if ((protocol_floor->protid == conn_protseq_list[i].epm_protocols[0]) && + (floor4->protid == conn_protseq_list[i].epm_protocols[1])) + { + protseq_ops = &conn_protseq_list[i]; + break; + } + + if (!protseq_ops) + return EPT_S_NOT_REGISTERED; + + status = protseq_ops->parse_top_of_tower(tower_data, tower_size, networkaddr, endpoint); + + if ((status == RPC_S_OK) && protseq) + { + *protseq = I_RpcAllocate(strlen(protseq_ops->name) + 1); + strcpy(*protseq, protseq_ops->name); + } + + return status; +} + +/*********************************************************************** + * RpcNetworkIsProtseqValidW (RPCRT4.@) + * + * Checks if the given protocol sequence is known by the RPC system. + * If it is, returns RPC_S_OK, otherwise RPC_S_PROTSEQ_NOT_SUPPORTED. + * + */ +RPC_STATUS WINAPI RpcNetworkIsProtseqValidW(RPC_WSTR protseq) +{ + char ps[0x10]; + + WideCharToMultiByte(CP_ACP, 0, protseq, -1, + ps, sizeof ps, NULL, NULL); + if (rpcrt4_get_conn_protseq_ops(ps)) + return RPC_S_OK; + + FIXME("Unknown protseq %s\n", debugstr_w(protseq)); + + return RPC_S_INVALID_RPC_PROTSEQ; +} + +/*********************************************************************** + * RpcNetworkIsProtseqValidA (RPCRT4.@) + */ +RPC_STATUS WINAPI RpcNetworkIsProtseqValidA(RPC_CSTR protseq) +{ + UNICODE_STRING protseqW; + + if (RtlCreateUnicodeStringFromAsciiz(&protseqW, (char*)protseq)) + { + RPC_STATUS ret = RpcNetworkIsProtseqValidW(protseqW.Buffer); + RtlFreeUnicodeString(&protseqW); + return ret; + } + return RPC_S_OUT_OF_MEMORY; +} diff --git a/reactos/dll/win32/rpcrt4_new/rpcrt4.rbuild b/reactos/dll/win32/rpcrt4_new/rpcrt4.rbuild index 1e4e1c09dc3..2da95d825fc 100644 --- a/reactos/dll/win32/rpcrt4_new/rpcrt4.rbuild +++ b/reactos/dll/win32/rpcrt4_new/rpcrt4.rbuild @@ -23,11 +23,13 @@ cproxy.c cpsf.c cstub.c + ndr_contexthandle.c ndr_clientserver.c ndr_fullpointer.c ndr_marshall.c ndr_ole.c ndr_stubless.c + rpc_assoc.c rpc_binding.c rpc_epmap.c rpc_message.c diff --git a/reactos/dll/win32/rpcrt4_new/rpcrt4.spec b/reactos/dll/win32/rpcrt4_new/rpcrt4.spec index c5498d7037a..1e9cbe3446d 100644 --- a/reactos/dll/win32/rpcrt4_new/rpcrt4.spec +++ b/reactos/dll/win32/rpcrt4_new/rpcrt4.spec @@ -1,565 +1,565 @@ -@ stdcall CreateProxyFromTypeInfo(ptr ptr ptr ptr ptr) -@ stub CreateStubFromTypeInfo -@ stdcall CStdStubBuffer_AddRef(ptr) -@ stdcall CStdStubBuffer_Connect(ptr ptr) -@ stdcall CStdStubBuffer_CountRefs(ptr) -@ stdcall CStdStubBuffer_DebugServerQueryInterface(ptr ptr) -@ stdcall CStdStubBuffer_DebugServerRelease(ptr ptr) -@ stdcall CStdStubBuffer_Disconnect(ptr) -@ stdcall CStdStubBuffer_Invoke(ptr ptr ptr) -@ stdcall CStdStubBuffer_IsIIDSupported(ptr ptr) -@ stdcall CStdStubBuffer_QueryInterface(ptr ptr ptr) -@ stub CreateServerInterfaceFromStub # wxp -@ stdcall DceErrorInqTextA (long ptr) -@ stdcall DceErrorInqTextW (long ptr) -@ stdcall -private DllRegisterServer() -@ stub GlobalMutexClearExternal -@ stub GlobalMutexRequestExternal -@ stdcall IUnknown_AddRef_Proxy(ptr) -@ stdcall IUnknown_QueryInterface_Proxy(ptr ptr ptr) -@ stdcall IUnknown_Release_Proxy(ptr) -@ stub I_RpcAbortAsyncCall -@ stdcall I_RpcAllocate(long) -@ stub I_RpcAsyncAbortCall -@ stub I_RpcAsyncSendReceive # NT4 -@ stub I_RpcAsyncSetHandle -@ stub I_RpcBCacheAllocate -@ stub I_RpcBCacheFree -@ stub I_RpcBindingCopy -@ stub I_RpcBindingInqConnId -@ stub I_RpcBindingInqDynamicEndPoint -@ stub I_RpcBindingInqDynamicEndPointA -@ stub I_RpcBindingInqDynamicEndPointW -@ stub I_RpcBindingInqLocalClientPID # wxp -@ stub I_RpcBindingInqSecurityContext -@ stub I_RpcBindingInqTransportType -@ stub I_RpcBindingInqWireIdForSnego -@ stub I_RpcBindingIsClientLocal -# 9x version of I_RpcBindingSetAsync has 3 arguments, not 2 -@ stdcall I_RpcBindingSetAsync(ptr ptr) -@ stub I_RpcBindingToStaticStringBindingW -@ stub I_RpcClearMutex -@ stub I_RpcConnectionInqSockBuffSize2 -@ stub I_RpcConnectionInqSockBuffSize -@ stub I_RpcConnectionSetSockBuffSize -@ stub I_RpcDeleteMutex -@ stub I_RpcEnableWmiTrace # wxp -@ stub I_RpcExceptionFilter # wxp -@ stdcall I_RpcFree(ptr) -@ stdcall I_RpcFreeBuffer(ptr) -@ stub I_RpcFreePipeBuffer -@ stub I_RpcGetAssociationContext -@ stdcall I_RpcGetBuffer(ptr) -@ stub I_RpcGetBufferWithObject -@ stub I_RpcGetCurrentCallHandle -@ stub I_RpcGetExtendedError -@ stub I_RpcGetServerContextList -@ stub I_RpcGetThreadEvent # win9x -@ stub I_RpcGetThreadWindowHandle # win9x -@ stub I_RpcIfInqTransferSyntaxes -@ stub I_RpcLaunchDatagramReceiveThread # win9x -@ stub I_RpcLogEvent -@ stdcall I_RpcMapWin32Status(long) -@ stub I_RpcMonitorAssociation -@ stub I_RpcNegotiateTransferSyntax # wxp -@ stub I_RpcNsBindingSetEntryName -@ stub I_RpcNsBindingSetEntryNameA -@ stub I_RpcNsBindingSetEntryNameW -@ stub I_RpcNsInterfaceExported -@ stub I_RpcNsInterfaceUnexported -@ stub I_RpcParseSecurity -@ stub I_RpcPauseExecution -@ stub I_RpcProxyNewConnection # wxp -@ stub I_RpcReallocPipeBuffer -@ stdcall I_RpcReceive(ptr) -@ stub I_RpcRequestMutex -@ stdcall I_RpcSend(ptr) -@ stdcall I_RpcSendReceive(ptr) -@ stub I_RpcServerAllocateIpPort -@ stub I_RpcServerInqAddressChangeFn -@ stub I_RpcServerInqLocalConnAddress # wxp -@ stub I_RpcServerInqTransportType -@ stub I_RpcServerRegisterForwardFunction -@ stub I_RpcServerSetAddressChangeFn -@ stdcall I_RpcServerStartListening(ptr) # win9x -@ stdcall I_RpcServerStopListening() # win9x -@ stub I_RpcServerUnregisterEndpointA # win9x -@ stub I_RpcServerUnregisterEndpointW # win9x -@ stub I_RpcServerUseProtseq2A -@ stub I_RpcServerUseProtseq2W -@ stub I_RpcServerUseProtseqEp2A -@ stub I_RpcServerUseProtseqEp2W -@ stub I_RpcSetAssociationContext # win9x -@ stub I_RpcSetAsyncHandle -@ stub I_RpcSetServerContextList -@ stub I_RpcSetThreadParams # win9x -@ stub I_RpcSetWMsgEndpoint # NT4 -@ stub I_RpcSsDontSerializeContext -@ stub I_RpcStopMonitorAssociation -@ stub I_RpcSystemFunction001 # wxp (oh, brother!) -@ stub I_RpcTransCancelMigration # win9x -@ stub I_RpcTransClientMaxFrag # win9x -@ stub I_RpcTransClientReallocBuffer # win9x -@ stub I_RpcTransConnectionAllocatePacket -@ stub I_RpcTransConnectionFreePacket -@ stub I_RpcTransConnectionReallocPacket -@ stub I_RpcTransDatagramAllocate2 -@ stub I_RpcTransDatagramAllocate -@ stub I_RpcTransDatagramFree -@ stub I_RpcTransGetAddressList -@ stub I_RpcTransGetThreadEvent -@ stub I_RpcTransIoCancelled -@ stub I_RpcTransMaybeMakeReceiveAny # win9x -@ stub I_RpcTransMaybeMakeReceiveDirect # win9x -@ stub I_RpcTransPingServer # win9x -@ stub I_RpcTransServerFindConnection # win9x -@ stub I_RpcTransServerFreeBuffer # win9x -@ stub I_RpcTransServerMaxFrag # win9x -@ stub I_RpcTransServerNewConnection -@ stub I_RpcTransServerProtectThread # win9x -@ stub I_RpcTransServerReallocBuffer # win9x -@ stub I_RpcTransServerReceiveDirectReady # win9x -@ stub I_RpcTransServerUnprotectThread # win9x -@ stub I_RpcTurnOnEEInfoPropagation # wxp -@ stdcall I_RpcWindowProc(ptr long long long) # win9x -@ stub I_RpcltDebugSetPDUFilter -@ stub I_UuidCreate -@ stub MIDL_wchar_strcpy -@ stub MIDL_wchar_strlen -@ stub MesBufferHandleReset -@ stub MesDecodeBufferHandleCreate -@ stub MesDecodeIncrementalHandleCreate -@ stub MesEncodeDynBufferHandleCreate -@ stub MesEncodeFixedBufferHandleCreate -@ stub MesEncodeIncrementalHandleCreate -@ stub MesHandleFree -@ stub MesIncrementalHandleReset -@ stub MesInqProcEncodingId -@ stub MqGetContext # win9x -@ stub MqRegisterQueue # win9x -@ stdcall NDRCContextBinding(ptr) -@ stdcall NDRCContextMarshall(ptr ptr) -@ stdcall NDRCContextUnmarshall(ptr ptr ptr long) -@ stdcall NDRSContextMarshall2(ptr ptr ptr ptr ptr long) -@ stdcall NDRSContextMarshall(ptr ptr ptr) -@ stdcall NDRSContextMarshallEx(ptr ptr ptr ptr) -@ stdcall NDRSContextUnmarshall2(ptr ptr ptr ptr long) -@ stdcall NDRSContextUnmarshall(ptr ptr) -@ stdcall NDRSContextUnmarshallEx(ptr ptr ptr) -@ stub NDRcopy -@ stdcall NdrAllocate(ptr long) -@ stub NdrAsyncClientCall -@ stub NdrAsyncServerCall -@ stdcall NdrByteCountPointerBufferSize(ptr ptr ptr) -@ stdcall NdrByteCountPointerFree(ptr ptr ptr) -@ stdcall NdrByteCountPointerMarshall(ptr ptr ptr) -@ stdcall NdrByteCountPointerUnmarshall(ptr ptr ptr long) -@ stdcall NdrCStdStubBuffer2_Release(ptr ptr) -@ stdcall NdrCStdStubBuffer_Release(ptr ptr) -@ stdcall NdrClearOutParameters(ptr ptr ptr) -@ varargs NdrClientCall2(ptr ptr) -@ varargs NdrClientCall(ptr ptr) NdrClientCall2 -@ stdcall NdrClientContextMarshall(ptr ptr long) -@ stdcall NdrClientContextUnmarshall(ptr ptr ptr) -@ stub NdrClientInitialize -@ stdcall NdrClientInitializeNew(ptr ptr ptr long) -@ stdcall NdrComplexArrayBufferSize(ptr ptr ptr) -@ stdcall NdrComplexArrayFree(ptr ptr ptr) -@ stdcall NdrComplexArrayMarshall(ptr ptr ptr) -@ stdcall NdrComplexArrayMemorySize(ptr ptr) -@ stdcall NdrComplexArrayUnmarshall(ptr ptr ptr long) -@ stdcall NdrComplexStructBufferSize(ptr ptr ptr) -@ stdcall NdrComplexStructFree(ptr ptr ptr) -@ stdcall NdrComplexStructMarshall(ptr ptr ptr) -@ stdcall NdrComplexStructMemorySize(ptr ptr) -@ stdcall NdrComplexStructUnmarshall(ptr ptr ptr long) -@ stdcall NdrConformantArrayBufferSize(ptr ptr ptr) -@ stdcall NdrConformantArrayFree(ptr ptr ptr) -@ stdcall NdrConformantArrayMarshall(ptr ptr ptr) -@ stdcall NdrConformantArrayMemorySize(ptr ptr) -@ stdcall NdrConformantArrayUnmarshall(ptr ptr ptr long) -@ stdcall NdrConformantStringBufferSize(ptr ptr ptr) -@ stdcall NdrConformantStringMarshall(ptr ptr ptr) -@ stdcall NdrConformantStringMemorySize(ptr ptr) -@ stdcall NdrConformantStringUnmarshall(ptr ptr ptr long) -@ stdcall NdrConformantStructBufferSize(ptr ptr ptr) -@ stdcall NdrConformantStructFree(ptr ptr ptr) -@ stdcall NdrConformantStructMarshall(ptr ptr ptr) -@ stdcall NdrConformantStructMemorySize(ptr ptr) -@ stdcall NdrConformantStructUnmarshall(ptr ptr ptr long) -@ stdcall NdrConformantVaryingArrayBufferSize(ptr ptr ptr) -@ stdcall NdrConformantVaryingArrayFree(ptr ptr ptr) -@ stdcall NdrConformantVaryingArrayMarshall(ptr ptr ptr) -@ stdcall NdrConformantVaryingArrayMemorySize(ptr ptr) -@ stdcall NdrConformantVaryingArrayUnmarshall(ptr ptr ptr long) -@ stdcall NdrConformantVaryingStructBufferSize(ptr ptr ptr) -@ stdcall NdrConformantVaryingStructFree(ptr ptr ptr) -@ stdcall NdrConformantVaryingStructMarshall(ptr ptr ptr) -@ stdcall NdrConformantVaryingStructMemorySize(ptr ptr) -@ stdcall NdrConformantVaryingStructUnmarshall(ptr ptr ptr long) -@ stdcall NdrContextHandleInitialize(ptr ptr) -@ stdcall NdrContextHandleSize(ptr ptr ptr) -@ stdcall NdrConvert2(ptr ptr long) -@ stdcall NdrConvert(ptr ptr) -@ stub NdrCorrelationFree -@ stub NdrCorrelationInitialize -@ stub NdrCorrelationPass -@ stub NdrDcomAsyncClientCall -@ stub NdrDcomAsyncStubCall -@ stdcall NdrDllCanUnloadNow(ptr) -@ stdcall NdrDllGetClassObject(ptr ptr ptr ptr ptr ptr) -@ stdcall NdrDllRegisterProxy(long ptr ptr) -@ stdcall NdrDllUnregisterProxy(long ptr ptr) -@ stdcall NdrEncapsulatedUnionBufferSize(ptr ptr ptr) -@ stdcall NdrEncapsulatedUnionFree(ptr ptr ptr) -@ stdcall NdrEncapsulatedUnionMarshall(ptr ptr ptr) -@ stdcall NdrEncapsulatedUnionMemorySize(ptr ptr) -@ stdcall NdrEncapsulatedUnionUnmarshall(ptr ptr ptr long) -@ stdcall NdrFixedArrayBufferSize(ptr ptr ptr) -@ stdcall NdrFixedArrayFree(ptr ptr ptr) -@ stdcall NdrFixedArrayMarshall(ptr ptr ptr) -@ stdcall NdrFixedArrayMemorySize(ptr ptr) -@ stdcall NdrFixedArrayUnmarshall(ptr ptr ptr long) -@ stdcall NdrFreeBuffer(ptr) -@ stdcall NdrFullPointerFree(ptr ptr) -@ stdcall NdrFullPointerInsertRefId(ptr long ptr) -@ stdcall NdrFullPointerQueryPointer(ptr ptr long ptr) -@ stdcall NdrFullPointerQueryRefId(ptr long long ptr) -@ stdcall NdrFullPointerXlatFree(ptr) -@ stdcall NdrFullPointerXlatInit(long long) -@ stdcall NdrGetBuffer(ptr long ptr) -@ stub NdrGetDcomProtocolVersion -@ stub NdrGetPartialBuffer -@ stub NdrGetPipeBuffer -@ stub NdrGetSimpleTypeBufferAlignment # wxp -@ stub NdrGetSimpleTypeBufferSize # wxp -@ stub NdrGetSimpleTypeMemorySize # wxp -@ stub NdrGetTypeFlags # wxp -@ stub NdrGetUserMarshallInfo -@ stub NdrHardStructBufferSize #(ptr ptr ptr) -@ stub NdrHardStructFree #(ptr ptr ptr) -@ stub NdrHardStructMarshall #(ptr ptr ptr) -@ stub NdrHardStructMemorySize #(ptr ptr) -@ stub NdrHardStructUnmarshall #(ptr ptr ptr long) -@ stdcall NdrInterfacePointerBufferSize(ptr ptr ptr) -@ stdcall NdrInterfacePointerFree(ptr ptr ptr) -@ stdcall NdrInterfacePointerMarshall(ptr ptr ptr) -@ stdcall NdrInterfacePointerMemorySize(ptr ptr) -@ stdcall NdrInterfacePointerUnmarshall(ptr ptr ptr long) -@ stub NdrIsAppDoneWithPipes -@ stdcall NdrMapCommAndFaultStatus(ptr ptr ptr long) -@ stub NdrMarkNextActivePipe -@ stub NdrMesProcEncodeDecode2 -@ stub NdrMesProcEncodeDecode -@ stub NdrMesSimpleTypeAlignSize -@ stub NdrMesSimpleTypeDecode -@ stub NdrMesSimpleTypeEncode -@ stub NdrMesTypeAlignSize2 -@ stub NdrMesTypeAlignSize -@ stub NdrMesTypeDecode2 -@ stub NdrMesTypeDecode -@ stub NdrMesTypeEncode2 -@ stub NdrMesTypeEncode -@ stub NdrMesTypeFree2 -@ stdcall NdrNonConformantStringBufferSize(ptr ptr ptr) -@ stdcall NdrNonConformantStringMarshall(ptr ptr ptr) -@ stdcall NdrNonConformantStringMemorySize(ptr ptr) -@ stdcall NdrNonConformantStringUnmarshall(ptr ptr ptr long) -@ stdcall NdrNonEncapsulatedUnionBufferSize(ptr ptr ptr) -@ stdcall NdrNonEncapsulatedUnionFree(ptr ptr ptr) -@ stdcall NdrNonEncapsulatedUnionMarshall(ptr ptr ptr) -@ stdcall NdrNonEncapsulatedUnionMemorySize(ptr ptr) -@ stdcall NdrNonEncapsulatedUnionUnmarshall(ptr ptr ptr long) -@ stub NdrNsGetBuffer -@ stub NdrNsSendReceive -@ stdcall NdrOleAllocate(long) -@ stdcall NdrOleFree(ptr) -@ stub NdrOutInit # wxp -@ stub NdrPartialIgnoreClientBufferSize # wxp -@ stub NdrPartialIgnoreClientMarshall # wxp -@ stub NdrPartialIgnoreServerInitialize # wxp -@ stub NdrPartialIgnoreServerUnmarshall # wxp -@ stub NdrPipePull -@ stub NdrPipePush -@ stub NdrPipeSendReceive -@ stub NdrPipesDone -@ stub NdrPipesInitialize -@ stdcall NdrPointerBufferSize(ptr ptr ptr) -@ stdcall NdrPointerFree(ptr ptr ptr) -@ stdcall NdrPointerMarshall(ptr ptr ptr) -@ stdcall NdrPointerMemorySize(ptr ptr) -@ stdcall NdrPointerUnmarshall(ptr ptr ptr long) -@ stdcall NdrProxyErrorHandler(long) -@ stdcall NdrProxyFreeBuffer(ptr ptr) -@ stdcall NdrProxyGetBuffer(ptr ptr) -@ stdcall NdrProxyInitialize(ptr ptr ptr ptr long) -@ stdcall NdrProxySendReceive(ptr ptr) -@ stub NdrRangeUnmarshall -@ stub NdrRpcSmClientAllocate -@ stub NdrRpcSmClientFree -@ stub NdrRpcSmSetClientToOsf -@ stub NdrRpcSsDefaultAllocate -@ stub NdrRpcSsDefaultFree -@ stub NdrRpcSsDisableAllocate -@ stub NdrRpcSsEnableAllocate -@ stdcall NdrSendReceive(ptr ptr) -@ stdcall NdrServerCall2(ptr) -@ stub NdrServerCall -@ stdcall NdrServerContextMarshall(ptr ptr long) -@ stdcall NdrServerContextNewMarshall(ptr ptr ptr ptr) # wxp -@ stdcall NdrServerContextNewUnmarshall(ptr ptr) # wxp -@ stdcall NdrServerContextUnmarshall(ptr) -@ stub NdrServerInitialize -@ stub NdrServerInitializeMarshall -@ stdcall NdrServerInitializeNew(ptr ptr ptr) -@ stub NdrServerInitializePartial # wxp -@ stub NdrServerInitializeUnmarshall -@ stub NdrServerMarshall -@ stub NdrServerUnmarshall -@ stdcall NdrSimpleStructBufferSize(ptr ptr ptr) -@ stdcall NdrSimpleStructFree(ptr ptr ptr) -@ stdcall NdrSimpleStructMarshall(ptr ptr ptr) -@ stdcall NdrSimpleStructMemorySize(ptr ptr) -@ stdcall NdrSimpleStructUnmarshall(ptr ptr ptr long) -@ stdcall NdrSimpleTypeMarshall(ptr ptr long) -@ stdcall NdrSimpleTypeUnmarshall(ptr ptr long) -@ stdcall NdrStubCall2(ptr ptr ptr ptr) -@ stub NdrStubCall -@ stdcall NdrStubForwardingFunction(ptr ptr ptr ptr) -@ stdcall NdrStubGetBuffer(ptr ptr ptr) -@ stdcall NdrStubInitialize(ptr ptr ptr ptr) -@ stub NdrStubInitializeMarshall -@ stub NdrTypeFlags # wxp -@ stub NdrTypeFree # wxp -@ stub NdrTypeMarshall # wxp -@ stub NdrTypeSize # wxp -@ stub NdrTypeUnmarshall # wxp -@ stub NdrUnmarshallBasetypeInline # wxp -@ stdcall NdrUserMarshalBufferSize(ptr ptr ptr) -@ stdcall NdrUserMarshalFree(ptr ptr ptr) -@ stdcall NdrUserMarshalMarshall(ptr ptr ptr) -@ stdcall NdrUserMarshalMemorySize(ptr ptr) -@ stub NdrUserMarshalSimpleTypeConvert -@ stdcall NdrUserMarshalUnmarshall(ptr ptr ptr long) -@ stdcall NdrVaryingArrayBufferSize(ptr ptr ptr) -@ stdcall NdrVaryingArrayFree(ptr ptr ptr) -@ stdcall NdrVaryingArrayMarshall(ptr ptr ptr) -@ stdcall NdrVaryingArrayMemorySize(ptr ptr) -@ stdcall NdrVaryingArrayUnmarshall(ptr ptr ptr long) -@ stdcall NdrXmitOrRepAsBufferSize(ptr ptr ptr) -@ stdcall NdrXmitOrRepAsFree(ptr ptr ptr) -@ stdcall NdrXmitOrRepAsMarshall(ptr ptr ptr) -@ stdcall NdrXmitOrRepAsMemorySize(ptr ptr) -@ stdcall NdrXmitOrRepAsUnmarshall(ptr ptr ptr long) -@ stub NdrpCreateProxy # wxp -@ stub NdrpCreateStub # wxp -@ stub NdrpGetProcFormatString # wxp -@ stub NdrpGetTypeFormatString # wxp -@ stub NdrpGetTypeGenCookie # wxp -@ stub NdrpMemoryIncrement # wxp -@ stub NdrpReleaseTypeFormatString # wxp -@ stub NdrpReleaseTypeGenCookie # wxp -@ stub NdrpSetRpcSsDefaults -@ stub NdrpVarVtOfTypeDesc # wxp -@ stub PerformRpcInitialization -@ stub RpcAbortAsyncCall -@ stub RpcAsyncAbortCall -@ stub RpcAsyncCancelCall -@ stub RpcAsyncCompleteCall -@ stub RpcAsyncGetCallStatus -@ stub RpcAsyncInitializeHandle -@ stub RpcAsyncRegisterInfo -@ stdcall RpcBindingCopy(ptr ptr) -@ stdcall RpcBindingFree(ptr) -@ stdcall RpcBindingFromStringBindingA(str ptr) -@ stdcall RpcBindingFromStringBindingW(wstr ptr) -@ stub RpcBindingInqAuthClientA -@ stub RpcBindingInqAuthClientExA -@ stub RpcBindingInqAuthClientExW -@ stub RpcBindingInqAuthClientW -@ stdcall RpcBindingInqAuthInfoA(ptr ptr ptr ptr ptr ptr) -@ stdcall RpcBindingInqAuthInfoExA(ptr ptr ptr ptr ptr ptr long ptr) -@ stdcall RpcBindingInqAuthInfoExW(ptr ptr ptr ptr ptr ptr long ptr) -@ stdcall RpcBindingInqAuthInfoW(ptr ptr ptr ptr ptr ptr) -@ stdcall RpcBindingInqObject(ptr ptr) -@ stub RpcBindingInqOption -@ stub RpcBindingReset -@ stub RpcBindingServerFromClient -@ stdcall RpcBindingSetAuthInfoA(ptr str long long ptr long) -@ stdcall RpcBindingSetAuthInfoExA(ptr str long long ptr long ptr) -@ stdcall RpcBindingSetAuthInfoExW(ptr wstr long long ptr long ptr) -@ stdcall RpcBindingSetAuthInfoW(ptr wstr long long ptr long) -@ stdcall RpcBindingSetObject(ptr ptr) -@ stdcall RpcBindingSetOption(ptr long long) -@ stdcall RpcBindingToStringBindingA(ptr ptr) -@ stdcall RpcBindingToStringBindingW(ptr ptr) -@ stdcall RpcBindingVectorFree(ptr) -@ stub RpcCancelAsyncCall -@ stub RpcCancelThread -@ stub RpcCancelThreadEx -@ stub RpcCertGeneratePrincipalNameA -@ stub RpcCertGeneratePrincipalNameW -@ stub RpcCompleteAsyncCall -@ stdcall RpcEpRegisterA(ptr ptr ptr str) -@ stub RpcEpRegisterNoReplaceA -@ stub RpcEpRegisterNoReplaceW -@ stub RpcEpRegisterW -@ stdcall RpcEpResolveBinding(ptr ptr) -@ stdcall RpcEpUnregister(ptr ptr ptr) -@ stub RpcErrorAddRecord # wxp -@ stub RpcErrorClearInformation # wxp -@ stub RpcErrorEndEnumeration # wxp -@ stub RpcErrorGetNextRecord # wxp -@ stub RpcErrorLoadErrorInfo # wxp -@ stub RpcErrorNumberOfRecords # wxp -@ stub RpcErrorResetEnumeration # wxp -@ stub RpcErrorSaveErrorInfo # wxp -@ stub RpcErrorStartEnumeration # wxp -@ stub RpcFreeAuthorizationContext # wxp -@ stub RpcGetAsyncCallStatus -@ stub RpcIfIdVectorFree -@ stub RpcIfInqId -@ stdcall RpcImpersonateClient(ptr) -@ stub RpcInitializeAsyncHandle -@ stub RpcMgmtBindingInqParameter # win9x -@ stub RpcMgmtBindingSetParameter # win9x -@ stdcall RpcMgmtEnableIdleCleanup() -@ stdcall RpcMgmtEpEltInqBegin(ptr long ptr long ptr ptr) -@ stub RpcMgmtEpEltInqDone -@ stub RpcMgmtEpEltInqNextA -@ stub RpcMgmtEpEltInqNextW -@ stub RpcMgmtEpUnregister -@ stub RpcMgmtInqComTimeout -@ stub RpcMgmtInqDefaultProtectLevel -@ stdcall RpcMgmtInqIfIds(ptr ptr) -@ stub RpcMgmtInqParameter # win9x -@ stub RpcMgmtInqServerPrincNameA -@ stub RpcMgmtInqServerPrincNameW -@ stub RpcMgmtInqStats -@ stdcall RpcMgmtIsServerListening(ptr) -@ stub RpcMgmtSetAuthorizationFn -@ stub RpcMgmtSetCancelTimeout -@ stdcall RpcMgmtSetComTimeout(ptr long) -@ stub RpcMgmtSetParameter # win9x -@ stdcall RpcMgmtSetServerStackSize(long) -@ stub RpcMgmtStatsVectorFree -@ stdcall RpcMgmtStopServerListening(ptr) -@ stdcall RpcMgmtWaitServerListen() -@ stub RpcNetworkInqProtseqsA -@ stub RpcNetworkInqProtseqsW -@ stdcall RpcNetworkIsProtseqValidA(ptr) -@ stdcall RpcNetworkIsProtseqValidW(ptr) -@ stub RpcNsBindingInqEntryNameA -@ stub RpcNsBindingInqEntryNameW -@ stub RpcObjectInqType -@ stub RpcObjectSetInqFn -@ stdcall RpcObjectSetType(ptr ptr) -@ stub RpcProtseqVectorFreeA -@ stub RpcProtseqVectorFreeW -@ stdcall RpcRaiseException(long) -@ stub RpcRegisterAsyncInfo -@ stdcall RpcRevertToSelf() -@ stdcall RpcRevertToSelfEx(ptr) -@ stdcall RpcServerInqBindings(ptr) -@ stub RpcServerInqCallAttributesA # wxp -@ stub RpcServerInqCallAttributesW # wxp -@ stub RpcServerInqDefaultPrincNameA -@ stub RpcServerInqDefaultPrincNameW -@ stub RpcServerInqIf -@ stdcall RpcServerListen(long long long) -@ stdcall RpcServerRegisterAuthInfoA(str long ptr ptr) -@ stdcall RpcServerRegisterAuthInfoW(wstr long ptr ptr) -@ stdcall RpcServerRegisterIf2(ptr ptr ptr long long long ptr) -@ stdcall RpcServerRegisterIf(ptr ptr ptr) -@ stdcall RpcServerRegisterIfEx(ptr ptr ptr long long ptr) -@ stub RpcServerTestCancel -@ stdcall RpcServerUnregisterIf(ptr ptr long) -@ stdcall RpcServerUnregisterIfEx(ptr ptr long) -@ stub RpcServerUseAllProtseqs -@ stub RpcServerUseAllProtseqsEx -@ stub RpcServerUseAllProtseqsIf -@ stub RpcServerUseAllProtseqsIfEx -@ stdcall RpcServerUseProtseqA(str long ptr) -@ stdcall RpcServerUseProtseqEpA(str long str ptr) -@ stdcall RpcServerUseProtseqEpExA(str long str ptr ptr) -@ stdcall RpcServerUseProtseqEpExW(wstr long wstr ptr ptr) -@ stdcall RpcServerUseProtseqEpW(wstr long wstr ptr) -@ stub RpcServerUseProtseqExA -@ stub RpcServerUseProtseqExW -@ stub RpcServerUseProtseqIfA -@ stub RpcServerUseProtseqIfExA -@ stub RpcServerUseProtseqIfExW -@ stub RpcServerUseProtseqIfW -@ stdcall RpcServerUseProtseqW(wstr long ptr) -@ stub RpcServerYield -@ stub RpcSmAllocate -@ stub RpcSmClientFree -@ stub RpcSmDestroyClientContext -@ stub RpcSmDisableAllocate -@ stub RpcSmEnableAllocate -@ stub RpcSmFree -@ stub RpcSmGetThreadHandle -@ stub RpcSmSetClientAllocFree -@ stub RpcSmSetThreadHandle -@ stub RpcSmSwapClientAllocFree -@ stub RpcSsAllocate -@ stub RpcSsContextLockExclusive # wxp -@ stub RpcSsContextLockShared # wxp -@ stub RpcSsDestroyClientContext -@ stub RpcSsDisableAllocate -@ stub RpcSsDontSerializeContext -@ stub RpcSsEnableAllocate -@ stub RpcSsFree -@ stub RpcSsGetContextBinding -@ stub RpcSsGetThreadHandle -@ stub RpcSsSetClientAllocFree -@ stub RpcSsSetThreadHandle -@ stub RpcSsSwapClientAllocFree -@ stdcall RpcStringBindingComposeA(str str str str str ptr) -@ stdcall RpcStringBindingComposeW(wstr wstr wstr wstr wstr ptr) -@ stdcall RpcStringBindingParseA(str ptr ptr ptr ptr ptr) -@ stdcall RpcStringBindingParseW(wstr ptr ptr ptr ptr ptr) -@ stdcall RpcStringFreeA(ptr) -@ stdcall RpcStringFreeW(ptr) -@ stub RpcTestCancel -@ stub RpcUserFree # wxp -@ stub SimpleTypeAlignment # wxp -@ stub SimpleTypeBufferSize # wxp -@ stub SimpleTypeMemorySize # wxp -@ stub StartServiceIfNecessary # win9x -@ stdcall TowerConstruct(ptr ptr ptr ptr ptr ptr) -@ stdcall TowerExplode(ptr ptr ptr ptr ptr ptr) -@ stdcall UuidCompare(ptr ptr ptr) -@ stdcall UuidCreate(ptr) -@ stdcall UuidCreateNil(ptr) -@ stdcall UuidCreateSequential(ptr) # win 2000 -@ stdcall UuidEqual(ptr ptr ptr) -@ stdcall UuidFromStringA(str ptr) -@ stdcall UuidFromStringW(wstr ptr) -@ stdcall UuidHash(ptr ptr) -@ stdcall UuidIsNil(ptr ptr) -@ stdcall UuidToStringA(ptr ptr) -@ stdcall UuidToStringW(ptr ptr) -@ stub char_array_from_ndr -@ stub char_from_ndr -@ stub data_from_ndr -@ stub data_into_ndr -@ stub data_size_ndr -@ stub double_array_from_ndr -@ stub double_from_ndr -@ stub enum_from_ndr -@ stub float_array_from_ndr -@ stub float_from_ndr -@ stub long_array_from_ndr -@ stub long_from_ndr -@ stub long_from_ndr_temp -@ stub pfnFreeRoutines # wxp -@ stub pfnMarshallRouteines # wxp -@ stub pfnSizeRoutines # wxp -@ stub pfnUnmarshallRouteines # wxp -@ stub short_array_from_ndr -@ stub short_from_ndr -@ stub short_from_ndr_temp -@ stub tree_into_ndr -@ stub tree_peek_ndr -@ stub tree_size_ndr +@ stdcall CreateProxyFromTypeInfo(ptr ptr ptr ptr ptr) +@ stub CreateStubFromTypeInfo +@ stdcall CStdStubBuffer_AddRef(ptr) +@ stdcall CStdStubBuffer_Connect(ptr ptr) +@ stdcall CStdStubBuffer_CountRefs(ptr) +@ stdcall CStdStubBuffer_DebugServerQueryInterface(ptr ptr) +@ stdcall CStdStubBuffer_DebugServerRelease(ptr ptr) +@ stdcall CStdStubBuffer_Disconnect(ptr) +@ stdcall CStdStubBuffer_Invoke(ptr ptr ptr) +@ stdcall CStdStubBuffer_IsIIDSupported(ptr ptr) +@ stdcall CStdStubBuffer_QueryInterface(ptr ptr ptr) +@ stub CreateServerInterfaceFromStub # wxp +@ stdcall DceErrorInqTextA (long ptr) +@ stdcall DceErrorInqTextW (long ptr) +@ stdcall -private DllRegisterServer() +@ stub GlobalMutexClearExternal +@ stub GlobalMutexRequestExternal +@ stdcall IUnknown_AddRef_Proxy(ptr) +@ stdcall IUnknown_QueryInterface_Proxy(ptr ptr ptr) +@ stdcall IUnknown_Release_Proxy(ptr) +@ stub I_RpcAbortAsyncCall +@ stdcall I_RpcAllocate(long) +@ stub I_RpcAsyncAbortCall +@ stub I_RpcAsyncSendReceive # NT4 +@ stub I_RpcAsyncSetHandle +@ stub I_RpcBCacheAllocate +@ stub I_RpcBCacheFree +@ stub I_RpcBindingCopy +@ stub I_RpcBindingInqConnId +@ stub I_RpcBindingInqDynamicEndPoint +@ stub I_RpcBindingInqDynamicEndPointA +@ stub I_RpcBindingInqDynamicEndPointW +@ stub I_RpcBindingInqLocalClientPID # wxp +@ stub I_RpcBindingInqSecurityContext +@ stub I_RpcBindingInqTransportType +@ stub I_RpcBindingInqWireIdForSnego +@ stub I_RpcBindingIsClientLocal +# 9x version of I_RpcBindingSetAsync has 3 arguments, not 2 +@ stdcall I_RpcBindingSetAsync(ptr ptr) +@ stub I_RpcBindingToStaticStringBindingW +@ stub I_RpcClearMutex +@ stub I_RpcConnectionInqSockBuffSize2 +@ stub I_RpcConnectionInqSockBuffSize +@ stub I_RpcConnectionSetSockBuffSize +@ stub I_RpcDeleteMutex +@ stub I_RpcEnableWmiTrace # wxp +@ stub I_RpcExceptionFilter # wxp +@ stdcall I_RpcFree(ptr) +@ stdcall I_RpcFreeBuffer(ptr) +@ stub I_RpcFreePipeBuffer +@ stub I_RpcGetAssociationContext +@ stdcall I_RpcGetBuffer(ptr) +@ stub I_RpcGetBufferWithObject +@ stdcall I_RpcGetCurrentCallHandle() +@ stub I_RpcGetExtendedError +@ stub I_RpcGetServerContextList +@ stub I_RpcGetThreadEvent # win9x +@ stub I_RpcGetThreadWindowHandle # win9x +@ stub I_RpcIfInqTransferSyntaxes +@ stub I_RpcLaunchDatagramReceiveThread # win9x +@ stub I_RpcLogEvent +@ stdcall I_RpcMapWin32Status(long) +@ stub I_RpcMonitorAssociation +@ stub I_RpcNegotiateTransferSyntax # wxp +@ stub I_RpcNsBindingSetEntryName +@ stub I_RpcNsBindingSetEntryNameA +@ stub I_RpcNsBindingSetEntryNameW +@ stub I_RpcNsInterfaceExported +@ stub I_RpcNsInterfaceUnexported +@ stub I_RpcParseSecurity +@ stub I_RpcPauseExecution +@ stub I_RpcProxyNewConnection # wxp +@ stub I_RpcReallocPipeBuffer +@ stdcall I_RpcReceive(ptr) +@ stub I_RpcRequestMutex +@ stdcall I_RpcSend(ptr) +@ stdcall I_RpcSendReceive(ptr) +@ stub I_RpcServerAllocateIpPort +@ stub I_RpcServerInqAddressChangeFn +@ stub I_RpcServerInqLocalConnAddress # wxp +@ stub I_RpcServerInqTransportType +@ stub I_RpcServerRegisterForwardFunction +@ stub I_RpcServerSetAddressChangeFn +@ stdcall I_RpcServerStartListening(ptr) # win9x +@ stdcall I_RpcServerStopListening() # win9x +@ stub I_RpcServerUnregisterEndpointA # win9x +@ stub I_RpcServerUnregisterEndpointW # win9x +@ stub I_RpcServerUseProtseq2A +@ stub I_RpcServerUseProtseq2W +@ stub I_RpcServerUseProtseqEp2A +@ stub I_RpcServerUseProtseqEp2W +@ stub I_RpcSetAssociationContext # win9x +@ stub I_RpcSetAsyncHandle +@ stub I_RpcSetServerContextList +@ stub I_RpcSetThreadParams # win9x +@ stub I_RpcSetWMsgEndpoint # NT4 +@ stub I_RpcSsDontSerializeContext +@ stub I_RpcStopMonitorAssociation +@ stub I_RpcSystemFunction001 # wxp (oh, brother!) +@ stub I_RpcTransCancelMigration # win9x +@ stub I_RpcTransClientMaxFrag # win9x +@ stub I_RpcTransClientReallocBuffer # win9x +@ stub I_RpcTransConnectionAllocatePacket +@ stub I_RpcTransConnectionFreePacket +@ stub I_RpcTransConnectionReallocPacket +@ stub I_RpcTransDatagramAllocate2 +@ stub I_RpcTransDatagramAllocate +@ stub I_RpcTransDatagramFree +@ stub I_RpcTransGetAddressList +@ stub I_RpcTransGetThreadEvent +@ stub I_RpcTransIoCancelled +@ stub I_RpcTransMaybeMakeReceiveAny # win9x +@ stub I_RpcTransMaybeMakeReceiveDirect # win9x +@ stub I_RpcTransPingServer # win9x +@ stub I_RpcTransServerFindConnection # win9x +@ stub I_RpcTransServerFreeBuffer # win9x +@ stub I_RpcTransServerMaxFrag # win9x +@ stub I_RpcTransServerNewConnection +@ stub I_RpcTransServerProtectThread # win9x +@ stub I_RpcTransServerReallocBuffer # win9x +@ stub I_RpcTransServerReceiveDirectReady # win9x +@ stub I_RpcTransServerUnprotectThread # win9x +@ stub I_RpcTurnOnEEInfoPropagation # wxp +@ stdcall I_RpcWindowProc(ptr long long long) # win9x +@ stub I_RpcltDebugSetPDUFilter +@ stub I_UuidCreate +@ stub MIDL_wchar_strcpy +@ stub MIDL_wchar_strlen +@ stub MesBufferHandleReset +@ stub MesDecodeBufferHandleCreate +@ stub MesDecodeIncrementalHandleCreate +@ stub MesEncodeDynBufferHandleCreate +@ stub MesEncodeFixedBufferHandleCreate +@ stub MesEncodeIncrementalHandleCreate +@ stub MesHandleFree +@ stub MesIncrementalHandleReset +@ stub MesInqProcEncodingId +@ stub MqGetContext # win9x +@ stub MqRegisterQueue # win9x +@ stdcall NDRCContextBinding(ptr) +@ stdcall NDRCContextMarshall(ptr ptr) +@ stdcall NDRCContextUnmarshall(ptr ptr ptr long) +@ stdcall NDRSContextMarshall2(ptr ptr ptr ptr ptr long) +@ stdcall NDRSContextMarshall(ptr ptr ptr) +@ stdcall NDRSContextMarshallEx(ptr ptr ptr ptr) +@ stdcall NDRSContextUnmarshall2(ptr ptr ptr ptr long) +@ stdcall NDRSContextUnmarshall(ptr ptr) +@ stdcall NDRSContextUnmarshallEx(ptr ptr ptr) +@ stub NDRcopy +@ stdcall NdrAllocate(ptr long) +@ stub NdrAsyncClientCall +@ stub NdrAsyncServerCall +@ stdcall NdrByteCountPointerBufferSize(ptr ptr ptr) +@ stdcall NdrByteCountPointerFree(ptr ptr ptr) +@ stdcall NdrByteCountPointerMarshall(ptr ptr ptr) +@ stdcall NdrByteCountPointerUnmarshall(ptr ptr ptr long) +@ stdcall NdrCStdStubBuffer2_Release(ptr ptr) +@ stdcall NdrCStdStubBuffer_Release(ptr ptr) +@ stdcall NdrClearOutParameters(ptr ptr ptr) +@ varargs NdrClientCall2(ptr ptr) +@ varargs NdrClientCall(ptr ptr) NdrClientCall2 +@ stdcall NdrClientContextMarshall(ptr ptr long) +@ stdcall NdrClientContextUnmarshall(ptr ptr ptr) +@ stub NdrClientInitialize +@ stdcall NdrClientInitializeNew(ptr ptr ptr long) +@ stdcall NdrComplexArrayBufferSize(ptr ptr ptr) +@ stdcall NdrComplexArrayFree(ptr ptr ptr) +@ stdcall NdrComplexArrayMarshall(ptr ptr ptr) +@ stdcall NdrComplexArrayMemorySize(ptr ptr) +@ stdcall NdrComplexArrayUnmarshall(ptr ptr ptr long) +@ stdcall NdrComplexStructBufferSize(ptr ptr ptr) +@ stdcall NdrComplexStructFree(ptr ptr ptr) +@ stdcall NdrComplexStructMarshall(ptr ptr ptr) +@ stdcall NdrComplexStructMemorySize(ptr ptr) +@ stdcall NdrComplexStructUnmarshall(ptr ptr ptr long) +@ stdcall NdrConformantArrayBufferSize(ptr ptr ptr) +@ stdcall NdrConformantArrayFree(ptr ptr ptr) +@ stdcall NdrConformantArrayMarshall(ptr ptr ptr) +@ stdcall NdrConformantArrayMemorySize(ptr ptr) +@ stdcall NdrConformantArrayUnmarshall(ptr ptr ptr long) +@ stdcall NdrConformantStringBufferSize(ptr ptr ptr) +@ stdcall NdrConformantStringMarshall(ptr ptr ptr) +@ stdcall NdrConformantStringMemorySize(ptr ptr) +@ stdcall NdrConformantStringUnmarshall(ptr ptr ptr long) +@ stdcall NdrConformantStructBufferSize(ptr ptr ptr) +@ stdcall NdrConformantStructFree(ptr ptr ptr) +@ stdcall NdrConformantStructMarshall(ptr ptr ptr) +@ stdcall NdrConformantStructMemorySize(ptr ptr) +@ stdcall NdrConformantStructUnmarshall(ptr ptr ptr long) +@ stdcall NdrConformantVaryingArrayBufferSize(ptr ptr ptr) +@ stdcall NdrConformantVaryingArrayFree(ptr ptr ptr) +@ stdcall NdrConformantVaryingArrayMarshall(ptr ptr ptr) +@ stdcall NdrConformantVaryingArrayMemorySize(ptr ptr) +@ stdcall NdrConformantVaryingArrayUnmarshall(ptr ptr ptr long) +@ stdcall NdrConformantVaryingStructBufferSize(ptr ptr ptr) +@ stdcall NdrConformantVaryingStructFree(ptr ptr ptr) +@ stdcall NdrConformantVaryingStructMarshall(ptr ptr ptr) +@ stdcall NdrConformantVaryingStructMemorySize(ptr ptr) +@ stdcall NdrConformantVaryingStructUnmarshall(ptr ptr ptr long) +@ stdcall NdrContextHandleInitialize(ptr ptr) +@ stdcall NdrContextHandleSize(ptr ptr ptr) +@ stdcall NdrConvert2(ptr ptr long) +@ stdcall NdrConvert(ptr ptr) +@ stub NdrCorrelationFree +@ stub NdrCorrelationInitialize +@ stub NdrCorrelationPass +@ stub NdrDcomAsyncClientCall +@ stub NdrDcomAsyncStubCall +@ stdcall NdrDllCanUnloadNow(ptr) +@ stdcall NdrDllGetClassObject(ptr ptr ptr ptr ptr ptr) +@ stdcall NdrDllRegisterProxy(long ptr ptr) +@ stdcall NdrDllUnregisterProxy(long ptr ptr) +@ stdcall NdrEncapsulatedUnionBufferSize(ptr ptr ptr) +@ stdcall NdrEncapsulatedUnionFree(ptr ptr ptr) +@ stdcall NdrEncapsulatedUnionMarshall(ptr ptr ptr) +@ stdcall NdrEncapsulatedUnionMemorySize(ptr ptr) +@ stdcall NdrEncapsulatedUnionUnmarshall(ptr ptr ptr long) +@ stdcall NdrFixedArrayBufferSize(ptr ptr ptr) +@ stdcall NdrFixedArrayFree(ptr ptr ptr) +@ stdcall NdrFixedArrayMarshall(ptr ptr ptr) +@ stdcall NdrFixedArrayMemorySize(ptr ptr) +@ stdcall NdrFixedArrayUnmarshall(ptr ptr ptr long) +@ stdcall NdrFreeBuffer(ptr) +@ stdcall NdrFullPointerFree(ptr ptr) +@ stdcall NdrFullPointerInsertRefId(ptr long ptr) +@ stdcall NdrFullPointerQueryPointer(ptr ptr long ptr) +@ stdcall NdrFullPointerQueryRefId(ptr long long ptr) +@ stdcall NdrFullPointerXlatFree(ptr) +@ stdcall NdrFullPointerXlatInit(long long) +@ stdcall NdrGetBuffer(ptr long ptr) +@ stub NdrGetDcomProtocolVersion +@ stub NdrGetPartialBuffer +@ stub NdrGetPipeBuffer +@ stub NdrGetSimpleTypeBufferAlignment # wxp +@ stub NdrGetSimpleTypeBufferSize # wxp +@ stub NdrGetSimpleTypeMemorySize # wxp +@ stub NdrGetTypeFlags # wxp +@ stub NdrGetUserMarshallInfo +@ stub NdrHardStructBufferSize #(ptr ptr ptr) +@ stub NdrHardStructFree #(ptr ptr ptr) +@ stub NdrHardStructMarshall #(ptr ptr ptr) +@ stub NdrHardStructMemorySize #(ptr ptr) +@ stub NdrHardStructUnmarshall #(ptr ptr ptr long) +@ stdcall NdrInterfacePointerBufferSize(ptr ptr ptr) +@ stdcall NdrInterfacePointerFree(ptr ptr ptr) +@ stdcall NdrInterfacePointerMarshall(ptr ptr ptr) +@ stdcall NdrInterfacePointerMemorySize(ptr ptr) +@ stdcall NdrInterfacePointerUnmarshall(ptr ptr ptr long) +@ stub NdrIsAppDoneWithPipes +@ stdcall NdrMapCommAndFaultStatus(ptr ptr ptr long) +@ stub NdrMarkNextActivePipe +@ stub NdrMesProcEncodeDecode2 +@ stub NdrMesProcEncodeDecode +@ stub NdrMesSimpleTypeAlignSize +@ stub NdrMesSimpleTypeDecode +@ stub NdrMesSimpleTypeEncode +@ stub NdrMesTypeAlignSize2 +@ stub NdrMesTypeAlignSize +@ stub NdrMesTypeDecode2 +@ stub NdrMesTypeDecode +@ stub NdrMesTypeEncode2 +@ stub NdrMesTypeEncode +@ stub NdrMesTypeFree2 +@ stdcall NdrNonConformantStringBufferSize(ptr ptr ptr) +@ stdcall NdrNonConformantStringMarshall(ptr ptr ptr) +@ stdcall NdrNonConformantStringMemorySize(ptr ptr) +@ stdcall NdrNonConformantStringUnmarshall(ptr ptr ptr long) +@ stdcall NdrNonEncapsulatedUnionBufferSize(ptr ptr ptr) +@ stdcall NdrNonEncapsulatedUnionFree(ptr ptr ptr) +@ stdcall NdrNonEncapsulatedUnionMarshall(ptr ptr ptr) +@ stdcall NdrNonEncapsulatedUnionMemorySize(ptr ptr) +@ stdcall NdrNonEncapsulatedUnionUnmarshall(ptr ptr ptr long) +@ stub NdrNsGetBuffer +@ stub NdrNsSendReceive +@ stdcall NdrOleAllocate(long) +@ stdcall NdrOleFree(ptr) +@ stub NdrOutInit # wxp +@ stub NdrPartialIgnoreClientBufferSize # wxp +@ stub NdrPartialIgnoreClientMarshall # wxp +@ stub NdrPartialIgnoreServerInitialize # wxp +@ stub NdrPartialIgnoreServerUnmarshall # wxp +@ stub NdrPipePull +@ stub NdrPipePush +@ stub NdrPipeSendReceive +@ stub NdrPipesDone +@ stub NdrPipesInitialize +@ stdcall NdrPointerBufferSize(ptr ptr ptr) +@ stdcall NdrPointerFree(ptr ptr ptr) +@ stdcall NdrPointerMarshall(ptr ptr ptr) +@ stdcall NdrPointerMemorySize(ptr ptr) +@ stdcall NdrPointerUnmarshall(ptr ptr ptr long) +@ stdcall NdrProxyErrorHandler(long) +@ stdcall NdrProxyFreeBuffer(ptr ptr) +@ stdcall NdrProxyGetBuffer(ptr ptr) +@ stdcall NdrProxyInitialize(ptr ptr ptr ptr long) +@ stdcall NdrProxySendReceive(ptr ptr) +@ stdcall NdrRangeUnmarshall(ptr ptr ptr long) +@ stub NdrRpcSmClientAllocate +@ stub NdrRpcSmClientFree +@ stub NdrRpcSmSetClientToOsf +@ stub NdrRpcSsDefaultAllocate +@ stub NdrRpcSsDefaultFree +@ stub NdrRpcSsDisableAllocate +@ stub NdrRpcSsEnableAllocate +@ stdcall NdrSendReceive(ptr ptr) +@ stdcall NdrServerCall2(ptr) +@ stub NdrServerCall +@ stdcall NdrServerContextMarshall(ptr ptr long) +@ stdcall NdrServerContextNewMarshall(ptr ptr ptr ptr) # wxp +@ stdcall NdrServerContextNewUnmarshall(ptr ptr) # wxp +@ stdcall NdrServerContextUnmarshall(ptr) +@ stub NdrServerInitialize +@ stub NdrServerInitializeMarshall +@ stdcall NdrServerInitializeNew(ptr ptr ptr) +@ stub NdrServerInitializePartial # wxp +@ stub NdrServerInitializeUnmarshall +@ stub NdrServerMarshall +@ stub NdrServerUnmarshall +@ stdcall NdrSimpleStructBufferSize(ptr ptr ptr) +@ stdcall NdrSimpleStructFree(ptr ptr ptr) +@ stdcall NdrSimpleStructMarshall(ptr ptr ptr) +@ stdcall NdrSimpleStructMemorySize(ptr ptr) +@ stdcall NdrSimpleStructUnmarshall(ptr ptr ptr long) +@ stdcall NdrSimpleTypeMarshall(ptr ptr long) +@ stdcall NdrSimpleTypeUnmarshall(ptr ptr long) +@ stdcall NdrStubCall2(ptr ptr ptr ptr) +@ stub NdrStubCall +@ stdcall NdrStubForwardingFunction(ptr ptr ptr ptr) +@ stdcall NdrStubGetBuffer(ptr ptr ptr) +@ stdcall NdrStubInitialize(ptr ptr ptr ptr) +@ stub NdrStubInitializeMarshall +@ stub NdrTypeFlags # wxp +@ stub NdrTypeFree # wxp +@ stub NdrTypeMarshall # wxp +@ stub NdrTypeSize # wxp +@ stub NdrTypeUnmarshall # wxp +@ stub NdrUnmarshallBasetypeInline # wxp +@ stdcall NdrUserMarshalBufferSize(ptr ptr ptr) +@ stdcall NdrUserMarshalFree(ptr ptr ptr) +@ stdcall NdrUserMarshalMarshall(ptr ptr ptr) +@ stdcall NdrUserMarshalMemorySize(ptr ptr) +@ stub NdrUserMarshalSimpleTypeConvert +@ stdcall NdrUserMarshalUnmarshall(ptr ptr ptr long) +@ stdcall NdrVaryingArrayBufferSize(ptr ptr ptr) +@ stdcall NdrVaryingArrayFree(ptr ptr ptr) +@ stdcall NdrVaryingArrayMarshall(ptr ptr ptr) +@ stdcall NdrVaryingArrayMemorySize(ptr ptr) +@ stdcall NdrVaryingArrayUnmarshall(ptr ptr ptr long) +@ stdcall NdrXmitOrRepAsBufferSize(ptr ptr ptr) +@ stdcall NdrXmitOrRepAsFree(ptr ptr ptr) +@ stdcall NdrXmitOrRepAsMarshall(ptr ptr ptr) +@ stdcall NdrXmitOrRepAsMemorySize(ptr ptr) +@ stdcall NdrXmitOrRepAsUnmarshall(ptr ptr ptr long) +@ stub NdrpCreateProxy # wxp +@ stub NdrpCreateStub # wxp +@ stub NdrpGetProcFormatString # wxp +@ stub NdrpGetTypeFormatString # wxp +@ stub NdrpGetTypeGenCookie # wxp +@ stub NdrpMemoryIncrement # wxp +@ stub NdrpReleaseTypeFormatString # wxp +@ stub NdrpReleaseTypeGenCookie # wxp +@ stub NdrpSetRpcSsDefaults +@ stub NdrpVarVtOfTypeDesc # wxp +@ stub PerformRpcInitialization +@ stub RpcAbortAsyncCall +@ stub RpcAsyncAbortCall +@ stub RpcAsyncCancelCall +@ stub RpcAsyncCompleteCall +@ stub RpcAsyncGetCallStatus +@ stub RpcAsyncInitializeHandle +@ stub RpcAsyncRegisterInfo +@ stdcall RpcBindingCopy(ptr ptr) +@ stdcall RpcBindingFree(ptr) +@ stdcall RpcBindingFromStringBindingA(str ptr) +@ stdcall RpcBindingFromStringBindingW(wstr ptr) +@ stub RpcBindingInqAuthClientA +@ stub RpcBindingInqAuthClientExA +@ stub RpcBindingInqAuthClientExW +@ stub RpcBindingInqAuthClientW +@ stdcall RpcBindingInqAuthInfoA(ptr ptr ptr ptr ptr ptr) +@ stdcall RpcBindingInqAuthInfoExA(ptr ptr ptr ptr ptr ptr long ptr) +@ stdcall RpcBindingInqAuthInfoExW(ptr ptr ptr ptr ptr ptr long ptr) +@ stdcall RpcBindingInqAuthInfoW(ptr ptr ptr ptr ptr ptr) +@ stdcall RpcBindingInqObject(ptr ptr) +@ stub RpcBindingInqOption +@ stub RpcBindingReset +@ stub RpcBindingServerFromClient +@ stdcall RpcBindingSetAuthInfoA(ptr str long long ptr long) +@ stdcall RpcBindingSetAuthInfoExA(ptr str long long ptr long ptr) +@ stdcall RpcBindingSetAuthInfoExW(ptr wstr long long ptr long ptr) +@ stdcall RpcBindingSetAuthInfoW(ptr wstr long long ptr long) +@ stdcall RpcBindingSetObject(ptr ptr) +@ stdcall RpcBindingSetOption(ptr long long) +@ stdcall RpcBindingToStringBindingA(ptr ptr) +@ stdcall RpcBindingToStringBindingW(ptr ptr) +@ stdcall RpcBindingVectorFree(ptr) +@ stub RpcCancelAsyncCall +@ stdcall RpcCancelThread(ptr) +@ stub RpcCancelThreadEx +@ stub RpcCertGeneratePrincipalNameA +@ stub RpcCertGeneratePrincipalNameW +@ stub RpcCompleteAsyncCall +@ stdcall RpcEpRegisterA(ptr ptr ptr str) +@ stub RpcEpRegisterNoReplaceA +@ stub RpcEpRegisterNoReplaceW +@ stub RpcEpRegisterW +@ stdcall RpcEpResolveBinding(ptr ptr) +@ stdcall RpcEpUnregister(ptr ptr ptr) +@ stub RpcErrorAddRecord # wxp +@ stub RpcErrorClearInformation # wxp +@ stub RpcErrorEndEnumeration # wxp +@ stub RpcErrorGetNextRecord # wxp +@ stub RpcErrorLoadErrorInfo # wxp +@ stub RpcErrorNumberOfRecords # wxp +@ stub RpcErrorResetEnumeration # wxp +@ stub RpcErrorSaveErrorInfo # wxp +@ stdcall RpcErrorStartEnumeration(ptr) +@ stub RpcFreeAuthorizationContext # wxp +@ stub RpcGetAsyncCallStatus +@ stub RpcIfIdVectorFree +@ stub RpcIfInqId +@ stdcall RpcImpersonateClient(ptr) +@ stub RpcInitializeAsyncHandle +@ stub RpcMgmtBindingInqParameter # win9x +@ stub RpcMgmtBindingSetParameter # win9x +@ stdcall RpcMgmtEnableIdleCleanup() +@ stdcall RpcMgmtEpEltInqBegin(ptr long ptr long ptr ptr) +@ stub RpcMgmtEpEltInqDone +@ stub RpcMgmtEpEltInqNextA +@ stub RpcMgmtEpEltInqNextW +@ stub RpcMgmtEpUnregister +@ stub RpcMgmtInqComTimeout +@ stub RpcMgmtInqDefaultProtectLevel +@ stdcall RpcMgmtInqIfIds(ptr ptr) +@ stub RpcMgmtInqParameter # win9x +@ stub RpcMgmtInqServerPrincNameA +@ stub RpcMgmtInqServerPrincNameW +@ stub RpcMgmtInqStats +@ stdcall RpcMgmtIsServerListening(ptr) +@ stub RpcMgmtSetAuthorizationFn +@ stdcall RpcMgmtSetCancelTimeout(long) +@ stdcall RpcMgmtSetComTimeout(ptr long) +@ stub RpcMgmtSetParameter # win9x +@ stdcall RpcMgmtSetServerStackSize(long) +@ stub RpcMgmtStatsVectorFree +@ stdcall RpcMgmtStopServerListening(ptr) +@ stdcall RpcMgmtWaitServerListen() +@ stub RpcNetworkInqProtseqsA +@ stub RpcNetworkInqProtseqsW +@ stdcall RpcNetworkIsProtseqValidA(ptr) +@ stdcall RpcNetworkIsProtseqValidW(ptr) +@ stub RpcNsBindingInqEntryNameA +@ stub RpcNsBindingInqEntryNameW +@ stub RpcObjectInqType +@ stub RpcObjectSetInqFn +@ stdcall RpcObjectSetType(ptr ptr) +@ stub RpcProtseqVectorFreeA +@ stub RpcProtseqVectorFreeW +@ stdcall RpcRaiseException(long) +@ stub RpcRegisterAsyncInfo +@ stdcall RpcRevertToSelf() +@ stdcall RpcRevertToSelfEx(ptr) +@ stdcall RpcServerInqBindings(ptr) +@ stub RpcServerInqCallAttributesA # wxp +@ stub RpcServerInqCallAttributesW # wxp +@ stub RpcServerInqDefaultPrincNameA +@ stub RpcServerInqDefaultPrincNameW +@ stub RpcServerInqIf +@ stdcall RpcServerListen(long long long) +@ stdcall RpcServerRegisterAuthInfoA(str long ptr ptr) +@ stdcall RpcServerRegisterAuthInfoW(wstr long ptr ptr) +@ stdcall RpcServerRegisterIf2(ptr ptr ptr long long long ptr) +@ stdcall RpcServerRegisterIf(ptr ptr ptr) +@ stdcall RpcServerRegisterIfEx(ptr ptr ptr long long ptr) +@ stub RpcServerTestCancel +@ stdcall RpcServerUnregisterIf(ptr ptr long) +@ stdcall RpcServerUnregisterIfEx(ptr ptr long) +@ stub RpcServerUseAllProtseqs +@ stub RpcServerUseAllProtseqsEx +@ stub RpcServerUseAllProtseqsIf +@ stub RpcServerUseAllProtseqsIfEx +@ stdcall RpcServerUseProtseqA(str long ptr) +@ stdcall RpcServerUseProtseqEpA(str long str ptr) +@ stdcall RpcServerUseProtseqEpExA(str long str ptr ptr) +@ stdcall RpcServerUseProtseqEpExW(wstr long wstr ptr ptr) +@ stdcall RpcServerUseProtseqEpW(wstr long wstr ptr) +@ stub RpcServerUseProtseqExA +@ stub RpcServerUseProtseqExW +@ stub RpcServerUseProtseqIfA +@ stub RpcServerUseProtseqIfExA +@ stub RpcServerUseProtseqIfExW +@ stub RpcServerUseProtseqIfW +@ stdcall RpcServerUseProtseqW(wstr long ptr) +@ stub RpcServerYield +@ stub RpcSmAllocate +@ stub RpcSmClientFree +@ stdcall RpcSmDestroyClientContext(ptr) +@ stub RpcSmDisableAllocate +@ stub RpcSmEnableAllocate +@ stub RpcSmFree +@ stub RpcSmGetThreadHandle +@ stub RpcSmSetClientAllocFree +@ stub RpcSmSetThreadHandle +@ stub RpcSmSwapClientAllocFree +@ stub RpcSsAllocate +@ stub RpcSsContextLockExclusive # wxp +@ stub RpcSsContextLockShared # wxp +@ stdcall RpcSsDestroyClientContext(ptr) +@ stub RpcSsDisableAllocate +@ stub RpcSsDontSerializeContext +@ stub RpcSsEnableAllocate +@ stub RpcSsFree +@ stub RpcSsGetContextBinding +@ stub RpcSsGetThreadHandle +@ stub RpcSsSetClientAllocFree +@ stub RpcSsSetThreadHandle +@ stub RpcSsSwapClientAllocFree +@ stdcall RpcStringBindingComposeA(str str str str str ptr) +@ stdcall RpcStringBindingComposeW(wstr wstr wstr wstr wstr ptr) +@ stdcall RpcStringBindingParseA(str ptr ptr ptr ptr ptr) +@ stdcall RpcStringBindingParseW(wstr ptr ptr ptr ptr ptr) +@ stdcall RpcStringFreeA(ptr) +@ stdcall RpcStringFreeW(ptr) +@ stub RpcTestCancel +@ stub RpcUserFree # wxp +@ stub SimpleTypeAlignment # wxp +@ stub SimpleTypeBufferSize # wxp +@ stub SimpleTypeMemorySize # wxp +@ stub StartServiceIfNecessary # win9x +@ stdcall TowerConstruct(ptr ptr ptr ptr ptr ptr) +@ stdcall TowerExplode(ptr ptr ptr ptr ptr ptr) +@ stdcall UuidCompare(ptr ptr ptr) +@ stdcall UuidCreate(ptr) +@ stdcall UuidCreateNil(ptr) +@ stdcall UuidCreateSequential(ptr) # win 2000 +@ stdcall UuidEqual(ptr ptr ptr) +@ stdcall UuidFromStringA(str ptr) +@ stdcall UuidFromStringW(wstr ptr) +@ stdcall UuidHash(ptr ptr) +@ stdcall UuidIsNil(ptr ptr) +@ stdcall UuidToStringA(ptr ptr) +@ stdcall UuidToStringW(ptr ptr) +@ stub char_array_from_ndr +@ stub char_from_ndr +@ stub data_from_ndr +@ stub data_into_ndr +@ stub data_size_ndr +@ stub double_array_from_ndr +@ stub double_from_ndr +@ stub enum_from_ndr +@ stub float_array_from_ndr +@ stub float_from_ndr +@ stub long_array_from_ndr +@ stub long_from_ndr +@ stub long_from_ndr_temp +@ stub pfnFreeRoutines # wxp +@ stub pfnMarshallRouteines # wxp +@ stub pfnSizeRoutines # wxp +@ stub pfnUnmarshallRouteines # wxp +@ stub short_array_from_ndr +@ stub short_from_ndr +@ stub short_from_ndr_temp +@ stub tree_into_ndr +@ stub tree_peek_ndr +@ stub tree_size_ndr diff --git a/reactos/dll/win32/rpcrt4_new/rpcrt4_main.c b/reactos/dll/win32/rpcrt4_new/rpcrt4_main.c index 8b97ff4e1f4..8ce6db906e9 100644 --- a/reactos/dll/win32/rpcrt4_new/rpcrt4_main.c +++ b/reactos/dll/win32/rpcrt4_new/rpcrt4_main.c @@ -16,7 +16,7 @@ * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - * + * * WINE RPC TODO's (and a few TODONT's) * * - Ove's decreasingly incomplete widl is an IDL compiler for wine. For widl @@ -45,11 +45,11 @@ * * - Some transports are not yet implemented. The existing transport implementations * are incomplete and may be bug-infested. - * + * * - The various transports that we do support ought to be supported in a more * object-oriented manner, as in DCE's RPC implementation, instead of cluttering * up the code with conditionals like we do now. - * + * * - Data marshalling: So far, only the beginnings of a full implementation * exist in wine. NDR protocol itself is documented, but the MS API's to * convert data-types in memory into NDR are not. This is challenging work, @@ -59,7 +59,7 @@ * use it to implement out-of-process OLE client/server communications. * ATM there is maybe a disconnect between the marshalling in the OLE DLLs * and the marshalling going on here [TODO: well, is there or not?] - * + * * - In-source API Documentation, at least for those functions which we have * implemented, but preferably for everything we can document, would be nice, * since some of this stuff is quite obscure. @@ -100,6 +100,8 @@ #include "winerror.h" #include "winbase.h" #include "winuser.h" +#include "winnt.h" +#include "winternl.h" #include "iptypes.h" #include "iphlpapi.h" #include "wine/unicode.h" @@ -133,6 +135,33 @@ static CRITICAL_SECTION_DEBUG critsect_debug = }; static CRITICAL_SECTION uuid_cs = { &critsect_debug, -1, 0, 0, 0, 0 }; +static CRITICAL_SECTION threaddata_cs; +static CRITICAL_SECTION_DEBUG threaddata_cs_debug = +{ + 0, 0, &threaddata_cs, + { &threaddata_cs_debug.ProcessLocksList, &threaddata_cs_debug.ProcessLocksList }, + 0, 0, { (DWORD_PTR)(__FILE__ ": threaddata_cs") } +}; +static CRITICAL_SECTION threaddata_cs = { &threaddata_cs_debug, -1, 0, 0, 0, 0 }; + +struct list threaddata_list = LIST_INIT(threaddata_list); + +struct context_handle_list +{ + struct context_handle_list *next; + NDR_SCONTEXT context_handle; +}; + +struct threaddata +{ + struct list entry; + CRITICAL_SECTION cs; + DWORD thread_id; + RpcConnection *connection; + RpcBinding *server_binding; + struct context_handle_list *context_handle_list; +}; + /*********************************************************************** * DllMain * @@ -148,14 +177,32 @@ static CRITICAL_SECTION uuid_cs = { &critsect_debug, -1, 0, 0, 0, 0 }; BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { + struct threaddata *tdata; + switch (fdwReason) { case DLL_PROCESS_ATTACH: - DisableThreadLibraryCalls(hinstDLL); master_mutex = CreateMutexA( NULL, FALSE, RPCSS_MASTER_MUTEX_NAME); if (!master_mutex) ERR("Failed to create master mutex\n"); break; + case DLL_THREAD_DETACH: + tdata = NtCurrentTeb()->ReservedForNtRpc; + if (tdata) + { + EnterCriticalSection(&threaddata_cs); + list_remove(&tdata->entry); + LeaveCriticalSection(&threaddata_cs); + + DeleteCriticalSection(&tdata->cs); + if (tdata->connection) + ERR("tdata->connection should be NULL but is still set to %p\n", tdata->connection); + if (tdata->server_binding) + ERR("tdata->server_binding should be NULL but is still set to %p\n", tdata->server_binding); + HeapFree(GetProcessHeap(), 0, tdata); + } + break; + case DLL_PROCESS_DETACH: CloseHandle(master_mutex); master_mutex = NULL; @@ -202,10 +249,12 @@ RPC_STATUS WINAPI RpcStringFreeW(RPC_WSTR* String) * * Raises an exception. */ -void WINAPI RpcRaiseException(RPC_STATUS exception) +void DECLSPEC_NORETURN WINAPI RpcRaiseException(RPC_STATUS exception) { - /* FIXME: translate exception? */ + /* shouldn't return */ RaiseException(exception, 0, 0, NULL); + ERR("handler continued execution\n"); + ExitProcess(1); } /************************************************************************* @@ -215,7 +264,7 @@ void WINAPI RpcRaiseException(RPC_STATUS exception) * UUID *Uuid1 [I] Uuid to compare * UUID *Uuid2 [I] Uuid to compare * RPC_STATUS *Status [O] returns RPC_S_OK - * + * * RETURNS * -1 if Uuid1 is less than Uuid2 * 0 if Uuid1 and Uuid2 are equal @@ -321,7 +370,7 @@ static void RPC_UuidGetSystemTime(ULONGLONG *time) *time += TICKS_15_OCT_1582_TO_1601; } -/* Assume that a hardware address is at least 6 bytes long */ +/* Assume that a hardware address is at least 6 bytes long */ #define ADDRESS_BYTES_NEEDED 6 static RPC_STATUS RPC_UuidGetNodeAddress(BYTE *address) @@ -368,9 +417,9 @@ static RPC_STATUS RPC_UuidGetNodeAddress(BYTE *address) * RPC_S_UUID_LOCAL_ONLY if UUID is only locally unique. * * FIXME: No compensation for changes across reloading - * this dll or across reboots (e.g. clock going + * this dll or across reboots (e.g. clock going * backwards and swapped network cards). The RFC - * suggests using NVRAM for storing persistent + * suggests using NVRAM for storing persistent * values. */ RPC_STATUS WINAPI UuidCreate(UUID *Uuid) @@ -693,11 +742,11 @@ static BOOL RPCRT4_StartRPCSS(void) /*********************************************************************** * RPCRT4_RPCSSOnDemandCall (internal) - * + * * Attempts to send a message to the RPCSS process * on the local machine, invoking it if necessary. * For remote RPCSS calls, use.... your imagination. - * + * * PARAMS * msg [I] pointer to the RPCSS message * vardata_payload [I] pointer vardata portion of the RPCSS message @@ -728,7 +777,7 @@ BOOL RPCRT4_RPCSSOnDemandCall(PRPCSS_NP_MESSAGE msg, char *vardata_payload, PRPC Sleep(200); client_handle = RPCRT4_RpcssNPConnect(); if (INVALID_HANDLE_VALUE != client_handle) break; - } + } /* we are only willing to try twice */ if (j++ >= 1) break; } @@ -823,8 +872,154 @@ void WINAPI I_RpcFree(void *Object) /****************************************************************************** * I_RpcMapWin32Status (rpcrt4.@) */ -DWORD WINAPI I_RpcMapWin32Status(RPC_STATUS status) +LONG WINAPI I_RpcMapWin32Status(RPC_STATUS status) { FIXME("(%ld): stub\n", status); return 0; } + +/****************************************************************************** + * RpcErrorStartEnumeration (rpcrt4.@) + */ +RPC_STATUS RPC_ENTRY RpcErrorStartEnumeration(RPC_ERROR_ENUM_HANDLE* EnumHandle) +{ + FIXME("(%p): stub\n", EnumHandle); + return RPC_S_ENTRY_NOT_FOUND; +} + +/****************************************************************************** + * RpcMgmtSetCancelTimeout (rpcrt4.@) + */ +RPC_STATUS RPC_ENTRY RpcMgmtSetCancelTimeout(LONG Timeout) +{ + FIXME("(%d): stub\n", Timeout); + return RPC_S_OK; +} + +static struct threaddata *get_or_create_threaddata(void) +{ + struct threaddata *tdata = NtCurrentTeb()->ReservedForNtRpc; + if (!tdata) + { + tdata = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*tdata)); + if (!tdata) return NULL; + + InitializeCriticalSection(&tdata->cs); + tdata->thread_id = GetCurrentThreadId(); + + EnterCriticalSection(&threaddata_cs); + list_add_tail(&threaddata_list, &tdata->entry); + LeaveCriticalSection(&threaddata_cs); + + NtCurrentTeb()->ReservedForNtRpc = tdata; + return tdata; + } + return tdata; +} + +void RPCRT4_SetThreadCurrentConnection(RpcConnection *Connection) +{ + struct threaddata *tdata = get_or_create_threaddata(); + if (!tdata) return; + + EnterCriticalSection(&tdata->cs); + tdata->connection = Connection; + LeaveCriticalSection(&tdata->cs); +} + +void RPCRT4_SetThreadCurrentCallHandle(RpcBinding *Binding) +{ + struct threaddata *tdata = get_or_create_threaddata(); + if (!tdata) return; + + tdata->server_binding = Binding; +} + +RpcBinding *RPCRT4_GetThreadCurrentCallHandle(void) +{ + struct threaddata *tdata = get_or_create_threaddata(); + if (!tdata) return NULL; + + return tdata->server_binding; +} + +void RPCRT4_PushThreadContextHandle(NDR_SCONTEXT SContext) +{ + struct threaddata *tdata = get_or_create_threaddata(); + struct context_handle_list *context_handle_list; + + if (!tdata) return; + + context_handle_list = HeapAlloc(GetProcessHeap(), 0, sizeof(*context_handle_list)); + if (!context_handle_list) return; + + context_handle_list->context_handle = SContext; + context_handle_list->next = tdata->context_handle_list; + tdata->context_handle_list = context_handle_list; +} + +void RPCRT4_RemoveThreadContextHandle(NDR_SCONTEXT SContext) +{ + struct threaddata *tdata = get_or_create_threaddata(); + struct context_handle_list *current, *prev; + + if (!tdata) return; + + for (current = tdata->context_handle_list, prev = NULL; current; prev = current, current = current->next) + { + if (current->context_handle == SContext) + { + if (prev) + prev->next = current->next; + else + tdata->context_handle_list = current->next; + HeapFree(GetProcessHeap(), 0, current); + return; + } + } +} + +NDR_SCONTEXT RPCRT4_PopThreadContextHandle(void) +{ + struct threaddata *tdata = get_or_create_threaddata(); + struct context_handle_list *context_handle_list; + NDR_SCONTEXT context_handle; + + if (!tdata) return NULL; + + context_handle_list = tdata->context_handle_list; + if (!context_handle_list) return NULL; + tdata->context_handle_list = context_handle_list->next; + + context_handle = context_handle_list->context_handle; + HeapFree(GetProcessHeap(), 0, context_handle_list); + return context_handle; +} + +/****************************************************************************** + * RpcCancelThread (rpcrt4.@) + */ +RPC_STATUS RPC_ENTRY RpcCancelThread(void* ThreadHandle) +{ + DWORD target_tid; + struct threaddata *tdata; + + TRACE("(%p)\n", ThreadHandle); + + target_tid = GetThreadId(ThreadHandle); + if (!target_tid) + return RPC_S_INVALID_ARG; + + EnterCriticalSection(&threaddata_cs); + LIST_FOR_EACH_ENTRY(tdata, &threaddata_list, struct threaddata, entry) + if (tdata->thread_id == target_tid) + { + EnterCriticalSection(&tdata->cs); + if (tdata->connection) rpcrt4_conn_cancel_call(tdata->connection); + LeaveCriticalSection(&tdata->cs); + break; + } + LeaveCriticalSection(&threaddata_cs); + + return RPC_S_OK; +} diff --git a/reactos/dll/win32/rpcrt4_new/rpcss_np_client.c b/reactos/dll/win32/rpcrt4_new/rpcss_np_client.c index f2ed65d00bf..f18fd56e03d 100644 --- a/reactos/dll/win32/rpcrt4_new/rpcss_np_client.c +++ b/reactos/dll/win32/rpcrt4_new/rpcss_np_client.c @@ -35,19 +35,19 @@ HANDLE RPCRT4_RpcssNPConnect(void) HANDLE the_pipe; DWORD dwmode, wait_result; HANDLE master_mutex = RPCRT4_GetMasterMutex(); - + TRACE("\n"); while (TRUE) { wait_result = WaitForSingleObject(master_mutex, MASTER_MUTEX_TIMEOUT); switch (wait_result) { - case WAIT_ABANDONED: + case WAIT_ABANDONED: case WAIT_OBJECT_0: break; case WAIT_FAILED: case WAIT_TIMEOUT: - default: + default: ERR("This should never happen: couldn't enter mutex.\n"); return NULL; } @@ -67,13 +67,13 @@ HANDLE RPCRT4_RpcssNPConnect(void) break; if (GetLastError() != ERROR_PIPE_BUSY) { - WARN("Unable to open named pipe %s (assuming unavailable).\n", + WARN("Unable to open named pipe %s (assuming unavailable).\n", debugstr_a(NAME_RPCSS_NAMED_PIPE)); break; } WARN("Named pipe busy (will wait)\n"); - + if (!ReleaseMutex(master_mutex)) ERR("Failed to release master mutex. Expect deadlock.\n"); @@ -122,7 +122,7 @@ BOOL RPCRT4_SendReceiveNPMsg(HANDLE np, PRPCSS_NP_MESSAGE msg, char *vardata, PR /* process the vardata payload if necessary */ vardata_payload_msg.message_type = RPCSS_NP_MESSAGE_TYPEID_VARDATAPAYLOADMSG; vardata_payload_msg.vardata_payload_size = 0; /* meaningless */ - for ( payload_offset = 0; payload_offset < msg->vardata_payload_size; + for ( payload_offset = 0; payload_offset < msg->vardata_payload_size; payload_offset += VARDATA_PAYLOAD_BYTES ) { TRACE("sending vardata payload. vd=%p, po=%d, ps=%d\n", vardata, payload_offset, msg->vardata_payload_size); @@ -136,7 +136,7 @@ BOOL RPCRT4_SendReceiveNPMsg(HANDLE np, PRPCSS_NP_MESSAGE msg, char *vardata, PR return FALSE; } } - + if (! ReadFile(np, reply, sizeof(RPCSS_NP_REPLY), &count, NULL)) { ERR("read failed.\n"); return FALSE;