From 4c3406bcd69ccbf3b013fe5d7344d3dca559163b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gardou?= Date: Sun, 7 Aug 2011 16:15:10 +0000 Subject: [PATCH] [RPCRT4] - sync with wine 1.3.26 MAny thanks to Filip Navara for his invaluable help. svn path=/trunk/; revision=53118 --- reactos/dll/win32/rpcrt4/cproxy.c | 231 ++- reactos/dll/win32/rpcrt4/cpsf.c | 2 +- reactos/dll/win32/rpcrt4/cpsf.h | 18 +- reactos/dll/win32/rpcrt4/cstub.c | 78 +- reactos/dll/win32/rpcrt4/msvc.S | 26 +- reactos/dll/win32/rpcrt4/ndr_es.c | 34 +- reactos/dll/win32/rpcrt4/ndr_marshall.c | 754 +++++---- reactos/dll/win32/rpcrt4/ndr_misc.h | 14 +- reactos/dll/win32/rpcrt4/ndr_ole.c | 30 +- reactos/dll/win32/rpcrt4/ndr_stubless.c | 1818 +++++++++++++--------- reactos/dll/win32/rpcrt4/ndr_stubless.h | 60 +- reactos/dll/win32/rpcrt4/rpc_assoc.c | 30 +- reactos/dll/win32/rpcrt4/rpc_assoc.h | 23 +- reactos/dll/win32/rpcrt4/rpc_async.c | 16 +- reactos/dll/win32/rpcrt4/rpc_binding.c | 221 ++- reactos/dll/win32/rpcrt4/rpc_binding.h | 119 +- reactos/dll/win32/rpcrt4/rpc_defs.h | 121 +- reactos/dll/win32/rpcrt4/rpc_epmap.c | 89 +- reactos/dll/win32/rpcrt4/rpc_message.c | 817 ++++++++-- reactos/dll/win32/rpcrt4/rpc_message.h | 41 +- reactos/dll/win32/rpcrt4/rpc_server.c | 684 ++++++-- reactos/dll/win32/rpcrt4/rpc_server.h | 9 +- reactos/dll/win32/rpcrt4/rpc_transport.c | 1276 ++++++++++++++- reactos/dll/win32/rpcrt4/rpcrt4.rbuild | 2 + reactos/dll/win32/rpcrt4/rpcrt4.spec | 37 +- reactos/dll/win32/rpcrt4/rpcrt4_main.c | 77 +- reactos/dll/win32/rpcrt4/version.rc | 26 + 27 files changed, 4862 insertions(+), 1791 deletions(-) create mode 100644 reactos/dll/win32/rpcrt4/version.rc diff --git a/reactos/dll/win32/rpcrt4/cproxy.c b/reactos/dll/win32/rpcrt4/cproxy.c index 176204667ad..b1acbb0c5dd 100644 --- a/reactos/dll/win32/rpcrt4/cproxy.c +++ b/reactos/dll/win32/rpcrt4/cproxy.c @@ -17,7 +17,7 @@ * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - * + * * TODO: Handle non-i386 architectures */ @@ -37,6 +37,7 @@ #include "cpsf.h" #include "ndr_misc.h" +#include "ndr_stubless.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(ole); @@ -44,7 +45,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole); /* 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; + IRpcProxyBuffer IRpcProxyBuffer_iface; LPVOID *PVtbl; LONG RefCount; const IID* piid; @@ -58,47 +59,130 @@ typedef struct { static const IRpcProxyBufferVtbl StdProxy_Vtbl; -#define ICOM_THIS_MULTI(impl,field,iface) impl* const This=(impl*)((char*)(iface) - offsetof(impl,field)) +static inline StdProxyImpl *impl_from_IRpcProxyBuffer(IRpcProxyBuffer *iface) +{ + return CONTAINING_RECORD(iface, StdProxyImpl, IRpcProxyBuffer_iface); +} -#if defined(__i386__) +static inline StdProxyImpl *impl_from_proxy_obj( void *iface ) +{ + return CONTAINING_RECORD(iface, StdProxyImpl, PVtbl); +} -#include "pshpack1.h" - -struct thunk { - BYTE push; - DWORD index; - BYTE jmp; - LONG handler; -}; - -#include "poppack.h" +#ifdef __i386__ extern void call_stubless_func(void); __ASM_GLOBAL_FUNC(call_stubless_func, - "pushl %esp\n\t" /* pointer to index */ + "movl 4(%esp),%ecx\n\t" /* This pointer */ + "movl (%ecx),%ecx\n\t" /* This->lpVtbl */ + "movl -8(%ecx),%ecx\n\t" /* MIDL_STUBLESS_PROXY_INFO */ + "movl 8(%ecx),%edx\n\t" /* info->FormatStringOffset */ + "movzwl (%edx,%eax,2),%edx\n\t" /* FormatStringOffset[index] */ + "addl 4(%ecx),%edx\n\t" /* info->ProcFormatString + offset */ + "movzwl 8(%edx),%eax\n\t" /* arguments size */ + "pushl %eax\n\t" __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") - "call " __ASM_NAME("ObjectStubless") __ASM_STDCALL(4) "\n\t" - "popl %edx\n\t" /* args size */ + "leal 8(%esp),%eax\n\t" /* &This */ + "pushl %eax\n\t" + __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") + "pushl %edx\n\t" /* format string */ + __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") + "pushl (%ecx)\n\t" /* info->pStubDesc */ + __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") + "call " __ASM_NAME("ndr_client_call") "\n\t" + "leal 12(%esp),%esp\n\t" + __ASM_CFI(".cfi_adjust_cfa_offset -12\n\t") + "popl %edx\n\t" /* arguments 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) +#include "pshpack1.h" +struct thunk { - 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]; + BYTE mov_eax; + DWORD index; + BYTE jmp; + LONG handler; +}; +#include "poppack.h" - /* 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).Simple; +static inline void init_thunk( struct thunk *thunk, unsigned int index ) +{ + thunk->mov_eax = 0xb8; /* movl $n,%eax */ + thunk->index = index; + thunk->jmp = 0xe9; /* jmp */ + thunk->handler = (char *)call_stubless_func - (char *)(&thunk->handler + 1); } +#elif defined(__x86_64__) + +extern void call_stubless_func(void); +__ASM_GLOBAL_FUNC(call_stubless_func, + "movq %rcx,0x8(%rsp)\n\t" + "movq %rdx,0x10(%rsp)\n\t" + "movq %r8,0x18(%rsp)\n\t" + "movq %r9,0x20(%rsp)\n\t" + "leaq 0x8(%rsp),%r8\n\t" /* &This */ + "movq (%rcx),%rcx\n\t" /* This->lpVtbl */ + "movq -0x10(%rcx),%rcx\n\t" /* MIDL_STUBLESS_PROXY_INFO */ + "movq 0x10(%rcx),%rdx\n\t" /* info->FormatStringOffset */ + "movzwq (%rdx,%r10,2),%rdx\n\t" /* FormatStringOffset[index] */ + "addq 8(%rcx),%rdx\n\t" /* info->ProcFormatString + offset */ + "movq (%rcx),%rcx\n\t" /* info->pStubDesc */ + "subq $0x38,%rsp\n\t" + __ASM_CFI(".cfi_adjust_cfa_offset 0x38\n\t") + "movq %xmm1,0x20(%rsp)\n\t" + "movq %xmm2,0x28(%rsp)\n\t" + "movq %xmm3,0x30(%rsp)\n\t" + "leaq 0x18(%rsp),%r9\n\t" /* fpu_args */ + "call " __ASM_NAME("ndr_client_call") "\n\t" + "addq $0x38,%rsp\n\t" + __ASM_CFI(".cfi_adjust_cfa_offset -0x38\n\t") + "ret" ); + +#include "pshpack1.h" +struct thunk +{ + BYTE mov_r10[3]; + DWORD index; + BYTE mov_rax[2]; + void *call_stubless; + BYTE jmp_rax[2]; +}; +#include "poppack.h" + +static const struct thunk thunk_template = +{ + { 0x49, 0xc7, 0xc2 }, 0, /* movq $index,%r10 */ + { 0x48, 0xb8 }, 0, /* movq $call_stubless_func,%rax */ + { 0xff, 0xe0 } /* jmp *%rax */ +}; + +static inline void init_thunk( struct thunk *thunk, unsigned int index ) +{ + *thunk = thunk_template; + thunk->index = index; + thunk->call_stubless = call_stubless_func; +} + +#else /* __i386__ */ + +#warning You must implement stubless proxies for your CPU + +struct thunk +{ + DWORD index; +}; + +static inline void init_thunk( struct thunk *thunk, unsigned int index ) +{ + thunk->index = index; +} + +#endif /* __i386__ */ + #define BLOCK_SIZE 1024 #define MAX_BLOCKS 64 /* 64k methods should be enough for anybody */ @@ -113,13 +197,7 @@ static const struct thunk *allocate_block( unsigned int num ) MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE ); if (!block) return NULL; - for (i = 0; i < BLOCK_SIZE; i++) - { - block[i].push = 0x68; /* pushl */ - block[i].index = BLOCK_SIZE * num + i + 3; - block[i].jmp = 0xe9; /* jmp */ - block[i].handler = (char *)call_stubless_func - (char *)(&block[i].handler + 1); - } + for (i = 0; i < BLOCK_SIZE; i++) init_thunk( &block[i], BLOCK_SIZE * num + i + 3 ); 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 */ @@ -150,16 +228,6 @@ static BOOL fill_stubless_table( IUnknownVtbl *vtbl, DWORD num ) return TRUE; } -#else /* __i386__ */ - -static BOOL fill_stubless_table( IUnknownVtbl *vtbl, DWORD num ) -{ - ERR("stubless proxies are not supported on this architecture\n"); - return FALSE; -} - -#endif /* __i386__ */ - HRESULT StdProxy_Construct(REFIID riid, LPUNKNOWN pUnkOuter, const ProxyFileInfo *ProxyInfo, @@ -191,7 +259,7 @@ HRESULT StdProxy_Construct(REFIID riid, if (!This) return E_OUTOFMEMORY; if (!pUnkOuter) pUnkOuter = (IUnknown *)This; - This->lpVtbl = &StdProxy_Vtbl; + This->IRpcProxyBuffer_iface.lpVtbl = &StdProxy_Vtbl; This->PVtbl = vtbl->Vtbl; /* one reference for the proxy */ This->RefCount = 1; @@ -214,7 +282,7 @@ HRESULT StdProxy_Construct(REFIID riid, } } - *ppProxy = (LPRPCPROXYBUFFER)&This->lpVtbl; + *ppProxy = &This->IRpcProxyBuffer_iface; *ppvObj = &This->PVtbl; IUnknown_AddRef((IUnknown *)*ppvObj); IPSFactoryBuffer_AddRef(pPSFactory); @@ -224,25 +292,11 @@ HRESULT StdProxy_Construct(REFIID riid, return S_OK; } -static void StdProxy_Destruct(LPRPCPROXYBUFFER iface) -{ - ICOM_THIS_MULTI(StdProxyImpl,lpVtbl,iface); - - 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); - HeapFree(GetProcessHeap(),0,This); -} - static HRESULT WINAPI StdProxy_QueryInterface(LPRPCPROXYBUFFER iface, REFIID riid, LPVOID *obj) { - ICOM_THIS_MULTI(StdProxyImpl,lpVtbl,iface); + StdProxyImpl *This = impl_from_IRpcProxyBuffer(iface); TRACE("(%p)->QueryInterface(%s,%p)\n",This,debugstr_guid(riid),obj); if (IsEqualGUID(&IID_IUnknown,riid) || @@ -253,7 +307,7 @@ static HRESULT WINAPI StdProxy_QueryInterface(LPRPCPROXYBUFFER iface, } if (IsEqualGUID(&IID_IRpcProxyBuffer,riid)) { - *obj = &This->lpVtbl; + *obj = &This->IRpcProxyBuffer_iface; InterlockedIncrement(&This->RefCount); return S_OK; } @@ -263,7 +317,7 @@ static HRESULT WINAPI StdProxy_QueryInterface(LPRPCPROXYBUFFER iface, static ULONG WINAPI StdProxy_AddRef(LPRPCPROXYBUFFER iface) { - ICOM_THIS_MULTI(StdProxyImpl,lpVtbl,iface); + StdProxyImpl *This = impl_from_IRpcProxyBuffer(iface); TRACE("(%p)->AddRef()\n",This); return InterlockedIncrement(&This->RefCount); @@ -272,19 +326,29 @@ static ULONG WINAPI StdProxy_AddRef(LPRPCPROXYBUFFER iface) static ULONG WINAPI StdProxy_Release(LPRPCPROXYBUFFER iface) { ULONG refs; - ICOM_THIS_MULTI(StdProxyImpl,lpVtbl,iface); + StdProxyImpl *This = impl_from_IRpcProxyBuffer(iface); TRACE("(%p)->Release()\n",This); refs = InterlockedDecrement(&This->RefCount); if (!refs) - StdProxy_Destruct((LPRPCPROXYBUFFER)&This->lpVtbl); + { + if (This->pChannel) + IRpcProxyBuffer_Disconnect(&This->IRpcProxyBuffer_iface); + + if (This->base_object) IUnknown_Release( This->base_object ); + if (This->base_proxy) IRpcProxyBuffer_Release( This->base_proxy ); + + IPSFactoryBuffer_Release(This->pPSFactory); + HeapFree(GetProcessHeap(),0,This); + } + return refs; } static HRESULT WINAPI StdProxy_Connect(LPRPCPROXYBUFFER iface, LPRPCCHANNELBUFFER pChannel) { - ICOM_THIS_MULTI(StdProxyImpl,lpVtbl,iface); + StdProxyImpl *This = impl_from_IRpcProxyBuffer(iface); TRACE("(%p)->Connect(%p)\n",This,pChannel); This->pChannel = pChannel; @@ -295,7 +359,7 @@ static HRESULT WINAPI StdProxy_Connect(LPRPCPROXYBUFFER iface, static VOID WINAPI StdProxy_Disconnect(LPRPCPROXYBUFFER iface) { - ICOM_THIS_MULTI(StdProxyImpl,lpVtbl,iface); + StdProxyImpl *This = impl_from_IRpcProxyBuffer(iface); TRACE("(%p)->Disconnect()\n",This); if (This->base_proxy) IRpcProxyBuffer_Disconnect( This->base_proxy ); @@ -316,7 +380,7 @@ static const IRpcProxyBufferVtbl StdProxy_Vtbl = static void StdProxy_GetChannel(LPVOID iface, LPRPCCHANNELBUFFER *ppChannel) { - ICOM_THIS_MULTI(StdProxyImpl,PVtbl,iface); + StdProxyImpl *This = impl_from_proxy_obj( iface ); TRACE("(%p)->GetChannel(%p) %s\n",This,ppChannel,This->name); *ppChannel = This->pChannel; @@ -325,7 +389,7 @@ static void StdProxy_GetChannel(LPVOID iface, static void StdProxy_GetIID(LPVOID iface, const IID **ppiid) { - ICOM_THIS_MULTI(StdProxyImpl,PVtbl,iface); + StdProxyImpl *This = impl_from_proxy_obj( iface ); TRACE("(%p)->GetIID(%p) %s\n",This,ppiid,This->name); *ppiid = This->piid; @@ -335,21 +399,21 @@ HRESULT WINAPI IUnknown_QueryInterface_Proxy(LPUNKNOWN iface, REFIID riid, LPVOID *ppvObj) { - ICOM_THIS_MULTI(StdProxyImpl,PVtbl,iface); + StdProxyImpl *This = impl_from_proxy_obj( iface ); TRACE("(%p)->QueryInterface(%s,%p) %s\n",This,debugstr_guid(riid),ppvObj,This->name); return IUnknown_QueryInterface(This->pUnkOuter,riid,ppvObj); } ULONG WINAPI IUnknown_AddRef_Proxy(LPUNKNOWN iface) { - ICOM_THIS_MULTI(StdProxyImpl,PVtbl,iface); + StdProxyImpl *This = impl_from_proxy_obj( iface ); TRACE("(%p)->AddRef() %s\n",This,This->name); return IUnknown_AddRef(This->pUnkOuter); } ULONG WINAPI IUnknown_Release_Proxy(LPUNKNOWN iface) { - ICOM_THIS_MULTI(StdProxyImpl,PVtbl,iface); + StdProxyImpl *This = impl_from_proxy_obj( iface ); TRACE("(%p)->Release() %s\n",This,This->name); return IUnknown_Release(This->pUnkOuter); } @@ -483,3 +547,24 @@ CreateProxyFromTypeInfo( LPTYPEINFO pTypeInfo, LPUNKNOWN pUnkOuter, REFIID riid, } return E_NOTIMPL; } + +HRESULT WINAPI +CreateStubFromTypeInfo(ITypeInfo *pTypeInfo, REFIID riid, IUnknown *pUnkServer, + IRpcStubBuffer **ppStub ) +{ + typedef INT (WINAPI *MessageBoxA)(HWND,LPCSTR,LPCSTR,UINT); + HMODULE hUser32 = LoadLibraryA("user32"); + MessageBoxA pMessageBoxA = (void *)GetProcAddress(hUser32, "MessageBoxA"); + + FIXME("%p %s %p %p\n", pTypeInfo, debugstr_guid(riid), pUnkServer, ppStub); + if (pMessageBoxA) + { + pMessageBoxA(NULL, + "The native implementation of OLEAUT32.DLL cannot be used " + "with Wine's RPCRT4.DLL. Remove OLEAUT32.DLL and try again.\n", + "Wine: Unimplemented CreateProxyFromTypeInfo", + 0x10); + ExitProcess(1); + } + return E_NOTIMPL; +} diff --git a/reactos/dll/win32/rpcrt4/cpsf.c b/reactos/dll/win32/rpcrt4/cpsf.c index d2efa012581..bf04bb85de3 100644 --- a/reactos/dll/win32/rpcrt4/cpsf.c +++ b/reactos/dll/win32/rpcrt4/cpsf.c @@ -242,7 +242,7 @@ HRESULT WINAPI NdrDllRegisterProxy(HMODULE hDll, TRACE("(%p,%p,%s)\n", hDll, pProxyFileList, debugstr_guid(pclsid)); //if (!hDll) return E_HANDLE; - if (!pProxyFileList || !*pProxyFileList) return E_NOINTERFACE; + if (!*pProxyFileList) return E_NOINTERFACE; if (pclsid) format_clsid( clsid, pclsid ); diff --git a/reactos/dll/win32/rpcrt4/cpsf.h b/reactos/dll/win32/rpcrt4/cpsf.h index 9cc046ff7ca..964fb4551fe 100644 --- a/reactos/dll/win32/rpcrt4/cpsf.h +++ b/reactos/dll/win32/rpcrt4/cpsf.h @@ -23,23 +23,23 @@ HRESULT StdProxy_Construct(REFIID riid, LPUNKNOWN pUnkOuter, const ProxyFileInfo *ProxyInfo, int Index, LPPSFACTORYBUFFER pPSFactory, LPRPCPROXYBUFFER *ppProxy, - LPVOID *ppvObj); + LPVOID *ppvObj) DECLSPEC_HIDDEN; HRESULT CStdStubBuffer_Construct(REFIID riid, LPUNKNOWN pUnkServer, PCInterfaceName name, CInterfaceStubVtbl *vtbl, LPPSFACTORYBUFFER pPSFactory, - LPRPCSTUBBUFFER *ppStub); + LPRPCSTUBBUFFER *ppStub) DECLSPEC_HIDDEN; HRESULT CStdStubBuffer_Delegating_Construct(REFIID riid, LPUNKNOWN pUnkServer, PCInterfaceName name, CInterfaceStubVtbl *vtbl, REFIID delegating_iid, - LPPSFACTORYBUFFER pPSFactory, LPRPCSTUBBUFFER *ppStub); + LPPSFACTORYBUFFER pPSFactory, LPRPCSTUBBUFFER *ppStub) DECLSPEC_HIDDEN; -const MIDL_SERVER_INFO *CStdStubBuffer_GetServerInfo(IRpcStubBuffer *iface); +const MIDL_SERVER_INFO *CStdStubBuffer_GetServerInfo(IRpcStubBuffer *iface) DECLSPEC_HIDDEN; -const IRpcStubBufferVtbl CStdStubBuffer_Vtbl; -const IRpcStubBufferVtbl CStdStubBuffer_Delegating_Vtbl; +extern const IRpcStubBufferVtbl CStdStubBuffer_Vtbl DECLSPEC_HIDDEN; +extern const IRpcStubBufferVtbl CStdStubBuffer_Delegating_Vtbl DECLSPEC_HIDDEN; -BOOL fill_delegated_proxy_table(IUnknownVtbl *vtbl, DWORD num); -HRESULT create_proxy(REFIID iid, IUnknown *pUnkOuter, IRpcProxyBuffer **pproxy, void **ppv); -HRESULT create_stub(REFIID iid, IUnknown *pUnk, IRpcStubBuffer **ppstub); +BOOL fill_delegated_proxy_table(IUnknownVtbl *vtbl, DWORD num) DECLSPEC_HIDDEN; +HRESULT create_proxy(REFIID iid, IUnknown *pUnkOuter, IRpcProxyBuffer **pproxy, void **ppv) DECLSPEC_HIDDEN; +HRESULT create_stub(REFIID iid, IUnknown *pUnk, IRpcStubBuffer **ppstub) DECLSPEC_HIDDEN; #endif /* __WINE_CPSF_H */ diff --git a/reactos/dll/win32/rpcrt4/cstub.c b/reactos/dll/win32/rpcrt4/cstub.c index 95ac1d89af2..74801f69b70 100644 --- a/reactos/dll/win32/rpcrt4/cstub.c +++ b/reactos/dll/win32/rpcrt4/cstub.c @@ -137,27 +137,54 @@ static ULONG WINAPI delegating_Release(IUnknown *pUnk) return 1; } -#if defined(__i386__) - /* The idea here is to replace the first param on the stack ie. This (which will point to cstdstubbuffer_delegating_t) with This->stub_buffer.pvServerObject and then jump to the relevant offset in This->stub_buffer.pvServerObject's vtbl. */ +#ifdef __i386__ + #include "pshpack1.h" typedef struct { - DWORD mov1; /* mov 0x4(%esp), %eax 8b 44 24 04 */ - WORD mov2; /* mov 0x10(%eax), %eax 8b 40 */ - BYTE sixteen; /* 10 */ - DWORD mov3; /* mov %eax, 0x4(%esp) 89 44 24 04 */ - WORD mov4; /* mov (%eax), %eax 8b 00 */ - WORD mov5; /* mov offset(%eax), %eax 8b 80 */ - DWORD offset; /* xx xx xx xx */ - WORD jmp; /* jmp *%eax ff e0 */ - BYTE pad[3]; /* lea 0x0(%esi), %esi 8d 76 00 */ + BYTE mov1[4]; /* mov 0x4(%esp),%eax 8b 44 24 04 */ + BYTE mov2[3]; /* mov 0x10(%eax),%eax 8b 40 10 */ + BYTE mov3[4]; /* mov %eax,0x4(%esp) 89 44 24 04 */ + BYTE mov4[2]; /* mov (%eax),%eax 8b 00 */ + BYTE mov5[2]; /* jmp *offset(%eax) ff a0 offset */ + DWORD offset; + BYTE pad[1]; /* nop 90 */ } vtbl_method_t; #include "poppack.h" +static const BYTE opcodes[20] = { 0x8b, 0x44, 0x24, 0x04, 0x8b, 0x40, 0x10, 0x89, 0x44, 0x24, 0x04, + 0x8b, 0x00, 0xff, 0xa0, 0, 0, 0, 0, 0x90 }; + +#elif defined(__x86_64__) + +#include "pshpack1.h" +typedef struct +{ + BYTE mov1[4]; /* movq 0x20(%rcx),%rcx 48 8b 49 20 */ + BYTE mov2[3]; /* movq (%rcx),%rax 48 8b 01 */ + BYTE jmp[2]; /* jmp *offset(%rax) ff a0 offset */ + DWORD offset; + BYTE pad[3]; /* lea 0x0(%rsi),%rsi 48 8d 36 */ +} vtbl_method_t; +#include "poppack.h" + +static const BYTE opcodes[16] = { 0x48, 0x8b, 0x49, 0x20, 0x48, 0x8b, 0x01, + 0xff, 0xa0, 0, 0, 0, 0, 0x48, 0x8d, 0x36 }; +#else + +#warning You must implement delegated proxies/stubs for your CPU +typedef struct +{ + DWORD offset; +} vtbl_method_t; +static const BYTE opcodes[1]; + +#endif + #define BLOCK_SIZE 1024 #define MAX_BLOCKS 64 /* 64k methods should be enough for anybody */ @@ -174,17 +201,8 @@ static const vtbl_method_t *allocate_block( unsigned int num ) 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; + memcpy( &block[i], opcodes, sizeof(opcodes) ); + block[i].offset = (BLOCK_SIZE * num + i + 3) * sizeof(void *); } VirtualProtect( block, BLOCK_SIZE * sizeof(*block), PAGE_EXECUTE_READ, NULL ); prev = InterlockedCompareExchangePointer( (void **)&method_blocks[num], block, NULL ); @@ -241,22 +259,6 @@ BOOL fill_delegated_proxy_table(IUnknownVtbl *vtbl, DWORD num) return TRUE; } -#else /* __i386__ */ - -static BOOL fill_delegated_stub_table(IUnknownVtbl *vtbl, 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) { IUnknownVtbl *ret; diff --git a/reactos/dll/win32/rpcrt4/msvc.S b/reactos/dll/win32/rpcrt4/msvc.S index b3d655c3a92..9eb1d99c06f 100644 --- a/reactos/dll/win32/rpcrt4/msvc.S +++ b/reactos/dll/win32/rpcrt4/msvc.S @@ -3,16 +3,30 @@ .code32 -EXTERN _ObjectStubless@4:PROC +EXTERN _ndr_client_call:PROC PUBLIC _call_stubless_func _call_stubless_func: - push esp /* pointer to index */ - call _ObjectStubless@4 - pop edx /* args size */ - mov ecx, [esp] /* return address */ + mov ecx,[esp+4] /* This Pointer */ + mov ecx,[ecx] /* This->lpVtbl */ + mov ecx,[ecx-8] /* MIDL_STUBLESS_PROXY_INFO */ + mov edx,[ecx-8] /* Info->FormatStringOffset */ + xor edx, edx + mov dx,[edx+eax*2] /* FormatStringOffset[index] */ + add edx,[ecx+4] /* info->ProcFormatString + offset */ + xor eax, eax + mov ax, [edx+8] /* arguments size */ + push eax + lea eax, [esp+8] /* &This */ + push eax + push edx /* format string */ + push [ecx] /* info->pstubdesc */ + call _ndr_client_call + lea esp, [esp+12] + pop edx /* arguments size */ + mov ecx, [esp] /* return address */ add esp, edx jmp ecx -END +END \ No newline at end of file diff --git a/reactos/dll/win32/rpcrt4/ndr_es.c b/reactos/dll/win32/rpcrt4/ndr_es.c index 52200dc3e3e..cd0967ddea9 100644 --- a/reactos/dll/win32/rpcrt4/ndr_es.c +++ b/reactos/dll/win32/rpcrt4/ndr_es.c @@ -329,9 +329,10 @@ void WINAPIV NdrMesProcEncodeDecode(handle_t Handle, const MIDL_STUB_DESC * pStu unsigned short stack_size; /* header for procedure string */ const NDR_PROC_HEADER *pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0]; - /* the value to return to the client from the remote procedure */ - LONG_PTR RetVal = 0; const RPC_CLIENT_INTERFACE *client_interface; + __ms_va_list args; + unsigned int number_of_params; + ULONG_PTR arg_buffer[256]; TRACE("Handle %p, pStubDesc %p, pFormat %p, ...\n", Handle, pStubDesc, pFormat); @@ -396,29 +397,26 @@ void WINAPIV NdrMesProcEncodeDecode(handle_t Handle, const MIDL_STUB_DESC * pStu TRACE("MIDL stub version = 0x%x\n", pStubDesc->MIDLVersion); /* needed for conformance of top-level objects */ -#ifdef __i386__ - pEsMsg->StubMsg.StackTop = *(unsigned char **)(&pFormat+1); -#else -# warning Stack not retrieved for your CPU architecture -#endif + __ms_va_start( args, pFormat ); + pEsMsg->StubMsg.StackTop = va_arg( args, unsigned char * ); + __ms_va_end( args ); + + pFormat = convert_old_args( &pEsMsg->StubMsg, pFormat, stack_size, FALSE, + arg_buffer, sizeof(arg_buffer), &number_of_params ); switch (pEsMsg->Operation) { case MES_ENCODE: pEsMsg->StubMsg.BufferLength = mes_proc_header_buffer_size(); - client_do_args_old_format(&pEsMsg->StubMsg, pFormat, PROXY_CALCSIZE, - pEsMsg->StubMsg.StackTop, stack_size, (unsigned char *)&RetVal, - FALSE /* object_proc */, TRUE /* ignore_retval */); + client_do_args( &pEsMsg->StubMsg, pFormat, STUBLESS_CALCSIZE, NULL, number_of_params, NULL ); pEsMsg->ByteCount = pEsMsg->StubMsg.BufferLength - mes_proc_header_buffer_size(); es_data_alloc(pEsMsg, pEsMsg->StubMsg.BufferLength); mes_proc_header_marshal(pEsMsg); - client_do_args_old_format(&pEsMsg->StubMsg, pFormat, PROXY_MARSHAL, - pEsMsg->StubMsg.StackTop, stack_size, (unsigned char *)&RetVal, - FALSE /* object_proc */, TRUE /* ignore_retval */); + client_do_args( &pEsMsg->StubMsg, pFormat, STUBLESS_MARSHAL, NULL, number_of_params, NULL ); es_data_write(pEsMsg, pEsMsg->ByteCount); break; @@ -427,9 +425,7 @@ void WINAPIV NdrMesProcEncodeDecode(handle_t Handle, const MIDL_STUB_DESC * pStu es_data_read(pEsMsg, pEsMsg->ByteCount); - client_do_args_old_format(&pEsMsg->StubMsg, pFormat, PROXY_UNMARSHAL, - pEsMsg->StubMsg.StackTop, stack_size, (unsigned char *)&RetVal, - FALSE /* object_proc */, TRUE /* ignore_retval */); + client_do_args( &pEsMsg->StubMsg, pFormat, STUBLESS_UNMARSHAL, NULL, number_of_params, NULL ); break; default: RpcRaiseException(RPC_S_INTERNAL_ERROR); @@ -446,6 +442,12 @@ void RPC_ENTRY NdrMesTypeDecode2(handle_t Handle, const MIDL_TYPE_PICKLING_INFO FIXME("(%p, %p, %p, %p, %p)\n", Handle, pPicklingInfo, pStubDesc, pFormatString, pObject); } +void RPC_ENTRY NdrMesTypeEncode2(handle_t Handle, const MIDL_TYPE_PICKLING_INFO *pPicklingInfo, + const MIDL_STUB_DESC *pStubDesc, PFORMAT_STRING pFormatString, const void *pObject) +{ + FIXME("(%p, %p, %p, %p, %p)\n", Handle, pPicklingInfo, pStubDesc, pFormatString, pObject); +} + void RPC_ENTRY NdrMesTypeFree2(handle_t Handle, const MIDL_TYPE_PICKLING_INFO *pPicklingInfo, const MIDL_STUB_DESC *pStubDesc, PFORMAT_STRING pFormatString, void *pObject) { diff --git a/reactos/dll/win32/rpcrt4/ndr_marshall.c b/reactos/dll/win32/rpcrt4/ndr_marshall.c index 839a4cad882..85d0a3cd85b 100644 --- a/reactos/dll/win32/rpcrt4/ndr_marshall.c +++ b/reactos/dll/win32/rpcrt4/ndr_marshall.c @@ -27,6 +27,7 @@ * - Checks for integer addition overflow in user marshall functions */ +#include #include #include #include @@ -91,17 +92,23 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole); LITTLE_ENDIAN_UINT32_READ(pchar) #endif -/* _Align must be the desired alignment, - * e.g. ALIGN_LENGTH(len, 4) to align on a dword boundary. */ -#define ALIGNED_LENGTH(_Len, _Align) (((_Len)+(_Align)-1)&~((_Align)-1)) -#define ALIGNED_POINTER(_Ptr, _Align) ((LPVOID)ALIGNED_LENGTH((ULONG_PTR)(_Ptr), _Align)) -#define ALIGN_LENGTH(_Len, _Align) _Len = ALIGNED_LENGTH(_Len, _Align) -#define ALIGN_POINTER(_Ptr, _Align) _Ptr = ALIGNED_POINTER(_Ptr, _Align) -#define ALIGN_POINTER_CLEAR(_Ptr, _Align) \ - do { \ - memset((_Ptr), 0, ((_Align) - (ULONG_PTR)(_Ptr)) & ((_Align) - 1)); \ - ALIGN_POINTER(_Ptr, _Align); \ - } while(0) +static inline void align_length( ULONG *len, unsigned int align ) +{ + *len = (*len + align - 1) & ~(align - 1); +} + +static inline void align_pointer( unsigned char **ptr, unsigned int align ) +{ + ULONG_PTR mask = align - 1; + *ptr = (unsigned char *)(((ULONG_PTR)*ptr + mask) & ~mask); +} + +static inline void align_pointer_clear( unsigned char **ptr, unsigned int align ) +{ + ULONG_PTR mask = align - 1; + memset( *ptr, 0, (align - (ULONG_PTR)*ptr) & mask ); + *ptr = (unsigned char *)(((ULONG_PTR)*ptr + mask) & ~mask); +} #define STD_OVERFLOW_CHECK(_Msg) do { \ TRACE("buffer=%d/%d\n", (ULONG)(_Msg->Buffer - (unsigned char *)_Msg->RpcMsg->Buffer), _Msg->BufferLength); \ @@ -133,6 +140,27 @@ static void WINAPI NdrRangeFree(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STR static ULONG WINAPI NdrByteCountPointerMemorySize(PMIDL_STUB_MESSAGE, PFORMAT_STRING); +static unsigned char * ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat, + PFORMAT_STRING pPointer); +static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat, + PFORMAT_STRING pPointer); +static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat, + PFORMAT_STRING pPointer, + unsigned char fMustAlloc); +static ULONG ComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat, + PFORMAT_STRING pPointer); +static unsigned char * ComplexFree(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat, + PFORMAT_STRING pPointer); + const NDR_MARSHALL NdrMarshaller[NDR_TABLE_SIZE] = { 0, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, @@ -377,7 +405,7 @@ void * WINAPI NdrAllocate(MIDL_STUB_MESSAGE *pStubMsg, SIZE_T len) void *p; NDR_MEMORY_LIST *mem_list; - aligned_len = ALIGNED_LENGTH(len, 8); + aligned_len = (len + 7) & ~7; adjusted_len = aligned_len + sizeof(NDR_MEMORY_LIST); /* check for overflow */ if (adjusted_len < len) @@ -414,7 +442,7 @@ static inline BOOL IsConformanceOrVariancePresent(PFORMAT_STRING pFormat) static PFORMAT_STRING ReadConformance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat) { - ALIGN_POINTER(pStubMsg->Buffer, 4); + align_pointer(&pStubMsg->Buffer, 4); if (pStubMsg->Buffer + 4 > pStubMsg->BufferEnd) RpcRaiseException(RPC_X_BAD_STUB_DATA); pStubMsg->MaxCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer); @@ -435,7 +463,7 @@ static inline PFORMAT_STRING ReadVariance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_S goto done; } - ALIGN_POINTER(pStubMsg->Buffer, 4); + align_pointer(&pStubMsg->Buffer, 4); if (pStubMsg->Buffer + 8 > pStubMsg->BufferEnd) RpcRaiseException(RPC_X_BAD_STUB_DATA); pStubMsg->Offset = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer); @@ -464,7 +492,7 @@ done: /* writes the conformance value to the buffer */ static inline void WriteConformance(MIDL_STUB_MESSAGE *pStubMsg) { - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4); + align_pointer_clear(&pStubMsg->Buffer, 4); if (pStubMsg->Buffer + 4 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) RpcRaiseException(RPC_X_BAD_STUB_DATA); NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->MaxCount); @@ -474,7 +502,7 @@ static inline void WriteConformance(MIDL_STUB_MESSAGE *pStubMsg) /* writes the variance values to the buffer */ static inline void WriteVariance(MIDL_STUB_MESSAGE *pStubMsg) { - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4); + align_pointer_clear(&pStubMsg->Buffer, 4); if (pStubMsg->Buffer + 8 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) RpcRaiseException(RPC_X_BAD_STUB_DATA); NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->Offset); @@ -486,7 +514,7 @@ static inline void WriteVariance(MIDL_STUB_MESSAGE *pStubMsg) /* requests buffer space for the conformance value */ static inline void SizeConformance(MIDL_STUB_MESSAGE *pStubMsg) { - ALIGN_LENGTH(pStubMsg->BufferLength, 4); + align_length(&pStubMsg->BufferLength, 4); if (pStubMsg->BufferLength + 4 < pStubMsg->BufferLength) RpcRaiseException(RPC_X_BAD_STUB_DATA); pStubMsg->BufferLength += 4; @@ -495,7 +523,7 @@ static inline void SizeConformance(MIDL_STUB_MESSAGE *pStubMsg) /* requests buffer space for the variance values */ static inline void SizeVariance(MIDL_STUB_MESSAGE *pStubMsg) { - ALIGN_LENGTH(pStubMsg->BufferLength, 4); + align_length(&pStubMsg->BufferLength, 4); if (pStubMsg->BufferLength + 8 < pStubMsg->BufferLength) RpcRaiseException(RPC_X_BAD_STUB_DATA); pStubMsg->BufferLength += 8; @@ -508,7 +536,7 @@ PFORMAT_STRING ComputeConformanceOrVariance( BYTE dtype = pFormat[0] & 0xf; short ofs = *(const short *)&pFormat[2]; LPVOID ptr = NULL; - DWORD data = 0; + ULONG_PTR data = 0; if (!IsConformanceOrVariancePresent(pFormat)) { /* null descriptor */ @@ -537,7 +565,7 @@ PFORMAT_STRING ComputeConformanceOrVariance( break; case RPC_FC_CONSTANT_CONFORMANCE: data = ofs | ((DWORD)pFormat[1] << 16); - TRACE("constant conformance, val=%d\n", data); + TRACE("constant conformance, val=%ld\n", data); *pCount = data; goto finish_conf; case RPC_FC_TOP_LEVEL_MULTID_CONFORMANCE: @@ -562,6 +590,8 @@ PFORMAT_STRING ComputeConformanceOrVariance( case RPC_FC_CALLBACK: { unsigned char *old_stack_top = pStubMsg->StackTop; + ULONG_PTR max_count, old_max_count = pStubMsg->MaxCount; + pStubMsg->StackTop = ptr; /* ofs is index into StubDesc->apfnExprEval */ @@ -571,7 +601,9 @@ PFORMAT_STRING ComputeConformanceOrVariance( pStubMsg->StackTop = old_stack_top; /* the callback function always stores the computed value in MaxCount */ - *pCount = pStubMsg->MaxCount; + max_count = pStubMsg->MaxCount; + pStubMsg->MaxCount = old_max_count; + *pCount = max_count; goto finish_conf; } default: @@ -598,11 +630,14 @@ PFORMAT_STRING ComputeConformanceOrVariance( case RPC_FC_USMALL: data = *(UCHAR*)ptr; break; + case RPC_FC_HYPER: + data = *(ULONGLONG *)ptr; + break; default: FIXME("unknown conformance data type %x\n", dtype); goto done_conf_grab; } - TRACE("dereferenced data type %x at %p, got %d\n", dtype, ptr, data); + TRACE("dereferenced data type %x at %p, got %ld\n", dtype, ptr, data); done_conf_grab: switch (pFormat[1]) { @@ -638,14 +673,16 @@ finish_conf: static inline PFORMAT_STRING SkipConformance(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat) { - if (IsConformanceOrVariancePresent(pFormat)) - { if (pStubMsg->fHasNewCorrDesc) pFormat += 6; else pFormat += 4; - } - return pFormat; + return pFormat; +} + +static inline PFORMAT_STRING SkipVariance(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat) +{ + return SkipConformance( pStubMsg, pFormat ); } /* multiply two numbers together, raising an RPC_S_INVALID_BOUND exception if @@ -889,7 +926,6 @@ static void PointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, } if (pointer_needs_unmarshaling) { - unsigned char *base_ptr_val = *pPointer; unsigned char **current_ptr = pPointer; if (pStubMsg->IsClient) { TRACE("client\n"); @@ -902,7 +938,7 @@ static void PointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, if (!fMustAlloc) { if (pSrcPointer) { TRACE("setting *pPointer to %p\n", pSrcPointer); - *pPointer = base_ptr_val = pSrcPointer; + *pPointer = pSrcPointer; } else fMustAlloc = TRUE; } @@ -915,7 +951,6 @@ static void PointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, if (attr & RPC_FC_P_DEREF) { fMustAlloc = TRUE; } else { - base_ptr_val = NULL; *current_ptr = NULL; } } @@ -925,7 +960,7 @@ static void PointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, if (attr & RPC_FC_P_DEREF) { if (fMustAlloc) { - base_ptr_val = NdrAllocate(pStubMsg, sizeof(void *)); + unsigned char *base_ptr_val = NdrAllocate(pStubMsg, sizeof(void *)); *pPointer = base_ptr_val; current_ptr = (unsigned char **)base_ptr_val; } else @@ -1047,7 +1082,7 @@ static ULONG PointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg, } if (attr & RPC_FC_P_DEREF) { - ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(void*)); + align_length(&pStubMsg->MemorySize, sizeof(void*)); pStubMsg->MemorySize += sizeof(void*); TRACE("deref\n"); } @@ -1482,7 +1517,7 @@ unsigned char * WINAPI NdrPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg, * the buffer, and shouldn't write any additional pointer data to the wire */ if (*pFormat != RPC_FC_RP) { - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4); + align_pointer_clear(&pStubMsg->Buffer, 4); Buffer = pStubMsg->Buffer; safe_buffer_increment(pStubMsg, 4); } @@ -1524,7 +1559,7 @@ unsigned char * WINAPI NdrPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, * as that is used by embedded pointers which already handle the incrementing * the buffer, and shouldn't read any additional pointer data from the * buffer */ - ALIGN_POINTER(pStubMsg->Buffer, 4); + align_pointer(&pStubMsg->Buffer, 4); Buffer = pStubMsg->Buffer; safe_buffer_increment(pStubMsg, 4); } @@ -1548,7 +1583,7 @@ void WINAPI NdrPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg, * length, and shouldn't write anything more to the wire */ if (*pFormat != RPC_FC_RP) { - ALIGN_LENGTH(pStubMsg->BufferLength, 4); + align_length(&pStubMsg->BufferLength, 4); safe_buffer_length_increment(pStubMsg, 4); } @@ -1564,10 +1599,10 @@ ULONG WINAPI NdrPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *Buffer = pStubMsg->Buffer; if (*pFormat != RPC_FC_RP) { - ALIGN_POINTER(pStubMsg->Buffer, 4); + align_pointer(&pStubMsg->Buffer, 4); safe_buffer_increment(pStubMsg, 4); } - ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(void *)); + align_length(&pStubMsg->MemorySize, sizeof(void *)); return PointerMemorySize(pStubMsg, Buffer, pFormat); } @@ -1604,7 +1639,7 @@ void WINAPI NdrSimpleTypeUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* unsigned char FormatChar ) { #define BASE_TYPE_UNMARSHALL(type) \ - ALIGN_POINTER(pStubMsg->Buffer, sizeof(type)); \ + align_pointer(&pStubMsg->Buffer, sizeof(type)); \ TRACE("pMemory: %p\n", pMemory); \ *(type *)pMemory = *(type *)pStubMsg->Buffer; \ pStubMsg->Buffer += sizeof(type); @@ -1644,13 +1679,27 @@ void WINAPI NdrSimpleTypeUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* TRACE("value: %s\n", wine_dbgstr_longlong(*(ULONGLONG *)pMemory)); break; case RPC_FC_ENUM16: - ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT)); + align_pointer(&pStubMsg->Buffer, sizeof(USHORT)); TRACE("pMemory: %p\n", pMemory); /* 16-bits on the wire, but int in memory */ *(UINT *)pMemory = *(USHORT *)pStubMsg->Buffer; pStubMsg->Buffer += sizeof(USHORT); TRACE("value: 0x%08x\n", *(UINT *)pMemory); break; + case RPC_FC_INT3264: + align_pointer(&pStubMsg->Buffer, sizeof(INT)); + /* 32-bits on the wire, but int_ptr in memory */ + *(INT_PTR *)pMemory = *(INT *)pStubMsg->Buffer; + pStubMsg->Buffer += sizeof(INT); + TRACE("value: 0x%08lx\n", *(INT_PTR *)pMemory); + break; + case RPC_FC_UINT3264: + align_pointer(&pStubMsg->Buffer, sizeof(UINT)); + /* 32-bits on the wire, but int_ptr in memory */ + *(UINT_PTR *)pMemory = *(UINT *)pStubMsg->Buffer; + pStubMsg->Buffer += sizeof(UINT); + TRACE("value: 0x%08lx\n", *(UINT_PTR *)pMemory); + break; case RPC_FC_IGNORE: break; default: @@ -1669,7 +1718,7 @@ unsigned char * WINAPI NdrSimpleStructMarshall(PMIDL_STUB_MESSAGE pStubMsg, unsigned size = *(const WORD*)(pFormat+2); TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pFormat[1] + 1); + align_pointer_clear(&pStubMsg->Buffer, pFormat[1] + 1); pStubMsg->BufferMark = pStubMsg->Buffer; safe_copy_to_buffer(pStubMsg, pMemory, size); @@ -1692,7 +1741,7 @@ unsigned char * WINAPI NdrSimpleStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *saved_buffer; TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); - ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1); + align_pointer(&pStubMsg->Buffer, pFormat[1] + 1); if (fMustAlloc) *ppMemory = NdrAllocate(pStubMsg, size); @@ -1725,7 +1774,7 @@ void WINAPI NdrSimpleStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned size = *(const WORD*)(pFormat+2); TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1); + align_length(&pStubMsg->BufferLength, pFormat[1] + 1); safe_buffer_length_increment(pStubMsg, size); if (pFormat[0] != RPC_FC_STRUCT) @@ -1742,7 +1791,7 @@ ULONG WINAPI NdrSimpleStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg, TRACE("(%p,%p)\n", pStubMsg, pFormat); - ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1); + align_pointer(&pStubMsg->Buffer, pFormat[1] + 1); pStubMsg->MemorySize += size; safe_buffer_increment(pStubMsg, size); @@ -1769,6 +1818,8 @@ static inline void array_compute_and_size_conformance( unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat) { + DWORD count; + switch (fc) { case RPC_FC_CARRAY: @@ -1800,6 +1851,13 @@ static inline void array_compute_and_size_conformance( SizeConformance(pStubMsg); break; + case RPC_FC_BOGUS_ARRAY: + count = *(const WORD *)(pFormat + 2); + pFormat += 4; + if (IsConformanceOrVariancePresent(pFormat)) SizeConformance(pStubMsg); + pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, count); + pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount); + break; default: ERR("unknown array format 0x%x\n", fc); RpcRaiseException(RPC_X_BAD_STUB_DATA); @@ -1810,7 +1868,7 @@ static inline void array_buffer_size( unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat, unsigned char fHasPointers) { - DWORD size; + DWORD i, size; DWORD esize; unsigned char alignment; @@ -1822,7 +1880,7 @@ static inline void array_buffer_size( pFormat = SkipConformance(pStubMsg, pFormat + 4); - ALIGN_LENGTH(pStubMsg->BufferLength, alignment); + align_length(&pStubMsg->BufferLength, alignment); size = safe_multiply(esize, pStubMsg->MaxCount); /* conformance value plus array */ @@ -1836,11 +1894,11 @@ static inline void array_buffer_size( alignment = pFormat[1] + 1; pFormat = SkipConformance(pStubMsg, pFormat + 4); - pFormat = SkipConformance(pStubMsg, pFormat); + pFormat = SkipVariance(pStubMsg, pFormat); SizeVariance(pStubMsg); - ALIGN_LENGTH(pStubMsg->BufferLength, alignment); + align_length(&pStubMsg->BufferLength, alignment); size = safe_multiply(esize, pStubMsg->ActualCount); safe_buffer_length_increment(pStubMsg, size); @@ -1860,6 +1918,18 @@ static inline void array_buffer_size( size = safe_multiply(esize, pStubMsg->ActualCount); safe_buffer_length_increment(pStubMsg, size); break; + case RPC_FC_BOGUS_ARRAY: + alignment = pFormat[1] + 1; + pFormat = SkipConformance(pStubMsg, pFormat + 4); + if (IsConformanceOrVariancePresent(pFormat)) SizeVariance(pStubMsg); + pFormat = SkipVariance(pStubMsg, pFormat); + + align_length(&pStubMsg->BufferLength, alignment); + + size = pStubMsg->ActualCount; + for (i = 0; i < size; i++) + pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, NULL); + break; default: ERR("unknown array format 0x%x\n", fc); RpcRaiseException(RPC_X_BAD_STUB_DATA); @@ -1870,6 +1940,9 @@ static inline void array_compute_and_write_conformance( unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat) { + ULONG def; + BOOL conformance_present; + switch (fc) { case RPC_FC_CARRAY: @@ -1900,6 +1973,14 @@ static inline void array_compute_and_write_conformance( pStubMsg->Offset = 0; WriteConformance(pStubMsg); break; + case RPC_FC_BOGUS_ARRAY: + def = *(const WORD *)(pFormat + 2); + pFormat += 4; + conformance_present = IsConformanceOrVariancePresent(pFormat); + pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def); + pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount); + if (conformance_present) WriteConformance(pStubMsg); + break; default: ERR("unknown array format 0x%x\n", fc); RpcRaiseException(RPC_X_BAD_STUB_DATA); @@ -1910,7 +1991,7 @@ static inline void array_write_variance_and_marshall( unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat, unsigned char fHasPointers) { - DWORD size; + DWORD i, size; DWORD esize; unsigned char alignment; @@ -1922,7 +2003,7 @@ static inline void array_write_variance_and_marshall( pFormat = SkipConformance(pStubMsg, pFormat + 4); - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment); + align_pointer_clear(&pStubMsg->Buffer, alignment); size = safe_multiply(esize, pStubMsg->MaxCount); if (fHasPointers) @@ -1936,14 +2017,12 @@ static inline void array_write_variance_and_marshall( esize = *(const WORD*)(pFormat+2); alignment = pFormat[1] + 1; - /* conformance */ pFormat = SkipConformance(pStubMsg, pFormat + 4); - /* variance */ - pFormat = SkipConformance(pStubMsg, pFormat); + pFormat = SkipVariance(pStubMsg, pFormat); WriteVariance(pStubMsg); - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment); + align_pointer_clear(&pStubMsg->Buffer, alignment); size = safe_multiply(esize, pStubMsg->ActualCount); @@ -1966,6 +2045,18 @@ static inline void array_write_variance_and_marshall( size = safe_multiply(esize, pStubMsg->ActualCount); safe_copy_to_buffer(pStubMsg, pMemory, size); /* the string itself */ break; + case RPC_FC_BOGUS_ARRAY: + alignment = pFormat[1] + 1; + pFormat = SkipConformance(pStubMsg, pFormat + 4); + if (IsConformanceOrVariancePresent(pFormat)) WriteVariance(pStubMsg); + pFormat = SkipVariance(pStubMsg, pFormat); + + align_pointer_clear(&pStubMsg->Buffer, alignment); + + size = pStubMsg->ActualCount; + for (i = 0; i < size; i++) + pMemory = ComplexMarshall(pStubMsg, pMemory, pFormat, NULL); + break; default: ERR("unknown array format 0x%x\n", fc); RpcRaiseException(RPC_X_BAD_STUB_DATA); @@ -1975,7 +2066,7 @@ static inline void array_write_variance_and_marshall( static inline ULONG array_read_conformance( unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat) { - DWORD esize; + DWORD def, esize; switch (fc) { @@ -1999,6 +2090,19 @@ static inline ULONG array_read_conformance( else ReadConformance(pStubMsg, NULL); return safe_multiply(esize, pStubMsg->MaxCount); + case RPC_FC_BOGUS_ARRAY: + def = *(const WORD *)(pFormat + 2); + pFormat += 4; + if (IsConformanceOrVariancePresent(pFormat)) pFormat = ReadConformance(pStubMsg, pFormat); + else + { + pStubMsg->MaxCount = def; + pFormat = SkipConformance( pStubMsg, pFormat ); + } + pFormat = SkipVariance( pStubMsg, pFormat ); + + esize = ComplexStructSize(pStubMsg, pFormat); + return safe_multiply(pStubMsg->MaxCount, esize); default: ERR("unknown array format 0x%x\n", fc); RpcRaiseException(RPC_X_BAD_STUB_DATA); @@ -2013,8 +2117,8 @@ static inline ULONG array_read_variance_and_unmarshall( ULONG bufsize, memsize; WORD esize; unsigned char alignment; - unsigned char *saved_buffer; - ULONG offset; + unsigned char *saved_buffer, *pMemory; + ULONG i, offset, count; switch (fc) { @@ -2026,7 +2130,7 @@ static inline ULONG array_read_variance_and_unmarshall( pFormat = SkipConformance(pStubMsg, pFormat + 4); - ALIGN_POINTER(pStubMsg->Buffer, alignment); + align_pointer(&pStubMsg->Buffer, alignment); if (fUnmarshall) { @@ -2058,7 +2162,7 @@ static inline ULONG array_read_variance_and_unmarshall( pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount); - ALIGN_POINTER(pStubMsg->Buffer, alignment); + align_pointer(&pStubMsg->Buffer, alignment); bufsize = safe_multiply(esize, pStubMsg->ActualCount); memsize = safe_multiply(esize, pStubMsg->MaxCount); @@ -2133,6 +2237,31 @@ static inline ULONG array_read_variance_and_unmarshall( TRACE("string=%s\n", debugstr_w((LPWSTR)*ppMemory)); } return bufsize; + + case RPC_FC_BOGUS_ARRAY: + alignment = pFormat[1] + 1; + pFormat = SkipConformance(pStubMsg, pFormat + 4); + pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount); + + esize = ComplexStructSize(pStubMsg, pFormat); + memsize = safe_multiply(esize, pStubMsg->MaxCount); + + assert( fUnmarshall ); + + if (!fMustAlloc && !*ppMemory) + fMustAlloc = TRUE; + if (fMustAlloc) + *ppMemory = NdrAllocate(pStubMsg, memsize); + + align_pointer(&pStubMsg->Buffer, alignment); + saved_buffer = pStubMsg->Buffer; + + pMemory = *ppMemory; + count = pStubMsg->ActualCount; + for (i = 0; i < count; i++) + pMemory = ComplexUnmarshall(pStubMsg, pMemory, pFormat, NULL, fMustAlloc); + return pStubMsg->Buffer - saved_buffer; + default: ERR("unknown array format 0x%x\n", fc); RpcRaiseException(RPC_X_BAD_STUB_DATA); @@ -2143,6 +2272,7 @@ static inline void array_memory_size( unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, unsigned char fHasPointers) { + ULONG i, count, SavedMemorySize; ULONG bufsize, memsize; DWORD esize; unsigned char alignment; @@ -2158,7 +2288,7 @@ static inline void array_memory_size( bufsize = memsize = safe_multiply(esize, pStubMsg->MaxCount); pStubMsg->MemorySize += memsize; - ALIGN_POINTER(pStubMsg->Buffer, alignment); + align_pointer(&pStubMsg->Buffer, alignment); if (fHasPointers) pStubMsg->BufferMark = pStubMsg->Buffer; safe_buffer_increment(pStubMsg, bufsize); @@ -2178,7 +2308,7 @@ static inline void array_memory_size( memsize = safe_multiply(esize, pStubMsg->MaxCount); pStubMsg->MemorySize += memsize; - ALIGN_POINTER(pStubMsg->Buffer, alignment); + align_pointer(&pStubMsg->Buffer, alignment); if (fHasPointers) pStubMsg->BufferMark = pStubMsg->Buffer; safe_buffer_increment(pStubMsg, bufsize); @@ -2215,6 +2345,24 @@ static inline void array_memory_size( safe_buffer_increment(pStubMsg, bufsize); pStubMsg->MemorySize += memsize; break; + case RPC_FC_BOGUS_ARRAY: + alignment = pFormat[1] + 1; + pFormat = SkipConformance(pStubMsg, pFormat + 4); + pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount); + + align_pointer(&pStubMsg->Buffer, alignment); + + SavedMemorySize = pStubMsg->MemorySize; + + esize = ComplexStructSize(pStubMsg, pFormat); + memsize = safe_multiply(pStubMsg->MaxCount, esize); + + count = pStubMsg->ActualCount; + for (i = 0; i < count; i++) + ComplexStructMemorySize(pStubMsg, pFormat, NULL); + + pStubMsg->MemorySize = SavedMemorySize + memsize; + break; default: ERR("unknown array format 0x%x\n", fc); RpcRaiseException(RPC_X_BAD_STUB_DATA); @@ -2225,6 +2373,8 @@ static inline void array_free( unsigned char fc, PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat, unsigned char fHasPointers) { + DWORD i, count; + switch (fc) { case RPC_FC_CARRAY: @@ -2242,6 +2392,15 @@ static inline void array_free( case RPC_FC_C_WSTRING: /* No embedded pointers so nothing to do */ break; + case RPC_FC_BOGUS_ARRAY: + count = *(const WORD *)(pFormat + 2); + pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 4, count); + pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount); + + count = pStubMsg->ActualCount; + for (i = 0; i < count; i++) + pMemory = ComplexFree(pStubMsg, pMemory, pFormat, NULL); + break; default: ERR("unknown array format 0x%x\n", fc); RpcRaiseException(RPC_X_BAD_STUB_DATA); @@ -2395,24 +2554,22 @@ unsigned char * WINAPI NdrNonConformantStringMarshall(PMIDL_STUB_MESSAGE pStubM TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat); - maxsize = *(USHORT *)&pFormat[2]; + maxsize = *(const USHORT *)&pFormat[2]; if (*pFormat == RPC_FC_CSTRING) { - ULONG i; + ULONG i = 0; const char *str = (const char *)pMemory; - for (i = 0; i < maxsize && *str; i++, str++) - ; + while (i < maxsize && str[i]) i++; TRACE("string=%s\n", debugstr_an(str, i)); pStubMsg->ActualCount = i + 1; esize = 1; } else if (*pFormat == RPC_FC_WSTRING) { - ULONG i; + ULONG i = 0; const WCHAR *str = (const WCHAR *)pMemory; - for (i = 0; i < maxsize && *str; i++, str++) - ; + while (i < maxsize && str[i]) i++; TRACE("string=%s\n", debugstr_wn(str, i)); pStubMsg->ActualCount = i + 1; esize = 2; @@ -2445,7 +2602,7 @@ unsigned char * WINAPI NdrNonConformantStringUnmarshall(PMIDL_STUB_MESSAGE pStu TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n", pStubMsg, *ppMemory, pFormat, fMustAlloc); - maxsize = *(USHORT *)&pFormat[2]; + maxsize = *(const USHORT *)&pFormat[2]; ReadVariance(pStubMsg, NULL, maxsize); if (pStubMsg->Offset) @@ -2495,26 +2652,24 @@ void WINAPI NdrNonConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg, TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat); - maxsize = *(USHORT *)&pFormat[2]; + maxsize = *(const USHORT *)&pFormat[2]; SizeVariance(pStubMsg); if (*pFormat == RPC_FC_CSTRING) { - ULONG i; + ULONG i = 0; const char *str = (const char *)pMemory; - for (i = 0; i < maxsize && *str; i++, str++) - ; + while (i < maxsize && str[i]) i++; TRACE("string=%s\n", debugstr_an(str, i)); pStubMsg->ActualCount = i + 1; esize = 1; } else if (*pFormat == RPC_FC_WSTRING) { - ULONG i; + ULONG i = 0; const WCHAR *str = (const WCHAR *)pMemory; - for (i = 0; i < maxsize && *str; i++, str++) - ; + while (i < maxsize && str[i]) i++; TRACE("string=%s\n", debugstr_wn(str, i)); pStubMsg->ActualCount = i + 1; esize = 2; @@ -2538,7 +2693,7 @@ ULONG WINAPI NdrNonConformantStringMemorySize(PMIDL_STUB_MESSAGE pStubMsg, TRACE("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat); - maxsize = *(USHORT *)&pFormat[2]; + maxsize = *(const USHORT *)&pFormat[2]; ReadVariance(pStubMsg, NULL, maxsize); @@ -2607,6 +2762,8 @@ static ULONG EmbeddedComplexSize(MIDL_STUB_MESSAGE *pStubMsg, case RPC_FC_LONG: case RPC_FC_ULONG: case RPC_FC_ENUM32: + case RPC_FC_INT3264: + case RPC_FC_UINT3264: return sizeof(ULONG); case RPC_FC_FLOAT: return sizeof(float); @@ -2683,12 +2840,15 @@ static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg, pMemory += 2; break; case RPC_FC_ENUM16: + { + USHORT val = *(DWORD *)pMemory; TRACE("enum16=%d <= %p\n", *(DWORD*)pMemory, pMemory); if (32767 < *(DWORD*)pMemory) RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE); - safe_copy_to_buffer(pStubMsg, pMemory, 2); + safe_copy_to_buffer(pStubMsg, &val, 2); pMemory += 4; break; + } case RPC_FC_LONG: case RPC_FC_ULONG: case RPC_FC_ENUM32: @@ -2696,6 +2856,15 @@ static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg, safe_copy_to_buffer(pStubMsg, pMemory, 4); pMemory += 4; break; + case RPC_FC_INT3264: + case RPC_FC_UINT3264: + { + UINT val = *(UINT_PTR *)pMemory; + TRACE("int3264=%ld <= %p\n", *(UINT_PTR *)pMemory, pMemory); + safe_copy_to_buffer(pStubMsg, &val, sizeof(UINT)); + pMemory += sizeof(UINT_PTR); + break; + } case RPC_FC_FLOAT: TRACE("float=%f <= %p\n", *(float*)pMemory, pMemory); safe_copy_to_buffer(pStubMsg, pMemory, sizeof(float)); @@ -2724,7 +2893,7 @@ static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg, if (*pFormat != RPC_FC_POINTER) pPointer = pFormat; if (*pPointer != RPC_FC_RP) - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4); + align_pointer_clear(&pStubMsg->Buffer, 4); saved_buffer = pStubMsg->Buffer; if (pStubMsg->PointerBufferMark) { @@ -2752,13 +2921,13 @@ static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg, break; } case RPC_FC_ALIGNM2: - ALIGN_POINTER(pMemory, 2); + align_pointer(&pMemory, 2); break; case RPC_FC_ALIGNM4: - ALIGN_POINTER(pMemory, 4); + align_pointer(&pMemory, 4); break; case RPC_FC_ALIGNM8: - ALIGN_POINTER(pMemory, 8); + align_pointer(&pMemory, 8); break; case RPC_FC_STRUCTPAD1: case RPC_FC_STRUCTPAD2: @@ -2830,13 +2999,16 @@ static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, pMemory += 2; break; case RPC_FC_ENUM16: - safe_copy_from_buffer(pStubMsg, pMemory, 2); - *(DWORD*)pMemory &= 0xffff; + { + WORD val; + safe_copy_from_buffer(pStubMsg, &val, 2); + *(DWORD*)pMemory = val; TRACE("enum16=%d => %p\n", *(DWORD*)pMemory, pMemory); if (32767 < *(DWORD*)pMemory) RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE); pMemory += 4; break; + } case RPC_FC_LONG: case RPC_FC_ULONG: case RPC_FC_ENUM32: @@ -2844,6 +3016,24 @@ static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, TRACE("long=%d => %p\n", *(DWORD*)pMemory, pMemory); pMemory += 4; break; + case RPC_FC_INT3264: + { + INT val; + safe_copy_from_buffer(pStubMsg, &val, 4); + *(INT_PTR *)pMemory = val; + TRACE("int3264=%ld => %p\n", *(INT_PTR*)pMemory, pMemory); + pMemory += sizeof(INT_PTR); + break; + } + case RPC_FC_UINT3264: + { + UINT val; + safe_copy_from_buffer(pStubMsg, &val, 4); + *(UINT_PTR *)pMemory = val; + TRACE("uint3264=%ld => %p\n", *(UINT_PTR*)pMemory, pMemory); + pMemory += sizeof(UINT_PTR); + break; + } case RPC_FC_FLOAT: safe_copy_from_buffer(pStubMsg, pMemory, sizeof(float)); TRACE("float=%f => %p\n", *(float*)pMemory, pMemory); @@ -2871,7 +3061,7 @@ static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, if (*pFormat != RPC_FC_POINTER) pPointer = pFormat; if (*pPointer != RPC_FC_RP) - ALIGN_POINTER(pStubMsg->Buffer, 4); + align_pointer(&pStubMsg->Buffer, 4); saved_buffer = pStubMsg->Buffer; if (pStubMsg->PointerBufferMark) { @@ -2899,13 +3089,13 @@ static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, break; } case RPC_FC_ALIGNM2: - ALIGN_POINTER_CLEAR(pMemory, 2); + align_pointer_clear(&pMemory, 2); break; case RPC_FC_ALIGNM4: - ALIGN_POINTER_CLEAR(pMemory, 4); + align_pointer_clear(&pMemory, 4); break; case RPC_FC_ALIGNM8: - ALIGN_POINTER_CLEAR(pMemory, 8); + align_pointer_clear(&pMemory, 8); break; case RPC_FC_STRUCTPAD1: case RPC_FC_STRUCTPAD2: @@ -2992,6 +3182,11 @@ static unsigned char * ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg, safe_buffer_length_increment(pStubMsg, 4); pMemory += 4; break; + case RPC_FC_INT3264: + case RPC_FC_UINT3264: + safe_buffer_length_increment(pStubMsg, 4); + pMemory += sizeof(INT_PTR); + break; case RPC_FC_HYPER: case RPC_FC_DOUBLE: safe_buffer_length_increment(pStubMsg, 8); @@ -3017,7 +3212,7 @@ static unsigned char * ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg, } if (*pPointer != RPC_FC_RP) { - ALIGN_LENGTH(pStubMsg->BufferLength, 4); + align_length(&pStubMsg->BufferLength, 4); safe_buffer_length_increment(pStubMsg, 4); } if (*pFormat == RPC_FC_POINTER) @@ -3027,13 +3222,13 @@ static unsigned char * ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg, pMemory += sizeof(void*); break; case RPC_FC_ALIGNM2: - ALIGN_POINTER(pMemory, 2); + align_pointer(&pMemory, 2); break; case RPC_FC_ALIGNM4: - ALIGN_POINTER(pMemory, 4); + align_pointer(&pMemory, 4); break; case RPC_FC_ALIGNM8: - ALIGN_POINTER(pMemory, 8); + align_pointer(&pMemory, 8); break; case RPC_FC_STRUCTPAD1: case RPC_FC_STRUCTPAD2: @@ -3105,6 +3300,10 @@ static unsigned char * ComplexFree(PMIDL_STUB_MESSAGE pStubMsg, case RPC_FC_FLOAT: pMemory += 4; break; + case RPC_FC_INT3264: + case RPC_FC_UINT3264: + pMemory += sizeof(INT_PTR); + break; case RPC_FC_HYPER: case RPC_FC_DOUBLE: pMemory += 8; @@ -3124,13 +3323,13 @@ static unsigned char * ComplexFree(PMIDL_STUB_MESSAGE pStubMsg, pMemory += sizeof(void *); break; case RPC_FC_ALIGNM2: - ALIGN_POINTER(pMemory, 2); + align_pointer(&pMemory, 2); break; case RPC_FC_ALIGNM4: - ALIGN_POINTER(pMemory, 4); + align_pointer(&pMemory, 4); break; case RPC_FC_ALIGNM8: - ALIGN_POINTER(pMemory, 8); + align_pointer(&pMemory, 8); break; case RPC_FC_STRUCTPAD1: case RPC_FC_STRUCTPAD2: @@ -3205,6 +3404,11 @@ static ULONG ComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg, size += 4; safe_buffer_increment(pStubMsg, 4); break; + case RPC_FC_INT3264: + case RPC_FC_UINT3264: + size += sizeof(INT_PTR); + safe_buffer_increment(pStubMsg, 4); + break; case RPC_FC_HYPER: case RPC_FC_DOUBLE: size += 8; @@ -3221,7 +3425,7 @@ static ULONG ComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg, if (*pFormat != RPC_FC_POINTER) pPointer = pFormat; if (*pPointer != RPC_FC_RP) - ALIGN_POINTER(pStubMsg->Buffer, 4); + align_pointer(&pStubMsg->Buffer, 4); saved_buffer = pStubMsg->Buffer; if (pStubMsg->PointerBufferMark) { @@ -3250,13 +3454,13 @@ static ULONG ComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg, break; } case RPC_FC_ALIGNM2: - ALIGN_LENGTH(size, 2); + align_length(&size, 2); break; case RPC_FC_ALIGNM4: - ALIGN_LENGTH(size, 4); + align_length(&size, 4); break; case RPC_FC_ALIGNM8: - ALIGN_LENGTH(size, 8); + align_length(&size, 8); break; case RPC_FC_STRUCTPAD1: case RPC_FC_STRUCTPAD2: @@ -3310,6 +3514,10 @@ ULONG ComplexStructSize(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat) case RPC_FC_FLOAT: size += 4; break; + case RPC_FC_INT3264: + case RPC_FC_UINT3264: + size += sizeof(INT_PTR); + break; case RPC_FC_HYPER: case RPC_FC_DOUBLE: size += 8; @@ -3324,13 +3532,13 @@ ULONG ComplexStructSize(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat) pFormat += 4; break; case RPC_FC_ALIGNM2: - ALIGN_LENGTH(size, 2); + align_length(&size, 2); break; case RPC_FC_ALIGNM4: - ALIGN_LENGTH(size, 4); + align_length(&size, 4); break; case RPC_FC_ALIGNM8: - ALIGN_LENGTH(size, 8); + align_length(&size, 8); break; case RPC_FC_STRUCTPAD1: case RPC_FC_STRUCTPAD2: @@ -3398,7 +3606,7 @@ unsigned char * WINAPI NdrComplexStructMarshall(PMIDL_STUB_MESSAGE pStubMsg, pStubMsg->BufferLength = saved_buffer_length; } - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pFormat[1] + 1); + align_pointer_clear(&pStubMsg->Buffer, pFormat[1] + 1); pFormat += 4; if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat; @@ -3484,7 +3692,7 @@ unsigned char * WINAPI NdrComplexStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, pStubMsg->Buffer = saved_buffer; } - ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1); + align_pointer(&pStubMsg->Buffer, pFormat[1] + 1); pFormat += 4; if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat; @@ -3549,7 +3757,7 @@ void WINAPI NdrComplexStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg, TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1); + align_length(&pStubMsg->BufferLength, pFormat[1] + 1); if(!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength) { @@ -3627,7 +3835,7 @@ ULONG WINAPI NdrComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg, TRACE("(%p,%p)\n", pStubMsg, pFormat); - ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1); + align_pointer(&pStubMsg->Buffer, pFormat[1] + 1); pFormat += 4; if (*(const SHORT*)pFormat) conf_array = pFormat + *(const SHORT*)pFormat; @@ -3918,9 +4126,6 @@ unsigned char * WINAPI NdrComplexArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat) { - ULONG i, count, def; - BOOL variance_present; - unsigned char alignment; int pointer_buffer_mark_set = 0; TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); @@ -3932,8 +4137,6 @@ unsigned char * WINAPI NdrComplexArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg, return NULL; } - alignment = pFormat[1] + 1; - if (!pStubMsg->PointerBufferMark) { /* save buffer fields that may be changed by buffer sizer functions @@ -3963,25 +4166,9 @@ unsigned char * WINAPI NdrComplexArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg, pStubMsg->BufferLength = saved_buffer_length; } - def = *(const WORD*)&pFormat[2]; - pFormat += 4; - - pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def); - TRACE("conformance = %ld\n", pStubMsg->MaxCount); - - variance_present = IsConformanceOrVariancePresent(pFormat); - pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount); - TRACE("variance = %d\n", pStubMsg->ActualCount); - - WriteConformance(pStubMsg); - if (variance_present) - WriteVariance(pStubMsg); - - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment); - - count = pStubMsg->ActualCount; - for (i = 0; i < count; i++) - pMemory = ComplexMarshall(pStubMsg, pMemory, pFormat, NULL); + array_compute_and_write_conformance(RPC_FC_BOGUS_ARRAY, pStubMsg, pMemory, pFormat); + array_write_variance_and_marshall(RPC_FC_BOGUS_ARRAY, pStubMsg, + pMemory, pFormat, TRUE /* fHasPointers */); STD_OVERFLOW_CHECK(pStubMsg); @@ -4002,9 +4189,6 @@ unsigned char * WINAPI NdrComplexArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, unsigned char fMustAlloc) { - ULONG i, count, size; - unsigned char alignment; - unsigned char *pMemory; unsigned char *saved_buffer; int pointer_buffer_mark_set = 0; int saved_ignore_embedded; @@ -4018,8 +4202,6 @@ unsigned char * WINAPI NdrComplexArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, return NULL; } - alignment = pFormat[1] + 1; - saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers; /* save buffer pointer */ saved_buffer = pStubMsg->Buffer; @@ -4028,7 +4210,6 @@ unsigned char * WINAPI NdrComplexArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, pStubMsg->IgnoreEmbeddedPointers = 1; pStubMsg->MemorySize = 0; NdrComplexArrayMemorySize(pStubMsg, pFormat); - size = pStubMsg->MemorySize; pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded; TRACE("difference = 0x%x\n", (ULONG)(pStubMsg->Buffer - saved_buffer)); @@ -4041,22 +4222,9 @@ unsigned char * WINAPI NdrComplexArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, /* restore the original buffer */ pStubMsg->Buffer = saved_buffer; - pFormat += 4; - - pFormat = ReadConformance(pStubMsg, pFormat); - pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount); - - if (!fMustAlloc && !*ppMemory) - fMustAlloc = TRUE; - if (fMustAlloc) - *ppMemory = NdrAllocate(pStubMsg, size); - - ALIGN_POINTER(pStubMsg->Buffer, alignment); - - pMemory = *ppMemory; - count = pStubMsg->ActualCount; - for (i = 0; i < count; i++) - pMemory = ComplexUnmarshall(pStubMsg, pMemory, pFormat, NULL, fMustAlloc); + array_read_conformance(RPC_FC_BOGUS_ARRAY, pStubMsg, pFormat); + array_read_variance_and_unmarshall(RPC_FC_BOGUS_ARRAY, pStubMsg, ppMemory, pFormat, fMustAlloc, + TRUE /* fUseBufferMemoryServer */, TRUE /* fUnmarshall */); if (pointer_buffer_mark_set) { @@ -4074,9 +4242,6 @@ void WINAPI NdrComplexArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat) { - ULONG i, count, def; - unsigned char alignment; - BOOL variance_present; int pointer_length_set = 0; TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); @@ -4088,8 +4253,6 @@ void WINAPI NdrComplexArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg, return; } - alignment = pFormat[1] + 1; - if (!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength) { /* save buffer fields that may be changed by buffer sizer functions @@ -4116,25 +4279,9 @@ void WINAPI NdrComplexArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg, pStubMsg->MaxCount = saved_max_count; pStubMsg->BufferLength = saved_buffer_length; } - def = *(const WORD*)&pFormat[2]; - pFormat += 4; - pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def); - TRACE("conformance = %ld\n", pStubMsg->MaxCount); - SizeConformance(pStubMsg); - - variance_present = IsConformanceOrVariancePresent(pFormat); - pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount); - TRACE("variance = %d\n", pStubMsg->ActualCount); - - if (variance_present) - SizeVariance(pStubMsg); - - ALIGN_LENGTH(pStubMsg->BufferLength, alignment); - - count = pStubMsg->ActualCount; - for (i = 0; i < count; i++) - pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, NULL); + array_compute_and_size_conformance(RPC_FC_BOGUS_ARRAY, pStubMsg, pMemory, pFormat); + array_buffer_size(RPC_FC_BOGUS_ARRAY, pStubMsg, pMemory, pFormat, TRUE /* fHasPointers */); if(pointer_length_set) { @@ -4149,9 +4296,6 @@ void WINAPI NdrComplexArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg, ULONG WINAPI NdrComplexArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat) { - ULONG i, count, esize, SavedMemorySize, MemorySize; - unsigned char alignment; - TRACE("(%p,%p)\n", pStubMsg, pFormat); if (pFormat[0] != RPC_FC_BOGUS_ARRAY) @@ -4161,29 +4305,9 @@ ULONG WINAPI NdrComplexArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg, return 0; } - alignment = pFormat[1] + 1; - - pFormat += 4; - - pFormat = ReadConformance(pStubMsg, pFormat); - pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount); - - ALIGN_POINTER(pStubMsg->Buffer, alignment); - - SavedMemorySize = pStubMsg->MemorySize; - - esize = ComplexStructSize(pStubMsg, pFormat); - - MemorySize = safe_multiply(pStubMsg->MaxCount, esize); - - count = pStubMsg->ActualCount; - for (i = 0; i < count; i++) - ComplexStructMemorySize(pStubMsg, pFormat, NULL); - - pStubMsg->MemorySize = SavedMemorySize; - - pStubMsg->MemorySize += MemorySize; - return MemorySize; + array_read_conformance(RPC_FC_BOGUS_ARRAY, pStubMsg, pFormat); + array_memory_size(RPC_FC_BOGUS_ARRAY, pStubMsg, pFormat, TRUE /* fHasPointers */); + return pStubMsg->MemorySize; } /*********************************************************************** @@ -4255,7 +4379,7 @@ unsigned char * WINAPI NdrUserMarshalMarshall(PMIDL_STUB_MESSAGE pStubMsg, if (flags & USER_MARSHAL_POINTER) { - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4); + align_pointer_clear(&pStubMsg->Buffer, 4); NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, USER_MARSHAL_PTR_PREFIX); pStubMsg->Buffer += 4; if (pStubMsg->PointerBufferMark) @@ -4264,10 +4388,10 @@ unsigned char * WINAPI NdrUserMarshalMarshall(PMIDL_STUB_MESSAGE pStubMsg, pStubMsg->Buffer = pStubMsg->PointerBufferMark; pStubMsg->PointerBufferMark = NULL; } - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 8); + align_pointer_clear(&pStubMsg->Buffer, 8); } else - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, (flags & 0xf) + 1); + align_pointer_clear(&pStubMsg->Buffer, (flags & 0xf) + 1); pStubMsg->Buffer = pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnMarshall( @@ -4306,7 +4430,7 @@ unsigned char * WINAPI NdrUserMarshalUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, if (flags & USER_MARSHAL_POINTER) { - ALIGN_POINTER(pStubMsg->Buffer, 4); + align_pointer(&pStubMsg->Buffer, 4); /* skip pointer prefix */ pStubMsg->Buffer += 4; if (pStubMsg->PointerBufferMark) @@ -4315,10 +4439,10 @@ unsigned char * WINAPI NdrUserMarshalUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, pStubMsg->Buffer = pStubMsg->PointerBufferMark; pStubMsg->PointerBufferMark = NULL; } - ALIGN_POINTER(pStubMsg->Buffer, 8); + align_pointer(&pStubMsg->Buffer, 8); } else - ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1); + align_pointer(&pStubMsg->Buffer, (flags & 0xf) + 1); if (!fMustAlloc && !*ppMemory) fMustAlloc = TRUE; @@ -4362,7 +4486,7 @@ void WINAPI NdrUserMarshalBufferSize(PMIDL_STUB_MESSAGE pStubMsg, if (flags & USER_MARSHAL_POINTER) { - ALIGN_LENGTH(pStubMsg->BufferLength, 4); + align_length(&pStubMsg->BufferLength, 4); /* skip pointer prefix */ safe_buffer_length_increment(pStubMsg, 4); if (pStubMsg->IgnoreEmbeddedPointers) @@ -4373,10 +4497,10 @@ void WINAPI NdrUserMarshalBufferSize(PMIDL_STUB_MESSAGE pStubMsg, pStubMsg->BufferLength = pStubMsg->PointerLength; pStubMsg->PointerLength = 0; } - ALIGN_LENGTH(pStubMsg->BufferLength, 8); + align_length(&pStubMsg->BufferLength, 8); } else - ALIGN_LENGTH(pStubMsg->BufferLength, (flags & 0xf) + 1); + align_length(&pStubMsg->BufferLength, (flags & 0xf) + 1); if (bufsize) { TRACE("size=%d\n", bufsize); @@ -4413,15 +4537,15 @@ ULONG WINAPI NdrUserMarshalMemorySize(PMIDL_STUB_MESSAGE pStubMsg, if (flags & USER_MARSHAL_POINTER) { - ALIGN_POINTER(pStubMsg->Buffer, 4); + align_pointer(&pStubMsg->Buffer, 4); /* skip pointer prefix */ pStubMsg->Buffer += 4; if (pStubMsg->IgnoreEmbeddedPointers) return pStubMsg->MemorySize; - ALIGN_POINTER(pStubMsg->Buffer, 8); + align_pointer(&pStubMsg->Buffer, 8); } else - ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1); + align_pointer(&pStubMsg->Buffer, (flags & 0xf) + 1); if (!bufsize) FIXME("not implemented for varying buffer size\n"); @@ -4578,7 +4702,7 @@ unsigned char * WINAPI NdrConformantStructMarshall(PMIDL_STUB_MESSAGE pStubMsg, WriteConformance(pStubMsg); - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pCStructFormat->alignment + 1); + align_pointer_clear(&pStubMsg->Buffer, pCStructFormat->alignment + 1); TRACE("memory_size = %d\n", pCStructFormat->memory_size); @@ -4633,7 +4757,7 @@ unsigned char * WINAPI NdrConformantStructUnmarshall(PMIDL_STUB_MESSAGE pStubMs pCArrayFormat = ReadConformance(pStubMsg, pCArrayFormat + 4); - ALIGN_POINTER(pStubMsg->Buffer, pCStructFormat->alignment + 1); + align_pointer(&pStubMsg->Buffer, pCStructFormat->alignment + 1); TRACE("memory_size = %d\n", pCStructFormat->memory_size); @@ -4702,7 +4826,7 @@ void WINAPI NdrConformantStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg, pCArrayFormat = ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size, pCArrayFormat+4, 0); SizeConformance(pStubMsg); - ALIGN_LENGTH(pStubMsg->BufferLength, pCStructFormat->alignment + 1); + align_length(&pStubMsg->BufferLength, pCStructFormat->alignment + 1); TRACE("memory_size = %d\n", pCStructFormat->memory_size); @@ -4791,7 +4915,7 @@ unsigned char * WINAPI NdrConformantVaryingStructMarshall(PMIDL_STUB_MESSAGE pS pMemory + pCVStructFormat->memory_size, pCVArrayFormat); - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pCVStructFormat->alignment + 1); + align_pointer_clear(&pStubMsg->Buffer, pCVStructFormat->alignment + 1); TRACE("memory_size = %d\n", pCVStructFormat->memory_size); @@ -4839,7 +4963,7 @@ unsigned char * WINAPI NdrConformantVaryingStructUnmarshall(PMIDL_STUB_MESSAGE memsize = array_read_conformance(*pCVArrayFormat, pStubMsg, pCVArrayFormat); - ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1); + align_pointer(&pStubMsg->Buffer, pCVStructFormat->alignment + 1); TRACE("memory_size = %d\n", pCVStructFormat->memory_size); @@ -4913,7 +5037,7 @@ void WINAPI NdrConformantVaryingStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg, pMemory + pCVStructFormat->memory_size, pCVArrayFormat); - ALIGN_LENGTH(pStubMsg->BufferLength, pCVStructFormat->alignment + 1); + align_length(&pStubMsg->BufferLength, pCVStructFormat->alignment + 1); TRACE("memory_size = %d\n", pCVStructFormat->memory_size); @@ -4949,7 +5073,7 @@ ULONG WINAPI NdrConformantVaryingStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg, pCVStructFormat->offset_to_array_description; array_read_conformance(*pCVArrayFormat, pStubMsg, pCVArrayFormat); - ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1); + align_pointer(&pStubMsg->Buffer, pCVStructFormat->alignment + 1); TRACE("memory_size = %d\n", pCVStructFormat->memory_size); @@ -5031,7 +5155,7 @@ unsigned char * WINAPI NdrFixedArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg, return NULL; } - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1); + align_pointer_clear(&pStubMsg->Buffer, pSmFArrayFormat->alignment + 1); if (pSmFArrayFormat->type == RPC_FC_SMFARRAY) { @@ -5075,7 +5199,7 @@ unsigned char * WINAPI NdrFixedArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, return NULL; } - ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1); + align_pointer(&pStubMsg->Buffer, pSmFArrayFormat->alignment + 1); if (pSmFArrayFormat->type == RPC_FC_SMFARRAY) { @@ -5129,7 +5253,7 @@ void WINAPI NdrFixedArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg, return; } - ALIGN_LENGTH(pStubMsg->BufferLength, pSmFArrayFormat->alignment + 1); + align_length(&pStubMsg->BufferLength, pSmFArrayFormat->alignment + 1); if (pSmFArrayFormat->type == RPC_FC_SMFARRAY) { @@ -5166,7 +5290,7 @@ ULONG WINAPI NdrFixedArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg, return 0; } - ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1); + align_pointer(&pStubMsg->Buffer, pSmFArrayFormat->alignment + 1); if (pSmFArrayFormat->type == RPC_FC_SMFARRAY) { @@ -5269,7 +5393,7 @@ unsigned char * WINAPI NdrVaryingArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg, WriteVariance(pStubMsg); - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment); + align_pointer_clear(&pStubMsg->Buffer, alignment); bufsize = safe_multiply(esize, pStubMsg->ActualCount); pStubMsg->BufferMark = pStubMsg->Buffer; @@ -5328,7 +5452,7 @@ unsigned char * WINAPI NdrVaryingArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, pFormat = ReadVariance(pStubMsg, pFormat, elements); - ALIGN_POINTER(pStubMsg->Buffer, alignment); + align_pointer(&pStubMsg->Buffer, alignment); bufsize = safe_multiply(esize, pStubMsg->ActualCount); offset = pStubMsg->Offset; @@ -5397,7 +5521,7 @@ void WINAPI NdrVaryingArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg, SizeVariance(pStubMsg); - ALIGN_LENGTH(pStubMsg->BufferLength, alignment); + align_length(&pStubMsg->BufferLength, alignment); safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount)); @@ -5447,7 +5571,7 @@ ULONG WINAPI NdrVaryingArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg, pFormat = ReadVariance(pStubMsg, pFormat, elements); - ALIGN_POINTER(pStubMsg->Buffer, alignment); + align_pointer(&pStubMsg->Buffer, alignment); safe_buffer_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount)); pStubMsg->MemorySize += size; @@ -5522,6 +5646,9 @@ static ULONG get_discriminant(unsigned char fc, const unsigned char *pMemory) case RPC_FC_ULONG: case RPC_FC_ENUM32: return *(const ULONG *)pMemory; + case RPC_FC_INT3264: + case RPC_FC_UINT3264: + return *(const ULONG_PTR *)pMemory; default: FIXME("Unhandled base type: 0x%02x\n", fc); return 0; @@ -5595,7 +5722,7 @@ static unsigned char *union_arm_marshall(PMIDL_STUB_MESSAGE pStubMsg, unsigned c case RPC_FC_UP: case RPC_FC_OP: case RPC_FC_FP: - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4); + align_pointer_clear(&pStubMsg->Buffer, 4); saved_buffer = pStubMsg->Buffer; if (pStubMsg->PointerBufferMark) { @@ -5663,7 +5790,7 @@ static unsigned char *union_arm_unmarshall(PMIDL_STUB_MESSAGE pStubMsg, case RPC_FC_UP: case RPC_FC_OP: case RPC_FC_FP: - ALIGN_POINTER(pStubMsg->Buffer, 4); + align_pointer(&pStubMsg->Buffer, 4); saved_buffer = pStubMsg->Buffer; if (pStubMsg->PointerBufferMark) { @@ -5729,7 +5856,7 @@ static void union_arm_buffer_size(PMIDL_STUB_MESSAGE pStubMsg, case RPC_FC_UP: case RPC_FC_OP: case RPC_FC_FP: - ALIGN_LENGTH(pStubMsg->BufferLength, 4); + align_length(&pStubMsg->BufferLength, 4); safe_buffer_length_increment(pStubMsg, 4); /* for pointer ID */ if (!pStubMsg->IgnoreEmbeddedPointers) { @@ -5783,10 +5910,10 @@ static ULONG union_arm_memory_size(PMIDL_STUB_MESSAGE pStubMsg, case RPC_FC_UP: case RPC_FC_OP: case RPC_FC_FP: - ALIGN_POINTER(pStubMsg->Buffer, 4); + align_pointer(&pStubMsg->Buffer, 4); saved_buffer = pStubMsg->Buffer; safe_buffer_increment(pStubMsg, 4); - ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(void *)); + align_length(&pStubMsg->MemorySize, sizeof(void *)); pStubMsg->MemorySize += sizeof(void *); if (!pStubMsg->IgnoreEmbeddedPointers) PointerMemorySize(pStubMsg, saved_buffer, pFormat); @@ -5855,7 +5982,7 @@ unsigned char * WINAPI NdrEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg increment = (*pFormat & 0xf0) >> 4; pFormat++; - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, increment); + align_pointer_clear(&pStubMsg->Buffer, increment); switch_value = get_discriminant(switch_type, pMemory); TRACE("got switch value 0x%x\n", switch_value); @@ -5887,7 +6014,7 @@ unsigned char * WINAPI NdrEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubM increment = (*pFormat & 0xf0) >> 4; pFormat++; - ALIGN_POINTER(pStubMsg->Buffer, increment); + align_pointer(&pStubMsg->Buffer, increment); switch_value = get_discriminant(switch_type, pStubMsg->Buffer); TRACE("got switch value 0x%x\n", switch_value); @@ -5929,7 +6056,7 @@ void WINAPI NdrEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg, increment = (*pFormat & 0xf0) >> 4; pFormat++; - ALIGN_LENGTH(pStubMsg->BufferLength, increment); + align_length(&pStubMsg->BufferLength, increment); switch_value = get_discriminant(switch_type, pMemory); TRACE("got switch value 0x%x\n", switch_value); @@ -5954,7 +6081,7 @@ ULONG WINAPI NdrEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg, increment = (*pFormat & 0xf0) >> 4; pFormat++; - ALIGN_POINTER(pStubMsg->Buffer, increment); + align_pointer(&pStubMsg->Buffer, increment); switch_value = get_discriminant(switch_type, pStubMsg->Buffer); TRACE("got switch value 0x%x\n", switch_value); @@ -6032,10 +6159,9 @@ static LONG unmarshall_discriminant(PMIDL_STUB_MESSAGE pStubMsg, case RPC_FC_WCHAR: case RPC_FC_SHORT: case RPC_FC_USHORT: - case RPC_FC_ENUM16: { USHORT d; - ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT)); + align_pointer(&pStubMsg->Buffer, sizeof(USHORT)); safe_copy_from_buffer(pStubMsg, &d, sizeof(d)); discriminant = d; break; @@ -6044,7 +6170,7 @@ static LONG unmarshall_discriminant(PMIDL_STUB_MESSAGE pStubMsg, case RPC_FC_ULONG: { ULONG d; - ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONG)); + align_pointer(&pStubMsg->Buffer, sizeof(ULONG)); safe_copy_from_buffer(pStubMsg, &d, sizeof(d)); discriminant = d; break; @@ -6269,7 +6395,7 @@ static unsigned char *WINAPI NdrRangeMarshall( unsigned char *pMemory, PFORMAT_STRING pFormat) { - NDR_RANGE *pRange = (NDR_RANGE *)pFormat; + const NDR_RANGE *pRange = (const NDR_RANGE *)pFormat; unsigned char base_type; TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat); @@ -6295,7 +6421,7 @@ unsigned char *WINAPI NdrRangeUnmarshall( PFORMAT_STRING pFormat, unsigned char fMustAlloc) { - NDR_RANGE *pRange = (NDR_RANGE *)pFormat; + const NDR_RANGE *pRange = (const NDR_RANGE *)pFormat; unsigned char base_type; TRACE("pStubMsg: %p, ppMemory: %p, type: 0x%02x, fMustAlloc: %s\n", pStubMsg, ppMemory, *pFormat, fMustAlloc ? "true" : "false"); @@ -6314,7 +6440,7 @@ unsigned char *WINAPI NdrRangeUnmarshall( #define RANGE_UNMARSHALL(mem_type, wire_type, format_spec) \ do \ { \ - ALIGN_POINTER(pStubMsg->Buffer, sizeof(wire_type)); \ + align_pointer(&pStubMsg->Buffer, sizeof(wire_type)); \ if (!fMustAlloc && !*ppMemory) \ fMustAlloc = TRUE; \ if (fMustAlloc) \ @@ -6392,7 +6518,7 @@ static void WINAPI NdrRangeBufferSize( unsigned char *pMemory, PFORMAT_STRING pFormat) { - NDR_RANGE *pRange = (NDR_RANGE *)pFormat; + const NDR_RANGE *pRange = (const NDR_RANGE *)pFormat; unsigned char base_type; TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat); @@ -6414,7 +6540,7 @@ static ULONG WINAPI NdrRangeMemorySize( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat) { - NDR_RANGE *pRange = (NDR_RANGE *)pFormat; + const NDR_RANGE *pRange = (const NDR_RANGE *)pFormat; unsigned char base_type; if (pRange->type != RPC_FC_RANGE) @@ -6462,7 +6588,7 @@ static unsigned char *WINAPI NdrBaseTypeMarshall( case RPC_FC_WCHAR: case RPC_FC_SHORT: case RPC_FC_USHORT: - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(USHORT)); + align_pointer_clear(&pStubMsg->Buffer, sizeof(USHORT)); safe_copy_to_buffer(pStubMsg, pMemory, sizeof(USHORT)); TRACE("value: 0x%04x\n", *(USHORT *)pMemory); break; @@ -6470,34 +6596,42 @@ static unsigned char *WINAPI NdrBaseTypeMarshall( case RPC_FC_ULONG: case RPC_FC_ERROR_STATUS_T: case RPC_FC_ENUM32: - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(ULONG)); + align_pointer_clear(&pStubMsg->Buffer, sizeof(ULONG)); safe_copy_to_buffer(pStubMsg, pMemory, sizeof(ULONG)); TRACE("value: 0x%08x\n", *(ULONG *)pMemory); break; case RPC_FC_FLOAT: - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(float)); + align_pointer_clear(&pStubMsg->Buffer, sizeof(float)); safe_copy_to_buffer(pStubMsg, pMemory, sizeof(float)); break; case RPC_FC_DOUBLE: - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(double)); + align_pointer_clear(&pStubMsg->Buffer, sizeof(double)); safe_copy_to_buffer(pStubMsg, pMemory, sizeof(double)); break; case RPC_FC_HYPER: - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(ULONGLONG)); + align_pointer_clear(&pStubMsg->Buffer, sizeof(ULONGLONG)); safe_copy_to_buffer(pStubMsg, pMemory, sizeof(ULONGLONG)); TRACE("value: %s\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory)); break; case RPC_FC_ENUM16: + { + USHORT val = *(UINT *)pMemory; /* only 16-bits on the wire, so do a sanity check */ if (*(UINT *)pMemory > SHRT_MAX) RpcRaiseException(RPC_X_ENUM_VALUE_OUT_OF_RANGE); - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(USHORT)); - if (pStubMsg->Buffer + sizeof(USHORT) > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) - RpcRaiseException(RPC_X_BAD_STUB_DATA); - *(USHORT *)pStubMsg->Buffer = *(UINT *)pMemory; - pStubMsg->Buffer += sizeof(USHORT); + align_pointer_clear(&pStubMsg->Buffer, sizeof(USHORT)); + safe_copy_to_buffer(pStubMsg, &val, sizeof(val)); TRACE("value: 0x%04x\n", *(UINT *)pMemory); break; + } + case RPC_FC_INT3264: + case RPC_FC_UINT3264: + { + UINT val = *(UINT_PTR *)pMemory; + align_pointer_clear(&pStubMsg->Buffer, sizeof(UINT)); + safe_copy_to_buffer(pStubMsg, &val, sizeof(val)); + break; + } case RPC_FC_IGNORE: break; default: @@ -6519,8 +6653,8 @@ static unsigned char *WINAPI NdrBaseTypeUnmarshall( { TRACE("pStubMsg: %p, ppMemory: %p, type: 0x%02x, fMustAlloc: %s\n", pStubMsg, ppMemory, *pFormat, fMustAlloc ? "true" : "false"); -#define BASE_TYPE_UNMARSHALL(type) \ - ALIGN_POINTER(pStubMsg->Buffer, sizeof(type)); \ +#define BASE_TYPE_UNMARSHALL(type) do { \ + align_pointer(&pStubMsg->Buffer, sizeof(type)); \ if (!fMustAlloc && !pStubMsg->IsClient && !*ppMemory) \ { \ *ppMemory = pStubMsg->Buffer; \ @@ -6533,7 +6667,8 @@ static unsigned char *WINAPI NdrBaseTypeUnmarshall( *ppMemory = NdrAllocate(pStubMsg, sizeof(type)); \ TRACE("*ppMemory: %p\n", *ppMemory); \ safe_copy_from_buffer(pStubMsg, *ppMemory, sizeof(type)); \ - } + } \ + } while (0) switch(*pFormat) { @@ -6570,19 +6705,49 @@ static unsigned char *WINAPI NdrBaseTypeUnmarshall( TRACE("value: %s\n", wine_dbgstr_longlong(**(ULONGLONG **)ppMemory)); break; case RPC_FC_ENUM16: - ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT)); + { + USHORT val; + align_pointer(&pStubMsg->Buffer, sizeof(USHORT)); if (!fMustAlloc && !*ppMemory) fMustAlloc = TRUE; if (fMustAlloc) *ppMemory = NdrAllocate(pStubMsg, sizeof(UINT)); - if (pStubMsg->Buffer + sizeof(USHORT) > pStubMsg->BufferEnd) - RpcRaiseException(RPC_X_BAD_STUB_DATA); - TRACE("*ppMemory: %p\n", *ppMemory); + safe_copy_from_buffer(pStubMsg, &val, sizeof(USHORT)); /* 16-bits on the wire, but int in memory */ - **(UINT **)ppMemory = *(USHORT *)pStubMsg->Buffer; - pStubMsg->Buffer += sizeof(USHORT); + **(UINT **)ppMemory = val; TRACE("value: 0x%08x\n", **(UINT **)ppMemory); break; + } + case RPC_FC_INT3264: + if (sizeof(INT_PTR) == sizeof(INT)) BASE_TYPE_UNMARSHALL(INT); + else + { + INT val; + align_pointer(&pStubMsg->Buffer, sizeof(INT)); + if (!fMustAlloc && !*ppMemory) + fMustAlloc = TRUE; + if (fMustAlloc) + *ppMemory = NdrAllocate(pStubMsg, sizeof(INT_PTR)); + safe_copy_from_buffer(pStubMsg, &val, sizeof(INT)); + **(INT_PTR **)ppMemory = val; + TRACE("value: 0x%08lx\n", **(INT_PTR **)ppMemory); + } + break; + case RPC_FC_UINT3264: + if (sizeof(UINT_PTR) == sizeof(UINT)) BASE_TYPE_UNMARSHALL(UINT); + else + { + UINT val; + align_pointer(&pStubMsg->Buffer, sizeof(UINT)); + if (!fMustAlloc && !*ppMemory) + fMustAlloc = TRUE; + if (fMustAlloc) + *ppMemory = NdrAllocate(pStubMsg, sizeof(UINT_PTR)); + safe_copy_from_buffer(pStubMsg, &val, sizeof(UINT)); + **(UINT_PTR **)ppMemory = val; + TRACE("value: 0x%08lx\n", **(UINT_PTR **)ppMemory); + } + break; case RPC_FC_IGNORE: break; default: @@ -6617,29 +6782,31 @@ static void WINAPI NdrBaseTypeBufferSize( case RPC_FC_SHORT: case RPC_FC_USHORT: case RPC_FC_ENUM16: - ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(USHORT)); + align_length(&pStubMsg->BufferLength, sizeof(USHORT)); safe_buffer_length_increment(pStubMsg, sizeof(USHORT)); break; case RPC_FC_LONG: case RPC_FC_ULONG: case RPC_FC_ENUM32: - ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(ULONG)); + case RPC_FC_INT3264: + case RPC_FC_UINT3264: + align_length(&pStubMsg->BufferLength, sizeof(ULONG)); safe_buffer_length_increment(pStubMsg, sizeof(ULONG)); break; case RPC_FC_FLOAT: - ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(float)); + align_length(&pStubMsg->BufferLength, sizeof(float)); safe_buffer_length_increment(pStubMsg, sizeof(float)); break; case RPC_FC_DOUBLE: - ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(double)); + align_length(&pStubMsg->BufferLength, sizeof(double)); safe_buffer_length_increment(pStubMsg, sizeof(double)); break; case RPC_FC_HYPER: - ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(ULONGLONG)); + align_length(&pStubMsg->BufferLength, sizeof(ULONGLONG)); safe_buffer_length_increment(pStubMsg, sizeof(ULONGLONG)); break; case RPC_FC_ERROR_STATUS_T: - ALIGN_LENGTH(pStubMsg->BufferLength, sizeof(error_status_t)); + align_length(&pStubMsg->BufferLength, sizeof(error_status_t)); safe_buffer_length_increment(pStubMsg, sizeof(error_status_t)); break; case RPC_FC_IGNORE: @@ -6670,51 +6837,58 @@ static ULONG WINAPI NdrBaseTypeMemorySize( case RPC_FC_WCHAR: case RPC_FC_SHORT: case RPC_FC_USHORT: - ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT)); + align_pointer(&pStubMsg->Buffer, sizeof(USHORT)); safe_buffer_increment(pStubMsg, sizeof(USHORT)); - ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(USHORT)); + align_length(&pStubMsg->MemorySize, sizeof(USHORT)); pStubMsg->MemorySize += sizeof(USHORT); return sizeof(USHORT); case RPC_FC_LONG: case RPC_FC_ULONG: case RPC_FC_ENUM32: - ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONG)); + align_pointer(&pStubMsg->Buffer, sizeof(ULONG)); safe_buffer_increment(pStubMsg, sizeof(ULONG)); - ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(ULONG)); + align_length(&pStubMsg->MemorySize, sizeof(ULONG)); pStubMsg->MemorySize += sizeof(ULONG); return sizeof(ULONG); case RPC_FC_FLOAT: - ALIGN_POINTER(pStubMsg->Buffer, sizeof(float)); + align_pointer(&pStubMsg->Buffer, sizeof(float)); safe_buffer_increment(pStubMsg, sizeof(float)); - ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(float)); + align_length(&pStubMsg->MemorySize, sizeof(float)); pStubMsg->MemorySize += sizeof(float); return sizeof(float); case RPC_FC_DOUBLE: - ALIGN_POINTER(pStubMsg->Buffer, sizeof(double)); + align_pointer(&pStubMsg->Buffer, sizeof(double)); safe_buffer_increment(pStubMsg, sizeof(double)); - ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(double)); + align_length(&pStubMsg->MemorySize, sizeof(double)); pStubMsg->MemorySize += sizeof(double); return sizeof(double); case RPC_FC_HYPER: - ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONGLONG)); + align_pointer(&pStubMsg->Buffer, sizeof(ULONGLONG)); safe_buffer_increment(pStubMsg, sizeof(ULONGLONG)); - ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(ULONGLONG)); + align_length(&pStubMsg->MemorySize, sizeof(ULONGLONG)); pStubMsg->MemorySize += sizeof(ULONGLONG); return sizeof(ULONGLONG); case RPC_FC_ERROR_STATUS_T: - ALIGN_POINTER(pStubMsg->Buffer, sizeof(error_status_t)); + align_pointer(&pStubMsg->Buffer, sizeof(error_status_t)); safe_buffer_increment(pStubMsg, sizeof(error_status_t)); - ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(error_status_t)); + align_length(&pStubMsg->MemorySize, sizeof(error_status_t)); pStubMsg->MemorySize += sizeof(error_status_t); return sizeof(error_status_t); case RPC_FC_ENUM16: - ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT)); + align_pointer(&pStubMsg->Buffer, sizeof(USHORT)); safe_buffer_increment(pStubMsg, sizeof(USHORT)); - ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(UINT)); + align_length(&pStubMsg->MemorySize, sizeof(UINT)); pStubMsg->MemorySize += sizeof(UINT); return sizeof(UINT); + case RPC_FC_INT3264: + case RPC_FC_UINT3264: + align_pointer(&pStubMsg->Buffer, sizeof(UINT)); + safe_buffer_increment(pStubMsg, sizeof(UINT)); + align_length(&pStubMsg->MemorySize, sizeof(UINT_PTR)); + pStubMsg->MemorySize += sizeof(UINT_PTR); + return sizeof(UINT_PTR); case RPC_FC_IGNORE: - ALIGN_LENGTH(pStubMsg->MemorySize, sizeof(void *)); + align_length(&pStubMsg->MemorySize, sizeof(void *)); pStubMsg->MemorySize += sizeof(void *); return sizeof(void *); default: @@ -6750,7 +6924,7 @@ static void WINAPI NdrContextHandleBufferSize( ERR("invalid format type %x\n", *pFormat); RpcRaiseException(RPC_S_INTERNAL_ERROR); } - ALIGN_LENGTH(pStubMsg->BufferLength, 4); + align_length(&pStubMsg->BufferLength, 4); safe_buffer_length_increment(pStubMsg, cbNDRContext); } @@ -6836,7 +7010,7 @@ void WINAPI NdrClientContextMarshall(PMIDL_STUB_MESSAGE pStubMsg, { TRACE("(%p, %p, %d)\n", pStubMsg, ContextHandle, fCheck); - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4); + align_pointer_clear(&pStubMsg->Buffer, 4); if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) { @@ -6861,7 +7035,7 @@ void WINAPI NdrClientContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, { TRACE("(%p, %p, %p)\n", pStubMsg, pContextHandle, BindHandle); - ALIGN_POINTER(pStubMsg->Buffer, 4); + align_pointer(&pStubMsg->Buffer, 4); if (pStubMsg->Buffer + cbNDRContext > pStubMsg->BufferEnd) RpcRaiseException(RPC_X_BAD_STUB_DATA); @@ -6880,7 +7054,7 @@ void WINAPI NdrServerContextMarshall(PMIDL_STUB_MESSAGE pStubMsg, { TRACE("(%p, %p, %p)\n", pStubMsg, ContextHandle, RundownRoutine); - ALIGN_POINTER(pStubMsg->Buffer, 4); + align_pointer(&pStubMsg->Buffer, 4); if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) { @@ -6901,7 +7075,7 @@ NDR_SCONTEXT WINAPI NdrServerContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg) TRACE("(%p)\n", pStubMsg); - ALIGN_POINTER(pStubMsg->Buffer, 4); + align_pointer(&pStubMsg->Buffer, 4); if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) { @@ -6959,7 +7133,7 @@ void WINAPI NdrServerContextNewMarshall(PMIDL_STUB_MESSAGE pStubMsg, TRACE("(%p, %p, %p, %p)\n", pStubMsg, ContextHandle, RundownRoutine, pFormat); - ALIGN_POINTER(pStubMsg->Buffer, 4); + align_pointer(&pStubMsg->Buffer, 4); if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) { @@ -6992,7 +7166,7 @@ NDR_SCONTEXT WINAPI NdrServerContextNewUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, TRACE("(%p, %p)\n", pStubMsg, pFormat); - ALIGN_POINTER(pStubMsg->Buffer, 4); + align_pointer(&pStubMsg->Buffer, 4); if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) { diff --git a/reactos/dll/win32/rpcrt4/ndr_misc.h b/reactos/dll/win32/rpcrt4/ndr_misc.h index b0150c3a2eb..2ca89b1744d 100644 --- a/reactos/dll/win32/rpcrt4/ndr_misc.h +++ b/reactos/dll/win32/rpcrt4/ndr_misc.h @@ -32,7 +32,7 @@ struct IPSFactoryBuffer; PFORMAT_STRING ComputeConformanceOrVariance( MIDL_STUB_MESSAGE *pStubMsg, unsigned char *pMemory, - PFORMAT_STRING pFormat, ULONG_PTR def, ULONG_PTR *pCount); + PFORMAT_STRING pFormat, ULONG_PTR def, ULONG_PTR *pCount) DECLSPEC_HIDDEN; static inline PFORMAT_STRING ComputeConformance(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat, ULONG def) { @@ -56,12 +56,12 @@ typedef void (WINAPI *NDR_BUFFERSIZE)(PMIDL_STUB_MESSAGE, unsigned cha typedef ULONG (WINAPI *NDR_MEMORYSIZE)(PMIDL_STUB_MESSAGE, PFORMAT_STRING); typedef void (WINAPI *NDR_FREE) (PMIDL_STUB_MESSAGE, unsigned char*, PFORMAT_STRING); -extern const NDR_MARSHALL NdrMarshaller[]; -extern const NDR_UNMARSHALL NdrUnmarshaller[]; -extern const NDR_BUFFERSIZE NdrBufferSizer[]; -extern const NDR_MEMORYSIZE NdrMemorySizer[]; -extern const NDR_FREE NdrFreer[]; +extern const NDR_MARSHALL NdrMarshaller[] DECLSPEC_HIDDEN; +extern const NDR_UNMARSHALL NdrUnmarshaller[] DECLSPEC_HIDDEN; +extern const NDR_BUFFERSIZE NdrBufferSizer[] DECLSPEC_HIDDEN; +extern const NDR_MEMORYSIZE NdrMemorySizer[] DECLSPEC_HIDDEN; +extern const NDR_FREE NdrFreer[] DECLSPEC_HIDDEN; -ULONG ComplexStructSize(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat); +ULONG ComplexStructSize(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat) DECLSPEC_HIDDEN; #endif /* __WINE_NDR_MISC_H */ diff --git a/reactos/dll/win32/rpcrt4/ndr_ole.c b/reactos/dll/win32/rpcrt4/ndr_ole.c index a4c23c2c5c2..c3ab5297df3 100644 --- a/reactos/dll/win32/rpcrt4/ndr_ole.c +++ b/reactos/dll/win32/rpcrt4/ndr_ole.c @@ -78,7 +78,7 @@ static HMODULE LoadCOM(void) * (which also implements the MInterfacePointer structure) */ typedef struct RpcStreamImpl { - const IStreamVtbl *lpVtbl; + IStream IStream_iface; LONG RefCount; PMIDL_STUB_MESSAGE pMsg; LPDWORD size; @@ -86,11 +86,16 @@ typedef struct RpcStreamImpl DWORD pos; } RpcStreamImpl; +static inline RpcStreamImpl *impl_from_IStream(IStream *iface) +{ + return CONTAINING_RECORD(iface, RpcStreamImpl, IStream_iface); +} + static HRESULT WINAPI RpcStream_QueryInterface(LPSTREAM iface, REFIID riid, LPVOID *obj) { - RpcStreamImpl *This = (RpcStreamImpl *)iface; + RpcStreamImpl *This = impl_from_IStream(iface); if (IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_ISequentialStream, riid) || IsEqualGUID(&IID_IStream, riid)) { @@ -103,13 +108,13 @@ static HRESULT WINAPI RpcStream_QueryInterface(LPSTREAM iface, static ULONG WINAPI RpcStream_AddRef(LPSTREAM iface) { - RpcStreamImpl *This = (RpcStreamImpl *)iface; + RpcStreamImpl *This = impl_from_IStream(iface); return InterlockedIncrement( &This->RefCount ); } static ULONG WINAPI RpcStream_Release(LPSTREAM iface) { - RpcStreamImpl *This = (RpcStreamImpl *)iface; + RpcStreamImpl *This = impl_from_IStream(iface); ULONG ref = InterlockedDecrement( &This->RefCount ); if (!ref) { TRACE("size=%d\n", *This->size); @@ -125,7 +130,7 @@ static HRESULT WINAPI RpcStream_Read(LPSTREAM iface, ULONG cb, ULONG *pcbRead) { - RpcStreamImpl *This = (RpcStreamImpl *)iface; + RpcStreamImpl *This = impl_from_IStream(iface); HRESULT hr = S_OK; if (This->pos + cb > *This->size) { @@ -145,7 +150,7 @@ static HRESULT WINAPI RpcStream_Write(LPSTREAM iface, ULONG cb, ULONG *pcbWritten) { - RpcStreamImpl *This = (RpcStreamImpl *)iface; + RpcStreamImpl *This = impl_from_IStream(iface); if (This->data + cb > (unsigned char *)This->pMsg->RpcMsg->Buffer + This->pMsg->BufferLength) return STG_E_MEDIUMFULL; memcpy(This->data + This->pos, pv, cb); @@ -160,7 +165,7 @@ static HRESULT WINAPI RpcStream_Seek(LPSTREAM iface, DWORD origin, ULARGE_INTEGER *newPos) { - RpcStreamImpl *This = (RpcStreamImpl *)iface; + RpcStreamImpl *This = impl_from_IStream(iface); switch (origin) { case STREAM_SEEK_SET: This->pos = move.u.LowPart; @@ -184,7 +189,7 @@ static HRESULT WINAPI RpcStream_Seek(LPSTREAM iface, static HRESULT WINAPI RpcStream_SetSize(LPSTREAM iface, ULARGE_INTEGER newSize) { - RpcStreamImpl *This = (RpcStreamImpl *)iface; + RpcStreamImpl *This = impl_from_IStream(iface); *This->size = newSize.u.LowPart; return S_OK; } @@ -212,7 +217,7 @@ static LPSTREAM RpcStream_Create(PMIDL_STUB_MESSAGE pStubMsg, BOOL init) RpcStreamImpl *This; This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(RpcStreamImpl)); if (!This) return NULL; - This->lpVtbl = &RpcStream_Vtbl; + This->IStream_iface.lpVtbl = &RpcStream_Vtbl; This->RefCount = 1; This->pMsg = pStubMsg; This->size = (LPDWORD)pStubMsg->Buffer; @@ -309,13 +314,12 @@ void WINAPI NdrInterfacePointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg, { const IID *riid = get_ip_iid(pStubMsg, pMemory, pFormat); ULONG size = 0; - HRESULT hr; TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); if (!LoadCOM()) return; - hr = COM_GetMarshalSizeMax(&size, riid, (LPUNKNOWN)pMemory, - pStubMsg->dwDestContext, pStubMsg->pvDestContext, - MSHLFLAGS_NORMAL); + COM_GetMarshalSizeMax(&size, riid, (LPUNKNOWN)pMemory, + pStubMsg->dwDestContext, pStubMsg->pvDestContext, + MSHLFLAGS_NORMAL); TRACE("size=%d\n", size); pStubMsg->BufferLength += sizeof(DWORD) + size; } diff --git a/reactos/dll/win32/rpcrt4/ndr_stubless.c b/reactos/dll/win32/rpcrt4/ndr_stubless.c index fcd3fe50724..fa5aad0f877 100644 --- a/reactos/dll/win32/rpcrt4/ndr_stubless.c +++ b/reactos/dll/win32/rpcrt4/ndr_stubless.c @@ -50,9 +50,24 @@ WINE_DEFAULT_DEBUG_CHANNEL(rpc); #define NDR_TABLE_MASK 127 -static inline void call_buffer_sizer(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat) +static inline void call_buffer_sizer(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, + const NDR_PARAM_OIF *param) { - NDR_BUFFERSIZE m = NdrBufferSizer[pFormat[0] & NDR_TABLE_MASK]; + PFORMAT_STRING pFormat; + NDR_BUFFERSIZE m; + + if (param->attr.IsBasetype) + { + pFormat = ¶m->u.type_format_char; + if (param->attr.IsSimpleRef) pMemory = *(unsigned char **)pMemory; + } + else + { + pFormat = &pStubMsg->StubDesc->pFormatTypes[param->u.type_offset]; + if (!param->attr.IsByValue) pMemory = *(unsigned char **)pMemory; + } + + m = NdrBufferSizer[pFormat[0] & NDR_TABLE_MASK]; if (m) m(pStubMsg, pMemory, pFormat); else { @@ -61,9 +76,24 @@ static inline void call_buffer_sizer(PMIDL_STUB_MESSAGE pStubMsg, unsigned char } } -static inline unsigned char *call_marshaller(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat) +static inline unsigned char *call_marshaller(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, + const NDR_PARAM_OIF *param) { - NDR_MARSHALL m = NdrMarshaller[pFormat[0] & NDR_TABLE_MASK]; + PFORMAT_STRING pFormat; + NDR_MARSHALL m; + + if (param->attr.IsBasetype) + { + pFormat = ¶m->u.type_format_char; + if (param->attr.IsSimpleRef) pMemory = *(unsigned char **)pMemory; + } + else + { + pFormat = &pStubMsg->StubDesc->pFormatTypes[param->u.type_offset]; + if (!param->attr.IsByValue) pMemory = *(unsigned char **)pMemory; + } + + m = NdrMarshaller[pFormat[0] & NDR_TABLE_MASK]; if (m) return m(pStubMsg, pMemory, pFormat); else { @@ -73,9 +103,24 @@ static inline unsigned char *call_marshaller(PMIDL_STUB_MESSAGE pStubMsg, unsign } } -static inline unsigned char *call_unmarshaller(PMIDL_STUB_MESSAGE pStubMsg, unsigned char **ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc) +static inline unsigned char *call_unmarshaller(PMIDL_STUB_MESSAGE pStubMsg, unsigned char **ppMemory, + const NDR_PARAM_OIF *param, unsigned char fMustAlloc) { - NDR_UNMARSHALL m = NdrUnmarshaller[pFormat[0] & NDR_TABLE_MASK]; + PFORMAT_STRING pFormat; + NDR_UNMARSHALL m; + + if (param->attr.IsBasetype) + { + pFormat = ¶m->u.type_format_char; + if (param->attr.IsSimpleRef) ppMemory = (unsigned char **)*ppMemory; + } + else + { + pFormat = &pStubMsg->StubDesc->pFormatTypes[param->u.type_offset]; + if (!param->attr.IsByValue) ppMemory = (unsigned char **)*ppMemory; + } + + m = NdrUnmarshaller[pFormat[0] & NDR_TABLE_MASK]; if (m) return m(pStubMsg, ppMemory, pFormat, fMustAlloc); else { @@ -85,19 +130,85 @@ static inline unsigned char *call_unmarshaller(PMIDL_STUB_MESSAGE pStubMsg, unsi } } -static inline void call_freer(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat) +static inline void call_freer(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, + const NDR_PARAM_OIF *param) { - NDR_FREE m = NdrFreer[pFormat[0] & NDR_TABLE_MASK]; + PFORMAT_STRING pFormat; + NDR_FREE m; + + if (param->attr.IsBasetype) return; /* nothing to do */ + pFormat = &pStubMsg->StubDesc->pFormatTypes[param->u.type_offset]; + if (!param->attr.IsByValue) pMemory = *(unsigned char **)pMemory; + + m = NdrFreer[pFormat[0] & NDR_TABLE_MASK]; if (m) m(pStubMsg, pMemory, pFormat); } -#define STUBLESS_UNMARSHAL 1 -#define STUBLESS_INITOUT 2 -#define STUBLESS_CALLSERVER 3 -#define STUBLESS_CALCSIZE 4 -#define STUBLESS_GETBUFFER 5 -#define STUBLESS_MARSHAL 6 -#define STUBLESS_FREE 7 +static DWORD calc_arg_size(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat) +{ + DWORD size; + switch(*pFormat) + { + case RPC_FC_STRUCT: + case RPC_FC_PSTRUCT: + size = *(const WORD*)(pFormat + 2); + break; + case RPC_FC_BOGUS_STRUCT: + size = *(const WORD*)(pFormat + 2); + if(*(const WORD*)(pFormat + 4)) + FIXME("Unhandled conformant description\n"); + break; + case RPC_FC_CARRAY: + case RPC_FC_CVARRAY: + size = *(const WORD*)(pFormat + 2); + ComputeConformance(pStubMsg, NULL, pFormat + 4, 0); + size *= pStubMsg->MaxCount; + break; + case RPC_FC_SMFARRAY: + case RPC_FC_SMVARRAY: + size = *(const WORD*)(pFormat + 2); + break; + case RPC_FC_LGFARRAY: + case RPC_FC_LGVARRAY: + size = *(const DWORD*)(pFormat + 2); + break; + case RPC_FC_BOGUS_ARRAY: + pFormat = ComputeConformance(pStubMsg, NULL, pFormat + 4, *(const WORD*)&pFormat[2]); + TRACE("conformance = %ld\n", pStubMsg->MaxCount); + pFormat = ComputeVariance(pStubMsg, NULL, pFormat, pStubMsg->MaxCount); + size = ComplexStructSize(pStubMsg, pFormat); + size *= pStubMsg->MaxCount; + break; + case RPC_FC_USER_MARSHAL: + size = *(const WORD*)(pFormat + 4); + break; + case RPC_FC_CSTRING: + size = *(const WORD*)(pFormat + 2); + break; + case RPC_FC_WSTRING: + size = *(const WORD*)(pFormat + 2) * sizeof(WCHAR); + break; + case RPC_FC_C_CSTRING: + case RPC_FC_C_WSTRING: + if (*pFormat == RPC_FC_C_CSTRING) + size = sizeof(CHAR); + else + size = sizeof(WCHAR); + if (pFormat[1] == RPC_FC_STRING_SIZED) + ComputeConformance(pStubMsg, NULL, pFormat + 2, 0); + else + pStubMsg->MaxCount = 0; + size *= pStubMsg->MaxCount; + break; + default: + FIXME("Unhandled type %02x\n", *pFormat); + /* fallthrough */ + case RPC_FC_RP: + size = sizeof(void *); + break; + } + return size; +} void WINAPI NdrRpcSmSetClientToOsf(PMIDL_STUB_MESSAGE pMessage) { @@ -107,33 +218,41 @@ void WINAPI NdrRpcSmSetClientToOsf(PMIDL_STUB_MESSAGE pMessage) #endif } -static void dump_RPC_FC_PROC_PF(PARAM_ATTRIBUTES param_attributes) +static const char *debugstr_PROC_PF(PARAM_ATTRIBUTES param_attributes) { - if (param_attributes.MustSize) TRACE(" MustSize"); - if (param_attributes.MustFree) TRACE(" MustFree"); - if (param_attributes.IsPipe) TRACE(" IsPipe"); - if (param_attributes.IsIn) TRACE(" IsIn"); - if (param_attributes.IsOut) TRACE(" IsOut"); - if (param_attributes.IsReturn) TRACE(" IsReturn"); - if (param_attributes.IsBasetype) TRACE(" IsBasetype"); - if (param_attributes.IsByValue) TRACE(" IsByValue"); - if (param_attributes.IsSimpleRef) TRACE(" IsSimpleRef"); - if (param_attributes.IsDontCallFreeInst) TRACE(" IsDontCallFreeInst"); - if (param_attributes.SaveForAsyncFinish) TRACE(" SaveForAsyncFinish"); - if (param_attributes.ServerAllocSize) TRACE(" ServerAllocSize = %d", param_attributes.ServerAllocSize * 8); + char buffer[160]; + + buffer[0] = 0; + if (param_attributes.MustSize) strcat(buffer, " MustSize"); + if (param_attributes.MustFree) strcat(buffer, " MustFree"); + if (param_attributes.IsPipe) strcat(buffer, " IsPipe"); + if (param_attributes.IsIn) strcat(buffer, " IsIn"); + if (param_attributes.IsOut) strcat(buffer, " IsOut"); + if (param_attributes.IsReturn) strcat(buffer, " IsReturn"); + if (param_attributes.IsBasetype) strcat(buffer, " IsBasetype"); + if (param_attributes.IsByValue) strcat(buffer, " IsByValue"); + if (param_attributes.IsSimpleRef) strcat(buffer, " IsSimpleRef"); + if (param_attributes.IsDontCallFreeInst) strcat(buffer, " IsDontCallFreeInst"); + if (param_attributes.SaveForAsyncFinish) strcat(buffer, " SaveForAsyncFinish"); + if (param_attributes.ServerAllocSize) + sprintf( buffer + strlen(buffer), " ServerAllocSize = %d", param_attributes.ServerAllocSize * 8); + return buffer[0] ? wine_dbg_sprintf( "%s", buffer + 1 ) : ""; } -static void dump_INTERPRETER_OPT_FLAGS(INTERPRETER_OPT_FLAGS Oi2Flags) +static const char *debugstr_INTERPRETER_OPT_FLAGS(INTERPRETER_OPT_FLAGS Oi2Flags) { - if (Oi2Flags.ServerMustSize) TRACE(" ServerMustSize"); - if (Oi2Flags.ClientMustSize) TRACE(" ClientMustSize"); - if (Oi2Flags.HasReturn) TRACE(" HasReturn"); - if (Oi2Flags.HasPipes) TRACE(" HasPipes"); - if (Oi2Flags.Unused) TRACE(" Unused"); - if (Oi2Flags.HasAsyncUuid) TRACE(" HasAsyncUuid"); - if (Oi2Flags.HasExtensions) TRACE(" HasExtensions"); - if (Oi2Flags.HasAsyncHandle) TRACE(" HasAsyncHandle"); - TRACE("\n"); + char buffer[160]; + + buffer[0] = 0; + if (Oi2Flags.ServerMustSize) strcat(buffer, " ServerMustSize"); + if (Oi2Flags.ClientMustSize) strcat(buffer, " ClientMustSize"); + if (Oi2Flags.HasReturn) strcat(buffer, " HasReturn"); + if (Oi2Flags.HasPipes) strcat(buffer, " HasPipes"); + if (Oi2Flags.Unused) strcat(buffer, " Unused"); + if (Oi2Flags.HasAsyncUuid) strcat(buffer, " HasAsyncUuid"); + if (Oi2Flags.HasExtensions) strcat(buffer, " HasExtensions"); + if (Oi2Flags.HasAsyncHandle) strcat(buffer, " HasAsyncHandle"); + return buffer[0] ? wine_dbg_sprintf( "%s", buffer + 1 ) : ""; } #define ARG_FROM_OFFSET(args, offset) ((args) + (offset)) @@ -173,7 +292,7 @@ static PFORMAT_STRING client_get_handle( if (pDesc->flag_and_size & HANDLE_PARAM_IS_VIA_PTR) pArg = *(void **)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset); else - pArg = (void *)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset); + pArg = ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset); memcpy(&pObject, pArg, pDesc->flag_and_size & 0xf); pGenPair = &pStubMsg->StubDesc->aGenericBindingRoutinePairs[pDesc->binding_routine_pair_index]; *phBinding = pGenPair->pfnBind(pObject); @@ -191,14 +310,14 @@ static PFORMAT_STRING client_get_handle( } else context_handle = *(NDR_CCONTEXT *)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset); - if ((pDesc->flags & NDR_CONTEXT_HANDLE_CANNOT_BE_NULL) && - !context_handle) + + if (context_handle) *phBinding = NDRCContextBinding(context_handle); + else if (pDesc->flags & NDR_CONTEXT_HANDLE_CANNOT_BE_NULL) { ERR("null context handle isn't allowed\n"); RpcRaiseException(RPC_X_SS_IN_NULL_CONTEXT); return NULL; } - *phBinding = NDRCContextBinding(context_handle); /* FIXME: should we store this structure in stubMsg.pContext? */ return pFormat + sizeof(NDR_EHD_CONTEXT); } @@ -256,7 +375,7 @@ static void client_free_handle( if (pDesc->flag_and_size & HANDLE_PARAM_IS_VIA_PTR) pArg = *(void **)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset); else - pArg = (void *)ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset); + pArg = ARG_FROM_OFFSET(pStubMsg->StackTop, pDesc->offset); memcpy(&pObject, pArg, pDesc->flag_and_size & 0xf); pGenPair = &pStubMsg->StubDesc->aGenericBindingRoutinePairs[pDesc->binding_routine_pair_index]; pGenPair->pfnUnbind(pObject, hBinding); @@ -284,123 +403,65 @@ static void client_free_handle( } } -static void client_do_args(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, - int phase, unsigned char *args, unsigned short number_of_params, - unsigned char *pRetVal) +void client_do_args( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, enum stubless_phase phase, + void **fpu_args, unsigned short number_of_params, unsigned char *pRetVal ) { - /* current format string offset */ - int current_offset = 0; - /* current stack offset */ - unsigned short current_stack_offset = 0; - /* counter */ - unsigned short i; + const NDR_PARAM_OIF *params = (const NDR_PARAM_OIF *)pFormat; + unsigned int i; for (i = 0; i < number_of_params; i++) { - const NDR_PARAM_OIF_BASETYPE *pParam = - (const NDR_PARAM_OIF_BASETYPE *)&pFormat[current_offset]; - unsigned char * pArg; + unsigned char *pArg = pStubMsg->StackTop + params[i].stack_offset; + PFORMAT_STRING pTypeFormat = (PFORMAT_STRING)&pStubMsg->StubDesc->pFormatTypes[params[i].u.type_offset]; - current_stack_offset = pParam->stack_offset; - pArg = ARG_FROM_OFFSET(args, current_stack_offset); +#ifdef __x86_64__ /* floats are passed as doubles through varargs functions */ + float f; - TRACE("param[%d]: new format\n", i); - TRACE("\tparam_attributes:"); dump_RPC_FC_PROC_PF(pParam->param_attributes); TRACE("\n"); - TRACE("\tstack_offset: 0x%x\n", current_stack_offset); - TRACE("\tmemory addr (before): %p\n", pArg); - - if (pParam->param_attributes.IsBasetype) + if (params[i].attr.IsBasetype && + params[i].u.type_format_char == RPC_FC_FLOAT && + !params[i].attr.IsSimpleRef && + !fpu_args) { - const unsigned char * pTypeFormat = - &pParam->type_format_char; - - if (pParam->param_attributes.IsSimpleRef) - pArg = *(unsigned char **)pArg; - - TRACE("\tbase type: 0x%02x\n", *pTypeFormat); - - switch (phase) - { - case PROXY_CALCSIZE: - if (pParam->param_attributes.IsIn) - call_buffer_sizer(pStubMsg, pArg, pTypeFormat); - break; - case PROXY_MARSHAL: - if (pParam->param_attributes.IsIn) - call_marshaller(pStubMsg, pArg, pTypeFormat); - break; - case PROXY_UNMARSHAL: - if (pParam->param_attributes.IsOut) - { - if (pParam->param_attributes.IsReturn) - call_unmarshaller(pStubMsg, &pRetVal, pTypeFormat, 0); - else - call_unmarshaller(pStubMsg, &pArg, pTypeFormat, 0); - TRACE("pRetVal = %p\n", pRetVal); - } - break; - default: - RpcRaiseException(RPC_S_INTERNAL_ERROR); - } - - current_offset += sizeof(NDR_PARAM_OIF_BASETYPE); + f = *(double *)pArg; + pArg = (unsigned char *)&f; } - else +#endif + + TRACE("param[%d]: %p type %02x %s\n", i, pArg, + params[i].attr.IsBasetype ? params[i].u.type_format_char : *pTypeFormat, + debugstr_PROC_PF( params[i].attr )); + + switch (phase) { - const NDR_PARAM_OIF_OTHER *pParamOther = - (const NDR_PARAM_OIF_OTHER *)&pFormat[current_offset]; - - const unsigned char * pTypeFormat = - &(pStubMsg->StubDesc->pFormatTypes[pParamOther->type_offset]); - - /* if a simple ref pointer then we have to do the - * check for the pointer being non-NULL. */ - if (pParam->param_attributes.IsSimpleRef) + case STUBLESS_INITOUT: + if (!params[i].attr.IsBasetype && params[i].attr.IsOut && + !params[i].attr.IsIn && !params[i].attr.IsByValue) { - if (!*(unsigned char **)pArg) - RpcRaiseException(RPC_X_NULL_REF_POINTER); + memset( *(unsigned char **)pArg, 0, calc_arg_size( pStubMsg, pTypeFormat )); } - - TRACE("\tcomplex type: 0x%02x\n", *pTypeFormat); - - switch (phase) + break; + case STUBLESS_CALCSIZE: + if (params[i].attr.IsSimpleRef && !*(unsigned char **)pArg) + RpcRaiseException(RPC_X_NULL_REF_POINTER); + if (params[i].attr.IsIn) call_buffer_sizer(pStubMsg, pArg, ¶ms[i]); + break; + case STUBLESS_MARSHAL: + if (params[i].attr.IsIn) call_marshaller(pStubMsg, pArg, ¶ms[i]); + break; + case STUBLESS_UNMARSHAL: + if (params[i].attr.IsOut) { - case PROXY_CALCSIZE: - if (pParam->param_attributes.IsIn) - { - if (pParam->param_attributes.IsByValue) - call_buffer_sizer(pStubMsg, pArg, pTypeFormat); - else - call_buffer_sizer(pStubMsg, *(unsigned char **)pArg, pTypeFormat); - } - break; - case PROXY_MARSHAL: - if (pParam->param_attributes.IsIn) - { - if (pParam->param_attributes.IsByValue) - call_marshaller(pStubMsg, pArg, pTypeFormat); - else - call_marshaller(pStubMsg, *(unsigned char **)pArg, pTypeFormat); - } - break; - case PROXY_UNMARSHAL: - if (pParam->param_attributes.IsOut) - { - if (pParam->param_attributes.IsReturn) - call_unmarshaller(pStubMsg, &pRetVal, pTypeFormat, 0); - else if (pParam->param_attributes.IsByValue) - call_unmarshaller(pStubMsg, &pArg, pTypeFormat, 0); - else - call_unmarshaller(pStubMsg, (unsigned char **)pArg, pTypeFormat, 0); - } - break; - default: - RpcRaiseException(RPC_S_INTERNAL_ERROR); + if (params[i].attr.IsReturn && pRetVal) pArg = pRetVal; + call_unmarshaller(pStubMsg, &pArg, ¶ms[i], 0); } - - current_offset += sizeof(NDR_PARAM_OIF_OTHER); + break; + case STUBLESS_FREE: + if (!params[i].attr.IsBasetype && params[i].attr.IsOut && !params[i].attr.IsByValue) + NdrClearOutParameters( pStubMsg, pTypeFormat, *(unsigned char **)pArg ); + break; + default: + RpcRaiseException(RPC_S_INTERNAL_ERROR); } - TRACE("\tmemory addr (after): %p\n", pArg); } } @@ -412,143 +473,119 @@ static unsigned int type_stack_size(unsigned char fc) case RPC_FC_CHAR: case RPC_FC_SMALL: case RPC_FC_USMALL: - return sizeof(char); case RPC_FC_WCHAR: case RPC_FC_SHORT: case RPC_FC_USHORT: - return sizeof(short); case RPC_FC_LONG: case RPC_FC_ULONG: + case RPC_FC_INT3264: + case RPC_FC_UINT3264: case RPC_FC_ENUM16: case RPC_FC_ENUM32: - return sizeof(int); case RPC_FC_FLOAT: - return sizeof(float); + case RPC_FC_ERROR_STATUS_T: + case RPC_FC_IGNORE: + return sizeof(void *); case RPC_FC_DOUBLE: return sizeof(double); case RPC_FC_HYPER: return sizeof(ULONGLONG); - case RPC_FC_ERROR_STATUS_T: - return sizeof(error_status_t); - case RPC_FC_IGNORE: - return sizeof(void *); default: ERR("invalid base type 0x%x\n", fc); RpcRaiseException(RPC_S_INTERNAL_ERROR); } } -void client_do_args_old_format(PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat, int phase, unsigned char *args, - unsigned short stack_size, - unsigned char *pRetVal, BOOL object_proc, BOOL ignore_retval) +static BOOL is_by_value( PFORMAT_STRING format ) { - /* current format string offset */ - int current_offset = 0; - /* current stack offset */ - unsigned short current_stack_offset = 0; - /* counter */ - unsigned short i; - - /* NOTE: V1 style format doesn't terminate on the number_of_params - * condition as it doesn't have this attribute. Instead it - * terminates when the stack size given in the header is exceeded. - */ - for (i = 0; TRUE; i++) + switch (*format) { - const NDR_PARAM_OI_BASETYPE *pParam = - (const NDR_PARAM_OI_BASETYPE *)&pFormat[current_offset]; - /* note: current_stack_offset starts after the This pointer - * if present, so adjust this */ - unsigned short current_stack_offset_adjusted = current_stack_offset + - (object_proc ? sizeof(void *) : 0); - unsigned char * pArg = ARG_FROM_OFFSET(args, current_stack_offset_adjusted); - - /* no more parameters; exit loop */ - if (current_stack_offset_adjusted >= stack_size) - break; - - TRACE("param[%d]: old format\n", i); - TRACE("\tparam_direction: 0x%x\n", pParam->param_direction); - TRACE("\tstack_offset: 0x%x\n", current_stack_offset_adjusted); - TRACE("\tmemory addr (before): %p\n", pArg); - - if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE || - pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE) - { - const unsigned char * pTypeFormat = - &pParam->type_format_char; - - TRACE("\tbase type 0x%02x\n", *pTypeFormat); - - switch (phase) - { - case PROXY_CALCSIZE: - if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE) - call_buffer_sizer(pStubMsg, pArg, pTypeFormat); - break; - case PROXY_MARSHAL: - if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE) - call_marshaller(pStubMsg, pArg, pTypeFormat); - break; - case PROXY_UNMARSHAL: - if (!ignore_retval && - pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE) - { - if (pParam->param_direction & RPC_FC_RETURN_PARAM) - call_unmarshaller(pStubMsg, &pRetVal, pTypeFormat, 0); - else - call_unmarshaller(pStubMsg, &pArg, pTypeFormat, 0); - } - break; - default: - RpcRaiseException(RPC_S_INTERNAL_ERROR); - } - - current_stack_offset += type_stack_size(*pTypeFormat); - current_offset += sizeof(NDR_PARAM_OI_BASETYPE); - } - else - { - const NDR_PARAM_OI_OTHER *pParamOther = - (const NDR_PARAM_OI_OTHER *)&pFormat[current_offset]; - - const unsigned char *pTypeFormat = - &pStubMsg->StubDesc->pFormatTypes[pParamOther->type_offset]; - - TRACE("\tcomplex type 0x%02x\n", *pTypeFormat); - - switch (phase) - { - case PROXY_CALCSIZE: - if (pParam->param_direction == RPC_FC_IN_PARAM || - pParam->param_direction & RPC_FC_IN_OUT_PARAM) - call_buffer_sizer(pStubMsg, *(unsigned char **)pArg, pTypeFormat); - break; - case PROXY_MARSHAL: - if (pParam->param_direction == RPC_FC_IN_PARAM || - pParam->param_direction & RPC_FC_IN_OUT_PARAM) - call_marshaller(pStubMsg, *(unsigned char **)pArg, pTypeFormat); - break; - case PROXY_UNMARSHAL: - if (pParam->param_direction == RPC_FC_IN_OUT_PARAM || - pParam->param_direction == RPC_FC_OUT_PARAM) - call_unmarshaller(pStubMsg, (unsigned char **)pArg, pTypeFormat, 0); - else if (pParam->param_direction == RPC_FC_RETURN_PARAM) - call_unmarshaller(pStubMsg, (unsigned char **)pRetVal, pTypeFormat, 0); - break; - default: - RpcRaiseException(RPC_S_INTERNAL_ERROR); - } - - current_stack_offset += pParamOther->stack_size * sizeof(INT); - current_offset += sizeof(NDR_PARAM_OI_OTHER); - } - TRACE("\tmemory addr (after): %p\n", pArg); + case RPC_FC_USER_MARSHAL: + case RPC_FC_STRUCT: + case RPC_FC_PSTRUCT: + case RPC_FC_CSTRUCT: + case RPC_FC_CPSTRUCT: + case RPC_FC_CVSTRUCT: + case RPC_FC_BOGUS_STRUCT: + return TRUE; + default: + return FALSE; } } -CLIENT_CALL_RETURN WINAPIV NdrClientCall2(PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pFormat, ...) +PFORMAT_STRING convert_old_args( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, + unsigned int stack_size, BOOL object_proc, + void *buffer, unsigned int size, unsigned int *count ) +{ + NDR_PARAM_OIF *args = buffer; + unsigned int i, stack_offset = object_proc ? sizeof(void *) : 0; + + for (i = 0; stack_offset < stack_size; i++) + { + const NDR_PARAM_OI_BASETYPE *param = (const NDR_PARAM_OI_BASETYPE *)pFormat; + const NDR_PARAM_OI_OTHER *other = (const NDR_PARAM_OI_OTHER *)pFormat; + + if (i + 1 > size / sizeof(*args)) + { + FIXME( "%u args not supported\n", i ); + RpcRaiseException( RPC_S_INTERNAL_ERROR ); + } + + args[i].stack_offset = stack_offset; + memset( &args[i].attr, 0, sizeof(args[i].attr) ); + + switch (param->param_direction) + { + case RPC_FC_IN_PARAM_BASETYPE: + args[i].attr.IsIn = 1; + args[i].attr.IsBasetype = 1; + break; + case RPC_FC_RETURN_PARAM_BASETYPE: + args[i].attr.IsOut = 1; + args[i].attr.IsReturn = 1; + args[i].attr.IsBasetype = 1; + break; + case RPC_FC_IN_PARAM: + args[i].attr.IsIn = 1; + args[i].attr.MustFree = 1; + break; + case RPC_FC_IN_PARAM_NO_FREE_INST: + args[i].attr.IsIn = 1; + args[i].attr.IsDontCallFreeInst = 1; + break; + case RPC_FC_IN_OUT_PARAM: + args[i].attr.IsIn = 1; + args[i].attr.IsOut = 1; + args[i].attr.MustFree = 1; + break; + case RPC_FC_OUT_PARAM: + args[i].attr.IsOut = 1; + break; + case RPC_FC_RETURN_PARAM: + args[i].attr.IsOut = 1; + args[i].attr.IsReturn = 1; + break; + } + if (args[i].attr.IsBasetype) + { + args[i].u.type_format_char = param->type_format_char; + stack_offset += type_stack_size( param->type_format_char ); + pFormat += sizeof(NDR_PARAM_OI_BASETYPE); + } + else + { + args[i].u.type_offset = other->type_offset; + args[i].attr.IsByValue = is_by_value( &pStubMsg->StubDesc->pFormatTypes[other->type_offset] ); + stack_offset += other->stack_size * sizeof(void *); + pFormat += sizeof(NDR_PARAM_OI_OTHER); + } + } + *count = i; + return (PFORMAT_STRING)args; +} + +LONG_PTR CDECL ndr_client_call( PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pFormat, + void **stack_top, void **fpu_stack ) { /* pointer to start of stack where arguments start */ RPC_MESSAGE rpcMsg; @@ -559,24 +596,20 @@ CLIENT_CALL_RETURN WINAPIV NdrClientCall2(PMIDL_STUB_DESC pStubDesc, PFORMAT_STR /* size of stack */ unsigned short stack_size; /* number of parameters. optional for client to give it to us */ - unsigned char number_of_params = ~0; + unsigned int number_of_params; /* 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; /* the value to return to the client from the remote procedure */ - CLIENT_CALL_RETURN RetVal = {0}; + LONG_PTR RetVal = 0; /* the pointer to the object when in OLE mode */ void * This = NULL; PFORMAT_STRING pHandleFormat; /* correlation cache */ - unsigned long NdrCorrCache[256]; + ULONG_PTR NdrCorrCache[256]; TRACE("pStubDesc %p, pFormat %p, ...\n", pStubDesc, pFormat); @@ -605,7 +638,7 @@ CLIENT_CALL_RETURN WINAPIV NdrClientCall2(PMIDL_STUB_DESC pStubDesc, PFORMAT_STR if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT) { /* object is always the first argument */ - This = **(void *const **)(&pFormat+1); + This = stack_top[0]; NdrProxyInitialize(This, &rpcMsg, &stubMsg, pStubDesc, procedure_number); } else @@ -614,25 +647,17 @@ CLIENT_CALL_RETURN WINAPIV NdrClientCall2(PMIDL_STUB_DESC pStubDesc, PFORMAT_STR 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__ - stubMsg.StackTop = *(unsigned char **)(&pFormat+1); -#else -# warning Stack not retrieved for your CPU architecture -#endif - + stubMsg.StackTop = (unsigned char *)stack_top; pHandleFormat = pFormat; /* we only need a handle if this isn't an object method */ if (!(pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)) { pFormat = client_get_handle(&stubMsg, pProcHeader, pHandleFormat, &hBinding); - if (!pFormat) return RetVal; + if (!pFormat) goto done; } - bV2Format = (pStubDesc->Version >= 0x20000); - - if (bV2Format) + if (pStubDesc->Version >= 0x20000) /* -Oicf format */ { const NDR_PROC_PARTIAL_OIF_HEADER *pOIFHeader = (const NDR_PROC_PARTIAL_OIF_HEADER *)pFormat; @@ -641,16 +666,35 @@ CLIENT_CALL_RETURN WINAPIV NdrClientCall2(PMIDL_STUB_DESC pStubDesc, PFORMAT_STR number_of_params = pOIFHeader->number_of_params; pFormat += sizeof(NDR_PROC_PARTIAL_OIF_HEADER); + + TRACE("Oif_flags = %s\n", debugstr_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; +#ifdef __x86_64__ + if (pExtensions->Size > sizeof(*pExtensions) && fpu_stack) + { + int i; + unsigned short fpu_mask = *(unsigned short *)(pExtensions + 1); + for (i = 0; i < 4; i++, fpu_mask >>= 2) + switch (fpu_mask & 3) + { + case 1: *(float *)&stack_top[i] = *(float *)&fpu_stack[i]; break; + case 2: *(double *)&stack_top[i] = *(double *)&fpu_stack[i]; break; + } + } +#endif + } } - - TRACE("Oif_flags = "); dump_INTERPRETER_OPT_FLAGS(Oif_flags); - - if (Oif_flags.HasExtensions) + else { - const NDR_PROC_HEADER_EXTS *pExtensions = - (const NDR_PROC_HEADER_EXTS *)pFormat; - ext_flags = pExtensions->Flags2; - pFormat += pExtensions->Size; + pFormat = convert_old_args( &stubMsg, pFormat, stack_size, + pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT, + /* reuse the correlation cache, it's not needed for v1 format */ + NdrCorrCache, sizeof(NdrCorrCache), &number_of_params ); } stubMsg.BufferLength = 0; @@ -677,74 +721,41 @@ CLIENT_CALL_RETURN WINAPIV NdrClientCall2(PMIDL_STUB_DESC pStubDesc, PFORMAT_STR } /* 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/receive buffer - * 5. PROXY_UNMARHSAL - unmarshal [out] params from buffer + * 1. INITOUT - zero [out] parameters (proxies only) + * 2. CALCSIZE - calculate the buffer size + * 3. GETBUFFER - allocate the buffer + * 4. MARSHAL - marshal [in] params into the buffer + * 5. SENDRECEIVE - send/receive buffer + * 6. UNMARSHAL - unmarshal [out] params from buffer + * 7. FREE - clear [out] parameters (for proxies, and only on error) */ - if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT) + if ((pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT) || + (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_HAS_COMM_OR_FAULT)) { + /* 1. INITOUT */ + if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT) + { + TRACE( "INITOUT\n" ); + client_do_args(&stubMsg, pFormat, STUBLESS_INITOUT, fpu_stack, + number_of_params, (unsigned char *)&RetVal); + } + __TRY { - for (phase = PROXY_CALCSIZE; phase <= PROXY_UNMARSHAL; phase++) + /* 2. CALCSIZE */ + TRACE( "CALCSIZE\n" ); + client_do_args(&stubMsg, pFormat, STUBLESS_CALCSIZE, fpu_stack, + number_of_params, (unsigned char *)&RetVal); + + /* 3. GETBUFFER */ + TRACE( "GETBUFFER\n" ); + if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT) { - TRACE("phase = %d\n", phase); - switch (phase) - { - case PROXY_GETBUFFER: - /* allocate the buffer */ - NdrProxyGetBuffer(This, &stubMsg); - break; - case PROXY_SENDRECEIVE: - /* send the [in] params and receive the [out] and [retval] - * params */ - NdrProxySendReceive(This, &stubMsg); - - /* convert strings, floating point values and endianess into our - * preferred format */ - if ((rpcMsg.DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION) - NdrConvert(&stubMsg, pFormat); - - break; - case PROXY_CALCSIZE: - case PROXY_MARSHAL: - case PROXY_UNMARSHAL: - if (bV2Format) - client_do_args(&stubMsg, pFormat, phase, stubMsg.StackTop, - number_of_params, (unsigned char *)&RetVal); - else - client_do_args_old_format(&stubMsg, pFormat, phase, - stubMsg.StackTop, stack_size, (unsigned char *)&RetVal, - (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT), FALSE); - break; - default: - ERR("shouldn't reach here. phase %d\n", phase); - break; - } + /* allocate the buffer */ + NdrProxyGetBuffer(This, &stubMsg); } - } - __EXCEPT_ALL - { - RetVal.Simple = NdrProxyErrorHandler(GetExceptionCode()); - } - __ENDTRY - } - else - { - /* 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/receive buffer - * 5. PROXY_UNMARHSAL - unmarshal [out] params from buffer - */ - for (phase = PROXY_CALCSIZE; phase <= PROXY_UNMARSHAL; phase++) - { - TRACE("phase = %d\n", phase); - switch (phase) + else { - case PROXY_GETBUFFER: /* allocate the buffer */ if (Oif_flags.HasPipes) /* NdrGetPipeBuffer(...) */ @@ -755,13 +766,28 @@ CLIENT_CALL_RETURN WINAPIV NdrClientCall2(PMIDL_STUB_DESC pStubDesc, PFORMAT_STR #if 0 NdrNsGetBuffer(&stubMsg, stubMsg.BufferLength, hBinding); #else - FIXME("using auto handle - call NdrNsGetBuffer when it gets implemented\n"); + FIXME("using auto handle - call NdrNsGetBuffer when it gets implemented\n"); #endif else NdrGetBuffer(&stubMsg, stubMsg.BufferLength, hBinding); } - break; - case PROXY_SENDRECEIVE: + } + + /* 4. MARSHAL */ + TRACE( "MARSHAL\n" ); + client_do_args(&stubMsg, pFormat, STUBLESS_MARSHAL, fpu_stack, + number_of_params, (unsigned char *)&RetVal); + + /* 5. SENDRECEIVE */ + TRACE( "SENDRECEIVE\n" ); + if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT) + { + /* send the [in] params and receive the [out] and [retval] + * params */ + NdrProxySendReceive(This, &stubMsg); + } + else + { /* send the [in] params and receive the [out] and [retval] * params */ if (Oif_flags.HasPipes) @@ -773,34 +799,116 @@ CLIENT_CALL_RETURN WINAPIV NdrClientCall2(PMIDL_STUB_DESC pStubDesc, PFORMAT_STR #if 0 NdrNsSendReceive(&stubMsg, stubMsg.Buffer, pStubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle); #else - FIXME("using auto handle - call NdrNsSendReceive when it gets implemented\n"); + FIXME("using auto handle - call NdrNsSendReceive when it gets implemented\n"); #endif else NdrSendReceive(&stubMsg, stubMsg.Buffer); } + } - /* convert strings, floating point values and endianess into our - * preferred format */ - if ((rpcMsg.DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION) - NdrConvert(&stubMsg, pFormat); + /* convert strings, floating point values and endianess into our + * preferred format */ + if ((rpcMsg.DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION) + NdrConvert(&stubMsg, pFormat); - break; - case PROXY_CALCSIZE: - case PROXY_MARSHAL: - case PROXY_UNMARSHAL: - if (bV2Format) - client_do_args(&stubMsg, pFormat, phase, stubMsg.StackTop, - number_of_params, (unsigned char *)&RetVal); + /* 6. UNMARSHAL */ + TRACE( "UNMARSHAL\n" ); + client_do_args(&stubMsg, pFormat, STUBLESS_UNMARSHAL, fpu_stack, + number_of_params, (unsigned char *)&RetVal); + } + __EXCEPT_ALL + { + if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT) + { + /* 7. FREE */ + TRACE( "FREE\n" ); + client_do_args(&stubMsg, pFormat, STUBLESS_FREE, fpu_stack, + number_of_params, (unsigned char *)&RetVal); + RetVal = NdrProxyErrorHandler(GetExceptionCode()); + } + else + { + const COMM_FAULT_OFFSETS *comm_fault_offsets = &pStubDesc->CommFaultOffsets[procedure_number]; + ULONG *comm_status; + ULONG *fault_status; + + TRACE("comm_fault_offsets = {0x%hx, 0x%hx}\n", comm_fault_offsets->CommOffset, comm_fault_offsets->FaultOffset); + + if (comm_fault_offsets->CommOffset == -1) + comm_status = (ULONG *)&RetVal; + else if (comm_fault_offsets->CommOffset >= 0) + comm_status = *(ULONG **)ARG_FROM_OFFSET(stubMsg.StackTop, comm_fault_offsets->CommOffset); else - client_do_args_old_format(&stubMsg, pFormat, phase, - stubMsg.StackTop, stack_size, (unsigned char *)&RetVal, - (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT), FALSE); - break; - default: - ERR("shouldn't reach here. phase %d\n", phase); - break; + comm_status = NULL; + + if (comm_fault_offsets->FaultOffset == -1) + fault_status = (ULONG *)&RetVal; + else if (comm_fault_offsets->FaultOffset >= 0) + fault_status = *(ULONG **)ARG_FROM_OFFSET(stubMsg.StackTop, comm_fault_offsets->CommOffset); + else + fault_status = NULL; + + NdrMapCommAndFaultStatus(&stubMsg, comm_status, fault_status, + GetExceptionCode()); } } + __ENDTRY + } + else + { + /* 2. CALCSIZE */ + TRACE( "CALCSIZE\n" ); + client_do_args(&stubMsg, pFormat, STUBLESS_CALCSIZE, fpu_stack, + number_of_params, (unsigned char *)&RetVal); + + /* 3. GETBUFFER */ + TRACE( "GETBUFFER\n" ); + if (Oif_flags.HasPipes) + /* NdrGetPipeBuffer(...) */ + FIXME("pipes not supported yet\n"); + else + { + if (pProcHeader->handle_type == RPC_FC_AUTO_HANDLE) +#if 0 + NdrNsGetBuffer(&stubMsg, stubMsg.BufferLength, hBinding); +#else + FIXME("using auto handle - call NdrNsGetBuffer when it gets implemented\n"); +#endif + else + NdrGetBuffer(&stubMsg, stubMsg.BufferLength, hBinding); + } + + /* 4. MARSHAL */ + TRACE( "MARSHAL\n" ); + client_do_args(&stubMsg, pFormat, STUBLESS_MARSHAL, fpu_stack, + number_of_params, (unsigned char *)&RetVal); + + /* 5. SENDRECEIVE */ + TRACE( "SENDRECEIVE\n" ); + if (Oif_flags.HasPipes) + /* NdrPipesSendReceive(...) */ + FIXME("pipes not supported yet\n"); + else + { + if (pProcHeader->handle_type == RPC_FC_AUTO_HANDLE) +#if 0 + NdrNsSendReceive(&stubMsg, stubMsg.Buffer, pStubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle); +#else + FIXME("using auto handle - call NdrNsSendReceive when it gets implemented\n"); +#endif + else + NdrSendReceive(&stubMsg, stubMsg.Buffer); + } + + /* convert strings, floating point values and endianness into our + * preferred format */ + if ((rpcMsg.DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION) + NdrConvert(&stubMsg, pFormat); + + /* 6. UNMARSHAL */ + TRACE( "UNMARSHAL\n" ); + client_do_args(&stubMsg, pFormat, STUBLESS_UNMARSHAL, fpu_stack, + number_of_params, (unsigned char *)&RetVal); } if (ext_flags.HasNewCorrDesc) @@ -827,11 +935,43 @@ CLIENT_CALL_RETURN WINAPIV NdrClientCall2(PMIDL_STUB_DESC pStubDesc, PFORMAT_STR client_free_handle(&stubMsg, pProcHeader, pHandleFormat, hBinding); } - TRACE("RetVal = 0x%p\n", RetVal.Pointer); - +done: + TRACE("RetVal = 0x%lx\n", RetVal); return RetVal; } +#ifdef __x86_64__ + +__ASM_GLOBAL_FUNC( NdrClientCall2, + "movq %r8,0x18(%rsp)\n\t" + "movq %r9,0x20(%rsp)\n\t" + "leaq 0x18(%rsp),%r8\n\t" + "xorq %r9,%r9\n\t" + "subq $0x28,%rsp\n\t" + __ASM_CFI(".cfi_adjust_cfa_offset 0x28\n\t") + "call " __ASM_NAME("ndr_client_call") "\n\t" + "addq $0x28,%rsp\n\t" + __ASM_CFI(".cfi_adjust_cfa_offset -0x28\n\t") + "ret" ); + +#else /* __x86_64__ */ + +/*********************************************************************** + * NdrClientCall2 [RPCRT4.@] + */ +CLIENT_CALL_RETURN WINAPIV NdrClientCall2( PMIDL_STUB_DESC desc, PFORMAT_STRING format, ... ) +{ + __ms_va_list args; + LONG_PTR ret; + + __ms_va_start( args, format ); + ret = ndr_client_call( desc, format, va_arg( args, void ** ), NULL ); + __ms_va_end( args ); + return *(CLIENT_CALL_RETURN *)&ret; +} + +#endif /* __x86_64__ */ + /* Calls a function with the specified arguments, restoring the stack * properly afterwards as we don't know the calling convention of the * function */ @@ -865,9 +1005,14 @@ __declspec(naked) LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigne LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned int stack_size); __ASM_GLOBAL_FUNC(call_server_func, "pushl %ebp\n\t" - "movl %esp, %ebp\n\t" + __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") + __ASM_CFI(".cfi_rel_offset %ebp,0\n\t") + "movl %esp,%ebp\n\t" + __ASM_CFI(".cfi_def_cfa_register %ebp\n\t") "pushl %edi\n\t" /* Save registers */ + __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 */ @@ -880,9 +1025,55 @@ __ASM_GLOBAL_FUNC(call_server_func, "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" - "ret\n" ) + __ASM_CFI(".cfi_def_cfa %esp,4\n\t") + __ASM_CFI(".cfi_same_value %ebp\n\t") + "ret" ) +#elif defined __x86_64__ +LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned int stack_size); +__ASM_GLOBAL_FUNC( call_server_func, + "pushq %rbp\n\t" + __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t") + __ASM_CFI(".cfi_rel_offset %rbp,0\n\t") + "movq %rsp,%rbp\n\t" + __ASM_CFI(".cfi_def_cfa_register %rbp\n\t") + "pushq %rsi\n\t" + __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t") + "pushq %rdi\n\t" + __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t") + "movq %rcx,%rax\n\t" /* function to call */ + "movq $32,%rcx\n\t" /* allocate max(32,stack_size) bytes of stack space */ + "cmpq %rcx,%r8\n\t" + "cmovgq %r8,%rcx\n\t" + "subq %rcx,%rsp\n\t" + "andq $~15,%rsp\n\t" + "movq %r8,%rcx\n\t" + "shrq $3,%rcx\n\t" + "movq %rsp,%rdi\n\t" + "movq %rdx,%rsi\n\t" + "rep; movsq\n\t" /* copy arguments */ + "movq 0(%rsp),%rcx\n\t" + "movq 8(%rsp),%rdx\n\t" + "movq 16(%rsp),%r8\n\t" + "movq 24(%rsp),%r9\n\t" + "movq %rcx,%xmm0\n\t" + "movq %rdx,%xmm1\n\t" + "movq %r8,%xmm2\n\t" + "movq %r9,%xmm3\n\t" + "callq *%rax\n\t" + "leaq -16(%rbp),%rsp\n\t" /* restore stack */ + "popq %rdi\n\t" + __ASM_CFI(".cfi_same_value %rdi\n\t") + "popq %rsi\n\t" + __ASM_CFI(".cfi_same_value %rsi\n\t") + __ASM_CFI(".cfi_def_cfa_register %rsp\n\t") + "popq %rbp\n\t" + __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t") + __ASM_CFI(".cfi_same_value %rbp\n\t") + "ret") #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) @@ -892,344 +1083,90 @@ LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, uns } #endif -static DWORD calc_arg_size(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat) -{ - DWORD size; - switch(*pFormat) - { - case RPC_FC_STRUCT: - size = *(const WORD*)(pFormat + 2); - break; - case RPC_FC_CARRAY: - size = *(const WORD*)(pFormat + 2); - ComputeConformance(pStubMsg, NULL, pFormat + 4, 0); - size *= pStubMsg->MaxCount; - break; - case RPC_FC_SMFARRAY: - size = *(const WORD*)(pFormat + 2); - break; - case RPC_FC_LGFARRAY: - size = *(const DWORD*)(pFormat + 2); - break; - case RPC_FC_BOGUS_ARRAY: - pFormat = ComputeConformance(pStubMsg, NULL, pFormat + 4, *(const WORD*)&pFormat[2]); - TRACE("conformance = %ld\n", pStubMsg->MaxCount); - pFormat = ComputeVariance(pStubMsg, NULL, pFormat, pStubMsg->MaxCount); - size = ComplexStructSize(pStubMsg, pFormat); - size *= pStubMsg->MaxCount; - break; - default: - FIXME("Unhandled type %02x\n", *pFormat); - /* fallthrough */ - case RPC_FC_RP: - size = sizeof(void *); - break; - } - return size; -} - static LONG_PTR *stub_do_args(MIDL_STUB_MESSAGE *pStubMsg, - PFORMAT_STRING pFormat, int phase, - unsigned char *args, + PFORMAT_STRING pFormat, enum stubless_phase phase, unsigned short number_of_params) { - /* counter */ - unsigned short i; - /* current format string offset */ - int current_offset = 0; - /* current stack offset */ - unsigned short current_stack_offset = 0; - /* location to put retval into */ + const NDR_PARAM_OIF *params = (const NDR_PARAM_OIF *)pFormat; + unsigned int i; LONG_PTR *retval_ptr = NULL; for (i = 0; i < number_of_params; i++) { - const NDR_PARAM_OIF_BASETYPE *pParam = - (const NDR_PARAM_OIF_BASETYPE *)&pFormat[current_offset]; - unsigned char *pArg; + unsigned char *pArg = pStubMsg->StackTop + params[i].stack_offset; + const unsigned char *pTypeFormat = &pStubMsg->StubDesc->pFormatTypes[params[i].u.type_offset]; - current_stack_offset = pParam->stack_offset; - pArg = args + current_stack_offset; + TRACE("param[%d]: %p -> %p type %02x %s\n", i, + pArg, *(unsigned char **)pArg, + params[i].attr.IsBasetype ? params[i].u.type_format_char : *pTypeFormat, + debugstr_PROC_PF( params[i].attr )); - TRACE("param[%d]: new format\n", i); - TRACE("\tparam_attributes:"); dump_RPC_FC_PROC_PF(pParam->param_attributes); TRACE("\n"); - TRACE("\tstack_offset: 0x%x\n", current_stack_offset); - TRACE("\tmemory addr (before): %p -> %p\n", pArg, *(unsigned char **)pArg); - - if (pParam->param_attributes.IsBasetype) + switch (phase) { - const unsigned char *pTypeFormat = - &pParam->type_format_char; - - TRACE("\tbase type: 0x%02x\n", *pTypeFormat); - - /* make a note of the address of the return value parameter for later */ - if (pParam->param_attributes.IsReturn) - retval_ptr = (LONG_PTR *)pArg; - - switch (phase) + case STUBLESS_MARSHAL: + if (params[i].attr.IsOut || params[i].attr.IsReturn) + call_marshaller(pStubMsg, pArg, ¶ms[i]); + break; + case STUBLESS_FREE: + if (params[i].attr.MustFree) { - case STUBLESS_MARSHAL: - if (pParam->param_attributes.IsOut || pParam->param_attributes.IsReturn) - { - if (pParam->param_attributes.IsSimpleRef) - call_marshaller(pStubMsg, *(unsigned char **)pArg, pTypeFormat); - else - call_marshaller(pStubMsg, pArg, pTypeFormat); - } - break; - case STUBLESS_FREE: - if (pParam->param_attributes.ServerAllocSize) - HeapFree(GetProcessHeap(), 0, *(void **)pArg); - break; - case STUBLESS_INITOUT: - break; - case STUBLESS_UNMARSHAL: - if (pParam->param_attributes.ServerAllocSize) - *(void **)pArg = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, - pParam->param_attributes.ServerAllocSize * 8); - - if (pParam->param_attributes.IsIn) - { - if (pParam->param_attributes.IsSimpleRef) - call_unmarshaller(pStubMsg, (unsigned char **)pArg, pTypeFormat, 0); - else - call_unmarshaller(pStubMsg, &pArg, pTypeFormat, 0); - } - break; - case STUBLESS_CALCSIZE: - if (pParam->param_attributes.IsOut || pParam->param_attributes.IsReturn) - { - if (pParam->param_attributes.IsSimpleRef) - call_buffer_sizer(pStubMsg, *(unsigned char **)pArg, pTypeFormat); - else - call_buffer_sizer(pStubMsg, pArg, pTypeFormat); - } - break; - default: - RpcRaiseException(RPC_S_INTERNAL_ERROR); + call_freer(pStubMsg, pArg, ¶ms[i]); } - - current_offset += sizeof(NDR_PARAM_OIF_BASETYPE); - } - else - { - const NDR_PARAM_OIF_OTHER *pParamOther = - (const NDR_PARAM_OIF_OTHER *)&pFormat[current_offset]; - - const unsigned char * pTypeFormat = - &(pStubMsg->StubDesc->pFormatTypes[pParamOther->type_offset]); - - TRACE("\tcomplex type 0x%02x\n", *pTypeFormat); - - switch (phase) + else if (params[i].attr.ServerAllocSize) { - case STUBLESS_MARSHAL: - if (pParam->param_attributes.IsOut || pParam->param_attributes.IsReturn) - { - if (pParam->param_attributes.IsByValue) - call_marshaller(pStubMsg, pArg, pTypeFormat); - else - call_marshaller(pStubMsg, *(unsigned char **)pArg, pTypeFormat); - } - break; - case STUBLESS_FREE: - if (pParam->param_attributes.MustFree) - { - if (pParam->param_attributes.IsByValue) - call_freer(pStubMsg, pArg, pTypeFormat); - else - call_freer(pStubMsg, *(unsigned char **)pArg, pTypeFormat); - } - - if (pParam->param_attributes.IsOut && - !pParam->param_attributes.IsIn && - !pParam->param_attributes.IsByValue && - !pParam->param_attributes.ServerAllocSize) - { - pStubMsg->pfnFree(*(void **)pArg); - } - - if (pParam->param_attributes.ServerAllocSize) - HeapFree(GetProcessHeap(), 0, *(void **)pArg); - break; - case STUBLESS_INITOUT: - if (!pParam->param_attributes.IsIn && - pParam->param_attributes.IsOut && - !pParam->param_attributes.ServerAllocSize && - !pParam->param_attributes.IsByValue) - { - DWORD size = calc_arg_size(pStubMsg, pTypeFormat); - - if(size) - { - *(void **)pArg = NdrAllocate(pStubMsg, size); - memset(*(void **)pArg, 0, size); - } - } - break; - case STUBLESS_UNMARSHAL: - if (pParam->param_attributes.ServerAllocSize) - *(void **)pArg = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, - pParam->param_attributes.ServerAllocSize * 8); - - if (pParam->param_attributes.IsIn) - { - if (pParam->param_attributes.IsByValue) - call_unmarshaller(pStubMsg, &pArg, pTypeFormat, 0); - else - call_unmarshaller(pStubMsg, (unsigned char **)pArg, pTypeFormat, 0); - } - break; - case STUBLESS_CALCSIZE: - if (pParam->param_attributes.IsOut || pParam->param_attributes.IsReturn) - { - if (pParam->param_attributes.IsByValue) - call_buffer_sizer(pStubMsg, pArg, pTypeFormat); - else - call_buffer_sizer(pStubMsg, *(unsigned char **)pArg, pTypeFormat); - } - break; - default: - RpcRaiseException(RPC_S_INTERNAL_ERROR); + HeapFree(GetProcessHeap(), 0, *(void **)pArg); } + else if (params[i].attr.IsOut && + !params[i].attr.IsIn && + !params[i].attr.IsBasetype && + !params[i].attr.IsByValue) + { + if (*pTypeFormat != RPC_FC_BIND_CONTEXT) pStubMsg->pfnFree(*(void **)pArg); + } + break; + case STUBLESS_INITOUT: + if (!params[i].attr.IsIn && + params[i].attr.IsOut && + !params[i].attr.IsBasetype && + !params[i].attr.ServerAllocSize && + !params[i].attr.IsByValue) + { + if (*pTypeFormat == RPC_FC_BIND_CONTEXT) + { + NDR_SCONTEXT ctxt = NdrContextHandleInitialize(pStubMsg, pTypeFormat); + *(void **)pArg = NDRSContextValue(ctxt); + } + else + { + DWORD size = calc_arg_size(pStubMsg, pTypeFormat); + if (size) + { + *(void **)pArg = NdrAllocate(pStubMsg, size); + memset(*(void **)pArg, 0, size); + } + } + } + break; + case STUBLESS_UNMARSHAL: + if (params[i].attr.ServerAllocSize) + *(void **)pArg = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + params[i].attr.ServerAllocSize * 8); - current_offset += sizeof(NDR_PARAM_OIF_OTHER); + if (params[i].attr.IsIn) + call_unmarshaller(pStubMsg, &pArg, ¶ms[i], 0); + break; + case STUBLESS_CALCSIZE: + if (params[i].attr.IsOut || params[i].attr.IsReturn) + call_buffer_sizer(pStubMsg, pArg, ¶ms[i]); + break; + default: + RpcRaiseException(RPC_S_INTERNAL_ERROR); } TRACE("\tmemory addr (after): %p -> %p\n", pArg, *(unsigned char **)pArg); + + /* make a note of the address of the return value parameter for later */ + if (params[i].attr.IsReturn) retval_ptr = (LONG_PTR *)pArg; } - - return retval_ptr; -} - -static LONG_PTR *stub_do_old_args(MIDL_STUB_MESSAGE *pStubMsg, - PFORMAT_STRING pFormat, int phase, - unsigned char *args, - unsigned short stack_size, BOOL object) -{ - /* counter */ - unsigned short i; - /* current format string offset */ - int current_offset = 0; - /* current stack offset */ - unsigned short current_stack_offset = 0; - /* location to put retval into */ - LONG_PTR *retval_ptr = NULL; - - for (i = 0; TRUE; i++) - { - const NDR_PARAM_OI_BASETYPE *pParam = - (const NDR_PARAM_OI_BASETYPE *)&pFormat[current_offset]; - /* note: current_stack_offset starts after the This pointer - * if present, so adjust this */ - unsigned short current_stack_offset_adjusted = current_stack_offset + - (object ? sizeof(void *) : 0); - unsigned char *pArg = args + current_stack_offset_adjusted; - - /* no more parameters; exit loop */ - if (current_stack_offset_adjusted >= stack_size) - break; - - TRACE("param[%d]: old format\n", i); - TRACE("\tparam_direction: 0x%x\n", pParam->param_direction); - TRACE("\tstack_offset: 0x%x\n", current_stack_offset_adjusted); - - if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE || - pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE) - { - const unsigned char *pTypeFormat = - &pParam->type_format_char; - - TRACE("\tbase type 0x%02x\n", *pTypeFormat); - - if (pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE) - retval_ptr = (LONG_PTR *)pArg; - - switch (phase) - { - case STUBLESS_MARSHAL: - if (pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE) - call_marshaller(pStubMsg, pArg, pTypeFormat); - break; - case STUBLESS_FREE: - if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE) - call_freer(pStubMsg, pArg, pTypeFormat); - break; - case STUBLESS_UNMARSHAL: - if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE) - call_unmarshaller(pStubMsg, &pArg, pTypeFormat, 0); - break; - case STUBLESS_CALCSIZE: - if (pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE) - call_buffer_sizer(pStubMsg, pArg, pTypeFormat); - break; - default: - RpcRaiseException(RPC_S_INTERNAL_ERROR); - } - - current_stack_offset += type_stack_size(*pTypeFormat); - current_offset += sizeof(NDR_PARAM_OI_BASETYPE); - } - else - { - const NDR_PARAM_OI_OTHER *pParamOther = - (const NDR_PARAM_OI_OTHER *)&pFormat[current_offset]; - - const unsigned char * pTypeFormat = - &pStubMsg->StubDesc->pFormatTypes[pParamOther->type_offset]; - - TRACE("\tcomplex type 0x%02x\n", *pTypeFormat); - - if (pParam->param_direction == RPC_FC_RETURN_PARAM) - retval_ptr = (LONG_PTR *)pArg; - - switch (phase) - { - case STUBLESS_MARSHAL: - if (pParam->param_direction == RPC_FC_OUT_PARAM || - pParam->param_direction == RPC_FC_IN_OUT_PARAM || - pParam->param_direction == RPC_FC_RETURN_PARAM) - call_marshaller(pStubMsg, *(unsigned char **)pArg, pTypeFormat); - break; - case STUBLESS_FREE: - if (pParam->param_direction == RPC_FC_IN_OUT_PARAM || - pParam->param_direction == RPC_FC_IN_PARAM) - call_freer(pStubMsg, *(unsigned char **)pArg, pTypeFormat); - else if (pParam->param_direction == RPC_FC_OUT_PARAM) - pStubMsg->pfnFree(*(void **)pArg); - break; - case STUBLESS_INITOUT: - if (pParam->param_direction == RPC_FC_OUT_PARAM) - { - DWORD size = calc_arg_size(pStubMsg, pTypeFormat); - - if(size) - { - *(void **)pArg = NdrAllocate(pStubMsg, size); - memset(*(void **)pArg, 0, size); - } - } - break; - case STUBLESS_UNMARSHAL: - if (pParam->param_direction == RPC_FC_IN_OUT_PARAM || - pParam->param_direction == RPC_FC_IN_PARAM) - call_unmarshaller(pStubMsg, (unsigned char **)pArg, pTypeFormat, 0); - break; - case STUBLESS_CALCSIZE: - if (pParam->param_direction == RPC_FC_OUT_PARAM || - pParam->param_direction == RPC_FC_IN_OUT_PARAM || - pParam->param_direction == RPC_FC_RETURN_PARAM) - call_buffer_sizer(pStubMsg, *(unsigned char **)pArg, pTypeFormat); - break; - default: - RpcRaiseException(RPC_S_INTERNAL_ERROR); - } - - current_stack_offset += pParamOther->stack_size * sizeof(INT); - current_offset += sizeof(NDR_PARAM_OI_OTHER); - } - } - return retval_ptr; } @@ -1257,23 +1194,19 @@ LONG WINAPI NdrStubCall2( /* size of stack */ unsigned short stack_size; /* number of parameters. optional for client to give it to us */ - unsigned char number_of_params = ~0; + unsigned int number_of_params; /* 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; + enum stubless_phase phase; /* header for procedure string */ const NDR_PROC_HEADER *pProcHeader; - /* offset in format string for start of params */ - int parameter_start_offset; - /* current format string offset */ - int current_offset; - /* -Oif or -Oicf generated format */ - BOOL bV2Format = FALSE; /* location to put retval into */ LONG_PTR *retval_ptr = NULL; + /* correlation cache */ + ULONG_PTR NdrCorrCache[256]; TRACE("pThis %p, pChannel %p, pRpcMsg %p, pdwStubPhase %p\n", pThis, pChannel, pRpcMsg, pdwStubPhase); @@ -1288,21 +1221,17 @@ LONG WINAPI NdrStubCall2( TRACE("NDR Version: 0x%x\n", pStubDesc->Version); - /* create the full pointer translation tables, if requested */ - if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR) - stubMsg.FullPtrXlatTables = NdrFullPointerXlatInit(0,XLAT_SERVER); - if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS) { const NDR_PROC_HEADER_RPC *pProcHeader = (const NDR_PROC_HEADER_RPC *)&pFormat[0]; stack_size = pProcHeader->stack_size; - current_offset = sizeof(NDR_PROC_HEADER_RPC); + pFormat += sizeof(NDR_PROC_HEADER_RPC); } else { stack_size = pProcHeader->stack_size; - current_offset = sizeof(NDR_PROC_HEADER); + pFormat += sizeof(NDR_PROC_HEADER); } TRACE("Oi_flags = 0x%02x\n", pProcHeader->Oi_flags); @@ -1312,16 +1241,16 @@ LONG WINAPI NdrStubCall2( { /* explicit binding: parse additional section */ case RPC_FC_BIND_EXPLICIT: - switch (pFormat[current_offset]) /* handle_type */ + switch (*pFormat) /* handle_type */ { case RPC_FC_BIND_PRIMITIVE: /* explicit primitive */ - current_offset += sizeof(NDR_EHD_PRIMITIVE); + pFormat += sizeof(NDR_EHD_PRIMITIVE); break; case RPC_FC_BIND_GENERIC: /* explicit generic */ - current_offset += sizeof(NDR_EHD_GENERIC); + pFormat += sizeof(NDR_EHD_GENERIC); break; case RPC_FC_BIND_CONTEXT: /* explicit context */ - current_offset += sizeof(NDR_EHD_CONTEXT); + pFormat += sizeof(NDR_EHD_CONTEXT); break; default: ERR("bad explicit binding handle type (0x%02x)\n", pProcHeader->handle_type); @@ -1338,34 +1267,15 @@ LONG WINAPI NdrStubCall2( RpcRaiseException(RPC_X_BAD_STUB_DATA); } - bV2Format = (pStubDesc->Version >= 0x20000); - - if (bV2Format) - { - const NDR_PROC_PARTIAL_OIF_HEADER *pOIFHeader = - (const NDR_PROC_PARTIAL_OIF_HEADER *)&pFormat[current_offset]; - - Oif_flags = pOIFHeader->Oi2Flags; - number_of_params = pOIFHeader->number_of_params; - - current_offset += 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[current_offset]; - ext_flags = pExtensions->Flags2; - current_offset += pExtensions->Size; - } - if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT) NdrStubInitialize(pRpcMsg, &stubMsg, pStubDesc, pChannel); else NdrServerInitializeNew(pRpcMsg, &stubMsg, pStubDesc); + /* create the full pointer translation tables, if requested */ + if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR) + stubMsg.FullPtrXlatTables = NdrFullPointerXlatInit(0,XLAT_SERVER); + /* store the RPC flags away */ if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS) pRpcMsg->RpcFlags = ((const NDR_PROC_HEADER_RPC *)pProcHeader)->rpc_flags; @@ -1378,27 +1288,6 @@ LONG WINAPI NdrStubCall2( FIXME("Set RPCSS memory allocation routines\n"); #endif - 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 */ - FIXME("new correlation description not implemented\n"); - stubMsg.fHasNewCorrDesc = TRUE; - } - - /* convert strings, floating point values and endianess into our - * preferred format */ - if ((pRpcMsg->DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION) - NdrConvert(&stubMsg, pFormat); - - parameter_start_offset = current_offset; - TRACE("allocating memory for stack of size %x\n", stack_size); args = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, stack_size); @@ -1409,13 +1298,51 @@ LONG WINAPI NdrStubCall2( if (pThis) *(void **)args = ((CStdStubBuffer *)pThis)->pvServerObject; - /* order of phases: - * 1. STUBLESS_UNMARHSAL - unmarshal [in] params from buffer - * 2. STUBLESS_CALLSERVER - send/receive buffer - * 3. STUBLESS_CALCSIZE - get [out] buffer size - * 4. STUBLESS_GETBUFFER - allocate [out] buffer - * 5. STUBLESS_MARHSAL - marshal [out] params to buffer - */ + if (pStubDesc->Version >= 0x20000) /* -Oicf format */ + { + const NDR_PROC_PARTIAL_OIF_HEADER *pOIFHeader = (const NDR_PROC_PARTIAL_OIF_HEADER *)pFormat; + + Oif_flags = pOIFHeader->Oi2Flags; + number_of_params = pOIFHeader->number_of_params; + + pFormat += sizeof(NDR_PROC_PARTIAL_OIF_HEADER); + + TRACE("Oif_flags = %s\n", debugstr_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; + } + + 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 */ + FIXME("new correlation description not implemented\n"); + stubMsg.fHasNewCorrDesc = TRUE; + } + } + else + { + pFormat = convert_old_args( &stubMsg, pFormat, stack_size, + pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT, + /* reuse the correlation cache, it's not needed for v1 format */ + NdrCorrCache, sizeof(NdrCorrCache), &number_of_params ); + } + + /* convert strings, floating point values and endianess into our + * preferred format */ + if ((pRpcMsg->DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION) + NdrConvert(&stubMsg, pFormat); + for (phase = STUBLESS_UNMARSHAL; phase <= STUBLESS_FREE; phase++) { TRACE("phase = %d\n", phase); @@ -1463,7 +1390,7 @@ LONG WINAPI NdrStubCall2( pRpcMsg->BufferLength = stubMsg.BufferLength; /* allocate buffer for [out] and [ret] params */ - Status = I_RpcGetBuffer(pRpcMsg); + Status = I_RpcGetBuffer(pRpcMsg); if (Status) RpcRaiseException(Status); stubMsg.Buffer = pRpcMsg->Buffer; @@ -1474,14 +1401,7 @@ LONG WINAPI NdrStubCall2( case STUBLESS_CALCSIZE: case STUBLESS_MARSHAL: case STUBLESS_FREE: - if (bV2Format) - retval_ptr = stub_do_args(&stubMsg, &pFormat[parameter_start_offset], - phase, args, number_of_params); - else - retval_ptr = stub_do_old_args(&stubMsg, &pFormat[parameter_start_offset], - phase, args, stack_size, - (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)); - + retval_ptr = stub_do_args(&stubMsg, pFormat, phase, number_of_params); break; default: ERR("shouldn't reach here. phase %d\n", phase); @@ -1520,3 +1440,357 @@ void WINAPI NdrServerCall2(PRPC_MESSAGE pRpcMsg) DWORD dwPhase; NdrStubCall2(NULL, NULL, pRpcMsg, &dwPhase); } + +/*********************************************************************** + * NdrStubCall [RPCRT4.@] + */ +LONG WINAPI NdrStubCall( struct IRpcStubBuffer *This, struct IRpcChannelBuffer *channel, + PRPC_MESSAGE msg, DWORD *phase ) +{ + return NdrStubCall2( This, channel, msg, phase ); +} + +/*********************************************************************** + * NdrServerCall [RPCRT4.@] + */ +void WINAPI NdrServerCall( PRPC_MESSAGE msg ) +{ + DWORD phase; + NdrStubCall( NULL, NULL, msg, &phase ); +} + +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 int number_of_params; + /* correlation cache */ + ULONG_PTR NdrCorrCache[256]; +}; + +LONG_PTR CDECL ndr_async_client_call( PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pFormat, void **stack_top ) +{ + /* 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 }; + /* header for procedure string */ + const NDR_PROC_HEADER * pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0]; + /* -Oif or -Oicf generated format */ + BOOL bV2Format = FALSE; + RPC_STATUS status; + + 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->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 */ + pStubMsg->StackTop = I_RpcAllocate(async_call_data->stack_size); + memcpy(pStubMsg->StackTop, stack_top, async_call_data->stack_size); + + 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) goto done; + + 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 = %s\n", debugstr_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; + } + } + else + { + pFormat = convert_old_args( pStubMsg, pFormat, async_call_data->stack_size, + pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT, + async_call_data->NdrCorrCache, sizeof(async_call_data->NdrCorrCache), + &async_call_data->number_of_params ); + } + + 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. CALCSIZE - calculate the buffer size + * 2. GETBUFFER - allocate the buffer + * 3. MARSHAL - marshal [in] params into the buffer + * 4. SENDRECEIVE - send buffer + * Then in NdrpCompleteAsyncClientCall: + * 1. SENDRECEIVE - receive buffer + * 2. UNMARSHAL - unmarshal [out] params from buffer + */ + + /* 1. CALCSIZE */ + TRACE( "CALCSIZE\n" ); + client_do_args(pStubMsg, pFormat, STUBLESS_CALCSIZE, NULL, async_call_data->number_of_params, NULL); + + /* 2. GETBUFFER */ + TRACE( "GETBUFFER\n" ); + 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); + + /* 3. MARSHAL */ + TRACE( "MARSHAL\n" ); + client_do_args(pStubMsg, pFormat, STUBLESS_MARSHAL, NULL, async_call_data->number_of_params, NULL); + + /* 4. SENDRECEIVE */ + TRACE( "SEND\n" ); + 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); + } + } + +done: + 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; + /* header for procedure string */ + const NDR_PROC_HEADER * pProcHeader; + 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; + + /* order of phases: + * 1. CALCSIZE - calculate the buffer size + * 2. GETBUFFER - allocate the buffer + * 3. MARSHAL - marshal [in] params into the buffer + * 4. SENDRECEIVE - send buffer + * Then in NdrpCompleteAsyncClientCall: + * 1. SENDRECEIVE - receive buffer + * 2. UNMARSHAL - unmarshal [out] params from buffer + */ + + /* 1. SENDRECEIVE */ + TRACE( "RECEIVE\n" ); + 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 endianness into our + * preferred format */ +#if 0 + if ((pStubMsg->RpcMsg.DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION) + NdrConvert(pStubMsg, pFormat); +#endif + + /* 2. UNMARSHAL */ + TRACE( "UNMARSHAL\n" ); + client_do_args(pStubMsg, async_call_data->pParamFormat, STUBLESS_UNMARSHAL, + NULL, async_call_data->number_of_params, Reply); + +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; +} + +#ifdef __x86_64__ + +__ASM_GLOBAL_FUNC( NdrAsyncClientCall, + "movq %r8,0x18(%rsp)\n\t" + "movq %r9,0x20(%rsp)\n\t" + "leaq 0x18(%rsp),%r8\n\t" + "subq $0x28,%rsp\n\t" + __ASM_CFI(".cfi_adjust_cfa_offset 0x28\n\t") + "call " __ASM_NAME("ndr_async_client_call") "\n\t" + "addq $0x28,%rsp\n\t" + __ASM_CFI(".cfi_adjust_cfa_offset -0x28\n\t") + "ret" ); + +#else /* __x86_64__ */ + +/*********************************************************************** + * NdrAsyncClientCall [RPCRT4.@] + */ +CLIENT_CALL_RETURN WINAPIV NdrAsyncClientCall( PMIDL_STUB_DESC desc, PFORMAT_STRING format, ... ) +{ + __ms_va_list args; + LONG_PTR ret; + + __ms_va_start( args, format ); + ret = ndr_async_client_call( desc, format, va_arg( args, void ** )); + __ms_va_end( args ); + return *(CLIENT_CALL_RETURN *)&ret; +} + +#endif /* __x86_64__ */ + +RPCRTAPI LONG RPC_ENTRY NdrAsyncStubCall(struct IRpcStubBuffer* pThis, + struct IRpcChannelBuffer* pChannel, PRPC_MESSAGE pRpcMsg, + DWORD * pdwStubPhase) +{ + FIXME("unimplemented, expect crash!\n"); + return 0; +} diff --git a/reactos/dll/win32/rpcrt4/ndr_stubless.h b/reactos/dll/win32/rpcrt4/ndr_stubless.h index 9a6fb444783..61bc60682c1 100644 --- a/reactos/dll/win32/rpcrt4/ndr_stubless.h +++ b/reactos/dll/win32/rpcrt4/ndr_stubless.h @@ -85,7 +85,7 @@ typedef struct _NDR_PROC_HEADER_RPC * RPCF_Asynchronous = 0x4000 - [async] MIDL attribute * Reserved = 0x8000 */ - unsigned long rpc_flags; + unsigned int rpc_flags; unsigned short proc_num; unsigned short stack_size; @@ -141,31 +141,20 @@ typedef struct _NDR_PARAM_OI_OTHER unsigned short type_offset; } NDR_PARAM_OI_OTHER; -typedef struct _NDR_PARAM_OIF_BASETYPE +typedef struct { - PARAM_ATTRIBUTES param_attributes; - + PARAM_ATTRIBUTES attr; /* the offset on the calling stack where the parameter is located */ unsigned short stack_offset; - - /* see NDR_PARAM_OI_BASETYPE::type_format_char */ - unsigned char type_format_char; - - /* always FC_PAD */ - unsigned char unused; -} NDR_PARAM_OIF_BASETYPE; - -typedef struct _NDR_PARAM_OIF_OTHER -{ - PARAM_ATTRIBUTES param_attributes; - - /* see NDR_PARAM_OIF_BASETYPE::stack_offset */ - unsigned short stack_offset; - - /* offset into the provided type format string where the type for this - * parameter starts */ - unsigned short type_offset; -} NDR_PARAM_OIF_OTHER; + union + { + /* see NDR_PARAM_OI_BASETYPE::type_format_char */ + unsigned char type_format_char; + /* offset into the provided type format string where the type for this + * parameter starts */ + unsigned short type_offset; + } u; +} NDR_PARAM_OIF; /* explicit handle description for FC_BIND_PRIMITIVE type */ typedef struct _NDR_EHD_PRIMITIVE @@ -236,7 +225,24 @@ typedef struct _NDR_EHD_CONTEXT #include "poppack.h" -void client_do_args_old_format(PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat, int phase, unsigned char *args, - unsigned short stack_size, unsigned char *pRetVal, BOOL object_proc, - BOOL ignore_retval); +enum stubless_phase +{ + STUBLESS_UNMARSHAL, + STUBLESS_INITOUT, + STUBLESS_CALLSERVER, + STUBLESS_CALCSIZE, + STUBLESS_GETBUFFER, + STUBLESS_MARSHAL, + STUBLESS_FREE +}; + +LONG_PTR CDECL ndr_client_call( PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pFormat, + void **stack_top, void **fpu_stack ) DECLSPEC_HIDDEN; +LONG_PTR CDECL ndr_async_client_call( PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pFormat, + void **stack_top ) DECLSPEC_HIDDEN; +void client_do_args( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, enum stubless_phase phase, + void **fpu_args, unsigned short number_of_params, unsigned char *pRetVal ) DECLSPEC_HIDDEN; +PFORMAT_STRING convert_old_args( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, + unsigned int stack_size, BOOL object_proc, + void *buffer, unsigned int size, unsigned int *count ) DECLSPEC_HIDDEN; +RPC_STATUS NdrpCompleteAsyncClientCall(RPC_ASYNC_STATE *pAsync, void *Reply) DECLSPEC_HIDDEN; diff --git a/reactos/dll/win32/rpcrt4/rpc_assoc.c b/reactos/dll/win32/rpcrt4/rpc_assoc.c index 32e951a929a..8364a9a4f36 100644 --- a/reactos/dll/win32/rpcrt4/rpc_assoc.c +++ b/reactos/dll/win32/rpcrt4/rpc_assoc.c @@ -84,6 +84,15 @@ static RPC_STATUS RpcAssoc_Alloc(LPCSTR Protseq, LPCSTR NetworkAddr, return RPC_S_OK; } +static BOOL compare_networkoptions(LPCWSTR opts1, LPCWSTR opts2) +{ + if ((opts1 == NULL) && (opts2 == NULL)) + return TRUE; + if ((opts1 == NULL) || (opts2 == NULL)) + return FALSE; + return !strcmpW(opts1, opts2); +} + RPC_STATUS RPCRT4_GetAssociation(LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint, LPCWSTR NetworkOptions, RpcAssoc **assoc_out) @@ -97,7 +106,7 @@ RPC_STATUS RPCRT4_GetAssociation(LPCSTR Protseq, LPCSTR NetworkAddr, if (!strcmp(Protseq, assoc->Protseq) && !strcmp(NetworkAddr, assoc->NetworkAddr) && !strcmp(Endpoint, assoc->Endpoint) && - ((!assoc->NetworkOptions && !NetworkOptions) || !strcmpW(NetworkOptions, assoc->NetworkOptions))) + compare_networkoptions(NetworkOptions, assoc->NetworkOptions)) { assoc->refs++; *assoc_out = assoc; @@ -125,7 +134,7 @@ RPC_STATUS RPCRT4_GetAssociation(LPCSTR Protseq, LPCSTR NetworkAddr, RPC_STATUS RpcServerAssoc_GetAssociation(LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint, LPCWSTR NetworkOptions, - unsigned long assoc_gid, + ULONG assoc_gid, RpcAssoc **assoc_out) { RpcAssoc *assoc; @@ -223,7 +232,7 @@ static RPC_STATUS RpcAssoc_BindConnection(const RpcAssoc *assoc, RpcConnection * RPC_MESSAGE msg; RPC_STATUS status; unsigned char *auth_data = NULL; - unsigned long auth_length; + ULONG auth_length; TRACE("sending bind request to server\n"); @@ -254,18 +263,19 @@ static RPC_STATUS RpcAssoc_BindConnection(const RpcAssoc *assoc, RpcConnection * { unsigned short remaining = msg.BufferLength - ROUND_UP(FIELD_OFFSET(RpcAddressString, string[server_address->length]), 4); - RpcResults *results = (RpcResults*)((ULONG_PTR)server_address + - ROUND_UP(FIELD_OFFSET(RpcAddressString, string[server_address->length]), 4)); - if ((results->num_results == 1) && (remaining >= sizeof(*results))) + RpcResultList *results = (RpcResultList*)((ULONG_PTR)server_address + + ROUND_UP(FIELD_OFFSET(RpcAddressString, string[server_address->length]), 4)); + if ((results->num_results == 1) && + (remaining >= FIELD_OFFSET(RpcResultList, results[results->num_results]))) { switch (results->results[0].result) { case RESULT_ACCEPT: /* respond to authorization request */ if (auth_length > sizeof(RpcAuthVerifier)) - status = RPCRT4_AuthorizeConnection(conn, - auth_data + sizeof(RpcAuthVerifier), - auth_length); + status = RPCRT4_ClientConnectionAuth(conn, + auth_data + sizeof(RpcAuthVerifier), + auth_length); if (status == RPC_S_OK) { conn->assoc_group_id = response_hdr->bind_ack.assoc_gid; @@ -394,6 +404,7 @@ RPC_STATUS RpcAssoc_GetClientConnection(RpcAssoc *assoc, if (status != RPC_S_OK) return status; + NewConnection->assoc = assoc; status = RPCRT4_OpenClientConnection(NewConnection); if (status != RPC_S_OK) { @@ -416,6 +427,7 @@ RPC_STATUS RpcAssoc_GetClientConnection(RpcAssoc *assoc, 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); diff --git a/reactos/dll/win32/rpcrt4/rpc_assoc.h b/reactos/dll/win32/rpcrt4/rpc_assoc.h index 1ce1f135638..f8df62d3802 100644 --- a/reactos/dll/win32/rpcrt4/rpc_assoc.h +++ b/reactos/dll/win32/rpcrt4/rpc_assoc.h @@ -34,6 +34,7 @@ typedef struct _RpcAssoc /* id of this association group */ ULONG assoc_group_id; + UUID http_uuid; CRITICAL_SECTION cs; @@ -45,14 +46,14 @@ typedef struct _RpcAssoc struct list context_handle_list; /* protected by cs */ } RpcAssoc; -RPC_STATUS RPCRT4_GetAssociation(LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint, LPCWSTR NetworkOptions, RpcAssoc **assoc); -RPC_STATUS RpcAssoc_GetClientConnection(RpcAssoc *assoc, const RPC_SYNTAX_IDENTIFIER *InterfaceId, const RPC_SYNTAX_IDENTIFIER *TransferSyntax, RpcAuthInfo *AuthInfo, RpcQualityOfService *QOS, RpcConnection **Connection); -void RpcAssoc_ReleaseIdleConnection(RpcAssoc *assoc, RpcConnection *Connection); -ULONG RpcAssoc_Release(RpcAssoc *assoc); -RPC_STATUS RpcServerAssoc_GetAssociation(LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint, LPCWSTR NetworkOptions, unsigned long assoc_gid, RpcAssoc **assoc_out); -RPC_STATUS RpcServerAssoc_AllocateContextHandle(RpcAssoc *assoc, void *CtxGuard, NDR_SCONTEXT *SContext); -RPC_STATUS RpcServerAssoc_FindContextHandle(RpcAssoc *assoc, const UUID *uuid, void *CtxGuard, ULONG Flags, NDR_SCONTEXT *SContext); -RPC_STATUS RpcServerAssoc_UpdateContextHandle(RpcAssoc *assoc, NDR_SCONTEXT SContext, void *CtxGuard, NDR_RUNDOWN rundown_routine); -unsigned int RpcServerAssoc_ReleaseContextHandle(RpcAssoc *assoc, NDR_SCONTEXT SContext, BOOL release_lock); -void RpcContextHandle_GetUuid(NDR_SCONTEXT SContext, UUID *uuid); -BOOL RpcContextHandle_IsGuardCorrect(NDR_SCONTEXT SContext, void *CtxGuard); +RPC_STATUS RPCRT4_GetAssociation(LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint, LPCWSTR NetworkOptions, RpcAssoc **assoc) DECLSPEC_HIDDEN; +RPC_STATUS RpcAssoc_GetClientConnection(RpcAssoc *assoc, const RPC_SYNTAX_IDENTIFIER *InterfaceId, const RPC_SYNTAX_IDENTIFIER *TransferSyntax, RpcAuthInfo *AuthInfo, RpcQualityOfService *QOS, RpcConnection **Connection) DECLSPEC_HIDDEN; +void RpcAssoc_ReleaseIdleConnection(RpcAssoc *assoc, RpcConnection *Connection) DECLSPEC_HIDDEN; +ULONG RpcAssoc_Release(RpcAssoc *assoc) DECLSPEC_HIDDEN; +RPC_STATUS RpcServerAssoc_GetAssociation(LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint, LPCWSTR NetworkOptions, ULONG assoc_gid, RpcAssoc **assoc_out) DECLSPEC_HIDDEN; +RPC_STATUS RpcServerAssoc_AllocateContextHandle(RpcAssoc *assoc, void *CtxGuard, NDR_SCONTEXT *SContext) DECLSPEC_HIDDEN; +RPC_STATUS RpcServerAssoc_FindContextHandle(RpcAssoc *assoc, const UUID *uuid, void *CtxGuard, ULONG Flags, NDR_SCONTEXT *SContext) DECLSPEC_HIDDEN; +RPC_STATUS RpcServerAssoc_UpdateContextHandle(RpcAssoc *assoc, NDR_SCONTEXT SContext, void *CtxGuard, NDR_RUNDOWN rundown_routine) DECLSPEC_HIDDEN; +unsigned int RpcServerAssoc_ReleaseContextHandle(RpcAssoc *assoc, NDR_SCONTEXT SContext, BOOL release_lock) DECLSPEC_HIDDEN; +void RpcContextHandle_GetUuid(NDR_SCONTEXT SContext, UUID *uuid) DECLSPEC_HIDDEN; +BOOL RpcContextHandle_IsGuardCorrect(NDR_SCONTEXT SContext, void *CtxGuard) DECLSPEC_HIDDEN; diff --git a/reactos/dll/win32/rpcrt4/rpc_async.c b/reactos/dll/win32/rpcrt4/rpc_async.c index 33fdc774304..891fc5ad725 100644 --- a/reactos/dll/win32/rpcrt4/rpc_async.c +++ b/reactos/dll/win32/rpcrt4/rpc_async.c @@ -29,11 +29,17 @@ #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.@] * @@ -104,8 +110,14 @@ RPC_STATUS WINAPI RpcAsyncGetCallStatus(PRPC_ASYNC_STATE pAsync) */ RPC_STATUS WINAPI RpcAsyncCompleteCall(PRPC_ASYNC_STATE pAsync, void *Reply) { - FIXME("(%p, %p): stub\n", pAsync, Reply); - return RPC_S_INVALID_ASYNC_HANDLE; + TRACE("(%p, %p)\n", pAsync, Reply); + + if (!valid_async_handle(pAsync)) + return RPC_S_INVALID_ASYNC_HANDLE; + + /* FIXME: check completed */ + + return NdrpCompleteAsyncClientCall(pAsync, Reply); } /*********************************************************************** diff --git a/reactos/dll/win32/rpcrt4/rpc_binding.c b/reactos/dll/win32/rpcrt4/rpc_binding.c index 7a1359fc570..685b569835e 100644 --- a/reactos/dll/win32/rpcrt4/rpc_binding.c +++ b/reactos/dll/win32/rpcrt4/rpc_binding.c @@ -661,11 +661,11 @@ RPC_STATUS WINAPI RpcStringBindingParseA( RPC_CSTR StringBinding, RPC_CSTR *ObjU return RPC_S_OK; fail: - 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); + if (ObjUuid) RpcStringFreeA(ObjUuid); + if (Protseq) RpcStringFreeA(Protseq); + if (NetworkAddr) RpcStringFreeA(NetworkAddr); + if (Endpoint) RpcStringFreeA(Endpoint); + if (Options) RpcStringFreeA(Options); return RPC_S_INVALID_STRING_BINDING; } @@ -798,13 +798,10 @@ RPC_STATUS WINAPI RpcBindingFree( RPC_BINDING_HANDLE* Binding ) */ RPC_STATUS WINAPI RpcBindingVectorFree( RPC_BINDING_VECTOR** BindingVector ) { - RPC_STATUS status; - unsigned long c; + ULONG c; TRACE("(%p)\n", BindingVector); - for (c=0; c<(*BindingVector)->Count; c++) { - status = RpcBindingFree(&(*BindingVector)->BindingH[c]); - } + for (c=0; c<(*BindingVector)->Count; c++) RpcBindingFree(&(*BindingVector)->BindingH[c]); HeapFree(GetProcessHeap(), 0, *BindingVector); *BindingVector = NULL; return RPC_S_OK; @@ -815,7 +812,7 @@ RPC_STATUS WINAPI RpcBindingVectorFree( RPC_BINDING_VECTOR** BindingVector ) */ RPC_STATUS WINAPI RpcBindingInqObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid ) { - RpcBinding* bind = (RpcBinding*)Binding; + RpcBinding* bind = Binding; TRACE("(%p,%p) = %s\n", Binding, ObjectUuid, debugstr_guid(&bind->ObjectUuid)); *ObjectUuid = bind->ObjectUuid; @@ -827,7 +824,7 @@ RPC_STATUS WINAPI RpcBindingInqObject( RPC_BINDING_HANDLE Binding, UUID* ObjectU */ RPC_STATUS WINAPI RpcBindingSetObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid ) { - RpcBinding* bind = (RpcBinding*)Binding; + RpcBinding* bind = Binding; TRACE("(%p,%s)\n", Binding, debugstr_guid(ObjectUuid)); if (bind->server) return RPC_S_WRONG_KIND_OF_BINDING; @@ -859,11 +856,11 @@ RPC_STATUS WINAPI RpcBindingFromStringBindingA( RPC_CSTR StringBinding, RPC_BIND if (ret == RPC_S_OK) ret = RPCRT4_CompleteBindingA(bind, (char*)NetworkAddr, (char*)Endpoint, (char*)Options); - RpcStringFreeA((unsigned char**)&Options); - RpcStringFreeA((unsigned char**)&Endpoint); - RpcStringFreeA((unsigned char**)&NetworkAddr); - RpcStringFreeA((unsigned char**)&Protseq); - RpcStringFreeA((unsigned char**)&ObjectUuid); + RpcStringFreeA(&Options); + RpcStringFreeA(&Endpoint); + RpcStringFreeA(&NetworkAddr); + RpcStringFreeA(&Protseq); + RpcStringFreeA(&ObjectUuid); if (ret == RPC_S_OK) *Binding = (RPC_BINDING_HANDLE)bind; @@ -918,7 +915,7 @@ RPC_STATUS WINAPI RpcBindingFromStringBindingW( RPC_WSTR StringBinding, RPC_BIND RPC_STATUS WINAPI RpcBindingToStringBindingA( RPC_BINDING_HANDLE Binding, RPC_CSTR *StringBinding ) { RPC_STATUS ret; - RpcBinding* bind = (RpcBinding*)Binding; + RpcBinding* bind = Binding; RPC_CSTR ObjectUuid; TRACE("(%p,%p)\n", Binding, StringBinding); @@ -949,7 +946,7 @@ RPC_STATUS WINAPI RpcBindingToStringBindingW( RPC_BINDING_HANDLE Binding, RPC_WS TRACE("(%p,%p)\n", Binding, StringBinding); ret = RpcBindingToStringBindingA(Binding, &str); *StringBinding = RPCRT4_strdupAtoW((char*)str); - RpcStringFreeA((unsigned char**)&str); + RpcStringFreeA(&str); return ret; } @@ -972,7 +969,7 @@ RPC_STATUS WINAPI I_RpcBindingInqTransportType( RPC_BINDING_HANDLE Binding, unsi */ RPC_STATUS WINAPI I_RpcBindingSetAsync( RPC_BINDING_HANDLE Binding, RPC_BLOCKING_FN BlockingFn) { - RpcBinding* bind = (RpcBinding*)Binding; + RpcBinding* bind = Binding; TRACE( "(%p,%p): stub\n", Binding, BlockingFn ); @@ -989,7 +986,7 @@ RPC_STATUS RPC_ENTRY RpcBindingCopy( RPC_BINDING_HANDLE* DestinationBinding) { RpcBinding *DestBinding; - RpcBinding *SrcBinding = (RpcBinding*)SourceBinding; + RpcBinding *SrcBinding = SourceBinding; RPC_STATUS status; TRACE("(%p, %p)\n", SourceBinding, DestinationBinding); @@ -1052,9 +1049,17 @@ RPC_STATUS RPC_ENTRY RpcBindingReset(RPC_BINDING_HANDLE Binding) */ RPC_STATUS WINAPI RpcImpersonateClient(RPC_BINDING_HANDLE BindingHandle) { - FIXME("(%p): stub\n", BindingHandle); - ImpersonateSelf(SecurityImpersonation); - return RPC_S_OK; + RpcBinding *bind; + + TRACE("(%p)\n", BindingHandle); + + if (!BindingHandle) BindingHandle = I_RpcGetCurrentCallHandle(); + if (!BindingHandle) return RPC_S_INVALID_BINDING; + + bind = BindingHandle; + if (bind->FromConn) + return rpcrt4_conn_impersonate_client(bind->FromConn); + return RPC_S_WRONG_KIND_OF_BINDING; } /*********************************************************************** @@ -1077,8 +1082,17 @@ RPC_STATUS WINAPI RpcImpersonateClient(RPC_BINDING_HANDLE BindingHandle) */ RPC_STATUS WINAPI RpcRevertToSelfEx(RPC_BINDING_HANDLE BindingHandle) { - FIXME("(%p): stub\n", BindingHandle); - return RPC_S_OK; + RpcBinding *bind; + + TRACE("(%p)\n", BindingHandle); + + if (!BindingHandle) BindingHandle = I_RpcGetCurrentCallHandle(); + if (!BindingHandle) return RPC_S_INVALID_BINDING; + + bind = BindingHandle; + if (bind->FromConn) + return rpcrt4_conn_revert_to_self(bind->FromConn); + return RPC_S_WRONG_KIND_OF_BINDING; } static inline BOOL has_nt_auth_identity(ULONG AuthnLevel) @@ -1094,11 +1108,11 @@ static inline BOOL has_nt_auth_identity(ULONG AuthnLevel) } } -static RPC_STATUS RpcAuthInfo_Create(ULONG AuthnLevel, ULONG AuthnSvc, - CredHandle cred, TimeStamp exp, - ULONG cbMaxToken, - RPC_AUTH_IDENTITY_HANDLE identity, - RpcAuthInfo **ret) +RPC_STATUS RpcAuthInfo_Create(ULONG AuthnLevel, ULONG AuthnSvc, + CredHandle cred, TimeStamp exp, + ULONG cbMaxToken, + RPC_AUTH_IDENTITY_HANDLE identity, + RpcAuthInfo **ret) { RpcAuthInfo *AuthInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(*AuthInfo)); if (!AuthInfo) @@ -1286,7 +1300,7 @@ static RPC_STATUS RpcQualityOfService_Create(const RPC_SECURITY_QOS *qos_src, BO cred_dst->User = HeapAlloc(GetProcessHeap(), 0, cred_dst->UserLength * sizeof(WCHAR)); cred_dst->Password = HeapAlloc(GetProcessHeap(), 0, cred_dst->PasswordLength * sizeof(WCHAR)); cred_dst->Domain = HeapAlloc(GetProcessHeap(), 0, cred_dst->DomainLength * sizeof(WCHAR)); - if (!cred_dst || !cred_dst->Password || !cred_dst->Domain) goto error; + if (!cred_dst->Password || !cred_dst->Domain) goto error; MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->User, cred_src->UserLength, cred_dst->User, cred_dst->UserLength); MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->Domain, cred_src->DomainLength, cred_dst->Domain, cred_dst->DomainLength); MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->Password, cred_src->PasswordLength, cred_dst->Password, cred_dst->PasswordLength); @@ -1431,9 +1445,8 @@ BOOL RpcQualityOfService_IsEqual(const RpcQualityOfService *qos1, const RpcQuali */ RPC_STATUS WINAPI RpcRevertToSelf(void) { - FIXME("stub\n"); - RevertToSelf(); - return RPC_S_OK; + TRACE("\n"); + return RpcRevertToSelfEx(NULL); } /*********************************************************************** @@ -1453,9 +1466,22 @@ RpcBindingInqAuthInfoExA( RPC_BINDING_HANDLE Binding, RPC_CSTR *ServerPrincName, ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc, ULONG RpcQosVersion, RPC_SECURITY_QOS *SecurityQOS ) { - FIXME("%p %p %p %p %p %p %u %p\n", Binding, ServerPrincName, AuthnLevel, + RPC_STATUS status; + RPC_WSTR principal; + + TRACE("%p %p %p %p %p %p %u %p\n", Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvc, RpcQosVersion, SecurityQOS); - return RPC_S_INVALID_BINDING; + + status = RpcBindingInqAuthInfoExW(Binding, ServerPrincName ? &principal : NULL, AuthnLevel, + AuthnSvc, AuthIdentity, AuthzSvc, RpcQosVersion, SecurityQOS); + if (status == RPC_S_OK && ServerPrincName) + { + *ServerPrincName = (RPC_CSTR)RPCRT4_strdupWtoA(principal); + RpcStringFreeW(&principal); + if (!*ServerPrincName) return ERROR_OUTOFMEMORY; + } + + return status; } /*********************************************************************** @@ -1466,9 +1492,38 @@ RpcBindingInqAuthInfoExW( RPC_BINDING_HANDLE Binding, RPC_WSTR *ServerPrincName, ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc, ULONG RpcQosVersion, RPC_SECURITY_QOS *SecurityQOS ) { - FIXME("%p %p %p %p %p %p %u %p\n", Binding, ServerPrincName, AuthnLevel, + RpcBinding *bind = Binding; + + TRACE("%p %p %p %p %p %p %u %p\n", Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvc, RpcQosVersion, SecurityQOS); - return RPC_S_INVALID_BINDING; + + if (!bind->AuthInfo) return RPC_S_BINDING_HAS_NO_AUTH; + + if (SecurityQOS) + { + FIXME("QOS not implemented\n"); + return RPC_S_INVALID_BINDING; + } + + if (ServerPrincName) + { + if (bind->AuthInfo->server_principal_name) + { + *ServerPrincName = RPCRT4_strdupW(bind->AuthInfo->server_principal_name); + if (!*ServerPrincName) return ERROR_OUTOFMEMORY; + } + else *ServerPrincName = NULL; + } + if (AuthnLevel) *AuthnLevel = bind->AuthInfo->AuthnLevel; + if (AuthnSvc) *AuthnSvc = bind->AuthInfo->AuthnSvc; + if (AuthIdentity) *AuthIdentity = bind->AuthInfo->identity; + if (AuthzSvc) + { + FIXME("authorization service not implemented\n"); + *AuthzSvc = RPC_C_AUTHZ_NONE; + } + + return RPC_S_OK; } /*********************************************************************** @@ -1478,9 +1533,8 @@ RPCRTAPI RPC_STATUS RPC_ENTRY RpcBindingInqAuthInfoA( RPC_BINDING_HANDLE Binding, RPC_CSTR *ServerPrincName, ULONG *AuthnLevel, ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc ) { - FIXME("%p %p %p %p %p %p\n", Binding, ServerPrincName, AuthnLevel, - AuthnSvc, AuthIdentity, AuthzSvc); - return RPC_S_INVALID_BINDING; + return RpcBindingInqAuthInfoExA(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity, + AuthzSvc, 0, NULL); } /*********************************************************************** @@ -1490,9 +1544,78 @@ RPCRTAPI RPC_STATUS RPC_ENTRY RpcBindingInqAuthInfoW( RPC_BINDING_HANDLE Binding, RPC_WSTR *ServerPrincName, ULONG *AuthnLevel, ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc ) { - FIXME("%p %p %p %p %p %p\n", Binding, ServerPrincName, AuthnLevel, - AuthnSvc, AuthIdentity, AuthzSvc); - return RPC_S_INVALID_BINDING; + return RpcBindingInqAuthInfoExW(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity, + AuthzSvc, 0, NULL); +} + +/*********************************************************************** + * RpcBindingInqAuthClientA (RPCRT4.@) + */ +RPCRTAPI RPC_STATUS RPC_ENTRY +RpcBindingInqAuthClientA( RPC_BINDING_HANDLE ClientBinding, RPC_AUTHZ_HANDLE *Privs, + RPC_CSTR *ServerPrincName, ULONG *AuthnLevel, ULONG *AuthnSvc, + ULONG *AuthzSvc ) +{ + return RpcBindingInqAuthClientExA(ClientBinding, Privs, ServerPrincName, AuthnLevel, + AuthnSvc, AuthzSvc, 0); +} + +/*********************************************************************** + * RpcBindingInqAuthClientW (RPCRT4.@) + */ +RPCRTAPI RPC_STATUS RPC_ENTRY +RpcBindingInqAuthClientW( RPC_BINDING_HANDLE ClientBinding, RPC_AUTHZ_HANDLE *Privs, + RPC_WSTR *ServerPrincName, ULONG *AuthnLevel, ULONG *AuthnSvc, + ULONG *AuthzSvc ) +{ + return RpcBindingInqAuthClientExW(ClientBinding, Privs, ServerPrincName, AuthnLevel, + AuthnSvc, AuthzSvc, 0); +} + +/*********************************************************************** + * RpcBindingInqAuthClientExA (RPCRT4.@) + */ +RPCRTAPI RPC_STATUS RPC_ENTRY +RpcBindingInqAuthClientExA( RPC_BINDING_HANDLE ClientBinding, RPC_AUTHZ_HANDLE *Privs, + RPC_CSTR *ServerPrincName, ULONG *AuthnLevel, ULONG *AuthnSvc, + ULONG *AuthzSvc, ULONG Flags ) +{ + RPC_STATUS status; + RPC_WSTR principal; + + TRACE("%p %p %p %p %p %p 0x%x\n", ClientBinding, Privs, ServerPrincName, AuthnLevel, + AuthnSvc, AuthzSvc, Flags); + + status = RpcBindingInqAuthClientExW(ClientBinding, Privs, ServerPrincName ? &principal : NULL, + AuthnLevel, AuthnSvc, AuthzSvc, Flags); + if (status == RPC_S_OK && ServerPrincName) + { + *ServerPrincName = (RPC_CSTR)RPCRT4_strdupWtoA(principal); + if (!*ServerPrincName && principal) status = ERROR_OUTOFMEMORY; + RpcStringFreeW(&principal); + } + + return status; +} + +/*********************************************************************** + * RpcBindingInqAuthClientExW (RPCRT4.@) + */ +RPCRTAPI RPC_STATUS RPC_ENTRY +RpcBindingInqAuthClientExW( RPC_BINDING_HANDLE ClientBinding, RPC_AUTHZ_HANDLE *Privs, + RPC_WSTR *ServerPrincName, ULONG *AuthnLevel, ULONG *AuthnSvc, + ULONG *AuthzSvc, ULONG Flags ) +{ + RpcBinding *bind = ClientBinding; + + TRACE("%p %p %p %p %p %p 0x%x\n", ClientBinding, Privs, ServerPrincName, AuthnLevel, + AuthnSvc, AuthzSvc, Flags); + + if (!bind->FromConn) return RPC_S_INVALID_BINDING; + + return rpcrt4_conn_inquire_auth_client(bind->FromConn, Privs, + ServerPrincName, AuthnLevel, + AuthnSvc, AuthzSvc, Flags); } /*********************************************************************** @@ -1504,7 +1627,7 @@ RpcBindingSetAuthInfoExA( RPC_BINDING_HANDLE Binding, RPC_CSTR ServerPrincName, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr, RPC_SECURITY_QOS *SecurityQos ) { - RpcBinding* bind = (RpcBinding*)Binding; + RpcBinding* bind = Binding; SECURITY_STATUS r; CredHandle cred; TimeStamp exp; @@ -1634,7 +1757,7 @@ RpcBindingSetAuthInfoExW( RPC_BINDING_HANDLE Binding, RPC_WSTR ServerPrincName, ULONG AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr, RPC_SECURITY_QOS *SecurityQos ) { - RpcBinding* bind = (RpcBinding*)Binding; + RpcBinding* bind = Binding; SECURITY_STATUS r; CredHandle cred; TimeStamp exp; @@ -1643,7 +1766,7 @@ RpcBindingSetAuthInfoExW( RPC_BINDING_HANDLE Binding, RPC_WSTR ServerPrincName, PSecPkgInfoW packages; ULONG cbMaxToken; - TRACE("%p %s %u %u %p %u %p\n", Binding, debugstr_w((const WCHAR*)ServerPrincName), + TRACE("%p %s %u %u %p %u %p\n", Binding, debugstr_w(ServerPrincName), AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, SecurityQos); if (SecurityQos) @@ -1775,7 +1898,7 @@ RPCRTAPI RPC_STATUS RPC_ENTRY 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((const WCHAR*)ServerPrincName), + TRACE("%p %s %u %u %p %u\n", Binding, debugstr_w(ServerPrincName), AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr); return RpcBindingSetAuthInfoExW(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, NULL); } diff --git a/reactos/dll/win32/rpcrt4/rpc_binding.h b/reactos/dll/win32/rpcrt4/rpc_binding.h index 5aa83079d51..7d49074fc5e 100644 --- a/reactos/dll/win32/rpcrt4/rpc_binding.h +++ b/reactos/dll/win32/rpcrt4/rpc_binding.h @@ -24,8 +24,15 @@ #include "rpcndr.h" #include "security.h" #include "wine/list.h" +#include "rpc_defs.h" +enum secure_packet_direction +{ + SECURE_PACKET_SEND, + SECURE_PACKET_RECEIVE +}; + typedef struct _RpcAuthInfo { LONG refs; @@ -66,6 +73,7 @@ typedef struct _RpcConnection TimeStamp exp; ULONG attr; RpcAuthInfo *AuthInfo; + ULONG auth_context_id; ULONG encryption_auth_len; ULONG signature_auth_len; RpcQualityOfService *QOS; @@ -74,6 +82,7 @@ typedef struct _RpcConnection 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. */ @@ -96,6 +105,13 @@ struct connection_ops { 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); + BOOL (*is_authorized)(RpcConnection *conn); + RPC_STATUS (*authorize)(RpcConnection *conn, BOOL first_time, unsigned char *in_buffer, unsigned int in_len, unsigned char *out_buffer, unsigned int *out_len); + RPC_STATUS (*secure_packet)(RpcConnection *Connection, enum secure_packet_direction dir, RpcPktHdr *hdr, unsigned int hdr_size, unsigned char *stub_data, unsigned int stub_data_size, RpcAuthVerifier *auth_hdr, unsigned char *auth_value, unsigned int auth_value_size); + RPC_STATUS (*impersonate_client)(RpcConnection *conn); + RPC_STATUS (*revert_to_self)(RpcConnection *conn); + RPC_STATUS (*inquire_auth_client)(RpcConnection *, RPC_AUTHZ_HANDLE *, RPC_WSTR *, ULONG *, ULONG *, ULONG *, ULONG); }; /* don't know what MS's structure looks like */ @@ -119,35 +135,36 @@ typedef struct _RpcBinding RpcQualityOfService *QOS; } RpcBinding; -LPSTR RPCRT4_strndupA(LPCSTR src, INT len); -LPWSTR RPCRT4_strndupW(LPCWSTR src, INT len); -LPSTR RPCRT4_strdupWtoA(LPCWSTR src); -LPWSTR RPCRT4_strdupAtoW(LPCSTR src); -void RPCRT4_strfree(LPSTR src); +LPSTR RPCRT4_strndupA(LPCSTR src, INT len) DECLSPEC_HIDDEN; +LPWSTR RPCRT4_strndupW(LPCWSTR src, INT len) DECLSPEC_HIDDEN; +LPSTR RPCRT4_strdupWtoA(LPCWSTR src) DECLSPEC_HIDDEN; +LPWSTR RPCRT4_strdupAtoW(LPCSTR src) DECLSPEC_HIDDEN; +void RPCRT4_strfree(LPSTR src) DECLSPEC_HIDDEN; #define RPCRT4_strdupA(x) RPCRT4_strndupA((x),-1) #define RPCRT4_strdupW(x) RPCRT4_strndupW((x),-1) -ULONG RpcAuthInfo_AddRef(RpcAuthInfo *AuthInfo); -ULONG RpcAuthInfo_Release(RpcAuthInfo *AuthInfo); -BOOL RpcAuthInfo_IsEqual(const RpcAuthInfo *AuthInfo1, const RpcAuthInfo *AuthInfo2); -ULONG RpcQualityOfService_AddRef(RpcQualityOfService *qos); -ULONG RpcQualityOfService_Release(RpcQualityOfService *qos); -BOOL RpcQualityOfService_IsEqual(const RpcQualityOfService *qos1, const RpcQualityOfService *qos2); +RPC_STATUS RpcAuthInfo_Create(ULONG AuthnLevel, ULONG AuthnSvc, CredHandle cred, TimeStamp exp, ULONG cbMaxToken, RPC_AUTH_IDENTITY_HANDLE identity, RpcAuthInfo **ret) DECLSPEC_HIDDEN; +ULONG RpcAuthInfo_AddRef(RpcAuthInfo *AuthInfo) DECLSPEC_HIDDEN; +ULONG RpcAuthInfo_Release(RpcAuthInfo *AuthInfo) DECLSPEC_HIDDEN; +BOOL RpcAuthInfo_IsEqual(const RpcAuthInfo *AuthInfo1, const RpcAuthInfo *AuthInfo2) DECLSPEC_HIDDEN; +ULONG RpcQualityOfService_AddRef(RpcQualityOfService *qos) DECLSPEC_HIDDEN; +ULONG RpcQualityOfService_Release(RpcQualityOfService *qos) DECLSPEC_HIDDEN; +BOOL RpcQualityOfService_IsEqual(const RpcQualityOfService *qos1, const RpcQualityOfService *qos2) DECLSPEC_HIDDEN; -RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server, LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint, LPCWSTR NetworkOptions, RpcAuthInfo* AuthInfo, RpcQualityOfService *QOS); -RPC_STATUS RPCRT4_DestroyConnection(RpcConnection* Connection); -RPC_STATUS RPCRT4_OpenClientConnection(RpcConnection* Connection); -RPC_STATUS RPCRT4_CloseConnection(RpcConnection* Connection); +RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server, LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint, LPCWSTR NetworkOptions, RpcAuthInfo* AuthInfo, RpcQualityOfService *QOS) DECLSPEC_HIDDEN; +RPC_STATUS RPCRT4_DestroyConnection(RpcConnection* Connection) DECLSPEC_HIDDEN; +RPC_STATUS RPCRT4_OpenClientConnection(RpcConnection* Connection) DECLSPEC_HIDDEN; +RPC_STATUS RPCRT4_CloseConnection(RpcConnection* Connection) DECLSPEC_HIDDEN; -RPC_STATUS RPCRT4_ResolveBinding(RpcBinding* Binding, LPCSTR Endpoint); -RPC_STATUS RPCRT4_SetBindingObject(RpcBinding* Binding, const UUID* ObjectUuid); -RPC_STATUS RPCRT4_MakeBinding(RpcBinding** Binding, RpcConnection* Connection); -void RPCRT4_AddRefBinding(RpcBinding* Binding); -RPC_STATUS RPCRT4_ReleaseBinding(RpcBinding* Binding); +RPC_STATUS RPCRT4_ResolveBinding(RpcBinding* Binding, LPCSTR Endpoint) DECLSPEC_HIDDEN; +RPC_STATUS RPCRT4_SetBindingObject(RpcBinding* Binding, const UUID* ObjectUuid) DECLSPEC_HIDDEN; +RPC_STATUS RPCRT4_MakeBinding(RpcBinding** Binding, RpcConnection* Connection) DECLSPEC_HIDDEN; +void RPCRT4_AddRefBinding(RpcBinding* Binding) DECLSPEC_HIDDEN; +RPC_STATUS RPCRT4_ReleaseBinding(RpcBinding* Binding) DECLSPEC_HIDDEN; RPC_STATUS RPCRT4_OpenBinding(RpcBinding* Binding, RpcConnection** Connection, - const RPC_SYNTAX_IDENTIFIER *TransferSyntax, const RPC_SYNTAX_IDENTIFIER *InterfaceId); -RPC_STATUS RPCRT4_CloseBinding(RpcBinding* Binding, RpcConnection* Connection); + const RPC_SYNTAX_IDENTIFIER *TransferSyntax, const RPC_SYNTAX_IDENTIFIER *InterfaceId) DECLSPEC_HIDDEN; +RPC_STATUS RPCRT4_CloseBinding(RpcBinding* Binding, RpcConnection* Connection) DECLSPEC_HIDDEN; static inline const char *rpcrt4_conn_get_name(const RpcConnection *Connection) { @@ -181,15 +198,55 @@ static inline RPC_STATUS rpcrt4_conn_handoff(RpcConnection *old_conn, RpcConnect return old_conn->ops->handoff(old_conn, new_conn); } -/* floors 3 and up */ -RPC_STATUS RpcTransport_GetTopOfTower(unsigned char *tower_data, size_t *tower_size, const char *protseq, const char *networkaddr, const char *endpoint); -RPC_STATUS RpcTransport_ParseTopOfTower(const unsigned char *tower_data, size_t tower_size, char **protseq, char **networkaddr, char **endpoint); +static inline BOOL rpcrt4_conn_is_authorized(RpcConnection *Connection) +{ + return Connection->ops->is_authorized(Connection); +} -void RPCRT4_SetThreadCurrentConnection(RpcConnection *Connection); -void RPCRT4_SetThreadCurrentCallHandle(RpcBinding *Binding); -RpcBinding *RPCRT4_GetThreadCurrentCallHandle(void); -void RPCRT4_PushThreadContextHandle(NDR_SCONTEXT SContext); -void RPCRT4_RemoveThreadContextHandle(NDR_SCONTEXT SContext); -NDR_SCONTEXT RPCRT4_PopThreadContextHandle(void); +static inline RPC_STATUS rpcrt4_conn_authorize( + RpcConnection *conn, BOOL first_time, unsigned char *in_buffer, + unsigned int in_len, unsigned char *out_buffer, unsigned int *out_len) +{ + return conn->ops->authorize(conn, first_time, in_buffer, in_len, out_buffer, out_len); +} + +static inline RPC_STATUS rpcrt4_conn_secure_packet( + RpcConnection *conn, enum secure_packet_direction dir, + RpcPktHdr *hdr, unsigned int hdr_size, unsigned char *stub_data, + unsigned int stub_data_size, RpcAuthVerifier *auth_hdr, + unsigned char *auth_value, unsigned int auth_value_size) +{ + return conn->ops->secure_packet(conn, dir, hdr, hdr_size, stub_data, stub_data_size, auth_hdr, auth_value, auth_value_size); +} + +static inline RPC_STATUS rpcrt4_conn_impersonate_client( + RpcConnection *conn) +{ + return conn->ops->impersonate_client(conn); +} + +static inline RPC_STATUS rpcrt4_conn_revert_to_self( + RpcConnection *conn) +{ + return conn->ops->revert_to_self(conn); +} + +static inline RPC_STATUS rpcrt4_conn_inquire_auth_client( + RpcConnection *conn, RPC_AUTHZ_HANDLE *privs, RPC_WSTR *server_princ_name, + ULONG *authn_level, ULONG *authn_svc, ULONG *authz_svc, ULONG flags) +{ + return conn->ops->inquire_auth_client(conn, privs, server_princ_name, authn_level, authn_svc, authz_svc, flags); +} + +/* floors 3 and up */ +RPC_STATUS RpcTransport_GetTopOfTower(unsigned char *tower_data, size_t *tower_size, const char *protseq, const char *networkaddr, const char *endpoint) DECLSPEC_HIDDEN; +RPC_STATUS RpcTransport_ParseTopOfTower(const unsigned char *tower_data, size_t tower_size, char **protseq, char **networkaddr, char **endpoint) DECLSPEC_HIDDEN; + +void RPCRT4_SetThreadCurrentConnection(RpcConnection *Connection) DECLSPEC_HIDDEN; +void RPCRT4_SetThreadCurrentCallHandle(RpcBinding *Binding) DECLSPEC_HIDDEN; +RpcBinding *RPCRT4_GetThreadCurrentCallHandle(void) DECLSPEC_HIDDEN; +void RPCRT4_PushThreadContextHandle(NDR_SCONTEXT SContext) DECLSPEC_HIDDEN; +void RPCRT4_RemoveThreadContextHandle(NDR_SCONTEXT SContext) DECLSPEC_HIDDEN; +NDR_SCONTEXT RPCRT4_PopThreadContextHandle(void) DECLSPEC_HIDDEN; #endif diff --git a/reactos/dll/win32/rpcrt4/rpc_defs.h b/reactos/dll/win32/rpcrt4/rpc_defs.h index cae77c4f356..434d39699ee 100644 --- a/reactos/dll/win32/rpcrt4/rpc_defs.h +++ b/reactos/dll/win32/rpcrt4/rpc_defs.h @@ -22,6 +22,7 @@ #ifndef __WINE_RPC_DEFS_H #define __WINE_RPC_DEFS_H +#include "pshpack1.h" typedef struct { unsigned char rpc_ver; /* RPC major version (5) */ @@ -31,13 +32,13 @@ typedef struct 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 long call_id; /* Call identifier. */ + unsigned int call_id; /* Call identifier. */ } RpcPktCommonHdr; typedef struct { RpcPktCommonHdr common; - unsigned long alloc_hint; /* Data size in bytes excluding header and tail. */ + unsigned int alloc_hint; /* Data size in bytes excluding header and tail. */ unsigned short context_id; /* Presentation context identifier */ unsigned short opnum; } RpcPktRequestHdr; @@ -45,7 +46,7 @@ typedef struct typedef struct { RpcPktCommonHdr common; - unsigned long alloc_hint; /* Data size in bytes excluding header and tail. */ + unsigned int alloc_hint; /* Data size in bytes excluding header and tail. */ unsigned short context_id; /* Presentation context identifier */ unsigned char cancel_count; unsigned char reserved; @@ -54,58 +55,68 @@ typedef struct typedef struct { RpcPktCommonHdr common; - unsigned long alloc_hint; /* Data size in bytes excluding header and tail. */ + unsigned int alloc_hint; /* Data size in bytes excluding header and tail. */ unsigned short context_id; /* Presentation context identifier */ unsigned char cancel_count; /* Received cancel count */ unsigned char reserved; /* Force alignment! */ - unsigned long status; /* Runtime fault code (RPC_STATUS) */ - unsigned long reserved2; + unsigned int status; /* Runtime fault code (RPC_STATUS) */ + unsigned int reserved2; } RpcPktFaultHdr; +typedef struct +{ + unsigned short context_id; /* Presentation context identifier */ + unsigned char num_syntaxes; /* Number of syntaxes */ + unsigned char reserved; /* For alignment */ + RPC_SYNTAX_IDENTIFIER abstract_syntax; + RPC_SYNTAX_IDENTIFIER transfer_syntaxes[ANYSIZE_ARRAY]; /* size_is(num_syntaxes) */ +} RpcContextElement; + typedef struct { RpcPktCommonHdr common; unsigned short max_tsize; /* Maximum transmission fragment size */ unsigned short max_rsize; /* Maximum receive fragment size */ - unsigned long assoc_gid; /* Associated group id */ + unsigned int assoc_gid; /* Associated group id */ unsigned char num_elements; /* Number of elements */ unsigned char padding[3]; /* Force alignment! */ - unsigned short context_id; /* Presentation context identifier */ - unsigned char num_syntaxes; /* Number of syntaxes */ - RPC_SYNTAX_IDENTIFIER abstract; - RPC_SYNTAX_IDENTIFIER transfer; + /* + * Following this header are these fields: + * RpcContextElement context_elements[num_elements] + */ } RpcPktBindHdr; -#include "pshpack1.h" typedef struct { unsigned short length; /* Length of the string including null terminator */ - char string[1]; /* String data in single byte, null terminated form */ + char string[ANYSIZE_ARRAY]; /* String data in single byte, null terminated form */ } RpcAddressString; -#include "poppack.h" + +typedef struct +{ + unsigned short result; + unsigned short reason; + RPC_SYNTAX_IDENTIFIER transfer_syntax; +} RpcResult; typedef struct { unsigned char num_results; /* Number of results */ unsigned char reserved[3]; /* Force alignment! */ - struct { - unsigned short result; - unsigned short reason; - } results[1]; -} RpcResults; + RpcResult results[ANYSIZE_ARRAY]; /* size_is(num_results) */ +} RpcResultList; typedef struct { RpcPktCommonHdr common; unsigned short max_tsize; /* Maximum transmission fragment size */ unsigned short max_rsize; /* Maximum receive fragment size */ - unsigned long assoc_gid; /* Associated group id */ + unsigned int assoc_gid; /* Associated group id */ /* * Following this header are these fields: * RpcAddressString server_address; * [0 - 3 bytes of padding so that results is 4-byte aligned] - * RpcResults results; - * RPC_SYNTAX_IDENTIFIER transfer; + * RpcResultList results; */ } RpcPktBindAckHdr; @@ -117,9 +128,24 @@ typedef struct struct { unsigned char rpc_ver; unsigned char rpc_ver_minor; - } protocols[1]; + } protocols[ANYSIZE_ARRAY]; } RpcPktBindNAckHdr; +/* undocumented packet sent during RPC over HTTP */ +typedef struct +{ + RpcPktCommonHdr common; + unsigned short flags; + unsigned short num_data_items; +} RpcPktHttpHdr; + +/* AUTH3 packet */ +typedef struct +{ + RpcPktCommonHdr common; + unsigned int pad; /* ignored */ +} RpcPktAuth3Hdr; + /* Union representing all possible packet headers */ typedef union { @@ -130,6 +156,8 @@ typedef union RpcPktBindHdr bind; RpcPktBindAckHdr bind_ack; RpcPktBindNAckHdr bind_nack; + RpcPktHttpHdr http; + RpcPktAuth3Hdr auth3; } RpcPktHdr; typedef struct @@ -138,8 +166,9 @@ 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 long auth_context_id; /* unique value for the authenticated connection */ + unsigned int auth_context_id; /* unique value for the authenticated connection */ } RpcAuthVerifier; +#include "poppack.h" #define RPC_AUTH_VERIFIER_LEN(common_hdr) \ ((common_hdr)->auth_len ? (common_hdr)->auth_len + sizeof(RpcAuthVerifier) : 0) @@ -154,26 +183,30 @@ typedef struct #define RPC_MIN_PACKET_SIZE 0x1000 #define RPC_MAX_PACKET_SIZE 0x16D0 -#define PKT_REQUEST 0 -#define PKT_PING 1 -#define PKT_RESPONSE 2 -#define PKT_FAULT 3 -#define PKT_WORKING 4 -#define PKT_NOCALL 5 -#define PKT_REJECT 6 -#define PKT_ACK 7 -#define PKT_CL_CANCEL 8 -#define PKT_FACK 9 -#define PKT_CANCEL_ACK 10 -#define PKT_BIND 11 -#define PKT_BIND_ACK 12 -#define PKT_BIND_NACK 13 -#define PKT_ALTER_CONTEXT 14 -#define PKT_ALTER_CONTEXT_RESP 15 -#define PKT_AUTH3 16 -#define PKT_SHUTDOWN 17 -#define PKT_CO_CANCEL 18 -#define PKT_ORPHANED 19 +enum rpc_packet_type +{ + PKT_REQUEST = 0, + PKT_PING = 1, + PKT_RESPONSE = 2, + PKT_FAULT = 3, + PKT_WORKING = 4, + PKT_NOCALL = 5, + PKT_REJECT = 6, + PKT_ACK = 7, + PKT_CL_CANCEL = 8, + PKT_FACK = 9, + PKT_CANCEL_ACK = 10, + PKT_BIND = 11, + PKT_BIND_ACK = 12, + PKT_BIND_NACK = 13, + PKT_ALTER_CONTEXT = 14, + PKT_ALTER_CONTEXT_RESP = 15, + PKT_AUTH3 = 16, + PKT_SHUTDOWN = 17, + PKT_CO_CANCEL = 18, + PKT_ORPHANED = 19, + PKT_HTTP = 20, +}; #define RESULT_ACCEPT 0 #define RESULT_USER_REJECTION 1 diff --git a/reactos/dll/win32/rpcrt4/rpc_epmap.c b/reactos/dll/win32/rpcrt4/rpc_epmap.c index bf4b1baa43f..c5c25778bfb 100644 --- a/reactos/dll/win32/rpcrt4/rpc_epmap.c +++ b/reactos/dll/win32/rpcrt4/rpc_epmap.c @@ -79,30 +79,21 @@ static BOOL start_rpcss(void) { PROCESS_INFORMATION pi; STARTUPINFOW si; - static WCHAR cmd[6]; - static const WCHAR rpcss[] = {'r','p','c','s','s',0}; + WCHAR cmd[MAX_PATH]; + static const WCHAR rpcss[] = {'\\','r','p','c','s','s','.','e','x','e',0}; BOOL rslt; + void *redir; TRACE("\n"); - ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); ZeroMemory(&si, sizeof(STARTUPINFOA)); si.cb = sizeof(STARTUPINFOA); + GetSystemDirectoryW( cmd, MAX_PATH - sizeof(rpcss)/sizeof(WCHAR) ); + lstrcatW( cmd, rpcss ); - memcpy(cmd, rpcss, sizeof(rpcss)); - - rslt = CreateProcessW( - NULL, /* executable */ - cmd, /* command line */ - NULL, /* process security attributes */ - NULL, /* primary thread security attributes */ - FALSE, /* inherit handles */ - 0, /* creation flags */ - NULL, /* use parent's environment */ - NULL, /* use parent's current directory */ - &si, /* STARTUPINFO pointer */ - &pi /* PROCESS_INFORMATION */ - ); + Wow64DisableWow64FsRedirection( &redir ); + rslt = CreateProcessW( cmd, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi ); + Wow64RevertWow64FsRedirection( redir ); if (rslt) { @@ -116,18 +107,18 @@ static BOOL start_rpcss(void) static inline BOOL is_epm_destination_local(RPC_BINDING_HANDLE handle) { - RpcBinding *bind = (RpcBinding *)handle; + RpcBinding *bind = handle; const char *protseq = bind->Protseq; const char *network_addr = bind->NetworkAddr; - return ((!strcmp(protseq, "ncalrpc") && !network_addr) || - (!strcmp(protseq, "ncacn_np") && + return (!strcmp(protseq, "ncalrpc") || + (!strcmp(protseq, "ncacn_np") && (!network_addr || !strcmp(network_addr, ".")))); } static RPC_STATUS get_epm_handle_client(RPC_BINDING_HANDLE handle, RPC_BINDING_HANDLE *epm_handle) { - RpcBinding *bind = (RpcBinding *)handle; + RpcBinding *bind = handle; const char * pszEndpoint = NULL; RPC_STATUS status; RpcBinding* epm_bind; @@ -149,7 +140,7 @@ static RPC_STATUS get_epm_handle_client(RPC_BINDING_HANDLE handle, RPC_BINDING_H status = RpcBindingCopy(handle, epm_handle); if (status != RPC_S_OK) return status; - epm_bind = (RpcBinding*)*epm_handle; + epm_bind = *epm_handle; if (epm_bind->AuthInfo) { /* don't bother with authenticating against the EPM by default @@ -187,8 +178,8 @@ static LONG WINAPI rpc_filter(EXCEPTION_POINTERS *__eptr) RPC_STATUS WINAPI RpcEpRegisterA( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *BindingVector, UUID_VECTOR *UuidVector, RPC_CSTR Annotation ) { - PRPC_SERVER_INTERFACE If = (PRPC_SERVER_INTERFACE)IfSpec; - unsigned long i; + PRPC_SERVER_INTERFACE If = IfSpec; + ULONG i; RPC_STATUS status = RPC_S_OK; error_status_t status2; ept_entry_t *entries; @@ -197,13 +188,13 @@ RPC_STATUS WINAPI RpcEpRegisterA( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *Bind TRACE("(%p,%p,%p,%s)\n", IfSpec, BindingVector, UuidVector, debugstr_a((char*)Annotation)); TRACE(" ifid=%s\n", debugstr_guid(&If->InterfaceId.SyntaxGUID)); for (i=0; iCount; i++) { - 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)); + 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)); } if (UuidVector) { for (i=0; iCount; i++) - TRACE(" obj[%ld]=%s\n", i, debugstr_guid(UuidVector->Uuid[i])); + TRACE(" obj[%d]=%s\n", i, debugstr_guid(UuidVector->Uuid[i])); } if (!BindingVector->Count) return RPC_S_OK; @@ -222,10 +213,9 @@ RPC_STATUS WINAPI RpcEpRegisterA( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *Bind for (i = 0; i < BindingVector->Count; i++) { unsigned j; - RpcBinding* bind = (RpcBinding*)(BindingVector->BindingH[i]); + RpcBinding* bind = 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, @@ -236,7 +226,9 @@ RPC_STATUS WINAPI RpcEpRegisterA( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *Bind memcpy(&entries[i * UuidVector->Count].object, &UuidVector->Uuid[j], sizeof(GUID)); else memset(&entries[i].object, 0, sizeof(entries[i].object)); - memcpy(entries[i].annotation, Annotation, min(len + 1, ept_max_annotation_size)); + if (Annotation) + memcpy(entries[i].annotation, Annotation, + min(strlen((char *)Annotation) + 1, ept_max_annotation_size)); } } @@ -280,14 +272,29 @@ RPC_STATUS WINAPI RpcEpRegisterA( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *Bind 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 = (PRPC_SERVER_INTERFACE)IfSpec; - unsigned long i; + PRPC_SERVER_INTERFACE If = IfSpec; + ULONG i; RPC_STATUS status = RPC_S_OK; error_status_t status2; ept_entry_t *entries; @@ -296,13 +303,13 @@ RPC_STATUS WINAPI RpcEpUnregister( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *Bin TRACE("(%p,%p,%p)\n", IfSpec, BindingVector, UuidVector); TRACE(" ifid=%s\n", debugstr_guid(&If->InterfaceId.SyntaxGUID)); for (i=0; iCount; i++) { - 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)); + 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)); } if (UuidVector) { for (i=0; iCount; i++) - TRACE(" obj[%ld]=%s\n", i, debugstr_guid(UuidVector->Uuid[i])); + TRACE(" obj[%d]=%s\n", i, debugstr_guid(UuidVector->Uuid[i])); } entries = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*entries) * BindingVector->Count * (UuidVector ? UuidVector->Count : 1)); @@ -319,7 +326,7 @@ RPC_STATUS WINAPI RpcEpUnregister( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *Bin for (i = 0; i < BindingVector->Count; i++) { unsigned j; - RpcBinding* bind = (RpcBinding*)(BindingVector->BindingH[i]); + RpcBinding* bind = BindingVector->BindingH[i]; for (j = 0; j < (UuidVector ? UuidVector->Count : 1); j++) { status = TowerConstruct(&If->InterfaceId, &If->TransferSyntax, @@ -372,8 +379,8 @@ RPC_STATUS WINAPI RpcEpUnregister( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *Bin */ RPC_STATUS WINAPI RpcEpResolveBinding( RPC_BINDING_HANDLE Binding, RPC_IF_HANDLE IfSpec ) { - PRPC_CLIENT_INTERFACE If = (PRPC_CLIENT_INTERFACE)IfSpec; - RpcBinding* bind = (RpcBinding*)Binding; + PRPC_CLIENT_INTERFACE If = IfSpec; + RpcBinding* bind = Binding; RPC_STATUS status; error_status_t status2; handle_t handle; @@ -396,7 +403,7 @@ RPC_STATUS WINAPI RpcEpResolveBinding( RPC_BINDING_HANDLE Binding, RPC_IF_HANDLE status = get_epm_handle_client(Binding, &handle); if (status != RPC_S_OK) return status; - + status = TowerConstruct(&If->InterfaceId, &If->TransferSyntax, bind->Protseq, ((RpcBinding *)handle)->Endpoint, bind->NetworkAddr, &tower); diff --git a/reactos/dll/win32/rpcrt4/rpc_message.c b/reactos/dll/win32/rpcrt4/rpc_message.c index e4f96a9179e..1d18627c339 100644 --- a/reactos/dll/win32/rpcrt4/rpc_message.c +++ b/reactos/dll/win32/rpcrt4/rpc_message.c @@ -51,32 +51,26 @@ WINE_DEFAULT_DEBUG_CHANNEL(rpc); (((alignment) - (((value) % (alignment)))) % (alignment)) #define ROUND_UP(value, alignment) (((value) + ((alignment) - 1)) & ~((alignment)-1)) -enum secure_packet_direction -{ - SECURE_PACKET_SEND, - SECURE_PACKET_RECEIVE -}; - static RPC_STATUS I_RpcReAllocateBuffer(PRPC_MESSAGE pMsg); -static DWORD RPCRT4_GetHeaderSize(const RpcPktHdr *Header) +DWORD RPCRT4_GetHeaderSize(const RpcPktHdr *Header) { static const DWORD header_sizes[] = { 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, 0, sizeof(Header->auth3), 0, 0, 0, sizeof(Header->http) }; ULONG ret = 0; if (Header->common.ptype < sizeof(header_sizes) / sizeof(header_sizes[0])) { ret = header_sizes[Header->common.ptype]; if (ret == 0) - FIXME("unhandled packet type\n"); + FIXME("unhandled packet type %u\n", Header->common.ptype); if (Header->common.flags & RPC_FLG_OBJECT_UUID) ret += sizeof(UUID); } else { - TRACE("invalid packet type\n"); + WARN("invalid packet type %u\n", Header->common.ptype); } return ret; @@ -95,8 +89,23 @@ static int packet_has_auth_verifier(const RpcPktHdr *Header) !(Header->common.ptype == PKT_SHUTDOWN); } +static int packet_does_auth_negotiation(const RpcPktHdr *Header) +{ + switch (Header->common.ptype) + { + case PKT_BIND: + case PKT_BIND_ACK: + case PKT_AUTH3: + case PKT_ALTER_CONTEXT: + case PKT_ALTER_CONTEXT_RESP: + return TRUE; + default: + return FALSE; + } +} + static VOID RPCRT4_BuildCommonHeader(RpcPktHdr *Header, unsigned char PacketType, - unsigned long DataRepresentation) + ULONG DataRepresentation) { Header->common.rpc_ver = RPC_VER_MAJOR; Header->common.rpc_ver_minor = RPC_VER_MINOR; @@ -111,8 +120,8 @@ static VOID RPCRT4_BuildCommonHeader(RpcPktHdr *Header, unsigned char PacketType /* Flags and fragment length are computed in RPCRT4_Send. */ } -static RpcPktHdr *RPCRT4_BuildRequestHeader(unsigned long DataRepresentation, - unsigned long BufferLength, +static RpcPktHdr *RPCRT4_BuildRequestHeader(ULONG DataRepresentation, + ULONG BufferLength, unsigned short ProcNum, UUID *ObjectUuid) { @@ -141,8 +150,7 @@ static RpcPktHdr *RPCRT4_BuildRequestHeader(unsigned long DataRepresentation, return header; } -RpcPktHdr *RPCRT4_BuildResponseHeader(unsigned long DataRepresentation, - unsigned long BufferLength) +RpcPktHdr *RPCRT4_BuildResponseHeader(ULONG DataRepresentation, ULONG BufferLength) { RpcPktHdr *header; @@ -158,8 +166,7 @@ RpcPktHdr *RPCRT4_BuildResponseHeader(unsigned long DataRepresentation, return header; } -RpcPktHdr *RPCRT4_BuildFaultHeader(unsigned long DataRepresentation, - RPC_STATUS Status) +RpcPktHdr *RPCRT4_BuildFaultHeader(ULONG DataRepresentation, RPC_STATUS Status) { RpcPktHdr *header; @@ -175,63 +182,66 @@ RpcPktHdr *RPCRT4_BuildFaultHeader(unsigned long DataRepresentation, return header; } -RpcPktHdr *RPCRT4_BuildBindHeader(unsigned long DataRepresentation, +RpcPktHdr *RPCRT4_BuildBindHeader(ULONG DataRepresentation, unsigned short MaxTransmissionSize, unsigned short MaxReceiveSize, - unsigned long AssocGroupId, + ULONG AssocGroupId, const RPC_SYNTAX_IDENTIFIER *AbstractId, const RPC_SYNTAX_IDENTIFIER *TransferId) { RpcPktHdr *header; + RpcContextElement *ctxt_elem; - header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(header->bind)); + header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof(header->bind) + FIELD_OFFSET(RpcContextElement, transfer_syntaxes[1])); if (header == NULL) { return NULL; } + ctxt_elem = (RpcContextElement *)(&header->bind + 1); RPCRT4_BuildCommonHeader(header, PKT_BIND, DataRepresentation); - header->common.frag_len = sizeof(header->bind); + header->common.frag_len = sizeof(header->bind) + FIELD_OFFSET(RpcContextElement, transfer_syntaxes[1]); header->bind.max_tsize = MaxTransmissionSize; header->bind.max_rsize = MaxReceiveSize; header->bind.assoc_gid = AssocGroupId; header->bind.num_elements = 1; - header->bind.num_syntaxes = 1; - header->bind.abstract = *AbstractId; - header->bind.transfer = *TransferId; + ctxt_elem->num_syntaxes = 1; + ctxt_elem->abstract_syntax = *AbstractId; + ctxt_elem->transfer_syntaxes[0] = *TransferId; return header; } -static RpcPktHdr *RPCRT4_BuildAuthHeader(unsigned long DataRepresentation) +static RpcPktHdr *RPCRT4_BuildAuthHeader(ULONG DataRepresentation) { RpcPktHdr *header; header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, - sizeof(header->common) + 12); + sizeof(header->auth3)); if (header == NULL) return NULL; RPCRT4_BuildCommonHeader(header, PKT_AUTH3, DataRepresentation); - header->common.frag_len = 0x14; - header->common.auth_len = 0; + header->common.frag_len = sizeof(header->auth3); return header; } -RpcPktHdr *RPCRT4_BuildBindNackHeader(unsigned long DataRepresentation, +RpcPktHdr *RPCRT4_BuildBindNackHeader(ULONG DataRepresentation, unsigned char RpcVersion, - unsigned char RpcVersionMinor) + unsigned char RpcVersionMinor, + unsigned short RejectReason) { RpcPktHdr *header; - header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(header->bind_nack)); + header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, FIELD_OFFSET(RpcPktHdr, bind_nack.protocols[1])); if (header == NULL) { return NULL; } RPCRT4_BuildCommonHeader(header, PKT_BIND_NACK, DataRepresentation); - header->common.frag_len = sizeof(header->bind_nack); - header->bind_nack.reject_reason = REJECT_REASON_NOT_SPECIFIED; + header->common.frag_len = FIELD_OFFSET(RpcPktHdr, bind_nack.protocols[1]); + header->bind_nack.reject_reason = RejectReason; header->bind_nack.protocols_count = 1; header->bind_nack.protocols[0].rpc_ver = RpcVersion; header->bind_nack.protocols[0].rpc_ver_minor = RpcVersionMinor; @@ -239,25 +249,22 @@ RpcPktHdr *RPCRT4_BuildBindNackHeader(unsigned long DataRepresentation, return header; } -RpcPktHdr *RPCRT4_BuildBindAckHeader(unsigned long DataRepresentation, +RpcPktHdr *RPCRT4_BuildBindAckHeader(ULONG DataRepresentation, unsigned short MaxTransmissionSize, unsigned short MaxReceiveSize, - unsigned long AssocGroupId, + ULONG AssocGroupId, LPCSTR ServerAddress, - unsigned long Result, - unsigned long Reason, - const RPC_SYNTAX_IDENTIFIER *TransferId) + unsigned char ResultCount, + const RpcResult *Results) { RpcPktHdr *header; - unsigned long header_size; + ULONG header_size; RpcAddressString *server_address; - RpcResults *results; - RPC_SYNTAX_IDENTIFIER *transfer_id; + RpcResultList *results; header_size = sizeof(header->bind_ack) + ROUND_UP(FIELD_OFFSET(RpcAddressString, string[strlen(ServerAddress) + 1]), 4) + - sizeof(RpcResults) + - sizeof(RPC_SYNTAX_IDENTIFIER); + FIELD_OFFSET(RpcResultList, results[ResultCount]); header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, header_size); if (header == NULL) { @@ -273,16 +280,125 @@ RpcPktHdr *RPCRT4_BuildBindAckHeader(unsigned long DataRepresentation, server_address->length = strlen(ServerAddress) + 1; strcpy(server_address->string, ServerAddress); /* results is 4-byte aligned */ - results = (RpcResults*)((ULONG_PTR)server_address + ROUND_UP(FIELD_OFFSET(RpcAddressString, string[server_address->length]), 4)); - results->num_results = 1; - results->results[0].result = Result; - results->results[0].reason = Reason; - transfer_id = (RPC_SYNTAX_IDENTIFIER*)(results + 1); - *transfer_id = *TransferId; + results = (RpcResultList*)((ULONG_PTR)server_address + ROUND_UP(FIELD_OFFSET(RpcAddressString, string[server_address->length]), 4)); + results->num_results = ResultCount; + memcpy(&results->results[0], Results, ResultCount * sizeof(*Results)); 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); @@ -362,7 +478,207 @@ static RPC_STATUS NCA2RPC_STATUS(NCA_STATUS status) } } -static RPC_STATUS RPCRT4_SecurePacket(RpcConnection *Connection, +/* 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; +} + + +RPC_STATUS RPCRT4_default_secure_packet(RpcConnection *Connection, enum secure_packet_direction dir, RpcPktHdr *hdr, unsigned int hdr_size, unsigned char *stub_data, unsigned int stub_data_size, @@ -441,9 +757,9 @@ static RPC_STATUS RPCRT4_SecurePacket(RpcConnection *Connection, * * Transmit a packet with authorization data over connection in acceptable fragments. */ -static RPC_STATUS RPCRT4_SendWithAuth(RpcConnection *Connection, RpcPktHdr *Header, - void *Buffer, unsigned int BufferLength, - const void *Auth, unsigned int AuthLength) +RPC_STATUS RPCRT4_SendWithAuth(RpcConnection *Connection, RpcPktHdr *Header, + void *Buffer, unsigned int BufferLength, + const void *Auth, unsigned int AuthLength) { PUCHAR buffer_pos; DWORD hdr_size; @@ -500,7 +816,7 @@ static RPC_STATUS RPCRT4_SendWithAuth(RpcConnection *Connection, RpcPktHdr *Head memcpy(pkt + hdr_size, buffer_pos, Header->common.frag_len - hdr_size - auth_pad_len - alen); /* add the authorization info */ - if (Connection->AuthInfo && packet_has_auth_verifier(Header)) + if (Header->common.auth_len) { RpcAuthVerifier *auth_hdr = (RpcAuthVerifier *)&pkt[Header->common.frag_len - alen]; @@ -509,13 +825,13 @@ static RPC_STATUS RPCRT4_SendWithAuth(RpcConnection *Connection, RpcPktHdr *Head auth_hdr->auth_pad_length = auth_pad_len; auth_hdr->auth_reserved = 0; /* a unique number... */ - auth_hdr->auth_context_id = (unsigned long)Connection; + auth_hdr->auth_context_id = Connection->auth_context_id; if (AuthLength) memcpy(auth_hdr + 1, Auth, AuthLength); else { - status = RPCRT4_SecurePacket(Connection, SECURE_PACKET_SEND, + status = rpcrt4_conn_secure_packet(Connection, SECURE_PACKET_SEND, (RpcPktHdr *)pkt, hdr_size, pkt + hdr_size, Header->common.frag_len - hdr_size - alen, auth_hdr, @@ -548,43 +864,84 @@ write: } /*********************************************************************** - * RPCRT4_ClientAuthorize (internal) + * RPCRT4_default_authorize (internal) * - * Authorize a client connection. A NULL in param signifies a new connection. + * Authorize a client connection. */ -static RPC_STATUS RPCRT4_ClientAuthorize(RpcConnection *conn, SecBuffer *in, - SecBuffer *out) +RPC_STATUS RPCRT4_default_authorize(RpcConnection *conn, BOOL first_time, + unsigned char *in_buffer, + unsigned int in_size, + unsigned char *out_buffer, + unsigned int *out_size) { SECURITY_STATUS r; SecBufferDesc out_desc; SecBufferDesc inp_desc; SecPkgContext_Sizes secctx_sizes; BOOL continue_needed; - ULONG context_req = ISC_REQ_CONNECTION | ISC_REQ_USE_DCE_STYLE | - ISC_REQ_MUTUAL_AUTH | ISC_REQ_DELEGATE; + ULONG context_req; + SecBuffer in, out; - if (conn->AuthInfo->AuthnLevel == RPC_C_AUTHN_LEVEL_PKT_INTEGRITY) - context_req |= ISC_REQ_INTEGRITY; - else if (conn->AuthInfo->AuthnLevel == RPC_C_AUTHN_LEVEL_PKT_PRIVACY) - context_req |= ISC_REQ_CONFIDENTIALITY | ISC_REQ_INTEGRITY; + if (!out_buffer) + { + *out_size = conn->AuthInfo->cbMaxToken; + return RPC_S_OK; + } - out->BufferType = SECBUFFER_TOKEN; - out->cbBuffer = conn->AuthInfo->cbMaxToken; - out->pvBuffer = HeapAlloc(GetProcessHeap(), 0, out->cbBuffer); - if (!out->pvBuffer) return ERROR_OUTOFMEMORY; + in.BufferType = SECBUFFER_TOKEN; + in.pvBuffer = in_buffer; + in.cbBuffer = in_size; + + out.BufferType = SECBUFFER_TOKEN; + out.pvBuffer = out_buffer; + out.cbBuffer = *out_size; out_desc.ulVersion = 0; out_desc.cBuffers = 1; - out_desc.pBuffers = out; + out_desc.pBuffers = &out; - inp_desc.cBuffers = 1; - inp_desc.pBuffers = in; inp_desc.ulVersion = 0; + inp_desc.cBuffers = 1; + inp_desc.pBuffers = ∈ - r = InitializeSecurityContextW(&conn->AuthInfo->cred, in ? &conn->ctx : NULL, - in ? NULL : conn->AuthInfo->server_principal_name, context_req, 0, - SECURITY_NETWORK_DREP, in ? &inp_desc : NULL, 0, &conn->ctx, - &out_desc, &conn->attr, &conn->exp); + if (conn->server) + { + context_req = ASC_REQ_CONNECTION | ASC_REQ_USE_DCE_STYLE | + ASC_REQ_DELEGATE; + + if (conn->AuthInfo->AuthnLevel == RPC_C_AUTHN_LEVEL_PKT_INTEGRITY) + context_req |= ASC_REQ_INTEGRITY; + else if (conn->AuthInfo->AuthnLevel == RPC_C_AUTHN_LEVEL_PKT_PRIVACY) + context_req |= ASC_REQ_CONFIDENTIALITY | ASC_REQ_INTEGRITY; + + r = AcceptSecurityContext(&conn->AuthInfo->cred, + first_time ? NULL : &conn->ctx, + &inp_desc, context_req, SECURITY_NETWORK_DREP, + &conn->ctx, + &out_desc, &conn->attr, &conn->exp); + if (r == SEC_E_OK || r == SEC_I_COMPLETE_NEEDED) + { + /* authorisation done, so nothing more to send */ + out.cbBuffer = 0; + } + } + else + { + context_req = ISC_REQ_CONNECTION | ISC_REQ_USE_DCE_STYLE | + ISC_REQ_MUTUAL_AUTH | ISC_REQ_DELEGATE; + + if (conn->AuthInfo->AuthnLevel == RPC_C_AUTHN_LEVEL_PKT_INTEGRITY) + context_req |= ISC_REQ_INTEGRITY; + else if (conn->AuthInfo->AuthnLevel == RPC_C_AUTHN_LEVEL_PKT_PRIVACY) + context_req |= ISC_REQ_CONFIDENTIALITY | ISC_REQ_INTEGRITY; + + r = InitializeSecurityContextW(&conn->AuthInfo->cred, + first_time ? NULL: &conn->ctx, + first_time ? conn->AuthInfo->server_principal_name : NULL, + context_req, 0, SECURITY_NETWORK_DREP, + first_time ? NULL : &inp_desc, 0, &conn->ctx, + &out_desc, &conn->attr, &conn->exp); + } if (FAILED(r)) { WARN("InitializeSecurityContext failed with error 0x%08x\n", r); @@ -606,7 +963,7 @@ static RPC_STATUS RPCRT4_ClientAuthorize(RpcConnection *conn, SecBuffer *in, } } - TRACE("cbBuffer = %d\n", out->cbBuffer); + TRACE("cbBuffer = %d\n", out.cbBuffer); if (!continue_needed) { @@ -620,45 +977,240 @@ static RPC_STATUS RPCRT4_ClientAuthorize(RpcConnection *conn, SecBuffer *in, conn->encryption_auth_len = secctx_sizes.cbSecurityTrailer; } + *out_size = out.cbBuffer; return RPC_S_OK; failed: - HeapFree(GetProcessHeap(), 0, out->pvBuffer); - out->pvBuffer = NULL; + *out_size = 0; return ERROR_ACCESS_DENIED; /* FIXME: is this correct? */ } /*********************************************************************** - * RPCRT4_AuthorizeBinding (internal) + * RPCRT4_ClientConnectionAuth (internal) */ -RPC_STATUS RPCRT4_AuthorizeConnection(RpcConnection* conn, BYTE *challenge, - ULONG count) +RPC_STATUS RPCRT4_ClientConnectionAuth(RpcConnection* conn, BYTE *challenge, + ULONG count) { - SecBuffer inp, out; RpcPktHdr *resp_hdr; RPC_STATUS status; + unsigned char *out_buffer; + unsigned int out_len = 0; TRACE("challenge %s, %d bytes\n", challenge, count); - inp.BufferType = SECBUFFER_TOKEN; - inp.pvBuffer = challenge; - inp.cbBuffer = count; - - status = RPCRT4_ClientAuthorize(conn, &inp, &out); + status = rpcrt4_conn_authorize(conn, FALSE, challenge, count, NULL, &out_len); + if (status) return status; + out_buffer = HeapAlloc(GetProcessHeap(), 0, out_len); + if (!out_buffer) return RPC_S_OUT_OF_RESOURCES; + status = rpcrt4_conn_authorize(conn, FALSE, challenge, count, out_buffer, &out_len); if (status) return status; resp_hdr = RPCRT4_BuildAuthHeader(NDR_LOCAL_DATA_REPRESENTATION); - if (!resp_hdr) - return E_OUTOFMEMORY; - status = RPCRT4_SendWithAuth(conn, resp_hdr, NULL, 0, out.pvBuffer, out.cbBuffer); + if (resp_hdr) + status = RPCRT4_SendWithAuth(conn, resp_hdr, NULL, 0, out_buffer, out_len); + else + status = RPC_S_OUT_OF_RESOURCES; - HeapFree(GetProcessHeap(), 0, out.pvBuffer); + HeapFree(GetProcessHeap(), 0, out_buffer); RPCRT4_FreeHeader(resp_hdr); return status; } +/*********************************************************************** + * RPCRT4_ServerConnectionAuth (internal) + */ +RPC_STATUS RPCRT4_ServerConnectionAuth(RpcConnection* conn, + BOOL start, + RpcAuthVerifier *auth_data_in, + ULONG auth_length_in, + unsigned char **auth_data_out, + ULONG *auth_length_out) +{ + unsigned char *out_buffer; + unsigned int out_size; + RPC_STATUS status; + + if (start) + { + /* remove any existing authentication information */ + if (conn->AuthInfo) + { + RpcAuthInfo_Release(conn->AuthInfo); + conn->AuthInfo = NULL; + } + if (SecIsValidHandle(&conn->ctx)) + { + DeleteSecurityContext(&conn->ctx); + SecInvalidateHandle(&conn->ctx); + } + if (auth_length_in >= sizeof(RpcAuthVerifier)) + { + CredHandle cred; + TimeStamp exp; + ULONG max_token; + + status = RPCRT4_ServerGetRegisteredAuthInfo( + auth_data_in->auth_type, &cred, &exp, &max_token); + if (status != RPC_S_OK) + { + ERR("unknown authentication service %u\n", auth_data_in->auth_type); + return status; + } + + status = RpcAuthInfo_Create(auth_data_in->auth_level, + auth_data_in->auth_type, cred, exp, + max_token, NULL, &conn->AuthInfo); + if (status != RPC_S_OK) + return status; + + /* FIXME: should auth_data_in->auth_context_id be checked in the !start case? */ + conn->auth_context_id = auth_data_in->auth_context_id; + } + } + + if (auth_length_in < sizeof(RpcAuthVerifier)) + return RPC_S_OK; + + if (!conn->AuthInfo) + /* should have filled in authentication info by now */ + return RPC_S_PROTOCOL_ERROR; + + status = rpcrt4_conn_authorize( + conn, start, (unsigned char *)(auth_data_in + 1), + auth_length_in - sizeof(RpcAuthVerifier), NULL, &out_size); + if (status) return status; + + out_buffer = HeapAlloc(GetProcessHeap(), 0, out_size); + if (!out_buffer) return RPC_S_OUT_OF_RESOURCES; + + status = rpcrt4_conn_authorize( + conn, start, (unsigned char *)(auth_data_in + 1), + auth_length_in - sizeof(RpcAuthVerifier), out_buffer, &out_size); + if (status != RPC_S_OK) + { + HeapFree(GetProcessHeap(), 0, out_buffer); + return status; + } + + if (out_size && !auth_length_out) + { + ERR("expected authentication to be complete but SSP returned data of " + "%u bytes to be sent back to client\n", out_size); + HeapFree(GetProcessHeap(), 0, out_buffer); + return RPC_S_SEC_PKG_ERROR; + } + else + { + *auth_data_out = out_buffer; + *auth_length_out = out_size; + } + + return status; +} + +/*********************************************************************** + * RPCRT4_default_is_authorized (internal) + * + * Has a connection started the process of authorizing with the server? + */ +BOOL RPCRT4_default_is_authorized(RpcConnection *Connection) +{ + return Connection->AuthInfo && SecIsValidHandle(&Connection->ctx); +} + +/*********************************************************************** + * RPCRT4_default_impersonate_client (internal) + * + */ +RPC_STATUS RPCRT4_default_impersonate_client(RpcConnection *conn) +{ + SECURITY_STATUS sec_status; + + TRACE("(%p)\n", conn); + + if (!conn->AuthInfo || !SecIsValidHandle(&conn->ctx)) + return RPC_S_NO_CONTEXT_AVAILABLE; + sec_status = ImpersonateSecurityContext(&conn->ctx); + if (sec_status != SEC_E_OK) + WARN("ImpersonateSecurityContext returned 0x%08x\n", sec_status); + switch (sec_status) + { + case SEC_E_UNSUPPORTED_FUNCTION: + return RPC_S_CANNOT_SUPPORT; + case SEC_E_NO_IMPERSONATION: + return RPC_S_NO_CONTEXT_AVAILABLE; + case SEC_E_OK: + return RPC_S_OK; + default: + return RPC_S_SEC_PKG_ERROR; + } +} + +/*********************************************************************** + * RPCRT4_default_revert_to_self (internal) + * + */ +RPC_STATUS RPCRT4_default_revert_to_self(RpcConnection *conn) +{ + SECURITY_STATUS sec_status; + + TRACE("(%p)\n", conn); + + if (!conn->AuthInfo || !SecIsValidHandle(&conn->ctx)) + return RPC_S_NO_CONTEXT_AVAILABLE; + sec_status = RevertSecurityContext(&conn->ctx); + if (sec_status != SEC_E_OK) + WARN("RevertSecurityContext returned 0x%08x\n", sec_status); + switch (sec_status) + { + case SEC_E_UNSUPPORTED_FUNCTION: + return RPC_S_CANNOT_SUPPORT; + case SEC_E_NO_IMPERSONATION: + return RPC_S_NO_CONTEXT_AVAILABLE; + case SEC_E_OK: + return RPC_S_OK; + default: + return RPC_S_SEC_PKG_ERROR; + } +} + +/*********************************************************************** + * RPCRT4_default_inquire_auth_client (internal) + * + * Default function to retrieve the authentication details that the client + * is using to call the server. + */ +RPC_STATUS RPCRT4_default_inquire_auth_client( + RpcConnection *conn, RPC_AUTHZ_HANDLE *privs, RPC_WSTR *server_princ_name, + ULONG *authn_level, ULONG *authn_svc, ULONG *authz_svc, ULONG flags) +{ + if (!conn->AuthInfo) return RPC_S_BINDING_HAS_NO_AUTH; + + if (privs) + { + FIXME("privs not implemented\n"); + *privs = NULL; + } + if (server_princ_name) + { + *server_princ_name = RPCRT4_strdupW(conn->AuthInfo->server_principal_name); + if (!*server_princ_name) return ERROR_OUTOFMEMORY; + } + if (authn_level) *authn_level = conn->AuthInfo->AuthnLevel; + if (authn_svc) *authn_svc = conn->AuthInfo->AuthnSvc; + if (authz_svc) + { + FIXME("authorization service not implemented\n"); + *authz_svc = RPC_C_AUTHZ_NONE; + } + if (flags) + FIXME("flags 0x%x not implemented\n", flags); + + return RPC_S_OK; +} + /*********************************************************************** * RPCRT4_Send (internal) * @@ -668,26 +1220,35 @@ RPC_STATUS RPCRT4_Send(RpcConnection *Connection, RpcPktHdr *Header, void *Buffer, unsigned int BufferLength) { RPC_STATUS r; - SecBuffer out; - if (!Connection->AuthInfo || SecIsValidHandle(&Connection->ctx)) + if (packet_does_auth_negotiation(Header) && + Connection->AuthInfo && + !rpcrt4_conn_is_authorized(Connection)) { - return RPCRT4_SendWithAuth(Connection, Header, Buffer, BufferLength, NULL, 0); - } + unsigned int out_size = 0; + unsigned char *out_buffer; - /* tack on a negotiate packet */ - r = RPCRT4_ClientAuthorize(Connection, NULL, &out); - if (r == RPC_S_OK) - { - r = RPCRT4_SendWithAuth(Connection, Header, Buffer, BufferLength, out.pvBuffer, out.cbBuffer); - HeapFree(GetProcessHeap(), 0, out.pvBuffer); + r = rpcrt4_conn_authorize(Connection, TRUE, NULL, 0, NULL, &out_size); + if (r != RPC_S_OK) return r; + + out_buffer = HeapAlloc(GetProcessHeap(), 0, out_size); + if (!out_buffer) return RPC_S_OUT_OF_RESOURCES; + + /* tack on a negotiate packet */ + r = rpcrt4_conn_authorize(Connection, TRUE, NULL, 0, out_buffer, &out_size); + if (r == RPC_S_OK) + r = RPCRT4_SendWithAuth(Connection, Header, Buffer, BufferLength, out_buffer, out_size); + + HeapFree(GetProcessHeap(), 0, out_buffer); } + else + r = RPCRT4_SendWithAuth(Connection, Header, Buffer, BufferLength, NULL, 0); return r; } /* validates version and frag_len fields */ -static RPC_STATUS RPCRT4_ValidateCommonHeader(const RpcPktCommonHdr *hdr) +RPC_STATUS RPCRT4_ValidateCommonHeader(const RpcPktCommonHdr *hdr) { DWORD hdr_length; @@ -716,11 +1277,11 @@ static RPC_STATUS RPCRT4_ValidateCommonHeader(const RpcPktCommonHdr *hdr) } /*********************************************************************** - * RPCRT4_receive_fragment (internal) + * RPCRT4_default_receive_fragment (internal) * * Receive a fragment from a connection. */ -static RPC_STATUS RPCRT4_receive_fragment(RpcConnection *Connection, RpcPktHdr **Header, void **Payload) +static RPC_STATUS RPCRT4_default_receive_fragment(RpcConnection *Connection, RpcPktHdr **Header, void **Payload) { RPC_STATUS status; DWORD hdr_length; @@ -794,6 +1355,14 @@ fail: 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) * @@ -803,20 +1372,22 @@ fail: RPC_STATUS RPCRT4_ReceiveWithAuth(RpcConnection *Connection, RpcPktHdr **Header, PRPC_MESSAGE pMsg, unsigned char **auth_data_out, - unsigned long *auth_length_out) + ULONG *auth_length_out) { RPC_STATUS status; DWORD hdr_length; unsigned short first_flag; - unsigned long data_length; - unsigned long buffer_length; - unsigned long auth_length = 0; + ULONG data_length; + ULONG buffer_length; + ULONG auth_length = 0; unsigned char *auth_data = NULL; RpcPktHdr *CurrentHeader = NULL; void *payload = NULL; *Header = NULL; pMsg->Buffer = NULL; + if (auth_data_out) *auth_data_out = NULL; + if (auth_length_out) *auth_length_out = 0; TRACE("(%p, %p, %p, %p)\n", Connection, Header, pMsg, auth_data_out); @@ -874,7 +1445,7 @@ RPC_STATUS RPCRT4_ReceiveWithAuth(RpcConnection *Connection, RpcPktHdr **Header, } if (CurrentHeader->common.auth_len != auth_length) { - WARN("auth_len header field changed from %ld to %d\n", + WARN("auth_len header field changed from %d to %d\n", auth_length, CurrentHeader->common.auth_len); status = RPC_S_PROTOCOL_ERROR; goto fail; @@ -888,7 +1459,7 @@ RPC_STATUS RPCRT4_ReceiveWithAuth(RpcConnection *Connection, RpcPktHdr **Header, 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 = %ld\n", + TRACE("allocation hint exceeded, new buffer length = %d\n", data_length + buffer_length); pMsg->BufferLength = data_length + buffer_length; status = I_RpcReAllocateBuffer(pMsg); @@ -914,9 +1485,9 @@ RPC_STATUS RPCRT4_ReceiveWithAuth(RpcConnection *Connection, RpcPktHdr **Header, /* these packets are handled specially, not by the generic SecurePacket * function */ - if (!auth_data_out && SecIsValidHandle(&Connection->ctx)) + if (!packet_does_auth_negotiation(*Header) && rpcrt4_conn_is_authorized(Connection)) { - status = RPCRT4_SecurePacket(Connection, SECURE_PACKET_RECEIVE, + status = rpcrt4_conn_secure_packet(Connection, SECURE_PACKET_RECEIVE, CurrentHeader, hdr_length, (unsigned char *)pMsg->Buffer + buffer_length, data_length, (RpcAuthVerifier *)auth_data, @@ -976,8 +1547,8 @@ fail: * * Receive a packet from connection and merge the fragments. */ -RPC_STATUS RPCRT4_Receive(RpcConnection *Connection, RpcPktHdr **Header, - PRPC_MESSAGE pMsg) +static RPC_STATUS RPCRT4_Receive(RpcConnection *Connection, RpcPktHdr **Header, + PRPC_MESSAGE pMsg) { return RPCRT4_ReceiveWithAuth(Connection, Header, pMsg, NULL, NULL); } @@ -998,7 +1569,7 @@ RPC_STATUS RPCRT4_Receive(RpcConnection *Connection, RpcPktHdr **Header, */ RPC_STATUS WINAPI I_RpcNegotiateTransferSyntax(PRPC_MESSAGE pMsg) { - RpcBinding* bind = (RpcBinding*)pMsg->Handle; + RpcBinding* bind = pMsg->Handle; RpcConnection* conn; RPC_STATUS status = RPC_S_OK; @@ -1063,7 +1634,7 @@ RPC_STATUS WINAPI I_RpcNegotiateTransferSyntax(PRPC_MESSAGE pMsg) RPC_STATUS WINAPI I_RpcGetBuffer(PRPC_MESSAGE pMsg) { RPC_STATUS status; - RpcBinding* bind = (RpcBinding*)pMsg->Handle; + RpcBinding* bind = pMsg->Handle; TRACE("(%p): BufferLength=%d\n", pMsg, pMsg->BufferLength); @@ -1120,7 +1691,7 @@ static RPC_STATUS I_RpcReAllocateBuffer(PRPC_MESSAGE pMsg) */ RPC_STATUS WINAPI I_RpcFreeBuffer(PRPC_MESSAGE pMsg) { - RpcBinding* bind = (RpcBinding*)pMsg->Handle; + RpcBinding* bind = pMsg->Handle; TRACE("(%p) Buffer=%p\n", pMsg, pMsg->Buffer); @@ -1214,7 +1785,7 @@ static DWORD WINAPI async_notifier_proc(LPVOID p) */ RPC_STATUS WINAPI I_RpcSend(PRPC_MESSAGE pMsg) { - RpcBinding* bind = (RpcBinding*)pMsg->Handle; + RpcBinding* bind = pMsg->Handle; RpcConnection* conn; RPC_STATUS status; RpcPktHdr *hdr; @@ -1268,7 +1839,7 @@ static inline BOOL is_hard_error(RPC_STATUS status) */ RPC_STATUS WINAPI I_RpcReceive(PRPC_MESSAGE pMsg) { - RpcBinding* bind = (RpcBinding*)pMsg->Handle; + RpcBinding* bind = pMsg->Handle; RPC_STATUS status; RpcPktHdr *hdr = NULL; RpcConnection *conn; @@ -1287,7 +1858,7 @@ RPC_STATUS WINAPI I_RpcReceive(PRPC_MESSAGE pMsg) case PKT_RESPONSE: break; case PKT_FAULT: - ERR ("we got fault packet with status 0x%lx\n", hdr->fault.status); + ERR ("we got fault packet with status 0x%x\n", hdr->fault.status); status = NCA2RPC_STATUS(hdr->fault.status); if (is_hard_error(status)) goto fail; @@ -1360,7 +1931,7 @@ RPC_STATUS WINAPI I_RpcSendReceive(PRPC_MESSAGE pMsg) */ RPC_STATUS WINAPI I_RpcAsyncSetHandle(PRPC_MESSAGE pMsg, PRPC_ASYNC_STATE pAsync) { - RpcBinding* bind = (RpcBinding*)pMsg->Handle; + RpcBinding* bind = pMsg->Handle; RpcConnection *conn; TRACE("(%p, %p)\n", pMsg, pAsync); diff --git a/reactos/dll/win32/rpcrt4/rpc_message.h b/reactos/dll/win32/rpcrt4/rpc_message.h index e4033882feb..3ad876174e0 100644 --- a/reactos/dll/win32/rpcrt4/rpc_message.h +++ b/reactos/dll/win32/rpcrt4/rpc_message.h @@ -25,16 +25,35 @@ typedef unsigned int NCA_STATUS; -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, unsigned long *auth_length_out); -NCA_STATUS RPC2NCA_STATUS(RPC_STATUS status); -RPC_STATUS RPCRT4_AuthorizeConnection(RpcConnection* conn, BYTE *challenge, ULONG count); +RpcPktHdr *RPCRT4_BuildFaultHeader(ULONG DataRepresentation, RPC_STATUS Status) DECLSPEC_HIDDEN; +RpcPktHdr *RPCRT4_BuildResponseHeader(ULONG DataRepresentation, ULONG BufferLength) DECLSPEC_HIDDEN; +RpcPktHdr *RPCRT4_BuildBindHeader(ULONG DataRepresentation, unsigned short MaxTransmissionSize, unsigned short MaxReceiveSize, ULONG AssocGroupId, const RPC_SYNTAX_IDENTIFIER *AbstractId, const RPC_SYNTAX_IDENTIFIER *TransferId) DECLSPEC_HIDDEN; +RpcPktHdr *RPCRT4_BuildBindNackHeader(ULONG DataRepresentation, unsigned char RpcVersion, unsigned char RpcVersionMinor, unsigned short RejectReason) DECLSPEC_HIDDEN; +RpcPktHdr *RPCRT4_BuildBindAckHeader(ULONG DataRepresentation, unsigned short MaxTransmissionSize, unsigned short MaxReceiveSize, ULONG AssocGroupId, LPCSTR ServerAddress, unsigned char ResultCount, const RpcResult *Results) DECLSPEC_HIDDEN; +RpcPktHdr *RPCRT4_BuildHttpHeader(ULONG DataRepresentation, unsigned short flags, unsigned short num_data_items, unsigned int payload_size) DECLSPEC_HIDDEN; +RpcPktHdr *RPCRT4_BuildHttpConnectHeader(unsigned short flags, int out_pipe, const UUID *connection_uuid, const UUID *pipe_uuid, const UUID *association_uuid) DECLSPEC_HIDDEN; +RpcPktHdr *RPCRT4_BuildHttpFlowControlHeader(BOOL server, ULONG bytes_transmitted, ULONG flow_control_increment, const UUID *pipe_uuid) DECLSPEC_HIDDEN; +VOID RPCRT4_FreeHeader(RpcPktHdr *Header) DECLSPEC_HIDDEN; +RPC_STATUS RPCRT4_Send(RpcConnection *Connection, RpcPktHdr *Header, void *Buffer, unsigned int BufferLength) DECLSPEC_HIDDEN; +RPC_STATUS RPCRT4_SendWithAuth(RpcConnection *Connection, RpcPktHdr *Header, void *Buffer, unsigned int BufferLength, const void *Auth, unsigned int AuthLength) DECLSPEC_HIDDEN; +RPC_STATUS RPCRT4_ReceiveWithAuth(RpcConnection *Connection, RpcPktHdr **Header, PRPC_MESSAGE pMsg, unsigned char **auth_data_out, ULONG *auth_length_out) DECLSPEC_HIDDEN; +DWORD RPCRT4_GetHeaderSize(const RpcPktHdr *Header) DECLSPEC_HIDDEN; +RPC_STATUS RPCRT4_ValidateCommonHeader(const RpcPktCommonHdr *hdr) DECLSPEC_HIDDEN; + +BOOL RPCRT4_IsValidHttpPacket(RpcPktHdr *hdr, unsigned char *data, unsigned short data_len) DECLSPEC_HIDDEN; +RPC_STATUS RPCRT4_ParseHttpPrepareHeader1(RpcPktHdr *header, unsigned char *data, ULONG *field1) DECLSPEC_HIDDEN; +RPC_STATUS RPCRT4_ParseHttpPrepareHeader2(RpcPktHdr *header, unsigned char *data, ULONG *field1, ULONG *bytes_until_next_packet, ULONG *field3) DECLSPEC_HIDDEN; +RPC_STATUS RPCRT4_ParseHttpFlowControlHeader(RpcPktHdr *header, unsigned char *data, BOOL server, ULONG *bytes_transmitted, ULONG *flow_control_increment, UUID *pipe_uuid) DECLSPEC_HIDDEN; +NCA_STATUS RPC2NCA_STATUS(RPC_STATUS status) DECLSPEC_HIDDEN; +RPC_STATUS RPCRT4_ClientConnectionAuth(RpcConnection* conn, BYTE *challenge, ULONG count) DECLSPEC_HIDDEN; +RPC_STATUS RPCRT4_ServerConnectionAuth(RpcConnection* conn, BOOL start, RpcAuthVerifier *auth_data_in, ULONG auth_length_in, unsigned char **auth_data_out, ULONG *auth_length_out) DECLSPEC_HIDDEN; +RPC_STATUS RPCRT4_AuthorizeConnection(RpcConnection* conn, BYTE *challenge, ULONG count) DECLSPEC_HIDDEN; +RPC_STATUS RPCRT4_ServerGetRegisteredAuthInfo(USHORT auth_type, CredHandle *cred, TimeStamp *exp, ULONG *max_token) DECLSPEC_HIDDEN; +RPC_STATUS RPCRT4_default_authorize(RpcConnection *conn, BOOL first_time, unsigned char *in_buffer, unsigned int in_size, unsigned char *out_buffer, unsigned int *out_size) DECLSPEC_HIDDEN; +BOOL RPCRT4_default_is_authorized(RpcConnection *Connection) DECLSPEC_HIDDEN; +RPC_STATUS RPCRT4_default_secure_packet(RpcConnection *Connection, enum secure_packet_direction dir, RpcPktHdr *hdr, unsigned int hdr_size, unsigned char *stub_data, unsigned int stub_data_size, RpcAuthVerifier *auth_hdr, unsigned char *auth_value, unsigned int auth_value_size) DECLSPEC_HIDDEN; +RPC_STATUS RPCRT4_default_impersonate_client(RpcConnection *conn) DECLSPEC_HIDDEN; +RPC_STATUS RPCRT4_default_revert_to_self(RpcConnection *conn) DECLSPEC_HIDDEN; +RPC_STATUS RPCRT4_default_inquire_auth_client(RpcConnection *conn, RPC_AUTHZ_HANDLE *privs, RPC_WSTR *server_princ_name, ULONG *authn_level, ULONG *authn_svc, ULONG *authz_svc, ULONG flags) DECLSPEC_HIDDEN; #endif diff --git a/reactos/dll/win32/rpcrt4/rpc_server.c b/reactos/dll/win32/rpcrt4/rpc_server.c index 473c7ba9328..c5d2224b69d 100644 --- a/reactos/dll/win32/rpcrt4/rpc_server.c +++ b/reactos/dll/win32/rpcrt4/rpc_server.c @@ -52,6 +52,8 @@ typedef struct _RpcPacket struct _RpcConnection* conn; RpcPktHdr* hdr; RPC_MESSAGE* msg; + unsigned char *auth_data; + ULONG auth_length; } RpcPacket; typedef struct _RpcObjTypeMap @@ -67,6 +69,7 @@ static RpcObjTypeMap *RpcObjTypeMaps; /* list of type RpcServerProtseq */ static struct list protseqs = LIST_INIT(protseqs); static struct list server_interfaces = LIST_INIT(server_interfaces); +static struct list server_registered_auth_info = LIST_INIT(server_registered_auth_info); static CRITICAL_SECTION server_cs; static CRITICAL_SECTION_DEBUG server_cs_debug = @@ -86,12 +89,23 @@ static CRITICAL_SECTION_DEBUG listen_cs_debug = }; static CRITICAL_SECTION listen_cs = { &listen_cs_debug, -1, 0, 0, 0, 0 }; +static CRITICAL_SECTION server_auth_info_cs; +static CRITICAL_SECTION_DEBUG server_auth_info_cs_debug = +{ + 0, 0, &server_auth_info_cs, + { &server_auth_info_cs_debug.ProcessLocksList, &server_auth_info_cs_debug.ProcessLocksList }, + 0, 0, { (DWORD_PTR)(__FILE__ ": server_auth_info_cs") } +}; +static CRITICAL_SECTION server_auth_info_cs = { &server_auth_info_cs_debug, -1, 0, 0, 0, 0 }; + /* whether the server is currently listening */ static BOOL std_listen; /* number of manual listeners (calls to RpcServerListen) */ static LONG manual_listen_count; /* total listeners including auto listeners */ static LONG listen_count; +/* event set once all listening is finished */ +static HANDLE listen_done_event; static UUID uuid_nil; @@ -118,7 +132,8 @@ static inline UUID *LookupObjType(UUID *ObjUuid) } static RpcServerInterface* RPCRT4_find_interface(UUID* object, - const RPC_SYNTAX_IDENTIFIER* if_id, + const RPC_SYNTAX_IDENTIFIER *if_id, + const RPC_SYNTAX_IDENTIFIER *transfer_syntax, BOOL check_object) { UUID* MgrType = NULL; @@ -130,6 +145,7 @@ static RpcServerInterface* RPCRT4_find_interface(UUID* object, EnterCriticalSection(&server_cs); LIST_FOR_EACH_ENTRY(cif, &server_interfaces, RpcServerInterface, entry) { if (!memcmp(if_id, &cif->If->InterfaceId, sizeof(RPC_SYNTAX_IDENTIFIER)) && + (!transfer_syntax || !memcmp(transfer_syntax, &cif->If->TransferSyntax, sizeof(RPC_SYNTAX_IDENTIFIER))) && (check_object == FALSE || UuidEqual(MgrType, &cif->MgrTypeUuid, &status)) && std_listen) { InterlockedIncrement(&cif->CurrentCalls); @@ -156,64 +172,197 @@ static void RPCRT4_release_server_interface(RpcServerInterface *sif) } } -static RPC_STATUS process_bind_packet(RpcConnection *conn, RpcPktBindHdr *hdr, RPC_MESSAGE *msg) +static RpcPktHdr *handle_bind_error(RpcConnection *conn, RPC_STATUS error) +{ + unsigned int reject_reason; + switch (error) + { + case RPC_S_SERVER_TOO_BUSY: + reject_reason = REJECT_TEMPORARY_CONGESTION; + break; + case ERROR_OUTOFMEMORY: + case RPC_S_OUT_OF_RESOURCES: + reject_reason = REJECT_LOCAL_LIMIT_EXCEEDED; + break; + case RPC_S_PROTOCOL_ERROR: + reject_reason = REJECT_PROTOCOL_VERSION_NOT_SUPPORTED; + break; + case RPC_S_UNKNOWN_AUTHN_SERVICE: + reject_reason = REJECT_UNKNOWN_AUTHN_SERVICE; + break; + case ERROR_ACCESS_DENIED: + reject_reason = REJECT_INVALID_CHECKSUM; + break; + default: + FIXME("unexpected status value %d\n", error); + /* fall through */ + case RPC_S_INVALID_BOUND: + reject_reason = REJECT_REASON_NOT_SPECIFIED; + break; + } + return RPCRT4_BuildBindNackHeader(NDR_LOCAL_DATA_REPRESENTATION, + RPC_VER_MAJOR, RPC_VER_MINOR, + reject_reason); +} + +static RPC_STATUS process_bind_packet_no_send( + RpcConnection *conn, RpcPktBindHdr *hdr, RPC_MESSAGE *msg, + unsigned char *auth_data, ULONG auth_length, RpcPktHdr **ack_response, + unsigned char **auth_data_out, ULONG *auth_length_out) { RPC_STATUS status; - RpcServerInterface* sif; - RpcPktHdr *response = NULL; + RpcContextElement *ctxt_elem; + unsigned int i; + RpcResult *results; + + /* validate data */ + for (i = 0, ctxt_elem = msg->Buffer; + i < hdr->num_elements; + i++, ctxt_elem = (RpcContextElement *)&ctxt_elem->transfer_syntaxes[ctxt_elem->num_syntaxes]) + { + if (((char *)ctxt_elem - (char *)msg->Buffer) > msg->BufferLength || + ((char *)&ctxt_elem->transfer_syntaxes[ctxt_elem->num_syntaxes] - (char *)msg->Buffer) > msg->BufferLength) + { + ERR("inconsistent data in packet - packet length %d, num elements %d\n", + msg->BufferLength, hdr->num_elements); + return RPC_S_INVALID_BOUND; + } + } - /* FIXME: do more checks! */ if (hdr->max_tsize < RPC_MIN_PACKET_SIZE || !UuidIsNil(&conn->ActiveInterface.SyntaxGUID, &status) || - conn->server_binding) { + conn->server_binding) + { TRACE("packet size less than min size, or active interface syntax guid non-null\n"); - sif = NULL; - } else { - /* create temporary binding */ - if (RPCRT4_MakeBinding(&conn->server_binding, conn) == RPC_S_OK && - RpcServerAssoc_GetAssociation(rpcrt4_conn_get_name(conn), - conn->NetworkAddr, conn->Endpoint, - conn->NetworkOptions, - hdr->assoc_gid, - &conn->server_binding->Assoc) == RPC_S_OK) - sif = RPCRT4_find_interface(NULL, &hdr->abstract, FALSE); - else - sif = NULL; - } - if (sif == NULL) { - TRACE("rejecting bind request on connection %p\n", conn); - /* Report failure to client. */ - response = RPCRT4_BuildBindNackHeader(NDR_LOCAL_DATA_REPRESENTATION, - RPC_VER_MAJOR, RPC_VER_MINOR); - } else { - TRACE("accepting bind request on connection %p for %s\n", conn, - debugstr_guid(&hdr->abstract.SyntaxGUID)); - /* accept. */ - response = RPCRT4_BuildBindAckHeader(NDR_LOCAL_DATA_REPRESENTATION, - RPC_MAX_PACKET_SIZE, - RPC_MAX_PACKET_SIZE, - conn->server_binding->Assoc->assoc_group_id, - conn->Endpoint, - RESULT_ACCEPT, REASON_NONE, - &sif->If->TransferSyntax); - - /* save the interface for later use */ - conn->ActiveInterface = hdr->abstract; - conn->MaxTransmissionSize = hdr->max_tsize; - - RPCRT4_release_server_interface(sif); + return RPC_S_INVALID_BOUND; } - if (response) - status = RPCRT4_Send(conn, response, NULL, 0); + results = HeapAlloc(GetProcessHeap(), 0, + hdr->num_elements * sizeof(*results)); + if (!results) + return RPC_S_OUT_OF_RESOURCES; + + for (i = 0, ctxt_elem = (RpcContextElement *)msg->Buffer; + i < hdr->num_elements; + i++, ctxt_elem = (RpcContextElement *)&ctxt_elem->transfer_syntaxes[ctxt_elem->num_syntaxes]) + { + RpcServerInterface* sif = NULL; + unsigned int j; + + for (j = 0; !sif && j < ctxt_elem->num_syntaxes; j++) + { + sif = RPCRT4_find_interface(NULL, &ctxt_elem->abstract_syntax, + &ctxt_elem->transfer_syntaxes[j], FALSE); + if (sif) + break; + } + if (sif) + { + RPCRT4_release_server_interface(sif); + TRACE("accepting bind request on connection %p for %s\n", conn, + debugstr_guid(&ctxt_elem->abstract_syntax.SyntaxGUID)); + results[i].result = RESULT_ACCEPT; + results[i].reason = REASON_NONE; + results[i].transfer_syntax = ctxt_elem->transfer_syntaxes[j]; + + /* save the interface for later use */ + /* FIXME: save linked list */ + conn->ActiveInterface = ctxt_elem->abstract_syntax; + } + else if ((sif = RPCRT4_find_interface(NULL, &ctxt_elem->abstract_syntax, + NULL, FALSE)) != NULL) + { + RPCRT4_release_server_interface(sif); + TRACE("not accepting bind request on connection %p for %s - no transfer syntaxes supported\n", + conn, debugstr_guid(&ctxt_elem->abstract_syntax.SyntaxGUID)); + results[i].result = RESULT_PROVIDER_REJECTION; + results[i].reason = REASON_TRANSFER_SYNTAXES_NOT_SUPPORTED; + memset(&results[i].transfer_syntax, 0, sizeof(results[i].transfer_syntax)); + } + else + { + TRACE("not accepting bind request on connection %p for %s - abstract syntax not supported\n", + conn, debugstr_guid(&ctxt_elem->abstract_syntax.SyntaxGUID)); + results[i].result = RESULT_PROVIDER_REJECTION; + results[i].reason = REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED; + memset(&results[i].transfer_syntax, 0, sizeof(results[i].transfer_syntax)); + } + } + + /* create temporary binding */ + status = RPCRT4_MakeBinding(&conn->server_binding, conn); + if (status != RPC_S_OK) + { + HeapFree(GetProcessHeap(), 0, results); + return status; + } + + status = RpcServerAssoc_GetAssociation(rpcrt4_conn_get_name(conn), + conn->NetworkAddr, conn->Endpoint, + conn->NetworkOptions, + hdr->assoc_gid, + &conn->server_binding->Assoc); + if (status != RPC_S_OK) + { + HeapFree(GetProcessHeap(), 0, results); + return status; + } + + if (auth_length) + { + status = RPCRT4_ServerConnectionAuth(conn, TRUE, + (RpcAuthVerifier *)auth_data, + auth_length, auth_data_out, + auth_length_out); + if (status != RPC_S_OK) + { + HeapFree(GetProcessHeap(), 0, results); + return status; + } + } + + *ack_response = RPCRT4_BuildBindAckHeader(NDR_LOCAL_DATA_REPRESENTATION, + RPC_MAX_PACKET_SIZE, + RPC_MAX_PACKET_SIZE, + conn->server_binding->Assoc->assoc_group_id, + conn->Endpoint, hdr->num_elements, + results); + HeapFree(GetProcessHeap(), 0, results); + + if (*ack_response) + conn->MaxTransmissionSize = hdr->max_tsize; else - status = ERROR_OUTOFMEMORY; - RPCRT4_FreeHeader(response); + status = RPC_S_OUT_OF_RESOURCES; return status; } +static RPC_STATUS process_bind_packet(RpcConnection *conn, RpcPktBindHdr *hdr, + RPC_MESSAGE *msg, + unsigned char *auth_data, + ULONG auth_length) +{ + RPC_STATUS status; + RpcPktHdr *response = NULL; + unsigned char *auth_data_out = NULL; + ULONG auth_length_out = 0; + + status = process_bind_packet_no_send(conn, hdr, msg, auth_data, auth_length, + &response, &auth_data_out, + &auth_length_out); + if (status != RPC_S_OK) + response = handle_bind_error(conn, status); + if (response) + status = RPCRT4_SendWithAuth(conn, response, NULL, 0, auth_data_out, auth_length_out); + else + status = ERROR_OUTOFMEMORY; + RPCRT4_FreeHeader(response); + + return status; +} + + static RPC_STATUS process_request_packet(RpcConnection *conn, RpcPktRequestHdr *hdr, RPC_MESSAGE *msg) { RPC_STATUS status; @@ -242,7 +391,7 @@ static RPC_STATUS process_request_packet(RpcConnection *conn, RpcPktRequestHdr * object_uuid = NULL; } - sif = RPCRT4_find_interface(object_uuid, &conn->ActiveInterface, TRUE); + sif = RPCRT4_find_interface(object_uuid, &conn->ActiveInterface, NULL, TRUE); if (!sif) { WARN("interface %s no longer registered, returning fault packet\n", debugstr_guid(&conn->ActiveInterface.SyntaxGUID)); response = RPCRT4_BuildFaultHeader(NDR_LOCAL_DATA_REPRESENTATION, @@ -327,25 +476,52 @@ static RPC_STATUS process_request_packet(RpcConnection *conn, RpcPktRequestHdr * return status; } -static void RPCRT4_process_packet(RpcConnection* conn, RpcPktHdr* hdr, RPC_MESSAGE* msg) +static RPC_STATUS process_auth3_packet(RpcConnection *conn, + RpcPktCommonHdr *hdr, + RPC_MESSAGE *msg, + unsigned char *auth_data, + ULONG auth_length) { - RPC_STATUS status; + RPC_STATUS status; + if (UuidIsNil(&conn->ActiveInterface.SyntaxGUID, &status) || + !auth_length || msg->BufferLength != 0) + status = RPC_S_PROTOCOL_ERROR; + else + { + status = RPCRT4_ServerConnectionAuth(conn, FALSE, + (RpcAuthVerifier *)auth_data, + auth_length, NULL, NULL); + } + + /* FIXME: client doesn't expect a response to this message so must store + * status in connection so that fault packet can be returned when next + * packet is received */ + + return RPC_S_OK; +} + +static void RPCRT4_process_packet(RpcConnection* conn, RpcPktHdr* hdr, + RPC_MESSAGE* msg, unsigned char *auth_data, + ULONG auth_length) +{ msg->Handle = (RPC_BINDING_HANDLE)conn->server_binding; switch (hdr->common.ptype) { case PKT_BIND: TRACE("got bind packet\n"); - - status = process_bind_packet(conn, &hdr->bind, msg); + process_bind_packet(conn, &hdr->bind, msg, auth_data, auth_length); break; case PKT_REQUEST: TRACE("got request packet\n"); - - status = process_request_packet(conn, &hdr->request, msg); + process_request_packet(conn, &hdr->request, msg); break; + case PKT_AUTH3: + TRACE("got auth3 packet\n"); + process_auth3_packet(conn, &hdr->common, msg, auth_data, auth_length); + break; default: FIXME("unhandled packet type %u\n", hdr->common.ptype); break; @@ -355,57 +531,96 @@ static void RPCRT4_process_packet(RpcConnection* conn, RpcPktHdr* hdr, RPC_MESSA I_RpcFree(msg->Buffer); RPCRT4_FreeHeader(hdr); HeapFree(GetProcessHeap(), 0, msg); + HeapFree(GetProcessHeap(), 0, auth_data); } static DWORD CALLBACK RPCRT4_worker_thread(LPVOID the_arg) { RpcPacket *pkt = the_arg; - RPCRT4_process_packet(pkt->conn, pkt->hdr, pkt->msg); + RPCRT4_process_packet(pkt->conn, pkt->hdr, pkt->msg, pkt->auth_data, + pkt->auth_length); HeapFree(GetProcessHeap(), 0, pkt); return 0; } static DWORD CALLBACK RPCRT4_io_thread(LPVOID the_arg) { - RpcConnection* conn = (RpcConnection*)the_arg; + RpcConnection* conn = the_arg; RpcPktHdr *hdr; RPC_MESSAGE *msg; RPC_STATUS status; RpcPacket *packet; + unsigned char *auth_data; + ULONG auth_length; TRACE("(%p)\n", conn); for (;;) { msg = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RPC_MESSAGE)); + if (!msg) break; - status = RPCRT4_Receive(conn, &hdr, msg); + status = RPCRT4_ReceiveWithAuth(conn, &hdr, msg, &auth_data, &auth_length); if (status != RPC_S_OK) { WARN("receive failed with error %x\n", status); HeapFree(GetProcessHeap(), 0, msg); break; } - packet = HeapAlloc(GetProcessHeap(), 0, sizeof(RpcPacket)); - if (!packet) { - I_RpcFree(msg->Buffer); - RPCRT4_FreeHeader(hdr); - HeapFree(GetProcessHeap(), 0, msg); + switch (hdr->common.ptype) { + case PKT_BIND: + TRACE("got bind packet\n"); + + status = process_bind_packet(conn, &hdr->bind, msg, auth_data, + auth_length); break; - } - packet->conn = conn; - packet->hdr = hdr; - packet->msg = msg; - if (!QueueUserWorkItem(RPCRT4_worker_thread, packet, WT_EXECUTELONGFUNCTION)) { - ERR("couldn't queue work item for worker thread, error was %d\n", GetLastError()); - I_RpcFree(msg->Buffer); - RPCRT4_FreeHeader(hdr); - HeapFree(GetProcessHeap(), 0, msg); - HeapFree(GetProcessHeap(), 0, packet); + + case PKT_REQUEST: + TRACE("got request packet\n"); + + packet = HeapAlloc(GetProcessHeap(), 0, sizeof(RpcPacket)); + if (!packet) { + I_RpcFree(msg->Buffer); + RPCRT4_FreeHeader(hdr); + HeapFree(GetProcessHeap(), 0, msg); + HeapFree(GetProcessHeap(), 0, auth_data); + goto exit; + } + packet->conn = conn; + packet->hdr = hdr; + packet->msg = msg; + packet->auth_data = auth_data; + packet->auth_length = auth_length; + if (!QueueUserWorkItem(RPCRT4_worker_thread, packet, WT_EXECUTELONGFUNCTION)) { + ERR("couldn't queue work item for worker thread, error was %d\n", GetLastError()); + HeapFree(GetProcessHeap(), 0, packet); + status = RPC_S_OUT_OF_RESOURCES; + } else { + continue; + } + break; + + case PKT_AUTH3: + TRACE("got auth3 packet\n"); + + status = process_auth3_packet(conn, &hdr->common, msg, auth_data, + auth_length); + break; + default: + FIXME("unhandled packet type %u\n", hdr->common.ptype); break; } - msg = NULL; + I_RpcFree(msg->Buffer); + RPCRT4_FreeHeader(hdr); + HeapFree(GetProcessHeap(), 0, msg); + HeapFree(GetProcessHeap(), 0, auth_data); + + if (status != RPC_S_OK) { + WARN("processing packet failed with error %u\n", status); + break; + } } +exit: RPCRT4_DestroyConnection(conn); return 0; } @@ -449,27 +664,23 @@ static DWORD CALLBACK RPCRT4_server_thread(LPVOID the_arg) /* start waiting */ res = cps->ops->wait_for_new_connection(cps, count, objs); - if (res == -1) - break; - else if (res == 0) + + if (res == -1 || (res == 0 && !std_listen)) { - if (!std_listen) - { + /* cleanup */ + cps->ops->free_wait_array(cps, objs); + EnterCriticalSection(&cps->cs); + for (conn = cps->conn; conn; conn = conn->Next) + RPCRT4_CloseConnection(conn); + LeaveCriticalSection(&cps->cs); + + if (res == 0 && !std_listen) SetEvent(cps->server_ready_event); - break; - } - set_ready_event = TRUE; + break; } + else if (res == 0) + set_ready_event = TRUE; } - cps->ops->free_wait_array(cps, objs); - EnterCriticalSection(&cps->cs); - /* close connections */ - conn = cps->conn; - while (conn) { - RPCRT4_CloseConnection(conn); - conn = conn->Next; - } - LeaveCriticalSection(&cps->cs); return 0; } @@ -563,6 +774,10 @@ static void RPCRT4_stop_listen(BOOL auto_listen) LIST_FOR_EACH_ENTRY(cps, &protseqs, RpcServerProtseq, entry) RPCRT4_sync_with_server_thread(cps); + EnterCriticalSection(&listen_cs); + if (listen_done_event) SetEvent( listen_done_event ); + listen_done_event = 0; + LeaveCriticalSection(&listen_cs); return; } assert(listen_count >= 0); @@ -570,11 +785,32 @@ static void RPCRT4_stop_listen(BOOL auto_listen) LeaveCriticalSection(&listen_cs); } -static RPC_STATUS RPCRT4_use_protseq(RpcServerProtseq* ps, LPSTR endpoint) +static BOOL RPCRT4_protseq_is_endpoint_registered(RpcServerProtseq *protseq, const char *endpoint) +{ + RpcConnection *conn; + EnterCriticalSection(&protseq->cs); + for (conn = protseq->conn; conn; conn = conn->Next) + { + if (!endpoint || !strcmp(endpoint, conn->Endpoint)) + break; + } + LeaveCriticalSection(&protseq->cs); + return (conn != NULL); +} + +static RPC_STATUS RPCRT4_use_protseq(RpcServerProtseq* ps, const char *endpoint) { RPC_STATUS status; - status = ps->ops->open_endpoint(ps, endpoint); + EnterCriticalSection(&ps->cs); + + if (RPCRT4_protseq_is_endpoint_registered(ps, endpoint)) + status = RPC_S_OK; + else + status = ps->ops->open_endpoint(ps, endpoint); + + LeaveCriticalSection(&ps->cs); + if (status != RPC_S_OK) return status; @@ -608,11 +844,8 @@ RPC_STATUS WINAPI RpcServerInqBindings( RPC_BINDING_VECTOR** BindingVector ) count = 0; LIST_FOR_EACH_ENTRY(ps, &protseqs, RpcServerProtseq, entry) { EnterCriticalSection(&ps->cs); - conn = ps->conn; - while (conn) { + for (conn = ps->conn; conn; conn = conn->Next) count++; - conn = conn->Next; - } LeaveCriticalSection(&ps->cs); } if (count) { @@ -624,12 +857,10 @@ RPC_STATUS WINAPI RpcServerInqBindings( RPC_BINDING_VECTOR** BindingVector ) count = 0; LIST_FOR_EACH_ENTRY(ps, &protseqs, RpcServerProtseq, entry) { EnterCriticalSection(&ps->cs); - conn = ps->conn; - while (conn) { + for (conn = ps->conn; conn; conn = conn->Next) { RPCRT4_MakeBinding((RpcBinding**)&(*BindingVector)->BindingH[count], conn); count++; - conn = conn->Next; } LeaveCriticalSection(&ps->cs); } @@ -681,7 +912,7 @@ RPC_STATUS WINAPI RpcServerUseProtseqEpW( RPC_WSTR Protseq, UINT MaxCalls, RPC_W * * Must be called with server_cs held. */ -static RPC_STATUS alloc_serverprotoseq(UINT MaxCalls, char *Protseq, RpcServerProtseq **ps) +static RPC_STATUS alloc_serverprotoseq(UINT MaxCalls, const char *Protseq, RpcServerProtseq **ps) { const struct protseq_ops *ops = rpcrt4_get_protseq_ops(Protseq); @@ -695,7 +926,7 @@ static RPC_STATUS alloc_serverprotoseq(UINT MaxCalls, char *Protseq, RpcServerPr if (!*ps) return RPC_S_OUT_OF_RESOURCES; (*ps)->MaxCalls = MaxCalls; - (*ps)->Protseq = Protseq; + (*ps)->Protseq = RPCRT4_strdupA(Protseq); (*ps)->ops = ops; (*ps)->MaxCalls = 0; (*ps)->conn = NULL; @@ -711,8 +942,19 @@ static RPC_STATUS alloc_serverprotoseq(UINT MaxCalls, char *Protseq, RpcServerPr 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, char *Protseq, RpcServerProtseq **ps) +static RPC_STATUS RPCRT4_get_or_create_serverprotseq(UINT MaxCalls, const char *Protseq, RpcServerProtseq **ps) { RPC_STATUS status; RpcServerProtseq *cps; @@ -741,19 +983,18 @@ static RPC_STATUS RPCRT4_get_or_create_serverprotseq(UINT MaxCalls, char *Protse RPC_STATUS WINAPI RpcServerUseProtseqEpExA( RPC_CSTR Protseq, UINT MaxCalls, RPC_CSTR Endpoint, LPVOID SecurityDescriptor, 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(szps), MaxCalls, - debugstr_a(szep), SecurityDescriptor, + TRACE("(%s,%u,%s,%p,{%u,%u,%u})\n", debugstr_a((const char *)Protseq), + MaxCalls, debugstr_a((const char *)Endpoint), SecurityDescriptor, lpPolicy->Length, lpPolicy->EndpointFlags, lpPolicy->NICFlags ); - status = RPCRT4_get_or_create_serverprotseq(MaxCalls, RPCRT4_strdupA(szps), &ps); + status = RPCRT4_get_or_create_serverprotseq(MaxCalls, (const char *)Protseq, &ps); if (status != RPC_S_OK) return status; - return RPCRT4_use_protseq(ps, szep); + return RPCRT4_use_protseq(ps, (const char *)Endpoint); } /*********************************************************************** @@ -764,13 +1005,16 @@ RPC_STATUS WINAPI RpcServerUseProtseqEpExW( RPC_WSTR Protseq, UINT MaxCalls, RPC { 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 ); - status = RPCRT4_get_or_create_serverprotseq(MaxCalls, RPCRT4_strdupWtoA(Protseq), &ps); + ProtseqA = RPCRT4_strdupWtoA(Protseq); + status = RPCRT4_get_or_create_serverprotseq(MaxCalls, ProtseqA, &ps); + RPCRT4_strfree(ProtseqA); if (status != RPC_S_OK) return status; @@ -785,8 +1029,16 @@ RPC_STATUS WINAPI RpcServerUseProtseqEpExW( RPC_WSTR Protseq, UINT MaxCalls, RPC */ RPC_STATUS WINAPI RpcServerUseProtseqA(RPC_CSTR Protseq, unsigned int MaxCalls, void *SecurityDescriptor) { + RPC_STATUS status; + RpcServerProtseq* ps; + TRACE("(Protseq == %s, MaxCalls == %d, SecurityDescriptor == ^%p)\n", debugstr_a((char*)Protseq), MaxCalls, SecurityDescriptor); - return RpcServerUseProtseqEpA(Protseq, MaxCalls, NULL, SecurityDescriptor); + + status = RPCRT4_get_or_create_serverprotseq(MaxCalls, (const char *)Protseq, &ps); + if (status != RPC_S_OK) + return status; + + return RPCRT4_use_protseq(ps, NULL); } /*********************************************************************** @@ -794,8 +1046,36 @@ RPC_STATUS WINAPI RpcServerUseProtseqA(RPC_CSTR Protseq, unsigned int MaxCalls, */ RPC_STATUS WINAPI RpcServerUseProtseqW(RPC_WSTR Protseq, unsigned int MaxCalls, void *SecurityDescriptor) { + RPC_STATUS status; + RpcServerProtseq* ps; + LPSTR ProtseqA; + TRACE("Protseq == %s, MaxCalls == %d, SecurityDescriptor == ^%p)\n", debugstr_w(Protseq), MaxCalls, SecurityDescriptor); - return RpcServerUseProtseqEpW(Protseq, MaxCalls, NULL, SecurityDescriptor); + + ProtseqA = RPCRT4_strdupWtoA(Protseq); + status = RPCRT4_get_or_create_serverprotseq(MaxCalls, ProtseqA, &ps); + RPCRT4_strfree(ProtseqA); + if (status != RPC_S_OK) + return status; + + return RPCRT4_use_protseq(ps, NULL); +} + +void RPCRT4_destroy_all_protseqs(void) +{ + RpcServerProtseq *cps, *cursor2; + + if (listen_count != 0) + std_listen = FALSE; + + EnterCriticalSection(&server_cs); + LIST_FOR_EACH_ENTRY_SAFE(cps, cursor2, &protseqs, RpcServerProtseq, entry) + { + if (listen_count != 0) + RPCRT4_sync_with_server_thread(cps); + destroy_serverprotoseq(cps); + } + LeaveCriticalSection(&server_cs); } /*********************************************************************** @@ -823,7 +1103,7 @@ RPC_STATUS WINAPI RpcServerRegisterIfEx( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid RPC_STATUS WINAPI RpcServerRegisterIf2( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, RPC_MGR_EPV* MgrEpv, UINT Flags, UINT MaxCalls, UINT MaxRpcSize, RPC_IF_CALLBACK_FN* IfCallbackFn ) { - PRPC_SERVER_INTERFACE If = (PRPC_SERVER_INTERFACE)IfSpec; + PRPC_SERVER_INTERFACE If = IfSpec; RpcServerInterface* sif; unsigned int i; @@ -876,7 +1156,7 @@ RPC_STATUS WINAPI RpcServerRegisterIf2( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, */ RPC_STATUS WINAPI RpcServerUnregisterIf( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, UINT WaitForCallsToComplete ) { - PRPC_SERVER_INTERFACE If = (PRPC_SERVER_INTERFACE)IfSpec; + PRPC_SERVER_INTERFACE If = IfSpec; HANDLE event = NULL; BOOL found = FALSE; BOOL completed = TRUE; @@ -944,7 +1224,7 @@ RPC_STATUS WINAPI RpcServerUnregisterIfEx( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUu * RPC_S_INVALID_OBJECT The provided object (nil) is not valid * RPC_S_ALREADY_REGISTERED The provided object is already registered * - * Maps "Object" UUIDs to "Type" UUID's. Passing the nil UUID as the type + * Maps "Object" UUIDs to "Type" UUIDs. Passing the nil UUID as the type * resets the mapping for the specified object UUID to nil (the default). * The nil object is always associated with the nil type and cannot be * reassigned. Servers can support multiple implementations on the same @@ -996,15 +1276,114 @@ RPC_STATUS WINAPI RpcObjectSetType( UUID* ObjUuid, UUID* TypeUuid ) return RPC_S_OK; } +struct rpc_server_registered_auth_info +{ + struct list entry; + TimeStamp exp; + CredHandle cred; + ULONG max_token; + USHORT auth_type; +}; + +RPC_STATUS RPCRT4_ServerGetRegisteredAuthInfo( + USHORT auth_type, CredHandle *cred, TimeStamp *exp, ULONG *max_token) +{ + RPC_STATUS status = RPC_S_UNKNOWN_AUTHN_SERVICE; + struct rpc_server_registered_auth_info *auth_info; + + EnterCriticalSection(&server_auth_info_cs); + LIST_FOR_EACH_ENTRY(auth_info, &server_registered_auth_info, struct rpc_server_registered_auth_info, entry) + { + if (auth_info->auth_type == auth_type) + { + *cred = auth_info->cred; + *exp = auth_info->exp; + *max_token = auth_info->max_token; + status = RPC_S_OK; + break; + } + } + LeaveCriticalSection(&server_auth_info_cs); + + return status; +} + +void RPCRT4_ServerFreeAllRegisteredAuthInfo(void) +{ + struct rpc_server_registered_auth_info *auth_info, *cursor2; + + EnterCriticalSection(&server_auth_info_cs); + LIST_FOR_EACH_ENTRY_SAFE(auth_info, cursor2, &server_registered_auth_info, struct rpc_server_registered_auth_info, entry) + { + FreeCredentialsHandle(&auth_info->cred); + HeapFree(GetProcessHeap(), 0, auth_info); + } + LeaveCriticalSection(&server_auth_info_cs); +} + /*********************************************************************** * RpcServerRegisterAuthInfoA (RPCRT4.@) */ RPC_STATUS WINAPI RpcServerRegisterAuthInfoA( RPC_CSTR ServerPrincName, ULONG AuthnSvc, RPC_AUTH_KEY_RETRIEVAL_FN GetKeyFn, LPVOID Arg ) { - FIXME( "(%s,%u,%p,%p): stub\n", ServerPrincName, AuthnSvc, GetKeyFn, Arg ); - - return RPC_S_UNKNOWN_AUTHN_SERVICE; /* We don't know any authentication services */ + SECURITY_STATUS sec_status; + CredHandle cred; + TimeStamp exp; + ULONG package_count; + ULONG i; + PSecPkgInfoA packages; + ULONG max_token; + struct rpc_server_registered_auth_info *auth_info; + + TRACE("(%s,%u,%p,%p)\n", ServerPrincName, AuthnSvc, GetKeyFn, Arg); + + sec_status = EnumerateSecurityPackagesA(&package_count, &packages); + if (sec_status != SEC_E_OK) + { + ERR("EnumerateSecurityPackagesA failed with error 0x%08x\n", + sec_status); + return RPC_S_SEC_PKG_ERROR; + } + + for (i = 0; i < package_count; i++) + if (packages[i].wRPCID == AuthnSvc) + break; + + if (i == package_count) + { + WARN("unsupported AuthnSvc %u\n", AuthnSvc); + FreeContextBuffer(packages); + return RPC_S_UNKNOWN_AUTHN_SERVICE; + } + TRACE("found package %s for service %u\n", packages[i].Name, + AuthnSvc); + sec_status = AcquireCredentialsHandleA((SEC_CHAR *)ServerPrincName, + packages[i].Name, + SECPKG_CRED_INBOUND, NULL, NULL, + NULL, NULL, &cred, &exp); + max_token = packages[i].cbMaxToken; + FreeContextBuffer(packages); + if (sec_status != SEC_E_OK) + return RPC_S_SEC_PKG_ERROR; + + auth_info = HeapAlloc(GetProcessHeap(), 0, sizeof(*auth_info)); + if (!auth_info) + { + FreeCredentialsHandle(&cred); + return RPC_S_OUT_OF_RESOURCES; + } + + auth_info->exp = exp; + auth_info->cred = cred; + auth_info->max_token = max_token; + auth_info->auth_type = AuthnSvc; + + EnterCriticalSection(&server_auth_info_cs); + list_add_tail(&server_registered_auth_info, &auth_info->entry); + LeaveCriticalSection(&server_auth_info_cs); + + return RPC_S_OK; } /*********************************************************************** @@ -1013,9 +1392,63 @@ RPC_STATUS WINAPI RpcServerRegisterAuthInfoA( RPC_CSTR ServerPrincName, ULONG Au RPC_STATUS WINAPI RpcServerRegisterAuthInfoW( RPC_WSTR ServerPrincName, ULONG AuthnSvc, RPC_AUTH_KEY_RETRIEVAL_FN GetKeyFn, LPVOID Arg ) { - FIXME( "(%s,%u,%p,%p): stub\n", debugstr_w( ServerPrincName ), AuthnSvc, GetKeyFn, Arg ); - - return RPC_S_UNKNOWN_AUTHN_SERVICE; /* We don't know any authentication services */ + SECURITY_STATUS sec_status; + CredHandle cred; + TimeStamp exp; + ULONG package_count; + ULONG i; + PSecPkgInfoW packages; + ULONG max_token; + struct rpc_server_registered_auth_info *auth_info; + + TRACE("(%s,%u,%p,%p)\n", debugstr_w(ServerPrincName), AuthnSvc, GetKeyFn, Arg); + + sec_status = EnumerateSecurityPackagesW(&package_count, &packages); + if (sec_status != SEC_E_OK) + { + ERR("EnumerateSecurityPackagesW failed with error 0x%08x\n", + sec_status); + return RPC_S_SEC_PKG_ERROR; + } + + for (i = 0; i < package_count; i++) + if (packages[i].wRPCID == AuthnSvc) + break; + + if (i == package_count) + { + WARN("unsupported AuthnSvc %u\n", AuthnSvc); + FreeContextBuffer(packages); + return RPC_S_UNKNOWN_AUTHN_SERVICE; + } + TRACE("found package %s for service %u\n", debugstr_w(packages[i].Name), + AuthnSvc); + sec_status = AcquireCredentialsHandleW((SEC_WCHAR *)ServerPrincName, + packages[i].Name, + SECPKG_CRED_INBOUND, NULL, NULL, + NULL, NULL, &cred, &exp); + max_token = packages[i].cbMaxToken; + FreeContextBuffer(packages); + if (sec_status != SEC_E_OK) + return RPC_S_SEC_PKG_ERROR; + + auth_info = HeapAlloc(GetProcessHeap(), 0, sizeof(*auth_info)); + if (!auth_info) + { + FreeCredentialsHandle(&cred); + return RPC_S_OUT_OF_RESOURCES; + } + + auth_info->exp = exp; + auth_info->cred = cred; + auth_info->max_token = max_token; + auth_info->auth_type = AuthnSvc; + + EnterCriticalSection(&server_auth_info_cs); + list_add_tail(&server_registered_auth_info, &auth_info->entry); + LeaveCriticalSection(&server_auth_info_cs); + + return RPC_S_OK; } /*********************************************************************** @@ -1044,23 +1477,23 @@ RPC_STATUS WINAPI RpcMgmtWaitServerListen( void ) { RpcServerProtseq *cps; + TRACE("()\n"); + EnterCriticalSection(&listen_cs); if (!std_listen) { LeaveCriticalSection(&listen_cs); return RPC_S_NOT_LISTENING; } - do { - LeaveCriticalSection(&listen_cs); + LeaveCriticalSection(&listen_cs); LIST_FOR_EACH_ENTRY(cps, &protseqs, RpcServerProtseq, entry) WaitForSingleObject(cps->server_ready_event, INFINITE); - + EnterCriticalSection(&listen_cs); } while (!std_listen); LeaveCriticalSection(&listen_cs); - return RPC_S_OK; } @@ -1183,6 +1616,15 @@ RPC_STATUS WINAPI RpcMgmtIsServerListening(RPC_BINDING_HANDLE Binding) return RPC_S_INVALID_BINDING; } +/*********************************************************************** + * RpcMgmtSetAuthorizationFn (RPCRT4.@) + */ +RPC_STATUS WINAPI RpcMgmtSetAuthorizationFn(RPC_MGMT_AUTHORIZATION_FN fn) +{ + FIXME("(%p): stub\n", fn); + return RPC_S_OK; +} + /*********************************************************************** * RpcMgmtSetServerStackSize (RPCRT4.@) */ diff --git a/reactos/dll/win32/rpcrt4/rpc_server.h b/reactos/dll/win32/rpcrt4/rpc_server.h index ffd5b016e4b..a7f95395465 100644 --- a/reactos/dll/win32/rpcrt4/rpc_server.h +++ b/reactos/dll/win32/rpcrt4/rpc_server.h @@ -56,7 +56,7 @@ struct protseq_ops * 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, LPSTR endpoint); + RPC_STATUS (*open_endpoint)(RpcServerProtseq *protseq, const char *endpoint); }; typedef struct _RpcServerInterface @@ -76,7 +76,10 @@ typedef struct _RpcServerInterface BOOL Delete; /* delete when the last call finishes */ } RpcServerInterface; -void RPCRT4_new_client(RpcConnection* conn); -const struct protseq_ops *rpcrt4_get_protseq_ops(const char *protseq); +void RPCRT4_new_client(RpcConnection* conn) DECLSPEC_HIDDEN; +const struct protseq_ops *rpcrt4_get_protseq_ops(const char *protseq) DECLSPEC_HIDDEN; + +void RPCRT4_destroy_all_protseqs(void) DECLSPEC_HIDDEN; +void RPCRT4_ServerFreeAllRegisteredAuthInfo(void) DECLSPEC_HIDDEN; #endif /* __WINE_RPC_SERVER_H */ diff --git a/reactos/dll/win32/rpcrt4/rpc_transport.c b/reactos/dll/win32/rpcrt4/rpc_transport.c index 92588bad087..4a8de65d9e8 100644 --- a/reactos/dll/win32/rpcrt4/rpc_transport.c +++ b/reactos/dll/win32/rpcrt4/rpc_transport.c @@ -40,6 +40,8 @@ # ifndef EAGAIN # define EAGAIN WSAEWOULDBLOCK # endif +# undef errno +# define errno WSAGetLastError() #else # include # ifdef HAVE_UNISTD_H @@ -97,8 +99,13 @@ # define SOL_TCP IPPROTO_TCP #endif +#define DEFAULT_NCACN_HTTP_TIMEOUT (60 * 1000) + WINE_DEFAULT_DEBUG_CHANNEL(rpc); +#undef ERR +#define ERR FIXME + static RPC_STATUS RPCRT4_SpawnConnection(RpcConnection** Connection, RpcConnection* OldConnection); /**** ncacn_np support ****/ @@ -107,7 +114,7 @@ typedef struct _RpcConnection_np { RpcConnection common; HANDLE pipe; - OVERLAPPED ovl[2]; + OVERLAPPED ovl; BOOL listening; } RpcConnection_np; @@ -131,13 +138,13 @@ static RPC_STATUS rpcrt4_conn_listen_pipe(RpcConnection_np *npc) npc->listening = TRUE; for (;;) { - if (ConnectNamedPipe(npc->pipe, &npc->ovl[0])) + if (ConnectNamedPipe(npc->pipe, &npc->ovl)) return RPC_S_OK; switch(GetLastError()) { case ERROR_PIPE_CONNECTED: - SetEvent(npc->ovl[0].hEvent); + SetEvent(npc->ovl.hEvent); return RPC_S_OK; case ERROR_IO_PENDING: /* will be completed in rpcrt4_protseq_np_wait_for_new_connection */ @@ -172,8 +179,7 @@ static RPC_STATUS rpcrt4_conn_create_pipe(RpcConnection *Connection, LPCSTR pnam } memset(&npc->ovl, 0, sizeof(npc->ovl)); - npc->ovl[0].hEvent = CreateEventW(NULL, TRUE, FALSE, NULL); - npc->ovl[1].hEvent = CreateEventW(NULL, TRUE, FALSE, NULL); + npc->ovl.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL); /* Note: we don't call ConnectNamedPipe here because it must be done in the * server thread as the thread must be alertable */ @@ -222,17 +228,18 @@ static RPC_STATUS rpcrt4_conn_open_pipe(RpcConnection *Connection, LPCSTR pname, ERR("connection to %s failed, error=%x\n", pname, err); return RPC_S_SERVER_TOO_BUSY; } - if (wait) ERR("Waiting for Pipe Instance\n"); - if (wait) { - if (!WaitNamedPipeA(pname, NMPWAIT_WAIT_FOREVER)) { - err = GetLastError(); - ERR("connection to %s failed, error=%x, wait %x\n", pname, err, wait); - return RPC_S_SERVER_UNAVAILABLE; - } - else - { - ERR("Pipe Instance Ready!!!!!!!!!!!!!!!!!!\n"); - } + if(wait) ERR("Waiting for pipe instance"); + if(wait) + { + if (!WaitNamedPipeA(pname, NMPWAIT_WAIT_FOREVER)) { + err = GetLastError(); + ERR("connection to %s failed, error=%x, wait %x\n", pname, err, wait); + return RPC_S_SERVER_UNAVAILABLE; + } + else + { + ERR("Pipe Instance Ready!!!!!!!!!!!!!!!!!!\n"); + } } } @@ -241,8 +248,7 @@ static RPC_STATUS rpcrt4_conn_open_pipe(RpcConnection *Connection, LPCSTR pname, /* pipe is connected; change to message-read mode. */ dwMode = PIPE_READMODE_MESSAGE; SetNamedPipeHandleState(pipe, &dwMode, NULL, NULL); - npc->ovl[0].hEvent = CreateEventW(NULL, TRUE, FALSE, NULL); - npc->ovl[1].hEvent = CreateEventW(NULL, TRUE, FALSE, NULL); + npc->ovl.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL); npc->pipe = pipe; return RPC_S_OK; @@ -269,7 +275,7 @@ static RPC_STATUS rpcrt4_ncalrpc_open(RpcConnection* Connection) return r; } -static RPC_STATUS rpcrt4_protseq_ncalrpc_open_endpoint(RpcServerProtseq* protseq, LPSTR endpoint) +static RPC_STATUS rpcrt4_protseq_ncalrpc_open_endpoint(RpcServerProtseq* protseq, const char *endpoint) { static const char prefix[] = "\\\\.\\pipe\\lrpc\\"; RPC_STATUS r; @@ -327,7 +333,7 @@ static RPC_STATUS rpcrt4_ncacn_np_open(RpcConnection* Connection) return r; } -static RPC_STATUS rpcrt4_protseq_ncacn_np_open_endpoint(RpcServerProtseq *protseq, LPSTR endpoint) +static RPC_STATUS rpcrt4_protseq_ncacn_np_open_endpoint(RpcServerProtseq *protseq, const char *endpoint) { static const char prefix[] = "\\\\."; RPC_STATUS r; @@ -370,8 +376,7 @@ static void rpcrt4_conn_np_handoff(RpcConnection_np *old_npc, RpcConnection_np * * to the child, then reopen the server binding to continue listening */ new_npc->pipe = old_npc->pipe; - new_npc->ovl[0] = old_npc->ovl[0]; - new_npc->ovl[1] = old_npc->ovl[1]; + new_npc->ovl = old_npc->ovl; old_npc->pipe = 0; memset(&old_npc->ovl, 0, sizeof(old_npc->ovl)); old_npc->listening = FALSE; @@ -418,21 +423,24 @@ static int rpcrt4_conn_np_read(RpcConnection *Connection, char *buf = buffer; BOOL ret = TRUE; unsigned int bytes_left = count; + OVERLAPPED ovl; + + ZeroMemory(&ovl, sizeof(ovl)); + ovl.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL); while (bytes_left) { DWORD bytes_read; - ret = ReadFile(npc->pipe, buf, bytes_left, &bytes_read, &npc->ovl[0]); - if ((!ret || !bytes_read) && (GetLastError() != ERROR_IO_PENDING)) + ret = ReadFile(npc->pipe, buf, bytes_left, &bytes_read, &ovl); + if ((!ret || !bytes_read) && (GetLastError() != ERROR_IO_PENDING)) break; - - ret = GetOverlappedResult(npc->pipe, &npc->ovl[0], &bytes_read, TRUE); + ret = GetOverlappedResult(npc->pipe, &ovl, &bytes_read, TRUE); if (!ret && (GetLastError() != ERROR_MORE_DATA)) break; - bytes_left -= bytes_read; buf += bytes_read; } + CloseHandle(ovl.hEvent); return ret ? count : -1; } @@ -443,18 +451,21 @@ static int rpcrt4_conn_np_write(RpcConnection *Connection, const char *buf = buffer; BOOL ret = TRUE; unsigned int bytes_left = count; + OVERLAPPED ovl; + + ZeroMemory(&ovl, sizeof(ovl)); + ovl.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL); while (bytes_left) { DWORD bytes_written; - ret = WriteFile(npc->pipe, buf, bytes_left, &bytes_written, &npc->ovl[1]); + ret = WriteFile(npc->pipe, buf, bytes_left, &bytes_written, &ovl); if ((!ret || !bytes_written) && (GetLastError() != ERROR_IO_PENDING)) break; - ret = GetOverlappedResult(npc->pipe, &npc->ovl[1], &bytes_written, TRUE); + ret = GetOverlappedResult(npc->pipe, &ovl, &bytes_written, TRUE); if (!ret && (GetLastError() != ERROR_MORE_DATA)) break; - bytes_left -= bytes_written; buf += bytes_written; } @@ -469,13 +480,9 @@ static int rpcrt4_conn_np_close(RpcConnection *Connection) CloseHandle(npc->pipe); npc->pipe = 0; } - if (npc->ovl[0].hEvent) { - CloseHandle(npc->ovl[0].hEvent); - npc->ovl[0].hEvent = 0; - } - if (npc->ovl[1].hEvent) { - CloseHandle(npc->ovl[1].hEvent); - npc->ovl[1].hEvent = 0; + if (npc->ovl.hEvent) { + CloseHandle(npc->ovl.hEvent); + npc->ovl.hEvent = 0; } return 0; } @@ -604,6 +611,48 @@ static RPC_STATUS rpcrt4_ncacn_np_parse_top_of_tower(const unsigned char *tower_ return RPC_S_OK; } +static RPC_STATUS rpcrt4_conn_np_impersonate_client(RpcConnection *conn) +{ + RpcConnection_np *npc = (RpcConnection_np *)conn; + BOOL ret; + + TRACE("(%p)\n", conn); + + if (conn->AuthInfo && SecIsValidHandle(&conn->ctx)) + return RPCRT4_default_impersonate_client(conn); + + ret = ImpersonateNamedPipeClient(npc->pipe); + if (!ret) + { + DWORD error = GetLastError(); + WARN("ImpersonateNamedPipeClient failed with error %u\n", error); + switch (error) + { + case ERROR_CANNOT_IMPERSONATE: + return RPC_S_NO_CONTEXT_AVAILABLE; + } + } + return RPC_S_OK; +} + +static RPC_STATUS rpcrt4_conn_np_revert_to_self(RpcConnection *conn) +{ + BOOL ret; + + TRACE("(%p)\n", conn); + + if (conn->AuthInfo && SecIsValidHandle(&conn->ctx)) + return RPCRT4_default_revert_to_self(conn); + + ret = RevertToSelf(); + if (!ret) + { + WARN("RevertToSelf failed with error %u\n", GetLastError()); + return RPC_S_NO_CONTEXT_AVAILABLE; + } + return RPC_S_OK; +} + typedef struct _RpcServerProtseq_np { RpcServerProtseq common; @@ -637,7 +686,7 @@ static void *rpcrt4_protseq_np_get_wait_array(RpcServerProtseq *protseq, void *p conn = CONTAINING_RECORD(protseq->conn, RpcConnection_np, common); while (conn) { rpcrt4_conn_listen_pipe(conn); - if (conn->ovl[0].hEvent) + if (conn->ovl.hEvent) (*count)++; conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_np, common); } @@ -658,7 +707,7 @@ static void *rpcrt4_protseq_np_get_wait_array(RpcServerProtseq *protseq, void *p *count = 1; conn = CONTAINING_RECORD(protseq->conn, RpcConnection_np, common); while (conn) { - if ((objs[*count] = conn->ovl[0].hEvent)) + if ((objs[*count] = conn->ovl.hEvent)) (*count)++; conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_np, common); } @@ -705,7 +754,7 @@ static int rpcrt4_protseq_np_wait_for_new_connection(RpcServerProtseq *protseq, EnterCriticalSection(&protseq->cs); conn = CONTAINING_RECORD(protseq->conn, RpcConnection_np, common); while (conn) { - if (b_handle == conn->ovl[0].hEvent) break; + if (b_handle == conn->ovl.hEvent) break; conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_np, common); } cconn = NULL; @@ -787,6 +836,65 @@ static RPC_STATUS rpcrt4_ncalrpc_parse_top_of_tower(const unsigned char *tower_d return RPC_S_OK; } +static BOOL rpcrt4_ncalrpc_is_authorized(RpcConnection *conn) +{ + return FALSE; +} + +static RPC_STATUS rpcrt4_ncalrpc_authorize(RpcConnection *conn, BOOL first_time, + unsigned char *in_buffer, + unsigned int in_size, + unsigned char *out_buffer, + unsigned int *out_size) +{ + /* since this protocol is local to the machine there is no need to + * authenticate the caller */ + *out_size = 0; + return RPC_S_OK; +} + +static RPC_STATUS rpcrt4_ncalrpc_secure_packet(RpcConnection *conn, + enum secure_packet_direction dir, + RpcPktHdr *hdr, unsigned int hdr_size, + unsigned char *stub_data, unsigned int stub_data_size, + RpcAuthVerifier *auth_hdr, + unsigned char *auth_value, unsigned int auth_value_size) +{ + /* since this protocol is local to the machine there is no need to secure + * the packet */ + return RPC_S_OK; +} + +static RPC_STATUS rpcrt4_ncalrpc_inquire_auth_client( + RpcConnection *conn, RPC_AUTHZ_HANDLE *privs, RPC_WSTR *server_princ_name, + ULONG *authn_level, ULONG *authn_svc, ULONG *authz_svc, ULONG flags) +{ + TRACE("(%p, %p, %p, %p, %p, %p, 0x%x)\n", conn, privs, + server_princ_name, authn_level, authn_svc, authz_svc, flags); + + if (privs) + { + FIXME("privs not implemented\n"); + *privs = NULL; + } + if (server_princ_name) + { + FIXME("server_princ_name not implemented\n"); + *server_princ_name = NULL; + } + if (authn_level) *authn_level = RPC_C_AUTHN_LEVEL_PKT_PRIVACY; + if (authn_svc) *authn_svc = RPC_C_AUTHN_WINNT; + if (authz_svc) + { + FIXME("authorization service not implemented\n"); + *authz_svc = RPC_C_AUTHZ_NONE; + } + if (flags) + FIXME("flags 0x%x not implemented\n", flags); + + return RPC_S_OK; +} + /**** ncacn_ip_tcp support ****/ static size_t rpcrt4_ip_tcp_get_top_of_tower(unsigned char *tower_data, @@ -1176,7 +1284,7 @@ static RPC_STATUS rpcrt4_ncacn_ip_tcp_open(RpcConnection* Connection) return RPC_S_SERVER_UNAVAILABLE; } -static RPC_STATUS rpcrt4_protseq_ncacn_ip_tcp_open_endpoint(RpcServerProtseq *protseq, LPSTR endpoint) +static RPC_STATUS rpcrt4_protseq_ncacn_ip_tcp_open_endpoint(RpcServerProtseq *protseq, const char *endpoint) { RPC_STATUS status = RPC_S_CANT_CREATE_ENDPOINT; int sock; @@ -1742,6 +1850,945 @@ static RPC_STATUS rpcrt4_ncacn_ip_tcp_parse_top_of_tower(const unsigned char *to endpoint); } +/**** ncacn_http support ****/ + +/* 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) : ""); + 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); +} + static const struct connection_ops conn_protseq_list[] = { { "ncacn_np", { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_SMB }, @@ -1755,6 +2802,13 @@ static const struct connection_ops conn_protseq_list[] = { rpcrt4_conn_np_wait_for_incoming_data, rpcrt4_ncacn_np_get_top_of_tower, rpcrt4_ncacn_np_parse_top_of_tower, + NULL, + RPCRT4_default_is_authorized, + RPCRT4_default_authorize, + RPCRT4_default_secure_packet, + rpcrt4_conn_np_impersonate_client, + rpcrt4_conn_np_revert_to_self, + RPCRT4_default_inquire_auth_client, }, { "ncalrpc", { EPM_PROTOCOL_NCALRPC, EPM_PROTOCOL_PIPE }, @@ -1768,6 +2822,13 @@ static const struct connection_ops conn_protseq_list[] = { rpcrt4_conn_np_wait_for_incoming_data, rpcrt4_ncalrpc_get_top_of_tower, rpcrt4_ncalrpc_parse_top_of_tower, + NULL, + rpcrt4_ncalrpc_is_authorized, + rpcrt4_ncalrpc_authorize, + rpcrt4_ncalrpc_secure_packet, + rpcrt4_conn_np_impersonate_client, + rpcrt4_conn_np_revert_to_self, + rpcrt4_ncalrpc_inquire_auth_client, }, { "ncacn_ip_tcp", { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_TCP }, @@ -1781,8 +2842,34 @@ static const struct connection_ops conn_protseq_list[] = { rpcrt4_conn_tcp_wait_for_incoming_data, rpcrt4_ncacn_ip_tcp_get_top_of_tower, rpcrt4_ncacn_ip_tcp_parse_top_of_tower, - } - + NULL, + RPCRT4_default_is_authorized, + RPCRT4_default_authorize, + RPCRT4_default_secure_packet, + RPCRT4_default_impersonate_client, + RPCRT4_default_revert_to_self, + RPCRT4_default_inquire_auth_client, + }, + { "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, + RPCRT4_default_is_authorized, + RPCRT4_default_authorize, + RPCRT4_default_secure_packet, + RPCRT4_default_impersonate_client, + RPCRT4_default_revert_to_self, + RPCRT4_default_inquire_auth_client, + }, }; @@ -1863,6 +2950,7 @@ RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server, LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint, LPCWSTR NetworkOptions, RpcAuthInfo* AuthInfo, RpcQualityOfService *QOS) { + static LONG next_id; const struct connection_ops *ops; RpcConnection* NewConnection; @@ -1890,6 +2978,7 @@ RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server, 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); @@ -2060,3 +3149,104 @@ RPC_STATUS WINAPI RpcNetworkIsProtseqValidA(RPC_CSTR protseq) } return RPC_S_OUT_OF_MEMORY; } + +/*********************************************************************** + * RpcProtseqVectorFreeA (RPCRT4.@) + */ +RPC_STATUS WINAPI RpcProtseqVectorFreeA(RPC_PROTSEQ_VECTORA **protseqs) +{ + TRACE("(%p)\n", protseqs); + + if (*protseqs) + { + int i; + for (i = 0; i < (*protseqs)->Count; i++) + HeapFree(GetProcessHeap(), 0, (*protseqs)->Protseq[i]); + HeapFree(GetProcessHeap(), 0, *protseqs); + *protseqs = NULL; + } + return RPC_S_OK; +} + +/*********************************************************************** + * RpcProtseqVectorFreeW (RPCRT4.@) + */ +RPC_STATUS WINAPI RpcProtseqVectorFreeW(RPC_PROTSEQ_VECTORW **protseqs) +{ + TRACE("(%p)\n", protseqs); + + if (*protseqs) + { + int i; + for (i = 0; i < (*protseqs)->Count; i++) + HeapFree(GetProcessHeap(), 0, (*protseqs)->Protseq[i]); + HeapFree(GetProcessHeap(), 0, *protseqs); + *protseqs = NULL; + } + return RPC_S_OK; +} + +/*********************************************************************** + * RpcNetworkInqProtseqsW (RPCRT4.@) + */ +RPC_STATUS WINAPI RpcNetworkInqProtseqsW( RPC_PROTSEQ_VECTORW** protseqs ) +{ + RPC_PROTSEQ_VECTORW *pvector; + int i = 0; + RPC_STATUS status = RPC_S_OUT_OF_MEMORY; + + TRACE("(%p)\n", protseqs); + + *protseqs = HeapAlloc(GetProcessHeap(), 0, sizeof(RPC_PROTSEQ_VECTORW)+(sizeof(unsigned short*)*ARRAYSIZE(protseq_list))); + if (!*protseqs) + goto end; + pvector = *protseqs; + pvector->Count = 0; + for (i = 0; i < ARRAYSIZE(protseq_list); i++) + { + pvector->Protseq[i] = HeapAlloc(GetProcessHeap(), 0, (strlen(protseq_list[i].name)+1)*sizeof(unsigned short)); + if (pvector->Protseq[i] == NULL) + goto end; + MultiByteToWideChar(CP_ACP, 0, (CHAR*)protseq_list[i].name, -1, + (WCHAR*)pvector->Protseq[i], strlen(protseq_list[i].name) + 1); + pvector->Count++; + } + status = RPC_S_OK; + +end: + if (status != RPC_S_OK) + RpcProtseqVectorFreeW(protseqs); + return status; +} + +/*********************************************************************** + * RpcNetworkInqProtseqsA (RPCRT4.@) + */ +RPC_STATUS WINAPI RpcNetworkInqProtseqsA(RPC_PROTSEQ_VECTORA** protseqs) +{ + RPC_PROTSEQ_VECTORA *pvector; + int i = 0; + RPC_STATUS status = RPC_S_OUT_OF_MEMORY; + + TRACE("(%p)\n", protseqs); + + *protseqs = HeapAlloc(GetProcessHeap(), 0, sizeof(RPC_PROTSEQ_VECTORW)+(sizeof(unsigned char*)*ARRAYSIZE(protseq_list))); + if (!*protseqs) + goto end; + pvector = *protseqs; + pvector->Count = 0; + for (i = 0; i < ARRAYSIZE(protseq_list); i++) + { + pvector->Protseq[i] = HeapAlloc(GetProcessHeap(), 0, strlen(protseq_list[i].name)+1); + if (pvector->Protseq[i] == NULL) + goto end; + strcpy((char*)pvector->Protseq[i], protseq_list[i].name); + pvector->Count++; + } + status = RPC_S_OK; + +end: + if (status != RPC_S_OK) + RpcProtseqVectorFreeA(protseqs); + return status; +} diff --git a/reactos/dll/win32/rpcrt4/rpcrt4.rbuild b/reactos/dll/win32/rpcrt4/rpcrt4.rbuild index 10d83df2f6f..54841c607ef 100644 --- a/reactos/dll/win32/rpcrt4/rpcrt4.rbuild +++ b/reactos/dll/win32/rpcrt4/rpcrt4.rbuild @@ -16,6 +16,8 @@ user32 advapi32 secur32 + wininet + delayimp iphlpapi ws2_32 ntdll diff --git a/reactos/dll/win32/rpcrt4/rpcrt4.spec b/reactos/dll/win32/rpcrt4/rpcrt4.spec index f724a44df07..62bee47089e 100644 --- a/reactos/dll/win32/rpcrt4/rpcrt4.spec +++ b/reactos/dll/win32/rpcrt4/rpcrt4.spec @@ -1,5 +1,5 @@ @ stdcall CreateProxyFromTypeInfo(ptr ptr ptr ptr ptr) -@ stub CreateStubFromTypeInfo +@ stdcall CreateStubFromTypeInfo(ptr ptr ptr ptr) @ stdcall CStdStubBuffer_AddRef(ptr) @ stdcall CStdStubBuffer_Connect(ptr ptr) @ stdcall CStdStubBuffer_CountRefs(ptr) @@ -53,7 +53,7 @@ @ stub I_RpcIfInqTransferSyntaxes @ stub I_RpcLogEvent @ stdcall I_RpcMapWin32Status(long) -@ stdcall I_RpcNegotiateTransferSyntax(ptr) # wxp +@ stdcall I_RpcNegotiateTransferSyntax(ptr) @ stub I_RpcNsBindingSetEntryName @ stub I_RpcNsBindingSetEntryNameA @ stub I_RpcNsBindingSetEntryNameW @@ -116,8 +116,9 @@ @ stdcall NDRSContextUnmarshallEx(ptr ptr ptr) @ stub NDRcopy @ stdcall NdrAllocate(ptr long) -@ stub NdrAsyncClientCall +@ varargs NdrAsyncClientCall(ptr ptr) @ stub NdrAsyncServerCall +@ stdcall NdrAsyncStubCall(ptr ptr ptr ptr) @ stdcall NdrByteCountPointerBufferSize(ptr ptr ptr) @ stdcall NdrByteCountPointerFree(ptr ptr ptr) @ stdcall NdrByteCountPointerMarshall(ptr ptr ptr) @@ -126,7 +127,7 @@ @ stdcall NdrCStdStubBuffer_Release(ptr ptr) @ stdcall NdrClearOutParameters(ptr ptr ptr) @ varargs NdrClientCall2(ptr ptr) -@ varargs NdrClientCall(ptr ptr) NdrClientCall2 +@ varargs -arch=i386 NdrClientCall(ptr ptr) NdrClientCall2 @ stdcall NdrClientContextMarshall(ptr ptr long) @ stdcall NdrClientContextUnmarshall(ptr ptr ptr) @ stub NdrClientInitialize @@ -194,7 +195,7 @@ @ stdcall NdrFullPointerQueryPointer(ptr ptr long ptr) @ stdcall NdrFullPointerQueryRefId(ptr long long ptr) @ stdcall NdrFullPointerXlatFree(ptr) -@ stdcall NdrFullPointerXlatInit(long long) +@ stdcall NdrFullPointerXlatInit(long long) @ stdcall NdrGetBuffer(ptr long ptr) @ stub NdrGetDcomProtocolVersion @ stub NdrGetPartialBuffer @@ -226,7 +227,7 @@ @ stub NdrMesTypeAlignSize @ stdcall NdrMesTypeDecode2(ptr ptr ptr ptr ptr) @ stub NdrMesTypeDecode -@ stub NdrMesTypeEncode2 +@ stdcall NdrMesTypeEncode2(ptr ptr ptr ptr ptr) @ stub NdrMesTypeEncode @ stdcall NdrMesTypeFree2(ptr ptr ptr ptr ptr) @ stdcall NdrNonConformantStringBufferSize(ptr ptr ptr) @@ -272,7 +273,7 @@ @ stub NdrRpcSsEnableAllocate @ stdcall NdrSendReceive(ptr ptr) @ stdcall NdrServerCall2(ptr) -@ stub NdrServerCall +@ stdcall NdrServerCall(ptr) @ stdcall NdrServerContextMarshall(ptr ptr long) @ stdcall NdrServerContextNewMarshall(ptr ptr ptr ptr) # wxp @ stdcall NdrServerContextNewUnmarshall(ptr ptr) # wxp @@ -292,7 +293,7 @@ @ stdcall NdrSimpleTypeMarshall(ptr ptr long) @ stdcall NdrSimpleTypeUnmarshall(ptr ptr long) @ stdcall NdrStubCall2(ptr ptr ptr ptr) -@ stub NdrStubCall +@ stdcall NdrStubCall(ptr ptr ptr ptr) @ stdcall NdrStubForwardingFunction(ptr ptr ptr ptr) @ stdcall NdrStubGetBuffer(ptr ptr ptr) @ stdcall NdrStubInitialize(ptr ptr ptr ptr) @@ -340,10 +341,10 @@ @ stdcall RpcBindingFree(ptr) @ stdcall RpcBindingFromStringBindingA(str ptr) @ stdcall RpcBindingFromStringBindingW(wstr ptr) -@ stub RpcBindingInqAuthClientA -@ stub RpcBindingInqAuthClientExA -@ stub RpcBindingInqAuthClientExW -@ stub RpcBindingInqAuthClientW +@ stdcall RpcBindingInqAuthClientA(ptr ptr ptr ptr ptr ptr) +@ stdcall RpcBindingInqAuthClientExA(ptr ptr ptr ptr ptr ptr long) +@ stdcall RpcBindingInqAuthClientExW(ptr ptr ptr ptr ptr ptr long) +@ stdcall RpcBindingInqAuthClientW(ptr ptr ptr ptr ptr ptr) @ stdcall RpcBindingInqAuthInfoA(ptr ptr ptr ptr ptr ptr) @ stdcall RpcBindingInqAuthInfoExA(ptr ptr ptr ptr ptr ptr long ptr) @ stdcall RpcBindingInqAuthInfoExW(ptr ptr ptr ptr ptr ptr long ptr) @@ -370,7 +371,7 @@ @ stdcall RpcEpRegisterA(ptr ptr ptr str) @ stub RpcEpRegisterNoReplaceA @ stub RpcEpRegisterNoReplaceW -@ stub RpcEpRegisterW +@ stdcall RpcEpRegisterW(ptr ptr ptr wstr) @ stdcall RpcEpResolveBinding(ptr ptr) @ stdcall RpcEpUnregister(ptr ptr ptr) @ stub RpcErrorAddRecord # wxp @@ -401,15 +402,15 @@ @ stub RpcMgmtInqServerPrincNameW @ stdcall RpcMgmtInqStats(ptr ptr) @ stdcall RpcMgmtIsServerListening(ptr) -@ stub RpcMgmtSetAuthorizationFn +@ stdcall RpcMgmtSetAuthorizationFn(ptr) @ stdcall RpcMgmtSetCancelTimeout(long) @ stdcall RpcMgmtSetComTimeout(ptr long) @ stdcall RpcMgmtSetServerStackSize(long) @ stdcall RpcMgmtStatsVectorFree(ptr) @ stdcall RpcMgmtStopServerListening(ptr) @ stdcall RpcMgmtWaitServerListen() -@ stub RpcNetworkInqProtseqsA -@ stub RpcNetworkInqProtseqsW +@ stdcall RpcNetworkInqProtseqsA(ptr) +@ stdcall RpcNetworkInqProtseqsW(ptr) @ stdcall RpcNetworkIsProtseqValidA(ptr) @ stdcall RpcNetworkIsProtseqValidW(ptr) @ stub RpcNsBindingInqEntryNameA @@ -417,8 +418,8 @@ @ stub RpcObjectInqType @ stub RpcObjectSetInqFn @ stdcall RpcObjectSetType(ptr ptr) -@ stub RpcProtseqVectorFreeA -@ stub RpcProtseqVectorFreeW +@ stdcall RpcProtseqVectorFreeA(ptr) +@ stdcall RpcProtseqVectorFreeW(ptr) @ stdcall RpcRaiseException(long) @ stub RpcRegisterAsyncInfo @ stdcall RpcRevertToSelf() diff --git a/reactos/dll/win32/rpcrt4/rpcrt4_main.c b/reactos/dll/win32/rpcrt4/rpcrt4_main.c index 537a00537bc..2d7a754d626 100644 --- a/reactos/dll/win32/rpcrt4/rpcrt4_main.c +++ b/reactos/dll/win32/rpcrt4/rpcrt4_main.c @@ -43,6 +43,7 @@ #include "winuser.h" #include "winnt.h" #include "winternl.h" +#include "ntsecapi.h" #include "iptypes.h" #include "iphlpapi.h" #include "wine/unicode.h" @@ -53,6 +54,7 @@ #include "rpcproxy.h" #include "rpc_binding.h" +#include "rpc_server.h" #include "wine/debug.h" @@ -135,6 +137,8 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) break; case DLL_PROCESS_DETACH: + RPCRT4_destroy_all_protseqs(); + RPCRT4_ServerFreeAllRegisteredAuthInfo(); break; } @@ -280,6 +284,38 @@ RPC_STATUS WINAPI UuidCreateNil(UUID *Uuid) return RPC_S_OK; } +/************************************************************************* + * UuidCreate [RPCRT4.@] + * + * Creates a 128bit UUID. + * + * RETURNS + * + * 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) + */ +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; + + TRACE("%s\n", debugstr_guid(Uuid)); + + 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 @@ -299,7 +335,7 @@ static void RPC_UuidGetSystemTime(ULONGLONG *time) *time += TICKS_15_OCT_1582_TO_1601; } -/* Assume that a hardware address is at least 6 bytes long */ +/* Assume that a hardware address is at least 6 bytes long */ #define ADDRESS_BYTES_NEEDED 6 static RPC_STATUS RPC_UuidGetNodeAddress(BYTE *address) @@ -323,10 +359,7 @@ static RPC_STATUS RPC_UuidGetNodeAddress(BYTE *address) /* 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; - } - + RtlGenRandom(address, ADDRESS_BYTES_NEEDED); address[0] |= 0x01; status = RPC_S_UUID_LOCAL_ONLY; } @@ -336,7 +369,7 @@ static RPC_STATUS RPC_UuidGetNodeAddress(BYTE *address) } /************************************************************************* - * UuidCreate [RPCRT4.@] + * UuidCreateSequential [RPCRT4.@] * * Creates a 128bit UUID. * @@ -346,12 +379,12 @@ static RPC_STATUS RPC_UuidGetNodeAddress(BYTE *address) * RPC_S_UUID_LOCAL_ONLY if UUID is only locally unique. * * FIXME: No compensation for changes across reloading - * this dll or across reboots (e.g. clock going + * this dll or across reboots (e.g. clock going * backwards and swapped network cards). The RFC - * suggests using NVRAM for storing persistent + * suggests using NVRAM for storing persistent * values. */ -RPC_STATUS WINAPI UuidCreate(UUID *Uuid) +RPC_STATUS WINAPI UuidCreateSequential(UUID *Uuid) { static int initialised, count; @@ -399,7 +432,7 @@ RPC_STATUS WINAPI UuidCreate(UUID *Uuid) /* Pack the information into the UUID structure. */ - Uuid->Data1 = (unsigned long)(time & 0xffffffff); + Uuid->Data1 = (ULONG)(time & 0xffffffff); Uuid->Data2 = (unsigned short)((time >> 32) & 0xffff); Uuid->Data3 = (unsigned short)((time >> 48) & 0x0fff); @@ -409,13 +442,7 @@ RPC_STATUS WINAPI UuidCreate(UUID *Uuid) 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]; + memcpy(&Uuid->Data4[2], address, ADDRESS_BYTES_NEEDED); LeaveCriticalSection(&uuid_cs); @@ -424,22 +451,6 @@ RPC_STATUS WINAPI UuidCreate(UUID *Uuid) return status; } -/************************************************************************* - * UuidCreateSequential [RPCRT4.@] - * - * Creates a 128bit UUID. - * - * RETURNS - * - * RPC_S_OK if successful. - * RPC_S_UUID_LOCAL_ONLY if UUID is only locally unique. - * - */ -RPC_STATUS WINAPI UuidCreateSequential(UUID *Uuid) -{ - return UuidCreate(Uuid); -} - /************************************************************************* * UuidHash [RPCRT4.@] diff --git a/reactos/dll/win32/rpcrt4/version.rc b/reactos/dll/win32/rpcrt4/version.rc new file mode 100644 index 00000000000..f0422acd1e3 --- /dev/null +++ b/reactos/dll/win32/rpcrt4/version.rc @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2007 Alexandre Julliard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define WINE_FILEDESCRIPTION_STR "Wine rpcrt4" +#define WINE_FILENAME_STR "rpcrt4.dll" +#define WINE_FILEVERSION 5,1,2600,2180 +#define WINE_FILEVERSION_STR "5.1.2600.2180" +#define WINE_PRODUCTVERSION 5,1,2600,2180 +#define WINE_PRODUCTVERSION_STR "5.1.2600.2180" + +#include "wine/wine_common_ver.rc"