- 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

@ -41,7 +41,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole);
static WINE_EXCEPTION_FILTER(stub_filter) static WINE_EXCEPTION_FILTER(stub_filter)
{ {
if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION) if (GetExceptionInformation()->ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE)
return EXCEPTION_CONTINUE_SEARCH; return EXCEPTION_CONTINUE_SEARCH;
return EXCEPTION_EXECUTE_HANDLER; return EXCEPTION_EXECUTE_HANDLER;
} }
@ -109,13 +109,15 @@ static CRITICAL_SECTION delegating_vtbl_section = { &critsect_debug, -1, 0, 0, 0
typedef struct typedef struct
{ {
DWORD ref; DWORD ref;
DWORD size;
void **methods;
IUnknownVtbl vtbl; IUnknownVtbl vtbl;
/* remaining entries in vtbl */
} ref_counted_vtbl; } ref_counted_vtbl;
static struct static struct
{ {
ref_counted_vtbl *table; ref_counted_vtbl *table;
DWORD size;
} current_vtbl; } current_vtbl;
@ -156,7 +158,7 @@ typedef struct {
} vtbl_method_t; } vtbl_method_t;
#include "poppack.h" #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; vtbl_method_t *method;
void **entry; void **entry;
@ -166,7 +168,7 @@ static void fill_table(IUnknownVtbl *vtbl, DWORD num)
vtbl->AddRef = delegating_AddRef; vtbl->AddRef = delegating_AddRef;
vtbl->Release = delegating_Release; vtbl->Release = delegating_Release;
method = (vtbl_method_t*)((void **)vtbl + num); method = (vtbl_method_t*)methods;
entry = (void**)(vtbl + 1); entry = (void**)(vtbl + 1);
for(i = 3; i < num; i++) for(i = 3; i < num; i++)
@ -209,19 +211,25 @@ void create_delegating_vtbl(DWORD num_methods)
} }
EnterCriticalSection(&delegating_vtbl_section); EnterCriticalSection(&delegating_vtbl_section);
if(num_methods > current_vtbl.size) if(!current_vtbl.table || num_methods > current_vtbl.table->size)
{ {
DWORD size; DWORD size;
DWORD old_protect;
if(current_vtbl.table && current_vtbl.table->ref == 0) if(current_vtbl.table && current_vtbl.table->ref == 0)
{ {
TRACE("freeing old table\n"); 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); HeapFree(GetProcessHeap(), 0, current_vtbl.table);
} }
size = sizeof(DWORD) + num_methods * sizeof(void*) + (num_methods - 3) * sizeof(vtbl_method_t); size = (num_methods - 3) * sizeof(vtbl_method_t);
current_vtbl.table = HeapAlloc(GetProcessHeap(), 0, size); current_vtbl.table = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(ref_counted_vtbl, vtbl) + num_methods * sizeof(void*));
fill_table(&current_vtbl.table->vtbl, num_methods);
current_vtbl.table->ref = 0; 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); LeaveCriticalSection(&delegating_vtbl_section);
} }
@ -247,6 +255,9 @@ static void release_delegating_vtbl(IUnknownVtbl *vtbl)
if(table->ref == 0 && table != current_vtbl.table) if(table->ref == 0 && table != current_vtbl.table)
{ {
TRACE("... and we're not current so free'ing\n"); 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); HeapFree(GetProcessHeap(), 0, table);
} }
LeaveCriticalSection(&delegating_vtbl_section); LeaveCriticalSection(&delegating_vtbl_section);
@ -558,6 +569,9 @@ void WINAPI NdrStubInitialize(PRPC_MESSAGE pRpcMsg,
TRACE("(%p,%p,%p,%p)\n", pRpcMsg, pStubMsg, pStubDescriptor, pRpcChannelBuffer); TRACE("(%p,%p,%p,%p)\n", pRpcMsg, pStubMsg, pStubDescriptor, pRpcChannelBuffer);
NdrServerInitializeNew(pRpcMsg, pStubMsg, pStubDescriptor); NdrServerInitializeNew(pRpcMsg, pStubMsg, pStubDescriptor);
pStubMsg->pRpcChannelBuffer = pRpcChannelBuffer; pStubMsg->pRpcChannelBuffer = pRpcChannelBuffer;
IRpcChannelBuffer_GetDestCtx(pStubMsg->pRpcChannelBuffer,
&pStubMsg->dwDestContext,
&pStubMsg->pvDestContext);
} }
/*********************************************************************** /***********************************************************************
@ -581,7 +595,5 @@ void WINAPI NdrStubGetBuffer(LPRPCSTUBBUFFER iface,
return; return;
} }
pStubMsg->BufferStart = pStubMsg->RpcMsg->Buffer; pStubMsg->Buffer = pStubMsg->RpcMsg->Buffer;
pStubMsg->BufferEnd = pStubMsg->BufferStart + pStubMsg->BufferLength;
pStubMsg->Buffer = pStubMsg->BufferStart;
} }

View file

@ -53,8 +53,6 @@ void WINAPI NdrClientInitializeNew( PRPC_MESSAGE pRpcMessage, PMIDL_STUB_MESSAGE
TRACE("(pRpcMessage == ^%p, pStubMsg == ^%p, pStubDesc == ^%p, ProcNum == %d)\n", TRACE("(pRpcMessage == ^%p, pStubMsg == ^%p, pStubDesc == ^%p, ProcNum == %d)\n",
pRpcMessage, pStubMsg, pStubDesc, ProcNum); pRpcMessage, pStubMsg, pStubDesc, ProcNum);
assert( pRpcMessage && pStubMsg && pStubDesc );
pRpcMessage->Handle = NULL; pRpcMessage->Handle = NULL;
pRpcMessage->ProcNum = ProcNum; pRpcMessage->ProcNum = ProcNum;
pRpcMessage->RpcInterfaceInformation = pStubDesc->RpcInterfaceInformation; pRpcMessage->RpcInterfaceInformation = pStubDesc->RpcInterfaceInformation;
@ -106,22 +104,42 @@ unsigned char* WINAPI NdrServerInitializeNew( PRPC_MESSAGE pRpcMsg, PMIDL_STUB_M
{ {
TRACE("(pRpcMsg == ^%p, pStubMsg == ^%p, pStubDesc == ^%p)\n", pRpcMsg, pStubMsg, 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->RpcMsg = pRpcMsg;
pStubMsg->Buffer = pStubMsg->BufferStart = pRpcMsg->Buffer; pStubMsg->Buffer = pStubMsg->BufferStart = pRpcMsg->Buffer;
pStubMsg->BufferEnd = pStubMsg->Buffer + pRpcMsg->BufferLength;
pStubMsg->BufferLength = pRpcMsg->BufferLength; pStubMsg->BufferLength = pRpcMsg->BufferLength;
pStubMsg->BufferEnd = pStubMsg->Buffer + pStubMsg->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;
/* FIXME: determine the proper return value */
return NULL; return NULL;
} }
@ -130,31 +148,33 @@ unsigned char* WINAPI NdrServerInitializeNew( PRPC_MESSAGE pRpcMsg, PMIDL_STUB_M
*/ */
unsigned char *WINAPI NdrGetBuffer(PMIDL_STUB_MESSAGE stubmsg, ULONG buflen, RPC_BINDING_HANDLE handle) 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); RPC_STATUS status;
assert( stubmsg && stubmsg->RpcMsg ); TRACE("(stubmsg == ^%p, buflen == %u, handle == %p)\n", stubmsg, buflen, handle);
/* I guess this is our chance to put the binding handle into the RPC_MESSAGE */
stubmsg->RpcMsg->Handle = handle; stubmsg->RpcMsg->Handle = handle;
stubmsg->RpcMsg->BufferLength = buflen; stubmsg->RpcMsg->BufferLength = buflen;
if (I_RpcGetBuffer(stubmsg->RpcMsg) != S_OK)
return NULL;
stubmsg->Buffer = stubmsg->BufferStart = stubmsg->RpcMsg->Buffer; 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; stubmsg->BufferLength = stubmsg->RpcMsg->BufferLength;
stubmsg->BufferEnd = stubmsg->Buffer + stubmsg->BufferLength; return stubmsg->Buffer;
return (stubmsg->Buffer = (unsigned char *)stubmsg->RpcMsg->Buffer);
} }
/*********************************************************************** /***********************************************************************
* NdrFreeBuffer [RPCRT4.@] * NdrFreeBuffer [RPCRT4.@]
*/ */
void WINAPI NdrFreeBuffer(PMIDL_STUB_MESSAGE pStubMsg) void WINAPI NdrFreeBuffer(PMIDL_STUB_MESSAGE pStubMsg)
{ {
TRACE("(pStubMsg == ^%p): wild guess.\n", pStubMsg); TRACE("(pStubMsg == ^%p)\n", pStubMsg);
if (pStubMsg->fBufferValid)
{
I_RpcFreeBuffer(pStubMsg->RpcMsg); I_RpcFreeBuffer(pStubMsg->RpcMsg);
pStubMsg->BufferLength = 0; pStubMsg->fBufferValid = FALSE;
pStubMsg->Buffer = pStubMsg->BufferEnd = (unsigned char *)(pStubMsg->RpcMsg->Buffer = NULL); }
} }
/************************************************************************ /************************************************************************

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

@ -63,8 +63,14 @@ PFULL_PTR_XLAT_TABLES WINAPI NdrFullPointerXlatInit(ULONG NumberOfPointers,
void WINAPI NdrFullPointerXlatFree(PFULL_PTR_XLAT_TABLES pXlatTables) void WINAPI NdrFullPointerXlatFree(PFULL_PTR_XLAT_TABLES pXlatTables)
{ {
ULONG i;
TRACE("(%p)\n", pXlatTables); 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.XlatTable);
HeapFree(GetProcessHeap(), 0, pXlatTables->RefIdToPointer.StateTable); HeapFree(GetProcessHeap(), 0, pXlatTables->RefIdToPointer.StateTable);
HeapFree(GetProcessHeap(), 0, pXlatTables->PointerToRefId.XlatTable); HeapFree(GetProcessHeap(), 0, pXlatTables->PointerToRefId.XlatTable);

File diff suppressed because it is too large Load diff

View file

@ -82,7 +82,7 @@ typedef struct RpcStreamImpl
DWORD RefCount; DWORD RefCount;
PMIDL_STUB_MESSAGE pMsg; PMIDL_STUB_MESSAGE pMsg;
LPDWORD size; LPDWORD size;
char *data; unsigned char *data;
DWORD pos; DWORD pos;
} RpcStreamImpl; } RpcStreamImpl;
@ -145,7 +145,7 @@ static HRESULT WINAPI RpcStream_Write(LPSTREAM iface,
ULONG *pcbWritten) ULONG *pcbWritten)
{ {
RpcStreamImpl *This = (RpcStreamImpl *)iface; RpcStreamImpl *This = (RpcStreamImpl *)iface;
if (This->data + cb > (char *)This->pMsg->BufferEnd) if (This->data + cb > (unsigned char *)This->pMsg->RpcMsg->Buffer + This->pMsg->BufferLength)
return STG_E_MEDIUMFULL; return STG_E_MEDIUMFULL;
memcpy(This->data + This->pos, pv, cb); memcpy(This->data + This->pos, pv, cb);
This->pos += cb; This->pos += cb;
@ -215,7 +215,7 @@ static LPSTREAM RpcStream_Create(PMIDL_STUB_MESSAGE pStubMsg, BOOL init)
This->RefCount = 1; This->RefCount = 1;
This->pMsg = pStubMsg; This->pMsg = pStubMsg;
This->size = (LPDWORD)pStubMsg->Buffer; This->size = (LPDWORD)pStubMsg->Buffer;
This->data = (char*)(This->size + 1); This->data = (unsigned char*)(This->size + 1);
This->pos = 0; This->pos = 0;
if (init) *This->size = 0; if (init) *This->size = 0;
TRACE("init size=%d\n", *This->size); TRACE("init size=%d\n", *This->size);

View file

@ -42,8 +42,9 @@
#include "wine/debug.h" #include "wine/debug.h"
#include "wine/rpcfc.h" #include "wine/rpcfc.h"
#include "ndr_misc.h"
#include "cpsf.h" #include "cpsf.h"
#include "ndr_misc.h"
#include "ndr_stubless.h"
WINE_DEFAULT_DEBUG_CHANNEL(rpc); WINE_DEFAULT_DEBUG_CHANNEL(rpc);
@ -113,9 +114,6 @@ static inline unsigned long call_memory_sizer(PMIDL_STUB_MESSAGE pStubMsg, PFORM
} }
} }
/* there can't be any alignment with the structures in this file */
#include "pshpack1.h"
#define STUBLESS_UNMARSHAL 1 #define STUBLESS_UNMARSHAL 1
#define STUBLESS_CALLSERVER 2 #define STUBLESS_CALLSERVER 2
#define STUBLESS_CALCSIZE 3 #define STUBLESS_CALCSIZE 3
@ -123,220 +121,6 @@ static inline unsigned long call_memory_sizer(PMIDL_STUB_MESSAGE pStubMsg, PFORM
#define STUBLESS_MARSHAL 5 #define STUBLESS_MARSHAL 5
#define STUBLESS_FREE 6 #define STUBLESS_FREE 6
/* From http://msdn.microsoft.com/library/default.asp?url=/library/en-us/rpc/rpc/parameter_descriptors.asp */
typedef struct _NDR_PROC_HEADER
{
/* type of handle to use:
* RPC_FC_BIND_EXPLICIT = 0 - Explicit handle.
* Handle is passed as a parameter to the function.
* Indicates that explicit handle information follows the header,
* which actually describes the handle.
* RPC_FC_BIND_GENERIC = 31 - Implicit handle with custom binding routines
* (MIDL_STUB_DESC::IMPLICIT_HANDLE_INFO::pGenericBindingInfo)
* RPC_FC_BIND_PRIMITIVE = 32 - Implicit handle using handle_t created by
* calling application
* RPC_FC_AUTO_HANDLE = 33 - Automatic handle
* RPC_FC_CALLBACK_HANDLE = 34 - undocmented
*/
unsigned char handle_type;
/* procedure flags:
* Oi_FULL_PTR_USED = 0x01 - A full pointer can have the value NULL and can
* change during the call from NULL to non-NULL and supports aliasing
* and cycles. Indicates that the NdrFullPointerXlatInit function
* should be called.
* Oi_RPCSS_ALLOC_USED = 0x02 - Use RpcSS allocate/free routines instead of
* normal allocate/free routines
* Oi_OBJECT_PROC = 0x04 - Indicates a procedure that is part of an OLE
* interface, rather than a DCE RPC interface.
* Oi_HAS_RPCFLAGS = 0x08 - Indicates that the rpc_flags element is
* present in the header.
* Oi_HAS_COMM_OR_FAULT = 0x20 - If Oi_OBJECT_PROC not present only then
* indicates that the procedure has the comm_status or fault_status
* MIDL attribute.
* Oi_OBJ_USE_V2_INTERPRETER = 0x20 - If Oi_OBJECT_PROC present only
* then indicates that the format string is in -Oif or -Oicf format
* Oi_USE_NEW_INIT_ROUTINES = 0x40 - Use NdrXInitializeNew instead of
* NdrXInitialize?
*/
unsigned char Oi_flags;
/* the zero-based index of the procedure */
unsigned short proc_num;
/* total size of all parameters on the stack, including any "this"
* pointer and/or return value */
unsigned short stack_size;
} NDR_PROC_HEADER;
/* same as above struct except additional element rpc_flags */
typedef struct _NDR_PROC_HEADER_RPC
{
unsigned char handle_type;
unsigned char Oi_flags;
/*
* RPCF_Idempotent = 0x0001 - [idempotent] MIDL attribute
* RPCF_Broadcast = 0x0002 - [broadcast] MIDL attribute
* RPCF_Maybe = 0x0004 - [maybe] MIDL attribute
* Reserved = 0x0008 - 0x0080
* RPCF_Message = 0x0100 - [message] MIDL attribute
* Reserved = 0x0200 - 0x1000
* RPCF_InputSynchronous = 0x2000 - unknown
* RPCF_Asynchronous = 0x4000 - [async] MIDL attribute
* Reserved = 0x8000
*/
unsigned long rpc_flags;
unsigned short proc_num;
unsigned short stack_size;
} NDR_PROC_HEADER_RPC;
typedef struct _NDR_PROC_PARTIAL_OIF_HEADER
{
/* the pre-computed client buffer size so that interpreter can skip all
* or some (if the flag RPC_FC_PROC_OI2F_CLTMUSTSIZE is specified) of the
* sizing pass */
unsigned short constant_client_buffer_size;
/* the pre-computed server buffer size so that interpreter can skip all
* or some (if the flag RPC_FC_PROC_OI2F_SRVMUSTSIZE is specified) of the
* sizing pass */
unsigned short constant_server_buffer_size;
INTERPRETER_OPT_FLAGS Oi2Flags;
/* number of params */
unsigned char number_of_params;
} NDR_PROC_PARTIAL_OIF_HEADER;
typedef struct _NDR_PARAM_OI_BASETYPE
{
/* parameter direction. One of:
* FC_IN_PARAM_BASETYPE = 0x4e - an in param
* FC_RETURN_PARAM_BASETYPE = 0x53 - a return param
*/
unsigned char param_direction;
/* One of: FC_BYTE,FC_CHAR,FC_SMALL,FC_USMALL,FC_WCHAR,FC_SHORT,FC_USHORT,
* FC_LONG,FC_ULONG,FC_FLOAT,FC_HYPER,FC_DOUBLE,FC_ENUM16,FC_ENUM32,
* FC_ERROR_STATUS_T,FC_INT3264,FC_UINT3264 */
unsigned char type_format_char;
} NDR_PARAM_OI_BASETYPE;
typedef struct _NDR_PARAM_OI_OTHER
{
/* One of:
* FC_IN_PARAM = 0x4d - An in param
* FC_IN_OUT_PARAM = 0x50 - An in/out param
* FC_OUT_PARAM = 0x51 - An out param
* FC_RETURN_PARAM = 0x52 - A return value
* FC_IN_PARAM_NO_FREE_INST = 0x4f - A param for which no freeing is done
*/
unsigned char param_direction;
/* Size of param on stack in NUMBERS OF INTS */
unsigned char stack_size;
/* offset in the type format string table */
unsigned short type_offset;
} NDR_PARAM_OI_OTHER;
typedef struct _NDR_PARAM_OIF_BASETYPE
{
PARAM_ATTRIBUTES param_attributes;
/* the offset on the calling stack where the parameter is located */
unsigned short stack_offset;
/* see NDR_PARAM_OI_BASETYPE::type_format_char */
unsigned char type_format_char;
/* always FC_PAD */
unsigned char unused;
} NDR_PARAM_OIF_BASETYPE;
typedef struct _NDR_PARAM_OIF_OTHER
{
PARAM_ATTRIBUTES param_attributes;
/* see NDR_PARAM_OIF_BASETYPE::stack_offset */
unsigned short stack_offset;
/* offset into the provided type format string where the type for this
* parameter starts */
unsigned short type_offset;
} NDR_PARAM_OIF_OTHER;
/* explicit handle description for FC_BIND_PRIMITIVE type */
typedef struct _NDR_EHD_PRIMITIVE
{
/* FC_BIND_PRIMITIVE */
unsigned char handle_type;
/* is the handle passed in via a pointer? */
unsigned char flag;
/* offset from the beginning of the stack to the handle in bytes */
unsigned short offset;
} NDR_EHD_PRIMITIVE;
/* explicit handle description for FC_BIND_GENERIC type */
typedef struct _NDR_EHD_GENERIC
{
/* FC_BIND_GENERIC */
unsigned char handle_type;
/* upper 4bits is a flag indicating whether the handle is passed in
* via a pointer. lower 4bits is the size of the user defined generic
* handle type. the size must be less than or equal to the machine
* register size */
unsigned char flag_and_size;
/* offset from the beginning of the stack to the handle in bytes */
unsigned short offset;
/* the index into the aGenericBindingRoutinesPairs field of MIDL_STUB_DESC
* giving the bind and unbind routines for the handle */
unsigned char binding_routine_pair_index;
/* FC_PAD */
unsigned char unused;
} NDR_EHD_GENERIC;
/* explicit handle description for FC_BIND_CONTEXT type */
typedef struct _NDR_EHD_CONTEXT
{
/* FC_BIND_CONTEXT */
unsigned char handle_type;
/* Any of the following flags:
* NDR_CONTEXT_HANDLE_CANNOT_BE_NULL = 0x01
* NDR_CONTEXT_HANDLE_SERIALIZE = 0x02
* NDR_CONTEXT_HANDLE_NO_SERIALIZE = 0x04
* NDR_STRICT_CONTEXT_HANDLE = 0x08
* HANDLE_PARAM_IS_OUT = 0x20
* HANDLE_PARAM_IS_RETURN = 0x21
* HANDLE_PARAM_IS_IN = 0x40
* HANDLE_PARAM_IS_VIA_PTR = 0x80
*/
unsigned char flags;
/* offset from the beginning of the stack to the handle in bytes */
unsigned short offset;
/* zero-based index on rundown routine in apfnNdrRundownRoutines field
* of MIDL_STUB_DESC */
unsigned char context_rundown_routine_index;
/* varies depending on NDR version used.
* V1: zero-based index into parameters
* V2: zero-based index into handles that are parameters */
unsigned char param_num;
} NDR_EHD_CONTEXT;
#include "poppack.h"
void WINAPI NdrRpcSmSetClientToOsf(PMIDL_STUB_MESSAGE pMessage) void WINAPI NdrRpcSmSetClientToOsf(PMIDL_STUB_MESSAGE pMessage)
{ {
#if 0 /* these functions are not defined yet */ #if 0 /* these functions are not defined yet */
@ -1075,7 +859,313 @@ static DWORD calc_arg_size(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat)
return size; return size;
} }
/* FIXME: need to free some stuff in here too */ static LONG_PTR *stub_do_args(MIDL_STUB_MESSAGE *pStubMsg,
PFORMAT_STRING pFormat, int phase,
unsigned char *args,
unsigned short number_of_params)
{
/* counter */
unsigned short i;
/* current format string offset */
int current_offset = 0;
/* current stack offset */
unsigned short current_stack_offset = 0;
/* location to put retval into */
LONG_PTR *retval_ptr = NULL;
for (i = 0; i < number_of_params; i++)
{
const NDR_PARAM_OIF_BASETYPE *pParam =
(const NDR_PARAM_OIF_BASETYPE *)&pFormat[current_offset];
unsigned char *pArg;
current_stack_offset = pParam->stack_offset;
pArg = (unsigned char *)(args+current_stack_offset);
TRACE("param[%d]: new format\n", i);
TRACE("\tparam_attributes:"); dump_RPC_FC_PROC_PF(pParam->param_attributes); TRACE("\n");
TRACE("\tstack_offset: 0x%x\n", current_stack_offset);
TRACE("\tmemory addr (before): %p -> %p\n", pArg, *(unsigned char **)pArg);
if (pParam->param_attributes.IsBasetype)
{
const unsigned char *pTypeFormat =
&pParam->type_format_char;
TRACE("\tbase type: 0x%02x\n", *pTypeFormat);
switch (phase)
{
case STUBLESS_MARSHAL:
if (pParam->param_attributes.IsOut || pParam->param_attributes.IsReturn)
{
if (pParam->param_attributes.IsSimpleRef)
call_marshaller(pStubMsg, *(unsigned char **)pArg, pTypeFormat);
else
call_marshaller(pStubMsg, pArg, pTypeFormat);
}
break;
case STUBLESS_FREE:
if (pParam->param_attributes.ServerAllocSize)
HeapFree(GetProcessHeap(), 0, *(void **)pArg);
break;
case STUBLESS_UNMARSHAL:
if (pParam->param_attributes.ServerAllocSize)
*(void **)pArg = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
pParam->param_attributes.ServerAllocSize * 8);
if (pParam->param_attributes.IsIn)
{
if (pParam->param_attributes.IsSimpleRef)
call_unmarshaller(pStubMsg, (unsigned char **)pArg, pTypeFormat, 0);
else
call_unmarshaller(pStubMsg, &pArg, pTypeFormat, 0);
}
/* make a note of the address of the return value parameter for later */
if (pParam->param_attributes.IsReturn)
retval_ptr = (LONG_PTR *)pArg;
break;
case STUBLESS_CALCSIZE:
if (pParam->param_attributes.IsOut || pParam->param_attributes.IsReturn)
{
if (pParam->param_attributes.IsSimpleRef)
call_buffer_sizer(pStubMsg, *(unsigned char **)pArg, pTypeFormat);
else
call_buffer_sizer(pStubMsg, pArg, pTypeFormat);
}
break;
default:
RpcRaiseException(RPC_S_INTERNAL_ERROR);
}
current_offset += sizeof(NDR_PARAM_OIF_BASETYPE);
}
else
{
const NDR_PARAM_OIF_OTHER *pParamOther =
(const NDR_PARAM_OIF_OTHER *)&pFormat[current_offset];
const unsigned char * pTypeFormat =
&(pStubMsg->StubDesc->pFormatTypes[pParamOther->type_offset]);
TRACE("\tcomplex type 0x%02x\n", *pTypeFormat);
switch (phase)
{
case STUBLESS_MARSHAL:
if (pParam->param_attributes.IsOut || pParam->param_attributes.IsReturn)
{
if (pParam->param_attributes.IsByValue)
call_marshaller(pStubMsg, pArg, pTypeFormat);
else
call_marshaller(pStubMsg, *(unsigned char **)pArg, pTypeFormat);
}
break;
case STUBLESS_FREE:
if (pParam->param_attributes.MustFree)
{
if (pParam->param_attributes.IsByValue)
call_freer(pStubMsg, pArg, pTypeFormat);
else
call_freer(pStubMsg, *(unsigned char **)pArg, pTypeFormat);
}
if (pParam->param_attributes.IsOut &&
!pParam->param_attributes.IsIn &&
!pParam->param_attributes.IsByValue &&
!pParam->param_attributes.ServerAllocSize)
{
pStubMsg->pfnFree(*(void **)pArg);
}
if (pParam->param_attributes.ServerAllocSize)
HeapFree(GetProcessHeap(), 0, *(void **)pArg);
/* FIXME: call call_freer here for IN types with MustFree set */
break;
case STUBLESS_UNMARSHAL:
if (pParam->param_attributes.ServerAllocSize)
*(void **)pArg = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
pParam->param_attributes.ServerAllocSize * 8);
if (pParam->param_attributes.IsIn)
{
if (pParam->param_attributes.IsByValue)
call_unmarshaller(pStubMsg, &pArg, pTypeFormat, 0);
else
call_unmarshaller(pStubMsg, (unsigned char **)pArg, pTypeFormat, 0);
}
else if (pParam->param_attributes.IsOut &&
!pParam->param_attributes.ServerAllocSize &&
!pParam->param_attributes.IsByValue)
{
DWORD size = calc_arg_size(pStubMsg, pTypeFormat);
if(size)
{
*(void **)pArg = NdrAllocate(pStubMsg, size);
memset(*(void **)pArg, 0, size);
}
}
break;
case STUBLESS_CALCSIZE:
if (pParam->param_attributes.IsOut || pParam->param_attributes.IsReturn)
{
if (pParam->param_attributes.IsByValue)
call_buffer_sizer(pStubMsg, pArg, pTypeFormat);
else
call_buffer_sizer(pStubMsg, *(unsigned char **)pArg, pTypeFormat);
}
break;
default:
RpcRaiseException(RPC_S_INTERNAL_ERROR);
}
current_offset += sizeof(NDR_PARAM_OIF_OTHER);
}
TRACE("\tmemory addr (after): %p -> %p\n", pArg, *(unsigned char **)pArg);
}
return retval_ptr;
}
static LONG_PTR *stub_do_old_args(MIDL_STUB_MESSAGE *pStubMsg,
PFORMAT_STRING pFormat, int phase,
unsigned char *args,
unsigned short stack_size, BOOL object)
{
/* counter */
unsigned short i;
/* current format string offset */
int current_offset = 0;
/* current stack offset */
unsigned short current_stack_offset = 0;
/* location to put retval into */
LONG_PTR *retval_ptr = NULL;
for (i = 0; TRUE; i++)
{
const NDR_PARAM_OI_BASETYPE *pParam =
(const NDR_PARAM_OI_BASETYPE *)&pFormat[current_offset];
/* note: current_stack_offset starts after the This pointer
* if present, so adjust this */
unsigned short current_stack_offset_adjusted = current_stack_offset +
(object ? sizeof(void *) : 0);
unsigned char *pArg = (unsigned char *)(args+current_stack_offset_adjusted);
/* no more parameters; exit loop */
if (current_stack_offset_adjusted >= stack_size)
break;
TRACE("param[%d]: old format\n", i);
TRACE("\tparam_direction: 0x%x\n", pParam->param_direction);
TRACE("\tstack_offset: 0x%x\n", current_stack_offset_adjusted);
if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE ||
pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE)
{
const unsigned char *pTypeFormat =
&pParam->type_format_char;
TRACE("\tbase type 0x%02x\n", *pTypeFormat);
switch (phase)
{
case STUBLESS_MARSHAL:
if (pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE)
call_marshaller(pStubMsg, pArg, pTypeFormat);
break;
case STUBLESS_FREE:
if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE)
call_freer(pStubMsg, pArg, pTypeFormat);
break;
case STUBLESS_UNMARSHAL:
if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE)
call_unmarshaller(pStubMsg, &pArg, pTypeFormat, 0);
else if (pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE)
retval_ptr = (LONG_PTR *)pArg;
break;
case STUBLESS_CALCSIZE:
if (pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE)
call_buffer_sizer(pStubMsg, pArg, pTypeFormat);
break;
default:
RpcRaiseException(RPC_S_INTERNAL_ERROR);
}
current_stack_offset += call_memory_sizer(pStubMsg, pTypeFormat);
current_offset += sizeof(NDR_PARAM_OI_BASETYPE);
}
else
{
const NDR_PARAM_OI_OTHER *pParamOther =
(const NDR_PARAM_OI_OTHER *)&pFormat[current_offset];
const unsigned char * pTypeFormat =
&pStubMsg->StubDesc->pFormatTypes[pParamOther->type_offset];
TRACE("\tcomplex type 0x%02x\n", *pTypeFormat);
switch (phase)
{
case STUBLESS_MARSHAL:
if (pParam->param_direction == RPC_FC_OUT_PARAM ||
pParam->param_direction == RPC_FC_IN_OUT_PARAM ||
pParam->param_direction == RPC_FC_RETURN_PARAM)
call_marshaller(pStubMsg, *(unsigned char **)pArg, pTypeFormat);
break;
case STUBLESS_FREE:
if (pParam->param_direction == RPC_FC_IN_OUT_PARAM ||
pParam->param_direction == RPC_FC_IN_PARAM)
call_freer(pStubMsg, *(unsigned char **)pArg, pTypeFormat);
else if (pParam->param_direction == RPC_FC_OUT_PARAM)
pStubMsg->pfnFree(*(void **)pArg);
break;
case STUBLESS_UNMARSHAL:
if (pParam->param_direction == RPC_FC_IN_OUT_PARAM ||
pParam->param_direction == RPC_FC_IN_PARAM)
call_unmarshaller(pStubMsg, (unsigned char **)pArg, pTypeFormat, 0);
else if (pParam->param_direction == RPC_FC_RETURN_PARAM)
retval_ptr = (LONG_PTR *)pArg;
else if (pParam->param_direction == RPC_FC_OUT_PARAM)
{
DWORD size = calc_arg_size(pStubMsg, pTypeFormat);
if(size)
{
*(void **)pArg = NdrAllocate(pStubMsg, size);
memset(*(void **)pArg, 0, size);
}
}
break;
case STUBLESS_CALCSIZE:
if (pParam->param_direction == RPC_FC_OUT_PARAM ||
pParam->param_direction == RPC_FC_IN_OUT_PARAM ||
pParam->param_direction == RPC_FC_RETURN_PARAM)
call_buffer_sizer(pStubMsg, *(unsigned char **)pArg, pTypeFormat);
break;
default:
RpcRaiseException(RPC_S_INTERNAL_ERROR);
}
current_stack_offset += pParamOther->stack_size * sizeof(INT);
current_offset += sizeof(NDR_PARAM_OI_OTHER);
}
}
return retval_ptr;
}
/***********************************************************************
* NdrStubCall2 [RPCRT4.@]
*
* Unmarshals [in] parameters, calls either a method in an object or a server
* function, marshals any [out] parameters and frees any allocated data.
*
* NOTES
* Used by stubless MIDL-generated code.
*/
LONG WINAPI NdrStubCall2( LONG WINAPI NdrStubCall2(
struct IRpcStubBuffer * pThis, struct IRpcStubBuffer * pThis,
struct IRpcChannelBuffer * pChannel, struct IRpcChannelBuffer * pChannel,
@ -1090,12 +1180,8 @@ LONG WINAPI NdrStubCall2(
unsigned char * args; unsigned char * args;
/* size of stack */ /* size of stack */
unsigned short stack_size; unsigned short stack_size;
/* current stack offset */
unsigned short current_stack_offset;
/* number of parameters. optional for client to give it to us */ /* number of parameters. optional for client to give it to us */
unsigned char number_of_params = ~0; unsigned char number_of_params = ~0;
/* counter */
unsigned short i;
/* cache of Oif_flags from v2 procedure header */ /* cache of Oif_flags from v2 procedure header */
INTERPRETER_OPT_FLAGS Oif_flags = { 0 }; INTERPRETER_OPT_FLAGS Oif_flags = { 0 };
/* cache of extension flags from NDR_PROC_HEADER_EXTS */ /* cache of extension flags from NDR_PROC_HEADER_EXTS */
@ -1318,278 +1404,13 @@ LONG WINAPI NdrStubCall2(
case STUBLESS_UNMARSHAL: case STUBLESS_UNMARSHAL:
case STUBLESS_CALCSIZE: case STUBLESS_CALCSIZE:
case STUBLESS_FREE: case STUBLESS_FREE:
current_offset = parameter_start_offset; if (bV2Format)
current_stack_offset = 0; retval_ptr = stub_do_args(&stubMsg, &pFormat[parameter_start_offset],
phase, args, number_of_params);
/* NOTE: V1 style format does't terminate on the number_of_params
* condition as it doesn't have this attribute. Instead it
* terminates when the stack size given in the header is exceeded.
*/
for (i = 0; i < number_of_params; i++)
{
if (bV2Format) /* new parameter format */
{
const NDR_PARAM_OIF_BASETYPE *pParam =
(const NDR_PARAM_OIF_BASETYPE *)&pFormat[current_offset];
unsigned char *pArg;
current_stack_offset = pParam->stack_offset;
pArg = (unsigned char *)(args+current_stack_offset);
TRACE("param[%d]: new format\n", i);
TRACE("\tparam_attributes:"); dump_RPC_FC_PROC_PF(pParam->param_attributes); TRACE("\n");
TRACE("\tstack_offset: 0x%x\n", current_stack_offset);
TRACE("\tmemory addr (before): %p -> %p\n", pArg, *(unsigned char **)pArg);
if (pParam->param_attributes.IsBasetype)
{
const unsigned char *pTypeFormat =
&pParam->type_format_char;
TRACE("\tbase type: 0x%02x\n", *pTypeFormat);
switch (phase)
{
case STUBLESS_MARSHAL:
if (pParam->param_attributes.IsOut || pParam->param_attributes.IsReturn)
{
if (pParam->param_attributes.IsSimpleRef)
call_marshaller(&stubMsg, *(unsigned char **)pArg, pTypeFormat);
else else
call_marshaller(&stubMsg, pArg, pTypeFormat); retval_ptr = stub_do_old_args(&stubMsg, &pFormat[parameter_start_offset],
} phase, args, stack_size,
break; (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT));
case STUBLESS_FREE:
if (pParam->param_attributes.ServerAllocSize)
HeapFree(GetProcessHeap(), 0, *(void **)pArg);
break;
case STUBLESS_UNMARSHAL:
if (pParam->param_attributes.ServerAllocSize)
*(void **)pArg = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
pParam->param_attributes.ServerAllocSize * 8);
if (pParam->param_attributes.IsIn)
{
if (pParam->param_attributes.IsSimpleRef)
call_unmarshaller(&stubMsg, (unsigned char **)pArg, pTypeFormat, 0);
else
call_unmarshaller(&stubMsg, &pArg, pTypeFormat, 0);
}
/* make a note of the address of the return value parameter for later */
if (pParam->param_attributes.IsReturn)
retval_ptr = (LONG_PTR *)pArg;
break;
case STUBLESS_CALCSIZE:
if (pParam->param_attributes.IsOut || pParam->param_attributes.IsReturn)
{
if (pParam->param_attributes.IsSimpleRef)
call_buffer_sizer(&stubMsg, *(unsigned char **)pArg, pTypeFormat);
else
call_buffer_sizer(&stubMsg, pArg, pTypeFormat);
}
break;
default:
RpcRaiseException(RPC_S_INTERNAL_ERROR);
}
current_offset += sizeof(NDR_PARAM_OIF_BASETYPE);
}
else
{
const NDR_PARAM_OIF_OTHER *pParamOther =
(const NDR_PARAM_OIF_OTHER *)&pFormat[current_offset];
const unsigned char * pTypeFormat =
&(pStubDesc->pFormatTypes[pParamOther->type_offset]);
TRACE("\tcomplex type 0x%02x\n", *pTypeFormat);
switch (phase)
{
case STUBLESS_MARSHAL:
if (pParam->param_attributes.IsOut || pParam->param_attributes.IsReturn)
{
if (pParam->param_attributes.IsByValue)
call_marshaller(&stubMsg, pArg, pTypeFormat);
else
call_marshaller(&stubMsg, *(unsigned char **)pArg, pTypeFormat);
}
break;
case STUBLESS_FREE:
if (pParam->param_attributes.MustFree)
{
if (pParam->param_attributes.IsByValue)
call_freer(&stubMsg, pArg, pTypeFormat);
else
call_freer(&stubMsg, *(unsigned char **)pArg, pTypeFormat);
}
if (pParam->param_attributes.IsOut &&
!pParam->param_attributes.IsIn &&
!pParam->param_attributes.IsByValue &&
!pParam->param_attributes.ServerAllocSize)
{
stubMsg.pfnFree(*(void **)pArg);
}
if (pParam->param_attributes.ServerAllocSize)
HeapFree(GetProcessHeap(), 0, *(void **)pArg);
/* FIXME: call call_freer here for IN types with MustFree set */
break;
case STUBLESS_UNMARSHAL:
if (pParam->param_attributes.ServerAllocSize)
*(void **)pArg = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
pParam->param_attributes.ServerAllocSize * 8);
if (pParam->param_attributes.IsIn)
{
if (pParam->param_attributes.IsByValue)
call_unmarshaller(&stubMsg, &pArg, pTypeFormat, 0);
else
call_unmarshaller(&stubMsg, (unsigned char **)pArg, pTypeFormat, 0);
}
else if (pParam->param_attributes.IsOut &&
!pParam->param_attributes.ServerAllocSize &&
!pParam->param_attributes.IsByValue)
{
DWORD size = calc_arg_size(&stubMsg, pTypeFormat);
if(size)
{
*(void **)pArg = NdrAllocate(&stubMsg, size);
memset(*(void **)pArg, 0, size);
}
}
break;
case STUBLESS_CALCSIZE:
if (pParam->param_attributes.IsOut || pParam->param_attributes.IsReturn)
{
if (pParam->param_attributes.IsByValue)
call_buffer_sizer(&stubMsg, pArg, pTypeFormat);
else
call_buffer_sizer(&stubMsg, *(unsigned char **)pArg, pTypeFormat);
}
break;
default:
RpcRaiseException(RPC_S_INTERNAL_ERROR);
}
current_offset += sizeof(NDR_PARAM_OIF_OTHER);
}
TRACE("\tmemory addr (after): %p -> %p\n", pArg, *(unsigned char **)pArg);
}
else /* old parameter format */
{
const NDR_PARAM_OI_BASETYPE *pParam =
(const NDR_PARAM_OI_BASETYPE *)&pFormat[current_offset];
/* note: current_stack_offset starts after the This pointer
* if present, so adjust this */
unsigned short current_stack_offset_adjusted = current_stack_offset +
((pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT) ? sizeof(void *) : 0);
unsigned char *pArg = (unsigned char *)(args+current_stack_offset_adjusted);
/* no more parameters; exit loop */
if (current_stack_offset_adjusted >= stack_size)
break;
TRACE("param[%d]: old format\n", i);
TRACE("\tparam_direction: 0x%x\n", pParam->param_direction);
TRACE("\tstack_offset: 0x%x\n", current_stack_offset_adjusted);
if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE ||
pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE)
{
const unsigned char *pTypeFormat =
&pParam->type_format_char;
TRACE("\tbase type 0x%02x\n", *pTypeFormat);
switch (phase)
{
case STUBLESS_MARSHAL:
if (pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE)
call_marshaller(&stubMsg, pArg, pTypeFormat);
break;
case STUBLESS_FREE:
if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE)
call_freer(&stubMsg, pArg, pTypeFormat);
break;
case STUBLESS_UNMARSHAL:
if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE)
call_unmarshaller(&stubMsg, &pArg, pTypeFormat, 0);
else if (pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE)
retval_ptr = (LONG_PTR *)pArg;
break;
case STUBLESS_CALCSIZE:
if (pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE)
call_buffer_sizer(&stubMsg, pArg, pTypeFormat);
break;
default:
RpcRaiseException(RPC_S_INTERNAL_ERROR);
}
current_stack_offset += call_memory_sizer(&stubMsg, pTypeFormat);
current_offset += sizeof(NDR_PARAM_OI_BASETYPE);
}
else
{
const NDR_PARAM_OI_OTHER *pParamOther =
(const NDR_PARAM_OI_OTHER *)&pFormat[current_offset];
const unsigned char * pTypeFormat =
&pStubDesc->pFormatTypes[pParamOther->type_offset];
TRACE("\tcomplex type 0x%02x\n", *pTypeFormat);
switch (phase)
{
case STUBLESS_MARSHAL:
if (pParam->param_direction == RPC_FC_OUT_PARAM ||
pParam->param_direction == RPC_FC_IN_OUT_PARAM ||
pParam->param_direction == RPC_FC_RETURN_PARAM)
call_marshaller(&stubMsg, *(unsigned char **)pArg, pTypeFormat);
break;
case STUBLESS_FREE:
if (pParam->param_direction == RPC_FC_IN_OUT_PARAM ||
pParam->param_direction == RPC_FC_IN_PARAM)
call_freer(&stubMsg, *(unsigned char **)pArg, pTypeFormat);
else if (pParam->param_direction == RPC_FC_OUT_PARAM)
stubMsg.pfnFree(*(void **)pArg);
break;
case STUBLESS_UNMARSHAL:
if (pParam->param_direction == RPC_FC_IN_OUT_PARAM ||
pParam->param_direction == RPC_FC_IN_PARAM)
call_unmarshaller(&stubMsg, (unsigned char **)pArg, pTypeFormat, 0);
else if (pParam->param_direction == RPC_FC_RETURN_PARAM)
retval_ptr = (LONG_PTR *)pArg;
else if (pParam->param_direction == RPC_FC_OUT_PARAM)
{
DWORD size = calc_arg_size(&stubMsg, pTypeFormat);
if(size)
{
*(void **)pArg = NdrAllocate(&stubMsg, size);
memset(*(void **)pArg, 0, size);
}
}
break;
case STUBLESS_CALCSIZE:
if (pParam->param_direction == RPC_FC_OUT_PARAM ||
pParam->param_direction == RPC_FC_IN_OUT_PARAM ||
pParam->param_direction == RPC_FC_RETURN_PARAM)
call_buffer_sizer(&stubMsg, *(unsigned char **)pArg, pTypeFormat);
break;
default:
RpcRaiseException(RPC_S_INTERNAL_ERROR);
}
current_stack_offset += pParamOther->stack_size * sizeof(INT);
current_offset += sizeof(NDR_PARAM_OI_OTHER);
}
}
}
break; break;
default: default:
@ -1621,6 +1442,9 @@ LONG WINAPI NdrStubCall2(
return S_OK; return S_OK;
} }
/***********************************************************************
* NdrServerCall2 [RPCRT4.@]
*/
void WINAPI NdrServerCall2(PRPC_MESSAGE pRpcMsg) void WINAPI NdrServerCall2(PRPC_MESSAGE pRpcMsg)
{ {
DWORD dwPhase; DWORD dwPhase;

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 "wine/debug.h"
#include "rpc_binding.h" #include "rpc_binding.h"
#include "rpc_message.h" #include "rpc_assoc.h"
WINE_DEFAULT_DEBUG_CHANNEL(rpc); WINE_DEFAULT_DEBUG_CHANNEL(rpc);
@ -1001,7 +1001,7 @@ ULONG RpcAuthInfo_Release(RpcAuthInfo *AuthInfo)
{ {
HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->User); HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->User);
HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->Domain); 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->nt_identity);
} }
HeapFree(GetProcessHeap(), 0, AuthInfo); HeapFree(GetProcessHeap(), 0, AuthInfo);

View file

@ -22,6 +22,7 @@
#define __WINE_RPC_BINDING_H #define __WINE_RPC_BINDING_H
#include "wine/rpcss_shared.h" #include "wine/rpcss_shared.h"
#include "rpcndr.h"
#include "security.h" #include "security.h"
#include "wine/list.h" #include "wine/list.h"
@ -49,37 +50,16 @@ typedef struct _RpcQualityOfService
RPC_SECURITY_QOS_V2_W *qos; RPC_SECURITY_QOS_V2_W *qos;
} RpcQualityOfService; } 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; struct connection_ops;
typedef struct _RpcConnection typedef struct _RpcConnection
{ {
struct _RpcConnection* Next;
BOOL server; BOOL server;
LPSTR NetworkAddr; LPSTR NetworkAddr;
LPSTR Endpoint; LPSTR Endpoint;
LPWSTR NetworkOptions; LPWSTR NetworkOptions;
const struct connection_ops *ops; const struct connection_ops *ops;
USHORT MaxTransmissionSize; USHORT MaxTransmissionSize;
/* The active interface bound to server. */
RPC_SYNTAX_IDENTIFIER ActiveInterface;
USHORT NextCallId;
/* authentication */ /* authentication */
CtxtHandle ctx; CtxtHandle ctx;
@ -93,6 +73,13 @@ typedef struct _RpcConnection
/* client-only */ /* client-only */
struct list conn_pool_entry; struct list conn_pool_entry;
ULONG assoc_group_id; /* association group returned during binding */ 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; } RpcConnection;
struct connection_ops { struct connection_ops {
@ -104,6 +91,7 @@ struct connection_ops {
int (*read)(RpcConnection *conn, void *buffer, unsigned int len); int (*read)(RpcConnection *conn, void *buffer, unsigned int len);
int (*write)(RpcConnection *conn, const void *buffer, unsigned int len); int (*write)(RpcConnection *conn, const void *buffer, unsigned int len);
int (*close)(RpcConnection *conn); 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); 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); 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; RPC_BLOCKING_FN BlockingFn;
ULONG ServerTid; ULONG ServerTid;
RpcConnection* FromConn; RpcConnection* FromConn;
RpcAssoc *Assoc; struct _RpcAssoc *Assoc;
/* authentication */ /* authentication */
RpcAuthInfo *AuthInfo; RpcAuthInfo *AuthInfo;
@ -145,11 +133,6 @@ ULONG RpcQualityOfService_AddRef(RpcQualityOfService *qos);
ULONG RpcQualityOfService_Release(RpcQualityOfService *qos); ULONG RpcQualityOfService_Release(RpcQualityOfService *qos);
BOOL RpcQualityOfService_IsEqual(const RpcQualityOfService *qos1, const RpcQualityOfService *qos2); 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_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_DestroyConnection(RpcConnection* Connection);
RPC_STATUS RPCRT4_OpenClientConnection(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); 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) static inline RPC_STATUS rpcrt4_conn_handoff(RpcConnection *old_conn, RpcConnection *new_conn)
{ {
return old_conn->ops->handoff(old_conn, 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_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); 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 #endif

View file

@ -241,6 +241,7 @@ RpcPktHdr *RPCRT4_BuildBindNackHeader(unsigned long DataRepresentation,
RpcPktHdr *RPCRT4_BuildBindAckHeader(unsigned long DataRepresentation, RpcPktHdr *RPCRT4_BuildBindAckHeader(unsigned long DataRepresentation,
unsigned short MaxTransmissionSize, unsigned short MaxTransmissionSize,
unsigned short MaxReceiveSize, unsigned short MaxReceiveSize,
unsigned long AssocGroupId,
LPCSTR ServerAddress, LPCSTR ServerAddress,
unsigned long Result, unsigned long Result,
unsigned long Reason, unsigned long Reason,
@ -266,6 +267,7 @@ RpcPktHdr *RPCRT4_BuildBindAckHeader(unsigned long DataRepresentation,
header->common.frag_len = header_size; header->common.frag_len = header_size;
header->bind_ack.max_tsize = MaxTransmissionSize; header->bind_ack.max_tsize = MaxTransmissionSize;
header->bind_ack.max_rsize = MaxReceiveSize; header->bind_ack.max_rsize = MaxReceiveSize;
header->bind_ack.assoc_gid = AssocGroupId;
server_address = (RpcAddressString*)(&header->bind_ack + 1); server_address = (RpcAddressString*)(&header->bind_ack + 1);
server_address->length = strlen(ServerAddress) + 1; server_address->length = strlen(ServerAddress) + 1;
strcpy(server_address->string, ServerAddress); 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); sec_status = DecryptMessage(&Connection->ctx, &message, 0 /* FIXME */, 0);
if (sec_status != SEC_E_OK) 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; return RPC_S_SEC_PKG_ERROR;
} }
} }
@ -449,6 +451,8 @@ static RPC_STATUS RPCRT4_SendAuth(RpcConnection *Connection, RpcPktHdr *Header,
LONG alen; LONG alen;
RPC_STATUS status; RPC_STATUS status;
RPCRT4_SetThreadCurrentConnection(Connection);
buffer_pos = Buffer; buffer_pos = Buffer;
/* The packet building functions save the packet header size, so we can use it. */ /* The packet building functions save the packet header size, so we can use it. */
hdr_size = Header->common.frag_len; hdr_size = Header->common.frag_len;
@ -518,6 +522,7 @@ static RPC_STATUS RPCRT4_SendAuth(RpcConnection *Connection, RpcPktHdr *Header,
if (status != RPC_S_OK) if (status != RPC_S_OK)
{ {
HeapFree(GetProcessHeap(), 0, pkt); HeapFree(GetProcessHeap(), 0, pkt);
RPCRT4_SetThreadCurrentConnection(NULL);
return status; return status;
} }
} }
@ -528,7 +533,8 @@ write:
HeapFree(GetProcessHeap(), 0, pkt); HeapFree(GetProcessHeap(), 0, pkt);
if (count<0) { if (count<0) {
WARN("rpcrt4_conn_write failed (auth)\n"); 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; buffer_pos += Header->common.frag_len - hdr_size - alen - auth_pad_len;
@ -536,6 +542,7 @@ write:
Header->common.flags &= ~RPC_FLG_FIRST; Header->common.flags &= ~RPC_FLG_FIRST;
} }
RPCRT4_SetThreadCurrentConnection(NULL);
return RPC_S_OK; return RPC_S_OK;
} }
@ -697,11 +704,13 @@ RPC_STATUS RPCRT4_Receive(RpcConnection *Connection, RpcPktHdr **Header,
TRACE("(%p, %p, %p)\n", Connection, Header, pMsg); TRACE("(%p, %p, %p)\n", Connection, Header, pMsg);
RPCRT4_SetThreadCurrentConnection(Connection);
/* read packet common header */ /* read packet common header */
dwRead = rpcrt4_conn_read(Connection, &common_hdr, sizeof(common_hdr)); dwRead = rpcrt4_conn_read(Connection, &common_hdr, sizeof(common_hdr));
if (dwRead != sizeof(common_hdr)) { if (dwRead != sizeof(common_hdr)) {
WARN("Short read of header, %d bytes\n", dwRead); WARN("Short read of header, %d bytes\n", dwRead);
status = RPC_S_PROTOCOL_ERROR; status = RPC_S_CALL_FAILED;
goto fail; 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)); dwRead = rpcrt4_conn_read(Connection, &(*Header)->common + 1, hdr_length - sizeof(common_hdr));
if (dwRead != 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); 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; goto fail;
} }
@ -753,7 +762,7 @@ RPC_STATUS RPCRT4_Receive(RpcConnection *Connection, RpcPktHdr **Header,
if (auth_length) { if (auth_length) {
auth_data = HeapAlloc(GetProcessHeap(), 0, RPC_AUTH_VERIFIER_LEN(&common_hdr)); auth_data = HeapAlloc(GetProcessHeap(), 0, RPC_AUTH_VERIFIER_LEN(&common_hdr));
if (!auth_data) { if (!auth_data) {
status = RPC_S_PROTOCOL_ERROR; status = RPC_S_OUT_OF_RESOURCES;
goto fail; goto fail;
} }
} }
@ -799,7 +808,7 @@ RPC_STATUS RPCRT4_Receive(RpcConnection *Connection, RpcPktHdr **Header,
(unsigned char *)pMsg->Buffer + buffer_length, data_length); (unsigned char *)pMsg->Buffer + buffer_length, data_length);
if (dwRead != data_length) { if (dwRead != data_length) {
WARN("bad data length, %d/%ld\n", 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; goto fail;
} }
@ -819,7 +828,7 @@ RPC_STATUS RPCRT4_Receive(RpcConnection *Connection, RpcPktHdr **Header,
if (dwRead != header_auth_len) { if (dwRead != header_auth_len) {
WARN("bad authentication data length, %d/%d\n", dwRead, WARN("bad authentication data length, %d/%d\n", dwRead,
header_auth_len); header_auth_len);
status = RPC_S_PROTOCOL_ERROR; status = RPC_S_CALL_FAILED;
goto fail; goto fail;
} }
@ -828,12 +837,15 @@ RPC_STATUS RPCRT4_Receive(RpcConnection *Connection, RpcPktHdr **Header,
if ((common_hdr.ptype != PKT_BIND) && if ((common_hdr.ptype != PKT_BIND) &&
(common_hdr.ptype != PKT_BIND_ACK) && (common_hdr.ptype != PKT_BIND_ACK) &&
(common_hdr.ptype != PKT_AUTH3)) (common_hdr.ptype != PKT_AUTH3))
{
status = RPCRT4_SecurePacket(Connection, SECURE_PACKET_RECEIVE, status = RPCRT4_SecurePacket(Connection, SECURE_PACKET_RECEIVE,
*Header, hdr_length, *Header, hdr_length,
(unsigned char *)pMsg->Buffer + buffer_length, data_length, (unsigned char *)pMsg->Buffer + buffer_length, data_length,
(RpcAuthVerifier *)auth_data, (RpcAuthVerifier *)auth_data,
(unsigned char *)auth_data + sizeof(RpcAuthVerifier), (unsigned char *)auth_data + sizeof(RpcAuthVerifier),
header_auth_len - sizeof(RpcAuthVerifier)); header_auth_len - sizeof(RpcAuthVerifier));
if (status != RPC_S_OK) goto fail;
}
} }
buffer_length += data_length; buffer_length += data_length;
@ -844,7 +856,7 @@ RPC_STATUS RPCRT4_Receive(RpcConnection *Connection, RpcPktHdr **Header,
dwRead = rpcrt4_conn_read(Connection, *Header, hdr_length); dwRead = rpcrt4_conn_read(Connection, *Header, hdr_length);
if (dwRead != hdr_length) { if (dwRead != hdr_length) {
WARN("invalid packet header size (%d)\n", dwRead); WARN("invalid packet header size (%d)\n", dwRead);
status = RPC_S_PROTOCOL_ERROR; status = RPC_S_CALL_FAILED;
goto fail; goto fail;
} }
@ -869,6 +881,7 @@ RPC_STATUS RPCRT4_Receive(RpcConnection *Connection, RpcPktHdr **Header,
status = RPC_S_OK; status = RPC_S_OK;
fail: fail:
RPCRT4_SetThreadCurrentConnection(NULL);
if (status != RPC_S_OK) { if (status != RPC_S_OK) {
RPCRT4_FreeHeader(*Header); RPCRT4_FreeHeader(*Header);
*Header = NULL; *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_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_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_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); VOID RPCRT4_FreeHeader(RpcPktHdr *Header);
RPC_STATUS RPCRT4_Send(RpcConnection *Connection, RpcPktHdr *Header, void *Buffer, unsigned int BufferLength); RPC_STATUS RPCRT4_Send(RpcConnection *Connection, RpcPktHdr *Header, void *Buffer, unsigned int BufferLength);
RPC_STATUS RPCRT4_Receive(RpcConnection *Connection, RpcPktHdr **Header, PRPC_MESSAGE pMsg); RPC_STATUS RPCRT4_Receive(RpcConnection *Connection, RpcPktHdr **Header, PRPC_MESSAGE pMsg);

View file

@ -42,6 +42,7 @@
#include "wine/exception.h" #include "wine/exception.h"
#include "rpc_server.h" #include "rpc_server.h"
#include "rpc_assoc.h"
#include "rpc_message.h" #include "rpc_message.h"
#include "rpc_defs.h" #include "rpc_defs.h"
#include "ncastatus.h" #include "ncastatus.h"
@ -167,10 +168,13 @@ static void RPCRT4_process_packet(RpcConnection* conn, RpcPktHdr* hdr, RPC_MESSA
RpcServerInterface* sif; RpcServerInterface* sif;
RPC_DISPATCH_FUNCTION func; RPC_DISPATCH_FUNCTION func;
UUID *object_uuid; UUID *object_uuid;
RpcPktHdr *response; RpcPktHdr *response = NULL;
void *buf = msg->Buffer; void *buf = msg->Buffer;
RPC_STATUS status; RPC_STATUS status;
BOOL exception; BOOL exception;
NDR_SCONTEXT context_handle;
msg->Handle = (RPC_BINDING_HANDLE)conn->server_binding;
switch (hdr->common.ptype) { switch (hdr->common.ptype) {
case PKT_BIND: case PKT_BIND:
@ -178,11 +182,21 @@ static void RPCRT4_process_packet(RpcConnection* conn, RpcPktHdr* hdr, RPC_MESSA
/* FIXME: do more checks! */ /* FIXME: do more checks! */
if (hdr->bind.max_tsize < RPC_MIN_PACKET_SIZE || 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"); TRACE("packet size less than min size, or active interface syntax guid non-null\n");
sif = NULL; sif = NULL;
} else { } else {
/* 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); sif = RPCRT4_find_interface(NULL, &hdr->bind.abstract, FALSE);
else
sif = NULL;
} }
if (sif == NULL) { if (sif == NULL) {
TRACE("rejecting bind request on connection %p\n", conn); 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, response = RPCRT4_BuildBindAckHeader(NDR_LOCAL_DATA_REPRESENTATION,
RPC_MAX_PACKET_SIZE, RPC_MAX_PACKET_SIZE,
RPC_MAX_PACKET_SIZE, RPC_MAX_PACKET_SIZE,
conn->server_binding->Assoc->assoc_group_id,
conn->Endpoint, conn->Endpoint,
RESULT_ACCEPT, REASON_NONE, RESULT_ACCEPT, REASON_NONE,
&sif->If->TransferSyntax); &sif->If->TransferSyntax);
@ -279,6 +294,7 @@ static void RPCRT4_process_packet(RpcConnection* conn, RpcPktHdr* hdr, RPC_MESSA
exception = FALSE; exception = FALSE;
/* dispatch */ /* dispatch */
RPCRT4_SetThreadCurrentCallHandle(msg->Handle);
__TRY { __TRY {
if (func) func(msg); if (func) func(msg);
} __EXCEPT(rpc_filter) { } __EXCEPT(rpc_filter) {
@ -290,6 +306,11 @@ static void RPCRT4_process_packet(RpcConnection* conn, RpcPktHdr* hdr, RPC_MESSA
response = RPCRT4_BuildFaultHeader(msg->DataRepresentation, response = RPCRT4_BuildFaultHeader(msg->DataRepresentation,
RPC2NCA_STATUS(status)); RPC2NCA_STATUS(status));
} __ENDTRY } __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) if (!exception)
response = RPCRT4_BuildResponseHeader(msg->DataRepresentation, response = RPCRT4_BuildResponseHeader(msg->DataRepresentation,
@ -318,7 +339,6 @@ fail:
if (msg->Buffer == buf) msg->Buffer = NULL; if (msg->Buffer == buf) msg->Buffer = NULL;
TRACE("freeing Buffer=%p\n", buf); TRACE("freeing Buffer=%p\n", buf);
HeapFree(GetProcessHeap(), 0, buf); HeapFree(GetProcessHeap(), 0, buf);
RPCRT4_DestroyBinding(msg->Handle);
msg->Handle = 0; msg->Handle = 0;
I_RpcFreeBuffer(msg); I_RpcFreeBuffer(msg);
msg->Buffer = NULL; msg->Buffer = NULL;
@ -338,7 +358,6 @@ static DWORD CALLBACK RPCRT4_io_thread(LPVOID the_arg)
{ {
RpcConnection* conn = (RpcConnection*)the_arg; RpcConnection* conn = (RpcConnection*)the_arg;
RpcPktHdr *hdr; RpcPktHdr *hdr;
RpcBinding *pbind;
RPC_MESSAGE *msg; RPC_MESSAGE *msg;
RPC_STATUS status; RPC_STATUS status;
RpcPacket *packet; RpcPacket *packet;
@ -348,11 +367,6 @@ static DWORD CALLBACK RPCRT4_io_thread(LPVOID the_arg)
for (;;) { for (;;) {
msg = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RPC_MESSAGE)); 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); status = RPCRT4_Receive(conn, &hdr, msg);
if (status != RPC_S_OK) { if (status != RPC_S_OK) {
WARN("receive failed with error %lx\n", status); WARN("receive failed with error %lx\n", status);
@ -1114,3 +1128,12 @@ RPC_STATUS WINAPI RpcMgmtSetServerStackSize(ULONG ThreadStackSize)
FIXME("(0x%x): stub\n", ThreadStackSize); FIXME("(0x%x): stub\n", ThreadStackSize);
return RPC_S_OK; return RPC_S_OK;
} }
/***********************************************************************
* I_RpcGetCurrentCallHandle (RPCRT4.@)
*/
RPC_BINDING_HANDLE WINAPI I_RpcGetCurrentCallHandle(void)
{
TRACE("\n");
return RPCRT4_GetThreadCurrentCallHandle();
}

View file

@ -84,17 +84,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(rpc); WINE_DEFAULT_DEBUG_CHANNEL(rpc);
static CRITICAL_SECTION assoc_list_cs;
static CRITICAL_SECTION_DEBUG assoc_list_cs_debug =
{
0, 0, &assoc_list_cs,
{ &assoc_list_cs_debug.ProcessLocksList, &assoc_list_cs_debug.ProcessLocksList },
0, 0, { (DWORD_PTR)(__FILE__ ": assoc_list_cs") }
};
static CRITICAL_SECTION assoc_list_cs = { &assoc_list_cs_debug, -1, 0, 0, 0, 0 };
static struct list assoc_list = LIST_INIT(assoc_list);
/**** ncacn_np support ****/ /**** ncacn_np support ****/
typedef struct _RpcConnection_np typedef struct _RpcConnection_np
@ -144,7 +133,7 @@ static RPC_STATUS rpcrt4_conn_create_pipe(RpcConnection *Connection, LPCSTR pnam
RpcConnection_np *npc = (RpcConnection_np *) Connection; RpcConnection_np *npc = (RpcConnection_np *) Connection;
TRACE("listening on %s\n", pname); TRACE("listening on %s\n", pname);
npc->pipe = CreateNamedPipeA(pname, PIPE_ACCESS_DUPLEX, npc->pipe = CreateNamedPipeA(pname, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE,
PIPE_UNLIMITED_INSTANCES, PIPE_UNLIMITED_INSTANCES,
RPC_MAX_PACKET_SIZE, RPC_MAX_PACKET_SIZE, 5000, NULL); RPC_MAX_PACKET_SIZE, RPC_MAX_PACKET_SIZE, 5000, NULL);
@ -421,6 +410,11 @@ static int rpcrt4_conn_np_close(RpcConnection *Connection)
return 0; return 0;
} }
static void rpcrt4_conn_np_cancel_call(RpcConnection *Connection)
{
/* FIXME: implement when named pipe writes use overlapped I/O */
}
static size_t rpcrt4_ncacn_np_get_top_of_tower(unsigned char *tower_data, static size_t rpcrt4_ncacn_np_get_top_of_tower(unsigned char *tower_data,
const char *networkaddr, const char *networkaddr,
const char *endpoint) const char *endpoint)
@ -605,7 +599,15 @@ static int rpcrt4_protseq_np_wait_for_new_connection(RpcServerProtseq *protseq,
if (!objs) if (!objs)
return -1; return -1;
res = WaitForMultipleObjects(count, objs, FALSE, INFINITE); do
{
/* an alertable wait isn't strictly necessary, but due to our
* overlapped I/O implementation in Wine we need to free some memory
* by the file user APC being called, even if no completion routine was
* specified at the time of starting the async operation */
res = WaitForMultipleObjectsEx(count, objs, FALSE, INFINITE, TRUE);
} while (res == WAIT_IO_COMPLETION);
if (res == WAIT_OBJECT_0) if (res == WAIT_OBJECT_0)
return 0; return 0;
else if (res == WAIT_FAILED) else if (res == WAIT_FAILED)
@ -708,6 +710,7 @@ typedef struct _RpcConnection_tcp
{ {
RpcConnection common; RpcConnection common;
int sock; int sock;
int cancel_fds[2];
} RpcConnection_tcp; } RpcConnection_tcp;
static RpcConnection *rpcrt4_conn_tcp_alloc(void) static RpcConnection *rpcrt4_conn_tcp_alloc(void)
@ -717,6 +720,14 @@ static RpcConnection *rpcrt4_conn_tcp_alloc(void)
if (tcpc == NULL) if (tcpc == NULL)
return NULL; return NULL;
tcpc->sock = -1; tcpc->sock = -1;
#ifndef __REACTOS__
if (socketpair(PF_UNIX, SOCK_STREAM, 0, tcpc->cancel_fds) < 0)
{
ERR("socketpair() failed: %s\n", strerror(errno));
HeapFree(GetProcessHeap(), 0, tcpc);
return NULL;
}
#endif
return &tcpc->common; return &tcpc->common;
} }
@ -766,7 +777,7 @@ static RPC_STATUS rpcrt4_ncacn_ip_tcp_open(RpcConnection* Connection)
} }
sock = socket(ai_cur->ai_family, ai_cur->ai_socktype, ai_cur->ai_protocol); sock = socket(ai_cur->ai_family, ai_cur->ai_socktype, ai_cur->ai_protocol);
if (sock < 0) if (sock == -1)
{ {
WARN("socket() failed: %s\n", strerror(errno)); WARN("socket() failed: %s\n", strerror(errno));
continue; continue;
@ -803,8 +814,8 @@ static RPC_STATUS rpcrt4_protseq_ncacn_ip_tcp_open_endpoint(RpcServerProtseq *pr
struct addrinfo *ai; struct addrinfo *ai;
struct addrinfo *ai_cur; struct addrinfo *ai_cur;
struct addrinfo hints; struct addrinfo hints;
RpcConnection *first_connection = NULL;
u_long blocking; u_long blocking;
RpcConnection *first_connection = NULL;
TRACE("(%p, %s)\n", protseq, endpoint); TRACE("(%p, %s)\n", protseq, endpoint);
@ -843,7 +854,7 @@ static RPC_STATUS rpcrt4_protseq_ncacn_ip_tcp_open_endpoint(RpcServerProtseq *pr
} }
sock = socket(ai_cur->ai_family, ai_cur->ai_socktype, ai_cur->ai_protocol); sock = socket(ai_cur->ai_family, ai_cur->ai_socktype, ai_cur->ai_protocol);
if (sock < 0) if (sock == -1)
{ {
WARN("socket() failed: %s\n", strerror(errno)); WARN("socket() failed: %s\n", strerror(errno));
status = RPC_S_CANT_CREATE_ENDPOINT; status = RPC_S_CANT_CREATE_ENDPOINT;
@ -951,18 +962,69 @@ static int rpcrt4_conn_tcp_read(RpcConnection *Connection,
void *buffer, unsigned int count) void *buffer, unsigned int count)
{ {
RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection; RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;
int r = recv(tcpc->sock, buffer, count, MSG_WAITALL); int bytes_read = 0;
TRACE("%d %p %u -> %d\n", tcpc->sock, buffer, count, r); do
return r; {
int r = recv(tcpc->sock, (char *)buffer + bytes_read, count - bytes_read, 0);
if (!r)
return -1;
else if (r > 0)
bytes_read += r;
else if (errno != EAGAIN)
{
WARN("recv() failed: %s\n", strerror(errno));
return -1;
}
else
{
struct pollfd pfds[2];
pfds[0].fd = tcpc->sock;
pfds[0].events = POLLIN;
pfds[1].fd = tcpc->cancel_fds[0];
pfds[1].events = POLLIN;
if (poll(pfds, 2, -1 /* infinite */) == -1 && errno != EINTR)
{
ERR("poll() failed: %s\n", strerror(errno));
return -1;
}
if (pfds[1].revents & POLLIN) /* canceled */
{
char dummy;
read(pfds[1].fd, &dummy, sizeof(dummy));
return -1;
}
}
} while (bytes_read != count);
TRACE("%d %p %u -> %d\n", tcpc->sock, buffer, count, bytes_read);
return bytes_read;
} }
static int rpcrt4_conn_tcp_write(RpcConnection *Connection, static int rpcrt4_conn_tcp_write(RpcConnection *Connection,
const void *buffer, unsigned int count) const void *buffer, unsigned int count)
{ {
RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection; RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;
int r = write(tcpc->sock, buffer, count); int bytes_written = 0;
TRACE("%d %p %u -> %d\n", tcpc->sock, buffer, count, r); do
return r; {
int r = write(tcpc->sock, (const char *)buffer + bytes_written, count - bytes_written);
if (r >= 0)
bytes_written += r;
else if (errno != EAGAIN)
return -1;
else
{
struct pollfd pfd;
pfd.fd = tcpc->sock;
pfd.events = POLLOUT;
if (poll(&pfd, 1, -1 /* infinite */) == -1 && errno != EINTR)
{
ERR("poll() failed: %s\n", strerror(errno));
return -1;
}
}
} while (bytes_written != count);
TRACE("%d %p %u -> %d\n", tcpc->sock, buffer, count, bytes_written);
return bytes_written;
} }
static int rpcrt4_conn_tcp_close(RpcConnection *Connection) static int rpcrt4_conn_tcp_close(RpcConnection *Connection)
@ -974,9 +1036,21 @@ static int rpcrt4_conn_tcp_close(RpcConnection *Connection)
if (tcpc->sock != -1) if (tcpc->sock != -1)
close(tcpc->sock); close(tcpc->sock);
tcpc->sock = -1; tcpc->sock = -1;
close(tcpc->cancel_fds[0]);
close(tcpc->cancel_fds[1]);
return 0; return 0;
} }
static void rpcrt4_conn_tcp_cancel_call(RpcConnection *Connection)
{
RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;
char dummy = 1;
TRACE("%p\n", Connection);
write(tcpc->cancel_fds[1], &dummy, 1);
}
static size_t rpcrt4_ncacn_ip_tcp_get_top_of_tower(unsigned char *tower_data, static size_t rpcrt4_ncacn_ip_tcp_get_top_of_tower(unsigned char *tower_data,
const char *networkaddr, const char *networkaddr,
const char *endpoint) const char *endpoint)
@ -1261,6 +1335,7 @@ static const struct connection_ops conn_protseq_list[] = {
rpcrt4_conn_np_read, rpcrt4_conn_np_read,
rpcrt4_conn_np_write, rpcrt4_conn_np_write,
rpcrt4_conn_np_close, rpcrt4_conn_np_close,
rpcrt4_conn_np_cancel_call,
rpcrt4_ncacn_np_get_top_of_tower, rpcrt4_ncacn_np_get_top_of_tower,
rpcrt4_ncacn_np_parse_top_of_tower, rpcrt4_ncacn_np_parse_top_of_tower,
}, },
@ -1272,6 +1347,7 @@ static const struct connection_ops conn_protseq_list[] = {
rpcrt4_conn_np_read, rpcrt4_conn_np_read,
rpcrt4_conn_np_write, rpcrt4_conn_np_write,
rpcrt4_conn_np_close, rpcrt4_conn_np_close,
rpcrt4_conn_np_cancel_call,
rpcrt4_ncalrpc_get_top_of_tower, rpcrt4_ncalrpc_get_top_of_tower,
rpcrt4_ncalrpc_parse_top_of_tower, rpcrt4_ncalrpc_parse_top_of_tower,
}, },
@ -1283,6 +1359,7 @@ static const struct connection_ops conn_protseq_list[] = {
rpcrt4_conn_tcp_read, rpcrt4_conn_tcp_read,
rpcrt4_conn_tcp_write, rpcrt4_conn_tcp_write,
rpcrt4_conn_tcp_close, rpcrt4_conn_tcp_close,
rpcrt4_conn_tcp_cancel_call,
rpcrt4_ncacn_ip_tcp_get_top_of_tower, rpcrt4_ncacn_ip_tcp_get_top_of_tower,
rpcrt4_ncacn_ip_tcp_parse_top_of_tower, rpcrt4_ncacn_ip_tcp_parse_top_of_tower,
} }
@ -1378,6 +1455,7 @@ RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server,
NewConnection = ops->alloc(); NewConnection = ops->alloc();
NewConnection->Next = NULL; NewConnection->Next = NULL;
NewConnection->server_binding = NULL;
NewConnection->server = server; NewConnection->server = server;
NewConnection->ops = ops; NewConnection->ops = ops;
NewConnection->NetworkAddr = RPCRT4_strdupA(NetworkAddr); NewConnection->NetworkAddr = RPCRT4_strdupA(NetworkAddr);
@ -1405,283 +1483,6 @@ RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server,
return RPC_S_OK; return RPC_S_OK;
} }
RPC_STATUS RPCRT4_GetAssociation(LPCSTR Protseq, LPCSTR NetworkAddr,
LPCSTR Endpoint, LPCWSTR NetworkOptions,
RpcAssoc **assoc_out)
{
RpcAssoc *assoc;
EnterCriticalSection(&assoc_list_cs);
LIST_FOR_EACH_ENTRY(assoc, &assoc_list, RpcAssoc, entry)
{
if (!strcmp(Protseq, assoc->Protseq) &&
!strcmp(NetworkAddr, assoc->NetworkAddr) &&
!strcmp(Endpoint, assoc->Endpoint) &&
((!assoc->NetworkOptions && !NetworkOptions) || !strcmpW(NetworkOptions, assoc->NetworkOptions)))
{
assoc->refs++;
*assoc_out = assoc;
LeaveCriticalSection(&assoc_list_cs);
TRACE("using existing assoc %p\n", assoc);
return RPC_S_OK;
}
}
assoc = HeapAlloc(GetProcessHeap(), 0, sizeof(*assoc));
if (!assoc)
{
LeaveCriticalSection(&assoc_list_cs);
return RPC_S_OUT_OF_RESOURCES;
}
assoc->refs = 1;
list_init(&assoc->connection_pool);
InitializeCriticalSection(&assoc->cs);
assoc->Protseq = RPCRT4_strdupA(Protseq);
assoc->NetworkAddr = RPCRT4_strdupA(NetworkAddr);
assoc->Endpoint = RPCRT4_strdupA(Endpoint);
assoc->NetworkOptions = NetworkOptions ? RPCRT4_strdupW(NetworkOptions) : NULL;
assoc->assoc_group_id = 0;
list_add_head(&assoc_list, &assoc->entry);
*assoc_out = assoc;
LeaveCriticalSection(&assoc_list_cs);
TRACE("new assoc %p\n", assoc);
return RPC_S_OK;
}
ULONG RpcAssoc_Release(RpcAssoc *assoc)
{
ULONG refs;
EnterCriticalSection(&assoc_list_cs);
refs = --assoc->refs;
if (!refs)
list_remove(&assoc->entry);
LeaveCriticalSection(&assoc_list_cs);
if (!refs)
{
RpcConnection *Connection, *cursor2;
TRACE("destroying assoc %p\n", assoc);
LIST_FOR_EACH_ENTRY_SAFE(Connection, cursor2, &assoc->connection_pool, RpcConnection, conn_pool_entry)
{
list_remove(&Connection->conn_pool_entry);
RPCRT4_DestroyConnection(Connection);
}
HeapFree(GetProcessHeap(), 0, assoc->NetworkOptions);
HeapFree(GetProcessHeap(), 0, assoc->Endpoint);
HeapFree(GetProcessHeap(), 0, assoc->NetworkAddr);
HeapFree(GetProcessHeap(), 0, assoc->Protseq);
HeapFree(GetProcessHeap(), 0, assoc);
}
return refs;
}
#define ROUND_UP(value, alignment) (((value) + ((alignment) - 1)) & ~((alignment)-1))
static RPC_STATUS RpcAssoc_BindConnection(const RpcAssoc *assoc, RpcConnection *conn,
const RPC_SYNTAX_IDENTIFIER *InterfaceId,
const RPC_SYNTAX_IDENTIFIER *TransferSyntax)
{
RpcPktHdr *hdr;
RpcPktHdr *response_hdr;
RPC_MESSAGE msg;
RPC_STATUS status;
TRACE("sending bind request to server\n");
hdr = RPCRT4_BuildBindHeader(NDR_LOCAL_DATA_REPRESENTATION,
RPC_MAX_PACKET_SIZE, RPC_MAX_PACKET_SIZE,
assoc->assoc_group_id,
InterfaceId, TransferSyntax);
status = RPCRT4_Send(conn, hdr, NULL, 0);
RPCRT4_FreeHeader(hdr);
if (status != RPC_S_OK)
return status;
status = RPCRT4_Receive(conn, &response_hdr, &msg);
if (status != RPC_S_OK)
{
ERR("receive failed\n");
return status;
}
switch (response_hdr->common.ptype)
{
case PKT_BIND_ACK:
{
RpcAddressString *server_address = msg.Buffer;
if ((msg.BufferLength >= FIELD_OFFSET(RpcAddressString, string[0])) ||
(msg.BufferLength >= ROUND_UP(FIELD_OFFSET(RpcAddressString, string[server_address->length]), 4)))
{
unsigned short remaining = msg.BufferLength -
ROUND_UP(FIELD_OFFSET(RpcAddressString, string[server_address->length]), 4);
RpcResults *results = (RpcResults*)((ULONG_PTR)server_address +
ROUND_UP(FIELD_OFFSET(RpcAddressString, string[server_address->length]), 4));
if ((results->num_results == 1) && (remaining >= sizeof(*results)))
{
switch (results->results[0].result)
{
case RESULT_ACCEPT:
conn->assoc_group_id = response_hdr->bind_ack.assoc_gid;
conn->MaxTransmissionSize = response_hdr->bind_ack.max_tsize;
conn->ActiveInterface = *InterfaceId;
break;
case RESULT_PROVIDER_REJECTION:
switch (results->results[0].reason)
{
case REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED:
ERR("syntax %s, %d.%d not supported\n",
debugstr_guid(&InterfaceId->SyntaxGUID),
InterfaceId->SyntaxVersion.MajorVersion,
InterfaceId->SyntaxVersion.MinorVersion);
status = RPC_S_UNKNOWN_IF;
break;
case REASON_TRANSFER_SYNTAXES_NOT_SUPPORTED:
ERR("transfer syntax not supported\n");
status = RPC_S_SERVER_UNAVAILABLE;
break;
case REASON_NONE:
default:
status = RPC_S_CALL_FAILED_DNE;
}
break;
case RESULT_USER_REJECTION:
default:
ERR("rejection result %d\n", results->results[0].result);
status = RPC_S_CALL_FAILED_DNE;
}
}
else
{
ERR("incorrect results size\n");
status = RPC_S_CALL_FAILED_DNE;
}
}
else
{
ERR("bind ack packet too small (%d)\n", msg.BufferLength);
status = RPC_S_PROTOCOL_ERROR;
}
break;
}
case PKT_BIND_NACK:
switch (response_hdr->bind_nack.reject_reason)
{
case REJECT_LOCAL_LIMIT_EXCEEDED:
case REJECT_TEMPORARY_CONGESTION:
ERR("server too busy\n");
status = RPC_S_SERVER_TOO_BUSY;
break;
case REJECT_PROTOCOL_VERSION_NOT_SUPPORTED:
ERR("protocol version not supported\n");
status = RPC_S_PROTOCOL_ERROR;
break;
case REJECT_UNKNOWN_AUTHN_SERVICE:
ERR("unknown authentication service\n");
status = RPC_S_UNKNOWN_AUTHN_SERVICE;
break;
case REJECT_INVALID_CHECKSUM:
ERR("invalid checksum\n");
status = ERROR_ACCESS_DENIED;
break;
default:
ERR("rejected bind for reason %d\n", response_hdr->bind_nack.reject_reason);
status = RPC_S_CALL_FAILED_DNE;
}
break;
default:
ERR("wrong packet type received %d\n", response_hdr->common.ptype);
status = RPC_S_PROTOCOL_ERROR;
break;
}
RPCRT4_FreeHeader(response_hdr);
return status;
}
static RpcConnection *RpcAssoc_GetIdleConnection(RpcAssoc *assoc,
const RPC_SYNTAX_IDENTIFIER *InterfaceId,
const RPC_SYNTAX_IDENTIFIER *TransferSyntax, const RpcAuthInfo *AuthInfo,
const RpcQualityOfService *QOS)
{
RpcConnection *Connection;
EnterCriticalSection(&assoc->cs);
/* try to find a compatible connection from the connection pool */
LIST_FOR_EACH_ENTRY(Connection, &assoc->connection_pool, RpcConnection, conn_pool_entry)
{
if (!memcmp(&Connection->ActiveInterface, InterfaceId,
sizeof(RPC_SYNTAX_IDENTIFIER)) &&
RpcAuthInfo_IsEqual(Connection->AuthInfo, AuthInfo) &&
RpcQualityOfService_IsEqual(Connection->QOS, QOS))
{
list_remove(&Connection->conn_pool_entry);
LeaveCriticalSection(&assoc->cs);
TRACE("got connection from pool %p\n", Connection);
return Connection;
}
}
LeaveCriticalSection(&assoc->cs);
return NULL;
}
RPC_STATUS RpcAssoc_GetClientConnection(RpcAssoc *assoc,
const RPC_SYNTAX_IDENTIFIER *InterfaceId,
const RPC_SYNTAX_IDENTIFIER *TransferSyntax, RpcAuthInfo *AuthInfo,
RpcQualityOfService *QOS, RpcConnection **Connection)
{
RpcConnection *NewConnection;
RPC_STATUS status;
*Connection = RpcAssoc_GetIdleConnection(assoc, InterfaceId, TransferSyntax, AuthInfo, QOS);
if (*Connection)
return RPC_S_OK;
/* create a new connection */
status = RPCRT4_CreateConnection(&NewConnection, FALSE /* is this a server connection? */,
assoc->Protseq, assoc->NetworkAddr,
assoc->Endpoint, assoc->NetworkOptions,
AuthInfo, QOS);
if (status != RPC_S_OK)
return status;
status = RPCRT4_OpenClientConnection(NewConnection);
if (status != RPC_S_OK)
{
RPCRT4_DestroyConnection(NewConnection);
return status;
}
status = RpcAssoc_BindConnection(assoc, NewConnection, InterfaceId, TransferSyntax);
if (status != RPC_S_OK)
{
RPCRT4_DestroyConnection(NewConnection);
return status;
}
*Connection = NewConnection;
return RPC_S_OK;
}
void RpcAssoc_ReleaseIdleConnection(RpcAssoc *assoc, RpcConnection *Connection)
{
assert(!Connection->server);
EnterCriticalSection(&assoc->cs);
if (!assoc->assoc_group_id) assoc->assoc_group_id = Connection->assoc_group_id;
list_add_head(&assoc->connection_pool, &Connection->conn_pool_entry);
LeaveCriticalSection(&assoc->cs);
}
RPC_STATUS RPCRT4_SpawnConnection(RpcConnection** Connection, RpcConnection* OldConnection) RPC_STATUS RPCRT4_SpawnConnection(RpcConnection** Connection, RpcConnection* OldConnection)
{ {
@ -1707,6 +1508,10 @@ RPC_STATUS RPCRT4_DestroyConnection(RpcConnection* Connection)
HeapFree(GetProcessHeap(), 0, Connection->NetworkOptions); HeapFree(GetProcessHeap(), 0, Connection->NetworkOptions);
if (Connection->AuthInfo) RpcAuthInfo_Release(Connection->AuthInfo); if (Connection->AuthInfo) RpcAuthInfo_Release(Connection->AuthInfo);
if (Connection->QOS) RpcQualityOfService_Release(Connection->QOS); if (Connection->QOS) RpcQualityOfService_Release(Connection->QOS);
/* server-only */
if (Connection->server_binding) RPCRT4_DestroyBinding(Connection->server_binding);
HeapFree(GetProcessHeap(), 0, Connection); HeapFree(GetProcessHeap(), 0, Connection);
return RPC_S_OK; return RPC_S_OK;
} }

View file

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

View file

@ -51,7 +51,7 @@
@ stub I_RpcGetAssociationContext @ stub I_RpcGetAssociationContext
@ stdcall I_RpcGetBuffer(ptr) @ stdcall I_RpcGetBuffer(ptr)
@ stub I_RpcGetBufferWithObject @ stub I_RpcGetBufferWithObject
@ stub I_RpcGetCurrentCallHandle @ stdcall I_RpcGetCurrentCallHandle()
@ stub I_RpcGetExtendedError @ stub I_RpcGetExtendedError
@ stub I_RpcGetServerContextList @ stub I_RpcGetServerContextList
@ stub I_RpcGetThreadEvent # win9x @ stub I_RpcGetThreadEvent # win9x
@ -294,7 +294,7 @@
@ stdcall NdrProxyGetBuffer(ptr ptr) @ stdcall NdrProxyGetBuffer(ptr ptr)
@ stdcall NdrProxyInitialize(ptr ptr ptr ptr long) @ stdcall NdrProxyInitialize(ptr ptr ptr ptr long)
@ stdcall NdrProxySendReceive(ptr ptr) @ stdcall NdrProxySendReceive(ptr ptr)
@ stub NdrRangeUnmarshall @ stdcall NdrRangeUnmarshall(ptr ptr ptr long)
@ stub NdrRpcSmClientAllocate @ stub NdrRpcSmClientAllocate
@ stub NdrRpcSmClientFree @ stub NdrRpcSmClientFree
@ stub NdrRpcSmSetClientToOsf @ stub NdrRpcSmSetClientToOsf
@ -395,7 +395,7 @@
@ stdcall RpcBindingToStringBindingW(ptr ptr) @ stdcall RpcBindingToStringBindingW(ptr ptr)
@ stdcall RpcBindingVectorFree(ptr) @ stdcall RpcBindingVectorFree(ptr)
@ stub RpcCancelAsyncCall @ stub RpcCancelAsyncCall
@ stub RpcCancelThread @ stdcall RpcCancelThread(ptr)
@ stub RpcCancelThreadEx @ stub RpcCancelThreadEx
@ stub RpcCertGeneratePrincipalNameA @ stub RpcCertGeneratePrincipalNameA
@ stub RpcCertGeneratePrincipalNameW @ stub RpcCertGeneratePrincipalNameW
@ -414,7 +414,7 @@
@ stub RpcErrorNumberOfRecords # wxp @ stub RpcErrorNumberOfRecords # wxp
@ stub RpcErrorResetEnumeration # wxp @ stub RpcErrorResetEnumeration # wxp
@ stub RpcErrorSaveErrorInfo # wxp @ stub RpcErrorSaveErrorInfo # wxp
@ stub RpcErrorStartEnumeration # wxp @ stdcall RpcErrorStartEnumeration(ptr)
@ stub RpcFreeAuthorizationContext # wxp @ stub RpcFreeAuthorizationContext # wxp
@ stub RpcGetAsyncCallStatus @ stub RpcGetAsyncCallStatus
@ stub RpcIfIdVectorFree @ stub RpcIfIdVectorFree
@ -438,7 +438,7 @@
@ stub RpcMgmtInqStats @ stub RpcMgmtInqStats
@ stdcall RpcMgmtIsServerListening(ptr) @ stdcall RpcMgmtIsServerListening(ptr)
@ stub RpcMgmtSetAuthorizationFn @ stub RpcMgmtSetAuthorizationFn
@ stub RpcMgmtSetCancelTimeout @ stdcall RpcMgmtSetCancelTimeout(long)
@ stdcall RpcMgmtSetComTimeout(ptr long) @ stdcall RpcMgmtSetComTimeout(ptr long)
@ stub RpcMgmtSetParameter # win9x @ stub RpcMgmtSetParameter # win9x
@ stdcall RpcMgmtSetServerStackSize(long) @ stdcall RpcMgmtSetServerStackSize(long)
@ -494,7 +494,7 @@
@ stub RpcServerYield @ stub RpcServerYield
@ stub RpcSmAllocate @ stub RpcSmAllocate
@ stub RpcSmClientFree @ stub RpcSmClientFree
@ stub RpcSmDestroyClientContext @ stdcall RpcSmDestroyClientContext(ptr)
@ stub RpcSmDisableAllocate @ stub RpcSmDisableAllocate
@ stub RpcSmEnableAllocate @ stub RpcSmEnableAllocate
@ stub RpcSmFree @ stub RpcSmFree
@ -505,7 +505,7 @@
@ stub RpcSsAllocate @ stub RpcSsAllocate
@ stub RpcSsContextLockExclusive # wxp @ stub RpcSsContextLockExclusive # wxp
@ stub RpcSsContextLockShared # wxp @ stub RpcSsContextLockShared # wxp
@ stub RpcSsDestroyClientContext @ stdcall RpcSsDestroyClientContext(ptr)
@ stub RpcSsDisableAllocate @ stub RpcSsDisableAllocate
@ stub RpcSsDontSerializeContext @ stub RpcSsDontSerializeContext
@ stub RpcSsEnableAllocate @ stub RpcSsEnableAllocate

View file

@ -100,6 +100,8 @@
#include "winerror.h" #include "winerror.h"
#include "winbase.h" #include "winbase.h"
#include "winuser.h" #include "winuser.h"
#include "winnt.h"
#include "winternl.h"
#include "iptypes.h" #include "iptypes.h"
#include "iphlpapi.h" #include "iphlpapi.h"
#include "wine/unicode.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 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 * 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) BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{ {
struct threaddata *tdata;
switch (fdwReason) { switch (fdwReason) {
case DLL_PROCESS_ATTACH: case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hinstDLL);
master_mutex = CreateMutexA( NULL, FALSE, RPCSS_MASTER_MUTEX_NAME); master_mutex = CreateMutexA( NULL, FALSE, RPCSS_MASTER_MUTEX_NAME);
if (!master_mutex) if (!master_mutex)
ERR("Failed to create master mutex\n"); ERR("Failed to create master mutex\n");
break; 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: case DLL_PROCESS_DETACH:
CloseHandle(master_mutex); CloseHandle(master_mutex);
master_mutex = NULL; master_mutex = NULL;
@ -202,10 +249,12 @@ RPC_STATUS WINAPI RpcStringFreeW(RPC_WSTR* String)
* *
* Raises an exception. * 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); RaiseException(exception, 0, 0, NULL);
ERR("handler continued execution\n");
ExitProcess(1);
} }
/************************************************************************* /*************************************************************************
@ -823,8 +872,154 @@ void WINAPI I_RpcFree(void *Object)
/****************************************************************************** /******************************************************************************
* I_RpcMapWin32Status (rpcrt4.@) * I_RpcMapWin32Status (rpcrt4.@)
*/ */
DWORD WINAPI I_RpcMapWin32Status(RPC_STATUS status) LONG WINAPI I_RpcMapWin32Status(RPC_STATUS status)
{ {
FIXME("(%ld): stub\n", status); FIXME("(%ld): stub\n", status);
return 0; 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;
}