mirror of
https://github.com/reactos/reactos.git
synced 2025-04-19 20:19:26 +00:00
- Update rpcrt4 to Wine-20080105, so it corresponds to the WIDL. Local changes applied.
svn path=/trunk/; revision=31631
This commit is contained in:
parent
07dce281aa
commit
ecdee48d72
26 changed files with 12518 additions and 11057 deletions
|
@ -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(¤t_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(¤t_vtbl.table->vtbl, current_vtbl.table->methods, num_methods);
|
||||||
|
VirtualProtect(current_vtbl.table->methods, size, PAGE_EXECUTE_READ, &old_protect);
|
||||||
}
|
}
|
||||||
LeaveCriticalSection(&delegating_vtbl_section);
|
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;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
|
|
345
reactos/dll/win32/rpcrt4_new/ndr_contexthandle.c
Normal file
345
reactos/dll/win32/rpcrt4_new/ndr_contexthandle.c
Normal 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;
|
||||||
|
}
|
|
@ -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
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
236
reactos/dll/win32/rpcrt4_new/ndr_stubless.h
Normal file
236
reactos/dll/win32/rpcrt4_new/ndr_stubless.h
Normal 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"
|
539
reactos/dll/win32/rpcrt4_new/rpc_assoc.c
Normal file
539
reactos/dll/win32/rpcrt4_new/rpc_assoc.c
Normal 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;
|
||||||
|
}
|
58
reactos/dll/win32/rpcrt4_new/rpc_assoc.h
Normal file
58
reactos/dll/win32/rpcrt4_new/rpc_assoc.h
Normal 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);
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue