- Update rpcrt4 to Wine-20080105, so it corresponds to the WIDL. Local changes applied.

svn path=/trunk/; revision=31631
This commit is contained in:
Aleksey Bragin 2008-01-06 16:18:31 +00:00
parent 07dce281aa
commit ecdee48d72
26 changed files with 12518 additions and 11057 deletions

View file

@ -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;

View file

@ -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(&current_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(&current_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;
}

View file

@ -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

View file

@ -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

View file

@ -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 <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#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 <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#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;
}

View file

@ -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;
}

View file

@ -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 <stdarg.h>
#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 <stdarg.h>
#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;
}

File diff suppressed because it is too large Load diff

View file

@ -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 <stdarg.h>
#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 <stdarg.h>
#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 */

View file

@ -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 <stdarg.h>
#include <stdio.h>
#include <string.h>
#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 <stdarg.h>
#include <stdio.h>
#include <string.h>
#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;
}

File diff suppressed because it is too large Load diff

View file

@ -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"

View file

@ -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 <stdarg.h>
#include <assert.h>
#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;
}

View file

@ -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);

View file

@ -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);

View file

@ -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

View file

@ -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]

View file

@ -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);
}

View file

@ -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;

View file

@ -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);

View file

@ -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();
}

File diff suppressed because it is too large Load diff

View file

@ -23,11 +23,13 @@
<file>cproxy.c</file>
<file>cpsf.c</file>
<file>cstub.c</file>
<file>ndr_contexthandle.c</file>
<file>ndr_clientserver.c</file>
<file>ndr_fullpointer.c</file>
<file>ndr_marshall.c</file>
<file>ndr_ole.c</file>
<file>ndr_stubless.c</file>
<file>rpc_assoc.c</file>
<file>rpc_binding.c</file>
<file>rpc_epmap.c</file>
<file>rpc_message.c</file>

File diff suppressed because it is too large Load diff

View file

@ -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;
}

View file

@ -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;