- Sync rpcrt4 with Wine-1.1.32. ReactOS-specific changes are:

* Use overlapped named pipes access mode, and use GetOverlappedResult for reading/writing too.
 * Add patch for waiting for server calls in RpcMgmtWaitServerListen (not fully correct one, but enough for now).
 * Hacks around ntsecapi.h inclusion (it can't be used properly with winternl.h).
 * Total removal of HTTP transport. Could be enabled when dynamic linking to wininet.dll will be possible.
- Change config.h to include new ASM macros. This is not platform independent.

svn path=/trunk/; revision=44130
This commit is contained in:
Aleksey Bragin 2009-11-13 13:26:54 +00:00
parent 08a2fdadeb
commit 8d0de240d5
26 changed files with 2971 additions and 903 deletions

View file

@ -2,6 +2,7 @@
* COM proxy implementation * COM proxy implementation
* *
* Copyright 2001 Ove Kåven, TransGaming Technologies * Copyright 2001 Ove Kåven, TransGaming Technologies
* Copyright 2009 Alexandre Julliard
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@ -20,6 +21,9 @@
* TODO: Handle non-i386 architectures * TODO: Handle non-i386 architectures
*/ */
#include "config.h"
#include "wine/port.h"
#include <stdarg.h> #include <stdarg.h>
#define COBJMACROS #define COBJMACROS
@ -37,21 +41,19 @@
WINE_DEFAULT_DEBUG_CHANNEL(ole); WINE_DEFAULT_DEBUG_CHANNEL(ole);
struct StublessThunk;
/* I don't know what MS's std proxy structure looks like, /* I don't know what MS's std proxy structure looks like,
so this probably doesn't match, but that shouldn't matter */ so this probably doesn't match, but that shouldn't matter */
typedef struct { typedef struct {
const IRpcProxyBufferVtbl *lpVtbl; const IRpcProxyBufferVtbl *lpVtbl;
LPVOID *PVtbl; LPVOID *PVtbl;
LONG RefCount; LONG RefCount;
const MIDL_STUBLESS_PROXY_INFO *stubless;
const IID* piid; const IID* piid;
LPUNKNOWN pUnkOuter; LPUNKNOWN pUnkOuter;
IUnknown *base_object; /* must be at offset 0x10 from PVtbl */
IRpcProxyBuffer *base_proxy;
PCInterfaceName name; PCInterfaceName name;
LPPSFACTORYBUFFER pPSFactory; LPPSFACTORYBUFFER pPSFactory;
LPRPCCHANNELBUFFER pChannel; LPRPCCHANNELBUFFER pChannel;
struct StublessThunk *thunks;
} StdProxyImpl; } StdProxyImpl;
static const IRpcProxyBufferVtbl StdProxy_Vtbl; static const IRpcProxyBufferVtbl StdProxy_Vtbl;
@ -62,66 +64,111 @@ static const IRpcProxyBufferVtbl StdProxy_Vtbl;
#include "pshpack1.h" #include "pshpack1.h"
struct StublessThunk { struct thunk {
BYTE push; BYTE push;
DWORD index; DWORD index;
BYTE call; BYTE jmp;
LONG handler; LONG handler;
BYTE ret;
WORD bytes;
BYTE pad[3];
}; };
#include "poppack.h" #include "poppack.h"
/* adjust the stack size since we don't use Windows's method */ extern void call_stubless_func(void);
#define STACK_ADJUST sizeof(DWORD) __ASM_GLOBAL_FUNC(call_stubless_func,
"pushl %esp\n\t" /* pointer to index */
__ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
"call " __ASM_NAME("ObjectStubless") __ASM_STDCALL(4) "\n\t"
"popl %edx\n\t" /* args size */
__ASM_CFI(".cfi_adjust_cfa_offset -4\n\t")
"movl (%esp),%ecx\n\t" /* return address */
"addl %edx,%esp\n\t"
"jmp *%ecx" );
#define FILL_STUBLESS(x,idx,stk) \ HRESULT WINAPI ObjectStubless(DWORD *args)
x->push = 0x68; /* pushl [immediate] */ \
x->index = (idx); \
x->call = 0xe8; /* call [near] */ \
x->handler = (char*)ObjectStubless - (char*)&x->ret; \
x->ret = 0xc2; /* ret [immediate] */ \
x->bytes = stk; \
x->pad[0] = 0x8d; /* leal (%esi),%esi */ \
x->pad[1] = 0x76; \
x->pad[2] = 0x00;
static HRESULT WINAPI ObjectStubless(DWORD index)
{ {
char *args = (char*)(&index + 2); DWORD index = args[0];
LPVOID iface = *(LPVOID*)args; void **iface = (void **)args[2];
const void **vtbl = (const void **)*iface;
const MIDL_STUBLESS_PROXY_INFO *stubless = *(const MIDL_STUBLESS_PROXY_INFO **)(vtbl - 2);
const PFORMAT_STRING fs = stubless->ProcFormatString + stubless->FormatStringOffset[index];
ICOM_THIS_MULTI(StdProxyImpl,PVtbl,iface); /* store bytes to remove from stack */
args[0] = *(const WORD*)(fs + 8);
TRACE("(%p)->(%d)([%d bytes]) ret=%08x\n", iface, index, args[0], args[1]);
PFORMAT_STRING fs = This->stubless->ProcFormatString + This->stubless->FormatStringOffset[index]; return NdrClientCall2(stubless->pStubDesc, fs, args + 2);
unsigned bytes = *(const WORD*)(fs+8) - STACK_ADJUST; }
TRACE("(%p)->(%d)([%d bytes]) ret=%08x\n", iface, index, bytes, *(DWORD*)(args+bytes));
return NdrClientCall2(This->stubless->pStubDesc, fs, args); #define BLOCK_SIZE 1024
#define MAX_BLOCKS 64 /* 64k methods should be enough for anybody */
static const struct thunk *method_blocks[MAX_BLOCKS];
static const struct thunk *allocate_block( unsigned int num )
{
unsigned int i;
struct thunk *prev, *block;
block = VirtualAlloc( NULL, BLOCK_SIZE * sizeof(*block),
MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE );
if (!block) return NULL;
for (i = 0; i < BLOCK_SIZE; i++)
{
block[i].push = 0x68; /* pushl */
block[i].index = BLOCK_SIZE * num + i + 3;
block[i].jmp = 0xe9; /* jmp */
block[i].handler = (char *)call_stubless_func - (char *)(&block[i].handler + 1);
}
VirtualProtect( block, BLOCK_SIZE * sizeof(*block), PAGE_EXECUTE_READ, NULL );
prev = InterlockedCompareExchangePointer( (void **)&method_blocks[num], block, NULL );
if (prev) /* someone beat us to it */
{
VirtualFree( block, 0, MEM_RELEASE );
block = prev;
}
return block;
}
static BOOL fill_stubless_table( IUnknownVtbl *vtbl, DWORD num )
{
const void **entry = (const void **)(vtbl + 1);
DWORD i, j;
if (num - 3 > BLOCK_SIZE * MAX_BLOCKS)
{
FIXME( "%u methods not supported\n", num );
return FALSE;
}
for (i = 0; i < (num - 3 + BLOCK_SIZE - 1) / BLOCK_SIZE; i++)
{
const struct thunk *block = method_blocks[i];
if (!block && !(block = allocate_block( i ))) return FALSE;
for (j = 0; j < BLOCK_SIZE && j < num - 3 - i * BLOCK_SIZE; j++, entry++)
if (*entry == (LPVOID)-1) *entry = &block[j];
}
return TRUE;
} }
#else /* __i386__ */ #else /* __i386__ */
/* can't do that on this arch */ static BOOL fill_stubless_table( IUnknownVtbl *vtbl, DWORD num )
struct StublessThunk { int dummy; }; {
#define FILL_STUBLESS(x,idx,stk) \ ERR("stubless proxies are not supported on this architecture\n");
ERR("stubless proxies are not supported on this architecture\n"); return FALSE;
#define STACK_ADJUST 0 }
#endif /* __i386__ */ #endif /* __i386__ */
HRESULT WINAPI StdProxy_Construct(REFIID riid, HRESULT StdProxy_Construct(REFIID riid,
LPUNKNOWN pUnkOuter, LPUNKNOWN pUnkOuter,
const ProxyFileInfo *ProxyInfo, const ProxyFileInfo *ProxyInfo,
int Index, int Index,
LPPSFACTORYBUFFER pPSFactory, LPPSFACTORYBUFFER pPSFactory,
LPRPCPROXYBUFFER *ppProxy, LPRPCPROXYBUFFER *ppProxy,
LPVOID *ppvObj) LPVOID *ppvObj)
{ {
StdProxyImpl *This; StdProxyImpl *This;
const MIDL_STUBLESS_PROXY_INFO *stubless = NULL;
PCInterfaceName name = ProxyInfo->pNamesArray[Index]; PCInterfaceName name = ProxyInfo->pNamesArray[Index];
CInterfaceProxyVtbl *vtbl = ProxyInfo->pProxyVtblList[Index]; CInterfaceProxyVtbl *vtbl = ProxyInfo->pProxyVtblList[Index];
@ -129,14 +176,12 @@ HRESULT WINAPI StdProxy_Construct(REFIID riid,
/* TableVersion = 2 means it is the stubless version of CInterfaceProxyVtbl */ /* TableVersion = 2 means it is the stubless version of CInterfaceProxyVtbl */
if (ProxyInfo->TableVersion > 1) { if (ProxyInfo->TableVersion > 1) {
stubless = *(const void **)vtbl; ULONG count = ProxyInfo->pStubVtblList[Index]->header.DispatchTableCount;
vtbl = (CInterfaceProxyVtbl *)((const void **)vtbl + 1); vtbl = (CInterfaceProxyVtbl *)((const void **)vtbl + 1);
TRACE("stubless=%p\n", stubless); TRACE("stubless vtbl %p: count=%d\n", vtbl->Vtbl, count );
fill_stubless_table( (IUnknownVtbl *)vtbl->Vtbl, count );
} }
TRACE("iid=%s\n", debugstr_guid(vtbl->header.piid));
TRACE("vtbl=%p\n", vtbl->Vtbl);
if (!IsEqualGUID(vtbl->header.piid, riid)) { if (!IsEqualGUID(vtbl->header.piid, riid)) {
ERR("IID mismatch during proxy creation\n"); ERR("IID mismatch during proxy creation\n");
return RPC_E_UNEXPECTED; return RPC_E_UNEXPECTED;
@ -145,51 +190,37 @@ HRESULT WINAPI StdProxy_Construct(REFIID riid,
This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(StdProxyImpl)); This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(StdProxyImpl));
if (!This) return E_OUTOFMEMORY; if (!This) return E_OUTOFMEMORY;
if (stubless) { if (!pUnkOuter) pUnkOuter = (IUnknown *)This;
CInterfaceStubVtbl *svtbl = ProxyInfo->pStubVtblList[Index];
unsigned long i, count = svtbl->header.DispatchTableCount;
/* Maybe the original vtbl is just modified directly to point at
* ObjectStublessClientXXX thunks in real Windows, but I don't like it
*/
TRACE("stubless thunks: count=%ld\n", count);
This->thunks = HeapAlloc(GetProcessHeap(),0,sizeof(struct StublessThunk)*count);
This->PVtbl = HeapAlloc(GetProcessHeap(),0,sizeof(LPVOID)*count);
for (i=0; i<count; i++) {
struct StublessThunk *thunk = &This->thunks[i];
if (vtbl->Vtbl[i] == (LPVOID)-1) {
PFORMAT_STRING fs = stubless->ProcFormatString + stubless->FormatStringOffset[i];
unsigned bytes = *(const WORD*)(fs+8) - STACK_ADJUST;
TRACE("method %ld: stacksize=%d\n", i, bytes);
FILL_STUBLESS(thunk, i, bytes)
This->PVtbl[i] = thunk;
}
else {
memset(thunk, 0, sizeof(struct StublessThunk));
This->PVtbl[i] = vtbl->Vtbl[i];
}
}
}
else
This->PVtbl = vtbl->Vtbl;
This->lpVtbl = &StdProxy_Vtbl; This->lpVtbl = &StdProxy_Vtbl;
This->PVtbl = vtbl->Vtbl;
/* one reference for the proxy */ /* one reference for the proxy */
This->RefCount = 1; This->RefCount = 1;
This->stubless = stubless;
This->piid = vtbl->header.piid; This->piid = vtbl->header.piid;
This->base_object = NULL;
This->base_proxy = NULL;
This->pUnkOuter = pUnkOuter; This->pUnkOuter = pUnkOuter;
This->name = name; This->name = name;
This->pPSFactory = pPSFactory; This->pPSFactory = pPSFactory;
This->pChannel = NULL; This->pChannel = NULL;
if(ProxyInfo->pDelegatedIIDs && ProxyInfo->pDelegatedIIDs[Index])
{
HRESULT r = create_proxy( ProxyInfo->pDelegatedIIDs[Index], NULL,
&This->base_proxy, (void **)&This->base_object );
if (FAILED(r))
{
HeapFree( GetProcessHeap(), 0, This );
return r;
}
}
*ppProxy = (LPRPCPROXYBUFFER)&This->lpVtbl; *ppProxy = (LPRPCPROXYBUFFER)&This->lpVtbl;
*ppvObj = &This->PVtbl; *ppvObj = &This->PVtbl;
/* if there is no outer unknown then the caller will control the lifetime IUnknown_AddRef((IUnknown *)*ppvObj);
* of the proxy object through the proxy buffer, so no need to increment the
* ref count of the proxy object */
if (pUnkOuter)
IUnknown_AddRef((IUnknown *)*ppvObj);
IPSFactoryBuffer_AddRef(pPSFactory); IPSFactoryBuffer_AddRef(pPSFactory);
TRACE( "iid=%s this %p proxy %p obj %p vtbl %p base proxy %p base obj %p\n",
debugstr_guid(riid), This, *ppProxy, *ppvObj, This->PVtbl, This->base_proxy, This->base_object );
return S_OK; return S_OK;
} }
@ -200,11 +231,10 @@ static void StdProxy_Destruct(LPRPCPROXYBUFFER iface)
if (This->pChannel) if (This->pChannel)
IRpcProxyBuffer_Disconnect(iface); IRpcProxyBuffer_Disconnect(iface);
if (This->base_object) IUnknown_Release( This->base_object );
if (This->base_proxy) IRpcProxyBuffer_Release( This->base_proxy );
IPSFactoryBuffer_Release(This->pPSFactory); IPSFactoryBuffer_Release(This->pPSFactory);
if (This->thunks) {
HeapFree(GetProcessHeap(),0,This->PVtbl);
HeapFree(GetProcessHeap(),0,This->thunks);
}
HeapFree(GetProcessHeap(),0,This); HeapFree(GetProcessHeap(),0,This);
} }
@ -259,6 +289,7 @@ static HRESULT WINAPI StdProxy_Connect(LPRPCPROXYBUFFER iface,
This->pChannel = pChannel; This->pChannel = pChannel;
IRpcChannelBuffer_AddRef(pChannel); IRpcChannelBuffer_AddRef(pChannel);
if (This->base_proxy) IRpcProxyBuffer_Connect( This->base_proxy, pChannel );
return S_OK; return S_OK;
} }
@ -267,6 +298,8 @@ static VOID WINAPI StdProxy_Disconnect(LPRPCPROXYBUFFER iface)
ICOM_THIS_MULTI(StdProxyImpl,lpVtbl,iface); ICOM_THIS_MULTI(StdProxyImpl,lpVtbl,iface);
TRACE("(%p)->Disconnect()\n",This); TRACE("(%p)->Disconnect()\n",This);
if (This->base_proxy) IRpcProxyBuffer_Disconnect( This->base_proxy );
IRpcChannelBuffer_Release(This->pChannel); IRpcChannelBuffer_Release(This->pChannel);
This->pChannel = NULL; This->pChannel = NULL;
} }

View file

@ -145,6 +145,41 @@ static const IPSFactoryBufferVtbl CStdPSFactory_Vtbl =
CStdPSFactory_CreateStub CStdPSFactory_CreateStub
}; };
static void init_psfactory( CStdPSFactoryBuffer *psfac, const ProxyFileInfo **file_list )
{
DWORD i, j, k;
psfac->lpVtbl = &CStdPSFactory_Vtbl;
psfac->RefCount = 0;
psfac->pProxyFileList = file_list;
for (i = 0; file_list[i]; i++)
{
const PCInterfaceProxyVtblList *proxies = file_list[i]->pProxyVtblList;
const PCInterfaceStubVtblList *stubs = file_list[i]->pStubVtblList;
for (j = 0; j < file_list[i]->TableSize; j++)
{
/* FIXME: i think that different vtables should be copied for
* async interfaces */
void * const *pSrcRpcStubVtbl = (void * const *)&CStdStubBuffer_Vtbl;
void **pRpcStubVtbl = (void **)&stubs[j]->Vtbl;
if (file_list[i]->pDelegatedIIDs && file_list[i]->pDelegatedIIDs[j])
{
void **vtbl = proxies[j]->Vtbl;
if (file_list[i]->TableVersion > 1) vtbl++;
fill_delegated_proxy_table( (IUnknownVtbl *)vtbl, stubs[j]->header.DispatchTableCount );
pSrcRpcStubVtbl = (void * const *)&CStdStubBuffer_Delegating_Vtbl;
}
for (k = 0; k < sizeof(IRpcStubBufferVtbl)/sizeof(void *); k++)
if (!pRpcStubVtbl[k]) pRpcStubVtbl[k] = pSrcRpcStubVtbl[k];
}
}
}
/*********************************************************************** /***********************************************************************
* NdrDllGetClassObject [RPCRT4.@] * NdrDllGetClassObject [RPCRT4.@]
*/ */
@ -158,35 +193,8 @@ HRESULT WINAPI NdrDllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv,
pPSFactoryBuffer); pPSFactoryBuffer);
*ppv = NULL; *ppv = NULL;
if (!pPSFactoryBuffer->lpVtbl) { if (!pPSFactoryBuffer->lpVtbl) init_psfactory( pPSFactoryBuffer, pProxyFileList );
const ProxyFileInfo **pProxyFileList2;
DWORD max_delegating_vtbl_size = 0;
pPSFactoryBuffer->lpVtbl = &CStdPSFactory_Vtbl;
pPSFactoryBuffer->RefCount = 0;
pPSFactoryBuffer->pProxyFileList = pProxyFileList;
for (pProxyFileList2 = pProxyFileList; *pProxyFileList2; pProxyFileList2++) {
int i;
for (i = 0; i < (*pProxyFileList2)->TableSize; i++) {
/* FIXME: i think that different vtables should be copied for
* async interfaces */
void * const *pSrcRpcStubVtbl = (void * const *)&CStdStubBuffer_Vtbl;
void **pRpcStubVtbl = (void **)&(*pProxyFileList2)->pStubVtblList[i]->Vtbl;
unsigned int j;
if ((*pProxyFileList2)->pDelegatedIIDs && (*pProxyFileList2)->pDelegatedIIDs[i]) {
pSrcRpcStubVtbl = (void * const *)&CStdStubBuffer_Delegating_Vtbl;
if ((*pProxyFileList2)->pStubVtblList[i]->header.DispatchTableCount > max_delegating_vtbl_size)
max_delegating_vtbl_size = (*pProxyFileList2)->pStubVtblList[i]->header.DispatchTableCount;
}
for (j = 0; j < sizeof(IRpcStubBufferVtbl)/sizeof(void *); j++)
if (!pRpcStubVtbl[j])
pRpcStubVtbl[j] = pSrcRpcStubVtbl[j];
}
}
if(max_delegating_vtbl_size > 0)
create_delegating_vtbl(max_delegating_vtbl_size);
}
if (pclsid && IsEqualGUID(rclsid, pclsid)) if (pclsid && IsEqualGUID(rclsid, pclsid))
return IPSFactoryBuffer_QueryInterface((LPPSFACTORYBUFFER)pPSFactoryBuffer, iid, ppv); return IPSFactoryBuffer_QueryInterface((LPPSFACTORYBUFFER)pPSFactoryBuffer, iid, ppv);
else { else {
@ -207,7 +215,7 @@ HRESULT WINAPI NdrDllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv,
*/ */
HRESULT WINAPI NdrDllCanUnloadNow(CStdPSFactoryBuffer *pPSFactoryBuffer) HRESULT WINAPI NdrDllCanUnloadNow(CStdPSFactoryBuffer *pPSFactoryBuffer)
{ {
return !(pPSFactoryBuffer->RefCount); return pPSFactoryBuffer->RefCount != 0 ? S_FALSE : S_OK;
} }
@ -266,7 +274,7 @@ HRESULT WINAPI NdrDllRegisterProxy(HMODULE hDll,
if (len && len < sizeof(module)) { if (len && len < sizeof(module)) {
TRACE("registering CLSID %s => %s\n", debugstr_w(clsid), debugstr_w(module)); TRACE("registering CLSID %s => %s\n", debugstr_w(clsid), debugstr_w(module));
if (RegCreateKeyW(HKEY_CLASSES_ROOT, keyname, &key) == ERROR_SUCCESS) { if (RegCreateKeyW(HKEY_CLASSES_ROOT, keyname, &key) == ERROR_SUCCESS) {
RegSetValueExW(subkey, NULL, 0, REG_SZ, (const BYTE *)psfactoryW, sizeof(psfactoryW)); RegSetValueExW(key, NULL, 0, REG_SZ, (const BYTE *)psfactoryW, sizeof(psfactoryW));
if (RegCreateKeyW(key, inprocserverW, &subkey) == ERROR_SUCCESS) { if (RegCreateKeyW(key, inprocserverW, &subkey) == ERROR_SUCCESS) {
RegSetValueExW(subkey, NULL, 0, REG_SZ, (LPBYTE)module, (strlenW(module)+1)*sizeof(WCHAR)); RegSetValueExW(subkey, NULL, 0, REG_SZ, (LPBYTE)module, (strlenW(module)+1)*sizeof(WCHAR));
RegSetValueExW(subkey, threadingmodelW, 0, REG_SZ, (const BYTE *)bothW, sizeof(bothW)); RegSetValueExW(subkey, threadingmodelW, 0, REG_SZ, (const BYTE *)bothW, sizeof(bothW));

View file

@ -21,36 +21,25 @@
#ifndef __WINE_CPSF_H #ifndef __WINE_CPSF_H
#define __WINE_CPSF_H #define __WINE_CPSF_H
HRESULT WINAPI StdProxy_Construct(REFIID riid, HRESULT StdProxy_Construct(REFIID riid, LPUNKNOWN pUnkOuter, const ProxyFileInfo *ProxyInfo,
LPUNKNOWN pUnkOuter, int Index, LPPSFACTORYBUFFER pPSFactory, LPRPCPROXYBUFFER *ppProxy,
const ProxyFileInfo *ProxyInfo, LPVOID *ppvObj);
int Index,
LPPSFACTORYBUFFER pPSFactory,
LPRPCPROXYBUFFER *ppProxy,
LPVOID *ppvObj);
HRESULT WINAPI CStdStubBuffer_Construct(REFIID riid, HRESULT CStdStubBuffer_Construct(REFIID riid, LPUNKNOWN pUnkServer, PCInterfaceName name,
LPUNKNOWN pUnkServer, CInterfaceStubVtbl *vtbl, LPPSFACTORYBUFFER pPSFactory,
PCInterfaceName name, LPRPCSTUBBUFFER *ppStub);
CInterfaceStubVtbl *vtbl,
LPPSFACTORYBUFFER pPSFactory,
LPRPCSTUBBUFFER *ppStub);
HRESULT WINAPI CStdStubBuffer_Delegating_Construct(REFIID riid, HRESULT CStdStubBuffer_Delegating_Construct(REFIID riid, LPUNKNOWN pUnkServer, PCInterfaceName name,
LPUNKNOWN pUnkServer, CInterfaceStubVtbl *vtbl, REFIID delegating_iid,
PCInterfaceName name, LPPSFACTORYBUFFER pPSFactory, LPRPCSTUBBUFFER *ppStub);
CInterfaceStubVtbl *vtbl,
REFIID delegating_iid,
LPPSFACTORYBUFFER pPSFactory,
LPRPCSTUBBUFFER *ppStub);
const MIDL_SERVER_INFO *CStdStubBuffer_GetServerInfo(IRpcStubBuffer *iface); const MIDL_SERVER_INFO *CStdStubBuffer_GetServerInfo(IRpcStubBuffer *iface);
const IRpcStubBufferVtbl CStdStubBuffer_Vtbl; const IRpcStubBufferVtbl CStdStubBuffer_Vtbl;
const IRpcStubBufferVtbl CStdStubBuffer_Delegating_Vtbl; const IRpcStubBufferVtbl CStdStubBuffer_Delegating_Vtbl;
void create_delegating_vtbl(DWORD num_methods); BOOL fill_delegated_proxy_table(IUnknownVtbl *vtbl, DWORD num);
HRESULT create_proxy(REFIID iid, IUnknown *pUnkOuter, IRpcProxyBuffer **pproxy, void **ppv);
HRESULT create_stub(REFIID iid, IUnknown *pUnk, IRpcStubBuffer **ppstub); HRESULT create_stub(REFIID iid, IUnknown *pUnk, IRpcStubBuffer **ppstub);
#endif /* __WINE_CPSF_H */ #endif /* __WINE_CPSF_H */

View file

@ -2,6 +2,7 @@
* COM stub (CStdStubBuffer) implementation * COM stub (CStdStubBuffer) implementation
* *
* Copyright 2001 Ove Kåven, TransGaming Technologies * Copyright 2001 Ove Kåven, TransGaming Technologies
* Copyright 2009 Alexandre Julliard
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@ -61,12 +62,12 @@ static inline cstdstubbuffer_delegating_t *impl_from_delegating( IRpcStubBuffer
return (cstdstubbuffer_delegating_t*)((char *)iface - FIELD_OFFSET(cstdstubbuffer_delegating_t, stub_buffer)); return (cstdstubbuffer_delegating_t*)((char *)iface - FIELD_OFFSET(cstdstubbuffer_delegating_t, stub_buffer));
} }
HRESULT WINAPI CStdStubBuffer_Construct(REFIID riid, HRESULT CStdStubBuffer_Construct(REFIID riid,
LPUNKNOWN pUnkServer, LPUNKNOWN pUnkServer,
PCInterfaceName name, PCInterfaceName name,
CInterfaceStubVtbl *vtbl, CInterfaceStubVtbl *vtbl,
LPPSFACTORYBUFFER pPSFactory, LPPSFACTORYBUFFER pPSFactory,
LPRPCSTUBBUFFER *ppStub) LPRPCSTUBBUFFER *ppStub)
{ {
CStdStubBuffer *This; CStdStubBuffer *This;
IUnknown *pvServer; IUnknown *pvServer;
@ -113,20 +114,16 @@ typedef struct
{ {
DWORD ref; DWORD ref;
DWORD size; DWORD size;
void **methods;
IUnknownVtbl vtbl; IUnknownVtbl vtbl;
/* remaining entries in vtbl */ /* remaining entries in vtbl */
} ref_counted_vtbl; } ref_counted_vtbl;
static struct static ref_counted_vtbl *current_vtbl;
{
ref_counted_vtbl *table;
} current_vtbl;
static HRESULT WINAPI delegating_QueryInterface(IUnknown *pUnk, REFIID iid, void **ppv) static HRESULT WINAPI delegating_QueryInterface(IUnknown *pUnk, REFIID iid, void **ppv)
{ {
*ppv = (void *)pUnk; *ppv = pUnk;
return S_OK; return S_OK;
} }
@ -161,87 +158,137 @@ typedef struct {
} vtbl_method_t; } vtbl_method_t;
#include "poppack.h" #include "poppack.h"
static void fill_table(IUnknownVtbl *vtbl, void **methods, DWORD num) #define BLOCK_SIZE 1024
{ #define MAX_BLOCKS 64 /* 64k methods should be enough for anybody */
vtbl_method_t *method;
void **entry;
DWORD i;
static const vtbl_method_t *method_blocks[MAX_BLOCKS];
static const vtbl_method_t *allocate_block( unsigned int num )
{
unsigned int i;
vtbl_method_t *prev, *block;
block = VirtualAlloc( NULL, BLOCK_SIZE * sizeof(*block),
MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE );
if (!block) return NULL;
for (i = 0; i < BLOCK_SIZE; i++)
{
block[i].mov1 = 0x0424448b;
block[i].mov2 = 0x408b;
block[i].sixteen = 0x10;
block[i].mov3 = 0x04244489;
block[i].mov4 = 0x008b;
block[i].mov5 = 0x808b;
block[i].offset = (BLOCK_SIZE * num + i + 3) << 2;
block[i].jmp = 0xe0ff;
block[i].pad[0] = 0x8d;
block[i].pad[1] = 0x76;
block[i].pad[2] = 0x00;
}
VirtualProtect( block, BLOCK_SIZE * sizeof(*block), PAGE_EXECUTE_READ, NULL );
prev = InterlockedCompareExchangePointer( (void **)&method_blocks[num], block, NULL );
if (prev) /* someone beat us to it */
{
VirtualFree( block, 0, MEM_RELEASE );
block = prev;
}
return block;
}
static BOOL fill_delegated_stub_table(IUnknownVtbl *vtbl, DWORD num)
{
const void **entry = (const void **)(vtbl + 1);
DWORD i, j;
if (num - 3 > BLOCK_SIZE * MAX_BLOCKS)
{
FIXME( "%u methods not supported\n", num );
return FALSE;
}
vtbl->QueryInterface = delegating_QueryInterface; vtbl->QueryInterface = delegating_QueryInterface;
vtbl->AddRef = delegating_AddRef; vtbl->AddRef = delegating_AddRef;
vtbl->Release = delegating_Release; vtbl->Release = delegating_Release;
for (i = 0; i < (num - 3 + BLOCK_SIZE - 1) / BLOCK_SIZE; i++)
method = (vtbl_method_t*)methods;
entry = (void**)(vtbl + 1);
for(i = 3; i < num; i++)
{ {
*entry = method; const vtbl_method_t *block = method_blocks[i];
method->mov1 = 0x0424448b; if (!block && !(block = allocate_block( i ))) return FALSE;
method->mov2 = 0x408b; for (j = 0; j < BLOCK_SIZE && j < num - 3 - i * BLOCK_SIZE; j++) *entry++ = &block[j];
method->sixteen = 0x10;
method->mov3 = 0x04244489;
method->mov4 = 0x008b;
method->mov5 = 0x808b;
method->offset = i << 2;
method->jmp = 0xe0ff;
method->pad[0] = 0x8d;
method->pad[1] = 0x76;
method->pad[2] = 0x00;
method++;
entry++;
} }
return TRUE;
}
BOOL fill_delegated_proxy_table(IUnknownVtbl *vtbl, DWORD num)
{
const void **entry = (const void **)(vtbl + 1);
DWORD i, j;
if (num - 3 > BLOCK_SIZE * MAX_BLOCKS)
{
FIXME( "%u methods not supported\n", num );
return FALSE;
}
vtbl->QueryInterface = IUnknown_QueryInterface_Proxy;
vtbl->AddRef = IUnknown_AddRef_Proxy;
vtbl->Release = IUnknown_Release_Proxy;
for (i = 0; i < (num - 3 + BLOCK_SIZE - 1) / BLOCK_SIZE; i++)
{
const vtbl_method_t *block = method_blocks[i];
if (!block && !(block = allocate_block( i ))) return FALSE;
for (j = 0; j < BLOCK_SIZE && j < num - 3 - i * BLOCK_SIZE; j++, entry++)
if (!*entry) *entry = &block[j];
}
return TRUE;
} }
#else /* __i386__ */ #else /* __i386__ */
typedef struct {int dummy;} vtbl_method_t; static BOOL fill_delegated_stub_table(IUnknownVtbl *vtbl, DWORD num)
static void fill_table(IUnknownVtbl *vtbl, void **methods, DWORD num)
{ {
ERR("delegated stubs are not supported on this architecture\n"); ERR("delegated stubs are not supported on this architecture\n");
return FALSE;
}
BOOL fill_delegated_proxy_table(IUnknownVtbl *vtbl, DWORD num)
{
ERR("delegated proxies are not supported on this architecture\n");
return FALSE;
} }
#endif /* __i386__ */ #endif /* __i386__ */
void create_delegating_vtbl(DWORD num_methods) static IUnknownVtbl *get_delegating_vtbl(DWORD num_methods)
{
TRACE("%d\n", num_methods);
if(num_methods <= 3)
{
ERR("should have more than %d methods\n", num_methods);
return;
}
EnterCriticalSection(&delegating_vtbl_section);
if(!current_vtbl.table || num_methods > current_vtbl.table->size)
{
DWORD size;
DWORD old_protect;
if(current_vtbl.table && current_vtbl.table->ref == 0)
{
TRACE("freeing old table\n");
VirtualFree(current_vtbl.table->methods, 0, MEM_RELEASE);
HeapFree(GetProcessHeap(), 0, current_vtbl.table);
}
size = (num_methods - 3) * sizeof(vtbl_method_t);
current_vtbl.table = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(ref_counted_vtbl, vtbl) + num_methods * sizeof(void*));
current_vtbl.table->ref = 0;
current_vtbl.table->size = num_methods;
current_vtbl.table->methods = VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
fill_table(&current_vtbl.table->vtbl, current_vtbl.table->methods, num_methods);
VirtualProtect(current_vtbl.table->methods, size, PAGE_EXECUTE_READ, &old_protect);
}
LeaveCriticalSection(&delegating_vtbl_section);
}
static IUnknownVtbl *get_delegating_vtbl(void)
{ {
IUnknownVtbl *ret; IUnknownVtbl *ret;
if (num_methods < 256) num_methods = 256; /* avoid frequent reallocations */
EnterCriticalSection(&delegating_vtbl_section); EnterCriticalSection(&delegating_vtbl_section);
current_vtbl.table->ref++;
ret = &current_vtbl.table->vtbl; if(!current_vtbl || num_methods > current_vtbl->size)
{
ref_counted_vtbl *table = HeapAlloc(GetProcessHeap(), 0,
FIELD_OFFSET(ref_counted_vtbl, vtbl) + num_methods * sizeof(void*));
if (!table)
{
LeaveCriticalSection(&delegating_vtbl_section);
return NULL;
}
table->ref = 0;
table->size = num_methods;
fill_delegated_stub_table(&table->vtbl, num_methods);
if (current_vtbl && current_vtbl->ref == 0)
{
TRACE("freeing old table\n");
HeapFree(GetProcessHeap(), 0, current_vtbl);
}
current_vtbl = table;
}
current_vtbl->ref++;
ret = &current_vtbl->vtbl;
LeaveCriticalSection(&delegating_vtbl_section); LeaveCriticalSection(&delegating_vtbl_section);
return ret; return ret;
} }
@ -253,22 +300,21 @@ static void release_delegating_vtbl(IUnknownVtbl *vtbl)
EnterCriticalSection(&delegating_vtbl_section); EnterCriticalSection(&delegating_vtbl_section);
table->ref--; table->ref--;
TRACE("ref now %d\n", table->ref); TRACE("ref now %d\n", table->ref);
if(table->ref == 0 && table != current_vtbl.table) if(table->ref == 0 && table != current_vtbl)
{ {
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, 0, MEM_RELEASE);
HeapFree(GetProcessHeap(), 0, table); HeapFree(GetProcessHeap(), 0, table);
} }
LeaveCriticalSection(&delegating_vtbl_section); LeaveCriticalSection(&delegating_vtbl_section);
} }
HRESULT WINAPI CStdStubBuffer_Delegating_Construct(REFIID riid, HRESULT CStdStubBuffer_Delegating_Construct(REFIID riid,
LPUNKNOWN pUnkServer, LPUNKNOWN pUnkServer,
PCInterfaceName name, PCInterfaceName name,
CInterfaceStubVtbl *vtbl, CInterfaceStubVtbl *vtbl,
REFIID delegating_iid, REFIID delegating_iid,
LPPSFACTORYBUFFER pPSFactory, LPPSFACTORYBUFFER pPSFactory,
LPRPCSTUBBUFFER *ppStub) LPRPCSTUBBUFFER *ppStub)
{ {
cstdstubbuffer_delegating_t *This; cstdstubbuffer_delegating_t *This;
IUnknown *pvServer; IUnknown *pvServer;
@ -294,7 +340,7 @@ HRESULT WINAPI CStdStubBuffer_Delegating_Construct(REFIID riid,
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
} }
This->base_obj = get_delegating_vtbl(); This->base_obj = get_delegating_vtbl( vtbl->header.DispatchTableCount );
r = create_stub(delegating_iid, (IUnknown*)&This->base_obj, &This->base_stub); r = create_stub(delegating_iid, (IUnknown*)&This->base_obj, &This->base_stub);
if(FAILED(r)) if(FAILED(r))
{ {

View file

@ -19,7 +19,7 @@
* *
*/ */
#include "epm_c.h" #include "epm.h"
#define EPM_PROTOCOL_DNET_NSP 0x04 #define EPM_PROTOCOL_DNET_NSP 0x04
#define EPM_PROTOCOL_OSI_TP4 0x05 #define EPM_PROTOCOL_OSI_TP4 0x05

View file

@ -59,7 +59,7 @@ 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) static struct context_handle_entry *get_context_entry(NDR_CCONTEXT CContext)
{ {
struct context_handle_entry *che = (struct context_handle_entry*) CContext; struct context_handle_entry *che = CContext;
if (che->magic != NDR_CONTEXT_HANDLE_MAGIC) if (che->magic != NDR_CONTEXT_HANDLE_MAGIC)
return NULL; return NULL;
@ -111,7 +111,7 @@ void WINAPI NDRCContextMarshall(NDR_CCONTEXT CContext, void *pBuff)
} }
else else
{ {
ndr_context_handle *wire_data = (ndr_context_handle *)pBuff; ndr_context_handle *wire_data = pBuff;
wire_data->attributes = 0; wire_data->attributes = 0;
wire_data->uuid = GUID_NULL; wire_data->uuid = GUID_NULL;
} }

View file

@ -62,6 +62,6 @@ extern const NDR_BUFFERSIZE NdrBufferSizer[];
extern const NDR_MEMORYSIZE NdrMemorySizer[]; extern const NDR_MEMORYSIZE NdrMemorySizer[];
extern const NDR_FREE NdrFreer[]; extern const NDR_FREE NdrFreer[];
unsigned long ComplexStructSize(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat); ULONG ComplexStructSize(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat);
#endif /* __WINE_NDR_MISC_H */ #endif /* __WINE_NDR_MISC_H */

View file

@ -369,6 +369,30 @@ void WINAPI NdrOleFree(void *NodeToFree)
COM_MemFree(NodeToFree); COM_MemFree(NodeToFree);
} }
/***********************************************************************
* Helper function to create a proxy.
* Probably similar to NdrpCreateProxy.
*/
HRESULT create_proxy(REFIID iid, IUnknown *pUnkOuter, IRpcProxyBuffer **pproxy, void **ppv)
{
CLSID clsid;
IPSFactoryBuffer *psfac;
HRESULT r;
if(!LoadCOM()) return E_FAIL;
r = COM_GetPSClsid( iid, &clsid );
if(FAILED(r)) return r;
r = COM_GetClassObject( &clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IPSFactoryBuffer, (void**)&psfac );
if(FAILED(r)) return r;
r = IPSFactoryBuffer_CreateProxy(psfac, pUnkOuter, iid, pproxy, ppv);
IPSFactoryBuffer_Release(psfac);
return r;
}
/*********************************************************************** /***********************************************************************
* Helper function to create a stub. * Helper function to create a stub.
* This probably looks very much like NdrpCreateStub. * This probably looks very much like NdrpCreateStub.

View file

@ -173,7 +173,7 @@ static PFORMAT_STRING client_get_handle(
if (pDesc->flag_and_size & HANDLE_PARAM_IS_VIA_PTR) if (pDesc->flag_and_size & HANDLE_PARAM_IS_VIA_PTR)
pArg = *(void **)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset); pArg = *(void **)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset);
else else
pArg = (void *)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset); pArg = ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset);
memcpy(&pObject, pArg, pDesc->flag_and_size & 0xf); memcpy(&pObject, pArg, pDesc->flag_and_size & 0xf);
pGenPair = &pStubMsg->StubDesc->aGenericBindingRoutinePairs[pDesc->binding_routine_pair_index]; pGenPair = &pStubMsg->StubDesc->aGenericBindingRoutinePairs[pDesc->binding_routine_pair_index];
*phBinding = pGenPair->pfnBind(pObject); *phBinding = pGenPair->pfnBind(pObject);
@ -256,7 +256,7 @@ static void client_free_handle(
if (pDesc->flag_and_size & HANDLE_PARAM_IS_VIA_PTR) if (pDesc->flag_and_size & HANDLE_PARAM_IS_VIA_PTR)
pArg = *(void **)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset); pArg = *(void **)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset);
else else
pArg = (void *)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset); pArg = ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset);
memcpy(&pObject, pArg, pDesc->flag_and_size & 0xf); memcpy(&pObject, pArg, pDesc->flag_and_size & 0xf);
pGenPair = &pStubMsg->StubDesc->aGenericBindingRoutinePairs[pDesc->binding_routine_pair_index]; pGenPair = &pStubMsg->StubDesc->aGenericBindingRoutinePairs[pDesc->binding_routine_pair_index];
pGenPair->pfnUnbind(pObject, hBinding); pGenPair->pfnUnbind(pObject, hBinding);
@ -867,9 +867,14 @@ __declspec(naked) LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigne
LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned int stack_size); LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned int stack_size);
__ASM_GLOBAL_FUNC(call_server_func, __ASM_GLOBAL_FUNC(call_server_func,
"pushl %ebp\n\t" "pushl %ebp\n\t"
"movl %esp, %ebp\n\t" __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
__ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
"movl %esp,%ebp\n\t"
__ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
"pushl %edi\n\t" /* Save registers */ "pushl %edi\n\t" /* Save registers */
__ASM_CFI(".cfi_rel_offset %edi,-4\n\t")
"pushl %esi\n\t" "pushl %esi\n\t"
__ASM_CFI(".cfi_rel_offset %esi,-8\n\t")
"movl 16(%ebp), %eax\n\t" /* Get stack size */ "movl 16(%ebp), %eax\n\t" /* Get stack size */
"subl %eax, %esp\n\t" /* Make room in stack for arguments */ "subl %eax, %esp\n\t" /* Make room in stack for arguments */
"andl $~15, %esp\n\t" /* Make sure stack has 16-byte alignment for Mac OS X */ "andl $~15, %esp\n\t" /* Make sure stack has 16-byte alignment for Mac OS X */
@ -882,9 +887,13 @@ __ASM_GLOBAL_FUNC(call_server_func,
"call *8(%ebp)\n\t" /* Call function */ "call *8(%ebp)\n\t" /* Call function */
"leal -8(%ebp), %esp\n\t" /* Restore stack */ "leal -8(%ebp), %esp\n\t" /* Restore stack */
"popl %esi\n\t" /* Restore registers */ "popl %esi\n\t" /* Restore registers */
__ASM_CFI(".cfi_same_value %esi\n\t")
"popl %edi\n\t" "popl %edi\n\t"
__ASM_CFI(".cfi_same_value %edi\n\t")
"popl %ebp\n\t" "popl %ebp\n\t"
"ret\n" ) __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
__ASM_CFI(".cfi_same_value %ebp\n\t")
"ret" )
#else #else
#warning call_server_func not implemented for your architecture #warning call_server_func not implemented for your architecture
LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned short stack_size) LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned short stack_size)
@ -1522,3 +1531,339 @@ void WINAPI NdrServerCall2(PRPC_MESSAGE pRpcMsg)
DWORD dwPhase; DWORD dwPhase;
NdrStubCall2(NULL, NULL, pRpcMsg, &dwPhase); NdrStubCall2(NULL, NULL, pRpcMsg, &dwPhase);
} }
struct async_call_data
{
MIDL_STUB_MESSAGE *pStubMsg;
const NDR_PROC_HEADER *pProcHeader;
PFORMAT_STRING pHandleFormat;
PFORMAT_STRING pParamFormat;
RPC_BINDING_HANDLE hBinding;
/* size of stack */
unsigned short stack_size;
/* number of parameters. optional for client to give it to us */
unsigned char number_of_params;
/* correlation cache */
unsigned long NdrCorrCache[256];
};
LONG_PTR WINAPIV NdrAsyncClientCall(PMIDL_STUB_DESC pStubDesc,
PFORMAT_STRING pFormat, ...)
{
/* pointer to start of stack where arguments start */
PRPC_MESSAGE pRpcMsg;
PMIDL_STUB_MESSAGE pStubMsg;
RPC_ASYNC_STATE *pAsync;
struct async_call_data *async_call_data;
/* procedure number */
unsigned short procedure_number;
/* cache of Oif_flags from v2 procedure header */
INTERPRETER_OPT_FLAGS Oif_flags = { 0 };
/* cache of extension flags from NDR_PROC_HEADER_EXTS */
INTERPRETER_OPT_FLAGS2 ext_flags = { 0 };
/* the type of pass we are currently doing */
int phase;
/* header for procedure string */
const NDR_PROC_HEADER * pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0];
/* -Oif or -Oicf generated format */
BOOL bV2Format = FALSE;
TRACE("pStubDesc %p, pFormat %p, ...\n", pStubDesc, pFormat);
/* Later NDR language versions probably won't be backwards compatible */
if (pStubDesc->Version > 0x50002)
{
FIXME("Incompatible stub description version: 0x%x\n", pStubDesc->Version);
RpcRaiseException(RPC_X_WRONG_STUB_VERSION);
}
async_call_data = I_RpcAllocate(sizeof(*async_call_data) + sizeof(MIDL_STUB_MESSAGE) + sizeof(RPC_MESSAGE));
if (!async_call_data) RpcRaiseException(ERROR_OUTOFMEMORY);
async_call_data->number_of_params = ~0;
async_call_data->pProcHeader = pProcHeader;
async_call_data->pStubMsg = pStubMsg = (PMIDL_STUB_MESSAGE)(async_call_data + 1);
pRpcMsg = (PRPC_MESSAGE)(pStubMsg + 1);
if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS)
{
const NDR_PROC_HEADER_RPC *pProcHeader = (const NDR_PROC_HEADER_RPC *)&pFormat[0];
async_call_data->stack_size = pProcHeader->stack_size;
procedure_number = pProcHeader->proc_num;
pFormat += sizeof(NDR_PROC_HEADER_RPC);
}
else
{
async_call_data->stack_size = pProcHeader->stack_size;
procedure_number = pProcHeader->proc_num;
pFormat += sizeof(NDR_PROC_HEADER);
}
TRACE("stack size: 0x%x\n", async_call_data->stack_size);
TRACE("proc num: %d\n", procedure_number);
/* create the full pointer translation tables, if requested */
if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR)
pStubMsg->FullPtrXlatTables = NdrFullPointerXlatInit(0,XLAT_CLIENT);
if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)
{
ERR("objects not supported\n");
I_RpcFree(async_call_data);
RpcRaiseException(RPC_X_BAD_STUB_DATA);
}
NdrClientInitializeNew(pRpcMsg, pStubMsg, pStubDesc, procedure_number);
TRACE("Oi_flags = 0x%02x\n", pProcHeader->Oi_flags);
TRACE("MIDL stub version = 0x%x\n", pStubDesc->MIDLVersion);
/* needed for conformance of top-level objects */
#ifdef __i386__
pStubMsg->StackTop = I_RpcAllocate(async_call_data->stack_size);
/* FIXME: this may read one more DWORD than is necessary, but it shouldn't hurt */
memcpy(pStubMsg->StackTop, *(unsigned char **)(&pFormat+1), async_call_data->stack_size);
#else
# warning Stack not retrieved for your CPU architecture
#endif
pAsync = *(RPC_ASYNC_STATE **)pStubMsg->StackTop;
pAsync->StubInfo = async_call_data;
async_call_data->pHandleFormat = pFormat;
pFormat = client_get_handle(pStubMsg, pProcHeader, async_call_data->pHandleFormat, &async_call_data->hBinding);
if (!pFormat) return 0;
bV2Format = (pStubDesc->Version >= 0x20000);
if (bV2Format)
{
const NDR_PROC_PARTIAL_OIF_HEADER *pOIFHeader =
(const NDR_PROC_PARTIAL_OIF_HEADER *)pFormat;
Oif_flags = pOIFHeader->Oi2Flags;
async_call_data->number_of_params = pOIFHeader->number_of_params;
pFormat += sizeof(NDR_PROC_PARTIAL_OIF_HEADER);
}
TRACE("Oif_flags = "); dump_INTERPRETER_OPT_FLAGS(Oif_flags);
if (Oif_flags.HasExtensions)
{
const NDR_PROC_HEADER_EXTS *pExtensions =
(const NDR_PROC_HEADER_EXTS *)pFormat;
ext_flags = pExtensions->Flags2;
pFormat += pExtensions->Size;
}
async_call_data->pParamFormat = pFormat;
pStubMsg->BufferLength = 0;
/* store the RPC flags away */
if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS)
pRpcMsg->RpcFlags = ((const NDR_PROC_HEADER_RPC *)pProcHeader)->rpc_flags;
/* use alternate memory allocation routines */
if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCSSALLOC)
NdrRpcSmSetClientToOsf(pStubMsg);
if (Oif_flags.HasPipes)
{
FIXME("pipes not supported yet\n");
RpcRaiseException(RPC_X_WRONG_STUB_VERSION); /* FIXME: remove when implemented */
/* init pipes package */
/* NdrPipesInitialize(...) */
}
if (ext_flags.HasNewCorrDesc)
{
/* initialize extra correlation package */
NdrCorrelationInitialize(pStubMsg, async_call_data->NdrCorrCache, sizeof(async_call_data->NdrCorrCache), 0);
}
/* order of phases:
* 1. PROXY_CALCSIZE - calculate the buffer size
* 2. PROXY_GETBUFFER - allocate the buffer
* 3. PROXY_MARHSAL - marshal [in] params into the buffer
* 4. PROXY_SENDRECEIVE - send buffer
* Then in NdrpCompleteAsyncClientCall:
* 1. PROXY_SENDRECEIVE - receive buffer
* 2. PROXY_UNMARHSAL - unmarshal [out] params from buffer
*/
for (phase = PROXY_CALCSIZE; phase <= PROXY_SENDRECEIVE; phase++)
{
RPC_STATUS status;
TRACE("phase = %d\n", phase);
switch (phase)
{
case PROXY_GETBUFFER:
/* allocate the buffer */
if (Oif_flags.HasPipes)
/* NdrGetPipeBuffer(...) */
FIXME("pipes not supported yet\n");
else
{
if (pProcHeader->handle_type == RPC_FC_AUTO_HANDLE)
#if 0
NdrNsGetBuffer(pStubMsg, pStubMsg->BufferLength, async_call_data->hBinding);
#else
FIXME("using auto handle - call NdrNsGetBuffer when it gets implemented\n");
#endif
else
NdrGetBuffer(pStubMsg, pStubMsg->BufferLength, async_call_data->hBinding);
}
pRpcMsg->RpcFlags |= RPC_BUFFER_ASYNC;
status = I_RpcAsyncSetHandle(pRpcMsg, pAsync);
if (status != RPC_S_OK)
RpcRaiseException(status);
break;
case PROXY_SENDRECEIVE:
pRpcMsg->RpcFlags |= RPC_BUFFER_ASYNC;
/* send the [in] params only */
if (Oif_flags.HasPipes)
/* NdrPipesSend(...) */
FIXME("pipes not supported yet\n");
else
{
if (pProcHeader->handle_type == RPC_FC_AUTO_HANDLE)
#if 0
NdrNsSend(&stubMsg, stubMsg.Buffer, pStubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle);
#else
FIXME("using auto handle - call NdrNsSend when it gets implemented\n");
#endif
else
{
pStubMsg->RpcMsg->BufferLength = pStubMsg->Buffer - (unsigned char *)pStubMsg->RpcMsg->Buffer;
status = I_RpcSend(pStubMsg->RpcMsg);
if (status != RPC_S_OK)
RpcRaiseException(status);
}
}
break;
case PROXY_CALCSIZE:
case PROXY_MARSHAL:
if (bV2Format)
client_do_args(pStubMsg, pFormat, phase, pStubMsg->StackTop,
async_call_data->number_of_params, NULL);
else
client_do_args_old_format(pStubMsg, pFormat, phase,
pStubMsg->StackTop, async_call_data->stack_size, NULL,
(pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT), FALSE);
break;
default:
ERR("shouldn't reach here. phase %d\n", phase);
break;
}
}
TRACE("returning 0\n");
return 0;
}
RPC_STATUS NdrpCompleteAsyncClientCall(RPC_ASYNC_STATE *pAsync, void *Reply)
{
/* pointer to start of stack where arguments start */
PMIDL_STUB_MESSAGE pStubMsg;
struct async_call_data *async_call_data;
/* the type of pass we are currently doing */
int phase;
/* header for procedure string */
const NDR_PROC_HEADER * pProcHeader;
/* -Oif or -Oicf generated format */
BOOL bV2Format;
RPC_STATUS status = RPC_S_OK;
if (!pAsync->StubInfo)
return RPC_S_INVALID_ASYNC_HANDLE;
async_call_data = pAsync->StubInfo;
pStubMsg = async_call_data->pStubMsg;
pProcHeader = async_call_data->pProcHeader;
bV2Format = (pStubMsg->StubDesc->Version >= 0x20000);
/* order of phases:
* 1. PROXY_CALCSIZE - calculate the buffer size
* 2. PROXY_GETBUFFER - allocate the buffer
* 3. PROXY_MARHSAL - marshal [in] params into the buffer
* 4. PROXY_SENDRECEIVE - send buffer
* Then in NdrpCompleteAsyncClientCall:
* 1. PROXY_SENDRECEIVE - receive buffer
* 2. PROXY_UNMARHSAL - unmarshal [out] params from buffer
*/
for (phase = PROXY_SENDRECEIVE; phase <= PROXY_UNMARSHAL; phase++)
{
switch (phase)
{
case PROXY_SENDRECEIVE:
pStubMsg->RpcMsg->RpcFlags |= RPC_BUFFER_ASYNC;
/* receive the [out] params */
if (pProcHeader->handle_type == RPC_FC_AUTO_HANDLE)
#if 0
NdrNsReceive(&stubMsg, stubMsg.Buffer, pStubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle);
#else
FIXME("using auto handle - call NdrNsReceive when it gets implemented\n");
#endif
else
{
status = I_RpcReceive(pStubMsg->RpcMsg);
if (status != RPC_S_OK)
goto cleanup;
pStubMsg->BufferLength = pStubMsg->RpcMsg->BufferLength;
pStubMsg->BufferStart = pStubMsg->RpcMsg->Buffer;
pStubMsg->BufferEnd = pStubMsg->BufferStart + pStubMsg->BufferLength;
pStubMsg->Buffer = pStubMsg->BufferStart;
}
/* convert strings, floating point values and endianess into our
* preferred format */
#if 0
if ((pStubMsg->RpcMsg.DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION)
NdrConvert(pStubMsg, pFormat);
#endif
break;
case PROXY_UNMARSHAL:
if (bV2Format)
client_do_args(pStubMsg, async_call_data->pParamFormat, phase, pStubMsg->StackTop,
async_call_data->number_of_params, Reply);
else
client_do_args_old_format(pStubMsg, async_call_data->pParamFormat, phase,
pStubMsg->StackTop, async_call_data->stack_size, Reply, FALSE, FALSE);
break;
default:
ERR("shouldn't reach here. phase %d\n", phase);
break;
}
}
cleanup:
if (pStubMsg->fHasNewCorrDesc)
{
/* free extra correlation package */
NdrCorrelationFree(pStubMsg);
}
/* free the full pointer translation tables */
if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR)
NdrFullPointerXlatFree(pStubMsg->FullPtrXlatTables);
/* free marshalling buffer */
NdrFreeBuffer(pStubMsg);
client_free_handle(pStubMsg, pProcHeader, async_call_data->pHandleFormat, async_call_data->hBinding);
I_RpcFree(pStubMsg->StackTop);
I_RpcFree(async_call_data);
TRACE("-- 0x%x\n", status);
return status;
}
RPCRTAPI LONG RPC_ENTRY NdrAsyncStubCall(struct IRpcStubBuffer* pThis,
struct IRpcChannelBuffer* pChannel, PRPC_MESSAGE pRpcMsg,
DWORD * pdwStubPhase)
{
FIXME("unimplemented, expect crash!\n");
return 0;
}

View file

@ -85,7 +85,7 @@ typedef struct _NDR_PROC_HEADER_RPC
* RPCF_Asynchronous = 0x4000 - [async] MIDL attribute * RPCF_Asynchronous = 0x4000 - [async] MIDL attribute
* Reserved = 0x8000 * Reserved = 0x8000
*/ */
unsigned long rpc_flags; unsigned int rpc_flags;
unsigned short proc_num; unsigned short proc_num;
unsigned short stack_size; unsigned short stack_size;
@ -240,3 +240,4 @@ void client_do_args_old_format(PMIDL_STUB_MESSAGE pStubMsg,
PFORMAT_STRING pFormat, int phase, unsigned char *args, PFORMAT_STRING pFormat, int phase, unsigned char *args,
unsigned short stack_size, unsigned char *pRetVal, BOOL object_proc, unsigned short stack_size, unsigned char *pRetVal, BOOL object_proc,
BOOL ignore_retval); BOOL ignore_retval);
RPC_STATUS NdrpCompleteAsyncClientCall(RPC_ASYNC_STATE *pAsync, void *Reply);

View file

@ -125,7 +125,7 @@ RPC_STATUS RPCRT4_GetAssociation(LPCSTR Protseq, LPCSTR NetworkAddr,
RPC_STATUS RpcServerAssoc_GetAssociation(LPCSTR Protseq, LPCSTR NetworkAddr, RPC_STATUS RpcServerAssoc_GetAssociation(LPCSTR Protseq, LPCSTR NetworkAddr,
LPCSTR Endpoint, LPCWSTR NetworkOptions, LPCSTR Endpoint, LPCWSTR NetworkOptions,
unsigned long assoc_gid, ULONG assoc_gid,
RpcAssoc **assoc_out) RpcAssoc **assoc_out)
{ {
RpcAssoc *assoc; RpcAssoc *assoc;
@ -223,7 +223,7 @@ static RPC_STATUS RpcAssoc_BindConnection(const RpcAssoc *assoc, RpcConnection *
RPC_MESSAGE msg; RPC_MESSAGE msg;
RPC_STATUS status; RPC_STATUS status;
unsigned char *auth_data = NULL; unsigned char *auth_data = NULL;
unsigned long auth_length; ULONG auth_length;
TRACE("sending bind request to server\n"); TRACE("sending bind request to server\n");
@ -394,6 +394,7 @@ RPC_STATUS RpcAssoc_GetClientConnection(RpcAssoc *assoc,
if (status != RPC_S_OK) if (status != RPC_S_OK)
return status; return status;
NewConnection->assoc = assoc;
status = RPCRT4_OpenClientConnection(NewConnection); status = RPCRT4_OpenClientConnection(NewConnection);
if (status != RPC_S_OK) if (status != RPC_S_OK)
{ {
@ -416,6 +417,7 @@ RPC_STATUS RpcAssoc_GetClientConnection(RpcAssoc *assoc,
void RpcAssoc_ReleaseIdleConnection(RpcAssoc *assoc, RpcConnection *Connection) void RpcAssoc_ReleaseIdleConnection(RpcAssoc *assoc, RpcConnection *Connection)
{ {
assert(!Connection->server); assert(!Connection->server);
Connection->async_state = NULL;
EnterCriticalSection(&assoc->cs); EnterCriticalSection(&assoc->cs);
if (!assoc->assoc_group_id) assoc->assoc_group_id = Connection->assoc_group_id; if (!assoc->assoc_group_id) assoc->assoc_group_id = Connection->assoc_group_id;
list_add_head(&assoc->free_connection_pool, &Connection->conn_pool_entry); list_add_head(&assoc->free_connection_pool, &Connection->conn_pool_entry);

View file

@ -34,6 +34,7 @@ typedef struct _RpcAssoc
/* id of this association group */ /* id of this association group */
ULONG assoc_group_id; ULONG assoc_group_id;
UUID http_uuid;
CRITICAL_SECTION cs; CRITICAL_SECTION cs;
@ -49,7 +50,7 @@ RPC_STATUS RPCRT4_GetAssociation(LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endp
RPC_STATUS RpcAssoc_GetClientConnection(RpcAssoc *assoc, const RPC_SYNTAX_IDENTIFIER *InterfaceId, const RPC_SYNTAX_IDENTIFIER *TransferSyntax, RpcAuthInfo *AuthInfo, RpcQualityOfService *QOS, RpcConnection **Connection); 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); void RpcAssoc_ReleaseIdleConnection(RpcAssoc *assoc, RpcConnection *Connection);
ULONG RpcAssoc_Release(RpcAssoc *assoc); 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_GetAssociation(LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint, LPCWSTR NetworkOptions, ULONG assoc_gid, RpcAssoc **assoc_out);
RPC_STATUS RpcServerAssoc_AllocateContextHandle(RpcAssoc *assoc, void *CtxGuard, NDR_SCONTEXT *SContext); 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_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); RPC_STATUS RpcServerAssoc_UpdateContextHandle(RpcAssoc *assoc, NDR_SCONTEXT SContext, void *CtxGuard, NDR_RUNDOWN rundown_routine);

View file

@ -29,11 +29,17 @@
#include "rpc_binding.h" #include "rpc_binding.h"
#include "rpc_message.h" #include "rpc_message.h"
#include "ndr_stubless.h"
WINE_DEFAULT_DEBUG_CHANNEL(rpc); WINE_DEFAULT_DEBUG_CHANNEL(rpc);
#define RPC_ASYNC_SIGNATURE 0x43595341 #define RPC_ASYNC_SIGNATURE 0x43595341
static inline BOOL valid_async_handle(PRPC_ASYNC_STATE pAsync)
{
return pAsync->Signature == RPC_ASYNC_SIGNATURE;
}
/*********************************************************************** /***********************************************************************
* RpcAsyncInitializeHandle [RPCRT4.@] * RpcAsyncInitializeHandle [RPCRT4.@]
* *
@ -104,8 +110,14 @@ RPC_STATUS WINAPI RpcAsyncGetCallStatus(PRPC_ASYNC_STATE pAsync)
*/ */
RPC_STATUS WINAPI RpcAsyncCompleteCall(PRPC_ASYNC_STATE pAsync, void *Reply) RPC_STATUS WINAPI RpcAsyncCompleteCall(PRPC_ASYNC_STATE pAsync, void *Reply)
{ {
FIXME("(%p, %p): stub\n", pAsync, Reply); TRACE("(%p, %p)\n", pAsync, Reply);
return RPC_S_INVALID_ASYNC_HANDLE;
if (!valid_async_handle(pAsync))
return RPC_S_INVALID_ASYNC_HANDLE;
/* FIXME: check completed */
return NdrpCompleteAsyncClientCall(pAsync, Reply);
} }
/*********************************************************************** /***********************************************************************

View file

@ -661,11 +661,11 @@ RPC_STATUS WINAPI RpcStringBindingParseA( RPC_CSTR StringBinding, RPC_CSTR *ObjU
return RPC_S_OK; return RPC_S_OK;
fail: fail:
if (ObjUuid) RpcStringFreeA((unsigned char**)ObjUuid); if (ObjUuid) RpcStringFreeA(ObjUuid);
if (Protseq) RpcStringFreeA((unsigned char**)Protseq); if (Protseq) RpcStringFreeA(Protseq);
if (NetworkAddr) RpcStringFreeA((unsigned char**)NetworkAddr); if (NetworkAddr) RpcStringFreeA(NetworkAddr);
if (Endpoint) RpcStringFreeA((unsigned char**)Endpoint); if (Endpoint) RpcStringFreeA(Endpoint);
if (Options) RpcStringFreeA((unsigned char**)Options); if (Options) RpcStringFreeA(Options);
return RPC_S_INVALID_STRING_BINDING; return RPC_S_INVALID_STRING_BINDING;
} }
@ -796,7 +796,7 @@ RPC_STATUS WINAPI RpcBindingFree( RPC_BINDING_HANDLE* Binding )
RPC_STATUS WINAPI RpcBindingVectorFree( RPC_BINDING_VECTOR** BindingVector ) RPC_STATUS WINAPI RpcBindingVectorFree( RPC_BINDING_VECTOR** BindingVector )
{ {
RPC_STATUS status; RPC_STATUS status;
unsigned long c; ULONG c;
TRACE("(%p)\n", BindingVector); TRACE("(%p)\n", BindingVector);
for (c=0; c<(*BindingVector)->Count; c++) { for (c=0; c<(*BindingVector)->Count; c++) {
@ -812,7 +812,7 @@ RPC_STATUS WINAPI RpcBindingVectorFree( RPC_BINDING_VECTOR** BindingVector )
*/ */
RPC_STATUS WINAPI RpcBindingInqObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid ) RPC_STATUS WINAPI RpcBindingInqObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid )
{ {
RpcBinding* bind = (RpcBinding*)Binding; RpcBinding* bind = Binding;
TRACE("(%p,%p) = %s\n", Binding, ObjectUuid, debugstr_guid(&bind->ObjectUuid)); TRACE("(%p,%p) = %s\n", Binding, ObjectUuid, debugstr_guid(&bind->ObjectUuid));
*ObjectUuid = bind->ObjectUuid; *ObjectUuid = bind->ObjectUuid;
@ -824,7 +824,7 @@ RPC_STATUS WINAPI RpcBindingInqObject( RPC_BINDING_HANDLE Binding, UUID* ObjectU
*/ */
RPC_STATUS WINAPI RpcBindingSetObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid ) RPC_STATUS WINAPI RpcBindingSetObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid )
{ {
RpcBinding* bind = (RpcBinding*)Binding; RpcBinding* bind = Binding;
TRACE("(%p,%s)\n", Binding, debugstr_guid(ObjectUuid)); TRACE("(%p,%s)\n", Binding, debugstr_guid(ObjectUuid));
if (bind->server) return RPC_S_WRONG_KIND_OF_BINDING; if (bind->server) return RPC_S_WRONG_KIND_OF_BINDING;
@ -856,11 +856,11 @@ RPC_STATUS WINAPI RpcBindingFromStringBindingA( RPC_CSTR StringBinding, RPC_BIND
if (ret == RPC_S_OK) if (ret == RPC_S_OK)
ret = RPCRT4_CompleteBindingA(bind, (char*)NetworkAddr, (char*)Endpoint, (char*)Options); ret = RPCRT4_CompleteBindingA(bind, (char*)NetworkAddr, (char*)Endpoint, (char*)Options);
RpcStringFreeA((unsigned char**)&Options); RpcStringFreeA(&Options);
RpcStringFreeA((unsigned char**)&Endpoint); RpcStringFreeA(&Endpoint);
RpcStringFreeA((unsigned char**)&NetworkAddr); RpcStringFreeA(&NetworkAddr);
RpcStringFreeA((unsigned char**)&Protseq); RpcStringFreeA(&Protseq);
RpcStringFreeA((unsigned char**)&ObjectUuid); RpcStringFreeA(&ObjectUuid);
if (ret == RPC_S_OK) if (ret == RPC_S_OK)
*Binding = (RPC_BINDING_HANDLE)bind; *Binding = (RPC_BINDING_HANDLE)bind;
@ -915,7 +915,7 @@ RPC_STATUS WINAPI RpcBindingFromStringBindingW( RPC_WSTR StringBinding, RPC_BIND
RPC_STATUS WINAPI RpcBindingToStringBindingA( RPC_BINDING_HANDLE Binding, RPC_CSTR *StringBinding ) RPC_STATUS WINAPI RpcBindingToStringBindingA( RPC_BINDING_HANDLE Binding, RPC_CSTR *StringBinding )
{ {
RPC_STATUS ret; RPC_STATUS ret;
RpcBinding* bind = (RpcBinding*)Binding; RpcBinding* bind = Binding;
RPC_CSTR ObjectUuid; RPC_CSTR ObjectUuid;
TRACE("(%p,%p)\n", Binding, StringBinding); TRACE("(%p,%p)\n", Binding, StringBinding);
@ -946,7 +946,7 @@ RPC_STATUS WINAPI RpcBindingToStringBindingW( RPC_BINDING_HANDLE Binding, RPC_WS
TRACE("(%p,%p)\n", Binding, StringBinding); TRACE("(%p,%p)\n", Binding, StringBinding);
ret = RpcBindingToStringBindingA(Binding, &str); ret = RpcBindingToStringBindingA(Binding, &str);
*StringBinding = RPCRT4_strdupAtoW((char*)str); *StringBinding = RPCRT4_strdupAtoW((char*)str);
RpcStringFreeA((unsigned char**)&str); RpcStringFreeA(&str);
return ret; return ret;
} }
@ -969,7 +969,7 @@ RPC_STATUS WINAPI I_RpcBindingInqTransportType( RPC_BINDING_HANDLE Binding, unsi
*/ */
RPC_STATUS WINAPI I_RpcBindingSetAsync( RPC_BINDING_HANDLE Binding, RPC_BLOCKING_FN BlockingFn) RPC_STATUS WINAPI I_RpcBindingSetAsync( RPC_BINDING_HANDLE Binding, RPC_BLOCKING_FN BlockingFn)
{ {
RpcBinding* bind = (RpcBinding*)Binding; RpcBinding* bind = Binding;
TRACE( "(%p,%p): stub\n", Binding, BlockingFn ); TRACE( "(%p,%p): stub\n", Binding, BlockingFn );
@ -986,7 +986,7 @@ RPC_STATUS RPC_ENTRY RpcBindingCopy(
RPC_BINDING_HANDLE* DestinationBinding) RPC_BINDING_HANDLE* DestinationBinding)
{ {
RpcBinding *DestBinding; RpcBinding *DestBinding;
RpcBinding *SrcBinding = (RpcBinding*)SourceBinding; RpcBinding *SrcBinding = SourceBinding;
RPC_STATUS status; RPC_STATUS status;
TRACE("(%p, %p)\n", SourceBinding, DestinationBinding); TRACE("(%p, %p)\n", SourceBinding, DestinationBinding);
@ -1501,7 +1501,7 @@ RpcBindingSetAuthInfoExA( RPC_BINDING_HANDLE Binding, RPC_CSTR ServerPrincName,
RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr,
RPC_SECURITY_QOS *SecurityQos ) RPC_SECURITY_QOS *SecurityQos )
{ {
RpcBinding* bind = (RpcBinding*)Binding; RpcBinding* bind = Binding;
SECURITY_STATUS r; SECURITY_STATUS r;
CredHandle cred; CredHandle cred;
TimeStamp exp; TimeStamp exp;
@ -1631,7 +1631,7 @@ RpcBindingSetAuthInfoExW( RPC_BINDING_HANDLE Binding, RPC_WSTR ServerPrincName,
ULONG AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr, ULONG AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr,
RPC_SECURITY_QOS *SecurityQos ) RPC_SECURITY_QOS *SecurityQos )
{ {
RpcBinding* bind = (RpcBinding*)Binding; RpcBinding* bind = Binding;
SECURITY_STATUS r; SECURITY_STATUS r;
CredHandle cred; CredHandle cred;
TimeStamp exp; TimeStamp exp;
@ -1640,7 +1640,7 @@ RpcBindingSetAuthInfoExW( RPC_BINDING_HANDLE Binding, RPC_WSTR ServerPrincName,
PSecPkgInfoW packages; PSecPkgInfoW packages;
ULONG cbMaxToken; ULONG cbMaxToken;
TRACE("%p %s %u %u %p %u %p\n", Binding, debugstr_w((const WCHAR*)ServerPrincName), TRACE("%p %s %u %u %p %u %p\n", Binding, debugstr_w(ServerPrincName),
AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, SecurityQos); AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, SecurityQos);
if (SecurityQos) if (SecurityQos)
@ -1772,7 +1772,7 @@ RPCRTAPI RPC_STATUS RPC_ENTRY
RpcBindingSetAuthInfoW( RPC_BINDING_HANDLE Binding, RPC_WSTR ServerPrincName, ULONG AuthnLevel, RpcBindingSetAuthInfoW( RPC_BINDING_HANDLE Binding, RPC_WSTR ServerPrincName, ULONG AuthnLevel,
ULONG AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr ) ULONG AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr )
{ {
TRACE("%p %s %u %u %p %u\n", Binding, debugstr_w((const WCHAR*)ServerPrincName), TRACE("%p %s %u %u %p %u\n", Binding, debugstr_w(ServerPrincName),
AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr); AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr);
return RpcBindingSetAuthInfoExW(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, NULL); return RpcBindingSetAuthInfoExW(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, NULL);
} }

View file

@ -24,6 +24,7 @@
#include "rpcndr.h" #include "rpcndr.h"
#include "security.h" #include "security.h"
#include "wine/list.h" #include "wine/list.h"
#include "rpc_defs.h"
typedef struct _RpcAuthInfo typedef struct _RpcAuthInfo
@ -66,6 +67,7 @@ typedef struct _RpcConnection
TimeStamp exp; TimeStamp exp;
ULONG attr; ULONG attr;
RpcAuthInfo *AuthInfo; RpcAuthInfo *AuthInfo;
ULONG auth_context_id;
ULONG encryption_auth_len; ULONG encryption_auth_len;
ULONG signature_auth_len; ULONG signature_auth_len;
RpcQualityOfService *QOS; RpcQualityOfService *QOS;
@ -74,6 +76,7 @@ typedef struct _RpcConnection
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 */
RPC_ASYNC_STATE *async_state; RPC_ASYNC_STATE *async_state;
struct _RpcAssoc *assoc; /* association this connection is part of */
/* server-only */ /* server-only */
/* The active interface bound to server. */ /* The active interface bound to server. */
@ -96,6 +99,7 @@ struct connection_ops {
int (*wait_for_incoming_data)(RpcConnection *conn); int (*wait_for_incoming_data)(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);
RPC_STATUS (*receive_fragment)(RpcConnection *conn, RpcPktHdr **Header, void **Payload);
}; };
/* don't know what MS's structure looks like */ /* don't know what MS's structure looks like */

View file

@ -31,13 +31,13 @@ typedef struct
unsigned char drep[4]; /* Data representation */ unsigned char drep[4]; /* Data representation */
unsigned short frag_len; /* Data size in bytes including header and tail. */ unsigned short frag_len; /* Data size in bytes including header and tail. */
unsigned short auth_len; /* Authentication length */ unsigned short auth_len; /* Authentication length */
unsigned long call_id; /* Call identifier. */ unsigned int call_id; /* Call identifier. */
} RpcPktCommonHdr; } RpcPktCommonHdr;
typedef struct typedef struct
{ {
RpcPktCommonHdr common; RpcPktCommonHdr common;
unsigned long alloc_hint; /* Data size in bytes excluding header and tail. */ unsigned int alloc_hint; /* Data size in bytes excluding header and tail. */
unsigned short context_id; /* Presentation context identifier */ unsigned short context_id; /* Presentation context identifier */
unsigned short opnum; unsigned short opnum;
} RpcPktRequestHdr; } RpcPktRequestHdr;
@ -45,7 +45,7 @@ typedef struct
typedef struct typedef struct
{ {
RpcPktCommonHdr common; RpcPktCommonHdr common;
unsigned long alloc_hint; /* Data size in bytes excluding header and tail. */ unsigned int alloc_hint; /* Data size in bytes excluding header and tail. */
unsigned short context_id; /* Presentation context identifier */ unsigned short context_id; /* Presentation context identifier */
unsigned char cancel_count; unsigned char cancel_count;
unsigned char reserved; unsigned char reserved;
@ -54,12 +54,12 @@ typedef struct
typedef struct typedef struct
{ {
RpcPktCommonHdr common; RpcPktCommonHdr common;
unsigned long alloc_hint; /* Data size in bytes excluding header and tail. */ unsigned int alloc_hint; /* Data size in bytes excluding header and tail. */
unsigned short context_id; /* Presentation context identifier */ unsigned short context_id; /* Presentation context identifier */
unsigned char cancel_count; /* Received cancel count */ unsigned char cancel_count; /* Received cancel count */
unsigned char reserved; /* Force alignment! */ unsigned char reserved; /* Force alignment! */
unsigned long status; /* Runtime fault code (RPC_STATUS) */ unsigned int status; /* Runtime fault code (RPC_STATUS) */
unsigned long reserved2; unsigned int reserved2;
} RpcPktFaultHdr; } RpcPktFaultHdr;
typedef struct typedef struct
@ -67,7 +67,7 @@ typedef struct
RpcPktCommonHdr common; RpcPktCommonHdr common;
unsigned short max_tsize; /* Maximum transmission fragment size */ unsigned short max_tsize; /* Maximum transmission fragment size */
unsigned short max_rsize; /* Maximum receive fragment size */ unsigned short max_rsize; /* Maximum receive fragment size */
unsigned long assoc_gid; /* Associated group id */ unsigned int assoc_gid; /* Associated group id */
unsigned char num_elements; /* Number of elements */ unsigned char num_elements; /* Number of elements */
unsigned char padding[3]; /* Force alignment! */ unsigned char padding[3]; /* Force alignment! */
unsigned short context_id; /* Presentation context identifier */ unsigned short context_id; /* Presentation context identifier */
@ -99,7 +99,7 @@ typedef struct
RpcPktCommonHdr common; RpcPktCommonHdr common;
unsigned short max_tsize; /* Maximum transmission fragment size */ unsigned short max_tsize; /* Maximum transmission fragment size */
unsigned short max_rsize; /* Maximum receive fragment size */ unsigned short max_rsize; /* Maximum receive fragment size */
unsigned long assoc_gid; /* Associated group id */ unsigned int assoc_gid; /* Associated group id */
/* /*
* Following this header are these fields: * Following this header are these fields:
* RpcAddressString server_address; * RpcAddressString server_address;
@ -120,6 +120,14 @@ typedef struct
} protocols[1]; } protocols[1];
} RpcPktBindNAckHdr; } RpcPktBindNAckHdr;
/* undocumented packet sent during RPC over HTTP */
typedef struct
{
RpcPktCommonHdr common;
unsigned short flags;
unsigned short num_data_items;
} RpcPktHttpHdr;
/* Union representing all possible packet headers */ /* Union representing all possible packet headers */
typedef union typedef union
{ {
@ -130,6 +138,7 @@ typedef union
RpcPktBindHdr bind; RpcPktBindHdr bind;
RpcPktBindAckHdr bind_ack; RpcPktBindAckHdr bind_ack;
RpcPktBindNAckHdr bind_nack; RpcPktBindNAckHdr bind_nack;
RpcPktHttpHdr http;
} RpcPktHdr; } RpcPktHdr;
typedef struct typedef struct
@ -138,7 +147,7 @@ typedef struct
unsigned char auth_level; /* RPC_C_AUTHN_LEVEL* */ unsigned char auth_level; /* RPC_C_AUTHN_LEVEL* */
unsigned char auth_pad_length; /* length of padding to restore n % 4 alignment */ unsigned char auth_pad_length; /* length of padding to restore n % 4 alignment */
unsigned char auth_reserved; /* reserved, must be zero */ unsigned char auth_reserved; /* reserved, must be zero */
unsigned long auth_context_id; /* unique value for the authenticated connection */ unsigned int auth_context_id; /* unique value for the authenticated connection */
} RpcAuthVerifier; } RpcAuthVerifier;
#define RPC_AUTH_VERIFIER_LEN(common_hdr) \ #define RPC_AUTH_VERIFIER_LEN(common_hdr) \
@ -174,6 +183,7 @@ typedef struct
#define PKT_SHUTDOWN 17 #define PKT_SHUTDOWN 17
#define PKT_CO_CANCEL 18 #define PKT_CO_CANCEL 18
#define PKT_ORPHANED 19 #define PKT_ORPHANED 19
#define PKT_HTTP 20
#define RESULT_ACCEPT 0 #define RESULT_ACCEPT 0
#define RESULT_USER_REJECTION 1 #define RESULT_USER_REJECTION 1

View file

@ -32,7 +32,7 @@
#include "wine/exception.h" #include "wine/exception.h"
#include "rpc_binding.h" #include "rpc_binding.h"
#include "epm_c.h" #include "epm.h"
#include "epm_towers.h" #include "epm_towers.h"
WINE_DEFAULT_DEBUG_CHANNEL(ole); WINE_DEFAULT_DEBUG_CHANNEL(ole);
@ -116,7 +116,7 @@ static BOOL start_rpcss(void)
static inline BOOL is_epm_destination_local(RPC_BINDING_HANDLE handle) static inline BOOL is_epm_destination_local(RPC_BINDING_HANDLE handle)
{ {
RpcBinding *bind = (RpcBinding *)handle; RpcBinding *bind = handle;
const char *protseq = bind->Protseq; const char *protseq = bind->Protseq;
const char *network_addr = bind->NetworkAddr; const char *network_addr = bind->NetworkAddr;
@ -127,7 +127,7 @@ static inline BOOL is_epm_destination_local(RPC_BINDING_HANDLE handle)
static RPC_STATUS get_epm_handle_client(RPC_BINDING_HANDLE handle, RPC_BINDING_HANDLE *epm_handle) static RPC_STATUS get_epm_handle_client(RPC_BINDING_HANDLE handle, RPC_BINDING_HANDLE *epm_handle)
{ {
RpcBinding *bind = (RpcBinding *)handle; RpcBinding *bind = handle;
const char * pszEndpoint = NULL; const char * pszEndpoint = NULL;
RPC_STATUS status; RPC_STATUS status;
RpcBinding* epm_bind; RpcBinding* epm_bind;
@ -149,7 +149,7 @@ static RPC_STATUS get_epm_handle_client(RPC_BINDING_HANDLE handle, RPC_BINDING_H
status = RpcBindingCopy(handle, epm_handle); status = RpcBindingCopy(handle, epm_handle);
if (status != RPC_S_OK) return status; if (status != RPC_S_OK) return status;
epm_bind = (RpcBinding*)*epm_handle; epm_bind = *epm_handle;
if (epm_bind->AuthInfo) if (epm_bind->AuthInfo)
{ {
/* don't bother with authenticating against the EPM by default /* don't bother with authenticating against the EPM by default
@ -187,8 +187,8 @@ static LONG WINAPI rpc_filter(EXCEPTION_POINTERS *__eptr)
RPC_STATUS WINAPI RpcEpRegisterA( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *BindingVector, RPC_STATUS WINAPI RpcEpRegisterA( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *BindingVector,
UUID_VECTOR *UuidVector, RPC_CSTR Annotation ) UUID_VECTOR *UuidVector, RPC_CSTR Annotation )
{ {
PRPC_SERVER_INTERFACE If = (PRPC_SERVER_INTERFACE)IfSpec; PRPC_SERVER_INTERFACE If = IfSpec;
unsigned long i; ULONG i;
RPC_STATUS status = RPC_S_OK; RPC_STATUS status = RPC_S_OK;
error_status_t status2; error_status_t status2;
ept_entry_t *entries; ept_entry_t *entries;
@ -197,13 +197,13 @@ RPC_STATUS WINAPI RpcEpRegisterA( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *Bind
TRACE("(%p,%p,%p,%s)\n", IfSpec, BindingVector, UuidVector, debugstr_a((char*)Annotation)); TRACE("(%p,%p,%p,%s)\n", IfSpec, BindingVector, UuidVector, debugstr_a((char*)Annotation));
TRACE(" ifid=%s\n", debugstr_guid(&If->InterfaceId.SyntaxGUID)); TRACE(" ifid=%s\n", debugstr_guid(&If->InterfaceId.SyntaxGUID));
for (i=0; i<BindingVector->Count; i++) { for (i=0; i<BindingVector->Count; i++) {
RpcBinding* bind = (RpcBinding*)(BindingVector->BindingH[i]); RpcBinding* bind = BindingVector->BindingH[i];
TRACE(" protseq[%ld]=%s\n", i, debugstr_a(bind->Protseq)); TRACE(" protseq[%d]=%s\n", i, debugstr_a(bind->Protseq));
TRACE(" endpoint[%ld]=%s\n", i, debugstr_a(bind->Endpoint)); TRACE(" endpoint[%d]=%s\n", i, debugstr_a(bind->Endpoint));
} }
if (UuidVector) { if (UuidVector) {
for (i=0; i<UuidVector->Count; i++) for (i=0; i<UuidVector->Count; i++)
TRACE(" obj[%ld]=%s\n", i, debugstr_guid(UuidVector->Uuid[i])); TRACE(" obj[%d]=%s\n", i, debugstr_guid(UuidVector->Uuid[i]));
} }
if (!BindingVector->Count) return RPC_S_OK; if (!BindingVector->Count) return RPC_S_OK;
@ -222,10 +222,9 @@ RPC_STATUS WINAPI RpcEpRegisterA( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *Bind
for (i = 0; i < BindingVector->Count; i++) for (i = 0; i < BindingVector->Count; i++)
{ {
unsigned j; unsigned j;
RpcBinding* bind = (RpcBinding*)(BindingVector->BindingH[i]); RpcBinding* bind = BindingVector->BindingH[i];
for (j = 0; j < (UuidVector ? UuidVector->Count : 1); j++) for (j = 0; j < (UuidVector ? UuidVector->Count : 1); j++)
{ {
int len = strlen((char *)Annotation);
status = TowerConstruct(&If->InterfaceId, &If->TransferSyntax, status = TowerConstruct(&If->InterfaceId, &If->TransferSyntax,
bind->Protseq, bind->Endpoint, bind->Protseq, bind->Endpoint,
bind->NetworkAddr, bind->NetworkAddr,
@ -236,7 +235,9 @@ RPC_STATUS WINAPI RpcEpRegisterA( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *Bind
memcpy(&entries[i * UuidVector->Count].object, &UuidVector->Uuid[j], sizeof(GUID)); memcpy(&entries[i * UuidVector->Count].object, &UuidVector->Uuid[j], sizeof(GUID));
else else
memset(&entries[i].object, 0, sizeof(entries[i].object)); memset(&entries[i].object, 0, sizeof(entries[i].object));
memcpy(entries[i].annotation, Annotation, min(len + 1, ept_max_annotation_size)); if (Annotation)
memcpy(entries[i].annotation, Annotation,
min(strlen((char *)Annotation) + 1, ept_max_annotation_size));
} }
} }
@ -280,14 +281,29 @@ RPC_STATUS WINAPI RpcEpRegisterA( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *Bind
return status; return status;
} }
/***********************************************************************
* RpcEpRegisterW (RPCRT4.@)
*/
RPC_STATUS WINAPI RpcEpRegisterW( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *BindingVector,
UUID_VECTOR *UuidVector, RPC_WSTR Annotation )
{
LPSTR annA = RPCRT4_strdupWtoA(Annotation);
RPC_STATUS status;
status = RpcEpRegisterA(IfSpec, BindingVector, UuidVector, (RPC_CSTR)annA);
HeapFree(GetProcessHeap(), 0, annA);
return status;
}
/*********************************************************************** /***********************************************************************
* RpcEpUnregister (RPCRT4.@) * RpcEpUnregister (RPCRT4.@)
*/ */
RPC_STATUS WINAPI RpcEpUnregister( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *BindingVector, RPC_STATUS WINAPI RpcEpUnregister( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *BindingVector,
UUID_VECTOR *UuidVector ) UUID_VECTOR *UuidVector )
{ {
PRPC_SERVER_INTERFACE If = (PRPC_SERVER_INTERFACE)IfSpec; PRPC_SERVER_INTERFACE If = IfSpec;
unsigned long i; ULONG i;
RPC_STATUS status = RPC_S_OK; RPC_STATUS status = RPC_S_OK;
error_status_t status2; error_status_t status2;
ept_entry_t *entries; ept_entry_t *entries;
@ -296,13 +312,13 @@ RPC_STATUS WINAPI RpcEpUnregister( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *Bin
TRACE("(%p,%p,%p)\n", IfSpec, BindingVector, UuidVector); TRACE("(%p,%p,%p)\n", IfSpec, BindingVector, UuidVector);
TRACE(" ifid=%s\n", debugstr_guid(&If->InterfaceId.SyntaxGUID)); TRACE(" ifid=%s\n", debugstr_guid(&If->InterfaceId.SyntaxGUID));
for (i=0; i<BindingVector->Count; i++) { for (i=0; i<BindingVector->Count; i++) {
RpcBinding* bind = (RpcBinding*)(BindingVector->BindingH[i]); RpcBinding* bind = BindingVector->BindingH[i];
TRACE(" protseq[%ld]=%s\n", i, debugstr_a(bind->Protseq)); TRACE(" protseq[%d]=%s\n", i, debugstr_a(bind->Protseq));
TRACE(" endpoint[%ld]=%s\n", i, debugstr_a(bind->Endpoint)); TRACE(" endpoint[%d]=%s\n", i, debugstr_a(bind->Endpoint));
} }
if (UuidVector) { if (UuidVector) {
for (i=0; i<UuidVector->Count; i++) for (i=0; i<UuidVector->Count; i++)
TRACE(" obj[%ld]=%s\n", i, debugstr_guid(UuidVector->Uuid[i])); TRACE(" obj[%d]=%s\n", i, debugstr_guid(UuidVector->Uuid[i]));
} }
entries = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*entries) * BindingVector->Count * (UuidVector ? UuidVector->Count : 1)); entries = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*entries) * BindingVector->Count * (UuidVector ? UuidVector->Count : 1));
@ -319,7 +335,7 @@ RPC_STATUS WINAPI RpcEpUnregister( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *Bin
for (i = 0; i < BindingVector->Count; i++) for (i = 0; i < BindingVector->Count; i++)
{ {
unsigned j; unsigned j;
RpcBinding* bind = (RpcBinding*)(BindingVector->BindingH[i]); RpcBinding* bind = BindingVector->BindingH[i];
for (j = 0; j < (UuidVector ? UuidVector->Count : 1); j++) for (j = 0; j < (UuidVector ? UuidVector->Count : 1); j++)
{ {
status = TowerConstruct(&If->InterfaceId, &If->TransferSyntax, status = TowerConstruct(&If->InterfaceId, &If->TransferSyntax,
@ -372,8 +388,8 @@ RPC_STATUS WINAPI RpcEpUnregister( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *Bin
*/ */
RPC_STATUS WINAPI RpcEpResolveBinding( RPC_BINDING_HANDLE Binding, RPC_IF_HANDLE IfSpec ) RPC_STATUS WINAPI RpcEpResolveBinding( RPC_BINDING_HANDLE Binding, RPC_IF_HANDLE IfSpec )
{ {
PRPC_CLIENT_INTERFACE If = (PRPC_CLIENT_INTERFACE)IfSpec; PRPC_CLIENT_INTERFACE If = IfSpec;
RpcBinding* bind = (RpcBinding*)Binding; RpcBinding* bind = Binding;
RPC_STATUS status; RPC_STATUS status;
error_status_t status2; error_status_t status2;
handle_t handle; handle_t handle;

View file

@ -59,13 +59,13 @@ enum secure_packet_direction
static RPC_STATUS I_RpcReAllocateBuffer(PRPC_MESSAGE pMsg); static RPC_STATUS I_RpcReAllocateBuffer(PRPC_MESSAGE pMsg);
static DWORD RPCRT4_GetHeaderSize(const RpcPktHdr *Header) DWORD RPCRT4_GetHeaderSize(const RpcPktHdr *Header)
{ {
static const DWORD header_sizes[] = { static const DWORD header_sizes[] = {
sizeof(Header->request), 0, sizeof(Header->response), sizeof(Header->request), 0, sizeof(Header->response),
sizeof(Header->fault), 0, 0, 0, 0, 0, 0, 0, sizeof(Header->bind), sizeof(Header->fault), 0, 0, 0, 0, 0, 0, 0, sizeof(Header->bind),
sizeof(Header->bind_ack), sizeof(Header->bind_nack), sizeof(Header->bind_ack), sizeof(Header->bind_nack),
0, 0, 0, 0, 0 0, 0, 0, 0, 0, 0, sizeof(Header->http)
}; };
ULONG ret = 0; ULONG ret = 0;
@ -76,7 +76,7 @@ static DWORD RPCRT4_GetHeaderSize(const RpcPktHdr *Header)
if (Header->common.flags & RPC_FLG_OBJECT_UUID) if (Header->common.flags & RPC_FLG_OBJECT_UUID)
ret += sizeof(UUID); ret += sizeof(UUID);
} else { } else {
TRACE("invalid packet type\n"); WARN("invalid packet type %u\n", Header->common.ptype);
} }
return ret; return ret;
@ -96,7 +96,7 @@ static int packet_has_auth_verifier(const RpcPktHdr *Header)
} }
static VOID RPCRT4_BuildCommonHeader(RpcPktHdr *Header, unsigned char PacketType, static VOID RPCRT4_BuildCommonHeader(RpcPktHdr *Header, unsigned char PacketType,
unsigned long DataRepresentation) ULONG DataRepresentation)
{ {
Header->common.rpc_ver = RPC_VER_MAJOR; Header->common.rpc_ver = RPC_VER_MAJOR;
Header->common.rpc_ver_minor = RPC_VER_MINOR; Header->common.rpc_ver_minor = RPC_VER_MINOR;
@ -111,8 +111,8 @@ static VOID RPCRT4_BuildCommonHeader(RpcPktHdr *Header, unsigned char PacketType
/* Flags and fragment length are computed in RPCRT4_Send. */ /* Flags and fragment length are computed in RPCRT4_Send. */
} }
static RpcPktHdr *RPCRT4_BuildRequestHeader(unsigned long DataRepresentation, static RpcPktHdr *RPCRT4_BuildRequestHeader(ULONG DataRepresentation,
unsigned long BufferLength, ULONG BufferLength,
unsigned short ProcNum, unsigned short ProcNum,
UUID *ObjectUuid) UUID *ObjectUuid)
{ {
@ -141,8 +141,7 @@ static RpcPktHdr *RPCRT4_BuildRequestHeader(unsigned long DataRepresentation,
return header; return header;
} }
RpcPktHdr *RPCRT4_BuildResponseHeader(unsigned long DataRepresentation, RpcPktHdr *RPCRT4_BuildResponseHeader(ULONG DataRepresentation, ULONG BufferLength)
unsigned long BufferLength)
{ {
RpcPktHdr *header; RpcPktHdr *header;
@ -158,8 +157,7 @@ RpcPktHdr *RPCRT4_BuildResponseHeader(unsigned long DataRepresentation,
return header; return header;
} }
RpcPktHdr *RPCRT4_BuildFaultHeader(unsigned long DataRepresentation, RpcPktHdr *RPCRT4_BuildFaultHeader(ULONG DataRepresentation, RPC_STATUS Status)
RPC_STATUS Status)
{ {
RpcPktHdr *header; RpcPktHdr *header;
@ -175,10 +173,10 @@ RpcPktHdr *RPCRT4_BuildFaultHeader(unsigned long DataRepresentation,
return header; return header;
} }
RpcPktHdr *RPCRT4_BuildBindHeader(unsigned long DataRepresentation, RpcPktHdr *RPCRT4_BuildBindHeader(ULONG DataRepresentation,
unsigned short MaxTransmissionSize, unsigned short MaxTransmissionSize,
unsigned short MaxReceiveSize, unsigned short MaxReceiveSize,
unsigned long AssocGroupId, ULONG AssocGroupId,
const RPC_SYNTAX_IDENTIFIER *AbstractId, const RPC_SYNTAX_IDENTIFIER *AbstractId,
const RPC_SYNTAX_IDENTIFIER *TransferId) const RPC_SYNTAX_IDENTIFIER *TransferId)
{ {
@ -202,7 +200,7 @@ RpcPktHdr *RPCRT4_BuildBindHeader(unsigned long DataRepresentation,
return header; return header;
} }
static RpcPktHdr *RPCRT4_BuildAuthHeader(unsigned long DataRepresentation) static RpcPktHdr *RPCRT4_BuildAuthHeader(ULONG DataRepresentation)
{ {
RpcPktHdr *header; RpcPktHdr *header;
@ -218,7 +216,7 @@ static RpcPktHdr *RPCRT4_BuildAuthHeader(unsigned long DataRepresentation)
return header; return header;
} }
RpcPktHdr *RPCRT4_BuildBindNackHeader(unsigned long DataRepresentation, RpcPktHdr *RPCRT4_BuildBindNackHeader(ULONG DataRepresentation,
unsigned char RpcVersion, unsigned char RpcVersion,
unsigned char RpcVersionMinor) unsigned char RpcVersionMinor)
{ {
@ -239,17 +237,17 @@ RpcPktHdr *RPCRT4_BuildBindNackHeader(unsigned long DataRepresentation,
return header; return header;
} }
RpcPktHdr *RPCRT4_BuildBindAckHeader(unsigned long DataRepresentation, RpcPktHdr *RPCRT4_BuildBindAckHeader(ULONG DataRepresentation,
unsigned short MaxTransmissionSize, unsigned short MaxTransmissionSize,
unsigned short MaxReceiveSize, unsigned short MaxReceiveSize,
unsigned long AssocGroupId, ULONG AssocGroupId,
LPCSTR ServerAddress, LPCSTR ServerAddress,
unsigned long Result, unsigned short Result,
unsigned long Reason, unsigned short Reason,
const RPC_SYNTAX_IDENTIFIER *TransferId) const RPC_SYNTAX_IDENTIFIER *TransferId)
{ {
RpcPktHdr *header; RpcPktHdr *header;
unsigned long header_size; ULONG header_size;
RpcAddressString *server_address; RpcAddressString *server_address;
RpcResults *results; RpcResults *results;
RPC_SYNTAX_IDENTIFIER *transfer_id; RPC_SYNTAX_IDENTIFIER *transfer_id;
@ -283,6 +281,118 @@ RpcPktHdr *RPCRT4_BuildBindAckHeader(unsigned long DataRepresentation,
return header; return header;
} }
RpcPktHdr *RPCRT4_BuildHttpHeader(ULONG DataRepresentation,
unsigned short flags,
unsigned short num_data_items,
unsigned int payload_size)
{
RpcPktHdr *header;
header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(header->http) + payload_size);
if (header == NULL) {
ERR("failed to allocate memory\n");
return NULL;
}
RPCRT4_BuildCommonHeader(header, PKT_HTTP, DataRepresentation);
/* since the packet isn't current sent using RPCRT4_Send, set the flags
* manually here */
header->common.flags = RPC_FLG_FIRST|RPC_FLG_LAST;
header->common.call_id = 0;
header->common.frag_len = sizeof(header->http) + payload_size;
header->http.flags = flags;
header->http.num_data_items = num_data_items;
return header;
}
#define WRITE_HTTP_PAYLOAD_FIELD_UINT32(payload, type, value) \
do { \
*(unsigned int *)(payload) = (type); \
(payload) += 4; \
*(unsigned int *)(payload) = (value); \
(payload) += 4; \
} while (0)
#define WRITE_HTTP_PAYLOAD_FIELD_UUID(payload, type, uuid) \
do { \
*(unsigned int *)(payload) = (type); \
(payload) += 4; \
*(UUID *)(payload) = (uuid); \
(payload) += sizeof(UUID); \
} while (0)
#define WRITE_HTTP_PAYLOAD_FIELD_FLOW_CONTROL(payload, bytes_transmitted, flow_control_increment, uuid) \
do { \
*(unsigned int *)(payload) = 0x00000001; \
(payload) += 4; \
*(unsigned int *)(payload) = (bytes_transmitted); \
(payload) += 4; \
*(unsigned int *)(payload) = (flow_control_increment); \
(payload) += 4; \
*(UUID *)(payload) = (uuid); \
(payload) += sizeof(UUID); \
} while (0)
RpcPktHdr *RPCRT4_BuildHttpConnectHeader(unsigned short flags, int out_pipe,
const UUID *connection_uuid,
const UUID *pipe_uuid,
const UUID *association_uuid)
{
RpcPktHdr *header;
unsigned int size;
char *payload;
size = 8 + 4 + sizeof(UUID) + 4 + sizeof(UUID) + 8;
if (!out_pipe)
size += 8 + 4 + sizeof(UUID);
header = RPCRT4_BuildHttpHeader(NDR_LOCAL_DATA_REPRESENTATION, flags,
out_pipe ? 4 : 6, size);
if (!header) return NULL;
payload = (char *)(&header->http+1);
/* FIXME: what does this part of the payload do? */
WRITE_HTTP_PAYLOAD_FIELD_UINT32(payload, 0x00000006, 0x00000001);
WRITE_HTTP_PAYLOAD_FIELD_UUID(payload, 0x00000003, *connection_uuid);
WRITE_HTTP_PAYLOAD_FIELD_UUID(payload, 0x00000003, *pipe_uuid);
if (out_pipe)
/* FIXME: what does this part of the payload do? */
WRITE_HTTP_PAYLOAD_FIELD_UINT32(payload, 0x00000000, 0x00010000);
else
{
/* FIXME: what does this part of the payload do? */
WRITE_HTTP_PAYLOAD_FIELD_UINT32(payload, 0x00000004, 0x40000000);
/* FIXME: what does this part of the payload do? */
WRITE_HTTP_PAYLOAD_FIELD_UINT32(payload, 0x00000005, 0x000493e0);
WRITE_HTTP_PAYLOAD_FIELD_UUID(payload, 0x0000000c, *association_uuid);
}
return header;
}
RpcPktHdr *RPCRT4_BuildHttpFlowControlHeader(BOOL server, ULONG bytes_transmitted,
ULONG flow_control_increment,
const UUID *pipe_uuid)
{
RpcPktHdr *header;
char *payload;
header = RPCRT4_BuildHttpHeader(NDR_LOCAL_DATA_REPRESENTATION, 0x2, 2,
5 * sizeof(ULONG) + sizeof(UUID));
if (!header) return NULL;
payload = (char *)(&header->http+1);
WRITE_HTTP_PAYLOAD_FIELD_UINT32(payload, 0x0000000d, (server ? 0x0 : 0x3));
WRITE_HTTP_PAYLOAD_FIELD_FLOW_CONTROL(payload, bytes_transmitted,
flow_control_increment, *pipe_uuid);
return header;
}
VOID RPCRT4_FreeHeader(RpcPktHdr *Header) VOID RPCRT4_FreeHeader(RpcPktHdr *Header)
{ {
HeapFree(GetProcessHeap(), 0, Header); HeapFree(GetProcessHeap(), 0, Header);
@ -362,6 +472,206 @@ static RPC_STATUS NCA2RPC_STATUS(NCA_STATUS status)
} }
} }
/* assumes the common header fields have already been validated */
BOOL RPCRT4_IsValidHttpPacket(RpcPktHdr *hdr, unsigned char *data,
unsigned short data_len)
{
unsigned short i;
BYTE *p = data;
for (i = 0; i < hdr->http.num_data_items; i++)
{
ULONG type;
if (data_len < sizeof(ULONG))
return FALSE;
type = *(ULONG *)p;
p += sizeof(ULONG);
data_len -= sizeof(ULONG);
switch (type)
{
case 0x3:
case 0xc:
if (data_len < sizeof(GUID))
return FALSE;
p += sizeof(GUID);
data_len -= sizeof(GUID);
break;
case 0x0:
case 0x2:
case 0x4:
case 0x5:
case 0x6:
case 0xd:
if (data_len < sizeof(ULONG))
return FALSE;
p += sizeof(ULONG);
data_len -= sizeof(ULONG);
break;
case 0x1:
if (data_len < 24)
return FALSE;
p += 24;
data_len -= 24;
break;
default:
FIXME("unimplemented type 0x%x\n", type);
break;
}
}
return TRUE;
}
/* assumes the HTTP packet has been validated */
static unsigned char *RPCRT4_NextHttpHeaderField(unsigned char *data)
{
ULONG type;
type = *(ULONG *)data;
data += sizeof(ULONG);
switch (type)
{
case 0x3:
case 0xc:
return data + sizeof(GUID);
case 0x0:
case 0x2:
case 0x4:
case 0x5:
case 0x6:
case 0xd:
return data + sizeof(ULONG);
case 0x1:
return data + 24;
default:
FIXME("unimplemented type 0x%x\n", type);
return data;
}
}
#define READ_HTTP_PAYLOAD_FIELD_TYPE(data) *(ULONG *)(data)
#define GET_HTTP_PAYLOAD_FIELD_DATA(data) ((data) + sizeof(ULONG))
/* assumes the HTTP packet has been validated */
RPC_STATUS RPCRT4_ParseHttpPrepareHeader1(RpcPktHdr *header,
unsigned char *data, ULONG *field1)
{
ULONG type;
if (header->http.flags != 0x0)
{
ERR("invalid flags 0x%x\n", header->http.flags);
return RPC_S_PROTOCOL_ERROR;
}
if (header->http.num_data_items != 1)
{
ERR("invalid number of data items %d\n", header->http.num_data_items);
return RPC_S_PROTOCOL_ERROR;
}
type = READ_HTTP_PAYLOAD_FIELD_TYPE(data);
if (type != 0x00000002)
{
ERR("invalid type 0x%08x\n", type);
return RPC_S_PROTOCOL_ERROR;
}
*field1 = *(ULONG *)GET_HTTP_PAYLOAD_FIELD_DATA(data);
return RPC_S_OK;
}
/* assumes the HTTP packet has been validated */
RPC_STATUS RPCRT4_ParseHttpPrepareHeader2(RpcPktHdr *header,
unsigned char *data, ULONG *field1,
ULONG *bytes_until_next_packet,
ULONG *field3)
{
ULONG type;
if (header->http.flags != 0x0)
{
ERR("invalid flags 0x%x\n", header->http.flags);
return RPC_S_PROTOCOL_ERROR;
}
if (header->http.num_data_items != 3)
{
ERR("invalid number of data items %d\n", header->http.num_data_items);
return RPC_S_PROTOCOL_ERROR;
}
type = READ_HTTP_PAYLOAD_FIELD_TYPE(data);
if (type != 0x00000006)
{
ERR("invalid type for field 1: 0x%08x\n", type);
return RPC_S_PROTOCOL_ERROR;
}
*field1 = *(ULONG *)GET_HTTP_PAYLOAD_FIELD_DATA(data);
data = RPCRT4_NextHttpHeaderField(data);
type = READ_HTTP_PAYLOAD_FIELD_TYPE(data);
if (type != 0x00000000)
{
ERR("invalid type for field 2: 0x%08x\n", type);
return RPC_S_PROTOCOL_ERROR;
}
*bytes_until_next_packet = *(ULONG *)GET_HTTP_PAYLOAD_FIELD_DATA(data);
data = RPCRT4_NextHttpHeaderField(data);
type = READ_HTTP_PAYLOAD_FIELD_TYPE(data);
if (type != 0x00000002)
{
ERR("invalid type for field 3: 0x%08x\n", type);
return RPC_S_PROTOCOL_ERROR;
}
*field3 = *(ULONG *)GET_HTTP_PAYLOAD_FIELD_DATA(data);
return RPC_S_OK;
}
RPC_STATUS RPCRT4_ParseHttpFlowControlHeader(RpcPktHdr *header,
unsigned char *data, BOOL server,
ULONG *bytes_transmitted,
ULONG *flow_control_increment,
UUID *pipe_uuid)
{
ULONG type;
if (header->http.flags != 0x2)
{
ERR("invalid flags 0x%x\n", header->http.flags);
return RPC_S_PROTOCOL_ERROR;
}
if (header->http.num_data_items != 2)
{
ERR("invalid number of data items %d\n", header->http.num_data_items);
return RPC_S_PROTOCOL_ERROR;
}
type = READ_HTTP_PAYLOAD_FIELD_TYPE(data);
if (type != 0x0000000d)
{
ERR("invalid type for field 1: 0x%08x\n", type);
return RPC_S_PROTOCOL_ERROR;
}
if (*(ULONG *)GET_HTTP_PAYLOAD_FIELD_DATA(data) != (server ? 0x3 : 0x0))
{
ERR("invalid type for 0xd field data: 0x%08x\n", *(ULONG *)GET_HTTP_PAYLOAD_FIELD_DATA(data));
return RPC_S_PROTOCOL_ERROR;
}
data = RPCRT4_NextHttpHeaderField(data);
type = READ_HTTP_PAYLOAD_FIELD_TYPE(data);
if (type != 0x00000001)
{
ERR("invalid type for field 2: 0x%08x\n", type);
return RPC_S_PROTOCOL_ERROR;
}
*bytes_transmitted = *(ULONG *)GET_HTTP_PAYLOAD_FIELD_DATA(data);
*flow_control_increment = *(ULONG *)(GET_HTTP_PAYLOAD_FIELD_DATA(data) + 4);
*pipe_uuid = *(UUID *)(GET_HTTP_PAYLOAD_FIELD_DATA(data) + 8);
return RPC_S_OK;
}
static RPC_STATUS RPCRT4_SecurePacket(RpcConnection *Connection, static RPC_STATUS RPCRT4_SecurePacket(RpcConnection *Connection,
enum secure_packet_direction dir, enum secure_packet_direction dir,
RpcPktHdr *hdr, unsigned int hdr_size, RpcPktHdr *hdr, unsigned int hdr_size,
@ -509,7 +819,7 @@ static RPC_STATUS RPCRT4_SendWithAuth(RpcConnection *Connection, RpcPktHdr *Head
auth_hdr->auth_pad_length = auth_pad_len; auth_hdr->auth_pad_length = auth_pad_len;
auth_hdr->auth_reserved = 0; auth_hdr->auth_reserved = 0;
/* a unique number... */ /* a unique number... */
auth_hdr->auth_context_id = (unsigned long)Connection; auth_hdr->auth_context_id = Connection->auth_context_id;
if (AuthLength) if (AuthLength)
memcpy(auth_hdr + 1, Auth, AuthLength); memcpy(auth_hdr + 1, Auth, AuthLength);
@ -687,7 +997,7 @@ RPC_STATUS RPCRT4_Send(RpcConnection *Connection, RpcPktHdr *Header,
} }
/* validates version and frag_len fields */ /* validates version and frag_len fields */
static RPC_STATUS RPCRT4_ValidateCommonHeader(const RpcPktCommonHdr *hdr) RPC_STATUS RPCRT4_ValidateCommonHeader(const RpcPktCommonHdr *hdr)
{ {
DWORD hdr_length; DWORD hdr_length;
@ -716,11 +1026,11 @@ static RPC_STATUS RPCRT4_ValidateCommonHeader(const RpcPktCommonHdr *hdr)
} }
/*********************************************************************** /***********************************************************************
* RPCRT4_receive_fragment (internal) * RPCRT4_default_receive_fragment (internal)
* *
* Receive a fragment from a connection. * Receive a fragment from a connection.
*/ */
static RPC_STATUS RPCRT4_receive_fragment(RpcConnection *Connection, RpcPktHdr **Header, void **Payload) static RPC_STATUS RPCRT4_default_receive_fragment(RpcConnection *Connection, RpcPktHdr **Header, void **Payload)
{ {
RPC_STATUS status; RPC_STATUS status;
DWORD hdr_length; DWORD hdr_length;
@ -794,6 +1104,14 @@ fail:
return status; return status;
} }
static RPC_STATUS RPCRT4_receive_fragment(RpcConnection *Connection, RpcPktHdr **Header, void **Payload)
{
if (Connection->ops->receive_fragment)
return Connection->ops->receive_fragment(Connection, Header, Payload);
else
return RPCRT4_default_receive_fragment(Connection, Header, Payload);
}
/*********************************************************************** /***********************************************************************
* RPCRT4_ReceiveWithAuth (internal) * RPCRT4_ReceiveWithAuth (internal)
* *
@ -803,14 +1121,14 @@ fail:
RPC_STATUS RPCRT4_ReceiveWithAuth(RpcConnection *Connection, RpcPktHdr **Header, RPC_STATUS RPCRT4_ReceiveWithAuth(RpcConnection *Connection, RpcPktHdr **Header,
PRPC_MESSAGE pMsg, PRPC_MESSAGE pMsg,
unsigned char **auth_data_out, unsigned char **auth_data_out,
unsigned long *auth_length_out) ULONG *auth_length_out)
{ {
RPC_STATUS status; RPC_STATUS status;
DWORD hdr_length; DWORD hdr_length;
unsigned short first_flag; unsigned short first_flag;
unsigned long data_length; ULONG data_length;
unsigned long buffer_length; ULONG buffer_length;
unsigned long auth_length = 0; ULONG auth_length = 0;
unsigned char *auth_data = NULL; unsigned char *auth_data = NULL;
RpcPktHdr *CurrentHeader = NULL; RpcPktHdr *CurrentHeader = NULL;
void *payload = NULL; void *payload = NULL;
@ -874,7 +1192,7 @@ RPC_STATUS RPCRT4_ReceiveWithAuth(RpcConnection *Connection, RpcPktHdr **Header,
} }
if (CurrentHeader->common.auth_len != auth_length) { if (CurrentHeader->common.auth_len != auth_length) {
WARN("auth_len header field changed from %ld to %d\n", WARN("auth_len header field changed from %d to %d\n",
auth_length, CurrentHeader->common.auth_len); auth_length, CurrentHeader->common.auth_len);
status = RPC_S_PROTOCOL_ERROR; status = RPC_S_PROTOCOL_ERROR;
goto fail; goto fail;
@ -888,7 +1206,7 @@ RPC_STATUS RPCRT4_ReceiveWithAuth(RpcConnection *Connection, RpcPktHdr **Header,
data_length = CurrentHeader->common.frag_len - hdr_length - header_auth_len; data_length = CurrentHeader->common.frag_len - hdr_length - header_auth_len;
if (data_length + buffer_length > pMsg->BufferLength) { if (data_length + buffer_length > pMsg->BufferLength) {
TRACE("allocation hint exceeded, new buffer length = %ld\n", TRACE("allocation hint exceeded, new buffer length = %d\n",
data_length + buffer_length); data_length + buffer_length);
pMsg->BufferLength = data_length + buffer_length; pMsg->BufferLength = data_length + buffer_length;
status = I_RpcReAllocateBuffer(pMsg); status = I_RpcReAllocateBuffer(pMsg);
@ -998,7 +1316,7 @@ RPC_STATUS RPCRT4_Receive(RpcConnection *Connection, RpcPktHdr **Header,
*/ */
RPC_STATUS WINAPI I_RpcNegotiateTransferSyntax(PRPC_MESSAGE pMsg) RPC_STATUS WINAPI I_RpcNegotiateTransferSyntax(PRPC_MESSAGE pMsg)
{ {
RpcBinding* bind = (RpcBinding*)pMsg->Handle; RpcBinding* bind = pMsg->Handle;
RpcConnection* conn; RpcConnection* conn;
RPC_STATUS status = RPC_S_OK; RPC_STATUS status = RPC_S_OK;
@ -1063,7 +1381,7 @@ RPC_STATUS WINAPI I_RpcNegotiateTransferSyntax(PRPC_MESSAGE pMsg)
RPC_STATUS WINAPI I_RpcGetBuffer(PRPC_MESSAGE pMsg) RPC_STATUS WINAPI I_RpcGetBuffer(PRPC_MESSAGE pMsg)
{ {
RPC_STATUS status; RPC_STATUS status;
RpcBinding* bind = (RpcBinding*)pMsg->Handle; RpcBinding* bind = pMsg->Handle;
TRACE("(%p): BufferLength=%d\n", pMsg, pMsg->BufferLength); TRACE("(%p): BufferLength=%d\n", pMsg, pMsg->BufferLength);
@ -1120,7 +1438,7 @@ static RPC_STATUS I_RpcReAllocateBuffer(PRPC_MESSAGE pMsg)
*/ */
RPC_STATUS WINAPI I_RpcFreeBuffer(PRPC_MESSAGE pMsg) RPC_STATUS WINAPI I_RpcFreeBuffer(PRPC_MESSAGE pMsg)
{ {
RpcBinding* bind = (RpcBinding*)pMsg->Handle; RpcBinding* bind = pMsg->Handle;
TRACE("(%p) Buffer=%p\n", pMsg, pMsg->Buffer); TRACE("(%p) Buffer=%p\n", pMsg, pMsg->Buffer);
@ -1214,7 +1532,7 @@ static DWORD WINAPI async_notifier_proc(LPVOID p)
*/ */
RPC_STATUS WINAPI I_RpcSend(PRPC_MESSAGE pMsg) RPC_STATUS WINAPI I_RpcSend(PRPC_MESSAGE pMsg)
{ {
RpcBinding* bind = (RpcBinding*)pMsg->Handle; RpcBinding* bind = pMsg->Handle;
RpcConnection* conn; RpcConnection* conn;
RPC_STATUS status; RPC_STATUS status;
RpcPktHdr *hdr; RpcPktHdr *hdr;
@ -1268,7 +1586,7 @@ static inline BOOL is_hard_error(RPC_STATUS status)
*/ */
RPC_STATUS WINAPI I_RpcReceive(PRPC_MESSAGE pMsg) RPC_STATUS WINAPI I_RpcReceive(PRPC_MESSAGE pMsg)
{ {
RpcBinding* bind = (RpcBinding*)pMsg->Handle; RpcBinding* bind = pMsg->Handle;
RPC_STATUS status; RPC_STATUS status;
RpcPktHdr *hdr = NULL; RpcPktHdr *hdr = NULL;
RpcConnection *conn; RpcConnection *conn;
@ -1287,7 +1605,7 @@ RPC_STATUS WINAPI I_RpcReceive(PRPC_MESSAGE pMsg)
case PKT_RESPONSE: case PKT_RESPONSE:
break; break;
case PKT_FAULT: case PKT_FAULT:
ERR ("we got fault packet with status 0x%lx\n", hdr->fault.status); ERR ("we got fault packet with status 0x%x\n", hdr->fault.status);
status = NCA2RPC_STATUS(hdr->fault.status); status = NCA2RPC_STATUS(hdr->fault.status);
if (is_hard_error(status)) if (is_hard_error(status))
goto fail; goto fail;
@ -1360,7 +1678,7 @@ RPC_STATUS WINAPI I_RpcSendReceive(PRPC_MESSAGE pMsg)
*/ */
RPC_STATUS WINAPI I_RpcAsyncSetHandle(PRPC_MESSAGE pMsg, PRPC_ASYNC_STATE pAsync) RPC_STATUS WINAPI I_RpcAsyncSetHandle(PRPC_MESSAGE pMsg, PRPC_ASYNC_STATE pAsync)
{ {
RpcBinding* bind = (RpcBinding*)pMsg->Handle; RpcBinding* bind = pMsg->Handle;
RpcConnection *conn; RpcConnection *conn;
TRACE("(%p, %p)\n", pMsg, pAsync); TRACE("(%p, %p)\n", pMsg, pAsync);

View file

@ -25,15 +25,25 @@
typedef unsigned int NCA_STATUS; typedef unsigned int NCA_STATUS;
RpcPktHdr *RPCRT4_BuildFaultHeader(unsigned long DataRepresentation, RPC_STATUS Status); RpcPktHdr *RPCRT4_BuildFaultHeader(ULONG DataRepresentation, RPC_STATUS Status);
RpcPktHdr *RPCRT4_BuildResponseHeader(unsigned long DataRepresentation, unsigned long BufferLength); RpcPktHdr *RPCRT4_BuildResponseHeader(ULONG DataRepresentation, ULONG 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(ULONG DataRepresentation, unsigned short MaxTransmissionSize, unsigned short MaxReceiveSize, ULONG 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(ULONG DataRepresentation, unsigned char RpcVersion, unsigned char RpcVersionMinor);
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); RpcPktHdr *RPCRT4_BuildBindAckHeader(ULONG DataRepresentation, unsigned short MaxTransmissionSize, unsigned short MaxReceiveSize, ULONG AssocGroupId, LPCSTR ServerAddress, unsigned short Result, unsigned short Reason, const RPC_SYNTAX_IDENTIFIER *TransferId);
RpcPktHdr *RPCRT4_BuildHttpHeader(ULONG DataRepresentation, unsigned short flags, unsigned short num_data_items, unsigned int payload_size);
RpcPktHdr *RPCRT4_BuildHttpConnectHeader(unsigned short flags, int out_pipe, const UUID *connection_uuid, const UUID *pipe_uuid, const UUID *association_uuid);
RpcPktHdr *RPCRT4_BuildHttpFlowControlHeader(BOOL server, ULONG bytes_transmitted, ULONG flow_control_increment, const UUID *pipe_uuid);
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);
RPC_STATUS RPCRT4_ReceiveWithAuth(RpcConnection *Connection, RpcPktHdr **Header, PRPC_MESSAGE pMsg, unsigned char **auth_data_out, unsigned long *auth_length_out); RPC_STATUS RPCRT4_ReceiveWithAuth(RpcConnection *Connection, RpcPktHdr **Header, PRPC_MESSAGE pMsg, unsigned char **auth_data_out, ULONG *auth_length_out);
DWORD RPCRT4_GetHeaderSize(const RpcPktHdr *Header);
RPC_STATUS RPCRT4_ValidateCommonHeader(const RpcPktCommonHdr *hdr);
BOOL RPCRT4_IsValidHttpPacket(RpcPktHdr *hdr, unsigned char *data, unsigned short data_len);
RPC_STATUS RPCRT4_ParseHttpPrepareHeader1(RpcPktHdr *header, unsigned char *data, ULONG *field1);
RPC_STATUS RPCRT4_ParseHttpPrepareHeader2(RpcPktHdr *header, unsigned char *data, ULONG *field1, ULONG *bytes_until_next_packet, ULONG *field3);
RPC_STATUS RPCRT4_ParseHttpFlowControlHeader(RpcPktHdr *header, unsigned char *data, BOOL server, ULONG *bytes_transmitted, ULONG *flow_control_increment, UUID *pipe_uuid);
NCA_STATUS RPC2NCA_STATUS(RPC_STATUS status); NCA_STATUS RPC2NCA_STATUS(RPC_STATUS status);
RPC_STATUS RPCRT4_AuthorizeConnection(RpcConnection* conn, BYTE *challenge, ULONG count); RPC_STATUS RPCRT4_AuthorizeConnection(RpcConnection* conn, BYTE *challenge, ULONG count);

View file

@ -367,7 +367,7 @@ static DWORD CALLBACK RPCRT4_worker_thread(LPVOID the_arg)
static DWORD CALLBACK RPCRT4_io_thread(LPVOID the_arg) static DWORD CALLBACK RPCRT4_io_thread(LPVOID the_arg)
{ {
RpcConnection* conn = (RpcConnection*)the_arg; RpcConnection* conn = the_arg;
RpcPktHdr *hdr; RpcPktHdr *hdr;
RPC_MESSAGE *msg; RPC_MESSAGE *msg;
RPC_STATUS status; RPC_STATUS status;
@ -449,27 +449,23 @@ static DWORD CALLBACK RPCRT4_server_thread(LPVOID the_arg)
/* start waiting */ /* start waiting */
res = cps->ops->wait_for_new_connection(cps, count, objs); res = cps->ops->wait_for_new_connection(cps, count, objs);
if (res == -1)
break; if (res == -1 || (res == 0 && !std_listen))
else if (res == 0)
{ {
if (!std_listen) /* cleanup */
{ cps->ops->free_wait_array(cps, objs);
EnterCriticalSection(&cps->cs);
for (conn = cps->conn; conn; conn = conn->Next)
RPCRT4_CloseConnection(conn);
LeaveCriticalSection(&cps->cs);
if (res == 0 && !std_listen)
SetEvent(cps->server_ready_event); SetEvent(cps->server_ready_event);
break; break;
}
set_ready_event = TRUE;
} }
else if (res == 0)
set_ready_event = TRUE;
} }
cps->ops->free_wait_array(cps, objs);
EnterCriticalSection(&cps->cs);
/* close connections */
conn = cps->conn;
while (conn) {
RPCRT4_CloseConnection(conn);
conn = conn->Next;
}
LeaveCriticalSection(&cps->cs);
return 0; return 0;
} }
@ -570,11 +566,32 @@ static void RPCRT4_stop_listen(BOOL auto_listen)
LeaveCriticalSection(&listen_cs); LeaveCriticalSection(&listen_cs);
} }
static RPC_STATUS RPCRT4_use_protseq(RpcServerProtseq* ps, LPSTR endpoint) static BOOL RPCRT4_protseq_is_endpoint_registered(RpcServerProtseq *protseq, const char *endpoint)
{
RpcConnection *conn;
EnterCriticalSection(&protseq->cs);
for (conn = protseq->conn; conn; conn = conn->Next)
{
if (!endpoint || !strcmp(endpoint, conn->Endpoint))
break;
}
LeaveCriticalSection(&protseq->cs);
return (conn != NULL);
}
static RPC_STATUS RPCRT4_use_protseq(RpcServerProtseq* ps, const char *endpoint)
{ {
RPC_STATUS status; RPC_STATUS status;
status = ps->ops->open_endpoint(ps, endpoint); EnterCriticalSection(&ps->cs);
if (RPCRT4_protseq_is_endpoint_registered(ps, endpoint))
status = RPC_S_OK;
else
status = ps->ops->open_endpoint(ps, endpoint);
LeaveCriticalSection(&ps->cs);
if (status != RPC_S_OK) if (status != RPC_S_OK)
return status; return status;
@ -608,11 +625,8 @@ RPC_STATUS WINAPI RpcServerInqBindings( RPC_BINDING_VECTOR** BindingVector )
count = 0; count = 0;
LIST_FOR_EACH_ENTRY(ps, &protseqs, RpcServerProtseq, entry) { LIST_FOR_EACH_ENTRY(ps, &protseqs, RpcServerProtseq, entry) {
EnterCriticalSection(&ps->cs); EnterCriticalSection(&ps->cs);
conn = ps->conn; for (conn = ps->conn; conn; conn = conn->Next)
while (conn) {
count++; count++;
conn = conn->Next;
}
LeaveCriticalSection(&ps->cs); LeaveCriticalSection(&ps->cs);
} }
if (count) { if (count) {
@ -624,12 +638,10 @@ RPC_STATUS WINAPI RpcServerInqBindings( RPC_BINDING_VECTOR** BindingVector )
count = 0; count = 0;
LIST_FOR_EACH_ENTRY(ps, &protseqs, RpcServerProtseq, entry) { LIST_FOR_EACH_ENTRY(ps, &protseqs, RpcServerProtseq, entry) {
EnterCriticalSection(&ps->cs); EnterCriticalSection(&ps->cs);
conn = ps->conn; for (conn = ps->conn; conn; conn = conn->Next) {
while (conn) {
RPCRT4_MakeBinding((RpcBinding**)&(*BindingVector)->BindingH[count], RPCRT4_MakeBinding((RpcBinding**)&(*BindingVector)->BindingH[count],
conn); conn);
count++; count++;
conn = conn->Next;
} }
LeaveCriticalSection(&ps->cs); LeaveCriticalSection(&ps->cs);
} }
@ -681,7 +693,7 @@ RPC_STATUS WINAPI RpcServerUseProtseqEpW( RPC_WSTR Protseq, UINT MaxCalls, RPC_W
* *
* Must be called with server_cs held. * Must be called with server_cs held.
*/ */
static RPC_STATUS alloc_serverprotoseq(UINT MaxCalls, char *Protseq, RpcServerProtseq **ps) static RPC_STATUS alloc_serverprotoseq(UINT MaxCalls, const char *Protseq, RpcServerProtseq **ps)
{ {
const struct protseq_ops *ops = rpcrt4_get_protseq_ops(Protseq); const struct protseq_ops *ops = rpcrt4_get_protseq_ops(Protseq);
@ -695,7 +707,7 @@ static RPC_STATUS alloc_serverprotoseq(UINT MaxCalls, char *Protseq, RpcServerPr
if (!*ps) if (!*ps)
return RPC_S_OUT_OF_RESOURCES; return RPC_S_OUT_OF_RESOURCES;
(*ps)->MaxCalls = MaxCalls; (*ps)->MaxCalls = MaxCalls;
(*ps)->Protseq = Protseq; (*ps)->Protseq = RPCRT4_strdupA(Protseq);
(*ps)->ops = ops; (*ps)->ops = ops;
(*ps)->MaxCalls = 0; (*ps)->MaxCalls = 0;
(*ps)->conn = NULL; (*ps)->conn = NULL;
@ -711,8 +723,19 @@ static RPC_STATUS alloc_serverprotoseq(UINT MaxCalls, char *Protseq, RpcServerPr
return RPC_S_OK; return RPC_S_OK;
} }
/* must be called with server_cs held */
static void destroy_serverprotoseq(RpcServerProtseq *ps)
{
RPCRT4_strfree(ps->Protseq);
DeleteCriticalSection(&ps->cs);
CloseHandle(ps->mgr_mutex);
CloseHandle(ps->server_ready_event);
list_remove(&ps->entry);
HeapFree(GetProcessHeap(), 0, ps);
}
/* Finds a given protseq or creates a new one if one doesn't already exist */ /* Finds a given protseq or creates a new one if one doesn't already exist */
static RPC_STATUS RPCRT4_get_or_create_serverprotseq(UINT MaxCalls, char *Protseq, RpcServerProtseq **ps) static RPC_STATUS RPCRT4_get_or_create_serverprotseq(UINT MaxCalls, const char *Protseq, RpcServerProtseq **ps)
{ {
RPC_STATUS status; RPC_STATUS status;
RpcServerProtseq *cps; RpcServerProtseq *cps;
@ -741,19 +764,18 @@ static RPC_STATUS RPCRT4_get_or_create_serverprotseq(UINT MaxCalls, char *Protse
RPC_STATUS WINAPI RpcServerUseProtseqEpExA( RPC_CSTR Protseq, UINT MaxCalls, RPC_CSTR Endpoint, LPVOID SecurityDescriptor, RPC_STATUS WINAPI RpcServerUseProtseqEpExA( RPC_CSTR Protseq, UINT MaxCalls, RPC_CSTR Endpoint, LPVOID SecurityDescriptor,
PRPC_POLICY lpPolicy ) PRPC_POLICY lpPolicy )
{ {
char *szps = (char*)Protseq, *szep = (char*)Endpoint;
RpcServerProtseq* ps; RpcServerProtseq* ps;
RPC_STATUS status; RPC_STATUS status;
TRACE("(%s,%u,%s,%p,{%u,%u,%u})\n", debugstr_a(szps), MaxCalls, TRACE("(%s,%u,%s,%p,{%u,%u,%u})\n", debugstr_a((const char *)Protseq),
debugstr_a(szep), SecurityDescriptor, MaxCalls, debugstr_a((const char *)Endpoint), SecurityDescriptor,
lpPolicy->Length, lpPolicy->EndpointFlags, lpPolicy->NICFlags ); lpPolicy->Length, lpPolicy->EndpointFlags, lpPolicy->NICFlags );
status = RPCRT4_get_or_create_serverprotseq(MaxCalls, RPCRT4_strdupA(szps), &ps); status = RPCRT4_get_or_create_serverprotseq(MaxCalls, (const char *)Protseq, &ps);
if (status != RPC_S_OK) if (status != RPC_S_OK)
return status; return status;
return RPCRT4_use_protseq(ps, szep); return RPCRT4_use_protseq(ps, (const char *)Endpoint);
} }
/*********************************************************************** /***********************************************************************
@ -764,13 +786,16 @@ RPC_STATUS WINAPI RpcServerUseProtseqEpExW( RPC_WSTR Protseq, UINT MaxCalls, RPC
{ {
RpcServerProtseq* ps; RpcServerProtseq* ps;
RPC_STATUS status; RPC_STATUS status;
LPSTR ProtseqA;
LPSTR EndpointA; LPSTR EndpointA;
TRACE("(%s,%u,%s,%p,{%u,%u,%u})\n", debugstr_w( Protseq ), MaxCalls, TRACE("(%s,%u,%s,%p,{%u,%u,%u})\n", debugstr_w( Protseq ), MaxCalls,
debugstr_w( Endpoint ), SecurityDescriptor, debugstr_w( Endpoint ), SecurityDescriptor,
lpPolicy->Length, lpPolicy->EndpointFlags, lpPolicy->NICFlags ); lpPolicy->Length, lpPolicy->EndpointFlags, lpPolicy->NICFlags );
status = RPCRT4_get_or_create_serverprotseq(MaxCalls, RPCRT4_strdupWtoA(Protseq), &ps); ProtseqA = RPCRT4_strdupWtoA(Protseq);
status = RPCRT4_get_or_create_serverprotseq(MaxCalls, ProtseqA, &ps);
RPCRT4_strfree(ProtseqA);
if (status != RPC_S_OK) if (status != RPC_S_OK)
return status; return status;
@ -785,8 +810,16 @@ RPC_STATUS WINAPI RpcServerUseProtseqEpExW( RPC_WSTR Protseq, UINT MaxCalls, RPC
*/ */
RPC_STATUS WINAPI RpcServerUseProtseqA(RPC_CSTR Protseq, unsigned int MaxCalls, void *SecurityDescriptor) RPC_STATUS WINAPI RpcServerUseProtseqA(RPC_CSTR Protseq, unsigned int MaxCalls, void *SecurityDescriptor)
{ {
RPC_STATUS status;
RpcServerProtseq* ps;
TRACE("(Protseq == %s, MaxCalls == %d, SecurityDescriptor == ^%p)\n", debugstr_a((char*)Protseq), MaxCalls, SecurityDescriptor); TRACE("(Protseq == %s, MaxCalls == %d, SecurityDescriptor == ^%p)\n", debugstr_a((char*)Protseq), MaxCalls, SecurityDescriptor);
return RpcServerUseProtseqEpA(Protseq, MaxCalls, NULL, SecurityDescriptor);
status = RPCRT4_get_or_create_serverprotseq(MaxCalls, (const char *)Protseq, &ps);
if (status != RPC_S_OK)
return status;
return RPCRT4_use_protseq(ps, NULL);
} }
/*********************************************************************** /***********************************************************************
@ -794,8 +827,36 @@ RPC_STATUS WINAPI RpcServerUseProtseqA(RPC_CSTR Protseq, unsigned int MaxCalls,
*/ */
RPC_STATUS WINAPI RpcServerUseProtseqW(RPC_WSTR Protseq, unsigned int MaxCalls, void *SecurityDescriptor) RPC_STATUS WINAPI RpcServerUseProtseqW(RPC_WSTR Protseq, unsigned int MaxCalls, void *SecurityDescriptor)
{ {
RPC_STATUS status;
RpcServerProtseq* ps;
LPSTR ProtseqA;
TRACE("Protseq == %s, MaxCalls == %d, SecurityDescriptor == ^%p)\n", debugstr_w(Protseq), MaxCalls, SecurityDescriptor); TRACE("Protseq == %s, MaxCalls == %d, SecurityDescriptor == ^%p)\n", debugstr_w(Protseq), MaxCalls, SecurityDescriptor);
return RpcServerUseProtseqEpW(Protseq, MaxCalls, NULL, SecurityDescriptor);
ProtseqA = RPCRT4_strdupWtoA(Protseq);
status = RPCRT4_get_or_create_serverprotseq(MaxCalls, ProtseqA, &ps);
RPCRT4_strfree(ProtseqA);
if (status != RPC_S_OK)
return status;
return RPCRT4_use_protseq(ps, NULL);
}
void RPCRT4_destroy_all_protseqs(void)
{
RpcServerProtseq *cps, *cursor2;
if (listen_count != 0)
std_listen = FALSE;
EnterCriticalSection(&server_cs);
LIST_FOR_EACH_ENTRY_SAFE(cps, cursor2, &protseqs, RpcServerProtseq, entry)
{
if (listen_count != 0)
RPCRT4_sync_with_server_thread(cps);
destroy_serverprotoseq(cps);
}
LeaveCriticalSection(&server_cs);
} }
/*********************************************************************** /***********************************************************************
@ -823,7 +884,7 @@ RPC_STATUS WINAPI RpcServerRegisterIfEx( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid
RPC_STATUS WINAPI RpcServerRegisterIf2( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, RPC_MGR_EPV* MgrEpv, RPC_STATUS WINAPI RpcServerRegisterIf2( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, RPC_MGR_EPV* MgrEpv,
UINT Flags, UINT MaxCalls, UINT MaxRpcSize, RPC_IF_CALLBACK_FN* IfCallbackFn ) UINT Flags, UINT MaxCalls, UINT MaxRpcSize, RPC_IF_CALLBACK_FN* IfCallbackFn )
{ {
PRPC_SERVER_INTERFACE If = (PRPC_SERVER_INTERFACE)IfSpec; PRPC_SERVER_INTERFACE If = IfSpec;
RpcServerInterface* sif; RpcServerInterface* sif;
unsigned int i; unsigned int i;
@ -876,7 +937,7 @@ RPC_STATUS WINAPI RpcServerRegisterIf2( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid,
*/ */
RPC_STATUS WINAPI RpcServerUnregisterIf( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, UINT WaitForCallsToComplete ) RPC_STATUS WINAPI RpcServerUnregisterIf( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, UINT WaitForCallsToComplete )
{ {
PRPC_SERVER_INTERFACE If = (PRPC_SERVER_INTERFACE)IfSpec; PRPC_SERVER_INTERFACE If = IfSpec;
HANDLE event = NULL; HANDLE event = NULL;
BOOL found = FALSE; BOOL found = FALSE;
BOOL completed = TRUE; BOOL completed = TRUE;

View file

@ -56,7 +56,7 @@ struct protseq_ops
* new connection was established */ * new connection was established */
int (*wait_for_new_connection)(RpcServerProtseq *protseq, unsigned int count, void *wait_array); int (*wait_for_new_connection)(RpcServerProtseq *protseq, unsigned int count, void *wait_array);
/* opens the endpoint and optionally begins listening */ /* opens the endpoint and optionally begins listening */
RPC_STATUS (*open_endpoint)(RpcServerProtseq *protseq, LPSTR endpoint); RPC_STATUS (*open_endpoint)(RpcServerProtseq *protseq, const char *endpoint);
}; };
typedef struct _RpcServerInterface typedef struct _RpcServerInterface
@ -79,4 +79,6 @@ typedef struct _RpcServerInterface
void RPCRT4_new_client(RpcConnection* conn); void RPCRT4_new_client(RpcConnection* conn);
const struct protseq_ops *rpcrt4_get_protseq_ops(const char *protseq); const struct protseq_ops *rpcrt4_get_protseq_ops(const char *protseq);
void RPCRT4_destroy_all_protseqs(void);
#endif /* __WINE_RPC_SERVER_H */ #endif /* __WINE_RPC_SERVER_H */

File diff suppressed because it is too large Load diff

View file

@ -14,6 +14,7 @@
<library>user32</library> <library>user32</library>
<library>advapi32</library> <library>advapi32</library>
<library>secur32</library> <library>secur32</library>
<!--library>wininet</library-->
<library>iphlpapi</library> <library>iphlpapi</library>
<library>ws2_32</library> <library>ws2_32</library>
<library>ntdll</library> <library>ntdll</library>

View file

@ -116,8 +116,9 @@
@ stdcall NDRSContextUnmarshallEx(ptr ptr ptr) @ stdcall NDRSContextUnmarshallEx(ptr ptr ptr)
@ stub NDRcopy @ stub NDRcopy
@ stdcall NdrAllocate(ptr long) @ stdcall NdrAllocate(ptr long)
@ stub NdrAsyncClientCall @ varargs NdrAsyncClientCall(ptr ptr)
@ stub NdrAsyncServerCall @ stub NdrAsyncServerCall
@ stdcall NdrAsyncStubCall(ptr ptr ptr ptr)
@ stdcall NdrByteCountPointerBufferSize(ptr ptr ptr) @ stdcall NdrByteCountPointerBufferSize(ptr ptr ptr)
@ stdcall NdrByteCountPointerFree(ptr ptr ptr) @ stdcall NdrByteCountPointerFree(ptr ptr ptr)
@ stdcall NdrByteCountPointerMarshall(ptr ptr ptr) @ stdcall NdrByteCountPointerMarshall(ptr ptr ptr)
@ -370,7 +371,7 @@
@ stdcall RpcEpRegisterA(ptr ptr ptr str) @ stdcall RpcEpRegisterA(ptr ptr ptr str)
@ stub RpcEpRegisterNoReplaceA @ stub RpcEpRegisterNoReplaceA
@ stub RpcEpRegisterNoReplaceW @ stub RpcEpRegisterNoReplaceW
@ stub RpcEpRegisterW @ stdcall RpcEpRegisterW(ptr ptr ptr wstr)
@ stdcall RpcEpResolveBinding(ptr ptr) @ stdcall RpcEpResolveBinding(ptr ptr)
@ stdcall RpcEpUnregister(ptr ptr ptr) @ stdcall RpcEpUnregister(ptr ptr ptr)
@ stub RpcErrorAddRecord # wxp @ stub RpcErrorAddRecord # wxp

View file

@ -43,8 +43,10 @@
#include "winuser.h" #include "winuser.h"
#include "winnt.h" #include "winnt.h"
#include "winternl.h" #include "winternl.h"
#include "iptypes.h" #define _NTDEF_
#include "iphlpapi.h" typedef NTSTATUS *PNTSTATUS;
#include "ntsecapi.h"
#undef _NTDEF_
#include "wine/unicode.h" #include "wine/unicode.h"
#include "rpc.h" #include "rpc.h"
@ -53,6 +55,7 @@
#include "rpcproxy.h" #include "rpcproxy.h"
#include "rpc_binding.h" #include "rpc_binding.h"
#include "rpc_server.h"
#include "wine/debug.h" #include "wine/debug.h"
@ -60,15 +63,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(rpc);
static UUID uuid_nil; static UUID uuid_nil;
static CRITICAL_SECTION uuid_cs;
static CRITICAL_SECTION_DEBUG critsect_debug =
{
0, 0, &uuid_cs,
{ &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
0, 0, { (DWORD_PTR)(__FILE__ ": uuid_cs") }
};
static CRITICAL_SECTION uuid_cs = { &critsect_debug, -1, 0, 0, 0, 0 };
static CRITICAL_SECTION threaddata_cs; static CRITICAL_SECTION threaddata_cs;
static CRITICAL_SECTION_DEBUG threaddata_cs_debug = static CRITICAL_SECTION_DEBUG threaddata_cs_debug =
{ {
@ -135,6 +129,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
break; break;
case DLL_PROCESS_DETACH: case DLL_PROCESS_DETACH:
RPCRT4_destroy_all_protseqs();
break; break;
} }
@ -280,61 +275,6 @@ RPC_STATUS WINAPI UuidCreateNil(UUID *Uuid)
return RPC_S_OK; return RPC_S_OK;
} }
/* Number of 100ns ticks per clock tick. To be safe, assume that the clock
resolution is at least 1000 * 100 * (1/1000000) = 1/10 of a second */
#define TICKS_PER_CLOCK_TICK 1000
#define SECSPERDAY 86400
#define TICKSPERSEC 10000000
/* UUID system time starts at October 15, 1582 */
#define SECS_15_OCT_1582_TO_1601 ((17 + 30 + 31 + 365 * 18 + 5) * SECSPERDAY)
#define TICKS_15_OCT_1582_TO_1601 ((ULONGLONG)SECS_15_OCT_1582_TO_1601 * TICKSPERSEC)
static void RPC_UuidGetSystemTime(ULONGLONG *time)
{
FILETIME ft;
GetSystemTimeAsFileTime(&ft);
*time = ((ULONGLONG)ft.dwHighDateTime << 32) | ft.dwLowDateTime;
*time += TICKS_15_OCT_1582_TO_1601;
}
/* Assume that a hardware address is at least 6 bytes long */
#define ADDRESS_BYTES_NEEDED 6
static RPC_STATUS RPC_UuidGetNodeAddress(BYTE *address)
{
int i;
DWORD status = RPC_S_OK;
ULONG buflen = sizeof(IP_ADAPTER_INFO);
PIP_ADAPTER_INFO adapter = HeapAlloc(GetProcessHeap(), 0, buflen);
if (GetAdaptersInfo(adapter, &buflen) == ERROR_BUFFER_OVERFLOW) {
HeapFree(GetProcessHeap(), 0, adapter);
adapter = HeapAlloc(GetProcessHeap(), 0, buflen);
}
if (GetAdaptersInfo(adapter, &buflen) == NO_ERROR) {
for (i = 0; i < ADDRESS_BYTES_NEEDED; i++) {
address[i] = adapter->Address[i];
}
}
/* We can't get a hardware address, just use random numbers.
Set the multicast bit to prevent conflicts with real cards. */
else {
for (i = 0; i < ADDRESS_BYTES_NEEDED; i++) {
address[i] = rand() & 0xff;
}
address[0] |= 0x01;
status = RPC_S_UUID_LOCAL_ONLY;
}
HeapFree(GetProcessHeap(), 0, adapter);
return status;
}
/************************************************************************* /*************************************************************************
* UuidCreate [RPCRT4.@] * UuidCreate [RPCRT4.@]
* *
@ -345,83 +285,26 @@ static RPC_STATUS RPC_UuidGetNodeAddress(BYTE *address)
* RPC_S_OK if successful. * RPC_S_OK if successful.
* RPC_S_UUID_LOCAL_ONLY if UUID is only locally unique. * RPC_S_UUID_LOCAL_ONLY if UUID is only locally unique.
* *
* FIXME: No compensation for changes across reloading * NOTES
* this dll or across reboots (e.g. clock going *
* backwards and swapped network cards). The RFC * Follows RFC 4122, section 4.4 (Algorithms for Creating a UUID from
* suggests using NVRAM for storing persistent * Truly Random or Pseudo-Random Numbers)
* values.
*/ */
RPC_STATUS WINAPI UuidCreate(UUID *Uuid) RPC_STATUS WINAPI UuidCreate(UUID *Uuid)
{ {
static int initialised, count; RtlGenRandom(Uuid, sizeof(*Uuid));
/* Clear the version bits and set the version (4) */
ULONGLONG time; Uuid->Data3 &= 0x0fff;
static ULONGLONG timelast; Uuid->Data3 |= (4 << 12);
static WORD sequence; /* Set the topmost bits of Data4 (clock_seq_hi_and_reserved) as
* specified in RFC 4122, section 4.4.
static DWORD status; */
static BYTE address[MAX_ADAPTER_ADDRESS_LENGTH]; Uuid->Data4[0] &= 0x3f;
Uuid->Data4[0] |= 0x80;
EnterCriticalSection(&uuid_cs);
if (!initialised) {
RPC_UuidGetSystemTime(&timelast);
count = TICKS_PER_CLOCK_TICK;
sequence = ((rand() & 0xff) << 8) + (rand() & 0xff);
sequence &= 0x1fff;
status = RPC_UuidGetNodeAddress(address);
initialised = 1;
}
/* Generate time element of the UUID. Account for going faster
than our clock as well as the clock going backwards. */
while (1) {
RPC_UuidGetSystemTime(&time);
if (time > timelast) {
count = 0;
break;
}
if (time < timelast) {
sequence = (sequence + 1) & 0x1fff;
count = 0;
break;
}
if (count < TICKS_PER_CLOCK_TICK) {
count++;
break;
}
}
timelast = time;
time += count;
/* Pack the information into the UUID structure. */
Uuid->Data1 = (unsigned long)(time & 0xffffffff);
Uuid->Data2 = (unsigned short)((time >> 32) & 0xffff);
Uuid->Data3 = (unsigned short)((time >> 48) & 0x0fff);
/* This is a version 1 UUID */
Uuid->Data3 |= (1 << 12);
Uuid->Data4[0] = sequence & 0xff;
Uuid->Data4[1] = (sequence & 0x3f00) >> 8;
Uuid->Data4[1] |= 0x80;
Uuid->Data4[2] = address[0];
Uuid->Data4[3] = address[1];
Uuid->Data4[4] = address[2];
Uuid->Data4[5] = address[3];
Uuid->Data4[6] = address[4];
Uuid->Data4[7] = address[5];
LeaveCriticalSection(&uuid_cs);
TRACE("%s\n", debugstr_guid(Uuid)); TRACE("%s\n", debugstr_guid(Uuid));
return status; return RPC_S_OK;
} }
/************************************************************************* /*************************************************************************

View file

@ -975,12 +975,18 @@
`char[]'. */ `char[]'. */
#define YYTEXT_POINTER 1 #define YYTEXT_POINTER 1
/* Define to a macro to output a .cfi assembly pseudo-op */
#define __ASM_CFI(x)
/* Define to a macro to generate an assembly function directive */ /* Define to a macro to generate an assembly function directive */
#define __ASM_FUNC(name) ".def " __ASM_NAME(name) "; .scl 2; .type 32; .endef" #define __ASM_FUNC(name) ".def " __ASM_NAME(name) "; .scl 2; .type 32; .endef"
/* Define to a macro to generate an assembly name from a C symbol */ /* Define to a macro to generate an assembly name from a C symbol */
#define __ASM_NAME(name) "_" name #define __ASM_NAME(name) "_" name
/* Define to a macro to generate an stdcall suffix */
#define __ASM_STDCALL(args) "@" #args
/* Define to empty if `const' does not conform to ANSI C. */ /* Define to empty if `const' does not conform to ANSI C. */
/* #undef const */ /* #undef const */