- Revert rpcrt4 back to 1.1.31-partial. Fixes various RPC related regressions.
svn path=/trunk/; revision=44287
* COM proxy implementation
*
* Copyright 2001 Ove Kåven, TransGaming Technologies
- * Copyright 2009 Alexandre Julliard
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* TODO: Handle non-i386 architectures
*/
-#include "config.h"
-#include "wine/port.h"
-
#include <stdarg.h>
#define COBJMACROS
WINE_DEFAULT_DEBUG_CHANNEL(ole);
+struct StublessThunk;
+
/* I don't know what MS's std proxy structure looks like,
so this probably doesn't match, but that shouldn't matter */
typedef struct {
const IRpcProxyBufferVtbl *lpVtbl;
LPVOID *PVtbl;
LONG RefCount;
+ const MIDL_STUBLESS_PROXY_INFO *stubless;
const IID* piid;
LPUNKNOWN pUnkOuter;
- IUnknown *base_object; /* must be at offset 0x10 from PVtbl */
- IRpcProxyBuffer *base_proxy;
PCInterfaceName name;
LPPSFACTORYBUFFER pPSFactory;
LPRPCCHANNELBUFFER pChannel;
+ struct StublessThunk *thunks;
} StdProxyImpl;
static const IRpcProxyBufferVtbl StdProxy_Vtbl;
#include "pshpack1.h"
-struct thunk {
+struct StublessThunk {
BYTE push;
DWORD index;
- BYTE jmp;
+ BYTE call;
LONG handler;
+ BYTE ret;
+ WORD bytes;
+ BYTE pad[3];
};
#include "poppack.h"
-extern void call_stubless_func(void);
-__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" );
-
-HRESULT WINAPI ObjectStubless(DWORD *args)
+/* adjust the stack size since we don't use Windows's method */
+#define STACK_ADJUST sizeof(DWORD)
+
+#define FILL_STUBLESS(x,idx,stk) \
+ 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)
{
- DWORD index = args[0];
- 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];
-
- /* 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]);
-
- return NdrClientCall2(stubless->pStubDesc, fs, args + 2);
-}
+ char *args = (char*)(&index + 2);
+ LPVOID iface = *(LPVOID*)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;
+ ICOM_THIS_MULTI(StdProxyImpl,PVtbl,iface);
- block = VirtualAlloc( NULL, BLOCK_SIZE * sizeof(*block),
- MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE );
- if (!block) return NULL;
+ PFORMAT_STRING fs = This->stubless->ProcFormatString + This->stubless->FormatStringOffset[index];
+ unsigned bytes = *(const WORD*)(fs+8) - STACK_ADJUST;
+ TRACE("(%p)->(%d)([%d bytes]) ret=%08x\n", iface, index, bytes, *(DWORD*)(args+bytes));
- 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;
+ return NdrClientCall2(This->stubless->pStubDesc, fs, args);
}
#else /* __i386__ */
-static BOOL fill_stubless_table( IUnknownVtbl *vtbl, DWORD num )
-{
- ERR("stubless proxies are not supported on this architecture\n");
- return FALSE;
-}
+/* can't do that on this arch */
+struct StublessThunk { int dummy; };
+#define FILL_STUBLESS(x,idx,stk) \
+ ERR("stubless proxies are not supported on this architecture\n");
+#define STACK_ADJUST 0
#endif /* __i386__ */
-HRESULT StdProxy_Construct(REFIID riid,
- LPUNKNOWN pUnkOuter,
- const ProxyFileInfo *ProxyInfo,
- int Index,
- LPPSFACTORYBUFFER pPSFactory,
- LPRPCPROXYBUFFER *ppProxy,
- LPVOID *ppvObj)
+HRESULT WINAPI StdProxy_Construct(REFIID riid,
+ LPUNKNOWN pUnkOuter,
+ const ProxyFileInfo *ProxyInfo,
+ int Index,
+ LPPSFACTORYBUFFER pPSFactory,
+ LPRPCPROXYBUFFER *ppProxy,
+ LPVOID *ppvObj)
{
StdProxyImpl *This;
+ const MIDL_STUBLESS_PROXY_INFO *stubless = NULL;
PCInterfaceName name = ProxyInfo->pNamesArray[Index];
CInterfaceProxyVtbl *vtbl = ProxyInfo->pProxyVtblList[Index];
/* TableVersion = 2 means it is the stubless version of CInterfaceProxyVtbl */
if (ProxyInfo->TableVersion > 1) {
- ULONG count = ProxyInfo->pStubVtblList[Index]->header.DispatchTableCount;
+ stubless = *(const void **)vtbl;
vtbl = (CInterfaceProxyVtbl *)((const void **)vtbl + 1);
- TRACE("stubless vtbl %p: count=%d\n", vtbl->Vtbl, count );
- fill_stubless_table( (IUnknownVtbl *)vtbl->Vtbl, count );
+ TRACE("stubless=%p\n", stubless);
}
+ TRACE("iid=%s\n", debugstr_guid(vtbl->header.piid));
+ TRACE("vtbl=%p\n", vtbl->Vtbl);
+
if (!IsEqualGUID(vtbl->header.piid, riid)) {
ERR("IID mismatch during proxy creation\n");
return RPC_E_UNEXPECTED;
This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(StdProxyImpl));
if (!This) return E_OUTOFMEMORY;
- if (!pUnkOuter) pUnkOuter = (IUnknown *)This;
+ if (stubless) {
+ 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->PVtbl = vtbl->Vtbl;
/* one reference for the proxy */
This->RefCount = 1;
+ This->stubless = stubless;
This->piid = vtbl->header.piid;
- This->base_object = NULL;
- This->base_proxy = NULL;
This->pUnkOuter = pUnkOuter;
This->name = name;
This->pPSFactory = pPSFactory;
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;
*ppvObj = &This->PVtbl;
- IUnknown_AddRef((IUnknown *)*ppvObj);
+ /* if there is no outer unknown then the caller will control the lifetime
+ * 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);
- 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;
}
if (This->pChannel)
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);
+ if (This->thunks) {
+ HeapFree(GetProcessHeap(),0,This->PVtbl);
+ HeapFree(GetProcessHeap(),0,This->thunks);
+ }
HeapFree(GetProcessHeap(),0,This);
}
This->pChannel = pChannel;
IRpcChannelBuffer_AddRef(pChannel);
- if (This->base_proxy) IRpcProxyBuffer_Connect( This->base_proxy, pChannel );
return S_OK;
}
ICOM_THIS_MULTI(StdProxyImpl,lpVtbl,iface);
TRACE("(%p)->Disconnect()\n",This);
- if (This->base_proxy) IRpcProxyBuffer_Disconnect( This->base_proxy );
-
IRpcChannelBuffer_Release(This->pChannel);
This->pChannel = NULL;
}
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.@]
*/
pPSFactoryBuffer);
*ppv = NULL;
- if (!pPSFactoryBuffer->lpVtbl) init_psfactory( pPSFactoryBuffer, pProxyFileList );
+ if (!pPSFactoryBuffer->lpVtbl) {
+ 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))
return IPSFactoryBuffer_QueryInterface((LPPSFACTORYBUFFER)pPSFactoryBuffer, iid, ppv);
else {
*/
HRESULT WINAPI NdrDllCanUnloadNow(CStdPSFactoryBuffer *pPSFactoryBuffer)
{
- return pPSFactoryBuffer->RefCount != 0 ? S_FALSE : S_OK;
+ return !(pPSFactoryBuffer->RefCount);
}
if (len && len < sizeof(module)) {
TRACE("registering CLSID %s => %s\n", debugstr_w(clsid), debugstr_w(module));
if (RegCreateKeyW(HKEY_CLASSES_ROOT, keyname, &key) == ERROR_SUCCESS) {
- RegSetValueExW(key, NULL, 0, REG_SZ, (const BYTE *)psfactoryW, sizeof(psfactoryW));
+ RegSetValueExW(subkey, NULL, 0, REG_SZ, (const BYTE *)psfactoryW, sizeof(psfactoryW));
if (RegCreateKeyW(key, inprocserverW, &subkey) == ERROR_SUCCESS) {
RegSetValueExW(subkey, NULL, 0, REG_SZ, (LPBYTE)module, (strlenW(module)+1)*sizeof(WCHAR));
RegSetValueExW(subkey, threadingmodelW, 0, REG_SZ, (const BYTE *)bothW, sizeof(bothW));
#ifndef __WINE_CPSF_H
#define __WINE_CPSF_H
-HRESULT StdProxy_Construct(REFIID riid, LPUNKNOWN pUnkOuter, const ProxyFileInfo *ProxyInfo,
- int Index, LPPSFACTORYBUFFER pPSFactory, LPRPCPROXYBUFFER *ppProxy,
- LPVOID *ppvObj);
-
-HRESULT CStdStubBuffer_Construct(REFIID riid, LPUNKNOWN pUnkServer, PCInterfaceName name,
- CInterfaceStubVtbl *vtbl, LPPSFACTORYBUFFER pPSFactory,
- LPRPCSTUBBUFFER *ppStub);
-
-HRESULT CStdStubBuffer_Delegating_Construct(REFIID riid, LPUNKNOWN pUnkServer, PCInterfaceName name,
- CInterfaceStubVtbl *vtbl, REFIID delegating_iid,
- LPPSFACTORYBUFFER pPSFactory, LPRPCSTUBBUFFER *ppStub);
+HRESULT WINAPI StdProxy_Construct(REFIID riid,
+ LPUNKNOWN pUnkOuter,
+ const ProxyFileInfo *ProxyInfo,
+ int Index,
+ LPPSFACTORYBUFFER pPSFactory,
+ LPRPCPROXYBUFFER *ppProxy,
+ LPVOID *ppvObj);
+
+HRESULT WINAPI CStdStubBuffer_Construct(REFIID riid,
+ LPUNKNOWN pUnkServer,
+ PCInterfaceName name,
+ CInterfaceStubVtbl *vtbl,
+ LPPSFACTORYBUFFER pPSFactory,
+ LPRPCSTUBBUFFER *ppStub);
+
+HRESULT WINAPI CStdStubBuffer_Delegating_Construct(REFIID riid,
+ LPUNKNOWN pUnkServer,
+ PCInterfaceName name,
+ CInterfaceStubVtbl *vtbl,
+ REFIID delegating_iid,
+ LPPSFACTORYBUFFER pPSFactory,
+ LPRPCSTUBBUFFER *ppStub);
const MIDL_SERVER_INFO *CStdStubBuffer_GetServerInfo(IRpcStubBuffer *iface);
const IRpcStubBufferVtbl CStdStubBuffer_Vtbl;
const IRpcStubBufferVtbl CStdStubBuffer_Delegating_Vtbl;
-BOOL fill_delegated_proxy_table(IUnknownVtbl *vtbl, DWORD num);
-HRESULT create_proxy(REFIID iid, IUnknown *pUnkOuter, IRpcProxyBuffer **pproxy, void **ppv);
+void create_delegating_vtbl(DWORD num_methods);
+
HRESULT create_stub(REFIID iid, IUnknown *pUnk, IRpcStubBuffer **ppstub);
#endif /* __WINE_CPSF_H */
* COM stub (CStdStubBuffer) implementation
*
* Copyright 2001 Ove Kåven, TransGaming Technologies
- * Copyright 2009 Alexandre Julliard
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
return (cstdstubbuffer_delegating_t*)((char *)iface - FIELD_OFFSET(cstdstubbuffer_delegating_t, stub_buffer));
}
-HRESULT CStdStubBuffer_Construct(REFIID riid,
- LPUNKNOWN pUnkServer,
- PCInterfaceName name,
- CInterfaceStubVtbl *vtbl,
- LPPSFACTORYBUFFER pPSFactory,
- LPRPCSTUBBUFFER *ppStub)
+HRESULT WINAPI CStdStubBuffer_Construct(REFIID riid,
+ LPUNKNOWN pUnkServer,
+ PCInterfaceName name,
+ CInterfaceStubVtbl *vtbl,
+ LPPSFACTORYBUFFER pPSFactory,
+ LPRPCSTUBBUFFER *ppStub)
{
CStdStubBuffer *This;
IUnknown *pvServer;
{
DWORD ref;
DWORD size;
+ void **methods;
IUnknownVtbl vtbl;
/* remaining entries in vtbl */
} ref_counted_vtbl;
-static ref_counted_vtbl *current_vtbl;
+static struct
+{
+ ref_counted_vtbl *table;
+} current_vtbl;
static HRESULT WINAPI delegating_QueryInterface(IUnknown *pUnk, REFIID iid, void **ppv)
{
- *ppv = pUnk;
+ *ppv = (void *)pUnk;
return S_OK;
}
} vtbl_method_t;
#include "poppack.h"
-#define BLOCK_SIZE 1024
-#define MAX_BLOCKS 64 /* 64k methods should be enough for anybody */
-
-static const vtbl_method_t *method_blocks[MAX_BLOCKS];
-
-static const vtbl_method_t *allocate_block( unsigned int num )
+static void fill_table(IUnknownVtbl *vtbl, void **methods, DWORD 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;
-}
+ vtbl_method_t *method;
+ void **entry;
+ DWORD i;
-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->AddRef = delegating_AddRef;
vtbl->Release = delegating_Release;
- 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++ = &block[j];
- }
- return TRUE;
-}
-BOOL fill_delegated_proxy_table(IUnknownVtbl *vtbl, DWORD num)
-{
- const void **entry = (const void **)(vtbl + 1);
- DWORD i, j;
+ method = (vtbl_method_t*)methods;
+ entry = (void**)(vtbl + 1);
- 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++)
+ for(i = 3; i < num; 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];
+ *entry = method;
+ method->mov1 = 0x0424448b;
+ method->mov2 = 0x408b;
+ 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;
}
#else /* __i386__ */
-static BOOL fill_delegated_stub_table(IUnknownVtbl *vtbl, DWORD num)
+typedef struct {int dummy;} vtbl_method_t;
+static void fill_table(IUnknownVtbl *vtbl, void **methods, DWORD num)
{
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__ */
-static IUnknownVtbl *get_delegating_vtbl(DWORD num_methods)
+void create_delegating_vtbl(DWORD num_methods)
{
- IUnknownVtbl *ret;
-
- if (num_methods < 256) num_methods = 256; /* avoid frequent reallocations */
+ 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 || num_methods > current_vtbl->size)
+ if(!current_vtbl.table || num_methods > current_vtbl.table->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)
+ DWORD size;
+ DWORD old_protect;
+ if(current_vtbl.table && current_vtbl.table->ref == 0)
{
TRACE("freeing old table\n");
- HeapFree(GetProcessHeap(), 0, current_vtbl);
+ VirtualFree(current_vtbl.table->methods, 0, MEM_RELEASE);
+ HeapFree(GetProcessHeap(), 0, current_vtbl.table);
}
- 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(¤t_vtbl.table->vtbl, current_vtbl.table->methods, num_methods);
+ VirtualProtect(current_vtbl.table->methods, size, PAGE_EXECUTE_READ, &old_protect);
}
+ LeaveCriticalSection(&delegating_vtbl_section);
+}
- current_vtbl->ref++;
- ret = ¤t_vtbl->vtbl;
+static IUnknownVtbl *get_delegating_vtbl(void)
+{
+ IUnknownVtbl *ret;
+
+ EnterCriticalSection(&delegating_vtbl_section);
+ current_vtbl.table->ref++;
+ ret = ¤t_vtbl.table->vtbl;
LeaveCriticalSection(&delegating_vtbl_section);
return ret;
}
EnterCriticalSection(&delegating_vtbl_section);
table->ref--;
TRACE("ref now %d\n", table->ref);
- if(table->ref == 0 && table != current_vtbl)
+ if(table->ref == 0 && table != current_vtbl.table)
{
TRACE("... and we're not current so free'ing\n");
+ VirtualFree(current_vtbl.table->methods, 0, MEM_RELEASE);
HeapFree(GetProcessHeap(), 0, table);
}
LeaveCriticalSection(&delegating_vtbl_section);
}
-HRESULT CStdStubBuffer_Delegating_Construct(REFIID riid,
- LPUNKNOWN pUnkServer,
- PCInterfaceName name,
- CInterfaceStubVtbl *vtbl,
- REFIID delegating_iid,
- LPPSFACTORYBUFFER pPSFactory,
- LPRPCSTUBBUFFER *ppStub)
+HRESULT WINAPI CStdStubBuffer_Delegating_Construct(REFIID riid,
+ LPUNKNOWN pUnkServer,
+ PCInterfaceName name,
+ CInterfaceStubVtbl *vtbl,
+ REFIID delegating_iid,
+ LPPSFACTORYBUFFER pPSFactory,
+ LPRPCSTUBBUFFER *ppStub)
{
cstdstubbuffer_delegating_t *This;
IUnknown *pvServer;
return E_OUTOFMEMORY;
}
- This->base_obj = get_delegating_vtbl( vtbl->header.DispatchTableCount );
+ This->base_obj = get_delegating_vtbl();
r = create_stub(delegating_iid, (IUnknown*)&This->base_obj, &This->base_stub);
if(FAILED(r))
{
*
*/
-#include "epm.h"
+#include "epm_c.h"
#define EPM_PROTOCOL_DNET_NSP 0x04
#define EPM_PROTOCOL_OSI_TP4 0x05
static struct context_handle_entry *get_context_entry(NDR_CCONTEXT CContext)
{
- struct context_handle_entry *che = CContext;
+ struct context_handle_entry *che = (struct context_handle_entry*) CContext;
if (che->magic != NDR_CONTEXT_HANDLE_MAGIC)
return NULL;
}
else
{
- ndr_context_handle *wire_data = pBuff;
+ ndr_context_handle *wire_data = (ndr_context_handle *)pBuff;
wire_data->attributes = 0;
wire_data->uuid = GUID_NULL;
}
extern const NDR_MEMORYSIZE NdrMemorySizer[];
extern const NDR_FREE NdrFreer[];
-ULONG ComplexStructSize(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat);
+unsigned long ComplexStructSize(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat);
#endif /* __WINE_NDR_MISC_H */
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.
* This probably looks very much like NdrpCreateStub.
if (pDesc->flag_and_size & HANDLE_PARAM_IS_VIA_PTR)
pArg = *(void **)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset);
else
- pArg = ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset);
+ pArg = (void *)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset);
memcpy(&pObject, pArg, pDesc->flag_and_size & 0xf);
pGenPair = &pStubMsg->StubDesc->aGenericBindingRoutinePairs[pDesc->binding_routine_pair_index];
*phBinding = pGenPair->pfnBind(pObject);
if (pDesc->flag_and_size & HANDLE_PARAM_IS_VIA_PTR)
pArg = *(void **)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset);
else
- pArg = ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset);
+ pArg = (void *)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset);
memcpy(&pObject, pArg, pDesc->flag_and_size & 0xf);
pGenPair = &pStubMsg->StubDesc->aGenericBindingRoutinePairs[pDesc->binding_routine_pair_index];
pGenPair->pfnUnbind(pObject, hBinding);
LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned int stack_size);
__ASM_GLOBAL_FUNC(call_server_func,
"pushl %ebp\n\t"
- __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")
+ "movl %esp, %ebp\n\t"
"pushl %edi\n\t" /* Save registers */
- __ASM_CFI(".cfi_rel_offset %edi,-4\n\t")
"pushl %esi\n\t"
- __ASM_CFI(".cfi_rel_offset %esi,-8\n\t")
"movl 16(%ebp), %eax\n\t" /* Get stack size */
"subl %eax, %esp\n\t" /* Make room in stack for arguments */
"andl $~15, %esp\n\t" /* Make sure stack has 16-byte alignment for Mac OS X */
"call *8(%ebp)\n\t" /* Call function */
"leal -8(%ebp), %esp\n\t" /* Restore stack */
"popl %esi\n\t" /* Restore registers */
- __ASM_CFI(".cfi_same_value %esi\n\t")
"popl %edi\n\t"
- __ASM_CFI(".cfi_same_value %edi\n\t")
"popl %ebp\n\t"
- __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
- __ASM_CFI(".cfi_same_value %ebp\n\t")
- "ret" )
+ "ret\n" )
#else
#warning call_server_func not implemented for your architecture
LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned short stack_size)
DWORD 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;
-}
* RPCF_Asynchronous = 0x4000 - [async] MIDL attribute
* Reserved = 0x8000
*/
- unsigned int rpc_flags;
+ unsigned long rpc_flags;
unsigned short proc_num;
unsigned short stack_size;
PFORMAT_STRING pFormat, int phase, unsigned char *args,
unsigned short stack_size, unsigned char *pRetVal, BOOL object_proc,
BOOL ignore_retval);
-RPC_STATUS NdrpCompleteAsyncClientCall(RPC_ASYNC_STATE *pAsync, void *Reply);
RPC_STATUS RpcServerAssoc_GetAssociation(LPCSTR Protseq, LPCSTR NetworkAddr,
LPCSTR Endpoint, LPCWSTR NetworkOptions,
- ULONG assoc_gid,
+ unsigned long assoc_gid,
RpcAssoc **assoc_out)
{
RpcAssoc *assoc;
RPC_MESSAGE msg;
RPC_STATUS status;
unsigned char *auth_data = NULL;
- ULONG auth_length;
+ unsigned long auth_length;
TRACE("sending bind request to server\n");
if (status != RPC_S_OK)
return status;
- NewConnection->assoc = assoc;
status = RPCRT4_OpenClientConnection(NewConnection);
if (status != RPC_S_OK)
{
void RpcAssoc_ReleaseIdleConnection(RpcAssoc *assoc, RpcConnection *Connection)
{
assert(!Connection->server);
- Connection->async_state = NULL;
EnterCriticalSection(&assoc->cs);
if (!assoc->assoc_group_id) assoc->assoc_group_id = Connection->assoc_group_id;
list_add_head(&assoc->free_connection_pool, &Connection->conn_pool_entry);
/* id of this association group */
ULONG assoc_group_id;
- UUID http_uuid;
CRITICAL_SECTION cs;
RPC_STATUS RpcAssoc_GetClientConnection(RpcAssoc *assoc, const RPC_SYNTAX_IDENTIFIER *InterfaceId, const RPC_SYNTAX_IDENTIFIER *TransferSyntax, RpcAuthInfo *AuthInfo, RpcQualityOfService *QOS, RpcConnection **Connection);
void RpcAssoc_ReleaseIdleConnection(RpcAssoc *assoc, RpcConnection *Connection);
ULONG RpcAssoc_Release(RpcAssoc *assoc);
-RPC_STATUS RpcServerAssoc_GetAssociation(LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint, LPCWSTR NetworkOptions, ULONG assoc_gid, RpcAssoc **assoc_out);
+RPC_STATUS RpcServerAssoc_GetAssociation(LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint, LPCWSTR NetworkOptions, unsigned long assoc_gid, RpcAssoc **assoc_out);
RPC_STATUS RpcServerAssoc_AllocateContextHandle(RpcAssoc *assoc, void *CtxGuard, NDR_SCONTEXT *SContext);
RPC_STATUS RpcServerAssoc_FindContextHandle(RpcAssoc *assoc, const UUID *uuid, void *CtxGuard, ULONG Flags, NDR_SCONTEXT *SContext);
RPC_STATUS RpcServerAssoc_UpdateContextHandle(RpcAssoc *assoc, NDR_SCONTEXT SContext, void *CtxGuard, NDR_RUNDOWN rundown_routine);
#include "rpc_binding.h"
#include "rpc_message.h"
-#include "ndr_stubless.h"
WINE_DEFAULT_DEBUG_CHANNEL(rpc);
#define RPC_ASYNC_SIGNATURE 0x43595341
-static inline BOOL valid_async_handle(PRPC_ASYNC_STATE pAsync)
-{
- return pAsync->Signature == RPC_ASYNC_SIGNATURE;
-}
-
/***********************************************************************
* RpcAsyncInitializeHandle [RPCRT4.@]
*
*/
RPC_STATUS WINAPI RpcAsyncCompleteCall(PRPC_ASYNC_STATE pAsync, void *Reply)
{
- TRACE("(%p, %p)\n", pAsync, Reply);
-
- if (!valid_async_handle(pAsync))
- return RPC_S_INVALID_ASYNC_HANDLE;
-
- /* FIXME: check completed */
-
- return NdrpCompleteAsyncClientCall(pAsync, Reply);
+ FIXME("(%p, %p): stub\n", pAsync, Reply);
+ return RPC_S_INVALID_ASYNC_HANDLE;
}
/***********************************************************************
return RPC_S_OK;
fail:
- if (ObjUuid) RpcStringFreeA(ObjUuid);
- if (Protseq) RpcStringFreeA(Protseq);
- if (NetworkAddr) RpcStringFreeA(NetworkAddr);
- if (Endpoint) RpcStringFreeA(Endpoint);
- if (Options) RpcStringFreeA(Options);
+ if (ObjUuid) RpcStringFreeA((unsigned char**)ObjUuid);
+ if (Protseq) RpcStringFreeA((unsigned char**)Protseq);
+ if (NetworkAddr) RpcStringFreeA((unsigned char**)NetworkAddr);
+ if (Endpoint) RpcStringFreeA((unsigned char**)Endpoint);
+ if (Options) RpcStringFreeA((unsigned char**)Options);
return RPC_S_INVALID_STRING_BINDING;
}
RPC_STATUS WINAPI RpcBindingVectorFree( RPC_BINDING_VECTOR** BindingVector )
{
RPC_STATUS status;
- ULONG c;
+ unsigned long c;
TRACE("(%p)\n", BindingVector);
for (c=0; c<(*BindingVector)->Count; c++) {
*/
RPC_STATUS WINAPI RpcBindingInqObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid )
{
- RpcBinding* bind = Binding;
+ RpcBinding* bind = (RpcBinding*)Binding;
TRACE("(%p,%p) = %s\n", Binding, ObjectUuid, debugstr_guid(&bind->ObjectUuid));
*ObjectUuid = bind->ObjectUuid;
*/
RPC_STATUS WINAPI RpcBindingSetObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid )
{
- RpcBinding* bind = Binding;
+ RpcBinding* bind = (RpcBinding*)Binding;
TRACE("(%p,%s)\n", Binding, debugstr_guid(ObjectUuid));
if (bind->server) return RPC_S_WRONG_KIND_OF_BINDING;
if (ret == RPC_S_OK)
ret = RPCRT4_CompleteBindingA(bind, (char*)NetworkAddr, (char*)Endpoint, (char*)Options);
- RpcStringFreeA(&Options);
- RpcStringFreeA(&Endpoint);
- RpcStringFreeA(&NetworkAddr);
- RpcStringFreeA(&Protseq);
- RpcStringFreeA(&ObjectUuid);
+ RpcStringFreeA((unsigned char**)&Options);
+ RpcStringFreeA((unsigned char**)&Endpoint);
+ RpcStringFreeA((unsigned char**)&NetworkAddr);
+ RpcStringFreeA((unsigned char**)&Protseq);
+ RpcStringFreeA((unsigned char**)&ObjectUuid);
if (ret == RPC_S_OK)
*Binding = (RPC_BINDING_HANDLE)bind;
RPC_STATUS WINAPI RpcBindingToStringBindingA( RPC_BINDING_HANDLE Binding, RPC_CSTR *StringBinding )
{
RPC_STATUS ret;
- RpcBinding* bind = Binding;
+ RpcBinding* bind = (RpcBinding*)Binding;
RPC_CSTR ObjectUuid;
TRACE("(%p,%p)\n", Binding, StringBinding);
TRACE("(%p,%p)\n", Binding, StringBinding);
ret = RpcBindingToStringBindingA(Binding, &str);
*StringBinding = RPCRT4_strdupAtoW((char*)str);
- RpcStringFreeA(&str);
+ RpcStringFreeA((unsigned char**)&str);
return ret;
}
*/
RPC_STATUS WINAPI I_RpcBindingSetAsync( RPC_BINDING_HANDLE Binding, RPC_BLOCKING_FN BlockingFn)
{
- RpcBinding* bind = Binding;
+ RpcBinding* bind = (RpcBinding*)Binding;
TRACE( "(%p,%p): stub\n", Binding, BlockingFn );
RPC_BINDING_HANDLE* DestinationBinding)
{
RpcBinding *DestBinding;
- RpcBinding *SrcBinding = SourceBinding;
+ RpcBinding *SrcBinding = (RpcBinding*)SourceBinding;
RPC_STATUS status;
TRACE("(%p, %p)\n", SourceBinding, DestinationBinding);
RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr,
RPC_SECURITY_QOS *SecurityQos )
{
- RpcBinding* bind = Binding;
+ RpcBinding* bind = (RpcBinding*)Binding;
SECURITY_STATUS r;
CredHandle cred;
TimeStamp exp;
ULONG AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr,
RPC_SECURITY_QOS *SecurityQos )
{
- RpcBinding* bind = Binding;
+ RpcBinding* bind = (RpcBinding*)Binding;
SECURITY_STATUS r;
CredHandle cred;
TimeStamp exp;
PSecPkgInfoW packages;
ULONG cbMaxToken;
- TRACE("%p %s %u %u %p %u %p\n", Binding, debugstr_w(ServerPrincName),
+ TRACE("%p %s %u %u %p %u %p\n", Binding, debugstr_w((const WCHAR*)ServerPrincName),
AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, SecurityQos);
if (SecurityQos)
RpcBindingSetAuthInfoW( RPC_BINDING_HANDLE Binding, RPC_WSTR ServerPrincName, ULONG AuthnLevel,
ULONG AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr )
{
- TRACE("%p %s %u %u %p %u\n", Binding, debugstr_w(ServerPrincName),
+ TRACE("%p %s %u %u %p %u\n", Binding, debugstr_w((const WCHAR*)ServerPrincName),
AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr);
return RpcBindingSetAuthInfoExW(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, NULL);
}
#include "rpcndr.h"
#include "security.h"
#include "wine/list.h"
-#include "rpc_defs.h"
typedef struct _RpcAuthInfo
TimeStamp exp;
ULONG attr;
RpcAuthInfo *AuthInfo;
- ULONG auth_context_id;
ULONG encryption_auth_len;
ULONG signature_auth_len;
RpcQualityOfService *QOS;
struct list conn_pool_entry;
ULONG assoc_group_id; /* association group returned during binding */
RPC_ASYNC_STATE *async_state;
- struct _RpcAssoc *assoc; /* association this connection is part of */
/* server-only */
/* The active interface bound to server. */
int (*wait_for_incoming_data)(RpcConnection *conn);
size_t (*get_top_of_tower)(unsigned char *tower_data, const char *networkaddr, const char *endpoint);
RPC_STATUS (*parse_top_of_tower)(const unsigned char *tower_data, size_t tower_size, char **networkaddr, char **endpoint);
- RPC_STATUS (*receive_fragment)(RpcConnection *conn, RpcPktHdr **Header, void **Payload);
};
/* don't know what MS's structure looks like */
unsigned char drep[4]; /* Data representation */
unsigned short frag_len; /* Data size in bytes including header and tail. */
unsigned short auth_len; /* Authentication length */
- unsigned int call_id; /* Call identifier. */
+ unsigned long call_id; /* Call identifier. */
} RpcPktCommonHdr;
typedef struct
{
RpcPktCommonHdr common;
- unsigned int alloc_hint; /* Data size in bytes excluding header and tail. */
+ unsigned long alloc_hint; /* Data size in bytes excluding header and tail. */
unsigned short context_id; /* Presentation context identifier */
unsigned short opnum;
} RpcPktRequestHdr;
typedef struct
{
RpcPktCommonHdr common;
- unsigned int alloc_hint; /* Data size in bytes excluding header and tail. */
+ unsigned long alloc_hint; /* Data size in bytes excluding header and tail. */
unsigned short context_id; /* Presentation context identifier */
unsigned char cancel_count;
unsigned char reserved;
typedef struct
{
RpcPktCommonHdr common;
- unsigned int alloc_hint; /* Data size in bytes excluding header and tail. */
+ unsigned long alloc_hint; /* Data size in bytes excluding header and tail. */
unsigned short context_id; /* Presentation context identifier */
unsigned char cancel_count; /* Received cancel count */
unsigned char reserved; /* Force alignment! */
- unsigned int status; /* Runtime fault code (RPC_STATUS) */
- unsigned int reserved2;
+ unsigned long status; /* Runtime fault code (RPC_STATUS) */
+ unsigned long reserved2;
} RpcPktFaultHdr;
typedef struct
RpcPktCommonHdr common;
unsigned short max_tsize; /* Maximum transmission fragment size */
unsigned short max_rsize; /* Maximum receive fragment size */
- unsigned int assoc_gid; /* Associated group id */
+ unsigned long assoc_gid; /* Associated group id */
unsigned char num_elements; /* Number of elements */
unsigned char padding[3]; /* Force alignment! */
unsigned short context_id; /* Presentation context identifier */
RpcPktCommonHdr common;
unsigned short max_tsize; /* Maximum transmission fragment size */
unsigned short max_rsize; /* Maximum receive fragment size */
- unsigned int assoc_gid; /* Associated group id */
+ unsigned long assoc_gid; /* Associated group id */
/*
* Following this header are these fields:
* RpcAddressString server_address;
} protocols[1];
} 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 */
typedef union
{
RpcPktBindHdr bind;
RpcPktBindAckHdr bind_ack;
RpcPktBindNAckHdr bind_nack;
- RpcPktHttpHdr http;
} RpcPktHdr;
typedef struct
unsigned char auth_level; /* RPC_C_AUTHN_LEVEL* */
unsigned char auth_pad_length; /* length of padding to restore n % 4 alignment */
unsigned char auth_reserved; /* reserved, must be zero */
- unsigned int auth_context_id; /* unique value for the authenticated connection */
+ unsigned long auth_context_id; /* unique value for the authenticated connection */
} RpcAuthVerifier;
#define RPC_AUTH_VERIFIER_LEN(common_hdr) \
#define PKT_SHUTDOWN 17
#define PKT_CO_CANCEL 18
#define PKT_ORPHANED 19
-#define PKT_HTTP 20
#define RESULT_ACCEPT 0
#define RESULT_USER_REJECTION 1
#include "wine/exception.h"
#include "rpc_binding.h"
-#include "epm.h"
+#include "epm_c.h"
#include "epm_towers.h"
WINE_DEFAULT_DEBUG_CHANNEL(ole);
static inline BOOL is_epm_destination_local(RPC_BINDING_HANDLE handle)
{
- RpcBinding *bind = handle;
+ RpcBinding *bind = (RpcBinding *)handle;
const char *protseq = bind->Protseq;
const char *network_addr = bind->NetworkAddr;
static RPC_STATUS get_epm_handle_client(RPC_BINDING_HANDLE handle, RPC_BINDING_HANDLE *epm_handle)
{
- RpcBinding *bind = handle;
+ RpcBinding *bind = (RpcBinding *)handle;
const char * pszEndpoint = NULL;
RPC_STATUS status;
RpcBinding* epm_bind;
status = RpcBindingCopy(handle, epm_handle);
if (status != RPC_S_OK) return status;
- epm_bind = *epm_handle;
+ epm_bind = (RpcBinding*)*epm_handle;
if (epm_bind->AuthInfo)
{
/* don't bother with authenticating against the EPM by default
RPC_STATUS WINAPI RpcEpRegisterA( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *BindingVector,
UUID_VECTOR *UuidVector, RPC_CSTR Annotation )
{
- PRPC_SERVER_INTERFACE If = IfSpec;
- ULONG i;
+ PRPC_SERVER_INTERFACE If = (PRPC_SERVER_INTERFACE)IfSpec;
+ unsigned long i;
RPC_STATUS status = RPC_S_OK;
error_status_t status2;
ept_entry_t *entries;
TRACE("(%p,%p,%p,%s)\n", IfSpec, BindingVector, UuidVector, debugstr_a((char*)Annotation));
TRACE(" ifid=%s\n", debugstr_guid(&If->InterfaceId.SyntaxGUID));
for (i=0; i<BindingVector->Count; i++) {
- RpcBinding* bind = BindingVector->BindingH[i];
- TRACE(" protseq[%d]=%s\n", i, debugstr_a(bind->Protseq));
- TRACE(" endpoint[%d]=%s\n", i, debugstr_a(bind->Endpoint));
+ RpcBinding* bind = (RpcBinding*)(BindingVector->BindingH[i]);
+ TRACE(" protseq[%ld]=%s\n", i, debugstr_a(bind->Protseq));
+ TRACE(" endpoint[%ld]=%s\n", i, debugstr_a(bind->Endpoint));
}
if (UuidVector) {
for (i=0; i<UuidVector->Count; i++)
- TRACE(" obj[%d]=%s\n", i, debugstr_guid(UuidVector->Uuid[i]));
+ TRACE(" obj[%ld]=%s\n", i, debugstr_guid(UuidVector->Uuid[i]));
}
if (!BindingVector->Count) return RPC_S_OK;
for (i = 0; i < BindingVector->Count; i++)
{
unsigned j;
- RpcBinding* bind = BindingVector->BindingH[i];
+ RpcBinding* bind = (RpcBinding*)(BindingVector->BindingH[i]);
for (j = 0; j < (UuidVector ? UuidVector->Count : 1); j++)
{
+ int len = strlen((char *)Annotation);
status = TowerConstruct(&If->InterfaceId, &If->TransferSyntax,
bind->Protseq, bind->Endpoint,
bind->NetworkAddr,
memcpy(&entries[i * UuidVector->Count].object, &UuidVector->Uuid[j], sizeof(GUID));
else
memset(&entries[i].object, 0, sizeof(entries[i].object));
- if (Annotation)
- memcpy(entries[i].annotation, Annotation,
- min(strlen((char *)Annotation) + 1, ept_max_annotation_size));
+ memcpy(entries[i].annotation, Annotation, min(len + 1, ept_max_annotation_size));
}
}
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.@)
*/
RPC_STATUS WINAPI RpcEpUnregister( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *BindingVector,
UUID_VECTOR *UuidVector )
{
- PRPC_SERVER_INTERFACE If = IfSpec;
- ULONG i;
+ PRPC_SERVER_INTERFACE If = (PRPC_SERVER_INTERFACE)IfSpec;
+ unsigned long i;
RPC_STATUS status = RPC_S_OK;
error_status_t status2;
ept_entry_t *entries;
TRACE("(%p,%p,%p)\n", IfSpec, BindingVector, UuidVector);
TRACE(" ifid=%s\n", debugstr_guid(&If->InterfaceId.SyntaxGUID));
for (i=0; i<BindingVector->Count; i++) {
- RpcBinding* bind = BindingVector->BindingH[i];
- TRACE(" protseq[%d]=%s\n", i, debugstr_a(bind->Protseq));
- TRACE(" endpoint[%d]=%s\n", i, debugstr_a(bind->Endpoint));
+ RpcBinding* bind = (RpcBinding*)(BindingVector->BindingH[i]);
+ TRACE(" protseq[%ld]=%s\n", i, debugstr_a(bind->Protseq));
+ TRACE(" endpoint[%ld]=%s\n", i, debugstr_a(bind->Endpoint));
}
if (UuidVector) {
for (i=0; i<UuidVector->Count; i++)
- TRACE(" obj[%d]=%s\n", i, debugstr_guid(UuidVector->Uuid[i]));
+ TRACE(" obj[%ld]=%s\n", i, debugstr_guid(UuidVector->Uuid[i]));
}
entries = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*entries) * BindingVector->Count * (UuidVector ? UuidVector->Count : 1));
for (i = 0; i < BindingVector->Count; i++)
{
unsigned j;
- RpcBinding* bind = BindingVector->BindingH[i];
+ RpcBinding* bind = (RpcBinding*)(BindingVector->BindingH[i]);
for (j = 0; j < (UuidVector ? UuidVector->Count : 1); j++)
{
status = TowerConstruct(&If->InterfaceId, &If->TransferSyntax,
*/
RPC_STATUS WINAPI RpcEpResolveBinding( RPC_BINDING_HANDLE Binding, RPC_IF_HANDLE IfSpec )
{
- PRPC_CLIENT_INTERFACE If = IfSpec;
- RpcBinding* bind = Binding;
+ PRPC_CLIENT_INTERFACE If = (PRPC_CLIENT_INTERFACE)IfSpec;
+ RpcBinding* bind = (RpcBinding*)Binding;
RPC_STATUS status;
error_status_t status2;
handle_t handle;
static RPC_STATUS I_RpcReAllocateBuffer(PRPC_MESSAGE pMsg);
-DWORD RPCRT4_GetHeaderSize(const RpcPktHdr *Header)
+static DWORD RPCRT4_GetHeaderSize(const RpcPktHdr *Header)
{
static const DWORD header_sizes[] = {
sizeof(Header->request), 0, sizeof(Header->response),
sizeof(Header->fault), 0, 0, 0, 0, 0, 0, 0, sizeof(Header->bind),
sizeof(Header->bind_ack), sizeof(Header->bind_nack),
- 0, 0, 0, 0, 0, 0, sizeof(Header->http)
+ 0, 0, 0, 0, 0
};
ULONG ret = 0;
if (Header->common.flags & RPC_FLG_OBJECT_UUID)
ret += sizeof(UUID);
} else {
- WARN("invalid packet type %u\n", Header->common.ptype);
+ TRACE("invalid packet type\n");
}
return ret;
}
static VOID RPCRT4_BuildCommonHeader(RpcPktHdr *Header, unsigned char PacketType,
- ULONG DataRepresentation)
+ unsigned long DataRepresentation)
{
Header->common.rpc_ver = RPC_VER_MAJOR;
Header->common.rpc_ver_minor = RPC_VER_MINOR;
/* Flags and fragment length are computed in RPCRT4_Send. */
}
-static RpcPktHdr *RPCRT4_BuildRequestHeader(ULONG DataRepresentation,
- ULONG BufferLength,
+static RpcPktHdr *RPCRT4_BuildRequestHeader(unsigned long DataRepresentation,
+ unsigned long BufferLength,
unsigned short ProcNum,
UUID *ObjectUuid)
{
return header;
}
-RpcPktHdr *RPCRT4_BuildResponseHeader(ULONG DataRepresentation, ULONG BufferLength)
+RpcPktHdr *RPCRT4_BuildResponseHeader(unsigned long DataRepresentation,
+ unsigned long BufferLength)
{
RpcPktHdr *header;
return header;
}
-RpcPktHdr *RPCRT4_BuildFaultHeader(ULONG DataRepresentation, RPC_STATUS Status)
+RpcPktHdr *RPCRT4_BuildFaultHeader(unsigned long DataRepresentation,
+ RPC_STATUS Status)
{
RpcPktHdr *header;
return header;
}
-RpcPktHdr *RPCRT4_BuildBindHeader(ULONG DataRepresentation,
+RpcPktHdr *RPCRT4_BuildBindHeader(unsigned long DataRepresentation,
unsigned short MaxTransmissionSize,
unsigned short MaxReceiveSize,
- ULONG AssocGroupId,
+ unsigned long AssocGroupId,
const RPC_SYNTAX_IDENTIFIER *AbstractId,
const RPC_SYNTAX_IDENTIFIER *TransferId)
{
return header;
}
-static RpcPktHdr *RPCRT4_BuildAuthHeader(ULONG DataRepresentation)
+static RpcPktHdr *RPCRT4_BuildAuthHeader(unsigned long DataRepresentation)
{
RpcPktHdr *header;
return header;
}
-RpcPktHdr *RPCRT4_BuildBindNackHeader(ULONG DataRepresentation,
+RpcPktHdr *RPCRT4_BuildBindNackHeader(unsigned long DataRepresentation,
unsigned char RpcVersion,
unsigned char RpcVersionMinor)
{
return header;
}
-RpcPktHdr *RPCRT4_BuildBindAckHeader(ULONG DataRepresentation,
+RpcPktHdr *RPCRT4_BuildBindAckHeader(unsigned long DataRepresentation,
unsigned short MaxTransmissionSize,
unsigned short MaxReceiveSize,
- ULONG AssocGroupId,
+ unsigned long AssocGroupId,
LPCSTR ServerAddress,
- unsigned short Result,
- unsigned short Reason,
+ unsigned long Result,
+ unsigned long Reason,
const RPC_SYNTAX_IDENTIFIER *TransferId)
{
RpcPktHdr *header;
- ULONG header_size;
+ unsigned long header_size;
RpcAddressString *server_address;
RpcResults *results;
RPC_SYNTAX_IDENTIFIER *transfer_id;
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)
{
HeapFree(GetProcessHeap(), 0, Header);
}
}
-/* 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,
enum secure_packet_direction dir,
RpcPktHdr *hdr, unsigned int hdr_size,
auth_hdr->auth_pad_length = auth_pad_len;
auth_hdr->auth_reserved = 0;
/* a unique number... */
- auth_hdr->auth_context_id = Connection->auth_context_id;
+ auth_hdr->auth_context_id = (unsigned long)Connection;
if (AuthLength)
memcpy(auth_hdr + 1, Auth, AuthLength);
}
/* validates version and frag_len fields */
-RPC_STATUS RPCRT4_ValidateCommonHeader(const RpcPktCommonHdr *hdr)
+static RPC_STATUS RPCRT4_ValidateCommonHeader(const RpcPktCommonHdr *hdr)
{
DWORD hdr_length;
}
/***********************************************************************
- * RPCRT4_default_receive_fragment (internal)
+ * RPCRT4_receive_fragment (internal)
*
* Receive a fragment from a connection.
*/
-static RPC_STATUS RPCRT4_default_receive_fragment(RpcConnection *Connection, RpcPktHdr **Header, void **Payload)
+static RPC_STATUS RPCRT4_receive_fragment(RpcConnection *Connection, RpcPktHdr **Header, void **Payload)
{
RPC_STATUS status;
DWORD hdr_length;
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)
*
RPC_STATUS RPCRT4_ReceiveWithAuth(RpcConnection *Connection, RpcPktHdr **Header,
PRPC_MESSAGE pMsg,
unsigned char **auth_data_out,
- ULONG *auth_length_out)
+ unsigned long *auth_length_out)
{
RPC_STATUS status;
DWORD hdr_length;
unsigned short first_flag;
- ULONG data_length;
- ULONG buffer_length;
- ULONG auth_length = 0;
+ unsigned long data_length;
+ unsigned long buffer_length;
+ unsigned long auth_length = 0;
unsigned char *auth_data = NULL;
RpcPktHdr *CurrentHeader = NULL;
void *payload = NULL;
}
if (CurrentHeader->common.auth_len != auth_length) {
- WARN("auth_len header field changed from %d to %d\n",
+ WARN("auth_len header field changed from %ld to %d\n",
auth_length, CurrentHeader->common.auth_len);
status = RPC_S_PROTOCOL_ERROR;
goto fail;
data_length = CurrentHeader->common.frag_len - hdr_length - header_auth_len;
if (data_length + buffer_length > pMsg->BufferLength) {
- TRACE("allocation hint exceeded, new buffer length = %d\n",
+ TRACE("allocation hint exceeded, new buffer length = %ld\n",
data_length + buffer_length);
pMsg->BufferLength = data_length + buffer_length;
status = I_RpcReAllocateBuffer(pMsg);
*/
RPC_STATUS WINAPI I_RpcNegotiateTransferSyntax(PRPC_MESSAGE pMsg)
{
- RpcBinding* bind = pMsg->Handle;
+ RpcBinding* bind = (RpcBinding*)pMsg->Handle;
RpcConnection* conn;
RPC_STATUS status = RPC_S_OK;
RPC_STATUS WINAPI I_RpcGetBuffer(PRPC_MESSAGE pMsg)
{
RPC_STATUS status;
- RpcBinding* bind = pMsg->Handle;
+ RpcBinding* bind = (RpcBinding*)pMsg->Handle;
TRACE("(%p): BufferLength=%d\n", pMsg, pMsg->BufferLength);
*/
RPC_STATUS WINAPI I_RpcFreeBuffer(PRPC_MESSAGE pMsg)
{
- RpcBinding* bind = pMsg->Handle;
+ RpcBinding* bind = (RpcBinding*)pMsg->Handle;
TRACE("(%p) Buffer=%p\n", pMsg, pMsg->Buffer);
*/
RPC_STATUS WINAPI I_RpcSend(PRPC_MESSAGE pMsg)
{
- RpcBinding* bind = pMsg->Handle;
+ RpcBinding* bind = (RpcBinding*)pMsg->Handle;
RpcConnection* conn;
RPC_STATUS status;
RpcPktHdr *hdr;
*/
RPC_STATUS WINAPI I_RpcReceive(PRPC_MESSAGE pMsg)
{
- RpcBinding* bind = pMsg->Handle;
+ RpcBinding* bind = (RpcBinding*)pMsg->Handle;
RPC_STATUS status;
RpcPktHdr *hdr = NULL;
RpcConnection *conn;
case PKT_RESPONSE:
break;
case PKT_FAULT:
- ERR ("we got fault packet with status 0x%x\n", hdr->fault.status);
+ ERR ("we got fault packet with status 0x%lx\n", hdr->fault.status);
status = NCA2RPC_STATUS(hdr->fault.status);
if (is_hard_error(status))
goto fail;
*/
RPC_STATUS WINAPI I_RpcAsyncSetHandle(PRPC_MESSAGE pMsg, PRPC_ASYNC_STATE pAsync)
{
- RpcBinding* bind = pMsg->Handle;
+ RpcBinding* bind = (RpcBinding*)pMsg->Handle;
RpcConnection *conn;
TRACE("(%p, %p)\n", pMsg, pAsync);
typedef unsigned int NCA_STATUS;
-RpcPktHdr *RPCRT4_BuildFaultHeader(ULONG DataRepresentation, RPC_STATUS Status);
-RpcPktHdr *RPCRT4_BuildResponseHeader(ULONG DataRepresentation, ULONG BufferLength);
-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(ULONG DataRepresentation, unsigned char RpcVersion, unsigned char RpcVersionMinor);
-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);
+RpcPktHdr *RPCRT4_BuildFaultHeader(unsigned long DataRepresentation, RPC_STATUS Status);
+RpcPktHdr *RPCRT4_BuildResponseHeader(unsigned long DataRepresentation, unsigned long BufferLength);
+RpcPktHdr *RPCRT4_BuildBindHeader(unsigned long DataRepresentation, unsigned short MaxTransmissionSize, unsigned short MaxReceiveSize, unsigned long AssocGroupId, const RPC_SYNTAX_IDENTIFIER *AbstractId, const RPC_SYNTAX_IDENTIFIER *TransferId);
+RpcPktHdr *RPCRT4_BuildBindNackHeader(unsigned long DataRepresentation, unsigned char RpcVersion, unsigned char RpcVersionMinor);
+RpcPktHdr *RPCRT4_BuildBindAckHeader(unsigned long DataRepresentation, unsigned short MaxTransmissionSize, unsigned short MaxReceiveSize, unsigned long AssocGroupId, LPCSTR ServerAddress, unsigned long Result, unsigned long Reason, const RPC_SYNTAX_IDENTIFIER *TransferId);
VOID RPCRT4_FreeHeader(RpcPktHdr *Header);
RPC_STATUS RPCRT4_Send(RpcConnection *Connection, RpcPktHdr *Header, void *Buffer, unsigned int BufferLength);
RPC_STATUS RPCRT4_Receive(RpcConnection *Connection, RpcPktHdr **Header, PRPC_MESSAGE pMsg);
-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);
+RPC_STATUS RPCRT4_ReceiveWithAuth(RpcConnection *Connection, RpcPktHdr **Header, PRPC_MESSAGE pMsg, unsigned char **auth_data_out, unsigned long *auth_length_out);
NCA_STATUS RPC2NCA_STATUS(RPC_STATUS status);
RPC_STATUS RPCRT4_AuthorizeConnection(RpcConnection* conn, BYTE *challenge, ULONG count);
static DWORD CALLBACK RPCRT4_io_thread(LPVOID the_arg)
{
- RpcConnection* conn = the_arg;
+ RpcConnection* conn = (RpcConnection*)the_arg;
RpcPktHdr *hdr;
RPC_MESSAGE *msg;
RPC_STATUS status;
/* start waiting */
res = cps->ops->wait_for_new_connection(cps, count, objs);
-
- if (res == -1 || (res == 0 && !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);
+ if (res == -1)
break;
- }
else if (res == 0)
+ {
+ if (!std_listen)
+ {
+ SetEvent(cps->server_ready_event);
+ break;
+ }
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;
}
LeaveCriticalSection(&listen_cs);
}
-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)
+static RPC_STATUS RPCRT4_use_protseq(RpcServerProtseq* ps, LPSTR endpoint)
{
RPC_STATUS status;
- 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);
-
+ status = ps->ops->open_endpoint(ps, endpoint);
if (status != RPC_S_OK)
return status;
count = 0;
LIST_FOR_EACH_ENTRY(ps, &protseqs, RpcServerProtseq, entry) {
EnterCriticalSection(&ps->cs);
- for (conn = ps->conn; conn; conn = conn->Next)
+ conn = ps->conn;
+ while (conn) {
count++;
+ conn = conn->Next;
+ }
LeaveCriticalSection(&ps->cs);
}
if (count) {
count = 0;
LIST_FOR_EACH_ENTRY(ps, &protseqs, RpcServerProtseq, entry) {
EnterCriticalSection(&ps->cs);
- for (conn = ps->conn; conn; conn = conn->Next) {
+ conn = ps->conn;
+ while (conn) {
RPCRT4_MakeBinding((RpcBinding**)&(*BindingVector)->BindingH[count],
conn);
count++;
+ conn = conn->Next;
}
LeaveCriticalSection(&ps->cs);
}
*
* Must be called with server_cs held.
*/
-static RPC_STATUS alloc_serverprotoseq(UINT MaxCalls, const char *Protseq, RpcServerProtseq **ps)
+static RPC_STATUS alloc_serverprotoseq(UINT MaxCalls, char *Protseq, RpcServerProtseq **ps)
{
const struct protseq_ops *ops = rpcrt4_get_protseq_ops(Protseq);
if (!*ps)
return RPC_S_OUT_OF_RESOURCES;
(*ps)->MaxCalls = MaxCalls;
- (*ps)->Protseq = RPCRT4_strdupA(Protseq);
+ (*ps)->Protseq = Protseq;
(*ps)->ops = ops;
(*ps)->MaxCalls = 0;
(*ps)->conn = NULL;
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 */
-static RPC_STATUS RPCRT4_get_or_create_serverprotseq(UINT MaxCalls, const char *Protseq, RpcServerProtseq **ps)
+static RPC_STATUS RPCRT4_get_or_create_serverprotseq(UINT MaxCalls, char *Protseq, RpcServerProtseq **ps)
{
RPC_STATUS status;
RpcServerProtseq *cps;
RPC_STATUS WINAPI RpcServerUseProtseqEpExA( RPC_CSTR Protseq, UINT MaxCalls, RPC_CSTR Endpoint, LPVOID SecurityDescriptor,
PRPC_POLICY lpPolicy )
{
+ char *szps = (char*)Protseq, *szep = (char*)Endpoint;
RpcServerProtseq* ps;
RPC_STATUS status;
- TRACE("(%s,%u,%s,%p,{%u,%u,%u})\n", debugstr_a((const char *)Protseq),
- MaxCalls, debugstr_a((const char *)Endpoint), SecurityDescriptor,
+ TRACE("(%s,%u,%s,%p,{%u,%u,%u})\n", debugstr_a(szps), MaxCalls,
+ debugstr_a(szep), SecurityDescriptor,
lpPolicy->Length, lpPolicy->EndpointFlags, lpPolicy->NICFlags );
- status = RPCRT4_get_or_create_serverprotseq(MaxCalls, (const char *)Protseq, &ps);
+ status = RPCRT4_get_or_create_serverprotseq(MaxCalls, RPCRT4_strdupA(szps), &ps);
if (status != RPC_S_OK)
return status;
- return RPCRT4_use_protseq(ps, (const char *)Endpoint);
+ return RPCRT4_use_protseq(ps, szep);
}
/***********************************************************************
{
RpcServerProtseq* ps;
RPC_STATUS status;
- LPSTR ProtseqA;
LPSTR EndpointA;
TRACE("(%s,%u,%s,%p,{%u,%u,%u})\n", debugstr_w( Protseq ), MaxCalls,
debugstr_w( Endpoint ), SecurityDescriptor,
lpPolicy->Length, lpPolicy->EndpointFlags, lpPolicy->NICFlags );
- ProtseqA = RPCRT4_strdupWtoA(Protseq);
- status = RPCRT4_get_or_create_serverprotseq(MaxCalls, ProtseqA, &ps);
- RPCRT4_strfree(ProtseqA);
+ status = RPCRT4_get_or_create_serverprotseq(MaxCalls, RPCRT4_strdupWtoA(Protseq), &ps);
if (status != RPC_S_OK)
return status;
*/
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);
-
- status = RPCRT4_get_or_create_serverprotseq(MaxCalls, (const char *)Protseq, &ps);
- if (status != RPC_S_OK)
- return status;
-
- return RPCRT4_use_protseq(ps, NULL);
+ return RpcServerUseProtseqEpA(Protseq, MaxCalls, NULL, 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);
-
- 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);
+ return RpcServerUseProtseqEpW(Protseq, MaxCalls, NULL, SecurityDescriptor);
}
/***********************************************************************
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 )
{
- PRPC_SERVER_INTERFACE If = IfSpec;
+ PRPC_SERVER_INTERFACE If = (PRPC_SERVER_INTERFACE)IfSpec;
RpcServerInterface* sif;
unsigned int i;
*/
RPC_STATUS WINAPI RpcServerUnregisterIf( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, UINT WaitForCallsToComplete )
{
- PRPC_SERVER_INTERFACE If = IfSpec;
+ PRPC_SERVER_INTERFACE If = (PRPC_SERVER_INTERFACE)IfSpec;
HANDLE event = NULL;
BOOL found = FALSE;
BOOL completed = TRUE;
* new connection was established */
int (*wait_for_new_connection)(RpcServerProtseq *protseq, unsigned int count, void *wait_array);
/* opens the endpoint and optionally begins listening */
- RPC_STATUS (*open_endpoint)(RpcServerProtseq *protseq, const char *endpoint);
+ RPC_STATUS (*open_endpoint)(RpcServerProtseq *protseq, LPSTR endpoint);
};
typedef struct _RpcServerInterface
void RPCRT4_new_client(RpcConnection* conn);
const struct protseq_ops *rpcrt4_get_protseq_ops(const char *protseq);
-void RPCRT4_destroy_all_protseqs(void);
-
#endif /* __WINE_RPC_SERVER_H */
# ifndef EAGAIN
# define EAGAIN WSAEWOULDBLOCK
# endif
-# undef errno
-# define errno WSAGetLastError()
#else
# include <errno.h>
# ifdef HAVE_UNISTD_H
# ifdef HAVE_SYS_POLL_H
# include <sys/poll.h>
# endif
-# ifdef HAVE_SYS_FILIO_H
-# include <sys/filio.h>
-# endif
-# ifdef HAVE_SYS_IOCTL_H
-# include <sys/ioctl.h>
-# endif
# define closesocket close
-# define ioctlsocket ioctl
#endif /* defined(__MINGW32__) || defined (_MSC_VER) */
+#include <winsock2.h>
+#include <ws2tcpip.h>
+
#include "windef.h"
#include "winbase.h"
#include "winnls.h"
#include "winerror.h"
-#include "wininet.h"
#include "winternl.h"
#include "wine/unicode.h"
#include "wine/debug.h"
#include "rpc_binding.h"
-#include "rpc_assoc.h"
#include "rpc_message.h"
#include "rpc_server.h"
#include "epm_towers.h"
+#include "unix_func.h"
+
#ifndef SOL_TCP
# define SOL_TCP IPPROTO_TCP
#endif
-#define DEFAULT_NCACN_HTTP_TIMEOUT (60 * 1000)
-
WINE_DEFAULT_DEBUG_CHANNEL(rpc);
static RPC_STATUS RPCRT4_SpawnConnection(RpcConnection** Connection, RpcConnection* OldConnection);
return r;
}
-static RPC_STATUS rpcrt4_protseq_ncalrpc_open_endpoint(RpcServerProtseq* protseq, const char *endpoint)
+static RPC_STATUS rpcrt4_protseq_ncalrpc_open_endpoint(RpcServerProtseq* protseq, LPSTR endpoint)
{
static const char prefix[] = "\\\\.\\pipe\\lrpc\\";
RPC_STATUS r;
LPSTR pname;
RpcConnection *Connection;
- char generated_endpoint[22];
-
- if (!endpoint)
- {
- static LONG lrpc_nameless_id;
- DWORD process_id = GetCurrentProcessId();
- ULONG id = InterlockedIncrement(&lrpc_nameless_id);
- snprintf(generated_endpoint, sizeof(generated_endpoint),
- "LRPC%08x.%08x", process_id, id);
- endpoint = generated_endpoint;
- }
r = RPCRT4_CreateConnection(&Connection, TRUE, protseq->Protseq, NULL,
endpoint, NULL, NULL, NULL);
return r;
}
-static RPC_STATUS rpcrt4_protseq_ncacn_np_open_endpoint(RpcServerProtseq *protseq, const char *endpoint)
+static RPC_STATUS rpcrt4_protseq_ncacn_np_open_endpoint(RpcServerProtseq *protseq, LPSTR endpoint)
{
static const char prefix[] = "\\\\.";
RPC_STATUS r;
LPSTR pname;
RpcConnection *Connection;
- char generated_endpoint[21];
-
- if (!endpoint)
- {
- static LONG np_nameless_id;
- DWORD process_id = GetCurrentProcessId();
- ULONG id = InterlockedExchangeAdd(&np_nameless_id, 1 );
- snprintf(generated_endpoint, sizeof(generated_endpoint),
- "\\\\pipe\\\\%08x.%03x", process_id, id);
- endpoint = generated_endpoint;
- }
r = RPCRT4_CreateConnection(&Connection, TRUE, protseq->Protseq, NULL,
endpoint, NULL, NULL, NULL);
new_npc->ovl[0] = old_npc->ovl[0];
new_npc->ovl[1] = old_npc->ovl[1];
old_npc->pipe = 0;
- memset(&old_npc->ovl[0], 0, sizeof(old_npc->ovl));
+ memset(&old_npc->ovl, 0, sizeof(old_npc->ovl));
old_npc->listening = FALSE;
}
ret = ReadFile(npc->pipe, buf, bytes_left, &bytes_read, &npc->ovl[0]);
if ((!ret || !bytes_read) && (GetLastError() != ERROR_IO_PENDING))
break;
+
ret = GetOverlappedResult(npc->pipe, &npc->ovl[0], &bytes_read, TRUE);
- if (!ret && GetLastError() == ERROR_MORE_DATA)
- ret = TRUE;
- if (!ret || !bytes_read)
+ if (!ret && (GetLastError() != ERROR_MORE_DATA))
break;
+
bytes_left -= bytes_read;
buf += bytes_read;
}
ret = WriteFile(npc->pipe, buf, bytes_left, &bytes_written, &npc->ovl[1]);
if ((!ret || !bytes_written) && (GetLastError() != ERROR_IO_PENDING))
break;
+
ret = GetOverlappedResult(npc->pipe, &npc->ovl[1], &bytes_written, TRUE);
- if (!ret && GetLastError() == ERROR_MORE_DATA)
- ret = TRUE;
- if (!ret || !bytes_written)
+ if (!ret && (GetLastError() != ERROR_MORE_DATA))
break;
+
bytes_left -= bytes_written;
buf += bytes_written;
}
/**** ncacn_ip_tcp support ****/
-static size_t rpcrt4_ip_tcp_get_top_of_tower(unsigned char *tower_data,
- const char *networkaddr,
- unsigned char tcp_protid,
- const char *endpoint)
-{
- twr_tcp_floor_t *tcp_floor;
- twr_ipv4_floor_t *ipv4_floor;
- struct addrinfo *ai;
- struct addrinfo hints;
- int ret;
- size_t size = sizeof(*tcp_floor) + sizeof(*ipv4_floor);
-
- TRACE("(%p, %s, %s)\n", tower_data, networkaddr, endpoint);
-
- if (!tower_data)
- return size;
-
- tcp_floor = (twr_tcp_floor_t *)tower_data;
- tower_data += sizeof(*tcp_floor);
-
- ipv4_floor = (twr_ipv4_floor_t *)tower_data;
-
- tcp_floor->count_lhs = sizeof(tcp_floor->protid);
- tcp_floor->protid = tcp_protid;
- tcp_floor->count_rhs = sizeof(tcp_floor->port);
-
- ipv4_floor->count_lhs = sizeof(ipv4_floor->protid);
- ipv4_floor->protid = EPM_PROTOCOL_IP;
- ipv4_floor->count_rhs = sizeof(ipv4_floor->ipv4addr);
-
- hints.ai_flags = AI_NUMERICHOST;
- /* FIXME: only support IPv4 at the moment. how is IPv6 represented by the EPM? */
- hints.ai_family = PF_INET;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = IPPROTO_TCP;
- hints.ai_addrlen = 0;
- hints.ai_addr = NULL;
- hints.ai_canonname = NULL;
- hints.ai_next = NULL;
-
- ret = getaddrinfo(networkaddr, endpoint, &hints, &ai);
- if (ret)
- {
- ret = getaddrinfo("0.0.0.0", endpoint, &hints, &ai);
- if (ret)
- {
- ERR("getaddrinfo failed: %s\n", gai_strerror(ret));
- return 0;
- }
- }
-
- if (ai->ai_family == PF_INET)
- {
- const struct sockaddr_in *sin = (const struct sockaddr_in *)ai->ai_addr;
- tcp_floor->port = sin->sin_port;
- ipv4_floor->ipv4addr = sin->sin_addr.s_addr;
- }
- else
- {
- ERR("unexpected protocol family %d\n", ai->ai_family);
- return 0;
- }
-
- freeaddrinfo(ai);
-
- return size;
-}
-
-static RPC_STATUS rpcrt4_ip_tcp_parse_top_of_tower(const unsigned char *tower_data,
- size_t tower_size,
- char **networkaddr,
- unsigned char tcp_protid,
- char **endpoint)
-{
- const twr_tcp_floor_t *tcp_floor = (const twr_tcp_floor_t *)tower_data;
- const twr_ipv4_floor_t *ipv4_floor;
- struct in_addr in_addr;
-
- TRACE("(%p, %d, %p, %p)\n", tower_data, (int)tower_size, networkaddr, endpoint);
-
- if (tower_size < sizeof(*tcp_floor))
- return EPT_S_NOT_REGISTERED;
-
- tower_data += sizeof(*tcp_floor);
- tower_size -= sizeof(*tcp_floor);
-
- if (tower_size < sizeof(*ipv4_floor))
- return EPT_S_NOT_REGISTERED;
-
- ipv4_floor = (const twr_ipv4_floor_t *)tower_data;
-
- if ((tcp_floor->count_lhs != sizeof(tcp_floor->protid)) ||
- (tcp_floor->protid != tcp_protid) ||
- (tcp_floor->count_rhs != sizeof(tcp_floor->port)) ||
- (ipv4_floor->count_lhs != sizeof(ipv4_floor->protid)) ||
- (ipv4_floor->protid != EPM_PROTOCOL_IP) ||
- (ipv4_floor->count_rhs != sizeof(ipv4_floor->ipv4addr)))
- return EPT_S_NOT_REGISTERED;
-
- if (endpoint)
- {
- *endpoint = I_RpcAllocate(6 /* sizeof("65535") + 1 */);
- if (!*endpoint)
- return RPC_S_OUT_OF_RESOURCES;
- sprintf(*endpoint, "%u", ntohs(tcp_floor->port));
- }
-
- if (networkaddr)
- {
- *networkaddr = I_RpcAllocate(INET_ADDRSTRLEN);
- if (!*networkaddr)
- {
- if (endpoint)
- {
- I_RpcFree(*endpoint);
- *endpoint = NULL;
- }
- return RPC_S_OUT_OF_RESOURCES;
- }
- in_addr.s_addr = ipv4_floor->ipv4addr;
- if (!inet_ntop(AF_INET, &in_addr, *networkaddr, INET_ADDRSTRLEN))
- {
- ERR("inet_ntop: %s\n", strerror(errno));
- I_RpcFree(*networkaddr);
- *networkaddr = NULL;
- if (endpoint)
- {
- I_RpcFree(*endpoint);
- *endpoint = NULL;
- }
- return EPT_S_NOT_REGISTERED;
- }
- }
-
- return RPC_S_OK;
-}
+#ifdef HAVE_SOCKETPAIR
typedef struct _RpcConnection_tcp
{
RpcConnection common;
int sock;
-#ifdef HAVE_SOCKETPAIR
int cancel_fds[2];
-#else
- HANDLE sock_event;
- HANDLE cancel_event;
-#endif
} RpcConnection_tcp;
-#ifdef HAVE_SOCKETPAIR
-
-static BOOL rpcrt4_sock_wait_init(RpcConnection_tcp *tcpc)
-{
- if (socketpair(PF_UNIX, SOCK_STREAM, 0, tcpc->cancel_fds) < 0)
- {
- ERR("socketpair() failed: %s\n", strerror(errno));
- return FALSE;
- }
- return TRUE;
-}
-
-static BOOL rpcrt4_sock_wait_for_recv(RpcConnection_tcp *tcpc)
-{
- struct pollfd pfds[2];
- pfds[0].fd = tcpc->sock;
- pfds[0].events = POLLIN;
- pfds[1].fd = tcpc->cancel_fds[0];
- pfds[1].events = POLLIN;
- if (poll(pfds, 2, -1 /* infinite */) == -1 && errno != EINTR)
- {
- ERR("poll() failed: %s\n", strerror(errno));
- return FALSE;
- }
- if (pfds[1].revents & POLLIN) /* canceled */
- {
- char dummy;
- read(pfds[1].fd, &dummy, sizeof(dummy));
- return FALSE;
- }
- return TRUE;
-}
-
-static BOOL rpcrt4_sock_wait_for_send(RpcConnection_tcp *tcpc)
-{
- struct pollfd pfd;
- pfd.fd = tcpc->sock;
- pfd.events = POLLOUT;
- if (poll(&pfd, 1, -1 /* infinite */) == -1 && errno != EINTR)
- {
- ERR("poll() failed: %s\n", strerror(errno));
- return FALSE;
- }
- return TRUE;
-}
-
-static void rpcrt4_sock_wait_cancel(RpcConnection_tcp *tcpc)
-{
- char dummy = 1;
-
- write(tcpc->cancel_fds[1], &dummy, 1);
-}
-
-static void rpcrt4_sock_wait_destroy(RpcConnection_tcp *tcpc)
-{
- close(tcpc->cancel_fds[0]);
- close(tcpc->cancel_fds[1]);
-}
-
-#else /* HAVE_SOCKETPAIR */
-
-static BOOL rpcrt4_sock_wait_init(RpcConnection_tcp *tcpc)
-{
- static BOOL wsa_inited;
- if (!wsa_inited)
- {
- WSADATA wsadata;
- WSAStartup(MAKEWORD(2, 2), &wsadata);
- /* Note: WSAStartup can be called more than once so we don't bother with
- * making accesses to wsa_inited thread-safe */
- wsa_inited = TRUE;
- }
- tcpc->sock_event = CreateEventW(NULL, FALSE, FALSE, NULL);
- tcpc->cancel_event = CreateEventW(NULL, FALSE, FALSE, NULL);
- if (!tcpc->sock_event || !tcpc->cancel_event)
- {
- ERR("event creation failed\n");
- if (tcpc->sock_event) CloseHandle(tcpc->sock_event);
- return FALSE;
- }
- return TRUE;
-}
-
-static BOOL rpcrt4_sock_wait_for_recv(RpcConnection_tcp *tcpc)
-{
- HANDLE wait_handles[2];
- DWORD res;
- if (WSAEventSelect(tcpc->sock, tcpc->sock_event, FD_READ | FD_CLOSE) == SOCKET_ERROR)
- {
- ERR("WSAEventSelect() failed with error %d\n", WSAGetLastError());
- return FALSE;
- }
- wait_handles[0] = tcpc->sock_event;
- wait_handles[1] = tcpc->cancel_event;
- res = WaitForMultipleObjects(2, wait_handles, FALSE, INFINITE);
- switch (res)
- {
- case WAIT_OBJECT_0:
- return TRUE;
- case WAIT_OBJECT_0 + 1:
- return FALSE;
- default:
- ERR("WaitForMultipleObjects() failed with error %d\n", GetLastError());
- return FALSE;
- }
-}
-
-static BOOL rpcrt4_sock_wait_for_send(RpcConnection_tcp *tcpc)
-{
- DWORD res;
- if (WSAEventSelect(tcpc->sock, tcpc->sock_event, FD_WRITE | FD_CLOSE) == SOCKET_ERROR)
- {
- ERR("WSAEventSelect() failed with error %d\n", WSAGetLastError());
- return FALSE;
- }
- res = WaitForSingleObject(tcpc->sock_event, INFINITE);
- switch (res)
- {
- case WAIT_OBJECT_0:
- return TRUE;
- default:
- ERR("WaitForMultipleObjects() failed with error %d\n", GetLastError());
- return FALSE;
- }
-}
-
-static void rpcrt4_sock_wait_cancel(RpcConnection_tcp *tcpc)
-{
- SetEvent(tcpc->cancel_event);
-}
-
-static void rpcrt4_sock_wait_destroy(RpcConnection_tcp *tcpc)
-{
- CloseHandle(tcpc->sock_event);
- CloseHandle(tcpc->cancel_event);
-}
-
-#endif
-
static RpcConnection *rpcrt4_conn_tcp_alloc(void)
{
RpcConnection_tcp *tcpc;
if (tcpc == NULL)
return NULL;
tcpc->sock = -1;
- if (!rpcrt4_sock_wait_init(tcpc))
+ if (socketpair(PF_UNIX, SOCK_STREAM, 0, tcpc->cancel_fds) < 0)
{
+ ERR("socketpair() failed: %s\n", strerror(errno));
HeapFree(GetProcessHeap(), 0, tcpc);
return NULL;
}
for (ai_cur = ai; ai_cur; ai_cur = ai_cur->ai_next)
{
int val;
- u_long nonblocking;
-
- if (ai_cur->ai_family != AF_INET && ai_cur->ai_family != AF_INET6)
- {
- TRACE("skipping non-IP/IPv6 address family\n");
- continue;
- }
if (TRACE_ON(rpc))
{
/* RPC depends on having minimal latency so disable the Nagle algorithm */
val = 1;
- setsockopt(sock, SOL_TCP, TCP_NODELAY, (char *)&val, sizeof(val));
- nonblocking = 1;
- ioctlsocket(sock, FIONBIO, &nonblocking);
+ setsockopt(sock, SOL_TCP, TCP_NODELAY, &val, sizeof(val));
+ fcntl(sock, F_SETFL, O_NONBLOCK); /* make socket nonblocking */
tcpc->sock = sock;
return RPC_S_SERVER_UNAVAILABLE;
}
-static RPC_STATUS rpcrt4_protseq_ncacn_ip_tcp_open_endpoint(RpcServerProtseq *protseq, const char *endpoint)
+static RPC_STATUS rpcrt4_protseq_ncacn_ip_tcp_open_endpoint(RpcServerProtseq *protseq, LPSTR endpoint)
{
RPC_STATUS status = RPC_S_CANT_CREATE_ENDPOINT;
int sock;
hints.ai_canonname = NULL;
hints.ai_next = NULL;
- ret = getaddrinfo(NULL, endpoint ? endpoint : "0", &hints, &ai);
+ ret = getaddrinfo(NULL, endpoint, &hints, &ai);
if (ret)
{
ERR("getaddrinfo for port %s failed: %s\n", endpoint,
{
RpcConnection_tcp *tcpc;
RPC_STATUS create_status;
- struct sockaddr_storage sa;
- socklen_t sa_len;
- char service[NI_MAXSERV];
- u_long nonblocking;
-
- if (ai_cur->ai_family != AF_INET && ai_cur->ai_family != AF_INET6)
- {
- TRACE("skipping non-IP/IPv6 address family\n");
- continue;
- }
if (TRACE_ON(rpc))
{
char host[256];
+ char service[256];
getnameinfo(ai_cur->ai_addr, ai_cur->ai_addrlen,
host, sizeof(host), service, sizeof(service),
NI_NUMERICHOST | NI_NUMERICSERV);
status = RPC_S_CANT_CREATE_ENDPOINT;
continue;
}
-
- sa_len = sizeof(sa);
- if (getsockname(sock, (struct sockaddr *)&sa, &sa_len))
- {
- WARN("getsockname() failed: %s\n", strerror(errno));
- status = RPC_S_CANT_CREATE_ENDPOINT;
- continue;
- }
-
- ret = getnameinfo((struct sockaddr *)&sa, sa_len,
- NULL, 0, service, sizeof(service),
- NI_NUMERICSERV);
- if (ret)
- {
- WARN("getnameinfo failed: %s\n", gai_strerror(ret));
- status = RPC_S_CANT_CREATE_ENDPOINT;
- continue;
- }
-
create_status = RPCRT4_CreateConnection((RpcConnection **)&tcpc, TRUE,
protseq->Protseq, NULL,
- service, NULL, NULL, NULL);
+ endpoint, NULL, NULL, NULL);
if (create_status != RPC_S_OK)
{
closesocket(sock);
* race-condition (poll() says it is readable, connection drops,
* and accept() blocks until the next connection comes...)
*/
- nonblocking = 1;
- ret = ioctlsocket(sock, FIONBIO, &nonblocking);
+ ret = fcntl(sock, F_SETFL, O_NONBLOCK);
if (ret < 0)
{
WARN("couldn't make socket non-blocking, error %d\n", ret);
tcpc->common.Next = first_connection;
first_connection = &tcpc->common;
-
- /* since IPv4 and IPv6 share the same port space, we only need one
- * successful bind to listen for both */
- break;
}
freeaddrinfo(ai);
socklen_t addrsize;
RpcConnection_tcp *server = (RpcConnection_tcp*) old_conn;
RpcConnection_tcp *client = (RpcConnection_tcp*) new_conn;
- u_long nonblocking;
addrsize = sizeof(address);
ret = accept(server->sock, (struct sockaddr*) &address, &addrsize);
ERR("Failed to accept a TCP connection: error %d\n", ret);
return RPC_S_OUT_OF_RESOURCES;
}
- nonblocking = 1;
- ioctlsocket(ret, FIONBIO, &nonblocking);
+ /* reset to blocking behaviour */
+ fcntl(ret, F_SETFL, 0);
client->sock = ret;
TRACE("Accepted a new TCP connection\n");
return RPC_S_OK;
}
else
{
- if (!rpcrt4_sock_wait_for_recv(tcpc))
+ struct pollfd pfds[2];
+ pfds[0].fd = tcpc->sock;
+ pfds[0].events = POLLIN;
+ pfds[1].fd = tcpc->cancel_fds[0];
+ pfds[1].events = POLLIN;
+ if (poll(pfds, 2, -1 /* infinite */) == -1 && errno != EINTR)
+ {
+ ERR("poll() failed: %s\n", strerror(errno));
+ return -1;
+ }
+ if (pfds[1].revents & POLLIN) /* canceled */
+ {
+ char dummy;
+ read(pfds[1].fd, &dummy, sizeof(dummy));
return -1;
+ }
}
} while (bytes_read != count);
TRACE("%d %p %u -> %d\n", tcpc->sock, buffer, count, bytes_read);
return -1;
else
{
- if (!rpcrt4_sock_wait_for_send(tcpc))
+ struct pollfd pfd;
+ pfd.fd = tcpc->sock;
+ pfd.events = POLLOUT;
+ if (poll(&pfd, 1, -1 /* infinite */) == -1 && errno != EINTR)
+ {
+ ERR("poll() failed: %s\n", strerror(errno));
return -1;
+ }
}
} while (bytes_written != count);
TRACE("%d %p %u -> %d\n", tcpc->sock, buffer, count, bytes_written);
if (tcpc->sock != -1)
closesocket(tcpc->sock);
tcpc->sock = -1;
- rpcrt4_sock_wait_destroy(tcpc);
+ close(tcpc->cancel_fds[0]);
+ close(tcpc->cancel_fds[1]);
return 0;
}
static void rpcrt4_conn_tcp_cancel_call(RpcConnection *Connection)
{
RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;
+ char dummy = 1;
+
TRACE("%p\n", Connection);
- rpcrt4_sock_wait_cancel(tcpc);
+
+ write(tcpc->cancel_fds[1], &dummy, 1);
}
static int rpcrt4_conn_tcp_wait_for_incoming_data(RpcConnection *Connection)
{
RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;
+ struct pollfd pfds[2];
TRACE("%p\n", Connection);
- if (!rpcrt4_sock_wait_for_recv(tcpc))
- return -1;
+ pfds[0].fd = tcpc->sock;
+ pfds[0].events = POLLIN;
+ pfds[1].fd = tcpc->cancel_fds[0];
+ pfds[1].events = POLLIN;
+ if (poll(pfds, 2, -1 /* infinite */) == -1 && errno != EINTR)
+ {
+ ERR("poll() failed: %s\n", strerror(errno));
+ return -1;
+ }
+ if (pfds[1].revents & POLLIN) /* canceled */
+ {
+ char dummy;
+ read(pfds[1].fd, &dummy, sizeof(dummy));
+ return -1;
+ }
+
return 0;
}
const char *networkaddr,
const char *endpoint)
{
- return rpcrt4_ip_tcp_get_top_of_tower(tower_data, networkaddr,
- EPM_PROTOCOL_TCP, endpoint);
-}
+ twr_tcp_floor_t *tcp_floor;
+ twr_ipv4_floor_t *ipv4_floor;
+ struct addrinfo *ai;
+ struct addrinfo hints;
+ int ret;
+ size_t size = sizeof(*tcp_floor) + sizeof(*ipv4_floor);
-#ifdef HAVE_SOCKETPAIR
+ TRACE("(%p, %s, %s)\n", tower_data, networkaddr, endpoint);
+
+ if (!tower_data)
+ return size;
+
+ tcp_floor = (twr_tcp_floor_t *)tower_data;
+ tower_data += sizeof(*tcp_floor);
+
+ ipv4_floor = (twr_ipv4_floor_t *)tower_data;
+
+ tcp_floor->count_lhs = sizeof(tcp_floor->protid);
+ tcp_floor->protid = EPM_PROTOCOL_TCP;
+ tcp_floor->count_rhs = sizeof(tcp_floor->port);
+
+ ipv4_floor->count_lhs = sizeof(ipv4_floor->protid);
+ ipv4_floor->protid = EPM_PROTOCOL_IP;
+ ipv4_floor->count_rhs = sizeof(ipv4_floor->ipv4addr);
+
+ hints.ai_flags = AI_NUMERICHOST;
+ /* FIXME: only support IPv4 at the moment. how is IPv6 represented by the EPM? */
+ hints.ai_family = PF_INET;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+ hints.ai_addrlen = 0;
+ hints.ai_addr = NULL;
+ hints.ai_canonname = NULL;
+ hints.ai_next = NULL;
+
+ ret = getaddrinfo(networkaddr, endpoint, &hints, &ai);
+ if (ret)
+ {
+ ret = getaddrinfo("0.0.0.0", endpoint, &hints, &ai);
+ if (ret)
+ {
+ ERR("getaddrinfo failed: %s\n", gai_strerror(ret));
+ return 0;
+ }
+ }
+
+ if (ai->ai_family == PF_INET)
+ {
+ const struct sockaddr_in *sin = (const struct sockaddr_in *)ai->ai_addr;
+ tcp_floor->port = sin->sin_port;
+ ipv4_floor->ipv4addr = sin->sin_addr.s_addr;
+ }
+ else
+ {
+ ERR("unexpected protocol family %d\n", ai->ai_family);
+ return 0;
+ }
+
+ freeaddrinfo(ai);
+
+ return size;
+}
+
+static RPC_STATUS rpcrt4_ncacn_ip_tcp_parse_top_of_tower(const unsigned char *tower_data,
+ size_t tower_size,
+ char **networkaddr,
+ char **endpoint)
+{
+ const twr_tcp_floor_t *tcp_floor = (const twr_tcp_floor_t *)tower_data;
+ const twr_ipv4_floor_t *ipv4_floor;
+ struct in_addr in_addr;
+
+ TRACE("(%p, %d, %p, %p)\n", tower_data, (int)tower_size, networkaddr, endpoint);
+
+ if (tower_size < sizeof(*tcp_floor))
+ return EPT_S_NOT_REGISTERED;
+
+ tower_data += sizeof(*tcp_floor);
+ tower_size -= sizeof(*tcp_floor);
+
+ if (tower_size < sizeof(*ipv4_floor))
+ return EPT_S_NOT_REGISTERED;
+
+ ipv4_floor = (const twr_ipv4_floor_t *)tower_data;
+
+ if ((tcp_floor->count_lhs != sizeof(tcp_floor->protid)) ||
+ (tcp_floor->protid != EPM_PROTOCOL_TCP) ||
+ (tcp_floor->count_rhs != sizeof(tcp_floor->port)) ||
+ (ipv4_floor->count_lhs != sizeof(ipv4_floor->protid)) ||
+ (ipv4_floor->protid != EPM_PROTOCOL_IP) ||
+ (ipv4_floor->count_rhs != sizeof(ipv4_floor->ipv4addr)))
+ return EPT_S_NOT_REGISTERED;
+
+ if (endpoint)
+ {
+ *endpoint = I_RpcAllocate(6 /* sizeof("65535") + 1 */);
+ if (!*endpoint)
+ return RPC_S_OUT_OF_RESOURCES;
+ sprintf(*endpoint, "%u", ntohs(tcp_floor->port));
+ }
+
+ if (networkaddr)
+ {
+ *networkaddr = I_RpcAllocate(INET_ADDRSTRLEN);
+ if (!*networkaddr)
+ {
+ if (endpoint)
+ {
+ I_RpcFree(*endpoint);
+ *endpoint = NULL;
+ }
+ return RPC_S_OUT_OF_RESOURCES;
+ }
+ in_addr.s_addr = ipv4_floor->ipv4addr;
+ if (!inet_ntop(AF_INET, &in_addr, *networkaddr, INET_ADDRSTRLEN))
+ {
+ ERR("inet_ntop: %s\n", strerror(errno));
+ I_RpcFree(*networkaddr);
+ *networkaddr = NULL;
+ if (endpoint)
+ {
+ I_RpcFree(*endpoint);
+ *endpoint = NULL;
+ }
+ return EPT_S_NOT_REGISTERED;
+ }
+ }
+
+ return RPC_S_OK;
+}
typedef struct _RpcServerProtseq_sock
{
return 1;
}
-#else /* HAVE_SOCKETPAIR */
-
-typedef struct _RpcServerProtseq_sock
-{
- RpcServerProtseq common;
- HANDLE mgr_event;
-} RpcServerProtseq_sock;
+#endif /* HAVE_SOCKETPAIR */
-static RpcServerProtseq *rpcrt4_protseq_sock_alloc(void)
-{
- RpcServerProtseq_sock *ps = HeapAlloc(GetProcessHeap(), 0, sizeof(*ps));
- if (ps)
- {
- static BOOL wsa_inited;
- if (!wsa_inited)
- {
- WSADATA wsadata;
- WSAStartup(MAKEWORD(2, 2), &wsadata);
- /* Note: WSAStartup can be called more than once so we don't bother with
- * making accesses to wsa_inited thread-safe */
- wsa_inited = TRUE;
- }
- ps->mgr_event = CreateEventW(NULL, FALSE, FALSE, NULL);
- }
- return &ps->common;
-}
+static const struct connection_ops conn_protseq_list[] = {
+ { "ncacn_np",
+ { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_SMB },
+ rpcrt4_conn_np_alloc,
+ rpcrt4_ncacn_np_open,
+ rpcrt4_ncacn_np_handoff,
+ rpcrt4_conn_np_read,
+ rpcrt4_conn_np_write,
+ rpcrt4_conn_np_close,
+ rpcrt4_conn_np_cancel_call,
+ rpcrt4_conn_np_wait_for_incoming_data,
+ rpcrt4_ncacn_np_get_top_of_tower,
+ rpcrt4_ncacn_np_parse_top_of_tower,
+ },
+ { "ncalrpc",
+ { EPM_PROTOCOL_NCALRPC, EPM_PROTOCOL_PIPE },
+ rpcrt4_conn_np_alloc,
+ rpcrt4_ncalrpc_open,
+ rpcrt4_ncalrpc_handoff,
+ rpcrt4_conn_np_read,
+ rpcrt4_conn_np_write,
+ rpcrt4_conn_np_close,
+ rpcrt4_conn_np_cancel_call,
+ rpcrt4_conn_np_wait_for_incoming_data,
+ rpcrt4_ncalrpc_get_top_of_tower,
+ rpcrt4_ncalrpc_parse_top_of_tower,
+ },
+#ifdef HAVE_SOCKETPAIR
+ { "ncacn_ip_tcp",
+ { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_TCP },
+ rpcrt4_conn_tcp_alloc,
+ rpcrt4_ncacn_ip_tcp_open,
+ rpcrt4_conn_tcp_handoff,
+ rpcrt4_conn_tcp_read,
+ rpcrt4_conn_tcp_write,
+ rpcrt4_conn_tcp_close,
+ rpcrt4_conn_tcp_cancel_call,
+ rpcrt4_conn_tcp_wait_for_incoming_data,
+ rpcrt4_ncacn_ip_tcp_get_top_of_tower,
+ rpcrt4_ncacn_ip_tcp_parse_top_of_tower,
+ }
+#endif
+};
-static void rpcrt4_protseq_sock_signal_state_changed(RpcServerProtseq *protseq)
-{
- RpcServerProtseq_sock *sockps = CONTAINING_RECORD(protseq, RpcServerProtseq_sock, common);
- SetEvent(sockps->mgr_event);
-}
-static void *rpcrt4_protseq_sock_get_wait_array(RpcServerProtseq *protseq, void *prev_array, unsigned int *count)
+static const struct protseq_ops protseq_list[] =
{
- HANDLE *objs = prev_array;
- RpcConnection_tcp *conn;
- RpcServerProtseq_sock *sockps = CONTAINING_RECORD(protseq, RpcServerProtseq_sock, common);
-
- EnterCriticalSection(&protseq->cs);
-
- /* open and count connections */
- *count = 1;
- conn = CONTAINING_RECORD(protseq->conn, RpcConnection_tcp, common);
- while (conn)
{
- if (conn->sock != -1)
- (*count)++;
- conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_tcp, common);
- }
-
- /* make array of connections */
- if (objs)
- objs = HeapReAlloc(GetProcessHeap(), 0, objs, *count*sizeof(HANDLE));
- else
- objs = HeapAlloc(GetProcessHeap(), 0, *count*sizeof(HANDLE));
- if (!objs)
+ "ncacn_np",
+ rpcrt4_protseq_np_alloc,
+ rpcrt4_protseq_np_signal_state_changed,
+ rpcrt4_protseq_np_get_wait_array,
+ rpcrt4_protseq_np_free_wait_array,
+ rpcrt4_protseq_np_wait_for_new_connection,
+ rpcrt4_protseq_ncacn_np_open_endpoint,
+ },
{
- ERR("couldn't allocate objs\n");
- LeaveCriticalSection(&protseq->cs);
- return NULL;
- }
-
- objs[0] = sockps->mgr_event;
- *count = 1;
- conn = CONTAINING_RECORD(protseq->conn, RpcConnection_tcp, common);
- while (conn)
- {
- if (conn->sock != -1)
- {
- int res = WSAEventSelect(conn->sock, conn->sock_event, FD_ACCEPT);
- if (res == SOCKET_ERROR)
- ERR("WSAEventSelect() failed with error %d\n", WSAGetLastError());
- else
- {
- objs[*count] = conn->sock_event;
- (*count)++;
- }
- }
- conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_tcp, common);
- }
- LeaveCriticalSection(&protseq->cs);
- return objs;
-}
-
-static void rpcrt4_protseq_sock_free_wait_array(RpcServerProtseq *protseq, void *array)
-{
- HeapFree(GetProcessHeap(), 0, array);
-}
-
-static int rpcrt4_protseq_sock_wait_for_new_connection(RpcServerProtseq *protseq, unsigned int count, void *wait_array)
-{
- HANDLE b_handle;
- HANDLE *objs = wait_array;
- DWORD res;
- RpcConnection *cconn;
- RpcConnection_tcp *conn;
-
- if (!objs)
- return -1;
-
- do
- {
- /* an alertable wait isn't strictly necessary, but due to our
- * overlapped I/O implementation in Wine we need to free some memory
- * by the file user APC being called, even if no completion routine was
- * specified at the time of starting the async operation */
- res = WaitForMultipleObjectsEx(count, objs, FALSE, INFINITE, TRUE);
- } while (res == WAIT_IO_COMPLETION);
-
- if (res == WAIT_OBJECT_0)
- return 0;
- else if (res == WAIT_FAILED)
- {
- ERR("wait failed with error %d\n", GetLastError());
- return -1;
- }
- else
- {
- b_handle = objs[res - WAIT_OBJECT_0];
- /* find which connection got a RPC */
- EnterCriticalSection(&protseq->cs);
- conn = CONTAINING_RECORD(protseq->conn, RpcConnection_tcp, common);
- while (conn)
- {
- if (b_handle == conn->sock_event) break;
- conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_tcp, common);
- }
- cconn = NULL;
- if (conn)
- RPCRT4_SpawnConnection(&cconn, &conn->common);
- else
- ERR("failed to locate connection for handle %p\n", b_handle);
- LeaveCriticalSection(&protseq->cs);
- if (cconn)
- {
- RPCRT4_new_client(cconn);
- return 1;
- }
- else return -1;
- }
-}
-
-#endif /* HAVE_SOCKETPAIR */
-
-static RPC_STATUS rpcrt4_ncacn_ip_tcp_parse_top_of_tower(const unsigned char *tower_data,
- size_t tower_size,
- char **networkaddr,
- char **endpoint)
-{
- return rpcrt4_ip_tcp_parse_top_of_tower(tower_data, tower_size,
- networkaddr, EPM_PROTOCOL_TCP,
- endpoint);
-}
-
-/**** ncacn_http support ****/
-#if 0
-/* 60 seconds is the period native uses */
-#define HTTP_IDLE_TIME 60000
-
-/* reference counted to avoid a race between a cancelled call's connection
- * being destroyed and the asynchronous InternetReadFileEx call being
- * completed */
-typedef struct _RpcHttpAsyncData
-{
- LONG refs;
- HANDLE completion_event;
- INTERNET_BUFFERSA inet_buffers;
- void *destination_buffer; /* the address that inet_buffers.lpvBuffer will be
- * copied into when the call completes */
- CRITICAL_SECTION cs;
-} RpcHttpAsyncData;
-
-static ULONG RpcHttpAsyncData_AddRef(RpcHttpAsyncData *data)
-{
- return InterlockedIncrement(&data->refs);
-}
-
-static ULONG RpcHttpAsyncData_Release(RpcHttpAsyncData *data)
-{
- ULONG refs = InterlockedDecrement(&data->refs);
- if (!refs)
- {
- TRACE("destroying async data %p\n", data);
- CloseHandle(data->completion_event);
- HeapFree(GetProcessHeap(), 0, data->inet_buffers.lpvBuffer);
- DeleteCriticalSection(&data->cs);
- HeapFree(GetProcessHeap(), 0, data);
- }
- return refs;
-}
-
-typedef struct _RpcConnection_http
-{
- RpcConnection common;
- HINTERNET app_info;
- HINTERNET session;
- HINTERNET in_request;
- HINTERNET out_request;
- HANDLE timer_cancelled;
- HANDLE cancel_event;
- DWORD last_sent_time;
- ULONG bytes_received;
- ULONG flow_control_mark; /* send a control packet to the server when this many bytes received */
- ULONG flow_control_increment; /* number of bytes to increment flow_control_mark by */
- UUID connection_uuid;
- UUID in_pipe_uuid;
- UUID out_pipe_uuid;
- RpcHttpAsyncData *async_data;
-} RpcConnection_http;
-
-static RpcConnection *rpcrt4_ncacn_http_alloc(void)
-{
- RpcConnection_http *httpc;
- httpc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*httpc));
- if (!httpc) return NULL;
- httpc->async_data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcHttpAsyncData));
- if (!httpc->async_data)
- {
- HeapFree(GetProcessHeap(), 0, httpc);
- return NULL;
- }
- TRACE("async data = %p\n", httpc->async_data);
- httpc->cancel_event = CreateEventW(NULL, FALSE, FALSE, NULL);
- httpc->async_data->refs = 1;
- httpc->async_data->inet_buffers.dwStructSize = sizeof(INTERNET_BUFFERSA);
- httpc->async_data->inet_buffers.lpvBuffer = NULL;
- httpc->async_data->destination_buffer = NULL;
- InitializeCriticalSection(&httpc->async_data->cs);
- return &httpc->common;
-}
-
-typedef struct _HttpTimerThreadData
-{
- PVOID timer_param;
- DWORD *last_sent_time;
- HANDLE timer_cancelled;
-} HttpTimerThreadData;
-
-static VOID rpcrt4_http_keep_connection_active_timer_proc(PVOID param, BOOLEAN dummy)
-{
- HINTERNET in_request = param;
- RpcPktHdr *idle_pkt;
-
- idle_pkt = RPCRT4_BuildHttpHeader(NDR_LOCAL_DATA_REPRESENTATION, 0x0001,
- 0, 0);
- if (idle_pkt)
- {
- DWORD bytes_written;
- InternetWriteFile(in_request, idle_pkt, idle_pkt->common.frag_len, &bytes_written);
- RPCRT4_FreeHeader(idle_pkt);
- }
-}
-
-static inline DWORD rpcrt4_http_timer_calc_timeout(DWORD *last_sent_time)
-{
- DWORD cur_time = GetTickCount();
- DWORD cached_last_sent_time = *last_sent_time;
- return HTTP_IDLE_TIME - (cur_time - cached_last_sent_time > HTTP_IDLE_TIME ? 0 : cur_time - cached_last_sent_time);
-}
-
-static DWORD CALLBACK rpcrt4_http_timer_thread(PVOID param)
-{
- HttpTimerThreadData *data_in = param;
- HttpTimerThreadData data;
- DWORD timeout;
-
- data = *data_in;
- HeapFree(GetProcessHeap(), 0, data_in);
-
- for (timeout = HTTP_IDLE_TIME;
- WaitForSingleObject(data.timer_cancelled, timeout) == WAIT_TIMEOUT;
- timeout = rpcrt4_http_timer_calc_timeout(data.last_sent_time))
- {
- /* are we too soon after last send? */
- if (GetTickCount() - HTTP_IDLE_TIME < *data.last_sent_time)
- continue;
- rpcrt4_http_keep_connection_active_timer_proc(data.timer_param, TRUE);
- }
-
- CloseHandle(data.timer_cancelled);
- return 0;
-}
-
-static VOID WINAPI rpcrt4_http_internet_callback(
- HINTERNET hInternet,
- DWORD_PTR dwContext,
- DWORD dwInternetStatus,
- LPVOID lpvStatusInformation,
- DWORD dwStatusInformationLength)
-{
- RpcHttpAsyncData *async_data = (RpcHttpAsyncData *)dwContext;
-
- switch (dwInternetStatus)
- {
- case INTERNET_STATUS_REQUEST_COMPLETE:
- TRACE("INTERNET_STATUS_REQUEST_COMPLETED\n");
- if (async_data)
- {
- if (async_data->inet_buffers.lpvBuffer)
- {
- EnterCriticalSection(&async_data->cs);
- if (async_data->destination_buffer)
- {
- memcpy(async_data->destination_buffer,
- async_data->inet_buffers.lpvBuffer,
- async_data->inet_buffers.dwBufferLength);
- async_data->destination_buffer = NULL;
- }
- LeaveCriticalSection(&async_data->cs);
- }
- HeapFree(GetProcessHeap(), 0, async_data->inet_buffers.lpvBuffer);
- async_data->inet_buffers.lpvBuffer = NULL;
- SetEvent(async_data->completion_event);
- RpcHttpAsyncData_Release(async_data);
- }
- break;
- }
-}
-
-static RPC_STATUS rpcrt4_http_check_response(HINTERNET hor)
-{
- BOOL ret;
- DWORD status_code;
- DWORD size;
- DWORD index;
- WCHAR buf[32];
- WCHAR *status_text = buf;
- TRACE("\n");
-
- index = 0;
- size = sizeof(status_code);
- ret = HttpQueryInfoW(hor, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, &status_code, &size, &index);
- if (!ret)
- return GetLastError();
- if (status_code < 400)
- return RPC_S_OK;
- index = 0;
- size = sizeof(buf);
- ret = HttpQueryInfoW(hor, HTTP_QUERY_STATUS_TEXT, status_text, &size, &index);
- if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
- {
- status_text = HeapAlloc(GetProcessHeap(), 0, size);
- ret = HttpQueryInfoW(hor, HTTP_QUERY_STATUS_TEXT, status_text, &size, &index);
- }
-
- ERR("server returned: %d %s\n", status_code, ret ? debugstr_w(status_text) : "<status text unavailable>");
- if(status_text != buf) HeapFree(GetProcessHeap(), 0, status_text);
-
- if (status_code == HTTP_STATUS_DENIED)
- return ERROR_ACCESS_DENIED;
- return RPC_S_SERVER_UNAVAILABLE;
-}
-
-static RPC_STATUS rpcrt4_http_internet_connect(RpcConnection_http *httpc)
-{
- static const WCHAR wszUserAgent[] = {'M','S','R','P','C',0};
- LPWSTR proxy = NULL;
- LPWSTR user = NULL;
- LPWSTR password = NULL;
- LPWSTR servername = NULL;
- const WCHAR *option;
- INTERNET_PORT port = INTERNET_INVALID_PORT_NUMBER; /* use default port */
-
- if (httpc->common.QOS &&
- (httpc->common.QOS->qos->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP))
- {
- const RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_cred = httpc->common.QOS->qos->u.HttpCredentials;
- if (http_cred->TransportCredentials)
- {
- WCHAR *p;
- const SEC_WINNT_AUTH_IDENTITY_W *cred = http_cred->TransportCredentials;
- ULONG len = cred->DomainLength + 1 + cred->UserLength;
- user = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
- if (!user)
- return RPC_S_OUT_OF_RESOURCES;
- p = user;
- if (cred->DomainLength)
- {
- memcpy(p, cred->Domain, cred->DomainLength * sizeof(WCHAR));
- p += cred->DomainLength;
- *p = '\\';
- p++;
- }
- memcpy(p, cred->User, cred->UserLength * sizeof(WCHAR));
- p[cred->UserLength] = 0;
-
- password = RPCRT4_strndupW(cred->Password, cred->PasswordLength);
- }
- }
-
- for (option = httpc->common.NetworkOptions; option;
- option = (strchrW(option, ',') ? strchrW(option, ',')+1 : NULL))
- {
- static const WCHAR wszRpcProxy[] = {'R','p','c','P','r','o','x','y','=',0};
- static const WCHAR wszHttpProxy[] = {'H','t','t','p','P','r','o','x','y','=',0};
-
- if (!strncmpiW(option, wszRpcProxy, sizeof(wszRpcProxy)/sizeof(wszRpcProxy[0])-1))
- {
- const WCHAR *value_start = option + sizeof(wszRpcProxy)/sizeof(wszRpcProxy[0])-1;
- const WCHAR *value_end;
- const WCHAR *p;
-
- value_end = strchrW(option, ',');
- if (!value_end)
- value_end = value_start + strlenW(value_start);
- for (p = value_start; p < value_end; p++)
- if (*p == ':')
- {
- port = atoiW(p+1);
- value_end = p;
- break;
- }
- TRACE("RpcProxy value is %s\n", debugstr_wn(value_start, value_end-value_start));
- servername = RPCRT4_strndupW(value_start, value_end-value_start);
- }
- else if (!strncmpiW(option, wszHttpProxy, sizeof(wszHttpProxy)/sizeof(wszHttpProxy[0])-1))
- {
- const WCHAR *value_start = option + sizeof(wszHttpProxy)/sizeof(wszHttpProxy[0])-1;
- const WCHAR *value_end;
-
- value_end = strchrW(option, ',');
- if (!value_end)
- value_end = value_start + strlenW(value_start);
- TRACE("HttpProxy value is %s\n", debugstr_wn(value_start, value_end-value_start));
- proxy = RPCRT4_strndupW(value_start, value_end-value_start);
- }
- else
- FIXME("unhandled option %s\n", debugstr_w(option));
- }
-
- httpc->app_info = InternetOpenW(wszUserAgent, proxy ? INTERNET_OPEN_TYPE_PROXY : INTERNET_OPEN_TYPE_PRECONFIG,
- NULL, NULL, INTERNET_FLAG_ASYNC);
- if (!httpc->app_info)
- {
- HeapFree(GetProcessHeap(), 0, password);
- HeapFree(GetProcessHeap(), 0, user);
- ERR("InternetOpenW failed with error %d\n", GetLastError());
- return RPC_S_SERVER_UNAVAILABLE;
- }
- InternetSetStatusCallbackW(httpc->app_info, rpcrt4_http_internet_callback);
-
- /* if no RpcProxy option specified, set the HTTP server address to the
- * RPC server address */
- if (!servername)
- {
- servername = HeapAlloc(GetProcessHeap(), 0, (strlen(httpc->common.NetworkAddr) + 1)*sizeof(WCHAR));
- if (!servername)
- {
- HeapFree(GetProcessHeap(), 0, password);
- HeapFree(GetProcessHeap(), 0, user);
- return RPC_S_OUT_OF_RESOURCES;
- }
- MultiByteToWideChar(CP_ACP, 0, httpc->common.NetworkAddr, -1, servername, strlen(httpc->common.NetworkAddr) + 1);
- }
-
- httpc->session = InternetConnectW(httpc->app_info, servername, port, user, password,
- INTERNET_SERVICE_HTTP, 0, 0);
-
- HeapFree(GetProcessHeap(), 0, password);
- HeapFree(GetProcessHeap(), 0, user);
- HeapFree(GetProcessHeap(), 0, servername);
-
- if (!httpc->session)
- {
- ERR("InternetConnectW failed with error %d\n", GetLastError());
- return RPC_S_SERVER_UNAVAILABLE;
- }
-
- return RPC_S_OK;
-}
-
-/* prepare the in pipe for use by RPC packets */
-static RPC_STATUS rpcrt4_http_prepare_in_pipe(HINTERNET in_request, RpcHttpAsyncData *async_data,
- const UUID *connection_uuid,
- const UUID *in_pipe_uuid,
- const UUID *association_uuid)
-{
- BYTE packet[44];
- BOOL ret;
- RPC_STATUS status;
- RpcPktHdr *hdr;
- INTERNET_BUFFERSW buffers_in;
- DWORD bytes_read, bytes_written;
-
- /* prepare in pipe */
- ResetEvent(async_data->completion_event);
- RpcHttpAsyncData_AddRef(async_data);
- ret = HttpSendRequestW(in_request, NULL, 0, NULL, 0);
- if (!ret)
- {
- if (GetLastError() == ERROR_IO_PENDING)
- WaitForSingleObject(async_data->completion_event, INFINITE);
- else
- {
- RpcHttpAsyncData_Release(async_data);
- ERR("HttpSendRequestW failed with error %d\n", GetLastError());
- return RPC_S_SERVER_UNAVAILABLE;
- }
- }
- status = rpcrt4_http_check_response(in_request);
- if (status != RPC_S_OK) return status;
-
- InternetReadFile(in_request, packet, 20, &bytes_read);
- /* FIXME: do something with retrieved data */
-
- memset(&buffers_in, 0, sizeof(buffers_in));
- buffers_in.dwStructSize = sizeof(buffers_in);
- /* FIXME: get this from the registry */
- buffers_in.dwBufferTotal = 1024 * 1024 * 1024; /* 1Gb */
- ResetEvent(async_data->completion_event);
- RpcHttpAsyncData_AddRef(async_data);
- ret = HttpSendRequestExW(in_request, &buffers_in, NULL, 0, 0);
- if (!ret)
- {
- if (GetLastError() == ERROR_IO_PENDING)
- WaitForSingleObject(async_data->completion_event, INFINITE);
- else
- {
- RpcHttpAsyncData_Release(async_data);
- ERR("HttpSendRequestExW failed with error %d\n", GetLastError());
- return RPC_S_SERVER_UNAVAILABLE;
- }
- }
-
- TRACE("sending HTTP connect header to server\n");
- hdr = RPCRT4_BuildHttpConnectHeader(0, FALSE, connection_uuid, in_pipe_uuid, association_uuid);
- if (!hdr) return RPC_S_OUT_OF_RESOURCES;
- ret = InternetWriteFile(in_request, hdr, hdr->common.frag_len, &bytes_written);
- RPCRT4_FreeHeader(hdr);
- if (!ret)
- {
- ERR("InternetWriteFile failed with error %d\n", GetLastError());
- return RPC_S_SERVER_UNAVAILABLE;
- }
-
- return RPC_S_OK;
-}
-
-static RPC_STATUS rpcrt4_http_read_http_packet(HINTERNET request, RpcPktHdr *hdr, BYTE **data)
-{
- BOOL ret;
- DWORD bytes_read;
- unsigned short data_len;
-
- ret = InternetReadFile(request, hdr, sizeof(hdr->common), &bytes_read);
- if (!ret)
- return RPC_S_SERVER_UNAVAILABLE;
- if (hdr->common.ptype != PKT_HTTP || hdr->common.frag_len < sizeof(hdr->http))
- {
- ERR("wrong packet type received %d or wrong frag_len %d\n",
- hdr->common.ptype, hdr->common.frag_len);
- return RPC_S_PROTOCOL_ERROR;
- }
-
- ret = InternetReadFile(request, &hdr->common + 1, sizeof(hdr->http) - sizeof(hdr->common), &bytes_read);
- if (!ret)
- return RPC_S_SERVER_UNAVAILABLE;
-
- data_len = hdr->common.frag_len - sizeof(hdr->http);
- if (data_len)
- {
- *data = HeapAlloc(GetProcessHeap(), 0, data_len);
- if (!*data)
- return RPC_S_OUT_OF_RESOURCES;
- ret = InternetReadFile(request, *data, data_len, &bytes_read);
- if (!ret)
- {
- HeapFree(GetProcessHeap(), 0, *data);
- return RPC_S_SERVER_UNAVAILABLE;
- }
- }
- else
- *data = NULL;
-
- if (!RPCRT4_IsValidHttpPacket(hdr, *data, data_len))
- {
- ERR("invalid http packet\n");
- return RPC_S_PROTOCOL_ERROR;
- }
-
- return RPC_S_OK;
-}
-
-/* prepare the out pipe for use by RPC packets */
-static RPC_STATUS rpcrt4_http_prepare_out_pipe(HINTERNET out_request,
- RpcHttpAsyncData *async_data,
- const UUID *connection_uuid,
- const UUID *out_pipe_uuid,
- ULONG *flow_control_increment)
-{
- BYTE packet[20];
- BOOL ret;
- RPC_STATUS status;
- RpcPktHdr *hdr;
- DWORD bytes_read;
- BYTE *data_from_server;
- RpcPktHdr pkt_from_server;
- ULONG field1, field3;
-
- ResetEvent(async_data->completion_event);
- RpcHttpAsyncData_AddRef(async_data);
- ret = HttpSendRequestW(out_request, NULL, 0, NULL, 0);
- if (!ret)
- {
- if (GetLastError() == ERROR_IO_PENDING)
- WaitForSingleObject(async_data->completion_event, INFINITE);
- else
- {
- RpcHttpAsyncData_Release(async_data);
- ERR("HttpSendRequestW failed with error %d\n", GetLastError());
- return RPC_S_SERVER_UNAVAILABLE;
- }
- }
- status = rpcrt4_http_check_response(out_request);
- if (status != RPC_S_OK) return status;
-
- InternetReadFile(out_request, packet, 20, &bytes_read);
- /* FIXME: do something with retrieved data */
-
- hdr = RPCRT4_BuildHttpConnectHeader(0, TRUE, connection_uuid, out_pipe_uuid, NULL);
- if (!hdr) return RPC_S_OUT_OF_RESOURCES;
- ResetEvent(async_data->completion_event);
- RpcHttpAsyncData_AddRef(async_data);
- ret = HttpSendRequestW(out_request, NULL, 0, hdr, hdr->common.frag_len);
- if (!ret)
- {
- if (GetLastError() == ERROR_IO_PENDING)
- WaitForSingleObject(async_data->completion_event, INFINITE);
- else
- {
- RpcHttpAsyncData_Release(async_data);
- ERR("HttpSendRequestW failed with error %d\n", GetLastError());
- RPCRT4_FreeHeader(hdr);
- return RPC_S_SERVER_UNAVAILABLE;
- }
- }
- RPCRT4_FreeHeader(hdr);
- status = rpcrt4_http_check_response(out_request);
- if (status != RPC_S_OK) return status;
-
- status = rpcrt4_http_read_http_packet(out_request, &pkt_from_server,
- &data_from_server);
- if (status != RPC_S_OK) return status;
- status = RPCRT4_ParseHttpPrepareHeader1(&pkt_from_server, data_from_server,
- &field1);
- HeapFree(GetProcessHeap(), 0, data_from_server);
- if (status != RPC_S_OK) return status;
- TRACE("received (%d) from first prepare header\n", field1);
-
- status = rpcrt4_http_read_http_packet(out_request, &pkt_from_server,
- &data_from_server);
- if (status != RPC_S_OK) return status;
- status = RPCRT4_ParseHttpPrepareHeader2(&pkt_from_server, data_from_server,
- &field1, flow_control_increment,
- &field3);
- HeapFree(GetProcessHeap(), 0, data_from_server);
- if (status != RPC_S_OK) return status;
- TRACE("received (0x%08x 0x%08x %d) from second prepare header\n", field1, *flow_control_increment, field3);
-
- return RPC_S_OK;
-}
-
-static RPC_STATUS rpcrt4_ncacn_http_open(RpcConnection* Connection)
-{
- RpcConnection_http *httpc = (RpcConnection_http *)Connection;
- static const WCHAR wszVerbIn[] = {'R','P','C','_','I','N','_','D','A','T','A',0};
- static const WCHAR wszVerbOut[] = {'R','P','C','_','O','U','T','_','D','A','T','A',0};
- static const WCHAR wszRpcProxyPrefix[] = {'/','r','p','c','/','r','p','c','p','r','o','x','y','.','d','l','l','?',0};
- static const WCHAR wszColon[] = {':',0};
- static const WCHAR wszAcceptType[] = {'a','p','p','l','i','c','a','t','i','o','n','/','r','p','c',0};
- LPCWSTR wszAcceptTypes[] = { wszAcceptType, NULL };
- WCHAR *url;
- RPC_STATUS status;
- BOOL secure;
- HttpTimerThreadData *timer_data;
- HANDLE thread;
-
- TRACE("(%s, %s)\n", Connection->NetworkAddr, Connection->Endpoint);
-
- if (Connection->server)
- {
- ERR("ncacn_http servers not supported yet\n");
- return RPC_S_SERVER_UNAVAILABLE;
- }
-
- if (httpc->in_request)
- return RPC_S_OK;
-
- httpc->async_data->completion_event = CreateEventW(NULL, FALSE, FALSE, NULL);
-
- status = UuidCreate(&httpc->connection_uuid);
- status = UuidCreate(&httpc->in_pipe_uuid);
- status = UuidCreate(&httpc->out_pipe_uuid);
-
- status = rpcrt4_http_internet_connect(httpc);
- if (status != RPC_S_OK)
- return status;
-
- url = HeapAlloc(GetProcessHeap(), 0, sizeof(wszRpcProxyPrefix) + (strlen(Connection->NetworkAddr) + 1 + strlen(Connection->Endpoint))*sizeof(WCHAR));
- if (!url)
- return RPC_S_OUT_OF_MEMORY;
- memcpy(url, wszRpcProxyPrefix, sizeof(wszRpcProxyPrefix));
- MultiByteToWideChar(CP_ACP, 0, Connection->NetworkAddr, -1, url+sizeof(wszRpcProxyPrefix)/sizeof(wszRpcProxyPrefix[0])-1, strlen(Connection->NetworkAddr)+1);
- strcatW(url, wszColon);
- MultiByteToWideChar(CP_ACP, 0, Connection->Endpoint, -1, url+strlenW(url), strlen(Connection->Endpoint)+1);
-
- secure = httpc->common.QOS &&
- (httpc->common.QOS->qos->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP) &&
- (httpc->common.QOS->qos->u.HttpCredentials->Flags & RPC_C_HTTP_FLAG_USE_SSL);
-
- httpc->in_request = HttpOpenRequestW(httpc->session, wszVerbIn, url, NULL, NULL,
- wszAcceptTypes,
- (secure ? INTERNET_FLAG_SECURE : 0)|INTERNET_FLAG_KEEP_CONNECTION|INTERNET_FLAG_PRAGMA_NOCACHE,
- (DWORD_PTR)httpc->async_data);
- if (!httpc->in_request)
- {
- ERR("HttpOpenRequestW failed with error %d\n", GetLastError());
- return RPC_S_SERVER_UNAVAILABLE;
- }
- httpc->out_request = HttpOpenRequestW(httpc->session, wszVerbOut, url, NULL, NULL,
- wszAcceptTypes,
- (secure ? INTERNET_FLAG_SECURE : 0)|INTERNET_FLAG_KEEP_CONNECTION|INTERNET_FLAG_PRAGMA_NOCACHE,
- (DWORD_PTR)httpc->async_data);
- if (!httpc->out_request)
- {
- ERR("HttpOpenRequestW failed with error %d\n", GetLastError());
- return RPC_S_SERVER_UNAVAILABLE;
- }
-
- status = rpcrt4_http_prepare_in_pipe(httpc->in_request,
- httpc->async_data,
- &httpc->connection_uuid,
- &httpc->in_pipe_uuid,
- &Connection->assoc->http_uuid);
- if (status != RPC_S_OK)
- return status;
-
- status = rpcrt4_http_prepare_out_pipe(httpc->out_request,
- httpc->async_data,
- &httpc->connection_uuid,
- &httpc->out_pipe_uuid,
- &httpc->flow_control_increment);
- if (status != RPC_S_OK)
- return status;
-
- httpc->flow_control_mark = httpc->flow_control_increment / 2;
- httpc->last_sent_time = GetTickCount();
- httpc->timer_cancelled = CreateEventW(NULL, FALSE, FALSE, NULL);
-
- timer_data = HeapAlloc(GetProcessHeap(), 0, sizeof(*timer_data));
- if (!timer_data)
- return ERROR_OUTOFMEMORY;
- timer_data->timer_param = httpc->in_request;
- timer_data->last_sent_time = &httpc->last_sent_time;
- timer_data->timer_cancelled = httpc->timer_cancelled;
- /* FIXME: should use CreateTimerQueueTimer when implemented */
- thread = CreateThread(NULL, 0, rpcrt4_http_timer_thread, timer_data, 0, NULL);
- if (!thread)
- {
- HeapFree(GetProcessHeap(), 0, timer_data);
- return GetLastError();
- }
- CloseHandle(thread);
-
- return RPC_S_OK;
-}
-
-static RPC_STATUS rpcrt4_ncacn_http_handoff(RpcConnection *old_conn, RpcConnection *new_conn)
-{
- assert(0);
- return RPC_S_SERVER_UNAVAILABLE;
-}
-
-static int rpcrt4_ncacn_http_read(RpcConnection *Connection,
- void *buffer, unsigned int count)
-{
- RpcConnection_http *httpc = (RpcConnection_http *) Connection;
- char *buf = buffer;
- BOOL ret = TRUE;
- unsigned int bytes_left = count;
-
- ResetEvent(httpc->async_data->completion_event);
- while (bytes_left)
- {
- RpcHttpAsyncData_AddRef(httpc->async_data);
- httpc->async_data->inet_buffers.dwBufferLength = bytes_left;
- httpc->async_data->inet_buffers.lpvBuffer = HeapAlloc(GetProcessHeap(), 0, bytes_left);
- httpc->async_data->destination_buffer = buf;
- ret = InternetReadFileExA(httpc->out_request, &httpc->async_data->inet_buffers, IRF_ASYNC, 0);
- if (ret)
- {
- /* INTERNET_STATUS_REQUEST_COMPLETED won't be sent, so release our
- * async ref now */
- RpcHttpAsyncData_Release(httpc->async_data);
- memcpy(buf, httpc->async_data->inet_buffers.lpvBuffer,
- httpc->async_data->inet_buffers.dwBufferLength);
- HeapFree(GetProcessHeap(), 0, httpc->async_data->inet_buffers.lpvBuffer);
- httpc->async_data->inet_buffers.lpvBuffer = NULL;
- httpc->async_data->destination_buffer = NULL;
- }
- else
- {
- if (GetLastError() == ERROR_IO_PENDING)
- {
- HANDLE handles[2] = { httpc->async_data->completion_event, httpc->cancel_event };
- DWORD result = WaitForMultipleObjects(2, handles, FALSE, DEFAULT_NCACN_HTTP_TIMEOUT);
- if (result == WAIT_OBJECT_0)
- ret = TRUE;
- else
- {
- TRACE("call cancelled\n");
- EnterCriticalSection(&httpc->async_data->cs);
- httpc->async_data->destination_buffer = NULL;
- LeaveCriticalSection(&httpc->async_data->cs);
- break;
- }
- }
- else
- {
- HeapFree(GetProcessHeap(), 0, httpc->async_data->inet_buffers.lpvBuffer);
- httpc->async_data->inet_buffers.lpvBuffer = NULL;
- httpc->async_data->destination_buffer = NULL;
- RpcHttpAsyncData_Release(httpc->async_data);
- break;
- }
- }
- if (!httpc->async_data->inet_buffers.dwBufferLength)
- break;
- bytes_left -= httpc->async_data->inet_buffers.dwBufferLength;
- buf += httpc->async_data->inet_buffers.dwBufferLength;
- }
- TRACE("%p %p %u -> %s\n", httpc->out_request, buffer, count, ret ? "TRUE" : "FALSE");
- return ret ? count : -1;
-}
-
-static RPC_STATUS rpcrt4_ncacn_http_receive_fragment(RpcConnection *Connection, RpcPktHdr **Header, void **Payload)
-{
- RpcConnection_http *httpc = (RpcConnection_http *) Connection;
- RPC_STATUS status;
- DWORD hdr_length;
- LONG dwRead;
- RpcPktCommonHdr common_hdr;
-
- *Header = NULL;
-
- TRACE("(%p, %p, %p)\n", Connection, Header, Payload);
-
-again:
- /* read packet common header */
- dwRead = rpcrt4_ncacn_http_read(Connection, &common_hdr, sizeof(common_hdr));
- if (dwRead != sizeof(common_hdr)) {
- WARN("Short read of header, %d bytes\n", dwRead);
- status = RPC_S_PROTOCOL_ERROR;
- goto fail;
- }
- if (!memcmp(&common_hdr, "HTTP/1.1", sizeof("HTTP/1.1")) ||
- !memcmp(&common_hdr, "HTTP/1.0", sizeof("HTTP/1.0")))
- {
- FIXME("server returned %s\n", debugstr_a((const char *)&common_hdr));
- status = RPC_S_PROTOCOL_ERROR;
- goto fail;
- }
-
- status = RPCRT4_ValidateCommonHeader(&common_hdr);
- if (status != RPC_S_OK) goto fail;
-
- hdr_length = RPCRT4_GetHeaderSize((RpcPktHdr*)&common_hdr);
- if (hdr_length == 0) {
- WARN("header length == 0\n");
- status = RPC_S_PROTOCOL_ERROR;
- goto fail;
- }
-
- *Header = HeapAlloc(GetProcessHeap(), 0, hdr_length);
- if (!*Header)
- {
- status = RPC_S_OUT_OF_RESOURCES;
- goto fail;
- }
- memcpy(*Header, &common_hdr, sizeof(common_hdr));
-
- /* read the rest of packet header */
- dwRead = rpcrt4_ncacn_http_read(Connection, &(*Header)->common + 1, hdr_length - sizeof(common_hdr));
- if (dwRead != hdr_length - sizeof(common_hdr)) {
- WARN("bad header length, %d bytes, hdr_length %d\n", dwRead, hdr_length);
- status = RPC_S_PROTOCOL_ERROR;
- goto fail;
- }
-
- if (common_hdr.frag_len - hdr_length)
- {
- *Payload = HeapAlloc(GetProcessHeap(), 0, common_hdr.frag_len - hdr_length);
- if (!*Payload)
- {
- status = RPC_S_OUT_OF_RESOURCES;
- goto fail;
- }
-
- dwRead = rpcrt4_ncacn_http_read(Connection, *Payload, common_hdr.frag_len - hdr_length);
- if (dwRead != common_hdr.frag_len - hdr_length)
- {
- WARN("bad data length, %d/%d\n", dwRead, common_hdr.frag_len - hdr_length);
- status = RPC_S_PROTOCOL_ERROR;
- goto fail;
- }
- }
- else
- *Payload = NULL;
-
- if ((*Header)->common.ptype == PKT_HTTP)
- {
- if (!RPCRT4_IsValidHttpPacket(*Header, *Payload, common_hdr.frag_len - hdr_length))
- {
- ERR("invalid http packet of length %d bytes\n", (*Header)->common.frag_len);
- status = RPC_S_PROTOCOL_ERROR;
- goto fail;
- }
- if ((*Header)->http.flags == 0x0001)
- {
- TRACE("http idle packet, waiting for real packet\n");
- if ((*Header)->http.num_data_items != 0)
- {
- ERR("HTTP idle packet should have no data items instead of %d\n", (*Header)->http.num_data_items);
- status = RPC_S_PROTOCOL_ERROR;
- goto fail;
- }
- }
- else if ((*Header)->http.flags == 0x0002)
- {
- ULONG bytes_transmitted;
- ULONG flow_control_increment;
- UUID pipe_uuid;
- status = RPCRT4_ParseHttpFlowControlHeader(*Header, *Payload,
- Connection->server,
- &bytes_transmitted,
- &flow_control_increment,
- &pipe_uuid);
- if (status != RPC_S_OK)
- goto fail;
- TRACE("received http flow control header (0x%x, 0x%x, %s)\n",
- bytes_transmitted, flow_control_increment, debugstr_guid(&pipe_uuid));
- /* FIXME: do something with parsed data */
- }
- else
- {
- FIXME("unrecognised http packet with flags 0x%04x\n", (*Header)->http.flags);
- status = RPC_S_PROTOCOL_ERROR;
- goto fail;
- }
- RPCRT4_FreeHeader(*Header);
- *Header = NULL;
- HeapFree(GetProcessHeap(), 0, *Payload);
- *Payload = NULL;
- goto again;
- }
-
- /* success */
- status = RPC_S_OK;
-
- httpc->bytes_received += common_hdr.frag_len;
-
- TRACE("httpc->bytes_received = 0x%x\n", httpc->bytes_received);
-
- if (httpc->bytes_received > httpc->flow_control_mark)
- {
- RpcPktHdr *hdr = RPCRT4_BuildHttpFlowControlHeader(httpc->common.server,
- httpc->bytes_received,
- httpc->flow_control_increment,
- &httpc->out_pipe_uuid);
- if (hdr)
- {
- DWORD bytes_written;
- BOOL ret2;
- TRACE("sending flow control packet at 0x%x\n", httpc->bytes_received);
- ret2 = InternetWriteFile(httpc->in_request, hdr, hdr->common.frag_len, &bytes_written);
- RPCRT4_FreeHeader(hdr);
- if (ret2)
- httpc->flow_control_mark = httpc->bytes_received + httpc->flow_control_increment / 2;
- }
- }
-
-fail:
- if (status != RPC_S_OK) {
- RPCRT4_FreeHeader(*Header);
- *Header = NULL;
- HeapFree(GetProcessHeap(), 0, *Payload);
- *Payload = NULL;
- }
- return status;
-}
-
-static int rpcrt4_ncacn_http_write(RpcConnection *Connection,
- const void *buffer, unsigned int count)
-{
- RpcConnection_http *httpc = (RpcConnection_http *) Connection;
- DWORD bytes_written;
- BOOL ret;
-
- httpc->last_sent_time = ~0U; /* disable idle packet sending */
- ret = InternetWriteFile(httpc->in_request, buffer, count, &bytes_written);
- httpc->last_sent_time = GetTickCount();
- TRACE("%p %p %u -> %s\n", httpc->in_request, buffer, count, ret ? "TRUE" : "FALSE");
- return ret ? bytes_written : -1;
-}
-
-static int rpcrt4_ncacn_http_close(RpcConnection *Connection)
-{
- RpcConnection_http *httpc = (RpcConnection_http *) Connection;
-
- TRACE("\n");
-
- SetEvent(httpc->timer_cancelled);
- if (httpc->in_request)
- InternetCloseHandle(httpc->in_request);
- httpc->in_request = NULL;
- if (httpc->out_request)
- InternetCloseHandle(httpc->out_request);
- httpc->out_request = NULL;
- if (httpc->app_info)
- InternetCloseHandle(httpc->app_info);
- httpc->app_info = NULL;
- if (httpc->session)
- InternetCloseHandle(httpc->session);
- httpc->session = NULL;
- RpcHttpAsyncData_Release(httpc->async_data);
- if (httpc->cancel_event)
- CloseHandle(httpc->cancel_event);
-
- return 0;
-}
-
-static void rpcrt4_ncacn_http_cancel_call(RpcConnection *Connection)
-{
- RpcConnection_http *httpc = (RpcConnection_http *) Connection;
-
- SetEvent(httpc->cancel_event);
-}
-
-static int rpcrt4_ncacn_http_wait_for_incoming_data(RpcConnection *Connection)
-{
- BOOL ret;
- RpcConnection_http *httpc = (RpcConnection_http *) Connection;
-
- RpcHttpAsyncData_AddRef(httpc->async_data);
- ret = InternetQueryDataAvailable(httpc->out_request,
- &httpc->async_data->inet_buffers.dwBufferLength, IRF_ASYNC, 0);
- if (ret)
- {
- /* INTERNET_STATUS_REQUEST_COMPLETED won't be sent, so release our
- * async ref now */
- RpcHttpAsyncData_Release(httpc->async_data);
- }
- else
- {
- if (GetLastError() == ERROR_IO_PENDING)
- {
- HANDLE handles[2] = { httpc->async_data->completion_event, httpc->cancel_event };
- DWORD result = WaitForMultipleObjects(2, handles, FALSE, DEFAULT_NCACN_HTTP_TIMEOUT);
- if (result != WAIT_OBJECT_0)
- {
- TRACE("call cancelled\n");
- return -1;
- }
- }
- else
- {
- RpcHttpAsyncData_Release(httpc->async_data);
- return -1;
- }
- }
-
- /* success */
- return 0;
-}
-
-static size_t rpcrt4_ncacn_http_get_top_of_tower(unsigned char *tower_data,
- const char *networkaddr,
- const char *endpoint)
-{
- return rpcrt4_ip_tcp_get_top_of_tower(tower_data, networkaddr,
- EPM_PROTOCOL_HTTP, endpoint);
-}
-
-static RPC_STATUS rpcrt4_ncacn_http_parse_top_of_tower(const unsigned char *tower_data,
- size_t tower_size,
- char **networkaddr,
- char **endpoint)
-{
- return rpcrt4_ip_tcp_parse_top_of_tower(tower_data, tower_size,
- networkaddr, EPM_PROTOCOL_HTTP,
- endpoint);
-}
-#endif
-static const struct connection_ops conn_protseq_list[] = {
- { "ncacn_np",
- { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_SMB },
- rpcrt4_conn_np_alloc,
- rpcrt4_ncacn_np_open,
- rpcrt4_ncacn_np_handoff,
- rpcrt4_conn_np_read,
- rpcrt4_conn_np_write,
- rpcrt4_conn_np_close,
- rpcrt4_conn_np_cancel_call,
- rpcrt4_conn_np_wait_for_incoming_data,
- rpcrt4_ncacn_np_get_top_of_tower,
- rpcrt4_ncacn_np_parse_top_of_tower,
- NULL,
- },
- { "ncalrpc",
- { EPM_PROTOCOL_NCALRPC, EPM_PROTOCOL_PIPE },
- rpcrt4_conn_np_alloc,
- rpcrt4_ncalrpc_open,
- rpcrt4_ncalrpc_handoff,
- rpcrt4_conn_np_read,
- rpcrt4_conn_np_write,
- rpcrt4_conn_np_close,
- rpcrt4_conn_np_cancel_call,
- rpcrt4_conn_np_wait_for_incoming_data,
- rpcrt4_ncalrpc_get_top_of_tower,
- rpcrt4_ncalrpc_parse_top_of_tower,
- NULL,
- },
- { "ncacn_ip_tcp",
- { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_TCP },
- rpcrt4_conn_tcp_alloc,
- rpcrt4_ncacn_ip_tcp_open,
- rpcrt4_conn_tcp_handoff,
- rpcrt4_conn_tcp_read,
- rpcrt4_conn_tcp_write,
- rpcrt4_conn_tcp_close,
- rpcrt4_conn_tcp_cancel_call,
- rpcrt4_conn_tcp_wait_for_incoming_data,
- rpcrt4_ncacn_ip_tcp_get_top_of_tower,
- rpcrt4_ncacn_ip_tcp_parse_top_of_tower,
- NULL,
- },
-#if 0
- { "ncacn_http",
- { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_HTTP },
- rpcrt4_ncacn_http_alloc,
- rpcrt4_ncacn_http_open,
- rpcrt4_ncacn_http_handoff,
- rpcrt4_ncacn_http_read,
- rpcrt4_ncacn_http_write,
- rpcrt4_ncacn_http_close,
- rpcrt4_ncacn_http_cancel_call,
- rpcrt4_ncacn_http_wait_for_incoming_data,
- rpcrt4_ncacn_http_get_top_of_tower,
- rpcrt4_ncacn_http_parse_top_of_tower,
- rpcrt4_ncacn_http_receive_fragment,
- },
-#endif
-};
-
-
-static const struct protseq_ops protseq_list[] =
-{
- {
- "ncacn_np",
- rpcrt4_protseq_np_alloc,
- rpcrt4_protseq_np_signal_state_changed,
- rpcrt4_protseq_np_get_wait_array,
- rpcrt4_protseq_np_free_wait_array,
- rpcrt4_protseq_np_wait_for_new_connection,
- rpcrt4_protseq_ncacn_np_open_endpoint,
- },
- {
- "ncalrpc",
- rpcrt4_protseq_np_alloc,
- rpcrt4_protseq_np_signal_state_changed,
- rpcrt4_protseq_np_get_wait_array,
- rpcrt4_protseq_np_free_wait_array,
- rpcrt4_protseq_np_wait_for_new_connection,
- rpcrt4_protseq_ncalrpc_open_endpoint,
- },
+ "ncalrpc",
+ rpcrt4_protseq_np_alloc,
+ rpcrt4_protseq_np_signal_state_changed,
+ rpcrt4_protseq_np_get_wait_array,
+ rpcrt4_protseq_np_free_wait_array,
+ rpcrt4_protseq_np_wait_for_new_connection,
+ rpcrt4_protseq_ncalrpc_open_endpoint,
+ },
+#ifdef HAVE_SOCKETPAIR
{
"ncacn_ip_tcp",
rpcrt4_protseq_sock_alloc,
rpcrt4_protseq_sock_wait_for_new_connection,
rpcrt4_protseq_ncacn_ip_tcp_open_endpoint,
},
+#endif
};
#define ARRAYSIZE(a) (sizeof((a)) / sizeof((a)[0]))
LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint,
LPCWSTR NetworkOptions, RpcAuthInfo* AuthInfo, RpcQualityOfService *QOS)
{
- static LONG next_id;
const struct connection_ops *ops;
RpcConnection* NewConnection;
NewConnection->attr = 0;
if (AuthInfo) RpcAuthInfo_AddRef(AuthInfo);
NewConnection->AuthInfo = AuthInfo;
- NewConnection->auth_context_id = InterlockedIncrement( &next_id );
NewConnection->encryption_auth_len = 0;
NewConnection->signature_auth_len = 0;
if (QOS) RpcQualityOfService_AddRef(QOS);
<library>user32</library>
<library>advapi32</library>
<library>secur32</library>
- <!--library>wininet</library-->
<library>iphlpapi</library>
<library>ws2_32</library>
<library>ntdll</library>
@ stdcall NDRSContextUnmarshallEx(ptr ptr ptr)
@ stub NDRcopy
@ stdcall NdrAllocate(ptr long)
-@ varargs NdrAsyncClientCall(ptr ptr)
+@ stub NdrAsyncClientCall
@ stub NdrAsyncServerCall
-@ stdcall NdrAsyncStubCall(ptr ptr ptr ptr)
@ stdcall NdrByteCountPointerBufferSize(ptr ptr ptr)
@ stdcall NdrByteCountPointerFree(ptr ptr ptr)
@ stdcall NdrByteCountPointerMarshall(ptr ptr ptr)
@ stdcall RpcEpRegisterA(ptr ptr ptr str)
@ stub RpcEpRegisterNoReplaceA
@ stub RpcEpRegisterNoReplaceW
-@ stdcall RpcEpRegisterW(ptr ptr ptr wstr)
+@ stub RpcEpRegisterW
@ stdcall RpcEpResolveBinding(ptr ptr)
@ stdcall RpcEpUnregister(ptr ptr ptr)
@ stub RpcErrorAddRecord # wxp
#include "winuser.h"
#include "winnt.h"
#include "winternl.h"
-#define _NTDEF_
-typedef NTSTATUS *PNTSTATUS;
-#include "ntsecapi.h"
-#undef _NTDEF_
+#include "iptypes.h"
+#include "iphlpapi.h"
#include "wine/unicode.h"
#include "rpc.h"
#include "rpcproxy.h"
#include "rpc_binding.h"
-#include "rpc_server.h"
#include "wine/debug.h"
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_DEBUG threaddata_cs_debug =
{
break;
case DLL_PROCESS_DETACH:
- RPCRT4_destroy_all_protseqs();
break;
}
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.@]
*
* RPC_S_OK if successful.
* RPC_S_UUID_LOCAL_ONLY if UUID is only locally unique.
*
- * NOTES
- *
- * Follows RFC 4122, section 4.4 (Algorithms for Creating a UUID from
- * Truly Random or Pseudo-Random Numbers)
+ * FIXME: No compensation for changes across reloading
+ * this dll or across reboots (e.g. clock going
+ * backwards and swapped network cards). The RFC
+ * suggests using NVRAM for storing persistent
+ * values.
*/
RPC_STATUS WINAPI UuidCreate(UUID *Uuid)
{
- RtlGenRandom(Uuid, sizeof(*Uuid));
- /* Clear the version bits and set the version (4) */
- Uuid->Data3 &= 0x0fff;
- Uuid->Data3 |= (4 << 12);
- /* Set the topmost bits of Data4 (clock_seq_hi_and_reserved) as
- * specified in RFC 4122, section 4.4.
- */
- Uuid->Data4[0] &= 0x3f;
- Uuid->Data4[0] |= 0x80;
+ static int initialised, count;
+
+ ULONGLONG time;
+ static ULONGLONG timelast;
+ static WORD sequence;
+
+ static DWORD status;
+ static BYTE address[MAX_ADAPTER_ADDRESS_LENGTH];
+
+ 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));
- return RPC_S_OK;
+ return status;
}
/*************************************************************************