diff --git a/reactos/dll/win32/rpcrt4_new/cproxy.c b/reactos/dll/win32/rpcrt4_new/cproxy.c index b3101fdf526..6580bcf143c 100644 --- a/reactos/dll/win32/rpcrt4_new/cproxy.c +++ b/reactos/dll/win32/rpcrt4_new/cproxy.c @@ -1,450 +1,450 @@ -/* - * COM proxy implementation - * - * Copyright 2001 Ove Kåven, TransGaming Technologies - * - * 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 - * - * TODO: Handle non-i386 architectures - */ - -#include - -#define COBJMACROS - -#include "windef.h" -#include "winbase.h" -#include "winerror.h" - -#include "objbase.h" -#include "rpcproxy.h" - -#include "cpsf.h" -#include "ndr_misc.h" -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(ole); - -struct StublessThunk; - -/* I don't know what MS's std proxy structure looks like, - so this probably doesn't match, but that shouldn't matter */ -typedef struct { - const IRpcProxyBufferVtbl *lpVtbl; - LPVOID *PVtbl; - LONG RefCount; - const MIDL_STUBLESS_PROXY_INFO *stubless; - const IID* piid; - LPUNKNOWN pUnkOuter; - PCInterfaceName name; - LPPSFACTORYBUFFER pPSFactory; - LPRPCCHANNELBUFFER pChannel; - struct StublessThunk *thunks; -} StdProxyImpl; - -static const IRpcProxyBufferVtbl StdProxy_Vtbl; - -#define ICOM_THIS_MULTI(impl,field,iface) impl* const This=(impl*)((char*)(iface) - offsetof(impl,field)) - -/* How the Windows stubless proxy thunks work is explained at - * http://msdn.microsoft.com/library/en-us/dnmsj99/html/com0199.asp, - * but I'll use a slightly different method, to make life easier */ - -#if defined(__i386__) - -#include "pshpack1.h" - -struct StublessThunk { - BYTE push; - DWORD index; - BYTE call; - LONG handler; - BYTE ret; - WORD bytes; - BYTE pad[3]; -}; - -#include "poppack.h" - -/* adjust the stack size since we don't use Windows's method */ -#define STACK_ADJUST sizeof(DWORD) - -#define FILL_STUBLESS(x,idx,stk) \ - x->push = 0x68; /* pushl [immediate] */ \ - x->index = (idx); \ - x->call = 0xe8; /* call [near] */ \ - x->handler = (char*)ObjectStubless - (char*)&x->ret; \ - x->ret = 0xc2; /* ret [immediate] */ \ - x->bytes = stk; \ - x->pad[0] = 0x8d; /* leal (%esi),%esi */ \ - x->pad[1] = 0x76; \ - x->pad[2] = 0x00; - -static HRESULT WINAPI ObjectStubless(DWORD index) -{ - char *args = (char*)(&index + 2); - LPVOID iface = *(LPVOID*)args; - - ICOM_THIS_MULTI(StdProxyImpl,PVtbl,iface); - - PFORMAT_STRING fs = This->stubless->ProcFormatString + This->stubless->FormatStringOffset[index]; - unsigned bytes = *(const WORD*)(fs+8) - STACK_ADJUST; - TRACE("(%p)->(%d)([%d bytes]) ret=%08x\n", iface, index, bytes, *(DWORD*)(args+bytes)); - - return NdrClientCall2(This->stubless->pStubDesc, fs, args); -} - -#else /* __i386__ */ - -/* can't do that on this arch */ -struct StublessThunk { int dummy; }; -#define FILL_STUBLESS(x,idx,stk) \ - ERR("stubless proxies are not supported on this architecture\n"); -#define STACK_ADJUST 0 - -#endif /* __i386__ */ - -HRESULT WINAPI StdProxy_Construct(REFIID riid, - LPUNKNOWN pUnkOuter, - const ProxyFileInfo *ProxyInfo, - int Index, - LPPSFACTORYBUFFER pPSFactory, - LPRPCPROXYBUFFER *ppProxy, - LPVOID *ppvObj) -{ - StdProxyImpl *This; - const MIDL_STUBLESS_PROXY_INFO *stubless = NULL; - PCInterfaceName name = ProxyInfo->pNamesArray[Index]; - CInterfaceProxyVtbl *vtbl = ProxyInfo->pProxyVtblList[Index]; - - TRACE("(%p,%p,%p,%p,%p) %s\n", pUnkOuter, vtbl, pPSFactory, ppProxy, ppvObj, name); - - /* TableVersion = 2 means it is the stubless version of CInterfaceProxyVtbl */ - if (ProxyInfo->TableVersion > 1) { - stubless = *(const void **)vtbl; - vtbl = (CInterfaceProxyVtbl *)((const void **)vtbl + 1); - TRACE("stubless=%p\n", stubless); - } - - TRACE("iid=%s\n", debugstr_guid(vtbl->header.piid)); - TRACE("vtbl=%p\n", vtbl->Vtbl); - - if (!IsEqualGUID(vtbl->header.piid, riid)) { - ERR("IID mismatch during proxy creation\n"); - return RPC_E_UNEXPECTED; - } - - This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(StdProxyImpl)); - if (!This) return E_OUTOFMEMORY; - - if (stubless) { - CInterfaceStubVtbl *svtbl = ProxyInfo->pStubVtblList[Index]; - unsigned long i, count = svtbl->header.DispatchTableCount; - /* Maybe the original vtbl is just modified directly to point at - * ObjectStublessClientXXX thunks in real Windows, but I don't like it - */ - TRACE("stubless thunks: count=%ld\n", count); - This->thunks = HeapAlloc(GetProcessHeap(),0,sizeof(struct StublessThunk)*count); - This->PVtbl = HeapAlloc(GetProcessHeap(),0,sizeof(LPVOID)*count); - for (i=0; ithunks[i]; - if (vtbl->Vtbl[i] == (LPVOID)-1) { - PFORMAT_STRING fs = stubless->ProcFormatString + stubless->FormatStringOffset[i]; - unsigned bytes = *(const WORD*)(fs+8) - STACK_ADJUST; - TRACE("method %ld: stacksize=%d\n", i, bytes); - FILL_STUBLESS(thunk, i, bytes) - This->PVtbl[i] = thunk; - } - else { - memset(thunk, 0, sizeof(struct StublessThunk)); - This->PVtbl[i] = vtbl->Vtbl[i]; - } - } - } - else - This->PVtbl = vtbl->Vtbl; - - This->lpVtbl = &StdProxy_Vtbl; - /* one reference for the proxy */ - This->RefCount = 1; - This->stubless = stubless; - This->piid = vtbl->header.piid; - This->pUnkOuter = pUnkOuter; - This->name = name; - This->pPSFactory = pPSFactory; - This->pChannel = NULL; - *ppProxy = (LPRPCPROXYBUFFER)&This->lpVtbl; - *ppvObj = &This->PVtbl; - /* if there is no outer unknown then the caller will control the lifetime - * of the proxy object through the proxy buffer, so no need to increment the - * ref count of the proxy object */ - if (pUnkOuter) - IUnknown_AddRef((IUnknown *)*ppvObj); - IPSFactoryBuffer_AddRef(pPSFactory); - - return S_OK; -} - -static void WINAPI StdProxy_Destruct(LPRPCPROXYBUFFER iface) -{ - ICOM_THIS_MULTI(StdProxyImpl,lpVtbl,iface); - - if (This->pChannel) - IRpcProxyBuffer_Disconnect(iface); - - IPSFactoryBuffer_Release(This->pPSFactory); - if (This->thunks) { - HeapFree(GetProcessHeap(),0,This->PVtbl); - HeapFree(GetProcessHeap(),0,This->thunks); - } - HeapFree(GetProcessHeap(),0,This); -} - -static HRESULT WINAPI StdProxy_QueryInterface(LPRPCPROXYBUFFER iface, - REFIID riid, - LPVOID *obj) -{ - ICOM_THIS_MULTI(StdProxyImpl,lpVtbl,iface); - TRACE("(%p)->QueryInterface(%s,%p)\n",This,debugstr_guid(riid),obj); - - if (IsEqualGUID(&IID_IUnknown,riid) || - IsEqualGUID(This->piid,riid)) { - *obj = &This->PVtbl; - InterlockedIncrement(&This->RefCount); - return S_OK; - } - - if (IsEqualGUID(&IID_IRpcProxyBuffer,riid)) { - *obj = &This->lpVtbl; - InterlockedIncrement(&This->RefCount); - return S_OK; - } - - return E_NOINTERFACE; -} - -static ULONG WINAPI StdProxy_AddRef(LPRPCPROXYBUFFER iface) -{ - ICOM_THIS_MULTI(StdProxyImpl,lpVtbl,iface); - TRACE("(%p)->AddRef()\n",This); - - return InterlockedIncrement(&This->RefCount); -} - -static ULONG WINAPI StdProxy_Release(LPRPCPROXYBUFFER iface) -{ - ULONG refs; - ICOM_THIS_MULTI(StdProxyImpl,lpVtbl,iface); - TRACE("(%p)->Release()\n",This); - - refs = InterlockedDecrement(&This->RefCount); - if (!refs) - StdProxy_Destruct((LPRPCPROXYBUFFER)&This->lpVtbl); - return refs; -} - -static HRESULT WINAPI StdProxy_Connect(LPRPCPROXYBUFFER iface, - LPRPCCHANNELBUFFER pChannel) -{ - ICOM_THIS_MULTI(StdProxyImpl,lpVtbl,iface); - TRACE("(%p)->Connect(%p)\n",This,pChannel); - - This->pChannel = pChannel; - IRpcChannelBuffer_AddRef(pChannel); - return S_OK; -} - -static VOID WINAPI StdProxy_Disconnect(LPRPCPROXYBUFFER iface) -{ - ICOM_THIS_MULTI(StdProxyImpl,lpVtbl,iface); - TRACE("(%p)->Disconnect()\n",This); - - IRpcChannelBuffer_Release(This->pChannel); - This->pChannel = NULL; -} - -static const IRpcProxyBufferVtbl StdProxy_Vtbl = -{ - StdProxy_QueryInterface, - StdProxy_AddRef, - StdProxy_Release, - StdProxy_Connect, - StdProxy_Disconnect -}; - -static void StdProxy_GetChannel(LPVOID iface, - LPRPCCHANNELBUFFER *ppChannel) -{ - ICOM_THIS_MULTI(StdProxyImpl,PVtbl,iface); - TRACE("(%p)->GetChannel(%p) %s\n",This,ppChannel,This->name); - - *ppChannel = This->pChannel; -} - -static void StdProxy_GetIID(LPVOID iface, - const IID **ppiid) -{ - ICOM_THIS_MULTI(StdProxyImpl,PVtbl,iface); - TRACE("(%p)->GetIID(%p) %s\n",This,ppiid,This->name); - - *ppiid = This->piid; -} - -HRESULT WINAPI IUnknown_QueryInterface_Proxy(LPUNKNOWN iface, - REFIID riid, - LPVOID *ppvObj) -{ - ICOM_THIS_MULTI(StdProxyImpl,PVtbl,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); - 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); - TRACE("(%p)->Release() %s\n",This,This->name); - return IUnknown_Release(This->pUnkOuter); -} - -/*********************************************************************** - * NdrProxyInitialize [RPCRT4.@] - */ -void WINAPI NdrProxyInitialize(void *This, - PRPC_MESSAGE pRpcMsg, - PMIDL_STUB_MESSAGE pStubMsg, - PMIDL_STUB_DESC pStubDescriptor, - unsigned int ProcNum) -{ - TRACE("(%p,%p,%p,%p,%d)\n", This, pRpcMsg, pStubMsg, pStubDescriptor, ProcNum); - NdrClientInitializeNew(pRpcMsg, pStubMsg, pStubDescriptor, ProcNum); - StdProxy_GetChannel(This, &pStubMsg->pRpcChannelBuffer); - IRpcChannelBuffer_GetDestCtx(pStubMsg->pRpcChannelBuffer, - &pStubMsg->dwDestContext, - &pStubMsg->pvDestContext); - TRACE("channel=%p\n", pStubMsg->pRpcChannelBuffer); -} - -/*********************************************************************** - * NdrProxyGetBuffer [RPCRT4.@] - */ -void WINAPI NdrProxyGetBuffer(void *This, - PMIDL_STUB_MESSAGE pStubMsg) -{ - HRESULT hr; - const IID *riid = NULL; - - TRACE("(%p,%p)\n", This, pStubMsg); - pStubMsg->RpcMsg->BufferLength = pStubMsg->BufferLength; - pStubMsg->dwStubPhase = PROXY_GETBUFFER; - StdProxy_GetIID(This, &riid); - hr = IRpcChannelBuffer_GetBuffer(pStubMsg->pRpcChannelBuffer, - (RPCOLEMESSAGE*)pStubMsg->RpcMsg, - riid); - if (FAILED(hr)) - { - RpcRaiseException(hr); - return; - } - pStubMsg->BufferStart = pStubMsg->RpcMsg->Buffer; - pStubMsg->BufferEnd = pStubMsg->BufferStart + pStubMsg->BufferLength; - pStubMsg->Buffer = pStubMsg->BufferStart; - pStubMsg->dwStubPhase = PROXY_MARSHAL; -} - -/*********************************************************************** - * NdrProxySendReceive [RPCRT4.@] - */ -void WINAPI NdrProxySendReceive(void *This, - PMIDL_STUB_MESSAGE pStubMsg) -{ - ULONG Status = 0; - HRESULT hr; - - TRACE("(%p,%p)\n", This, pStubMsg); - - if (!pStubMsg->pRpcChannelBuffer) - { - WARN("Trying to use disconnected proxy %p\n", This); - RpcRaiseException(RPC_E_DISCONNECTED); - } - - pStubMsg->dwStubPhase = PROXY_SENDRECEIVE; - hr = IRpcChannelBuffer_SendReceive(pStubMsg->pRpcChannelBuffer, - (RPCOLEMESSAGE*)pStubMsg->RpcMsg, - &Status); - pStubMsg->dwStubPhase = PROXY_UNMARSHAL; - pStubMsg->BufferLength = pStubMsg->RpcMsg->BufferLength; - pStubMsg->BufferStart = pStubMsg->RpcMsg->Buffer; - pStubMsg->BufferEnd = pStubMsg->BufferStart + pStubMsg->BufferLength; - pStubMsg->Buffer = pStubMsg->BufferStart; - - /* raise exception if call failed */ - if (hr == RPC_S_CALL_FAILED) RpcRaiseException(*(DWORD*)pStubMsg->Buffer); - else if (FAILED(hr)) RpcRaiseException(hr); -} - -/*********************************************************************** - * NdrProxyFreeBuffer [RPCRT4.@] - */ -void WINAPI NdrProxyFreeBuffer(void *This, - PMIDL_STUB_MESSAGE pStubMsg) -{ - HRESULT hr; - - TRACE("(%p,%p)\n", This, pStubMsg); - hr = IRpcChannelBuffer_FreeBuffer(pStubMsg->pRpcChannelBuffer, - (RPCOLEMESSAGE*)pStubMsg->RpcMsg); -} - -/*********************************************************************** - * NdrProxyErrorHandler [RPCRT4.@] - */ -HRESULT WINAPI NdrProxyErrorHandler(DWORD dwExceptionCode) -{ - WARN("(0x%08x): a proxy call failed\n", dwExceptionCode); - - if (FAILED(dwExceptionCode)) - return dwExceptionCode; - else - return HRESULT_FROM_WIN32(dwExceptionCode); -} - -HRESULT WINAPI -CreateProxyFromTypeInfo( LPTYPEINFO pTypeInfo, LPUNKNOWN pUnkOuter, REFIID riid, - LPRPCPROXYBUFFER *ppProxy, LPVOID *ppv ) -{ - typedef INT (WINAPI *MessageBoxA)(HWND,LPCSTR,LPCSTR,UINT); - HMODULE hUser32 = LoadLibraryA("user32"); - MessageBoxA pMessageBoxA = (void *)GetProcAddress(hUser32, "MessageBoxA"); - - FIXME("%p %p %s %p %p\n", pTypeInfo, pUnkOuter, debugstr_guid(riid), ppProxy, ppv); - 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; -} +/* + * COM proxy implementation + * + * Copyright 2001 Ove Kåven, TransGaming Technologies + * + * 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 + * + * TODO: Handle non-i386 architectures + */ + +#include + +#define COBJMACROS + +#include "windef.h" +#include "winbase.h" +#include "winerror.h" + +#include "objbase.h" +#include "rpcproxy.h" + +#include "cpsf.h" +#include "ndr_misc.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(ole); + +struct StublessThunk; + +/* I don't know what MS's std proxy structure looks like, + so this probably doesn't match, but that shouldn't matter */ +typedef struct { + const IRpcProxyBufferVtbl *lpVtbl; + LPVOID *PVtbl; + LONG RefCount; + const MIDL_STUBLESS_PROXY_INFO *stubless; + const IID* piid; + LPUNKNOWN pUnkOuter; + PCInterfaceName name; + LPPSFACTORYBUFFER pPSFactory; + LPRPCCHANNELBUFFER pChannel; + struct StublessThunk *thunks; +} StdProxyImpl; + +static const IRpcProxyBufferVtbl StdProxy_Vtbl; + +#define ICOM_THIS_MULTI(impl,field,iface) impl* const This=(impl*)((char*)(iface) - offsetof(impl,field)) + +/* How the Windows stubless proxy thunks work is explained at + * http://msdn.microsoft.com/library/en-us/dnmsj99/html/com0199.asp, + * but I'll use a slightly different method, to make life easier */ + +#if defined(__i386__) + +#include "pshpack1.h" + +struct StublessThunk { + BYTE push; + DWORD index; + BYTE call; + LONG handler; + BYTE ret; + WORD bytes; + BYTE pad[3]; +}; + +#include "poppack.h" + +/* adjust the stack size since we don't use Windows's method */ +#define STACK_ADJUST sizeof(DWORD) + +#define FILL_STUBLESS(x,idx,stk) \ + x->push = 0x68; /* pushl [immediate] */ \ + x->index = (idx); \ + x->call = 0xe8; /* call [near] */ \ + x->handler = (char*)ObjectStubless - (char*)&x->ret; \ + x->ret = 0xc2; /* ret [immediate] */ \ + x->bytes = stk; \ + x->pad[0] = 0x8d; /* leal (%esi),%esi */ \ + x->pad[1] = 0x76; \ + x->pad[2] = 0x00; + +static HRESULT WINAPI ObjectStubless(DWORD index) +{ + char *args = (char*)(&index + 2); + LPVOID iface = *(LPVOID*)args; + + ICOM_THIS_MULTI(StdProxyImpl,PVtbl,iface); + + PFORMAT_STRING fs = This->stubless->ProcFormatString + This->stubless->FormatStringOffset[index]; + unsigned bytes = *(const WORD*)(fs+8) - STACK_ADJUST; + TRACE("(%p)->(%d)([%d bytes]) ret=%08x\n", iface, index, bytes, *(DWORD*)(args+bytes)); + + return NdrClientCall2(This->stubless->pStubDesc, fs, args); +} + +#else /* __i386__ */ + +/* can't do that on this arch */ +struct StublessThunk { int dummy; }; +#define FILL_STUBLESS(x,idx,stk) \ + ERR("stubless proxies are not supported on this architecture\n"); +#define STACK_ADJUST 0 + +#endif /* __i386__ */ + +HRESULT WINAPI StdProxy_Construct(REFIID riid, + LPUNKNOWN pUnkOuter, + const ProxyFileInfo *ProxyInfo, + int Index, + LPPSFACTORYBUFFER pPSFactory, + LPRPCPROXYBUFFER *ppProxy, + LPVOID *ppvObj) +{ + StdProxyImpl *This; + const MIDL_STUBLESS_PROXY_INFO *stubless = NULL; + PCInterfaceName name = ProxyInfo->pNamesArray[Index]; + CInterfaceProxyVtbl *vtbl = ProxyInfo->pProxyVtblList[Index]; + + TRACE("(%p,%p,%p,%p,%p) %s\n", pUnkOuter, vtbl, pPSFactory, ppProxy, ppvObj, name); + + /* TableVersion = 2 means it is the stubless version of CInterfaceProxyVtbl */ + if (ProxyInfo->TableVersion > 1) { + stubless = *(const void **)vtbl; + vtbl = (CInterfaceProxyVtbl *)((const void **)vtbl + 1); + TRACE("stubless=%p\n", stubless); + } + + TRACE("iid=%s\n", debugstr_guid(vtbl->header.piid)); + TRACE("vtbl=%p\n", vtbl->Vtbl); + + if (!IsEqualGUID(vtbl->header.piid, riid)) { + ERR("IID mismatch during proxy creation\n"); + return RPC_E_UNEXPECTED; + } + + This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(StdProxyImpl)); + if (!This) return E_OUTOFMEMORY; + + if (stubless) { + CInterfaceStubVtbl *svtbl = ProxyInfo->pStubVtblList[Index]; + unsigned long i, count = svtbl->header.DispatchTableCount; + /* Maybe the original vtbl is just modified directly to point at + * ObjectStublessClientXXX thunks in real Windows, but I don't like it + */ + TRACE("stubless thunks: count=%ld\n", count); + This->thunks = HeapAlloc(GetProcessHeap(),0,sizeof(struct StublessThunk)*count); + This->PVtbl = HeapAlloc(GetProcessHeap(),0,sizeof(LPVOID)*count); + for (i=0; ithunks[i]; + if (vtbl->Vtbl[i] == (LPVOID)-1) { + PFORMAT_STRING fs = stubless->ProcFormatString + stubless->FormatStringOffset[i]; + unsigned bytes = *(const WORD*)(fs+8) - STACK_ADJUST; + TRACE("method %ld: stacksize=%d\n", i, bytes); + FILL_STUBLESS(thunk, i, bytes) + This->PVtbl[i] = thunk; + } + else { + memset(thunk, 0, sizeof(struct StublessThunk)); + This->PVtbl[i] = vtbl->Vtbl[i]; + } + } + } + else + This->PVtbl = vtbl->Vtbl; + + This->lpVtbl = &StdProxy_Vtbl; + /* one reference for the proxy */ + This->RefCount = 1; + This->stubless = stubless; + This->piid = vtbl->header.piid; + This->pUnkOuter = pUnkOuter; + This->name = name; + This->pPSFactory = pPSFactory; + This->pChannel = NULL; + *ppProxy = (LPRPCPROXYBUFFER)&This->lpVtbl; + *ppvObj = &This->PVtbl; + /* if there is no outer unknown then the caller will control the lifetime + * of the proxy object through the proxy buffer, so no need to increment the + * ref count of the proxy object */ + if (pUnkOuter) + IUnknown_AddRef((IUnknown *)*ppvObj); + IPSFactoryBuffer_AddRef(pPSFactory); + + return S_OK; +} + +static void WINAPI StdProxy_Destruct(LPRPCPROXYBUFFER iface) +{ + ICOM_THIS_MULTI(StdProxyImpl,lpVtbl,iface); + + if (This->pChannel) + IRpcProxyBuffer_Disconnect(iface); + + IPSFactoryBuffer_Release(This->pPSFactory); + if (This->thunks) { + HeapFree(GetProcessHeap(),0,This->PVtbl); + HeapFree(GetProcessHeap(),0,This->thunks); + } + HeapFree(GetProcessHeap(),0,This); +} + +static HRESULT WINAPI StdProxy_QueryInterface(LPRPCPROXYBUFFER iface, + REFIID riid, + LPVOID *obj) +{ + ICOM_THIS_MULTI(StdProxyImpl,lpVtbl,iface); + TRACE("(%p)->QueryInterface(%s,%p)\n",This,debugstr_guid(riid),obj); + + if (IsEqualGUID(&IID_IUnknown,riid) || + IsEqualGUID(This->piid,riid)) { + *obj = &This->PVtbl; + InterlockedIncrement(&This->RefCount); + return S_OK; + } + + if (IsEqualGUID(&IID_IRpcProxyBuffer,riid)) { + *obj = &This->lpVtbl; + InterlockedIncrement(&This->RefCount); + return S_OK; + } + + return E_NOINTERFACE; +} + +static ULONG WINAPI StdProxy_AddRef(LPRPCPROXYBUFFER iface) +{ + ICOM_THIS_MULTI(StdProxyImpl,lpVtbl,iface); + TRACE("(%p)->AddRef()\n",This); + + return InterlockedIncrement(&This->RefCount); +} + +static ULONG WINAPI StdProxy_Release(LPRPCPROXYBUFFER iface) +{ + ULONG refs; + ICOM_THIS_MULTI(StdProxyImpl,lpVtbl,iface); + TRACE("(%p)->Release()\n",This); + + refs = InterlockedDecrement(&This->RefCount); + if (!refs) + StdProxy_Destruct((LPRPCPROXYBUFFER)&This->lpVtbl); + return refs; +} + +static HRESULT WINAPI StdProxy_Connect(LPRPCPROXYBUFFER iface, + LPRPCCHANNELBUFFER pChannel) +{ + ICOM_THIS_MULTI(StdProxyImpl,lpVtbl,iface); + TRACE("(%p)->Connect(%p)\n",This,pChannel); + + This->pChannel = pChannel; + IRpcChannelBuffer_AddRef(pChannel); + return S_OK; +} + +static VOID WINAPI StdProxy_Disconnect(LPRPCPROXYBUFFER iface) +{ + ICOM_THIS_MULTI(StdProxyImpl,lpVtbl,iface); + TRACE("(%p)->Disconnect()\n",This); + + IRpcChannelBuffer_Release(This->pChannel); + This->pChannel = NULL; +} + +static const IRpcProxyBufferVtbl StdProxy_Vtbl = +{ + StdProxy_QueryInterface, + StdProxy_AddRef, + StdProxy_Release, + StdProxy_Connect, + StdProxy_Disconnect +}; + +static void StdProxy_GetChannel(LPVOID iface, + LPRPCCHANNELBUFFER *ppChannel) +{ + ICOM_THIS_MULTI(StdProxyImpl,PVtbl,iface); + TRACE("(%p)->GetChannel(%p) %s\n",This,ppChannel,This->name); + + *ppChannel = This->pChannel; +} + +static void StdProxy_GetIID(LPVOID iface, + const IID **ppiid) +{ + ICOM_THIS_MULTI(StdProxyImpl,PVtbl,iface); + TRACE("(%p)->GetIID(%p) %s\n",This,ppiid,This->name); + + *ppiid = This->piid; +} + +HRESULT WINAPI IUnknown_QueryInterface_Proxy(LPUNKNOWN iface, + REFIID riid, + LPVOID *ppvObj) +{ + ICOM_THIS_MULTI(StdProxyImpl,PVtbl,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); + 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); + TRACE("(%p)->Release() %s\n",This,This->name); + return IUnknown_Release(This->pUnkOuter); +} + +/*********************************************************************** + * NdrProxyInitialize [RPCRT4.@] + */ +void WINAPI NdrProxyInitialize(void *This, + PRPC_MESSAGE pRpcMsg, + PMIDL_STUB_MESSAGE pStubMsg, + PMIDL_STUB_DESC pStubDescriptor, + unsigned int ProcNum) +{ + TRACE("(%p,%p,%p,%p,%d)\n", This, pRpcMsg, pStubMsg, pStubDescriptor, ProcNum); + NdrClientInitializeNew(pRpcMsg, pStubMsg, pStubDescriptor, ProcNum); + StdProxy_GetChannel(This, &pStubMsg->pRpcChannelBuffer); + IRpcChannelBuffer_GetDestCtx(pStubMsg->pRpcChannelBuffer, + &pStubMsg->dwDestContext, + &pStubMsg->pvDestContext); + TRACE("channel=%p\n", pStubMsg->pRpcChannelBuffer); +} + +/*********************************************************************** + * NdrProxyGetBuffer [RPCRT4.@] + */ +void WINAPI NdrProxyGetBuffer(void *This, + PMIDL_STUB_MESSAGE pStubMsg) +{ + HRESULT hr; + const IID *riid = NULL; + + TRACE("(%p,%p)\n", This, pStubMsg); + pStubMsg->RpcMsg->BufferLength = pStubMsg->BufferLength; + pStubMsg->dwStubPhase = PROXY_GETBUFFER; + StdProxy_GetIID(This, &riid); + hr = IRpcChannelBuffer_GetBuffer(pStubMsg->pRpcChannelBuffer, + (RPCOLEMESSAGE*)pStubMsg->RpcMsg, + riid); + if (FAILED(hr)) + { + RpcRaiseException(hr); + return; + } + pStubMsg->BufferStart = pStubMsg->RpcMsg->Buffer; + pStubMsg->BufferEnd = pStubMsg->BufferStart + pStubMsg->BufferLength; + pStubMsg->Buffer = pStubMsg->BufferStart; + pStubMsg->dwStubPhase = PROXY_MARSHAL; +} + +/*********************************************************************** + * NdrProxySendReceive [RPCRT4.@] + */ +void WINAPI NdrProxySendReceive(void *This, + PMIDL_STUB_MESSAGE pStubMsg) +{ + ULONG Status = 0; + HRESULT hr; + + TRACE("(%p,%p)\n", This, pStubMsg); + + if (!pStubMsg->pRpcChannelBuffer) + { + WARN("Trying to use disconnected proxy %p\n", This); + RpcRaiseException(RPC_E_DISCONNECTED); + } + + pStubMsg->dwStubPhase = PROXY_SENDRECEIVE; + hr = IRpcChannelBuffer_SendReceive(pStubMsg->pRpcChannelBuffer, + (RPCOLEMESSAGE*)pStubMsg->RpcMsg, + &Status); + pStubMsg->dwStubPhase = PROXY_UNMARSHAL; + pStubMsg->BufferLength = pStubMsg->RpcMsg->BufferLength; + pStubMsg->BufferStart = pStubMsg->RpcMsg->Buffer; + pStubMsg->BufferEnd = pStubMsg->BufferStart + pStubMsg->BufferLength; + pStubMsg->Buffer = pStubMsg->BufferStart; + + /* raise exception if call failed */ + if (hr == RPC_S_CALL_FAILED) RpcRaiseException(*(DWORD*)pStubMsg->Buffer); + else if (FAILED(hr)) RpcRaiseException(hr); +} + +/*********************************************************************** + * NdrProxyFreeBuffer [RPCRT4.@] + */ +void WINAPI NdrProxyFreeBuffer(void *This, + PMIDL_STUB_MESSAGE pStubMsg) +{ + HRESULT hr; + + TRACE("(%p,%p)\n", This, pStubMsg); + hr = IRpcChannelBuffer_FreeBuffer(pStubMsg->pRpcChannelBuffer, + (RPCOLEMESSAGE*)pStubMsg->RpcMsg); +} + +/*********************************************************************** + * NdrProxyErrorHandler [RPCRT4.@] + */ +HRESULT WINAPI NdrProxyErrorHandler(DWORD dwExceptionCode) +{ + WARN("(0x%08x): a proxy call failed\n", dwExceptionCode); + + if (FAILED(dwExceptionCode)) + return dwExceptionCode; + else + return HRESULT_FROM_WIN32(dwExceptionCode); +} + +HRESULT WINAPI +CreateProxyFromTypeInfo( LPTYPEINFO pTypeInfo, LPUNKNOWN pUnkOuter, REFIID riid, + LPRPCPROXYBUFFER *ppProxy, LPVOID *ppv ) +{ + typedef INT (WINAPI *MessageBoxA)(HWND,LPCSTR,LPCSTR,UINT); + HMODULE hUser32 = LoadLibraryA("user32"); + MessageBoxA pMessageBoxA = (void *)GetProcAddress(hUser32, "MessageBoxA"); + + FIXME("%p %p %s %p %p\n", pTypeInfo, pUnkOuter, debugstr_guid(riid), ppProxy, ppv); + 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_new/cpsf.c b/reactos/dll/win32/rpcrt4_new/cpsf.c index d87f347d88a..dcf37219195 100644 --- a/reactos/dll/win32/rpcrt4_new/cpsf.c +++ b/reactos/dll/win32/rpcrt4_new/cpsf.c @@ -1,307 +1,307 @@ -/* - * COM proxy/stub factory (CStdPSFactory) implementation - * - * Copyright 2001 Ove Kåven, TransGaming Technologies - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include -#include -#include - -#define COBJMACROS - -#include "windef.h" -#include "winbase.h" -#include "winerror.h" -#include "winreg.h" - -#include "objbase.h" - -#include "rpcproxy.h" - -#include "wine/debug.h" - -#include "cpsf.h" - -WINE_DEFAULT_DEBUG_CHANNEL(ole); - -static BOOL FindProxyInfo(const ProxyFileInfo **pProxyFileList, REFIID riid, const ProxyFileInfo **pProxyInfo, int *pIndex) -{ - while (*pProxyFileList) { - if ((*pProxyFileList)->pIIDLookupRtn(riid, pIndex)) { - *pProxyInfo = *pProxyFileList; - TRACE("found: ProxyInfo %p Index %d\n", *pProxyInfo, *pIndex); - return TRUE; - } - pProxyFileList++; - } - TRACE("not found\n"); - return FALSE; -} - -static HRESULT WINAPI CStdPSFactory_QueryInterface(LPPSFACTORYBUFFER iface, - REFIID riid, - LPVOID *obj) -{ - CStdPSFactoryBuffer *This = (CStdPSFactoryBuffer *)iface; - TRACE("(%p)->QueryInterface(%s,%p)\n",iface,debugstr_guid(riid),obj); - if (IsEqualGUID(&IID_IUnknown,riid) || - IsEqualGUID(&IID_IPSFactoryBuffer,riid)) { - *obj = This; - This->RefCount++; - return S_OK; - } - return E_NOINTERFACE; -} - -static ULONG WINAPI CStdPSFactory_AddRef(LPPSFACTORYBUFFER iface) -{ - CStdPSFactoryBuffer *This = (CStdPSFactoryBuffer *)iface; - TRACE("(%p)->AddRef()\n",iface); - return ++(This->RefCount); -} - -static ULONG WINAPI CStdPSFactory_Release(LPPSFACTORYBUFFER iface) -{ - CStdPSFactoryBuffer *This = (CStdPSFactoryBuffer *)iface; - TRACE("(%p)->Release()\n",iface); - return --(This->RefCount); -} - -static HRESULT WINAPI CStdPSFactory_CreateProxy(LPPSFACTORYBUFFER iface, - LPUNKNOWN pUnkOuter, - REFIID riid, - LPRPCPROXYBUFFER *ppProxy, - LPVOID *ppv) -{ - CStdPSFactoryBuffer *This = (CStdPSFactoryBuffer *)iface; - const ProxyFileInfo *ProxyInfo; - int Index; - TRACE("(%p)->CreateProxy(%p,%s,%p,%p)\n",iface,pUnkOuter, - debugstr_guid(riid),ppProxy,ppv); - if (!FindProxyInfo(This->pProxyFileList,riid,&ProxyInfo,&Index)) - return E_NOINTERFACE; - return StdProxy_Construct(riid, pUnkOuter, ProxyInfo, Index, iface, ppProxy, ppv); -} - -static HRESULT WINAPI CStdPSFactory_CreateStub(LPPSFACTORYBUFFER iface, - REFIID riid, - LPUNKNOWN pUnkServer, - LPRPCSTUBBUFFER *ppStub) -{ - CStdPSFactoryBuffer *This = (CStdPSFactoryBuffer *)iface; - const ProxyFileInfo *ProxyInfo; - int Index; - TRACE("(%p)->CreateStub(%s,%p,%p)\n",iface,debugstr_guid(riid), - pUnkServer,ppStub); - if (!FindProxyInfo(This->pProxyFileList,riid,&ProxyInfo,&Index)) - return E_NOINTERFACE; - - if(ProxyInfo->pDelegatedIIDs && ProxyInfo->pDelegatedIIDs[Index]) - return CStdStubBuffer_Delegating_Construct(riid, pUnkServer, ProxyInfo->pNamesArray[Index], - ProxyInfo->pStubVtblList[Index], ProxyInfo->pDelegatedIIDs[Index], - iface, ppStub); - - return CStdStubBuffer_Construct(riid, pUnkServer, ProxyInfo->pNamesArray[Index], - ProxyInfo->pStubVtblList[Index], iface, ppStub); -} - -static const IPSFactoryBufferVtbl CStdPSFactory_Vtbl = -{ - CStdPSFactory_QueryInterface, - CStdPSFactory_AddRef, - CStdPSFactory_Release, - CStdPSFactory_CreateProxy, - CStdPSFactory_CreateStub -}; - -/*********************************************************************** - * NdrDllGetClassObject [RPCRT4.@] - */ -HRESULT WINAPI NdrDllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv, - const ProxyFileInfo **pProxyFileList, - const CLSID *pclsid, - CStdPSFactoryBuffer *pPSFactoryBuffer) -{ - TRACE("(%s, %s, %p, %p, %s, %p)\n", debugstr_guid(rclsid), - debugstr_guid(iid), ppv, pProxyFileList, debugstr_guid(pclsid), - pPSFactoryBuffer); - - *ppv = NULL; - if (!pPSFactoryBuffer->lpVtbl) { - const ProxyFileInfo **pProxyFileList2; - int max_delegating_vtbl_size = 0; - pPSFactoryBuffer->lpVtbl = &CStdPSFactory_Vtbl; - pPSFactoryBuffer->RefCount = 0; - pPSFactoryBuffer->pProxyFileList = pProxyFileList; - for (pProxyFileList2 = pProxyFileList; *pProxyFileList2; pProxyFileList2++) { - int i; - for (i = 0; i < (*pProxyFileList2)->TableSize; i++) { - /* FIXME: i think that different vtables should be copied for - * async interfaces */ - void * const *pSrcRpcStubVtbl = (void * const *)&CStdStubBuffer_Vtbl; - void **pRpcStubVtbl = (void **)&(*pProxyFileList2)->pStubVtblList[i]->Vtbl; - int j; - - if ((*pProxyFileList2)->pDelegatedIIDs && (*pProxyFileList2)->pDelegatedIIDs[i]) { - pSrcRpcStubVtbl = (void * const *)&CStdStubBuffer_Delegating_Vtbl; - if ((*pProxyFileList2)->pStubVtblList[i]->header.DispatchTableCount > max_delegating_vtbl_size) - max_delegating_vtbl_size = (*pProxyFileList2)->pStubVtblList[i]->header.DispatchTableCount; - } - - for (j = 0; j < sizeof(IRpcStubBufferVtbl)/sizeof(void *); j++) - if (!pRpcStubVtbl[j]) - pRpcStubVtbl[j] = pSrcRpcStubVtbl[j]; - } - } - if(max_delegating_vtbl_size > 0) - create_delegating_vtbl(max_delegating_vtbl_size); - } - if (IsEqualGUID(rclsid, pclsid)) - return IPSFactoryBuffer_QueryInterface((LPPSFACTORYBUFFER)pPSFactoryBuffer, iid, ppv); - else { - const ProxyFileInfo *info; - int index; - /* otherwise, the dll may be using the iid as the clsid, so - * search for it in the proxy file list */ - if (FindProxyInfo(pProxyFileList, rclsid, &info, &index)) - return IPSFactoryBuffer_QueryInterface((LPPSFACTORYBUFFER)pPSFactoryBuffer, iid, ppv); - - WARN("class %s not available\n", debugstr_guid(rclsid)); - return CLASS_E_CLASSNOTAVAILABLE; - } -} - -/*********************************************************************** - * NdrDllCanUnloadNow [RPCRT4.@] - */ -HRESULT WINAPI NdrDllCanUnloadNow(CStdPSFactoryBuffer *pPSFactoryBuffer) -{ - return !(pPSFactoryBuffer->RefCount); -} - -/*********************************************************************** - * NdrDllRegisterProxy [RPCRT4.@] - */ -HRESULT WINAPI NdrDllRegisterProxy(HMODULE hDll, - const ProxyFileInfo **pProxyFileList, - const CLSID *pclsid) -{ - LPSTR clsid; - char keyname[120], module[MAX_PATH]; - HKEY key, subkey; - DWORD len; - - TRACE("(%p,%p,%s)\n", hDll, pProxyFileList, debugstr_guid(pclsid)); - UuidToStringA((UUID*)pclsid, (unsigned char**)&clsid); - - /* register interfaces to point to clsid */ - while (*pProxyFileList) { - unsigned u; - for (u=0; u<(*pProxyFileList)->TableSize; u++) { - CInterfaceStubVtbl *proxy = (*pProxyFileList)->pStubVtblList[u]; - PCInterfaceName name = (*pProxyFileList)->pNamesArray[u]; - LPSTR iid; - - TRACE("registering %s %s => %s\n", name, debugstr_guid(proxy->header.piid), clsid); - - UuidToStringA((UUID*)proxy->header.piid, (unsigned char**)&iid); - snprintf(keyname, sizeof(keyname), "Interface\\{%s}", iid); - RpcStringFreeA((unsigned char**)&iid); - if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyname, 0, NULL, 0, - KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS) { - if (name) - RegSetValueExA(key, NULL, 0, REG_SZ, (const BYTE *)name, strlen(name)); - if (RegCreateKeyExA(key, "ProxyStubClsid32", 0, NULL, 0, - KEY_WRITE, NULL, &subkey, NULL) == ERROR_SUCCESS) { - snprintf(module, sizeof(module), "{%s}", clsid); - RegSetValueExA(subkey, NULL, 0, REG_SZ, (LPBYTE)module, strlen(module)); - RegCloseKey(subkey); - } - RegCloseKey(key); - } - } - pProxyFileList++; - } - - /* register clsid to point to module */ - snprintf(keyname, sizeof(keyname), "CLSID\\{%s}", clsid); - len = GetModuleFileNameA(hDll, module, sizeof(module)); - if (len && len < sizeof(module)) { - TRACE("registering CLSID %s => %s\n", clsid, module); - if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyname, 0, NULL, 0, - KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS) { - RegSetValueExA(subkey, NULL, 0, REG_SZ, (const BYTE *)"PSFactoryBuffer", strlen("PSFactoryBuffer")); - if (RegCreateKeyExA(key, "InProcServer32", 0, NULL, 0, - KEY_WRITE, NULL, &subkey, NULL) == ERROR_SUCCESS) { - RegSetValueExA(subkey, NULL, 0, REG_SZ, (LPBYTE)module, strlen(module)); - RegSetValueExA(subkey, "ThreadingModel", 0, REG_SZ, (const BYTE *)"Both", strlen("Both")); - RegCloseKey(subkey); - } - RegCloseKey(key); - } - } - - /* done */ - RpcStringFreeA((unsigned char**)&clsid); - return S_OK; -} - -/*********************************************************************** - * NdrDllUnregisterProxy [RPCRT4.@] - */ -HRESULT WINAPI NdrDllUnregisterProxy(HMODULE hDll, - const ProxyFileInfo **pProxyFileList, - const CLSID *pclsid) -{ - LPSTR clsid; - char keyname[120], module[MAX_PATH]; - DWORD len; - - TRACE("(%p,%p,%s)\n", hDll, pProxyFileList, debugstr_guid(pclsid)); - UuidToStringA((UUID*)pclsid, (unsigned char**)&clsid); - - /* unregister interfaces */ - while (*pProxyFileList) { - unsigned u; - for (u=0; u<(*pProxyFileList)->TableSize; u++) { - CInterfaceStubVtbl *proxy = (*pProxyFileList)->pStubVtblList[u]; - PCInterfaceName name = (*pProxyFileList)->pNamesArray[u]; - LPSTR iid; - - TRACE("unregistering %s %s <= %s\n", name, debugstr_guid(proxy->header.piid), clsid); - - UuidToStringA((UUID*)proxy->header.piid, (unsigned char**)&iid); - snprintf(keyname, sizeof(keyname), "Interface\\{%s}", iid); - RpcStringFreeA((unsigned char**)&iid); - RegDeleteKeyA(HKEY_CLASSES_ROOT, keyname); - } - pProxyFileList++; - } - - /* unregister clsid */ - snprintf(keyname, sizeof(keyname), "CLSID\\{%s}", clsid); - len = GetModuleFileNameA(hDll, module, sizeof(module)); - if (len && len < sizeof(module)) { - TRACE("unregistering CLSID %s <= %s\n", clsid, module); - RegDeleteKeyA(HKEY_CLASSES_ROOT, keyname); - } - - /* done */ - RpcStringFreeA((unsigned char**)&clsid); - return S_OK; -} +/* + * COM proxy/stub factory (CStdPSFactory) implementation + * + * Copyright 2001 Ove Kåven, TransGaming Technologies + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include +#include + +#define COBJMACROS + +#include "windef.h" +#include "winbase.h" +#include "winerror.h" +#include "winreg.h" + +#include "objbase.h" + +#include "rpcproxy.h" + +#include "wine/debug.h" + +#include "cpsf.h" + +WINE_DEFAULT_DEBUG_CHANNEL(ole); + +static BOOL FindProxyInfo(const ProxyFileInfo **pProxyFileList, REFIID riid, const ProxyFileInfo **pProxyInfo, int *pIndex) +{ + while (*pProxyFileList) { + if ((*pProxyFileList)->pIIDLookupRtn(riid, pIndex)) { + *pProxyInfo = *pProxyFileList; + TRACE("found: ProxyInfo %p Index %d\n", *pProxyInfo, *pIndex); + return TRUE; + } + pProxyFileList++; + } + TRACE("not found\n"); + return FALSE; +} + +static HRESULT WINAPI CStdPSFactory_QueryInterface(LPPSFACTORYBUFFER iface, + REFIID riid, + LPVOID *obj) +{ + CStdPSFactoryBuffer *This = (CStdPSFactoryBuffer *)iface; + TRACE("(%p)->QueryInterface(%s,%p)\n",iface,debugstr_guid(riid),obj); + if (IsEqualGUID(&IID_IUnknown,riid) || + IsEqualGUID(&IID_IPSFactoryBuffer,riid)) { + *obj = This; + This->RefCount++; + return S_OK; + } + return E_NOINTERFACE; +} + +static ULONG WINAPI CStdPSFactory_AddRef(LPPSFACTORYBUFFER iface) +{ + CStdPSFactoryBuffer *This = (CStdPSFactoryBuffer *)iface; + TRACE("(%p)->AddRef()\n",iface); + return ++(This->RefCount); +} + +static ULONG WINAPI CStdPSFactory_Release(LPPSFACTORYBUFFER iface) +{ + CStdPSFactoryBuffer *This = (CStdPSFactoryBuffer *)iface; + TRACE("(%p)->Release()\n",iface); + return --(This->RefCount); +} + +static HRESULT WINAPI CStdPSFactory_CreateProxy(LPPSFACTORYBUFFER iface, + LPUNKNOWN pUnkOuter, + REFIID riid, + LPRPCPROXYBUFFER *ppProxy, + LPVOID *ppv) +{ + CStdPSFactoryBuffer *This = (CStdPSFactoryBuffer *)iface; + const ProxyFileInfo *ProxyInfo; + int Index; + TRACE("(%p)->CreateProxy(%p,%s,%p,%p)\n",iface,pUnkOuter, + debugstr_guid(riid),ppProxy,ppv); + if (!FindProxyInfo(This->pProxyFileList,riid,&ProxyInfo,&Index)) + return E_NOINTERFACE; + return StdProxy_Construct(riid, pUnkOuter, ProxyInfo, Index, iface, ppProxy, ppv); +} + +static HRESULT WINAPI CStdPSFactory_CreateStub(LPPSFACTORYBUFFER iface, + REFIID riid, + LPUNKNOWN pUnkServer, + LPRPCSTUBBUFFER *ppStub) +{ + CStdPSFactoryBuffer *This = (CStdPSFactoryBuffer *)iface; + const ProxyFileInfo *ProxyInfo; + int Index; + TRACE("(%p)->CreateStub(%s,%p,%p)\n",iface,debugstr_guid(riid), + pUnkServer,ppStub); + if (!FindProxyInfo(This->pProxyFileList,riid,&ProxyInfo,&Index)) + return E_NOINTERFACE; + + if(ProxyInfo->pDelegatedIIDs && ProxyInfo->pDelegatedIIDs[Index]) + return CStdStubBuffer_Delegating_Construct(riid, pUnkServer, ProxyInfo->pNamesArray[Index], + ProxyInfo->pStubVtblList[Index], ProxyInfo->pDelegatedIIDs[Index], + iface, ppStub); + + return CStdStubBuffer_Construct(riid, pUnkServer, ProxyInfo->pNamesArray[Index], + ProxyInfo->pStubVtblList[Index], iface, ppStub); +} + +static const IPSFactoryBufferVtbl CStdPSFactory_Vtbl = +{ + CStdPSFactory_QueryInterface, + CStdPSFactory_AddRef, + CStdPSFactory_Release, + CStdPSFactory_CreateProxy, + CStdPSFactory_CreateStub +}; + +/*********************************************************************** + * NdrDllGetClassObject [RPCRT4.@] + */ +HRESULT WINAPI NdrDllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv, + const ProxyFileInfo **pProxyFileList, + const CLSID *pclsid, + CStdPSFactoryBuffer *pPSFactoryBuffer) +{ + TRACE("(%s, %s, %p, %p, %s, %p)\n", debugstr_guid(rclsid), + debugstr_guid(iid), ppv, pProxyFileList, debugstr_guid(pclsid), + pPSFactoryBuffer); + + *ppv = NULL; + if (!pPSFactoryBuffer->lpVtbl) { + const ProxyFileInfo **pProxyFileList2; + int max_delegating_vtbl_size = 0; + pPSFactoryBuffer->lpVtbl = &CStdPSFactory_Vtbl; + pPSFactoryBuffer->RefCount = 0; + pPSFactoryBuffer->pProxyFileList = pProxyFileList; + for (pProxyFileList2 = pProxyFileList; *pProxyFileList2; pProxyFileList2++) { + int i; + for (i = 0; i < (*pProxyFileList2)->TableSize; i++) { + /* FIXME: i think that different vtables should be copied for + * async interfaces */ + void * const *pSrcRpcStubVtbl = (void * const *)&CStdStubBuffer_Vtbl; + void **pRpcStubVtbl = (void **)&(*pProxyFileList2)->pStubVtblList[i]->Vtbl; + int j; + + if ((*pProxyFileList2)->pDelegatedIIDs && (*pProxyFileList2)->pDelegatedIIDs[i]) { + pSrcRpcStubVtbl = (void * const *)&CStdStubBuffer_Delegating_Vtbl; + if ((*pProxyFileList2)->pStubVtblList[i]->header.DispatchTableCount > max_delegating_vtbl_size) + max_delegating_vtbl_size = (*pProxyFileList2)->pStubVtblList[i]->header.DispatchTableCount; + } + + for (j = 0; j < sizeof(IRpcStubBufferVtbl)/sizeof(void *); j++) + if (!pRpcStubVtbl[j]) + pRpcStubVtbl[j] = pSrcRpcStubVtbl[j]; + } + } + if(max_delegating_vtbl_size > 0) + create_delegating_vtbl(max_delegating_vtbl_size); + } + if (IsEqualGUID(rclsid, pclsid)) + return IPSFactoryBuffer_QueryInterface((LPPSFACTORYBUFFER)pPSFactoryBuffer, iid, ppv); + else { + const ProxyFileInfo *info; + int index; + /* otherwise, the dll may be using the iid as the clsid, so + * search for it in the proxy file list */ + if (FindProxyInfo(pProxyFileList, rclsid, &info, &index)) + return IPSFactoryBuffer_QueryInterface((LPPSFACTORYBUFFER)pPSFactoryBuffer, iid, ppv); + + WARN("class %s not available\n", debugstr_guid(rclsid)); + return CLASS_E_CLASSNOTAVAILABLE; + } +} + +/*********************************************************************** + * NdrDllCanUnloadNow [RPCRT4.@] + */ +HRESULT WINAPI NdrDllCanUnloadNow(CStdPSFactoryBuffer *pPSFactoryBuffer) +{ + return !(pPSFactoryBuffer->RefCount); +} + +/*********************************************************************** + * NdrDllRegisterProxy [RPCRT4.@] + */ +HRESULT WINAPI NdrDllRegisterProxy(HMODULE hDll, + const ProxyFileInfo **pProxyFileList, + const CLSID *pclsid) +{ + LPSTR clsid; + char keyname[120], module[MAX_PATH]; + HKEY key, subkey; + DWORD len; + + TRACE("(%p,%p,%s)\n", hDll, pProxyFileList, debugstr_guid(pclsid)); + UuidToStringA((UUID*)pclsid, (unsigned char**)&clsid); + + /* register interfaces to point to clsid */ + while (*pProxyFileList) { + unsigned u; + for (u=0; u<(*pProxyFileList)->TableSize; u++) { + CInterfaceStubVtbl *proxy = (*pProxyFileList)->pStubVtblList[u]; + PCInterfaceName name = (*pProxyFileList)->pNamesArray[u]; + LPSTR iid; + + TRACE("registering %s %s => %s\n", name, debugstr_guid(proxy->header.piid), clsid); + + UuidToStringA((UUID*)proxy->header.piid, (unsigned char**)&iid); + snprintf(keyname, sizeof(keyname), "Interface\\{%s}", iid); + RpcStringFreeA((unsigned char**)&iid); + if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyname, 0, NULL, 0, + KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS) { + if (name) + RegSetValueExA(key, NULL, 0, REG_SZ, (const BYTE *)name, strlen(name)); + if (RegCreateKeyExA(key, "ProxyStubClsid32", 0, NULL, 0, + KEY_WRITE, NULL, &subkey, NULL) == ERROR_SUCCESS) { + snprintf(module, sizeof(module), "{%s}", clsid); + RegSetValueExA(subkey, NULL, 0, REG_SZ, (LPBYTE)module, strlen(module)); + RegCloseKey(subkey); + } + RegCloseKey(key); + } + } + pProxyFileList++; + } + + /* register clsid to point to module */ + snprintf(keyname, sizeof(keyname), "CLSID\\{%s}", clsid); + len = GetModuleFileNameA(hDll, module, sizeof(module)); + if (len && len < sizeof(module)) { + TRACE("registering CLSID %s => %s\n", clsid, module); + if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyname, 0, NULL, 0, + KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS) { + RegSetValueExA(subkey, NULL, 0, REG_SZ, (const BYTE *)"PSFactoryBuffer", strlen("PSFactoryBuffer")); + if (RegCreateKeyExA(key, "InProcServer32", 0, NULL, 0, + KEY_WRITE, NULL, &subkey, NULL) == ERROR_SUCCESS) { + RegSetValueExA(subkey, NULL, 0, REG_SZ, (LPBYTE)module, strlen(module)); + RegSetValueExA(subkey, "ThreadingModel", 0, REG_SZ, (const BYTE *)"Both", strlen("Both")); + RegCloseKey(subkey); + } + RegCloseKey(key); + } + } + + /* done */ + RpcStringFreeA((unsigned char**)&clsid); + return S_OK; +} + +/*********************************************************************** + * NdrDllUnregisterProxy [RPCRT4.@] + */ +HRESULT WINAPI NdrDllUnregisterProxy(HMODULE hDll, + const ProxyFileInfo **pProxyFileList, + const CLSID *pclsid) +{ + LPSTR clsid; + char keyname[120], module[MAX_PATH]; + DWORD len; + + TRACE("(%p,%p,%s)\n", hDll, pProxyFileList, debugstr_guid(pclsid)); + UuidToStringA((UUID*)pclsid, (unsigned char**)&clsid); + + /* unregister interfaces */ + while (*pProxyFileList) { + unsigned u; + for (u=0; u<(*pProxyFileList)->TableSize; u++) { + CInterfaceStubVtbl *proxy = (*pProxyFileList)->pStubVtblList[u]; + PCInterfaceName name = (*pProxyFileList)->pNamesArray[u]; + LPSTR iid; + + TRACE("unregistering %s %s <= %s\n", name, debugstr_guid(proxy->header.piid), clsid); + + UuidToStringA((UUID*)proxy->header.piid, (unsigned char**)&iid); + snprintf(keyname, sizeof(keyname), "Interface\\{%s}", iid); + RpcStringFreeA((unsigned char**)&iid); + RegDeleteKeyA(HKEY_CLASSES_ROOT, keyname); + } + pProxyFileList++; + } + + /* unregister clsid */ + snprintf(keyname, sizeof(keyname), "CLSID\\{%s}", clsid); + len = GetModuleFileNameA(hDll, module, sizeof(module)); + if (len && len < sizeof(module)) { + TRACE("unregistering CLSID %s <= %s\n", clsid, module); + RegDeleteKeyA(HKEY_CLASSES_ROOT, keyname); + } + + /* done */ + RpcStringFreeA((unsigned char**)&clsid); + return S_OK; +} diff --git a/reactos/dll/win32/rpcrt4_new/cpsf.h b/reactos/dll/win32/rpcrt4_new/cpsf.h index 015389c01b2..5ce8fe6575e 100644 --- a/reactos/dll/win32/rpcrt4_new/cpsf.h +++ b/reactos/dll/win32/rpcrt4_new/cpsf.h @@ -1,56 +1,56 @@ -/* - * COM proxy definitions - * - * Copyright 2001 Ove Kåven, TransGaming Technologies - * - * 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 - */ - -#ifndef __WINE_CPSF_H -#define __WINE_CPSF_H - -HRESULT WINAPI StdProxy_Construct(REFIID riid, - LPUNKNOWN pUnkOuter, - const ProxyFileInfo *ProxyInfo, - int Index, - LPPSFACTORYBUFFER pPSFactory, - LPRPCPROXYBUFFER *ppProxy, - LPVOID *ppvObj); - -HRESULT WINAPI CStdStubBuffer_Construct(REFIID riid, - LPUNKNOWN pUnkServer, - PCInterfaceName name, - CInterfaceStubVtbl *vtbl, - LPPSFACTORYBUFFER pPSFactory, - LPRPCSTUBBUFFER *ppStub); - -HRESULT WINAPI CStdStubBuffer_Delegating_Construct(REFIID riid, - LPUNKNOWN pUnkServer, - PCInterfaceName name, - CInterfaceStubVtbl *vtbl, - REFIID delegating_iid, - LPPSFACTORYBUFFER pPSFactory, - LPRPCSTUBBUFFER *ppStub); - -const MIDL_SERVER_INFO *CStdStubBuffer_GetServerInfo(IRpcStubBuffer *iface); - -const IRpcStubBufferVtbl CStdStubBuffer_Vtbl; -const IRpcStubBufferVtbl CStdStubBuffer_Delegating_Vtbl; - -void create_delegating_vtbl(DWORD num_methods); - -HRESULT create_stub(REFIID iid, IUnknown *pUnk, IRpcStubBuffer **ppstub); - -#endif /* __WINE_CPSF_H */ +/* + * COM proxy definitions + * + * Copyright 2001 Ove Kåven, TransGaming Technologies + * + * 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 + */ + +#ifndef __WINE_CPSF_H +#define __WINE_CPSF_H + +HRESULT WINAPI StdProxy_Construct(REFIID riid, + LPUNKNOWN pUnkOuter, + const ProxyFileInfo *ProxyInfo, + int Index, + LPPSFACTORYBUFFER pPSFactory, + LPRPCPROXYBUFFER *ppProxy, + LPVOID *ppvObj); + +HRESULT WINAPI CStdStubBuffer_Construct(REFIID riid, + LPUNKNOWN pUnkServer, + PCInterfaceName name, + CInterfaceStubVtbl *vtbl, + LPPSFACTORYBUFFER pPSFactory, + LPRPCSTUBBUFFER *ppStub); + +HRESULT WINAPI CStdStubBuffer_Delegating_Construct(REFIID riid, + LPUNKNOWN pUnkServer, + PCInterfaceName name, + CInterfaceStubVtbl *vtbl, + REFIID delegating_iid, + LPPSFACTORYBUFFER pPSFactory, + LPRPCSTUBBUFFER *ppStub); + +const MIDL_SERVER_INFO *CStdStubBuffer_GetServerInfo(IRpcStubBuffer *iface); + +const IRpcStubBufferVtbl CStdStubBuffer_Vtbl; +const IRpcStubBufferVtbl CStdStubBuffer_Delegating_Vtbl; + +void create_delegating_vtbl(DWORD num_methods); + +HRESULT create_stub(REFIID iid, IUnknown *pUnk, IRpcStubBuffer **ppstub); + +#endif /* __WINE_CPSF_H */ diff --git a/reactos/dll/win32/rpcrt4_new/cstub.c b/reactos/dll/win32/rpcrt4_new/cstub.c index 22dc97ecd1d..cd07c297390 100644 --- a/reactos/dll/win32/rpcrt4_new/cstub.c +++ b/reactos/dll/win32/rpcrt4_new/cstub.c @@ -1,599 +1,599 @@ -/* - * COM stub (CStdStubBuffer) implementation - * - * Copyright 2001 Ove Kåven, TransGaming Technologies - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include - -#define COBJMACROS - -#include "windef.h" -#include "winbase.h" -#include "winerror.h" -#include "excpt.h" - -#include "objbase.h" -#include "rpcproxy.h" - -#include "wine/debug.h" -#include "wine/exception.h" - -#include "cpsf.h" - -WINE_DEFAULT_DEBUG_CHANNEL(ole); - -#define STUB_HEADER(This) (((const CInterfaceStubHeader*)((This)->lpVtbl))[-1]) - -static WINE_EXCEPTION_FILTER(stub_filter) -{ - if (GetExceptionInformation()->ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE) - return EXCEPTION_CONTINUE_SEARCH; - return EXCEPTION_EXECUTE_HANDLER; -} - -typedef struct -{ - IUnknownVtbl *base_obj; - IRpcStubBuffer *base_stub; - CStdStubBuffer stub_buffer; -} cstdstubbuffer_delegating_t; - -static inline cstdstubbuffer_delegating_t *impl_from_delegating( IRpcStubBuffer *iface ) -{ - return (cstdstubbuffer_delegating_t*)((char *)iface - FIELD_OFFSET(cstdstubbuffer_delegating_t, stub_buffer)); -} - -HRESULT WINAPI CStdStubBuffer_Construct(REFIID riid, - LPUNKNOWN pUnkServer, - PCInterfaceName name, - CInterfaceStubVtbl *vtbl, - LPPSFACTORYBUFFER pPSFactory, - LPRPCSTUBBUFFER *ppStub) -{ - CStdStubBuffer *This; - IUnknown *pvServer; - HRESULT r; - TRACE("(%p,%p,%p,%p) %s\n", pUnkServer, vtbl, pPSFactory, ppStub, name); - TRACE("iid=%s\n", debugstr_guid(vtbl->header.piid)); - TRACE("vtbl=%p\n", &vtbl->Vtbl); - - if (!IsEqualGUID(vtbl->header.piid, riid)) { - ERR("IID mismatch during stub creation\n"); - return RPC_E_UNEXPECTED; - } - - r = IUnknown_QueryInterface(pUnkServer, riid, (void**)&pvServer); - if(FAILED(r)) - return r; - - This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(CStdStubBuffer)); - if (!This) { - IUnknown_Release(pvServer); - return E_OUTOFMEMORY; - } - - This->lpVtbl = &vtbl->Vtbl; - This->RefCount = 1; - This->pvServerObject = pvServer; - This->pPSFactory = pPSFactory; - *ppStub = (LPRPCSTUBBUFFER)This; - - IPSFactoryBuffer_AddRef(pPSFactory); - return S_OK; -} - -static CRITICAL_SECTION delegating_vtbl_section; -static CRITICAL_SECTION_DEBUG critsect_debug = -{ - 0, 0, &delegating_vtbl_section, - { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList }, - 0, 0, { (DWORD_PTR)(__FILE__ ": delegating_vtbl_section") } -}; -static CRITICAL_SECTION delegating_vtbl_section = { &critsect_debug, -1, 0, 0, 0, 0 }; - -typedef struct -{ - DWORD ref; - DWORD size; - void **methods; - IUnknownVtbl vtbl; - /* remaining entries in vtbl */ -} ref_counted_vtbl; - -static struct -{ - ref_counted_vtbl *table; -} current_vtbl; - - -static HRESULT WINAPI delegating_QueryInterface(IUnknown *pUnk, REFIID iid, void **ppv) -{ - *ppv = (void *)pUnk; - return S_OK; -} - -static ULONG WINAPI delegating_AddRef(IUnknown *pUnk) -{ - return 1; -} - -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. -*/ -#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 */ -} vtbl_method_t; -#include "poppack.h" - -static void fill_table(IUnknownVtbl *vtbl, void **methods, DWORD num) -{ - vtbl_method_t *method; - void **entry; - DWORD i; - - vtbl->QueryInterface = delegating_QueryInterface; - vtbl->AddRef = delegating_AddRef; - vtbl->Release = delegating_Release; - - method = (vtbl_method_t*)methods; - entry = (void**)(vtbl + 1); - - for(i = 3; i < num; i++) - { - *entry = method; - method->mov1 = 0x0424448b; - method->mov2 = 0x408b; - method->sixteen = 0x10; - method->mov3 = 0x04244489; - method->mov4 = 0x008b; - method->mov5 = 0x808b; - method->offset = i << 2; - method->jmp = 0xe0ff; - method->pad[0] = 0x8d; - method->pad[1] = 0x76; - method->pad[2] = 0x00; - - method++; - entry++; - } -} - -#else /* __i386__ */ - -typedef struct {int dummy;} vtbl_method_t; -static void fill_table(IUnknownVtbl *vtbl, DWORD num) -{ - ERR("delegated stubs are not supported on this architecture\n"); -} - -#endif /* __i386__ */ - -void create_delegating_vtbl(DWORD num_methods) -{ - TRACE("%d\n", num_methods); - if(num_methods <= 3) - { - ERR("should have more than %d methods\n", num_methods); - return; - } - - EnterCriticalSection(&delegating_vtbl_section); - if(!current_vtbl.table || num_methods > current_vtbl.table->size) - { - DWORD size; - DWORD old_protect; - if(current_vtbl.table && current_vtbl.table->ref == 0) - { - TRACE("freeing old table\n"); - VirtualFree(current_vtbl.table->methods, - (current_vtbl.table->size - 3) * sizeof(vtbl_method_t), - MEM_RELEASE); - HeapFree(GetProcessHeap(), 0, current_vtbl.table); - } - size = (num_methods - 3) * sizeof(vtbl_method_t); - current_vtbl.table = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(ref_counted_vtbl, vtbl) + num_methods * sizeof(void*)); - current_vtbl.table->ref = 0; - current_vtbl.table->size = num_methods; - current_vtbl.table->methods = VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); - fill_table(¤t_vtbl.table->vtbl, current_vtbl.table->methods, num_methods); - VirtualProtect(current_vtbl.table->methods, size, PAGE_EXECUTE_READ, &old_protect); - } - LeaveCriticalSection(&delegating_vtbl_section); -} - -static IUnknownVtbl *get_delegating_vtbl(void) -{ - IUnknownVtbl *ret; - - EnterCriticalSection(&delegating_vtbl_section); - current_vtbl.table->ref++; - ret = ¤t_vtbl.table->vtbl; - LeaveCriticalSection(&delegating_vtbl_section); - return ret; -} - -static void release_delegating_vtbl(IUnknownVtbl *vtbl) -{ - ref_counted_vtbl *table = (ref_counted_vtbl*)((DWORD *)vtbl - 1); - - EnterCriticalSection(&delegating_vtbl_section); - table->ref--; - TRACE("ref now %d\n", table->ref); - if(table->ref == 0 && table != current_vtbl.table) - { - TRACE("... and we're not current so free'ing\n"); - VirtualFree(current_vtbl.table->methods, - (current_vtbl.table->size - 3) * sizeof(vtbl_method_t), - MEM_RELEASE); - HeapFree(GetProcessHeap(), 0, table); - } - LeaveCriticalSection(&delegating_vtbl_section); -} - -HRESULT WINAPI CStdStubBuffer_Delegating_Construct(REFIID riid, - LPUNKNOWN pUnkServer, - PCInterfaceName name, - CInterfaceStubVtbl *vtbl, - REFIID delegating_iid, - LPPSFACTORYBUFFER pPSFactory, - LPRPCSTUBBUFFER *ppStub) -{ - cstdstubbuffer_delegating_t *This; - IUnknown *pvServer; - HRESULT r; - - TRACE("(%p,%p,%p,%p) %s\n", pUnkServer, vtbl, pPSFactory, ppStub, name); - TRACE("iid=%s delegating to %s\n", debugstr_guid(vtbl->header.piid), debugstr_guid(delegating_iid)); - TRACE("vtbl=%p\n", &vtbl->Vtbl); - - if (!IsEqualGUID(vtbl->header.piid, riid)) - { - ERR("IID mismatch during stub creation\n"); - return RPC_E_UNEXPECTED; - } - - r = IUnknown_QueryInterface(pUnkServer, riid, (void**)&pvServer); - if(FAILED(r)) return r; - - This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This)); - if (!This) - { - IUnknown_Release(pvServer); - return E_OUTOFMEMORY; - } - - This->base_obj = get_delegating_vtbl(); - r = create_stub(delegating_iid, (IUnknown*)&This->base_obj, &This->base_stub); - if(FAILED(r)) - { - release_delegating_vtbl(This->base_obj); - HeapFree(GetProcessHeap(), 0, This); - IUnknown_Release(pvServer); - return r; - } - - This->stub_buffer.lpVtbl = &vtbl->Vtbl; - This->stub_buffer.RefCount = 1; - This->stub_buffer.pvServerObject = pvServer; - This->stub_buffer.pPSFactory = pPSFactory; - *ppStub = (LPRPCSTUBBUFFER)&This->stub_buffer; - - IPSFactoryBuffer_AddRef(pPSFactory); - return S_OK; -} - -HRESULT WINAPI CStdStubBuffer_QueryInterface(LPRPCSTUBBUFFER iface, - REFIID riid, - LPVOID *obj) -{ - CStdStubBuffer *This = (CStdStubBuffer *)iface; - TRACE("(%p)->QueryInterface(%s,%p)\n",This,debugstr_guid(riid),obj); - - if (IsEqualIID(&IID_IUnknown, riid) || - IsEqualIID(&IID_IRpcStubBuffer, riid)) - { - IUnknown_AddRef(iface); - *obj = iface; - return S_OK; - } - *obj = NULL; - return E_NOINTERFACE; -} - -ULONG WINAPI CStdStubBuffer_AddRef(LPRPCSTUBBUFFER iface) -{ - CStdStubBuffer *This = (CStdStubBuffer *)iface; - TRACE("(%p)->AddRef()\n",This); - return InterlockedIncrement(&This->RefCount); -} - -ULONG WINAPI NdrCStdStubBuffer_Release(LPRPCSTUBBUFFER iface, - LPPSFACTORYBUFFER pPSF) -{ - CStdStubBuffer *This = (CStdStubBuffer *)iface; - ULONG refs; - - TRACE("(%p)->Release()\n",This); - - refs = InterlockedDecrement(&This->RefCount); - if (!refs) - { - /* test_Release shows that native doesn't call Disconnect here. - We'll leave it in for the time being. */ - IRpcStubBuffer_Disconnect(iface); - - IPSFactoryBuffer_Release(pPSF); - HeapFree(GetProcessHeap(),0,This); - } - return refs; -} - -ULONG WINAPI NdrCStdStubBuffer2_Release(LPRPCSTUBBUFFER iface, - LPPSFACTORYBUFFER pPSF) -{ - cstdstubbuffer_delegating_t *This = impl_from_delegating( iface ); - ULONG refs; - - TRACE("(%p)->Release()\n", This); - - refs = InterlockedDecrement(&This->stub_buffer.RefCount); - if (!refs) - { - /* Just like NdrCStdStubBuffer_Release, we shouldn't call - Disconnect here */ - IRpcStubBuffer_Disconnect((IRpcStubBuffer *)&This->stub_buffer); - - IRpcStubBuffer_Release(This->base_stub); - release_delegating_vtbl(This->base_obj); - - IPSFactoryBuffer_Release(pPSF); - HeapFree(GetProcessHeap(), 0, This); - } - - return refs; -} - -HRESULT WINAPI CStdStubBuffer_Connect(LPRPCSTUBBUFFER iface, - LPUNKNOWN lpUnkServer) -{ - CStdStubBuffer *This = (CStdStubBuffer *)iface; - HRESULT r; - IUnknown *new = NULL; - - TRACE("(%p)->Connect(%p)\n",This,lpUnkServer); - - r = IUnknown_QueryInterface(lpUnkServer, STUB_HEADER(This).piid, (void**)&new); - new = InterlockedExchangePointer((void**)&This->pvServerObject, new); - if(new) - IUnknown_Release(new); - return r; -} - -void WINAPI CStdStubBuffer_Disconnect(LPRPCSTUBBUFFER iface) -{ - CStdStubBuffer *This = (CStdStubBuffer *)iface; - IUnknown *old; - TRACE("(%p)->Disconnect()\n",This); - - old = InterlockedExchangePointer((void**)&This->pvServerObject, NULL); - - if(old) - IUnknown_Release(old); -} - -HRESULT WINAPI CStdStubBuffer_Invoke(LPRPCSTUBBUFFER iface, - PRPCOLEMESSAGE pMsg, - LPRPCCHANNELBUFFER pChannel) -{ - CStdStubBuffer *This = (CStdStubBuffer *)iface; - DWORD dwPhase = STUB_UNMARSHAL; - HRESULT hr = S_OK; - - TRACE("(%p)->Invoke(%p,%p)\n",This,pMsg,pChannel); - - __TRY - { - if (STUB_HEADER(This).pDispatchTable) - STUB_HEADER(This).pDispatchTable[pMsg->iMethod](iface, pChannel, (PRPC_MESSAGE)pMsg, &dwPhase); - else /* pure interpreted */ - NdrStubCall2(iface, pChannel, (PRPC_MESSAGE)pMsg, &dwPhase); - } - __EXCEPT(stub_filter) - { - DWORD dwExceptionCode = GetExceptionCode(); - WARN("a stub call failed with exception 0x%08x (%d)\n", dwExceptionCode, dwExceptionCode); - if (FAILED(dwExceptionCode)) - hr = dwExceptionCode; - else - hr = HRESULT_FROM_WIN32(dwExceptionCode); - } - __ENDTRY - - return hr; -} - -LPRPCSTUBBUFFER WINAPI CStdStubBuffer_IsIIDSupported(LPRPCSTUBBUFFER iface, - REFIID riid) -{ - CStdStubBuffer *This = (CStdStubBuffer *)iface; - TRACE("(%p)->IsIIDSupported(%s)\n",This,debugstr_guid(riid)); - return IsEqualGUID(STUB_HEADER(This).piid, riid) ? iface : NULL; -} - -ULONG WINAPI CStdStubBuffer_CountRefs(LPRPCSTUBBUFFER iface) -{ - CStdStubBuffer *This = (CStdStubBuffer *)iface; - TRACE("(%p)->CountRefs()\n",This); - return This->RefCount; -} - -HRESULT WINAPI CStdStubBuffer_DebugServerQueryInterface(LPRPCSTUBBUFFER iface, - LPVOID *ppv) -{ - CStdStubBuffer *This = (CStdStubBuffer *)iface; - TRACE("(%p)->DebugServerQueryInterface(%p)\n",This,ppv); - return S_OK; -} - -void WINAPI CStdStubBuffer_DebugServerRelease(LPRPCSTUBBUFFER iface, - LPVOID pv) -{ - CStdStubBuffer *This = (CStdStubBuffer *)iface; - TRACE("(%p)->DebugServerRelease(%p)\n",This,pv); -} - -const IRpcStubBufferVtbl CStdStubBuffer_Vtbl = -{ - CStdStubBuffer_QueryInterface, - CStdStubBuffer_AddRef, - NULL, - CStdStubBuffer_Connect, - CStdStubBuffer_Disconnect, - CStdStubBuffer_Invoke, - CStdStubBuffer_IsIIDSupported, - CStdStubBuffer_CountRefs, - CStdStubBuffer_DebugServerQueryInterface, - CStdStubBuffer_DebugServerRelease -}; - -static HRESULT WINAPI CStdStubBuffer_Delegating_Connect(LPRPCSTUBBUFFER iface, - LPUNKNOWN lpUnkServer) -{ - cstdstubbuffer_delegating_t *This = impl_from_delegating(iface); - HRESULT r; - TRACE("(%p)->Connect(%p)\n", This, lpUnkServer); - - r = CStdStubBuffer_Connect(iface, lpUnkServer); - if(SUCCEEDED(r)) - r = IRpcStubBuffer_Connect(This->base_stub, (IUnknown*)&This->base_obj); - - return r; -} - -static void WINAPI CStdStubBuffer_Delegating_Disconnect(LPRPCSTUBBUFFER iface) -{ - cstdstubbuffer_delegating_t *This = impl_from_delegating(iface); - TRACE("(%p)->Disconnect()\n", This); - - IRpcStubBuffer_Disconnect(This->base_stub); - CStdStubBuffer_Disconnect(iface); -} - -static ULONG WINAPI CStdStubBuffer_Delegating_CountRefs(LPRPCSTUBBUFFER iface) -{ - cstdstubbuffer_delegating_t *This = impl_from_delegating(iface); - ULONG ret; - TRACE("(%p)->CountRefs()\n", This); - - ret = CStdStubBuffer_CountRefs(iface); - ret += IRpcStubBuffer_CountRefs(This->base_stub); - - return ret; -} - -const IRpcStubBufferVtbl CStdStubBuffer_Delegating_Vtbl = -{ - CStdStubBuffer_QueryInterface, - CStdStubBuffer_AddRef, - NULL, - CStdStubBuffer_Delegating_Connect, - CStdStubBuffer_Delegating_Disconnect, - CStdStubBuffer_Invoke, - CStdStubBuffer_IsIIDSupported, - CStdStubBuffer_Delegating_CountRefs, - CStdStubBuffer_DebugServerQueryInterface, - CStdStubBuffer_DebugServerRelease -}; - -const MIDL_SERVER_INFO *CStdStubBuffer_GetServerInfo(IRpcStubBuffer *iface) -{ - CStdStubBuffer *This = (CStdStubBuffer *)iface; - return STUB_HEADER(This).pServerInfo; -} - -/************************************************************************ - * NdrStubForwardingFunction [RPCRT4.@] - */ -void __RPC_STUB NdrStubForwardingFunction( IRpcStubBuffer *iface, IRpcChannelBuffer *pChannel, - PRPC_MESSAGE pMsg, DWORD *pdwStubPhase ) -{ - /* Note pMsg is passed intact since RPCOLEMESSAGE is basically a RPC_MESSAGE. */ - - cstdstubbuffer_delegating_t *This = impl_from_delegating(iface); - HRESULT r = IRpcStubBuffer_Invoke(This->base_stub, (RPCOLEMESSAGE*)pMsg, pChannel); - if(FAILED(r)) RpcRaiseException(r); - return; -} - -/*********************************************************************** - * NdrStubInitialize [RPCRT4.@] - */ -void WINAPI NdrStubInitialize(PRPC_MESSAGE pRpcMsg, - PMIDL_STUB_MESSAGE pStubMsg, - PMIDL_STUB_DESC pStubDescriptor, - LPRPCCHANNELBUFFER pRpcChannelBuffer) -{ - TRACE("(%p,%p,%p,%p)\n", pRpcMsg, pStubMsg, pStubDescriptor, pRpcChannelBuffer); - NdrServerInitializeNew(pRpcMsg, pStubMsg, pStubDescriptor); - pStubMsg->pRpcChannelBuffer = pRpcChannelBuffer; - IRpcChannelBuffer_GetDestCtx(pStubMsg->pRpcChannelBuffer, - &pStubMsg->dwDestContext, - &pStubMsg->pvDestContext); -} - -/*********************************************************************** - * NdrStubGetBuffer [RPCRT4.@] - */ -void WINAPI NdrStubGetBuffer(LPRPCSTUBBUFFER iface, - LPRPCCHANNELBUFFER pRpcChannelBuffer, - PMIDL_STUB_MESSAGE pStubMsg) -{ - CStdStubBuffer *This = (CStdStubBuffer *)iface; - HRESULT hr; - - TRACE("(%p, %p, %p)\n", This, pRpcChannelBuffer, pStubMsg); - - pStubMsg->RpcMsg->BufferLength = pStubMsg->BufferLength; - hr = IRpcChannelBuffer_GetBuffer(pRpcChannelBuffer, - (RPCOLEMESSAGE *)pStubMsg->RpcMsg, STUB_HEADER(This).piid); - if (FAILED(hr)) - { - RpcRaiseException(hr); - return; - } - - pStubMsg->Buffer = pStubMsg->RpcMsg->Buffer; -} +/* + * COM stub (CStdStubBuffer) implementation + * + * Copyright 2001 Ove Kåven, TransGaming Technologies + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include + +#define COBJMACROS + +#include "windef.h" +#include "winbase.h" +#include "winerror.h" +#include "excpt.h" + +#include "objbase.h" +#include "rpcproxy.h" + +#include "wine/debug.h" +#include "wine/exception.h" + +#include "cpsf.h" + +WINE_DEFAULT_DEBUG_CHANNEL(ole); + +#define STUB_HEADER(This) (((const CInterfaceStubHeader*)((This)->lpVtbl))[-1]) + +static WINE_EXCEPTION_FILTER(stub_filter) +{ + if (GetExceptionInformation()->ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE) + return EXCEPTION_CONTINUE_SEARCH; + return EXCEPTION_EXECUTE_HANDLER; +} + +typedef struct +{ + IUnknownVtbl *base_obj; + IRpcStubBuffer *base_stub; + CStdStubBuffer stub_buffer; +} cstdstubbuffer_delegating_t; + +static inline cstdstubbuffer_delegating_t *impl_from_delegating( IRpcStubBuffer *iface ) +{ + return (cstdstubbuffer_delegating_t*)((char *)iface - FIELD_OFFSET(cstdstubbuffer_delegating_t, stub_buffer)); +} + +HRESULT WINAPI CStdStubBuffer_Construct(REFIID riid, + LPUNKNOWN pUnkServer, + PCInterfaceName name, + CInterfaceStubVtbl *vtbl, + LPPSFACTORYBUFFER pPSFactory, + LPRPCSTUBBUFFER *ppStub) +{ + CStdStubBuffer *This; + IUnknown *pvServer; + HRESULT r; + TRACE("(%p,%p,%p,%p) %s\n", pUnkServer, vtbl, pPSFactory, ppStub, name); + TRACE("iid=%s\n", debugstr_guid(vtbl->header.piid)); + TRACE("vtbl=%p\n", &vtbl->Vtbl); + + if (!IsEqualGUID(vtbl->header.piid, riid)) { + ERR("IID mismatch during stub creation\n"); + return RPC_E_UNEXPECTED; + } + + r = IUnknown_QueryInterface(pUnkServer, riid, (void**)&pvServer); + if(FAILED(r)) + return r; + + This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(CStdStubBuffer)); + if (!This) { + IUnknown_Release(pvServer); + return E_OUTOFMEMORY; + } + + This->lpVtbl = &vtbl->Vtbl; + This->RefCount = 1; + This->pvServerObject = pvServer; + This->pPSFactory = pPSFactory; + *ppStub = (LPRPCSTUBBUFFER)This; + + IPSFactoryBuffer_AddRef(pPSFactory); + return S_OK; +} + +static CRITICAL_SECTION delegating_vtbl_section; +static CRITICAL_SECTION_DEBUG critsect_debug = +{ + 0, 0, &delegating_vtbl_section, + { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList }, + 0, 0, { (DWORD_PTR)(__FILE__ ": delegating_vtbl_section") } +}; +static CRITICAL_SECTION delegating_vtbl_section = { &critsect_debug, -1, 0, 0, 0, 0 }; + +typedef struct +{ + DWORD ref; + DWORD size; + void **methods; + IUnknownVtbl vtbl; + /* remaining entries in vtbl */ +} ref_counted_vtbl; + +static struct +{ + ref_counted_vtbl *table; +} current_vtbl; + + +static HRESULT WINAPI delegating_QueryInterface(IUnknown *pUnk, REFIID iid, void **ppv) +{ + *ppv = (void *)pUnk; + return S_OK; +} + +static ULONG WINAPI delegating_AddRef(IUnknown *pUnk) +{ + return 1; +} + +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. +*/ +#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 */ +} vtbl_method_t; +#include "poppack.h" + +static void fill_table(IUnknownVtbl *vtbl, void **methods, DWORD num) +{ + vtbl_method_t *method; + void **entry; + DWORD i; + + vtbl->QueryInterface = delegating_QueryInterface; + vtbl->AddRef = delegating_AddRef; + vtbl->Release = delegating_Release; + + method = (vtbl_method_t*)methods; + entry = (void**)(vtbl + 1); + + for(i = 3; i < num; i++) + { + *entry = method; + method->mov1 = 0x0424448b; + method->mov2 = 0x408b; + method->sixteen = 0x10; + method->mov3 = 0x04244489; + method->mov4 = 0x008b; + method->mov5 = 0x808b; + method->offset = i << 2; + method->jmp = 0xe0ff; + method->pad[0] = 0x8d; + method->pad[1] = 0x76; + method->pad[2] = 0x00; + + method++; + entry++; + } +} + +#else /* __i386__ */ + +typedef struct {int dummy;} vtbl_method_t; +static void fill_table(IUnknownVtbl *vtbl, DWORD num) +{ + ERR("delegated stubs are not supported on this architecture\n"); +} + +#endif /* __i386__ */ + +void create_delegating_vtbl(DWORD num_methods) +{ + TRACE("%d\n", num_methods); + if(num_methods <= 3) + { + ERR("should have more than %d methods\n", num_methods); + return; + } + + EnterCriticalSection(&delegating_vtbl_section); + if(!current_vtbl.table || num_methods > current_vtbl.table->size) + { + DWORD size; + DWORD old_protect; + if(current_vtbl.table && current_vtbl.table->ref == 0) + { + TRACE("freeing old table\n"); + VirtualFree(current_vtbl.table->methods, + (current_vtbl.table->size - 3) * sizeof(vtbl_method_t), + MEM_RELEASE); + HeapFree(GetProcessHeap(), 0, current_vtbl.table); + } + size = (num_methods - 3) * sizeof(vtbl_method_t); + current_vtbl.table = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(ref_counted_vtbl, vtbl) + num_methods * sizeof(void*)); + current_vtbl.table->ref = 0; + current_vtbl.table->size = num_methods; + current_vtbl.table->methods = VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); + fill_table(¤t_vtbl.table->vtbl, current_vtbl.table->methods, num_methods); + VirtualProtect(current_vtbl.table->methods, size, PAGE_EXECUTE_READ, &old_protect); + } + LeaveCriticalSection(&delegating_vtbl_section); +} + +static IUnknownVtbl *get_delegating_vtbl(void) +{ + IUnknownVtbl *ret; + + EnterCriticalSection(&delegating_vtbl_section); + current_vtbl.table->ref++; + ret = ¤t_vtbl.table->vtbl; + LeaveCriticalSection(&delegating_vtbl_section); + return ret; +} + +static void release_delegating_vtbl(IUnknownVtbl *vtbl) +{ + ref_counted_vtbl *table = (ref_counted_vtbl*)((DWORD *)vtbl - 1); + + EnterCriticalSection(&delegating_vtbl_section); + table->ref--; + TRACE("ref now %d\n", table->ref); + if(table->ref == 0 && table != current_vtbl.table) + { + TRACE("... and we're not current so free'ing\n"); + VirtualFree(current_vtbl.table->methods, + (current_vtbl.table->size - 3) * sizeof(vtbl_method_t), + MEM_RELEASE); + HeapFree(GetProcessHeap(), 0, table); + } + LeaveCriticalSection(&delegating_vtbl_section); +} + +HRESULT WINAPI CStdStubBuffer_Delegating_Construct(REFIID riid, + LPUNKNOWN pUnkServer, + PCInterfaceName name, + CInterfaceStubVtbl *vtbl, + REFIID delegating_iid, + LPPSFACTORYBUFFER pPSFactory, + LPRPCSTUBBUFFER *ppStub) +{ + cstdstubbuffer_delegating_t *This; + IUnknown *pvServer; + HRESULT r; + + TRACE("(%p,%p,%p,%p) %s\n", pUnkServer, vtbl, pPSFactory, ppStub, name); + TRACE("iid=%s delegating to %s\n", debugstr_guid(vtbl->header.piid), debugstr_guid(delegating_iid)); + TRACE("vtbl=%p\n", &vtbl->Vtbl); + + if (!IsEqualGUID(vtbl->header.piid, riid)) + { + ERR("IID mismatch during stub creation\n"); + return RPC_E_UNEXPECTED; + } + + r = IUnknown_QueryInterface(pUnkServer, riid, (void**)&pvServer); + if(FAILED(r)) return r; + + This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This)); + if (!This) + { + IUnknown_Release(pvServer); + return E_OUTOFMEMORY; + } + + This->base_obj = get_delegating_vtbl(); + r = create_stub(delegating_iid, (IUnknown*)&This->base_obj, &This->base_stub); + if(FAILED(r)) + { + release_delegating_vtbl(This->base_obj); + HeapFree(GetProcessHeap(), 0, This); + IUnknown_Release(pvServer); + return r; + } + + This->stub_buffer.lpVtbl = &vtbl->Vtbl; + This->stub_buffer.RefCount = 1; + This->stub_buffer.pvServerObject = pvServer; + This->stub_buffer.pPSFactory = pPSFactory; + *ppStub = (LPRPCSTUBBUFFER)&This->stub_buffer; + + IPSFactoryBuffer_AddRef(pPSFactory); + return S_OK; +} + +HRESULT WINAPI CStdStubBuffer_QueryInterface(LPRPCSTUBBUFFER iface, + REFIID riid, + LPVOID *obj) +{ + CStdStubBuffer *This = (CStdStubBuffer *)iface; + TRACE("(%p)->QueryInterface(%s,%p)\n",This,debugstr_guid(riid),obj); + + if (IsEqualIID(&IID_IUnknown, riid) || + IsEqualIID(&IID_IRpcStubBuffer, riid)) + { + IUnknown_AddRef(iface); + *obj = iface; + return S_OK; + } + *obj = NULL; + return E_NOINTERFACE; +} + +ULONG WINAPI CStdStubBuffer_AddRef(LPRPCSTUBBUFFER iface) +{ + CStdStubBuffer *This = (CStdStubBuffer *)iface; + TRACE("(%p)->AddRef()\n",This); + return InterlockedIncrement(&This->RefCount); +} + +ULONG WINAPI NdrCStdStubBuffer_Release(LPRPCSTUBBUFFER iface, + LPPSFACTORYBUFFER pPSF) +{ + CStdStubBuffer *This = (CStdStubBuffer *)iface; + ULONG refs; + + TRACE("(%p)->Release()\n",This); + + refs = InterlockedDecrement(&This->RefCount); + if (!refs) + { + /* test_Release shows that native doesn't call Disconnect here. + We'll leave it in for the time being. */ + IRpcStubBuffer_Disconnect(iface); + + IPSFactoryBuffer_Release(pPSF); + HeapFree(GetProcessHeap(),0,This); + } + return refs; +} + +ULONG WINAPI NdrCStdStubBuffer2_Release(LPRPCSTUBBUFFER iface, + LPPSFACTORYBUFFER pPSF) +{ + cstdstubbuffer_delegating_t *This = impl_from_delegating( iface ); + ULONG refs; + + TRACE("(%p)->Release()\n", This); + + refs = InterlockedDecrement(&This->stub_buffer.RefCount); + if (!refs) + { + /* Just like NdrCStdStubBuffer_Release, we shouldn't call + Disconnect here */ + IRpcStubBuffer_Disconnect((IRpcStubBuffer *)&This->stub_buffer); + + IRpcStubBuffer_Release(This->base_stub); + release_delegating_vtbl(This->base_obj); + + IPSFactoryBuffer_Release(pPSF); + HeapFree(GetProcessHeap(), 0, This); + } + + return refs; +} + +HRESULT WINAPI CStdStubBuffer_Connect(LPRPCSTUBBUFFER iface, + LPUNKNOWN lpUnkServer) +{ + CStdStubBuffer *This = (CStdStubBuffer *)iface; + HRESULT r; + IUnknown *new = NULL; + + TRACE("(%p)->Connect(%p)\n",This,lpUnkServer); + + r = IUnknown_QueryInterface(lpUnkServer, STUB_HEADER(This).piid, (void**)&new); + new = InterlockedExchangePointer((void**)&This->pvServerObject, new); + if(new) + IUnknown_Release(new); + return r; +} + +void WINAPI CStdStubBuffer_Disconnect(LPRPCSTUBBUFFER iface) +{ + CStdStubBuffer *This = (CStdStubBuffer *)iface; + IUnknown *old; + TRACE("(%p)->Disconnect()\n",This); + + old = InterlockedExchangePointer((void**)&This->pvServerObject, NULL); + + if(old) + IUnknown_Release(old); +} + +HRESULT WINAPI CStdStubBuffer_Invoke(LPRPCSTUBBUFFER iface, + PRPCOLEMESSAGE pMsg, + LPRPCCHANNELBUFFER pChannel) +{ + CStdStubBuffer *This = (CStdStubBuffer *)iface; + DWORD dwPhase = STUB_UNMARSHAL; + HRESULT hr = S_OK; + + TRACE("(%p)->Invoke(%p,%p)\n",This,pMsg,pChannel); + + __TRY + { + if (STUB_HEADER(This).pDispatchTable) + STUB_HEADER(This).pDispatchTable[pMsg->iMethod](iface, pChannel, (PRPC_MESSAGE)pMsg, &dwPhase); + else /* pure interpreted */ + NdrStubCall2(iface, pChannel, (PRPC_MESSAGE)pMsg, &dwPhase); + } + __EXCEPT(stub_filter) + { + DWORD dwExceptionCode = GetExceptionCode(); + WARN("a stub call failed with exception 0x%08x (%d)\n", dwExceptionCode, dwExceptionCode); + if (FAILED(dwExceptionCode)) + hr = dwExceptionCode; + else + hr = HRESULT_FROM_WIN32(dwExceptionCode); + } + __ENDTRY + + return hr; +} + +LPRPCSTUBBUFFER WINAPI CStdStubBuffer_IsIIDSupported(LPRPCSTUBBUFFER iface, + REFIID riid) +{ + CStdStubBuffer *This = (CStdStubBuffer *)iface; + TRACE("(%p)->IsIIDSupported(%s)\n",This,debugstr_guid(riid)); + return IsEqualGUID(STUB_HEADER(This).piid, riid) ? iface : NULL; +} + +ULONG WINAPI CStdStubBuffer_CountRefs(LPRPCSTUBBUFFER iface) +{ + CStdStubBuffer *This = (CStdStubBuffer *)iface; + TRACE("(%p)->CountRefs()\n",This); + return This->RefCount; +} + +HRESULT WINAPI CStdStubBuffer_DebugServerQueryInterface(LPRPCSTUBBUFFER iface, + LPVOID *ppv) +{ + CStdStubBuffer *This = (CStdStubBuffer *)iface; + TRACE("(%p)->DebugServerQueryInterface(%p)\n",This,ppv); + return S_OK; +} + +void WINAPI CStdStubBuffer_DebugServerRelease(LPRPCSTUBBUFFER iface, + LPVOID pv) +{ + CStdStubBuffer *This = (CStdStubBuffer *)iface; + TRACE("(%p)->DebugServerRelease(%p)\n",This,pv); +} + +const IRpcStubBufferVtbl CStdStubBuffer_Vtbl = +{ + CStdStubBuffer_QueryInterface, + CStdStubBuffer_AddRef, + NULL, + CStdStubBuffer_Connect, + CStdStubBuffer_Disconnect, + CStdStubBuffer_Invoke, + CStdStubBuffer_IsIIDSupported, + CStdStubBuffer_CountRefs, + CStdStubBuffer_DebugServerQueryInterface, + CStdStubBuffer_DebugServerRelease +}; + +static HRESULT WINAPI CStdStubBuffer_Delegating_Connect(LPRPCSTUBBUFFER iface, + LPUNKNOWN lpUnkServer) +{ + cstdstubbuffer_delegating_t *This = impl_from_delegating(iface); + HRESULT r; + TRACE("(%p)->Connect(%p)\n", This, lpUnkServer); + + r = CStdStubBuffer_Connect(iface, lpUnkServer); + if(SUCCEEDED(r)) + r = IRpcStubBuffer_Connect(This->base_stub, (IUnknown*)&This->base_obj); + + return r; +} + +static void WINAPI CStdStubBuffer_Delegating_Disconnect(LPRPCSTUBBUFFER iface) +{ + cstdstubbuffer_delegating_t *This = impl_from_delegating(iface); + TRACE("(%p)->Disconnect()\n", This); + + IRpcStubBuffer_Disconnect(This->base_stub); + CStdStubBuffer_Disconnect(iface); +} + +static ULONG WINAPI CStdStubBuffer_Delegating_CountRefs(LPRPCSTUBBUFFER iface) +{ + cstdstubbuffer_delegating_t *This = impl_from_delegating(iface); + ULONG ret; + TRACE("(%p)->CountRefs()\n", This); + + ret = CStdStubBuffer_CountRefs(iface); + ret += IRpcStubBuffer_CountRefs(This->base_stub); + + return ret; +} + +const IRpcStubBufferVtbl CStdStubBuffer_Delegating_Vtbl = +{ + CStdStubBuffer_QueryInterface, + CStdStubBuffer_AddRef, + NULL, + CStdStubBuffer_Delegating_Connect, + CStdStubBuffer_Delegating_Disconnect, + CStdStubBuffer_Invoke, + CStdStubBuffer_IsIIDSupported, + CStdStubBuffer_Delegating_CountRefs, + CStdStubBuffer_DebugServerQueryInterface, + CStdStubBuffer_DebugServerRelease +}; + +const MIDL_SERVER_INFO *CStdStubBuffer_GetServerInfo(IRpcStubBuffer *iface) +{ + CStdStubBuffer *This = (CStdStubBuffer *)iface; + return STUB_HEADER(This).pServerInfo; +} + +/************************************************************************ + * NdrStubForwardingFunction [RPCRT4.@] + */ +void __RPC_STUB NdrStubForwardingFunction( IRpcStubBuffer *iface, IRpcChannelBuffer *pChannel, + PRPC_MESSAGE pMsg, DWORD *pdwStubPhase ) +{ + /* Note pMsg is passed intact since RPCOLEMESSAGE is basically a RPC_MESSAGE. */ + + cstdstubbuffer_delegating_t *This = impl_from_delegating(iface); + HRESULT r = IRpcStubBuffer_Invoke(This->base_stub, (RPCOLEMESSAGE*)pMsg, pChannel); + if(FAILED(r)) RpcRaiseException(r); + return; +} + +/*********************************************************************** + * NdrStubInitialize [RPCRT4.@] + */ +void WINAPI NdrStubInitialize(PRPC_MESSAGE pRpcMsg, + PMIDL_STUB_MESSAGE pStubMsg, + PMIDL_STUB_DESC pStubDescriptor, + LPRPCCHANNELBUFFER pRpcChannelBuffer) +{ + TRACE("(%p,%p,%p,%p)\n", pRpcMsg, pStubMsg, pStubDescriptor, pRpcChannelBuffer); + NdrServerInitializeNew(pRpcMsg, pStubMsg, pStubDescriptor); + pStubMsg->pRpcChannelBuffer = pRpcChannelBuffer; + IRpcChannelBuffer_GetDestCtx(pStubMsg->pRpcChannelBuffer, + &pStubMsg->dwDestContext, + &pStubMsg->pvDestContext); +} + +/*********************************************************************** + * NdrStubGetBuffer [RPCRT4.@] + */ +void WINAPI NdrStubGetBuffer(LPRPCSTUBBUFFER iface, + LPRPCCHANNELBUFFER pRpcChannelBuffer, + PMIDL_STUB_MESSAGE pStubMsg) +{ + CStdStubBuffer *This = (CStdStubBuffer *)iface; + HRESULT hr; + + TRACE("(%p, %p, %p)\n", This, pRpcChannelBuffer, pStubMsg); + + pStubMsg->RpcMsg->BufferLength = pStubMsg->BufferLength; + hr = IRpcChannelBuffer_GetBuffer(pRpcChannelBuffer, + (RPCOLEMESSAGE *)pStubMsg->RpcMsg, STUB_HEADER(This).piid); + if (FAILED(hr)) + { + RpcRaiseException(hr); + return; + } + + pStubMsg->Buffer = pStubMsg->RpcMsg->Buffer; +} diff --git a/reactos/dll/win32/rpcrt4_new/epm_towers.h b/reactos/dll/win32/rpcrt4_new/epm_towers.h index 9c58ff0c3dd..7570cc2e846 100644 --- a/reactos/dll/win32/rpcrt4_new/epm_towers.h +++ b/reactos/dll/win32/rpcrt4_new/epm_towers.h @@ -1,88 +1,88 @@ -/* - * Endpoint Mapper Tower Definitions - * - * Copyright 2006 Robert Shearman (for CodeWeavers) - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - * - */ - -#define EPM_PROTOCOL_DNET_NSP 0x04 -#define EPM_PROTOCOL_OSI_TP4 0x05 -#define EPM_PROTOCOL_OSI_CLNS 0x06 -#define EPM_PROTOCOL_TCP 0x07 -#define EPM_PROTOCOL_UDP 0x08 -#define EPM_PROTOCOL_IP 0x09 -#define EPM_PROTOCOL_NCADG 0x0a /* Connectionless RPC */ -#define EPM_PROTOCOL_NCACN 0x0b -#define EPM_PROTOCOL_NCALRPC 0x0c /* Local RPC */ -#define EPM_PROTOCOL_UUID 0x0d -#define EPM_PROTOCOL_IPX 0x0e -#define EPM_PROTOCOL_SMB 0x0f -#define EPM_PROTOCOL_PIPE 0x10 -#define EPM_PROTOCOL_NETBIOS 0x11 -#define EPM_PROTOCOL_NETBEUI 0x12 -#define EPM_PROTOCOL_SPX 0x13 -#define EPM_PROTOCOL_NB_IPX 0x14 /* NetBIOS over IPX */ -#define EPM_PROTOCOL_DSP 0x16 /* AppleTalk Data Stream Protocol */ -#define EPM_PROTOCOL_DDP 0x17 /* AppleTalk Data Datagram Protocol */ -#define EPM_PROTOCOL_APPLETALK 0x18 /* AppleTalk */ -#define EPM_PROTOCOL_VINES_SPP 0x1a -#define EPM_PROTOCOL_VINES_IPC 0x1b /* Inter Process Communication */ -#define EPM_PROTOCOL_STREETTALK 0x1c /* Vines Streettalk */ -#define EPM_PROTOCOL_HTTP 0x1f -#define EPM_PROTOCOL_UNIX_DS 0x20 /* Unix domain socket */ -#define EPM_PROTOCOL_NULL 0x21 - -#include - -typedef unsigned char u_int8; -typedef unsigned short u_int16; -typedef unsigned int u_int32; - -typedef struct -{ - u_int16 count_lhs; - u_int8 protid; - GUID uuid; - u_int16 major_version; - u_int16 count_rhs; - u_int16 minor_version; -} twr_uuid_floor_t; - -typedef struct -{ - u_int16 count_lhs; - u_int8 protid; - u_int16 count_rhs; - u_int16 port; -} twr_tcp_floor_t; - -typedef struct -{ - u_int16 count_lhs; - u_int8 protid; - u_int16 count_rhs; - u_int32 ipv4addr; -} twr_ipv4_floor_t; - -typedef struct -{ - u_int16 count_lhs; - u_int8 protid; - u_int16 count_rhs; -} twr_empty_floor_t; - -#include +/* + * Endpoint Mapper Tower Definitions + * + * Copyright 2006 Robert Shearman (for CodeWeavers) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + * + */ + +#define EPM_PROTOCOL_DNET_NSP 0x04 +#define EPM_PROTOCOL_OSI_TP4 0x05 +#define EPM_PROTOCOL_OSI_CLNS 0x06 +#define EPM_PROTOCOL_TCP 0x07 +#define EPM_PROTOCOL_UDP 0x08 +#define EPM_PROTOCOL_IP 0x09 +#define EPM_PROTOCOL_NCADG 0x0a /* Connectionless RPC */ +#define EPM_PROTOCOL_NCACN 0x0b +#define EPM_PROTOCOL_NCALRPC 0x0c /* Local RPC */ +#define EPM_PROTOCOL_UUID 0x0d +#define EPM_PROTOCOL_IPX 0x0e +#define EPM_PROTOCOL_SMB 0x0f +#define EPM_PROTOCOL_PIPE 0x10 +#define EPM_PROTOCOL_NETBIOS 0x11 +#define EPM_PROTOCOL_NETBEUI 0x12 +#define EPM_PROTOCOL_SPX 0x13 +#define EPM_PROTOCOL_NB_IPX 0x14 /* NetBIOS over IPX */ +#define EPM_PROTOCOL_DSP 0x16 /* AppleTalk Data Stream Protocol */ +#define EPM_PROTOCOL_DDP 0x17 /* AppleTalk Data Datagram Protocol */ +#define EPM_PROTOCOL_APPLETALK 0x18 /* AppleTalk */ +#define EPM_PROTOCOL_VINES_SPP 0x1a +#define EPM_PROTOCOL_VINES_IPC 0x1b /* Inter Process Communication */ +#define EPM_PROTOCOL_STREETTALK 0x1c /* Vines Streettalk */ +#define EPM_PROTOCOL_HTTP 0x1f +#define EPM_PROTOCOL_UNIX_DS 0x20 /* Unix domain socket */ +#define EPM_PROTOCOL_NULL 0x21 + +#include + +typedef unsigned char u_int8; +typedef unsigned short u_int16; +typedef unsigned int u_int32; + +typedef struct +{ + u_int16 count_lhs; + u_int8 protid; + GUID uuid; + u_int16 major_version; + u_int16 count_rhs; + u_int16 minor_version; +} twr_uuid_floor_t; + +typedef struct +{ + u_int16 count_lhs; + u_int8 protid; + u_int16 count_rhs; + u_int16 port; +} twr_tcp_floor_t; + +typedef struct +{ + u_int16 count_lhs; + u_int8 protid; + u_int16 count_rhs; + u_int32 ipv4addr; +} twr_ipv4_floor_t; + +typedef struct +{ + u_int16 count_lhs; + u_int8 protid; + u_int16 count_rhs; +} twr_empty_floor_t; + +#include diff --git a/reactos/dll/win32/rpcrt4_new/ncastatus.h b/reactos/dll/win32/rpcrt4_new/ncastatus.h index 2c054236423..0a9700268e2 100644 --- a/reactos/dll/win32/rpcrt4_new/ncastatus.h +++ b/reactos/dll/win32/rpcrt4_new/ncastatus.h @@ -1,66 +1,66 @@ -/* - * NCA Status definitions - * - * Copyright 2007 Robert Shearman - * - * 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 NCA_S_COMM_FAILURE 0x1C010001 -#define NCA_S_OP_RNG_ERROR 0x1C010002 -#define NCA_S_UNK_IF 0x1C010003 -#define NCA_S_WRONG_BOOT_TIME 0x1C010006 -#define NCA_S_YOU_CRASHED 0x1C010009 -#define NCA_S_PROTO_ERROR 0x1C01000B -#define NCA_S_OUT_ARGS_TOO_BIG 0x1C010013 -#define NCA_S_SERVER_TOO_BUSY 0x1C010014 -#define NCA_S_FAULT_STRING_TOO_LONG 0x1C010015 -#define NCA_S_UNSUPPORTED_TYPE 0x1C010017 - -#define NCA_S_FAULT_INT_DIV_BY_ZERO 0x1C000001 -#define NCA_S_FAULT_ADDR_ERROR 0x1C000002 -#define NCA_S_FAULT_FP_DIV_ZERO 0x1C000003 -#define NCA_S_FAULT_FP_UNDERFLOW 0x1C000004 -#define NCA_S_FAULT_FP_OVERFLOW 0x1C000005 -#define NCA_S_FAULT_INVALID_TAG 0x1C000006 -#define NCA_S_FAULT_INVALID_BOUND 0x1C000007 -#define NCA_S_RPC_VERSION_MISMATCH 0x1C000008 -#define NCA_S_UNSPEC_REJECT 0x1C000009 -#define NCA_S_BAD_ACTID 0x1C00000A -#define NCA_S_WHO_ARE_YOU_FAILED 0x1C00000B -#define NCA_S_MANAGER_NOT_ENTERED 0x1C00000C -#define NCA_S_FAULT_CANCEL 0x1C00000D -#define NCA_S_FAULT_ILL_INST 0x1C00000E -#define NCA_S_FAULT_FP_ERROR 0x1C00000F -#define NCA_S_FAULT_INT_OVERFLOW 0x1C000010 -#define NCA_S_FAULT_UNSPEC 0x1C000012 -#define NCA_S_FAULT_REMOTE_COMM_FAILURE 0x1C000013 -#define NCA_S_FAULT_PIPE_EMPTY 0x1C000014 -#define NCA_S_FAULT_PIPE_CLOSED 0x1C000015 -#define NCA_S_FAULT_PIPE_ORDER 0x1C000016 -#define NCA_S_FAULT_PIPE_DISCIPLINE 0x1C000017 -#define NCA_S_FAULT_PIPE_COMM_ERROR 0x1C000018 -#define NCA_S_FAULT_PIPE_MEMORY 0x1C000019 -#define NCA_S_FAULT_CONTEXT_MISMATCH 0x1C00001A -#define NCA_S_FAULT_REMOTE_NO_MEMORY 0x1C00001B -#define NCA_S_INVALID_PRES_CONTEXT_ID 0x1C00001C -#define NCA_S_UNSUPPORTED_AUTHN_LEVEL 0x1C00001D -#define NCA_S_INVALID_CHECKSUM 0x1C00001F -#define NCA_S_INVALID_CRC 0x1C000020 -#define NCA_S_FAULT_USER_DEFINED 0x1C000021 -#define NCA_S_FAULT_TX_OPEN_FAILED 0x1C000022 -#define NCA_S_FAULT_CODESET_CONV_ERROR 0x1C000023 -#define NCA_S_FAULT_OBJECT_NOT_FOUND 0x1C000024 -#define NCA_S_FAULT_NO_CLIENT_STUB 0x1C000025 +/* + * NCA Status definitions + * + * Copyright 2007 Robert Shearman + * + * 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 NCA_S_COMM_FAILURE 0x1C010001 +#define NCA_S_OP_RNG_ERROR 0x1C010002 +#define NCA_S_UNK_IF 0x1C010003 +#define NCA_S_WRONG_BOOT_TIME 0x1C010006 +#define NCA_S_YOU_CRASHED 0x1C010009 +#define NCA_S_PROTO_ERROR 0x1C01000B +#define NCA_S_OUT_ARGS_TOO_BIG 0x1C010013 +#define NCA_S_SERVER_TOO_BUSY 0x1C010014 +#define NCA_S_FAULT_STRING_TOO_LONG 0x1C010015 +#define NCA_S_UNSUPPORTED_TYPE 0x1C010017 + +#define NCA_S_FAULT_INT_DIV_BY_ZERO 0x1C000001 +#define NCA_S_FAULT_ADDR_ERROR 0x1C000002 +#define NCA_S_FAULT_FP_DIV_ZERO 0x1C000003 +#define NCA_S_FAULT_FP_UNDERFLOW 0x1C000004 +#define NCA_S_FAULT_FP_OVERFLOW 0x1C000005 +#define NCA_S_FAULT_INVALID_TAG 0x1C000006 +#define NCA_S_FAULT_INVALID_BOUND 0x1C000007 +#define NCA_S_RPC_VERSION_MISMATCH 0x1C000008 +#define NCA_S_UNSPEC_REJECT 0x1C000009 +#define NCA_S_BAD_ACTID 0x1C00000A +#define NCA_S_WHO_ARE_YOU_FAILED 0x1C00000B +#define NCA_S_MANAGER_NOT_ENTERED 0x1C00000C +#define NCA_S_FAULT_CANCEL 0x1C00000D +#define NCA_S_FAULT_ILL_INST 0x1C00000E +#define NCA_S_FAULT_FP_ERROR 0x1C00000F +#define NCA_S_FAULT_INT_OVERFLOW 0x1C000010 +#define NCA_S_FAULT_UNSPEC 0x1C000012 +#define NCA_S_FAULT_REMOTE_COMM_FAILURE 0x1C000013 +#define NCA_S_FAULT_PIPE_EMPTY 0x1C000014 +#define NCA_S_FAULT_PIPE_CLOSED 0x1C000015 +#define NCA_S_FAULT_PIPE_ORDER 0x1C000016 +#define NCA_S_FAULT_PIPE_DISCIPLINE 0x1C000017 +#define NCA_S_FAULT_PIPE_COMM_ERROR 0x1C000018 +#define NCA_S_FAULT_PIPE_MEMORY 0x1C000019 +#define NCA_S_FAULT_CONTEXT_MISMATCH 0x1C00001A +#define NCA_S_FAULT_REMOTE_NO_MEMORY 0x1C00001B +#define NCA_S_INVALID_PRES_CONTEXT_ID 0x1C00001C +#define NCA_S_UNSUPPORTED_AUTHN_LEVEL 0x1C00001D +#define NCA_S_INVALID_CHECKSUM 0x1C00001F +#define NCA_S_INVALID_CRC 0x1C000020 +#define NCA_S_FAULT_USER_DEFINED 0x1C000021 +#define NCA_S_FAULT_TX_OPEN_FAILED 0x1C000022 +#define NCA_S_FAULT_CODESET_CONV_ERROR 0x1C000023 +#define NCA_S_FAULT_OBJECT_NOT_FOUND 0x1C000024 +#define NCA_S_FAULT_NO_CLIENT_STUB 0x1C000025 diff --git a/reactos/dll/win32/rpcrt4_new/ndr_clientserver.c b/reactos/dll/win32/rpcrt4_new/ndr_clientserver.c index ab73e66d32e..809d4cb2968 100644 --- a/reactos/dll/win32/rpcrt4_new/ndr_clientserver.c +++ b/reactos/dll/win32/rpcrt4_new/ndr_clientserver.c @@ -1,227 +1,227 @@ -/* - * MIDL proxy/stub stuff - * - * Copyright 2002 Ove Kåven, TransGaming Technologies - * - * 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 - * - * TODO: - * - figure out whether we *really* got this right - * - check for errors and throw exceptions - */ - -#include -#include -#include -#include - -#define COBJMACROS - -#include "windef.h" -#include "winbase.h" -#include "winerror.h" - -#include "objbase.h" - -#include "rpcproxy.h" - -#include "wine/debug.h" - -#include "ndr_misc.h" -#include "rpcndr.h" - -WINE_DEFAULT_DEBUG_CHANNEL(rpc); - -/************************************************************************ - * NdrClientInitializeNew [RPCRT4.@] - */ -void WINAPI NdrClientInitializeNew( PRPC_MESSAGE pRpcMessage, PMIDL_STUB_MESSAGE pStubMsg, - PMIDL_STUB_DESC pStubDesc, unsigned int ProcNum ) -{ - TRACE("(pRpcMessage == ^%p, pStubMsg == ^%p, pStubDesc == ^%p, ProcNum == %d)\n", - pRpcMessage, pStubMsg, pStubDesc, ProcNum); - - pRpcMessage->Handle = NULL; - pRpcMessage->ProcNum = ProcNum; - pRpcMessage->RpcInterfaceInformation = pStubDesc->RpcInterfaceInformation; - pRpcMessage->RpcFlags = 0; - pRpcMessage->DataRepresentation = NDR_LOCAL_DATA_REPRESENTATION; - - pStubMsg->RpcMsg = pRpcMessage; - pStubMsg->BufferStart = NULL; - pStubMsg->BufferEnd = NULL; - pStubMsg->BufferLength = 0; - pStubMsg->IsClient = TRUE; - pStubMsg->ReuseBuffer = FALSE; - pStubMsg->pAllocAllNodesContext = NULL; - pStubMsg->pPointerQueueState = NULL; - pStubMsg->IgnoreEmbeddedPointers = 0; - pStubMsg->PointerBufferMark = NULL; - pStubMsg->fBufferValid = 0; - pStubMsg->uFlags = 0; - pStubMsg->pfnAllocate = pStubDesc->pfnAllocate; - pStubMsg->pfnFree = pStubDesc->pfnFree; - pStubMsg->StackTop = NULL; - pStubMsg->StubDesc = pStubDesc; - pStubMsg->FullPtrRefId = 0; - pStubMsg->PointerLength = 0; - pStubMsg->fInDontFree = 0; - pStubMsg->fDontCallFreeInst = 0; - pStubMsg->fInOnlyParam = 0; - pStubMsg->fHasReturn = 0; - pStubMsg->fHasExtensions = 0; - pStubMsg->fHasNewCorrDesc = 0; - pStubMsg->fUnused = 0; - pStubMsg->dwDestContext = MSHCTX_DIFFERENTMACHINE; - pStubMsg->pvDestContext = NULL; - pStubMsg->pRpcChannelBuffer = NULL; - pStubMsg->pArrayInfo = NULL; - pStubMsg->dwStubPhase = 0; - /* FIXME: LowStackMark */ - pStubMsg->pAsyncMsg = NULL; - pStubMsg->pCorrInfo = NULL; - pStubMsg->pCorrMemory = NULL; - pStubMsg->pMemoryList = NULL; -} - -/*********************************************************************** - * NdrServerInitializeNew [RPCRT4.@] - */ -unsigned char* WINAPI NdrServerInitializeNew( PRPC_MESSAGE pRpcMsg, PMIDL_STUB_MESSAGE pStubMsg, - PMIDL_STUB_DESC pStubDesc ) -{ - TRACE("(pRpcMsg == ^%p, pStubMsg == ^%p, pStubDesc == ^%p)\n", pRpcMsg, pStubMsg, pStubDesc); - - pStubMsg->RpcMsg = pRpcMsg; - pStubMsg->Buffer = pStubMsg->BufferStart = pRpcMsg->Buffer; - pStubMsg->BufferEnd = pStubMsg->Buffer + pRpcMsg->BufferLength; - pStubMsg->BufferLength = pRpcMsg->BufferLength; - pStubMsg->IsClient = FALSE; - pStubMsg->ReuseBuffer = FALSE; - pStubMsg->pAllocAllNodesContext = NULL; - pStubMsg->pPointerQueueState = NULL; - pStubMsg->IgnoreEmbeddedPointers = 0; - pStubMsg->PointerBufferMark = NULL; - pStubMsg->uFlags = 0; - pStubMsg->pfnAllocate = pStubDesc->pfnAllocate; - pStubMsg->pfnFree = pStubDesc->pfnFree; - pStubMsg->StackTop = NULL; - pStubMsg->StubDesc = pStubDesc; - pStubMsg->FullPtrXlatTables = NULL; - pStubMsg->FullPtrRefId = 0; - pStubMsg->PointerLength = 0; - pStubMsg->fInDontFree = 0; - pStubMsg->fDontCallFreeInst = 0; - pStubMsg->fInOnlyParam = 0; - pStubMsg->fHasReturn = 0; - pStubMsg->fHasExtensions = 0; - pStubMsg->fHasNewCorrDesc = 0; - pStubMsg->fUnused = 0; - pStubMsg->dwDestContext = MSHCTX_DIFFERENTMACHINE; - pStubMsg->pvDestContext = NULL; - pStubMsg->pRpcChannelBuffer = NULL; - pStubMsg->pArrayInfo = NULL; - pStubMsg->dwStubPhase = 0; - /* FIXME: LowStackMark */ - pStubMsg->pAsyncMsg = NULL; - pStubMsg->pCorrInfo = NULL; - pStubMsg->pCorrMemory = NULL; - pStubMsg->pMemoryList = NULL; - - return NULL; -} - -/*********************************************************************** - * NdrGetBuffer [RPCRT4.@] - */ -unsigned char *WINAPI NdrGetBuffer(PMIDL_STUB_MESSAGE stubmsg, ULONG buflen, RPC_BINDING_HANDLE handle) -{ - RPC_STATUS status; - - TRACE("(stubmsg == ^%p, buflen == %u, handle == %p)\n", stubmsg, buflen, handle); - - stubmsg->RpcMsg->Handle = handle; - stubmsg->RpcMsg->BufferLength = buflen; - - status = I_RpcGetBuffer(stubmsg->RpcMsg); - if (status != RPC_S_OK) - RpcRaiseException(status); - - stubmsg->Buffer = stubmsg->RpcMsg->Buffer; - stubmsg->fBufferValid = TRUE; - stubmsg->BufferLength = stubmsg->RpcMsg->BufferLength; - return stubmsg->Buffer; -} -/*********************************************************************** - * NdrFreeBuffer [RPCRT4.@] - */ -void WINAPI NdrFreeBuffer(PMIDL_STUB_MESSAGE pStubMsg) -{ - TRACE("(pStubMsg == ^%p)\n", pStubMsg); - if (pStubMsg->fBufferValid) - { - I_RpcFreeBuffer(pStubMsg->RpcMsg); - pStubMsg->fBufferValid = FALSE; - } -} - -/************************************************************************ - * NdrSendReceive [RPCRT4.@] - */ -unsigned char *WINAPI NdrSendReceive( PMIDL_STUB_MESSAGE stubmsg, unsigned char *buffer ) -{ - RPC_STATUS status; - - TRACE("(stubmsg == ^%p, buffer == ^%p)\n", stubmsg, buffer); - - /* FIXME: how to handle errors? (raise exception?) */ - if (!stubmsg) { - ERR("NULL stub message. No action taken.\n"); - return NULL; - } - if (!stubmsg->RpcMsg) { - ERR("RPC Message not present in stub message. No action taken.\n"); - return NULL; - } - - stubmsg->RpcMsg->BufferLength = buffer - (unsigned char *)stubmsg->RpcMsg->Buffer; - status = I_RpcSendReceive(stubmsg->RpcMsg); - if (status != RPC_S_OK) - RpcRaiseException(status); - - stubmsg->BufferLength = stubmsg->RpcMsg->BufferLength; - stubmsg->BufferStart = stubmsg->RpcMsg->Buffer; - stubmsg->BufferEnd = stubmsg->BufferStart + stubmsg->BufferLength; - stubmsg->Buffer = stubmsg->BufferStart; - - /* FIXME: is this the right return value? */ - return NULL; -} - -/************************************************************************ - * NdrMapCommAndFaultStatus [RPCRT4.@] - */ -RPC_STATUS RPC_ENTRY NdrMapCommAndFaultStatus( PMIDL_STUB_MESSAGE pStubMsg, - ULONG *pCommStatus, - ULONG *pFaultStatus, - RPC_STATUS Status ) -{ - FIXME("(%p, %p, %p, %ld): stub\n", pStubMsg, pCommStatus, pFaultStatus, Status); - - *pCommStatus = 0; - *pFaultStatus = 0; - - return RPC_S_OK; -} +/* + * MIDL proxy/stub stuff + * + * Copyright 2002 Ove Kåven, TransGaming Technologies + * + * 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 + * + * TODO: + * - figure out whether we *really* got this right + * - check for errors and throw exceptions + */ + +#include +#include +#include +#include + +#define COBJMACROS + +#include "windef.h" +#include "winbase.h" +#include "winerror.h" + +#include "objbase.h" + +#include "rpcproxy.h" + +#include "wine/debug.h" + +#include "ndr_misc.h" +#include "rpcndr.h" + +WINE_DEFAULT_DEBUG_CHANNEL(rpc); + +/************************************************************************ + * NdrClientInitializeNew [RPCRT4.@] + */ +void WINAPI NdrClientInitializeNew( PRPC_MESSAGE pRpcMessage, PMIDL_STUB_MESSAGE pStubMsg, + PMIDL_STUB_DESC pStubDesc, unsigned int ProcNum ) +{ + TRACE("(pRpcMessage == ^%p, pStubMsg == ^%p, pStubDesc == ^%p, ProcNum == %d)\n", + pRpcMessage, pStubMsg, pStubDesc, ProcNum); + + pRpcMessage->Handle = NULL; + pRpcMessage->ProcNum = ProcNum; + pRpcMessage->RpcInterfaceInformation = pStubDesc->RpcInterfaceInformation; + pRpcMessage->RpcFlags = 0; + pRpcMessage->DataRepresentation = NDR_LOCAL_DATA_REPRESENTATION; + + pStubMsg->RpcMsg = pRpcMessage; + pStubMsg->BufferStart = NULL; + pStubMsg->BufferEnd = NULL; + pStubMsg->BufferLength = 0; + pStubMsg->IsClient = TRUE; + pStubMsg->ReuseBuffer = FALSE; + pStubMsg->pAllocAllNodesContext = NULL; + pStubMsg->pPointerQueueState = NULL; + pStubMsg->IgnoreEmbeddedPointers = 0; + pStubMsg->PointerBufferMark = NULL; + pStubMsg->fBufferValid = 0; + pStubMsg->uFlags = 0; + pStubMsg->pfnAllocate = pStubDesc->pfnAllocate; + pStubMsg->pfnFree = pStubDesc->pfnFree; + pStubMsg->StackTop = NULL; + pStubMsg->StubDesc = pStubDesc; + pStubMsg->FullPtrRefId = 0; + pStubMsg->PointerLength = 0; + pStubMsg->fInDontFree = 0; + pStubMsg->fDontCallFreeInst = 0; + pStubMsg->fInOnlyParam = 0; + pStubMsg->fHasReturn = 0; + pStubMsg->fHasExtensions = 0; + pStubMsg->fHasNewCorrDesc = 0; + pStubMsg->fUnused = 0; + pStubMsg->dwDestContext = MSHCTX_DIFFERENTMACHINE; + pStubMsg->pvDestContext = NULL; + pStubMsg->pRpcChannelBuffer = NULL; + pStubMsg->pArrayInfo = NULL; + pStubMsg->dwStubPhase = 0; + /* FIXME: LowStackMark */ + pStubMsg->pAsyncMsg = NULL; + pStubMsg->pCorrInfo = NULL; + pStubMsg->pCorrMemory = NULL; + pStubMsg->pMemoryList = NULL; +} + +/*********************************************************************** + * NdrServerInitializeNew [RPCRT4.@] + */ +unsigned char* WINAPI NdrServerInitializeNew( PRPC_MESSAGE pRpcMsg, PMIDL_STUB_MESSAGE pStubMsg, + PMIDL_STUB_DESC pStubDesc ) +{ + TRACE("(pRpcMsg == ^%p, pStubMsg == ^%p, pStubDesc == ^%p)\n", pRpcMsg, pStubMsg, pStubDesc); + + pStubMsg->RpcMsg = pRpcMsg; + pStubMsg->Buffer = pStubMsg->BufferStart = pRpcMsg->Buffer; + pStubMsg->BufferEnd = pStubMsg->Buffer + pRpcMsg->BufferLength; + pStubMsg->BufferLength = pRpcMsg->BufferLength; + pStubMsg->IsClient = FALSE; + pStubMsg->ReuseBuffer = FALSE; + pStubMsg->pAllocAllNodesContext = NULL; + pStubMsg->pPointerQueueState = NULL; + pStubMsg->IgnoreEmbeddedPointers = 0; + pStubMsg->PointerBufferMark = NULL; + pStubMsg->uFlags = 0; + pStubMsg->pfnAllocate = pStubDesc->pfnAllocate; + pStubMsg->pfnFree = pStubDesc->pfnFree; + pStubMsg->StackTop = NULL; + pStubMsg->StubDesc = pStubDesc; + pStubMsg->FullPtrXlatTables = NULL; + pStubMsg->FullPtrRefId = 0; + pStubMsg->PointerLength = 0; + pStubMsg->fInDontFree = 0; + pStubMsg->fDontCallFreeInst = 0; + pStubMsg->fInOnlyParam = 0; + pStubMsg->fHasReturn = 0; + pStubMsg->fHasExtensions = 0; + pStubMsg->fHasNewCorrDesc = 0; + pStubMsg->fUnused = 0; + pStubMsg->dwDestContext = MSHCTX_DIFFERENTMACHINE; + pStubMsg->pvDestContext = NULL; + pStubMsg->pRpcChannelBuffer = NULL; + pStubMsg->pArrayInfo = NULL; + pStubMsg->dwStubPhase = 0; + /* FIXME: LowStackMark */ + pStubMsg->pAsyncMsg = NULL; + pStubMsg->pCorrInfo = NULL; + pStubMsg->pCorrMemory = NULL; + pStubMsg->pMemoryList = NULL; + + return NULL; +} + +/*********************************************************************** + * NdrGetBuffer [RPCRT4.@] + */ +unsigned char *WINAPI NdrGetBuffer(PMIDL_STUB_MESSAGE stubmsg, ULONG buflen, RPC_BINDING_HANDLE handle) +{ + RPC_STATUS status; + + TRACE("(stubmsg == ^%p, buflen == %u, handle == %p)\n", stubmsg, buflen, handle); + + stubmsg->RpcMsg->Handle = handle; + stubmsg->RpcMsg->BufferLength = buflen; + + status = I_RpcGetBuffer(stubmsg->RpcMsg); + if (status != RPC_S_OK) + RpcRaiseException(status); + + stubmsg->Buffer = stubmsg->RpcMsg->Buffer; + stubmsg->fBufferValid = TRUE; + stubmsg->BufferLength = stubmsg->RpcMsg->BufferLength; + return stubmsg->Buffer; +} +/*********************************************************************** + * NdrFreeBuffer [RPCRT4.@] + */ +void WINAPI NdrFreeBuffer(PMIDL_STUB_MESSAGE pStubMsg) +{ + TRACE("(pStubMsg == ^%p)\n", pStubMsg); + if (pStubMsg->fBufferValid) + { + I_RpcFreeBuffer(pStubMsg->RpcMsg); + pStubMsg->fBufferValid = FALSE; + } +} + +/************************************************************************ + * NdrSendReceive [RPCRT4.@] + */ +unsigned char *WINAPI NdrSendReceive( PMIDL_STUB_MESSAGE stubmsg, unsigned char *buffer ) +{ + RPC_STATUS status; + + TRACE("(stubmsg == ^%p, buffer == ^%p)\n", stubmsg, buffer); + + /* FIXME: how to handle errors? (raise exception?) */ + if (!stubmsg) { + ERR("NULL stub message. No action taken.\n"); + return NULL; + } + if (!stubmsg->RpcMsg) { + ERR("RPC Message not present in stub message. No action taken.\n"); + return NULL; + } + + stubmsg->RpcMsg->BufferLength = buffer - (unsigned char *)stubmsg->RpcMsg->Buffer; + status = I_RpcSendReceive(stubmsg->RpcMsg); + if (status != RPC_S_OK) + RpcRaiseException(status); + + stubmsg->BufferLength = stubmsg->RpcMsg->BufferLength; + stubmsg->BufferStart = stubmsg->RpcMsg->Buffer; + stubmsg->BufferEnd = stubmsg->BufferStart + stubmsg->BufferLength; + stubmsg->Buffer = stubmsg->BufferStart; + + /* FIXME: is this the right return value? */ + return NULL; +} + +/************************************************************************ + * NdrMapCommAndFaultStatus [RPCRT4.@] + */ +RPC_STATUS RPC_ENTRY NdrMapCommAndFaultStatus( PMIDL_STUB_MESSAGE pStubMsg, + ULONG *pCommStatus, + ULONG *pFaultStatus, + RPC_STATUS Status ) +{ + FIXME("(%p, %p, %p, %ld): stub\n", pStubMsg, pCommStatus, pFaultStatus, Status); + + *pCommStatus = 0; + *pFaultStatus = 0; + + return RPC_S_OK; +} diff --git a/reactos/dll/win32/rpcrt4_new/ndr_fullpointer.c b/reactos/dll/win32/rpcrt4_new/ndr_fullpointer.c index e3d37e2dc1d..3586bc39e30 100644 --- a/reactos/dll/win32/rpcrt4_new/ndr_fullpointer.c +++ b/reactos/dll/win32/rpcrt4_new/ndr_fullpointer.c @@ -1,239 +1,239 @@ -/* - * Full Pointer Translation Routines - * - * Copyright 2006 Robert Shearman - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include - -#include "windef.h" -#include "winbase.h" -#include "rpc.h" -#include "rpcndr.h" - -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(rpc); - -PFULL_PTR_XLAT_TABLES WINAPI NdrFullPointerXlatInit(ULONG NumberOfPointers, - XLAT_SIDE XlatSide) -{ - ULONG NumberOfBuckets; - PFULL_PTR_XLAT_TABLES pXlatTables = HeapAlloc(GetProcessHeap(), 0, sizeof(*pXlatTables)); - - TRACE("(%d, %d)\n", NumberOfPointers, XlatSide); - - if (!NumberOfPointers) NumberOfPointers = 512; - NumberOfBuckets = ((NumberOfPointers + 3) & ~3) - 1; - - pXlatTables->RefIdToPointer.XlatTable = - HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, - sizeof(void *) * NumberOfPointers); - pXlatTables->RefIdToPointer.StateTable = - HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, - sizeof(unsigned char) * NumberOfPointers); - pXlatTables->RefIdToPointer.NumberOfEntries = NumberOfPointers; - - TRACE("NumberOfBuckets = %d\n", NumberOfBuckets); - pXlatTables->PointerToRefId.XlatTable = - HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, - sizeof(PFULL_PTR_TO_REFID_ELEMENT) * NumberOfBuckets); - pXlatTables->PointerToRefId.NumberOfBuckets = NumberOfBuckets; - pXlatTables->PointerToRefId.HashMask = NumberOfBuckets - 1; - - pXlatTables->NextRefId = 1; - pXlatTables->XlatSide = XlatSide; - - return pXlatTables; -} - -void WINAPI NdrFullPointerXlatFree(PFULL_PTR_XLAT_TABLES pXlatTables) -{ - ULONG i; - - TRACE("(%p)\n", pXlatTables); - - /* free the entries in the table */ - for (i = 0; i < pXlatTables->RefIdToPointer.NumberOfEntries; i++) - HeapFree(GetProcessHeap(), 0, pXlatTables->RefIdToPointer.XlatTable[i]); - - HeapFree(GetProcessHeap(), 0, pXlatTables->RefIdToPointer.XlatTable); - HeapFree(GetProcessHeap(), 0, pXlatTables->RefIdToPointer.StateTable); - HeapFree(GetProcessHeap(), 0, pXlatTables->PointerToRefId.XlatTable); - - HeapFree(GetProcessHeap(), 0, pXlatTables); -} - -static void expand_pointer_table_if_necessary(PFULL_PTR_XLAT_TABLES pXlatTables, ULONG RefId) -{ - if (RefId >= pXlatTables->RefIdToPointer.NumberOfEntries) - { - pXlatTables->RefIdToPointer.NumberOfEntries = RefId * 2; - pXlatTables->RefIdToPointer.XlatTable = - HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, - pXlatTables->RefIdToPointer.XlatTable, - sizeof(void *) * pXlatTables->RefIdToPointer.NumberOfEntries); - pXlatTables->RefIdToPointer.StateTable = - HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, - pXlatTables->RefIdToPointer.StateTable, - sizeof(unsigned char) * pXlatTables->RefIdToPointer.NumberOfEntries); - - if (!pXlatTables->RefIdToPointer.XlatTable || !pXlatTables->RefIdToPointer.StateTable) - pXlatTables->RefIdToPointer.NumberOfEntries = 0; - } -} - -int WINAPI NdrFullPointerQueryPointer(PFULL_PTR_XLAT_TABLES pXlatTables, - void *pPointer, unsigned char QueryType, - ULONG *pRefId ) -{ - ULONG Hash = 0; - int i; - PFULL_PTR_TO_REFID_ELEMENT XlatTableEntry; - - TRACE("(%p, %p, %d, %p)\n", pXlatTables, pPointer, QueryType, pRefId); - - if (!pPointer) - { - *pRefId = 0; - return 1; - } - - /* simple hashing algorithm, don't know whether it matches native */ - for (i = 0; i < sizeof(pPointer); i++) - Hash = (Hash * 3) ^ ((unsigned char *)&pPointer)[i]; - - XlatTableEntry = pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask]; - for (; XlatTableEntry; XlatTableEntry = XlatTableEntry->Next) - if (pPointer == XlatTableEntry->Pointer) - { - *pRefId = XlatTableEntry->RefId; - if (XlatTableEntry->State & QueryType) - return 1; - XlatTableEntry->State |= QueryType; - return 0; - } - - XlatTableEntry = HeapAlloc(GetProcessHeap(), 0, sizeof(*XlatTableEntry)); - XlatTableEntry->Next = pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask]; - XlatTableEntry->Pointer = pPointer; - XlatTableEntry->RefId = *pRefId = pXlatTables->NextRefId++; - XlatTableEntry->State = QueryType; - pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask] = XlatTableEntry; - - /* insert pointer into mapping table */ - expand_pointer_table_if_necessary(pXlatTables, XlatTableEntry->RefId); - if (pXlatTables->RefIdToPointer.NumberOfEntries > XlatTableEntry->RefId) - { - pXlatTables->RefIdToPointer.XlatTable[XlatTableEntry->RefId] = pPointer; - pXlatTables->RefIdToPointer.StateTable[XlatTableEntry->RefId] = QueryType; - } - - return 0; -} - -int WINAPI NdrFullPointerQueryRefId(PFULL_PTR_XLAT_TABLES pXlatTables, - ULONG RefId, unsigned char QueryType, - void **ppPointer) -{ - TRACE("(%p, 0x%x, %d, %p)\n", pXlatTables, RefId, QueryType, ppPointer); - - expand_pointer_table_if_necessary(pXlatTables, RefId); - - pXlatTables->NextRefId = max(RefId + 1, pXlatTables->NextRefId); - - if (pXlatTables->RefIdToPointer.NumberOfEntries > RefId) - { - *ppPointer = pXlatTables->RefIdToPointer.XlatTable[RefId]; - if (QueryType) - { - if (pXlatTables->RefIdToPointer.StateTable[RefId] & QueryType) - return 1; - pXlatTables->RefIdToPointer.StateTable[RefId] |= QueryType; - return 0; - } - else - return 0; - } - *ppPointer = NULL; - return 0; -} - -void WINAPI NdrFullPointerInsertRefId(PFULL_PTR_XLAT_TABLES pXlatTables, - ULONG RefId, void *pPointer) -{ - ULONG Hash = 0; - int i; - PFULL_PTR_TO_REFID_ELEMENT XlatTableEntry; - - TRACE("(%p, 0x%x, %p)\n", pXlatTables, RefId, pPointer); - - /* simple hashing algorithm, don't know whether it matches native */ - for (i = 0; i < sizeof(pPointer); i++) - Hash = (Hash * 3) ^ ((unsigned char *)&pPointer)[i]; - - XlatTableEntry = HeapAlloc(GetProcessHeap(), 0, sizeof(*XlatTableEntry)); - XlatTableEntry->Next = pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask]; - XlatTableEntry->Pointer = pPointer; - XlatTableEntry->RefId = RefId; - XlatTableEntry->State = 0; - pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask] = XlatTableEntry; - - /* insert pointer into mapping table */ - expand_pointer_table_if_necessary(pXlatTables, RefId); - if (pXlatTables->RefIdToPointer.NumberOfEntries > RefId) - pXlatTables->RefIdToPointer.XlatTable[XlatTableEntry->RefId] = pPointer; -} - -int WINAPI NdrFullPointerFree(PFULL_PTR_XLAT_TABLES pXlatTables, void *Pointer) -{ - ULONG Hash = 0; - int i; - PFULL_PTR_TO_REFID_ELEMENT XlatTableEntry; - ULONG RefId = 0; - - TRACE("(%p, %p)\n", pXlatTables, Pointer); - - if (!Pointer) - return 1; - - /* simple hashing algorithm, don't know whether it matches native */ - for (i = 0; i < sizeof(Pointer); i++) - Hash = (Hash * 3) ^ ((unsigned char *)&Pointer)[i]; - - XlatTableEntry = pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask]; - for (; XlatTableEntry; XlatTableEntry = XlatTableEntry->Next) - if (Pointer == XlatTableEntry->Pointer) - { - if (XlatTableEntry->State & 0x20) - return 0; - XlatTableEntry->State |= 0x20; - RefId = XlatTableEntry->RefId; - break; - } - - if (!XlatTableEntry) - return 0; - - if (pXlatTables->RefIdToPointer.NumberOfEntries > RefId) - { - pXlatTables->RefIdToPointer.StateTable[RefId] |= 0x20; - return 1; - } - - return 0; -} +/* + * Full Pointer Translation Routines + * + * Copyright 2006 Robert Shearman + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include + +#include "windef.h" +#include "winbase.h" +#include "rpc.h" +#include "rpcndr.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(rpc); + +PFULL_PTR_XLAT_TABLES WINAPI NdrFullPointerXlatInit(ULONG NumberOfPointers, + XLAT_SIDE XlatSide) +{ + ULONG NumberOfBuckets; + PFULL_PTR_XLAT_TABLES pXlatTables = HeapAlloc(GetProcessHeap(), 0, sizeof(*pXlatTables)); + + TRACE("(%d, %d)\n", NumberOfPointers, XlatSide); + + if (!NumberOfPointers) NumberOfPointers = 512; + NumberOfBuckets = ((NumberOfPointers + 3) & ~3) - 1; + + pXlatTables->RefIdToPointer.XlatTable = + HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof(void *) * NumberOfPointers); + pXlatTables->RefIdToPointer.StateTable = + HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof(unsigned char) * NumberOfPointers); + pXlatTables->RefIdToPointer.NumberOfEntries = NumberOfPointers; + + TRACE("NumberOfBuckets = %d\n", NumberOfBuckets); + pXlatTables->PointerToRefId.XlatTable = + HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof(PFULL_PTR_TO_REFID_ELEMENT) * NumberOfBuckets); + pXlatTables->PointerToRefId.NumberOfBuckets = NumberOfBuckets; + pXlatTables->PointerToRefId.HashMask = NumberOfBuckets - 1; + + pXlatTables->NextRefId = 1; + pXlatTables->XlatSide = XlatSide; + + return pXlatTables; +} + +void WINAPI NdrFullPointerXlatFree(PFULL_PTR_XLAT_TABLES pXlatTables) +{ + ULONG i; + + TRACE("(%p)\n", pXlatTables); + + /* free the entries in the table */ + for (i = 0; i < pXlatTables->RefIdToPointer.NumberOfEntries; i++) + HeapFree(GetProcessHeap(), 0, pXlatTables->RefIdToPointer.XlatTable[i]); + + HeapFree(GetProcessHeap(), 0, pXlatTables->RefIdToPointer.XlatTable); + HeapFree(GetProcessHeap(), 0, pXlatTables->RefIdToPointer.StateTable); + HeapFree(GetProcessHeap(), 0, pXlatTables->PointerToRefId.XlatTable); + + HeapFree(GetProcessHeap(), 0, pXlatTables); +} + +static void expand_pointer_table_if_necessary(PFULL_PTR_XLAT_TABLES pXlatTables, ULONG RefId) +{ + if (RefId >= pXlatTables->RefIdToPointer.NumberOfEntries) + { + pXlatTables->RefIdToPointer.NumberOfEntries = RefId * 2; + pXlatTables->RefIdToPointer.XlatTable = + HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + pXlatTables->RefIdToPointer.XlatTable, + sizeof(void *) * pXlatTables->RefIdToPointer.NumberOfEntries); + pXlatTables->RefIdToPointer.StateTable = + HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + pXlatTables->RefIdToPointer.StateTable, + sizeof(unsigned char) * pXlatTables->RefIdToPointer.NumberOfEntries); + + if (!pXlatTables->RefIdToPointer.XlatTable || !pXlatTables->RefIdToPointer.StateTable) + pXlatTables->RefIdToPointer.NumberOfEntries = 0; + } +} + +int WINAPI NdrFullPointerQueryPointer(PFULL_PTR_XLAT_TABLES pXlatTables, + void *pPointer, unsigned char QueryType, + ULONG *pRefId ) +{ + ULONG Hash = 0; + int i; + PFULL_PTR_TO_REFID_ELEMENT XlatTableEntry; + + TRACE("(%p, %p, %d, %p)\n", pXlatTables, pPointer, QueryType, pRefId); + + if (!pPointer) + { + *pRefId = 0; + return 1; + } + + /* simple hashing algorithm, don't know whether it matches native */ + for (i = 0; i < sizeof(pPointer); i++) + Hash = (Hash * 3) ^ ((unsigned char *)&pPointer)[i]; + + XlatTableEntry = pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask]; + for (; XlatTableEntry; XlatTableEntry = XlatTableEntry->Next) + if (pPointer == XlatTableEntry->Pointer) + { + *pRefId = XlatTableEntry->RefId; + if (XlatTableEntry->State & QueryType) + return 1; + XlatTableEntry->State |= QueryType; + return 0; + } + + XlatTableEntry = HeapAlloc(GetProcessHeap(), 0, sizeof(*XlatTableEntry)); + XlatTableEntry->Next = pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask]; + XlatTableEntry->Pointer = pPointer; + XlatTableEntry->RefId = *pRefId = pXlatTables->NextRefId++; + XlatTableEntry->State = QueryType; + pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask] = XlatTableEntry; + + /* insert pointer into mapping table */ + expand_pointer_table_if_necessary(pXlatTables, XlatTableEntry->RefId); + if (pXlatTables->RefIdToPointer.NumberOfEntries > XlatTableEntry->RefId) + { + pXlatTables->RefIdToPointer.XlatTable[XlatTableEntry->RefId] = pPointer; + pXlatTables->RefIdToPointer.StateTable[XlatTableEntry->RefId] = QueryType; + } + + return 0; +} + +int WINAPI NdrFullPointerQueryRefId(PFULL_PTR_XLAT_TABLES pXlatTables, + ULONG RefId, unsigned char QueryType, + void **ppPointer) +{ + TRACE("(%p, 0x%x, %d, %p)\n", pXlatTables, RefId, QueryType, ppPointer); + + expand_pointer_table_if_necessary(pXlatTables, RefId); + + pXlatTables->NextRefId = max(RefId + 1, pXlatTables->NextRefId); + + if (pXlatTables->RefIdToPointer.NumberOfEntries > RefId) + { + *ppPointer = pXlatTables->RefIdToPointer.XlatTable[RefId]; + if (QueryType) + { + if (pXlatTables->RefIdToPointer.StateTable[RefId] & QueryType) + return 1; + pXlatTables->RefIdToPointer.StateTable[RefId] |= QueryType; + return 0; + } + else + return 0; + } + *ppPointer = NULL; + return 0; +} + +void WINAPI NdrFullPointerInsertRefId(PFULL_PTR_XLAT_TABLES pXlatTables, + ULONG RefId, void *pPointer) +{ + ULONG Hash = 0; + int i; + PFULL_PTR_TO_REFID_ELEMENT XlatTableEntry; + + TRACE("(%p, 0x%x, %p)\n", pXlatTables, RefId, pPointer); + + /* simple hashing algorithm, don't know whether it matches native */ + for (i = 0; i < sizeof(pPointer); i++) + Hash = (Hash * 3) ^ ((unsigned char *)&pPointer)[i]; + + XlatTableEntry = HeapAlloc(GetProcessHeap(), 0, sizeof(*XlatTableEntry)); + XlatTableEntry->Next = pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask]; + XlatTableEntry->Pointer = pPointer; + XlatTableEntry->RefId = RefId; + XlatTableEntry->State = 0; + pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask] = XlatTableEntry; + + /* insert pointer into mapping table */ + expand_pointer_table_if_necessary(pXlatTables, RefId); + if (pXlatTables->RefIdToPointer.NumberOfEntries > RefId) + pXlatTables->RefIdToPointer.XlatTable[XlatTableEntry->RefId] = pPointer; +} + +int WINAPI NdrFullPointerFree(PFULL_PTR_XLAT_TABLES pXlatTables, void *Pointer) +{ + ULONG Hash = 0; + int i; + PFULL_PTR_TO_REFID_ELEMENT XlatTableEntry; + ULONG RefId = 0; + + TRACE("(%p, %p)\n", pXlatTables, Pointer); + + if (!Pointer) + return 1; + + /* simple hashing algorithm, don't know whether it matches native */ + for (i = 0; i < sizeof(Pointer); i++) + Hash = (Hash * 3) ^ ((unsigned char *)&Pointer)[i]; + + XlatTableEntry = pXlatTables->PointerToRefId.XlatTable[Hash & pXlatTables->PointerToRefId.HashMask]; + for (; XlatTableEntry; XlatTableEntry = XlatTableEntry->Next) + if (Pointer == XlatTableEntry->Pointer) + { + if (XlatTableEntry->State & 0x20) + return 0; + XlatTableEntry->State |= 0x20; + RefId = XlatTableEntry->RefId; + break; + } + + if (!XlatTableEntry) + return 0; + + if (pXlatTables->RefIdToPointer.NumberOfEntries > RefId) + { + pXlatTables->RefIdToPointer.StateTable[RefId] |= 0x20; + return 1; + } + + return 0; +} diff --git a/reactos/dll/win32/rpcrt4_new/ndr_marshall.c b/reactos/dll/win32/rpcrt4_new/ndr_marshall.c index e1a4e417732..3b6106fe7c5 100644 --- a/reactos/dll/win32/rpcrt4_new/ndr_marshall.c +++ b/reactos/dll/win32/rpcrt4_new/ndr_marshall.c @@ -1,6334 +1,6334 @@ -/* - * NDR data marshalling - * - * Copyright 2002 Greg Turner - * Copyright 2003-2006 CodeWeavers - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - * - * TODO: - * - Non-conformant strings - * - String structs - * - Byte count pointers - * - transmit_as/represent as - * - Multi-dimensional arrays - * - Conversion functions (NdrConvert) - * - Checks for integer addition overflow in base type and user marshall functions - */ - -#include -#include -#include -#include -#include - -#include "windef.h" -#include "winbase.h" -#include "winerror.h" - -#include "ndr_misc.h" -#include "rpcndr.h" - -#include "wine/unicode.h" -#include "wine/rpcfc.h" - -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(ole); - -#if defined(__i386__) -# define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \ - (*((UINT32 *)(pchar)) = (uint32)) - -# define LITTLE_ENDIAN_UINT32_READ(pchar) \ - (*((UINT32 *)(pchar))) -#else - /* these would work for i386 too, but less efficient */ -# define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \ - (*(pchar) = LOBYTE(LOWORD(uint32)), \ - *((pchar)+1) = HIBYTE(LOWORD(uint32)), \ - *((pchar)+2) = LOBYTE(HIWORD(uint32)), \ - *((pchar)+3) = HIBYTE(HIWORD(uint32)), \ - (uint32)) /* allow as r-value */ - -# define LITTLE_ENDIAN_UINT32_READ(pchar) \ - (MAKELONG( \ - MAKEWORD(*(pchar), *((pchar)+1)), \ - MAKEWORD(*((pchar)+2), *((pchar)+3)))) -#endif - -#define BIG_ENDIAN_UINT32_WRITE(pchar, uint32) \ - (*((pchar)+3) = LOBYTE(LOWORD(uint32)), \ - *((pchar)+2) = HIBYTE(LOWORD(uint32)), \ - *((pchar)+1) = LOBYTE(HIWORD(uint32)), \ - *(pchar) = HIBYTE(HIWORD(uint32)), \ - (uint32)) /* allow as r-value */ - -#define BIG_ENDIAN_UINT32_READ(pchar) \ - (MAKELONG( \ - MAKEWORD(*((pchar)+3), *((pchar)+2)), \ - MAKEWORD(*((pchar)+1), *(pchar)))) - -#ifdef NDR_LOCAL_IS_BIG_ENDIAN -# define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \ - BIG_ENDIAN_UINT32_WRITE(pchar, uint32) -# define NDR_LOCAL_UINT32_READ(pchar) \ - BIG_ENDIAN_UINT32_READ(pchar) -#else -# define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \ - LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) -# define NDR_LOCAL_UINT32_READ(pchar) \ - 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) - -#define STD_OVERFLOW_CHECK(_Msg) do { \ - TRACE("buffer=%d/%d\n", _Msg->Buffer - (unsigned char *)_Msg->RpcMsg->Buffer, _Msg->BufferLength); \ - if (_Msg->Buffer > (unsigned char *)_Msg->RpcMsg->Buffer + _Msg->BufferLength) \ - ERR("buffer overflow %d bytes\n", _Msg->Buffer - ((unsigned char *)_Msg->RpcMsg->Buffer + _Msg->BufferLength)); \ - } while (0) - -#define NDR_TABLE_SIZE 128 -#define NDR_TABLE_MASK 127 - -static unsigned char *WINAPI NdrBaseTypeMarshall(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING); -static unsigned char *WINAPI NdrBaseTypeUnmarshall(PMIDL_STUB_MESSAGE, unsigned char **, PFORMAT_STRING, unsigned char); -static void WINAPI NdrBaseTypeBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING); -static void WINAPI NdrBaseTypeFree(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING); -static ULONG WINAPI NdrBaseTypeMemorySize(PMIDL_STUB_MESSAGE, PFORMAT_STRING); - -static unsigned char *WINAPI NdrContextHandleMarshall(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING); -static void WINAPI NdrContextHandleBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING); -static unsigned char *WINAPI NdrContextHandleUnmarshall(PMIDL_STUB_MESSAGE, unsigned char **, PFORMAT_STRING, unsigned char); - -const NDR_MARSHALL NdrMarshaller[NDR_TABLE_SIZE] = { - 0, - NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, - NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, - NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, - NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, - /* 0x10 */ - NdrBaseTypeMarshall, - /* 0x11 */ - NdrPointerMarshall, NdrPointerMarshall, - NdrPointerMarshall, NdrPointerMarshall, - /* 0x15 */ - NdrSimpleStructMarshall, NdrSimpleStructMarshall, - NdrConformantStructMarshall, NdrConformantStructMarshall, - NdrConformantVaryingStructMarshall, - NdrComplexStructMarshall, - /* 0x1b */ - NdrConformantArrayMarshall, - NdrConformantVaryingArrayMarshall, - NdrFixedArrayMarshall, NdrFixedArrayMarshall, - NdrVaryingArrayMarshall, NdrVaryingArrayMarshall, - NdrComplexArrayMarshall, - /* 0x22 */ - NdrConformantStringMarshall, 0, 0, - NdrConformantStringMarshall, - NdrNonConformantStringMarshall, 0, 0, 0, - /* 0x2a */ - NdrEncapsulatedUnionMarshall, - NdrNonEncapsulatedUnionMarshall, - NdrByteCountPointerMarshall, - NdrXmitOrRepAsMarshall, NdrXmitOrRepAsMarshall, - /* 0x2f */ - NdrInterfacePointerMarshall, - /* 0x30 */ - NdrContextHandleMarshall, - /* 0xb1 */ - 0, 0, 0, - NdrUserMarshalMarshall, - 0, 0, - /* 0xb7 */ - NdrRangeMarshall -}; -const NDR_UNMARSHALL NdrUnmarshaller[NDR_TABLE_SIZE] = { - 0, - NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, - NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, - NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, - NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, - /* 0x10 */ - NdrBaseTypeUnmarshall, - /* 0x11 */ - NdrPointerUnmarshall, NdrPointerUnmarshall, - NdrPointerUnmarshall, NdrPointerUnmarshall, - /* 0x15 */ - NdrSimpleStructUnmarshall, NdrSimpleStructUnmarshall, - NdrConformantStructUnmarshall, NdrConformantStructUnmarshall, - NdrConformantVaryingStructUnmarshall, - NdrComplexStructUnmarshall, - /* 0x1b */ - NdrConformantArrayUnmarshall, - NdrConformantVaryingArrayUnmarshall, - NdrFixedArrayUnmarshall, NdrFixedArrayUnmarshall, - NdrVaryingArrayUnmarshall, NdrVaryingArrayUnmarshall, - NdrComplexArrayUnmarshall, - /* 0x22 */ - NdrConformantStringUnmarshall, 0, 0, - NdrConformantStringUnmarshall, - NdrNonConformantStringUnmarshall, 0, 0, 0, - /* 0x2a */ - NdrEncapsulatedUnionUnmarshall, - NdrNonEncapsulatedUnionUnmarshall, - NdrByteCountPointerUnmarshall, - NdrXmitOrRepAsUnmarshall, NdrXmitOrRepAsUnmarshall, - /* 0x2f */ - NdrInterfacePointerUnmarshall, - /* 0x30 */ - NdrContextHandleUnmarshall, - /* 0xb1 */ - 0, 0, 0, - NdrUserMarshalUnmarshall, - 0, 0, - /* 0xb7 */ - NdrRangeUnmarshall -}; -const NDR_BUFFERSIZE NdrBufferSizer[NDR_TABLE_SIZE] = { - 0, - NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, - NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, - NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, - NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, - /* 0x10 */ - NdrBaseTypeBufferSize, - /* 0x11 */ - NdrPointerBufferSize, NdrPointerBufferSize, - NdrPointerBufferSize, NdrPointerBufferSize, - /* 0x15 */ - NdrSimpleStructBufferSize, NdrSimpleStructBufferSize, - NdrConformantStructBufferSize, NdrConformantStructBufferSize, - NdrConformantVaryingStructBufferSize, - NdrComplexStructBufferSize, - /* 0x1b */ - NdrConformantArrayBufferSize, - NdrConformantVaryingArrayBufferSize, - NdrFixedArrayBufferSize, NdrFixedArrayBufferSize, - NdrVaryingArrayBufferSize, NdrVaryingArrayBufferSize, - NdrComplexArrayBufferSize, - /* 0x22 */ - NdrConformantStringBufferSize, 0, 0, - NdrConformantStringBufferSize, - NdrNonConformantStringBufferSize, 0, 0, 0, - /* 0x2a */ - NdrEncapsulatedUnionBufferSize, - NdrNonEncapsulatedUnionBufferSize, - NdrByteCountPointerBufferSize, - NdrXmitOrRepAsBufferSize, NdrXmitOrRepAsBufferSize, - /* 0x2f */ - NdrInterfacePointerBufferSize, - /* 0x30 */ - NdrContextHandleBufferSize, - /* 0xb1 */ - 0, 0, 0, - NdrUserMarshalBufferSize, - 0, 0, - /* 0xb7 */ - NdrRangeBufferSize -}; -const NDR_MEMORYSIZE NdrMemorySizer[NDR_TABLE_SIZE] = { - 0, - NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, - NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, - NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, - NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, - /* 0x10 */ - NdrBaseTypeMemorySize, - /* 0x11 */ - NdrPointerMemorySize, NdrPointerMemorySize, - NdrPointerMemorySize, NdrPointerMemorySize, - /* 0x15 */ - NdrSimpleStructMemorySize, NdrSimpleStructMemorySize, - NdrConformantStructMemorySize, NdrConformantStructMemorySize, - NdrConformantVaryingStructMemorySize, - NdrComplexStructMemorySize, - /* 0x1b */ - NdrConformantArrayMemorySize, - NdrConformantVaryingArrayMemorySize, - NdrFixedArrayMemorySize, NdrFixedArrayMemorySize, - NdrVaryingArrayMemorySize, NdrVaryingArrayMemorySize, - NdrComplexArrayMemorySize, - /* 0x22 */ - NdrConformantStringMemorySize, 0, 0, - NdrConformantStringMemorySize, - NdrNonConformantStringMemorySize, 0, 0, 0, - /* 0x2a */ - NdrEncapsulatedUnionMemorySize, - NdrNonEncapsulatedUnionMemorySize, - NdrByteCountPointerMemorySize, - NdrXmitOrRepAsMemorySize, NdrXmitOrRepAsMemorySize, - /* 0x2f */ - NdrInterfacePointerMemorySize, - /* 0x30 */ - 0, - /* 0xb1 */ - 0, 0, 0, - NdrUserMarshalMemorySize, - 0, 0, - /* 0xb7 */ - NdrRangeMemorySize -}; -const NDR_FREE NdrFreer[NDR_TABLE_SIZE] = { - 0, - NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, - NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, - NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, - NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, - /* 0x10 */ - NdrBaseTypeFree, - /* 0x11 */ - NdrPointerFree, NdrPointerFree, - NdrPointerFree, NdrPointerFree, - /* 0x15 */ - NdrSimpleStructFree, NdrSimpleStructFree, - NdrConformantStructFree, NdrConformantStructFree, - NdrConformantVaryingStructFree, - NdrComplexStructFree, - /* 0x1b */ - NdrConformantArrayFree, - NdrConformantVaryingArrayFree, - NdrFixedArrayFree, NdrFixedArrayFree, - NdrVaryingArrayFree, NdrVaryingArrayFree, - NdrComplexArrayFree, - /* 0x22 */ - 0, 0, 0, - 0, 0, 0, 0, 0, - /* 0x2a */ - NdrEncapsulatedUnionFree, - NdrNonEncapsulatedUnionFree, - 0, - NdrXmitOrRepAsFree, NdrXmitOrRepAsFree, - /* 0x2f */ - NdrInterfacePointerFree, - /* 0x30 */ - 0, - /* 0xb1 */ - 0, 0, 0, - NdrUserMarshalFree, - 0, 0, - /* 0xb7 */ - NdrRangeFree -}; - -typedef struct _NDR_MEMORY_LIST -{ - ULONG magic; - ULONG size; - ULONG reserved; - struct _NDR_MEMORY_LIST *next; -} NDR_MEMORY_LIST; - -#define MEML_MAGIC ('M' << 24 | 'E' << 16 | 'M' << 8 | 'L') - -/*********************************************************************** - * NdrAllocate [RPCRT4.@] - * - * Allocates a block of memory using pStubMsg->pfnAllocate. - * - * PARAMS - * pStubMsg [I/O] MIDL_STUB_MESSAGE structure. - * len [I] Size of memory block to allocate. - * - * RETURNS - * The memory block of size len that was allocated. - * - * NOTES - * The memory block is always 8-byte aligned. - * If the function is unable to allocate memory an ERROR_OUTOFMEMORY - * exception is raised. - */ -void * WINAPI NdrAllocate(MIDL_STUB_MESSAGE *pStubMsg, size_t len) -{ - size_t aligned_len; - size_t adjusted_len; - void *p; - NDR_MEMORY_LIST *mem_list; - - aligned_len = ALIGNED_LENGTH(len, 8); - adjusted_len = aligned_len + sizeof(NDR_MEMORY_LIST); - /* check for overflow */ - if (adjusted_len < len) - { - ERR("overflow of adjusted_len %d, len %d\n", adjusted_len, len); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - } - - p = pStubMsg->pfnAllocate(adjusted_len); - if (!p) RpcRaiseException(ERROR_OUTOFMEMORY); - - mem_list = (NDR_MEMORY_LIST *)((char *)p + aligned_len); - mem_list->magic = MEML_MAGIC; - mem_list->size = aligned_len; - mem_list->reserved = 0; - mem_list->next = pStubMsg->pMemoryList; - pStubMsg->pMemoryList = mem_list; - - TRACE("-- %p\n", p); - return p; -} - -static void WINAPI NdrFree(MIDL_STUB_MESSAGE *pStubMsg, unsigned char *Pointer) -{ - TRACE("(%p, %p)\n", pStubMsg, Pointer); - - pStubMsg->pfnFree(Pointer); -} - -static inline BOOL IsConformanceOrVariancePresent(PFORMAT_STRING pFormat) -{ - return (*(const ULONG *)pFormat != -1); -} - -static PFORMAT_STRING ReadConformance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat) -{ - 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); - pStubMsg->Buffer += 4; - TRACE("unmarshalled conformance is %ld\n", pStubMsg->MaxCount); - if (pStubMsg->fHasNewCorrDesc) - return pFormat+6; - else - return pFormat+4; -} - -static inline PFORMAT_STRING ReadVariance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat, ULONG MaxValue) -{ - if (pFormat && !IsConformanceOrVariancePresent(pFormat)) - { - pStubMsg->Offset = 0; - pStubMsg->ActualCount = pStubMsg->MaxCount; - goto done; - } - - 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); - pStubMsg->Buffer += 4; - TRACE("offset is %d\n", pStubMsg->Offset); - pStubMsg->ActualCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer); - pStubMsg->Buffer += 4; - TRACE("variance is %d\n", pStubMsg->ActualCount); - - if ((pStubMsg->ActualCount > MaxValue) || - (pStubMsg->ActualCount + pStubMsg->Offset > MaxValue)) - { - ERR("invalid array bound(s): ActualCount = %d, Offset = %d, MaxValue = %d\n", - pStubMsg->ActualCount, pStubMsg->Offset, MaxValue); - RpcRaiseException(RPC_S_INVALID_BOUND); - return NULL; - } - -done: - if (pStubMsg->fHasNewCorrDesc) - return pFormat+6; - else - return pFormat+4; -} - -/* writes the conformance value to the buffer */ -static inline void WriteConformance(MIDL_STUB_MESSAGE *pStubMsg) -{ - 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); - pStubMsg->Buffer += 4; -} - -/* writes the variance values to the buffer */ -static inline void WriteVariance(MIDL_STUB_MESSAGE *pStubMsg) -{ - 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); - pStubMsg->Buffer += 4; - NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->ActualCount); - pStubMsg->Buffer += 4; -} - -/* requests buffer space for the conformance value */ -static inline void SizeConformance(MIDL_STUB_MESSAGE *pStubMsg) -{ - ALIGN_LENGTH(pStubMsg->BufferLength, 4); - if (pStubMsg->BufferLength + 4 < pStubMsg->BufferLength) - RpcRaiseException(RPC_X_BAD_STUB_DATA); - pStubMsg->BufferLength += 4; -} - -/* requests buffer space for the variance values */ -static inline void SizeVariance(MIDL_STUB_MESSAGE *pStubMsg) -{ - ALIGN_LENGTH(pStubMsg->BufferLength, 4); - if (pStubMsg->BufferLength + 8 < pStubMsg->BufferLength) - RpcRaiseException(RPC_X_BAD_STUB_DATA); - pStubMsg->BufferLength += 8; -} - -PFORMAT_STRING ComputeConformanceOrVariance( - MIDL_STUB_MESSAGE *pStubMsg, unsigned char *pMemory, - PFORMAT_STRING pFormat, ULONG_PTR def, ULONG_PTR *pCount) -{ - BYTE dtype = pFormat[0] & 0xf; - short ofs = *(const short *)&pFormat[2]; - LPVOID ptr = NULL; - DWORD data = 0; - - if (!IsConformanceOrVariancePresent(pFormat)) { - /* null descriptor */ - *pCount = def; - goto finish_conf; - } - - switch (pFormat[0] & 0xf0) { - case RPC_FC_NORMAL_CONFORMANCE: - TRACE("normal conformance, ofs=%d\n", ofs); - ptr = pMemory; - break; - case RPC_FC_POINTER_CONFORMANCE: - TRACE("pointer conformance, ofs=%d\n", ofs); - ptr = pStubMsg->Memory; - break; - case RPC_FC_TOP_LEVEL_CONFORMANCE: - TRACE("toplevel conformance, ofs=%d\n", ofs); - if (pStubMsg->StackTop) { - ptr = pStubMsg->StackTop; - } - else { - /* -Os mode, *pCount is already set */ - goto finish_conf; - } - break; - case RPC_FC_CONSTANT_CONFORMANCE: - data = ofs | ((DWORD)pFormat[1] << 16); - TRACE("constant conformance, val=%d\n", data); - *pCount = data; - goto finish_conf; - case RPC_FC_TOP_LEVEL_MULTID_CONFORMANCE: - FIXME("toplevel multidimensional conformance, ofs=%d\n", ofs); - if (pStubMsg->StackTop) { - ptr = pStubMsg->StackTop; - } - else { - /* ? */ - goto done_conf_grab; - } - break; - default: - FIXME("unknown conformance type %x\n", pFormat[0] & 0xf0); - } - - switch (pFormat[1]) { - case RPC_FC_DEREFERENCE: - ptr = *(LPVOID*)((char *)ptr + ofs); - break; - case RPC_FC_CALLBACK: - { - unsigned char *old_stack_top = pStubMsg->StackTop; - pStubMsg->StackTop = ptr; - - /* ofs is index into StubDesc->apfnExprEval */ - TRACE("callback conformance into apfnExprEval[%d]\n", ofs); - pStubMsg->StubDesc->apfnExprEval[ofs](pStubMsg); - - pStubMsg->StackTop = old_stack_top; - - /* the callback function always stores the computed value in MaxCount */ - *pCount = pStubMsg->MaxCount; - goto finish_conf; - } - default: - ptr = (char *)ptr + ofs; - break; - } - - switch (dtype) { - case RPC_FC_LONG: - case RPC_FC_ULONG: - data = *(DWORD*)ptr; - break; - case RPC_FC_SHORT: - data = *(SHORT*)ptr; - break; - case RPC_FC_USHORT: - data = *(USHORT*)ptr; - break; - case RPC_FC_CHAR: - case RPC_FC_SMALL: - data = *(CHAR*)ptr; - break; - case RPC_FC_BYTE: - case RPC_FC_USMALL: - data = *(UCHAR*)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); - -done_conf_grab: - switch (pFormat[1]) { - case RPC_FC_DEREFERENCE: /* already handled */ - case 0: /* no op */ - *pCount = data; - break; - case RPC_FC_ADD_1: - *pCount = data + 1; - break; - case RPC_FC_SUB_1: - *pCount = data - 1; - break; - case RPC_FC_MULT_2: - *pCount = data * 2; - break; - case RPC_FC_DIV_2: - *pCount = data / 2; - break; - default: - FIXME("unknown conformance op %d\n", pFormat[1]); - goto finish_conf; - } - -finish_conf: - TRACE("resulting conformance is %ld\n", *pCount); - if (pStubMsg->fHasNewCorrDesc) - return pFormat+6; - else - return pFormat+4; -} - -/* multiply two numbers together, raising an RPC_S_INVALID_BOUND exception if - * the result overflows 32-bits */ -static inline ULONG safe_multiply(ULONG a, ULONG b) -{ - ULONGLONG ret = (ULONGLONG)a * b; - if (ret > 0xffffffff) - { - RpcRaiseException(RPC_S_INVALID_BOUND); - return 0; - } - return ret; -} - -static inline void safe_buffer_increment(MIDL_STUB_MESSAGE *pStubMsg, ULONG size) -{ - if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */ - (pStubMsg->Buffer + size > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)) - RpcRaiseException(RPC_X_BAD_STUB_DATA); - pStubMsg->Buffer += size; -} - -static inline void safe_buffer_length_increment(MIDL_STUB_MESSAGE *pStubMsg, ULONG size) -{ - if (pStubMsg->BufferLength + size < pStubMsg->BufferLength) /* integer overflow of pStubMsg->BufferSize */ - { - ERR("buffer length overflow - BufferLength = %u, size = %u\n", - pStubMsg->BufferLength, size); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - } - pStubMsg->BufferLength += size; -} - -/* copies data from the buffer, checking that there is enough data in the buffer - * to do so */ -static inline void safe_copy_from_buffer(MIDL_STUB_MESSAGE *pStubMsg, void *p, ULONG size) -{ - if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */ - (pStubMsg->Buffer + size > pStubMsg->BufferEnd)) - { - ERR("buffer overflow - Buffer = %p, BufferEnd = %p, size = %u\n", - pStubMsg->Buffer, pStubMsg->BufferEnd, size); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - } - if (p == pStubMsg->Buffer) - ERR("pointer is the same as the buffer\n"); - memcpy(p, pStubMsg->Buffer, size); - pStubMsg->Buffer += size; -} - -/* copies data to the buffer, checking that there is enough space to do so */ -static inline void safe_copy_to_buffer(MIDL_STUB_MESSAGE *pStubMsg, const void *p, ULONG size) -{ - if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */ - (pStubMsg->Buffer + size > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)) - { - ERR("buffer overflow - Buffer = %p, BufferEnd = %p, size = %u\n", - pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength, - size); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - } - memcpy(pStubMsg->Buffer, p, size); - pStubMsg->Buffer += size; -} - -/* - * NdrConformantString: - * - * What MS calls a ConformantString is, in DCE terminology, - * a Varying-Conformant String. - * [ - * maxlen: DWORD (max # of CHARTYPE characters, inclusive of '\0') - * offset: DWORD (actual string data begins at (offset) CHARTYPE's - * into unmarshalled string) - * length: DWORD (# of CHARTYPE characters, inclusive of '\0') - * [ - * data: CHARTYPE[maxlen] - * ] - * ], where CHARTYPE is the appropriate character type (specified externally) - * - */ - -/*********************************************************************** - * NdrConformantStringMarshall [RPCRT4.@] - */ -unsigned char *WINAPI NdrConformantStringMarshall(MIDL_STUB_MESSAGE *pStubMsg, - unsigned char *pszMessage, PFORMAT_STRING pFormat) -{ - ULONG esize, size; - - TRACE("(pStubMsg == ^%p, pszMessage == ^%p, pFormat == ^%p)\n", pStubMsg, pszMessage, pFormat); - - if (*pFormat == RPC_FC_C_CSTRING) { - TRACE("string=%s\n", debugstr_a((char*)pszMessage)); - pStubMsg->ActualCount = strlen((char*)pszMessage)+1; - esize = 1; - } - else if (*pFormat == RPC_FC_C_WSTRING) { - TRACE("string=%s\n", debugstr_w((LPWSTR)pszMessage)); - pStubMsg->ActualCount = strlenW((LPWSTR)pszMessage)+1; - esize = 2; - } - else { - ERR("Unhandled string type: %#x\n", *pFormat); - /* FIXME: raise an exception. */ - return NULL; - } - - if (pFormat[1] == RPC_FC_STRING_SIZED) - pFormat = ComputeConformance(pStubMsg, pszMessage, pFormat + 2, 0); - else - pStubMsg->MaxCount = pStubMsg->ActualCount; - pStubMsg->Offset = 0; - WriteConformance(pStubMsg); - WriteVariance(pStubMsg); - - size = safe_multiply(esize, pStubMsg->ActualCount); - safe_copy_to_buffer(pStubMsg, pszMessage, size); /* the string itself */ - - /* success */ - return NULL; /* is this always right? */ -} - -/*********************************************************************** - * NdrConformantStringBufferSize [RPCRT4.@] - */ -void WINAPI NdrConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char* pMemory, PFORMAT_STRING pFormat) -{ - ULONG esize; - - TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat); - - SizeConformance(pStubMsg); - SizeVariance(pStubMsg); - - if (*pFormat == RPC_FC_C_CSTRING) { - TRACE("string=%s\n", debugstr_a((char*)pMemory)); - pStubMsg->ActualCount = strlen((char*)pMemory)+1; - esize = 1; - } - else if (*pFormat == RPC_FC_C_WSTRING) { - TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory)); - pStubMsg->ActualCount = strlenW((LPWSTR)pMemory)+1; - esize = 2; - } - else { - ERR("Unhandled string type: %#x\n", *pFormat); - /* FIXME: raise an exception */ - return; - } - - if (pFormat[1] == RPC_FC_STRING_SIZED) - pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 2, 0); - else - pStubMsg->MaxCount = pStubMsg->ActualCount; - - safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount)); -} - -/************************************************************************ - * NdrConformantStringMemorySize [RPCRT4.@] - */ -ULONG WINAPI NdrConformantStringMemorySize( PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat ) -{ - ULONG bufsize, memsize, esize, i; - - TRACE("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat); - - ReadConformance(pStubMsg, NULL); - ReadVariance(pStubMsg, NULL, pStubMsg->MaxCount); - - if (pFormat[1] != RPC_FC_STRING_SIZED && (pStubMsg->MaxCount != pStubMsg->ActualCount)) - { - ERR("buffer size %d must equal memory size %ld for non-sized conformant strings\n", - pStubMsg->ActualCount, pStubMsg->MaxCount); - RpcRaiseException(RPC_S_INVALID_BOUND); - } - if (pStubMsg->Offset) - { - ERR("conformant strings can't have Offset (%d)\n", pStubMsg->Offset); - RpcRaiseException(RPC_S_INVALID_BOUND); - } - - if (*pFormat == RPC_FC_C_CSTRING) esize = 1; - else if (*pFormat == RPC_FC_C_WSTRING) esize = 2; - else { - ERR("Unhandled string type: %#x\n", *pFormat); - /* FIXME: raise an exception */ - esize = 0; - } - - memsize = safe_multiply(esize, pStubMsg->MaxCount); - bufsize = safe_multiply(esize, pStubMsg->ActualCount); - - /* strings must always have null terminating bytes */ - if (bufsize < esize) - { - ERR("invalid string length of %d\n", pStubMsg->ActualCount); - RpcRaiseException(RPC_S_INVALID_BOUND); - } - - /* verify the buffer is safe to access */ - if ((pStubMsg->Buffer + bufsize < pStubMsg->Buffer) || - (pStubMsg->Buffer + bufsize > pStubMsg->BufferEnd)) - { - ERR("bufsize 0x%x exceeded buffer end %p of buffer %p\n", bufsize, - pStubMsg->BufferEnd, pStubMsg->Buffer); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - } - - for (i = bufsize - esize; i < bufsize; i++) - if (pStubMsg->Buffer[i] != 0) - { - ERR("string not null-terminated at byte position %d, data is 0x%x\n", - i, pStubMsg->Buffer[i]); - RpcRaiseException(RPC_S_INVALID_BOUND); - } - - safe_buffer_increment(pStubMsg, bufsize); - pStubMsg->MemorySize += memsize; - - return pStubMsg->MemorySize; -} - -/************************************************************************ - * NdrConformantStringUnmarshall [RPCRT4.@] - */ -unsigned char *WINAPI NdrConformantStringUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, - unsigned char** ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc ) -{ - ULONG bufsize, memsize, esize, i; - - TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n", - pStubMsg, *ppMemory, pFormat, fMustAlloc); - - assert(pFormat && ppMemory && pStubMsg); - - ReadConformance(pStubMsg, NULL); - ReadVariance(pStubMsg, NULL, pStubMsg->MaxCount); - - if (pFormat[1] != RPC_FC_STRING_SIZED && (pStubMsg->MaxCount != pStubMsg->ActualCount)) - { - ERR("buffer size %d must equal memory size %ld for non-sized conformant strings\n", - pStubMsg->ActualCount, pStubMsg->MaxCount); - RpcRaiseException(RPC_S_INVALID_BOUND); - return NULL; - } - if (pStubMsg->Offset) - { - ERR("conformant strings can't have Offset (%d)\n", pStubMsg->Offset); - RpcRaiseException(RPC_S_INVALID_BOUND); - return NULL; - } - - if (*pFormat == RPC_FC_C_CSTRING) esize = 1; - else if (*pFormat == RPC_FC_C_WSTRING) esize = 2; - else { - ERR("Unhandled string type: %#x\n", *pFormat); - /* FIXME: raise an exception */ - esize = 0; - } - - memsize = safe_multiply(esize, pStubMsg->MaxCount); - bufsize = safe_multiply(esize, pStubMsg->ActualCount); - - /* strings must always have null terminating bytes */ - if (bufsize < esize) - { - ERR("invalid string length of %d\n", pStubMsg->ActualCount); - RpcRaiseException(RPC_S_INVALID_BOUND); - return NULL; - } - - /* verify the buffer is safe to access */ - if ((pStubMsg->Buffer + bufsize < pStubMsg->Buffer) || - (pStubMsg->Buffer + bufsize > pStubMsg->BufferEnd)) - { - ERR("bufsize 0x%x exceeded buffer end %p of buffer %p\n", bufsize, - pStubMsg->BufferEnd, pStubMsg->Buffer); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - return NULL; - } - - for (i = bufsize - esize; i < bufsize; i++) - if (pStubMsg->Buffer[i] != 0) - { - ERR("string not null-terminated at byte position %d, data is 0x%x\n", - i, pStubMsg->Buffer[i]); - RpcRaiseException(RPC_S_INVALID_BOUND); - return NULL; - } - - if (fMustAlloc) - *ppMemory = NdrAllocate(pStubMsg, memsize); - else - { - if (!pStubMsg->IsClient && !*ppMemory && (pStubMsg->MaxCount == pStubMsg->ActualCount)) - /* if the data in the RPC buffer is big enough, we just point straight - * into it */ - *ppMemory = pStubMsg->Buffer; - else if (!*ppMemory) - *ppMemory = NdrAllocate(pStubMsg, memsize); - } - - if (*ppMemory == pStubMsg->Buffer) - safe_buffer_increment(pStubMsg, bufsize); - else - safe_copy_from_buffer(pStubMsg, *ppMemory, bufsize); - - if (*pFormat == RPC_FC_C_CSTRING) { - TRACE("string=%s\n", debugstr_a((char*)*ppMemory)); - } - else if (*pFormat == RPC_FC_C_WSTRING) { - TRACE("string=%s\n", debugstr_w((LPWSTR)*ppMemory)); - } - - return NULL; /* FIXME: is this always right? */ -} - -/*********************************************************************** - * NdrNonConformantStringMarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrNonConformantStringMarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - ULONG esize, size, maxsize; - - TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat); - - maxsize = *(USHORT *)&pFormat[2]; - - if (*pFormat == RPC_FC_CSTRING) - { - ULONG i; - const char *str = (const char *)pMemory; - for (i = 0; i < maxsize && *str; i++, str++) - ; - TRACE("string=%s\n", debugstr_an(str, i)); - pStubMsg->ActualCount = i + 1; - esize = 1; - } - else if (*pFormat == RPC_FC_WSTRING) - { - ULONG i; - const WCHAR *str = (const WCHAR *)pMemory; - for (i = 0; i < maxsize && *str; i++, str++) - ; - TRACE("string=%s\n", debugstr_wn(str, i)); - pStubMsg->ActualCount = i + 1; - esize = 2; - } - else - { - ERR("Unhandled string type: %#x\n", *pFormat); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - } - - pStubMsg->Offset = 0; - WriteVariance(pStubMsg); - - size = safe_multiply(esize, pStubMsg->ActualCount); - safe_copy_to_buffer(pStubMsg, pMemory, size); /* the string itself */ - - return NULL; -} - -/*********************************************************************** - * NdrNonConformantStringUnmarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrNonConformantStringUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char **ppMemory, - PFORMAT_STRING pFormat, - unsigned char fMustAlloc) -{ - ULONG bufsize, memsize, esize, i, maxsize; - - TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n", - pStubMsg, *ppMemory, pFormat, fMustAlloc); - - maxsize = *(USHORT *)&pFormat[2]; - - ReadVariance(pStubMsg, NULL, maxsize); - if (pStubMsg->Offset) - { - ERR("non-conformant strings can't have Offset (%d)\n", pStubMsg->Offset); - RpcRaiseException(RPC_S_INVALID_BOUND); - } - - if (*pFormat == RPC_FC_CSTRING) esize = 1; - else if (*pFormat == RPC_FC_WSTRING) esize = 2; - else - { - ERR("Unhandled string type: %#x\n", *pFormat); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - } - - memsize = esize * maxsize; - bufsize = safe_multiply(esize, pStubMsg->ActualCount); - - if (bufsize < esize) - { - ERR("invalid string length of %d\n", pStubMsg->ActualCount); - RpcRaiseException(RPC_S_INVALID_BOUND); - return NULL; - } - - /* verify the buffer is safe to access */ - if ((pStubMsg->Buffer + bufsize < pStubMsg->Buffer) || - (pStubMsg->Buffer + bufsize > pStubMsg->BufferEnd)) - { - ERR("bufsize 0x%x exceeded buffer end %p of buffer %p\n", bufsize, - pStubMsg->BufferEnd, pStubMsg->Buffer); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - return NULL; - } - - /* strings must always have null terminating bytes */ - for (i = bufsize - esize; i < bufsize; i++) - if (pStubMsg->Buffer[i] != 0) - { - ERR("string not null-terminated at byte position %d, data is 0x%x\n", - i, pStubMsg->Buffer[i]); - RpcRaiseException(RPC_S_INVALID_BOUND); - } - - if (fMustAlloc || !*ppMemory) - *ppMemory = NdrAllocate(pStubMsg, memsize); - - safe_copy_from_buffer(pStubMsg, *ppMemory, bufsize); - - if (*pFormat == RPC_FC_CSTRING) { - TRACE("string=%s\n", debugstr_an((char*)*ppMemory, pStubMsg->ActualCount)); - } - else if (*pFormat == RPC_FC_WSTRING) { - TRACE("string=%s\n", debugstr_wn((LPWSTR)*ppMemory, pStubMsg->ActualCount)); - } - - return NULL; -} - -/*********************************************************************** - * NdrNonConformantStringBufferSize [RPCRT4.@] - */ -void WINAPI NdrNonConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - ULONG esize, maxsize; - - TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat); - - maxsize = *(USHORT *)&pFormat[2]; - - SizeVariance(pStubMsg); - - if (*pFormat == RPC_FC_CSTRING) - { - ULONG i; - const char *str = (const char *)pMemory; - for (i = 0; i < maxsize && *str; i++, str++) - ; - TRACE("string=%s\n", debugstr_an(str, i)); - pStubMsg->ActualCount = i + 1; - esize = 1; - } - else if (*pFormat == RPC_FC_WSTRING) - { - ULONG i; - const WCHAR *str = (const WCHAR *)pMemory; - for (i = 0; i < maxsize && *str; i++, str++) - ; - TRACE("string=%s\n", debugstr_wn(str, i)); - pStubMsg->ActualCount = i + 1; - esize = 2; - } - else - { - ERR("Unhandled string type: %#x\n", *pFormat); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - } - - safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount)); -} - -/*********************************************************************** - * NdrNonConformantStringMemorySize [RPCRT4.@] - */ -ULONG WINAPI NdrNonConformantStringMemorySize(PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat) -{ - ULONG bufsize, memsize, esize, i, maxsize; - - TRACE("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat); - - maxsize = *(USHORT *)&pFormat[2]; - - ReadVariance(pStubMsg, NULL, maxsize); - - if (pStubMsg->Offset) - { - ERR("non-conformant strings can't have Offset (%d)\n", pStubMsg->Offset); - RpcRaiseException(RPC_S_INVALID_BOUND); - } - - if (*pFormat == RPC_FC_CSTRING) esize = 1; - else if (*pFormat == RPC_FC_WSTRING) esize = 2; - else - { - ERR("Unhandled string type: %#x\n", *pFormat); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - } - - memsize = esize * maxsize; - bufsize = safe_multiply(esize, pStubMsg->ActualCount); - - /* strings must always have null terminating bytes */ - if (bufsize < esize) - { - ERR("invalid string length of %d\n", pStubMsg->ActualCount); - RpcRaiseException(RPC_S_INVALID_BOUND); - } - - /* verify the buffer is safe to access */ - if ((pStubMsg->Buffer + bufsize < pStubMsg->Buffer) || - (pStubMsg->Buffer + bufsize > pStubMsg->BufferEnd)) - { - ERR("bufsize 0x%x exceeded buffer end %p of buffer %p\n", bufsize, - pStubMsg->BufferEnd, pStubMsg->Buffer); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - } - - for (i = bufsize - esize; i < bufsize; i++) - if (pStubMsg->Buffer[i] != 0) - { - ERR("string not null-terminated at byte position %d, data is 0x%x\n", - i, pStubMsg->Buffer[i]); - RpcRaiseException(RPC_S_INVALID_BOUND); - } - - safe_buffer_increment(pStubMsg, bufsize); - pStubMsg->MemorySize += memsize; - - return pStubMsg->MemorySize; -} - -static inline void dump_pointer_attr(unsigned char attr) -{ - if (attr & RPC_FC_P_ALLOCALLNODES) - TRACE(" RPC_FC_P_ALLOCALLNODES"); - if (attr & RPC_FC_P_DONTFREE) - TRACE(" RPC_FC_P_DONTFREE"); - if (attr & RPC_FC_P_ONSTACK) - TRACE(" RPC_FC_P_ONSTACK"); - if (attr & RPC_FC_P_SIMPLEPOINTER) - TRACE(" RPC_FC_P_SIMPLEPOINTER"); - if (attr & RPC_FC_P_DEREF) - TRACE(" RPC_FC_P_DEREF"); - TRACE("\n"); -} - -/*********************************************************************** - * PointerMarshall [internal] - */ -static void PointerMarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *Buffer, - unsigned char *Pointer, - PFORMAT_STRING pFormat) -{ - unsigned type = pFormat[0], attr = pFormat[1]; - PFORMAT_STRING desc; - NDR_MARSHALL m; - ULONG pointer_id; - int pointer_needs_marshaling; - - TRACE("(%p,%p,%p,%p)\n", pStubMsg, Buffer, Pointer, pFormat); - TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr); - pFormat += 2; - if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat; - else desc = pFormat + *(const SHORT*)pFormat; - - switch (type) { - case RPC_FC_RP: /* ref pointer (always non-null) */ - if (!Pointer) - { - ERR("NULL ref pointer is not allowed\n"); - RpcRaiseException(RPC_X_NULL_REF_POINTER); - } - pointer_needs_marshaling = 1; - break; - case RPC_FC_UP: /* unique pointer */ - case RPC_FC_OP: /* object pointer - same as unique here */ - if (Pointer) - pointer_needs_marshaling = 1; - else - pointer_needs_marshaling = 0; - pointer_id = (ULONG)Pointer; - TRACE("writing 0x%08x to buffer\n", pointer_id); - NDR_LOCAL_UINT32_WRITE(Buffer, pointer_id); - break; - case RPC_FC_FP: - pointer_needs_marshaling = !NdrFullPointerQueryPointer( - pStubMsg->FullPtrXlatTables, Pointer, 1, &pointer_id); - TRACE("writing 0x%08x to buffer\n", pointer_id); - NDR_LOCAL_UINT32_WRITE(Buffer, pointer_id); - break; - default: - FIXME("unhandled ptr type=%02x\n", type); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - return; - } - - TRACE("calling marshaller for type 0x%x\n", (int)*desc); - - if (pointer_needs_marshaling) { - if (attr & RPC_FC_P_DEREF) { - Pointer = *(unsigned char**)Pointer; - TRACE("deref => %p\n", Pointer); - } - m = NdrMarshaller[*desc & NDR_TABLE_MASK]; - if (m) m(pStubMsg, Pointer, desc); - else FIXME("no marshaller for data type=%02x\n", *desc); - } - - STD_OVERFLOW_CHECK(pStubMsg); -} - -/*********************************************************************** - * PointerUnmarshall [internal] - */ -static void PointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *Buffer, - unsigned char **pPointer, - unsigned char *pSrcPointer, - PFORMAT_STRING pFormat, - unsigned char fMustAlloc) -{ - unsigned type = pFormat[0], attr = pFormat[1]; - PFORMAT_STRING desc; - NDR_UNMARSHALL m; - DWORD pointer_id = 0; - int pointer_needs_unmarshaling; - - TRACE("(%p,%p,%p,%p,%p,%d)\n", pStubMsg, Buffer, pPointer, pSrcPointer, pFormat, fMustAlloc); - TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr); - pFormat += 2; - if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat; - else desc = pFormat + *(const SHORT*)pFormat; - - switch (type) { - case RPC_FC_RP: /* ref pointer (always non-null) */ - pointer_needs_unmarshaling = 1; - break; - case RPC_FC_UP: /* unique pointer */ - pointer_id = NDR_LOCAL_UINT32_READ(Buffer); - TRACE("pointer_id is 0x%08x\n", pointer_id); - if (pointer_id) - pointer_needs_unmarshaling = 1; - else { - *pPointer = NULL; - pointer_needs_unmarshaling = 0; - } - break; - case RPC_FC_OP: /* object pointer - we must free data before overwriting it */ - pointer_id = NDR_LOCAL_UINT32_READ(Buffer); - TRACE("pointer_id is 0x%08x\n", pointer_id); - if (!fMustAlloc && pSrcPointer) - { - FIXME("free object pointer %p\n", pSrcPointer); - fMustAlloc = TRUE; - } - if (pointer_id) - pointer_needs_unmarshaling = 1; - else - pointer_needs_unmarshaling = 0; - break; - case RPC_FC_FP: - pointer_id = NDR_LOCAL_UINT32_READ(Buffer); - TRACE("pointer_id is 0x%08x\n", pointer_id); - pointer_needs_unmarshaling = !NdrFullPointerQueryRefId( - pStubMsg->FullPtrXlatTables, pointer_id, 1, (void **)pPointer); - break; - default: - FIXME("unhandled ptr type=%02x\n", type); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - return; - } - - if (pointer_needs_unmarshaling) { - unsigned char *base_ptr_val = *pPointer; - unsigned char **current_ptr = pPointer; - if (pStubMsg->IsClient) { - TRACE("client\n"); - /* if we aren't forcing allocation of memory then try to use the existing - * (source) pointer to unmarshall the data into so that [in,out] - * parameters behave correctly. it doesn't matter if the parameter is - * [out] only since in that case the pointer will be NULL. we force - * allocation when the source pointer is NULL here instead of in the type - * unmarshalling routine for the benefit of the deref code below */ - if (!fMustAlloc) { - if (pSrcPointer) { - TRACE("setting *pPointer to %p\n", pSrcPointer); - *pPointer = base_ptr_val = pSrcPointer; - } else - fMustAlloc = TRUE; - } - } else { - TRACE("server\n"); - /* the memory in a stub is never initialised, so we have to work out here - * whether we have to initialise it so we can use the optimisation of - * setting the pointer to the buffer, if possible, or set fMustAlloc to - * TRUE. */ - if (attr & RPC_FC_P_DEREF) { - fMustAlloc = TRUE; - } else { - base_ptr_val = NULL; - *current_ptr = NULL; - } - } - - if (attr & RPC_FC_P_ALLOCALLNODES) - FIXME("RPC_FC_P_ALLOCALLNODES not implemented\n"); - - if (attr & RPC_FC_P_DEREF) { - if (fMustAlloc) { - base_ptr_val = NdrAllocate(pStubMsg, sizeof(void *)); - *pPointer = base_ptr_val; - current_ptr = (unsigned char **)base_ptr_val; - } else - current_ptr = *(unsigned char***)current_ptr; - TRACE("deref => %p\n", current_ptr); - if (!fMustAlloc && !*current_ptr) fMustAlloc = TRUE; - } - m = NdrUnmarshaller[*desc & NDR_TABLE_MASK]; - if (m) m(pStubMsg, current_ptr, desc, fMustAlloc); - else FIXME("no unmarshaller for data type=%02x\n", *desc); - - if (type == RPC_FC_FP) - NdrFullPointerInsertRefId(pStubMsg->FullPtrXlatTables, pointer_id, - base_ptr_val); - } - - TRACE("pointer=%p\n", *pPointer); -} - -/*********************************************************************** - * PointerBufferSize [internal] - */ -static void PointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *Pointer, - PFORMAT_STRING pFormat) -{ - unsigned type = pFormat[0], attr = pFormat[1]; - PFORMAT_STRING desc; - NDR_BUFFERSIZE m; - int pointer_needs_sizing; - ULONG pointer_id; - - TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat); - TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr); - pFormat += 2; - if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat; - else desc = pFormat + *(const SHORT*)pFormat; - - switch (type) { - case RPC_FC_RP: /* ref pointer (always non-null) */ - if (!Pointer) - { - ERR("NULL ref pointer is not allowed\n"); - RpcRaiseException(RPC_X_NULL_REF_POINTER); - } - break; - case RPC_FC_OP: - case RPC_FC_UP: - /* NULL pointer has no further representation */ - if (!Pointer) - return; - break; - case RPC_FC_FP: - pointer_needs_sizing = !NdrFullPointerQueryPointer( - pStubMsg->FullPtrXlatTables, Pointer, 0, &pointer_id); - if (!pointer_needs_sizing) - return; - break; - default: - FIXME("unhandled ptr type=%02x\n", type); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - return; - } - - if (attr & RPC_FC_P_DEREF) { - Pointer = *(unsigned char**)Pointer; - TRACE("deref => %p\n", Pointer); - } - - m = NdrBufferSizer[*desc & NDR_TABLE_MASK]; - if (m) m(pStubMsg, Pointer, desc); - else FIXME("no buffersizer for data type=%02x\n", *desc); -} - -/*********************************************************************** - * PointerMemorySize [internal] - */ -static unsigned long PointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *Buffer, - PFORMAT_STRING pFormat) -{ - unsigned type = pFormat[0], attr = pFormat[1]; - PFORMAT_STRING desc; - NDR_MEMORYSIZE m; - DWORD pointer_id = 0; - int pointer_needs_sizing; - - TRACE("(%p,%p,%p)\n", pStubMsg, Buffer, pFormat); - TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr); - pFormat += 2; - if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat; - else desc = pFormat + *(const SHORT*)pFormat; - - switch (type) { - case RPC_FC_RP: /* ref pointer (always non-null) */ - pointer_needs_sizing = 1; - break; - case RPC_FC_UP: /* unique pointer */ - case RPC_FC_OP: /* object pointer - we must free data before overwriting it */ - pointer_id = NDR_LOCAL_UINT32_READ(Buffer); - TRACE("pointer_id is 0x%08x\n", pointer_id); - if (pointer_id) - pointer_needs_sizing = 1; - else - pointer_needs_sizing = 0; - break; - case RPC_FC_FP: - { - void *pointer; - pointer_id = NDR_LOCAL_UINT32_READ(Buffer); - TRACE("pointer_id is 0x%08x\n", pointer_id); - pointer_needs_sizing = !NdrFullPointerQueryRefId( - pStubMsg->FullPtrXlatTables, pointer_id, 1, &pointer); - break; - } - default: - FIXME("unhandled ptr type=%02x\n", type); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - return 0; - } - - if (attr & RPC_FC_P_DEREF) { - TRACE("deref\n"); - } - - if (pointer_needs_sizing) { - m = NdrMemorySizer[*desc & NDR_TABLE_MASK]; - if (m) m(pStubMsg, desc); - else FIXME("no memorysizer for data type=%02x\n", *desc); - } - - return pStubMsg->MemorySize; -} - -/*********************************************************************** - * PointerFree [internal] - */ -static void PointerFree(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *Pointer, - PFORMAT_STRING pFormat) -{ - unsigned type = pFormat[0], attr = pFormat[1]; - PFORMAT_STRING desc; - NDR_FREE m; - unsigned char *current_pointer = Pointer; - - TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat); - TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr); - if (attr & RPC_FC_P_DONTFREE) return; - pFormat += 2; - if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat; - else desc = pFormat + *(const SHORT*)pFormat; - - if (!Pointer) return; - - if (type == RPC_FC_FP) { - int pointer_needs_freeing = NdrFullPointerFree( - pStubMsg->FullPtrXlatTables, Pointer); - if (!pointer_needs_freeing) - return; - } - - if (attr & RPC_FC_P_DEREF) { - current_pointer = *(unsigned char**)Pointer; - TRACE("deref => %p\n", current_pointer); - } - - m = NdrFreer[*desc & NDR_TABLE_MASK]; - if (m) m(pStubMsg, current_pointer, desc); - - /* this check stops us from trying to free buffer memory. we don't have to - * worry about clients, since they won't call this function. - * we don't have to check for the buffer being reallocated because - * BufferStart and BufferEnd won't be reset when allocating memory for - * sending the response. we don't have to check for the new buffer here as - * it won't be used a type memory, only for buffer memory */ - if (Pointer >= (unsigned char *)pStubMsg->BufferStart && - Pointer < (unsigned char *)pStubMsg->BufferEnd) - goto notfree; - - if (attr & RPC_FC_P_ONSTACK) { - TRACE("not freeing stack ptr %p\n", Pointer); - return; - } - TRACE("freeing %p\n", Pointer); - NdrFree(pStubMsg, Pointer); - return; -notfree: - TRACE("not freeing %p\n", Pointer); -} - -/*********************************************************************** - * EmbeddedPointerMarshall - */ -static unsigned char * EmbeddedPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - unsigned char *Mark = pStubMsg->BufferMark; - unsigned rep, count, stride; - unsigned i; - unsigned char *saved_buffer = NULL; - - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - - if (*pFormat != RPC_FC_PP) return NULL; - pFormat += 2; - - if (pStubMsg->PointerBufferMark) - { - saved_buffer = pStubMsg->Buffer; - pStubMsg->Buffer = pStubMsg->PointerBufferMark; - pStubMsg->PointerBufferMark = NULL; - } - - while (pFormat[0] != RPC_FC_END) { - switch (pFormat[0]) { - default: - FIXME("unknown repeat type %d\n", pFormat[0]); - case RPC_FC_NO_REPEAT: - rep = 1; - stride = 0; - count = 1; - pFormat += 2; - break; - case RPC_FC_FIXED_REPEAT: - rep = *(const WORD*)&pFormat[2]; - stride = *(const WORD*)&pFormat[4]; - count = *(const WORD*)&pFormat[8]; - pFormat += 10; - break; - case RPC_FC_VARIABLE_REPEAT: - rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount; - stride = *(const WORD*)&pFormat[2]; - count = *(const WORD*)&pFormat[6]; - pFormat += 8; - break; - } - for (i = 0; i < rep; i++) { - PFORMAT_STRING info = pFormat; - unsigned char *membase = pMemory + (i * stride); - unsigned char *bufbase = Mark + (i * stride); - unsigned u; - - for (u=0; uMemory; - - pStubMsg->Memory = pMemory; - PointerMarshall(pStubMsg, bufptr, *(unsigned char**)memptr, info+4); - pStubMsg->Memory = saved_memory; - } - } - pFormat += 8 * count; - } - - if (saved_buffer) - { - pStubMsg->PointerBufferMark = pStubMsg->Buffer; - pStubMsg->Buffer = saved_buffer; - } - - STD_OVERFLOW_CHECK(pStubMsg); - - return NULL; -} - -/*********************************************************************** - * EmbeddedPointerUnmarshall - */ -static unsigned char * EmbeddedPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pDstMemoryPtrs, - unsigned char *pSrcMemoryPtrs, - PFORMAT_STRING pFormat, - unsigned char fMustAlloc) -{ - unsigned char *Mark = pStubMsg->BufferMark; - unsigned rep, count, stride; - unsigned i; - unsigned char *saved_buffer = NULL; - - TRACE("(%p,%p,%p,%p,%d)\n", pStubMsg, pDstMemoryPtrs, pSrcMemoryPtrs, pFormat, fMustAlloc); - - if (*pFormat != RPC_FC_PP) return NULL; - pFormat += 2; - - if (pStubMsg->PointerBufferMark) - { - saved_buffer = pStubMsg->Buffer; - pStubMsg->Buffer = pStubMsg->PointerBufferMark; - pStubMsg->PointerBufferMark = NULL; - } - - while (pFormat[0] != RPC_FC_END) { - TRACE("pFormat[0] = 0x%x\n", pFormat[0]); - switch (pFormat[0]) { - default: - FIXME("unknown repeat type %d\n", pFormat[0]); - case RPC_FC_NO_REPEAT: - rep = 1; - stride = 0; - count = 1; - pFormat += 2; - break; - case RPC_FC_FIXED_REPEAT: - rep = *(const WORD*)&pFormat[2]; - stride = *(const WORD*)&pFormat[4]; - count = *(const WORD*)&pFormat[8]; - pFormat += 10; - break; - case RPC_FC_VARIABLE_REPEAT: - rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount; - stride = *(const WORD*)&pFormat[2]; - count = *(const WORD*)&pFormat[6]; - pFormat += 8; - break; - } - for (i = 0; i < rep; i++) { - PFORMAT_STRING info = pFormat; - unsigned char *memdstbase = pDstMemoryPtrs + (i * stride); - unsigned char *memsrcbase = pSrcMemoryPtrs + (i * stride); - unsigned char *bufbase = Mark + (i * stride); - unsigned u; - - for (u=0; uPointerBufferMark = pStubMsg->Buffer; - pStubMsg->Buffer = saved_buffer; - } - - return NULL; -} - -/*********************************************************************** - * EmbeddedPointerBufferSize - */ -static void EmbeddedPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - unsigned rep, count, stride; - unsigned i; - ULONG saved_buffer_length = 0; - - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - - if (pStubMsg->IgnoreEmbeddedPointers) return; - - if (*pFormat != RPC_FC_PP) return; - pFormat += 2; - - if (pStubMsg->PointerLength) - { - saved_buffer_length = pStubMsg->BufferLength; - pStubMsg->BufferLength = pStubMsg->PointerLength; - pStubMsg->PointerLength = 0; - } - - while (pFormat[0] != RPC_FC_END) { - switch (pFormat[0]) { - default: - FIXME("unknown repeat type %d\n", pFormat[0]); - case RPC_FC_NO_REPEAT: - rep = 1; - stride = 0; - count = 1; - pFormat += 2; - break; - case RPC_FC_FIXED_REPEAT: - rep = *(const WORD*)&pFormat[2]; - stride = *(const WORD*)&pFormat[4]; - count = *(const WORD*)&pFormat[8]; - pFormat += 10; - break; - case RPC_FC_VARIABLE_REPEAT: - rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount; - stride = *(const WORD*)&pFormat[2]; - count = *(const WORD*)&pFormat[6]; - pFormat += 8; - break; - } - for (i = 0; i < rep; i++) { - PFORMAT_STRING info = pFormat; - unsigned char *membase = pMemory + (i * stride); - unsigned u; - - for (u=0; uMemory; - - pStubMsg->Memory = pMemory; - PointerBufferSize(pStubMsg, *(unsigned char**)memptr, info+4); - pStubMsg->Memory = saved_memory; - } - } - pFormat += 8 * count; - } - - if (saved_buffer_length) - { - pStubMsg->PointerLength = pStubMsg->BufferLength; - pStubMsg->BufferLength = saved_buffer_length; - } -} - -/*********************************************************************** - * EmbeddedPointerMemorySize [internal] - */ -static unsigned long EmbeddedPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat) -{ - unsigned char *Mark = pStubMsg->BufferMark; - unsigned rep, count, stride; - unsigned i; - unsigned char *saved_buffer = NULL; - - TRACE("(%p,%p)\n", pStubMsg, pFormat); - - if (pStubMsg->IgnoreEmbeddedPointers) return 0; - - if (pStubMsg->PointerBufferMark) - { - saved_buffer = pStubMsg->Buffer; - pStubMsg->Buffer = pStubMsg->PointerBufferMark; - pStubMsg->PointerBufferMark = NULL; - } - - if (*pFormat != RPC_FC_PP) return 0; - pFormat += 2; - - while (pFormat[0] != RPC_FC_END) { - switch (pFormat[0]) { - default: - FIXME("unknown repeat type %d\n", pFormat[0]); - case RPC_FC_NO_REPEAT: - rep = 1; - stride = 0; - count = 1; - pFormat += 2; - break; - case RPC_FC_FIXED_REPEAT: - rep = *(const WORD*)&pFormat[2]; - stride = *(const WORD*)&pFormat[4]; - count = *(const WORD*)&pFormat[8]; - pFormat += 10; - break; - case RPC_FC_VARIABLE_REPEAT: - rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount; - stride = *(const WORD*)&pFormat[2]; - count = *(const WORD*)&pFormat[6]; - pFormat += 8; - break; - } - for (i = 0; i < rep; i++) { - PFORMAT_STRING info = pFormat; - unsigned char *bufbase = Mark + (i * stride); - unsigned u; - for (u=0; uPointerBufferMark = pStubMsg->Buffer; - pStubMsg->Buffer = saved_buffer; - } - - return 0; -} - -/*********************************************************************** - * EmbeddedPointerFree [internal] - */ -static void EmbeddedPointerFree(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - unsigned rep, count, stride; - unsigned i; - - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - if (*pFormat != RPC_FC_PP) return; - pFormat += 2; - - while (pFormat[0] != RPC_FC_END) { - switch (pFormat[0]) { - default: - FIXME("unknown repeat type %d\n", pFormat[0]); - case RPC_FC_NO_REPEAT: - rep = 1; - stride = 0; - count = 1; - pFormat += 2; - break; - case RPC_FC_FIXED_REPEAT: - rep = *(const WORD*)&pFormat[2]; - stride = *(const WORD*)&pFormat[4]; - count = *(const WORD*)&pFormat[8]; - pFormat += 10; - break; - case RPC_FC_VARIABLE_REPEAT: - rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount; - stride = *(const WORD*)&pFormat[2]; - count = *(const WORD*)&pFormat[6]; - pFormat += 8; - break; - } - for (i = 0; i < rep; i++) { - PFORMAT_STRING info = pFormat; - unsigned char *membase = pMemory + (i * stride); - unsigned u; - - for (u=0; uMemory; - - pStubMsg->Memory = pMemory; - PointerFree(pStubMsg, *(unsigned char**)memptr, info+4); - pStubMsg->Memory = saved_memory; - } - } - pFormat += 8 * count; - } -} - -/*********************************************************************** - * NdrPointerMarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - unsigned char *Buffer; - - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - - /* incremement the buffer here instead of in PointerMarshall, - * as that is used by embedded pointers which already handle the incrementing - * the buffer, and shouldn't write any additional pointer data to the wire */ - if (*pFormat != RPC_FC_RP) - { - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4); - Buffer = pStubMsg->Buffer; - safe_buffer_increment(pStubMsg, 4); - } - else - Buffer = pStubMsg->Buffer; - - PointerMarshall(pStubMsg, Buffer, pMemory, pFormat); - - return NULL; -} - -/*********************************************************************** - * NdrPointerUnmarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char **ppMemory, - PFORMAT_STRING pFormat, - unsigned char fMustAlloc) -{ - unsigned char *Buffer; - - TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); - - /* incremement the buffer here instead of in PointerUnmarshall, - * 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 */ - if (*pFormat != RPC_FC_RP) - { - ALIGN_POINTER(pStubMsg->Buffer, 4); - Buffer = pStubMsg->Buffer; - safe_buffer_increment(pStubMsg, 4); - } - else - Buffer = pStubMsg->Buffer; - - PointerUnmarshall(pStubMsg, Buffer, ppMemory, *ppMemory, pFormat, fMustAlloc); - - return NULL; -} - -/*********************************************************************** - * NdrPointerBufferSize [RPCRT4.@] - */ -void WINAPI NdrPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - - /* incremement the buffer length here instead of in PointerBufferSize, - * as that is used by embedded pointers which already handle the buffer - * length, and shouldn't write anything more to the wire */ - if (*pFormat != RPC_FC_RP) - { - ALIGN_LENGTH(pStubMsg->BufferLength, 4); - safe_buffer_length_increment(pStubMsg, 4); - } - - PointerBufferSize(pStubMsg, pMemory, pFormat); -} - -/*********************************************************************** - * NdrPointerMemorySize [RPCRT4.@] - */ -ULONG WINAPI NdrPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat) -{ - /* unsigned size = *(LPWORD)(pFormat+2); */ - FIXME("(%p,%p): stub\n", pStubMsg, pFormat); - PointerMemorySize(pStubMsg, pStubMsg->Buffer, pFormat); - return 0; -} - -/*********************************************************************** - * NdrPointerFree [RPCRT4.@] - */ -void WINAPI NdrPointerFree(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - PointerFree(pStubMsg, pMemory, pFormat); -} - -/*********************************************************************** - * NdrSimpleTypeMarshall [RPCRT4.@] - */ -void WINAPI NdrSimpleTypeMarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, - unsigned char FormatChar ) -{ - NdrBaseTypeMarshall(pStubMsg, pMemory, &FormatChar); -} - -/*********************************************************************** - * NdrSimpleTypeUnmarshall [RPCRT4.@] - */ -void WINAPI NdrSimpleTypeUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, - unsigned char FormatChar ) -{ - NdrBaseTypeUnmarshall(pStubMsg, &pMemory, &FormatChar, 0); -} - -/*********************************************************************** - * NdrSimpleStructMarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrSimpleStructMarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - unsigned size = *(const WORD*)(pFormat+2); - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pFormat[1] + 1); - - pStubMsg->BufferMark = pStubMsg->Buffer; - safe_copy_to_buffer(pStubMsg, pMemory, size); - - if (pFormat[0] != RPC_FC_STRUCT) - EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat+4); - - return NULL; -} - -/*********************************************************************** - * NdrSimpleStructUnmarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrSimpleStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char **ppMemory, - PFORMAT_STRING pFormat, - unsigned char fMustAlloc) -{ - unsigned size = *(const WORD*)(pFormat+2); - unsigned char *saved_buffer; - TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); - - ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1); - - if (fMustAlloc) - *ppMemory = NdrAllocate(pStubMsg, size); - else - { - if (!pStubMsg->IsClient && !*ppMemory) - /* for servers, we just point straight into the RPC buffer */ - *ppMemory = pStubMsg->Buffer; - } - - saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer; - safe_buffer_increment(pStubMsg, size); - if (pFormat[0] == RPC_FC_PSTRUCT) - EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat+4, fMustAlloc); - - TRACE("copying %p to %p\n", saved_buffer, *ppMemory); - if (*ppMemory != saved_buffer) - memcpy(*ppMemory, saved_buffer, size); - - return NULL; -} - -/*********************************************************************** - * NdrSimpleStructBufferSize [RPCRT4.@] - */ -void WINAPI NdrSimpleStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - unsigned size = *(const WORD*)(pFormat+2); - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - - ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1); - - safe_buffer_length_increment(pStubMsg, size); - if (pFormat[0] != RPC_FC_STRUCT) - EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat+4); -} - -/*********************************************************************** - * NdrSimpleStructMemorySize [RPCRT4.@] - */ -ULONG WINAPI NdrSimpleStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat) -{ - unsigned short size = *(const WORD *)(pFormat+2); - - TRACE("(%p,%p)\n", pStubMsg, pFormat); - - ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1); - pStubMsg->MemorySize += size; - safe_buffer_increment(pStubMsg, size); - - if (pFormat[0] != RPC_FC_STRUCT) - EmbeddedPointerMemorySize(pStubMsg, pFormat+4); - return pStubMsg->MemorySize; -} - -/*********************************************************************** - * NdrSimpleStructFree [RPCRT4.@] - */ -void WINAPI NdrSimpleStructFree(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - if (pFormat[0] != RPC_FC_STRUCT) - EmbeddedPointerFree(pStubMsg, pMemory, pFormat+4); -} - - -static unsigned long EmbeddedComplexSize(const MIDL_STUB_MESSAGE *pStubMsg, - PFORMAT_STRING pFormat) -{ - switch (*pFormat) { - case RPC_FC_STRUCT: - case RPC_FC_PSTRUCT: - case RPC_FC_CSTRUCT: - case RPC_FC_BOGUS_STRUCT: - case RPC_FC_SMFARRAY: - case RPC_FC_SMVARRAY: - return *(const WORD*)&pFormat[2]; - case RPC_FC_USER_MARSHAL: - return *(const WORD*)&pFormat[4]; - case RPC_FC_NON_ENCAPSULATED_UNION: - pFormat += 2; - if (pStubMsg->fHasNewCorrDesc) - pFormat += 6; - else - pFormat += 4; - - pFormat += *(const SHORT*)pFormat; - return *(const SHORT*)pFormat; - case RPC_FC_IP: - return sizeof(void *); - default: - FIXME("unhandled embedded type %02x\n", *pFormat); - } - return 0; -} - - -static unsigned long EmbeddedComplexMemorySize(PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat) -{ - NDR_MEMORYSIZE m = NdrMemorySizer[*pFormat & NDR_TABLE_MASK]; - - if (!m) - { - FIXME("no memorysizer for data type=%02x\n", *pFormat); - return 0; - } - - return m(pStubMsg, pFormat); -} - - -static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat, - PFORMAT_STRING pPointer) -{ - PFORMAT_STRING desc; - NDR_MARSHALL m; - unsigned long size; - - while (*pFormat != RPC_FC_END) { - switch (*pFormat) { - case RPC_FC_BYTE: - case RPC_FC_CHAR: - case RPC_FC_SMALL: - case RPC_FC_USMALL: - TRACE("byte=%d <= %p\n", *(WORD*)pMemory, pMemory); - safe_copy_to_buffer(pStubMsg, pMemory, 1); - pMemory += 1; - break; - case RPC_FC_WCHAR: - case RPC_FC_SHORT: - case RPC_FC_USHORT: - TRACE("short=%d <= %p\n", *(WORD*)pMemory, pMemory); - safe_copy_to_buffer(pStubMsg, pMemory, 2); - pMemory += 2; - break; - case RPC_FC_LONG: - case RPC_FC_ULONG: - case RPC_FC_ENUM32: - TRACE("long=%d <= %p\n", *(DWORD*)pMemory, pMemory); - safe_copy_to_buffer(pStubMsg, pMemory, 4); - pMemory += 4; - break; - case RPC_FC_HYPER: - TRACE("longlong=%s <= %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory); - safe_copy_to_buffer(pStubMsg, pMemory, 8); - pMemory += 8; - break; - case RPC_FC_POINTER: - { - unsigned char *saved_buffer; - int pointer_buffer_mark_set = 0; - TRACE("pointer=%p <= %p\n", *(unsigned char**)pMemory, pMemory); - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4); - saved_buffer = pStubMsg->Buffer; - if (pStubMsg->PointerBufferMark) - { - pStubMsg->Buffer = pStubMsg->PointerBufferMark; - pStubMsg->PointerBufferMark = NULL; - pointer_buffer_mark_set = 1; - } - else - safe_buffer_increment(pStubMsg, 4); /* for pointer ID */ - PointerMarshall(pStubMsg, saved_buffer, *(unsigned char**)pMemory, pPointer); - if (pointer_buffer_mark_set) - { - STD_OVERFLOW_CHECK(pStubMsg); - pStubMsg->PointerBufferMark = pStubMsg->Buffer; - if (saved_buffer + 4 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) - { - ERR("buffer overflow - saved_buffer = %p, BufferEnd = %p\n", - saved_buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - } - pStubMsg->Buffer = saved_buffer + 4; - } - pPointer += 4; - pMemory += 4; - break; - } - case RPC_FC_ALIGNM4: - ALIGN_POINTER(pMemory, 4); - break; - case RPC_FC_ALIGNM8: - ALIGN_POINTER(pMemory, 8); - break; - case RPC_FC_STRUCTPAD1: - case RPC_FC_STRUCTPAD2: - case RPC_FC_STRUCTPAD3: - case RPC_FC_STRUCTPAD4: - case RPC_FC_STRUCTPAD5: - case RPC_FC_STRUCTPAD6: - case RPC_FC_STRUCTPAD7: - pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1; - break; - case RPC_FC_EMBEDDED_COMPLEX: - pMemory += pFormat[1]; - pFormat += 2; - desc = pFormat + *(const SHORT*)pFormat; - size = EmbeddedComplexSize(pStubMsg, desc); - TRACE("embedded complex (size=%ld) <= %p\n", size, pMemory); - m = NdrMarshaller[*desc & NDR_TABLE_MASK]; - if (m) - { - /* for some reason interface pointers aren't generated as - * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet - * they still need the derefencing treatment that pointers are - * given */ - if (*desc == RPC_FC_IP) - m(pStubMsg, *(unsigned char **)pMemory, desc); - else - m(pStubMsg, pMemory, desc); - } - else FIXME("no marshaller for embedded type %02x\n", *desc); - pMemory += size; - pFormat += 2; - continue; - case RPC_FC_PAD: - break; - default: - FIXME("unhandled format 0x%02x\n", *pFormat); - } - pFormat++; - } - - return pMemory; -} - -static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat, - PFORMAT_STRING pPointer) -{ - PFORMAT_STRING desc; - NDR_UNMARSHALL m; - unsigned long size; - - while (*pFormat != RPC_FC_END) { - switch (*pFormat) { - case RPC_FC_BYTE: - case RPC_FC_CHAR: - case RPC_FC_SMALL: - case RPC_FC_USMALL: - safe_copy_from_buffer(pStubMsg, pMemory, 1); - TRACE("byte=%d => %p\n", *(WORD*)pMemory, pMemory); - pMemory += 1; - break; - case RPC_FC_WCHAR: - case RPC_FC_SHORT: - case RPC_FC_USHORT: - safe_copy_from_buffer(pStubMsg, pMemory, 2); - TRACE("short=%d => %p\n", *(WORD*)pMemory, pMemory); - pMemory += 2; - break; - case RPC_FC_LONG: - case RPC_FC_ULONG: - case RPC_FC_ENUM32: - safe_copy_from_buffer(pStubMsg, pMemory, 4); - TRACE("long=%d => %p\n", *(DWORD*)pMemory, pMemory); - pMemory += 4; - break; - case RPC_FC_HYPER: - safe_copy_from_buffer(pStubMsg, pMemory, 8); - TRACE("longlong=%s => %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory); - pMemory += 8; - break; - case RPC_FC_POINTER: - { - unsigned char *saved_buffer; - int pointer_buffer_mark_set = 0; - TRACE("pointer => %p\n", pMemory); - ALIGN_POINTER(pStubMsg->Buffer, 4); - saved_buffer = pStubMsg->Buffer; - if (pStubMsg->PointerBufferMark) - { - pStubMsg->Buffer = pStubMsg->PointerBufferMark; - pStubMsg->PointerBufferMark = NULL; - pointer_buffer_mark_set = 1; - } - else - safe_buffer_increment(pStubMsg, 4); /* for pointer ID */ - - PointerUnmarshall(pStubMsg, saved_buffer, (unsigned char**)pMemory, *(unsigned char**)pMemory, pPointer, TRUE); - if (pointer_buffer_mark_set) - { - STD_OVERFLOW_CHECK(pStubMsg); - pStubMsg->PointerBufferMark = pStubMsg->Buffer; - if (saved_buffer + 4 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) - { - ERR("buffer overflow - saved_buffer = %p, BufferEnd = %p\n", - saved_buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - } - pStubMsg->Buffer = saved_buffer + 4; - } - pPointer += 4; - pMemory += 4; - break; - } - case RPC_FC_ALIGNM4: - ALIGN_POINTER_CLEAR(pMemory, 4); - break; - case RPC_FC_ALIGNM8: - ALIGN_POINTER_CLEAR(pMemory, 8); - break; - case RPC_FC_STRUCTPAD1: - case RPC_FC_STRUCTPAD2: - case RPC_FC_STRUCTPAD3: - case RPC_FC_STRUCTPAD4: - case RPC_FC_STRUCTPAD5: - case RPC_FC_STRUCTPAD6: - case RPC_FC_STRUCTPAD7: - memset(pMemory, 0, *pFormat - RPC_FC_STRUCTPAD1 + 1); - pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1; - break; - case RPC_FC_EMBEDDED_COMPLEX: - pMemory += pFormat[1]; - pFormat += 2; - desc = pFormat + *(const SHORT*)pFormat; - size = EmbeddedComplexSize(pStubMsg, desc); - TRACE("embedded complex (size=%ld) => %p\n", size, pMemory); - m = NdrUnmarshaller[*desc & NDR_TABLE_MASK]; - memset(pMemory, 0, size); /* just in case */ - if (m) - { - /* for some reason interface pointers aren't generated as - * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet - * they still need the derefencing treatment that pointers are - * given */ - if (*desc == RPC_FC_IP) - m(pStubMsg, (unsigned char **)pMemory, desc, FALSE); - else - m(pStubMsg, &pMemory, desc, FALSE); - } - else FIXME("no unmarshaller for embedded type %02x\n", *desc); - pMemory += size; - pFormat += 2; - continue; - case RPC_FC_PAD: - break; - default: - FIXME("unhandled format %d\n", *pFormat); - } - pFormat++; - } - - return pMemory; -} - -static unsigned char * ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat, - PFORMAT_STRING pPointer) -{ - PFORMAT_STRING desc; - NDR_BUFFERSIZE m; - unsigned long size; - - while (*pFormat != RPC_FC_END) { - switch (*pFormat) { - case RPC_FC_BYTE: - case RPC_FC_CHAR: - case RPC_FC_SMALL: - case RPC_FC_USMALL: - safe_buffer_length_increment(pStubMsg, 1); - pMemory += 1; - break; - case RPC_FC_WCHAR: - case RPC_FC_SHORT: - case RPC_FC_USHORT: - safe_buffer_length_increment(pStubMsg, 2); - pMemory += 2; - break; - case RPC_FC_LONG: - case RPC_FC_ULONG: - case RPC_FC_ENUM32: - safe_buffer_length_increment(pStubMsg, 4); - pMemory += 4; - break; - case RPC_FC_HYPER: - safe_buffer_length_increment(pStubMsg, 8); - pMemory += 8; - break; - case RPC_FC_POINTER: - if (!pStubMsg->IgnoreEmbeddedPointers) - { - int saved_buffer_length = pStubMsg->BufferLength; - pStubMsg->BufferLength = pStubMsg->PointerLength; - pStubMsg->PointerLength = 0; - if(!pStubMsg->BufferLength) - ERR("BufferLength == 0??\n"); - PointerBufferSize(pStubMsg, *(unsigned char**)pMemory, pPointer); - pStubMsg->PointerLength = pStubMsg->BufferLength; - pStubMsg->BufferLength = saved_buffer_length; - } - safe_buffer_length_increment(pStubMsg, 4); - pPointer += 4; - pMemory += 4; - break; - case RPC_FC_ALIGNM4: - ALIGN_POINTER(pMemory, 4); - break; - case RPC_FC_ALIGNM8: - ALIGN_POINTER(pMemory, 8); - break; - case RPC_FC_STRUCTPAD1: - case RPC_FC_STRUCTPAD2: - case RPC_FC_STRUCTPAD3: - case RPC_FC_STRUCTPAD4: - case RPC_FC_STRUCTPAD5: - case RPC_FC_STRUCTPAD6: - case RPC_FC_STRUCTPAD7: - pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1; - break; - case RPC_FC_EMBEDDED_COMPLEX: - pMemory += pFormat[1]; - pFormat += 2; - desc = pFormat + *(const SHORT*)pFormat; - size = EmbeddedComplexSize(pStubMsg, desc); - m = NdrBufferSizer[*desc & NDR_TABLE_MASK]; - if (m) - { - /* for some reason interface pointers aren't generated as - * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet - * they still need the derefencing treatment that pointers are - * given */ - if (*desc == RPC_FC_IP) - m(pStubMsg, *(unsigned char **)pMemory, desc); - else - m(pStubMsg, pMemory, desc); - } - else FIXME("no buffersizer for embedded type %02x\n", *desc); - pMemory += size; - pFormat += 2; - continue; - case RPC_FC_PAD: - break; - default: - FIXME("unhandled format 0x%02x\n", *pFormat); - } - pFormat++; - } - - return pMemory; -} - -static unsigned char * ComplexFree(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat, - PFORMAT_STRING pPointer) -{ - PFORMAT_STRING desc; - NDR_FREE m; - unsigned long size; - - while (*pFormat != RPC_FC_END) { - switch (*pFormat) { - case RPC_FC_BYTE: - case RPC_FC_CHAR: - case RPC_FC_SMALL: - case RPC_FC_USMALL: - pMemory += 1; - break; - case RPC_FC_WCHAR: - case RPC_FC_SHORT: - case RPC_FC_USHORT: - pMemory += 2; - break; - case RPC_FC_LONG: - case RPC_FC_ULONG: - case RPC_FC_ENUM32: - pMemory += 4; - break; - case RPC_FC_HYPER: - pMemory += 8; - break; - case RPC_FC_POINTER: - NdrPointerFree(pStubMsg, *(unsigned char**)pMemory, pPointer); - pPointer += 4; - pMemory += 4; - break; - case RPC_FC_ALIGNM4: - ALIGN_POINTER(pMemory, 4); - break; - case RPC_FC_ALIGNM8: - ALIGN_POINTER(pMemory, 8); - break; - case RPC_FC_STRUCTPAD1: - case RPC_FC_STRUCTPAD2: - case RPC_FC_STRUCTPAD3: - case RPC_FC_STRUCTPAD4: - case RPC_FC_STRUCTPAD5: - case RPC_FC_STRUCTPAD6: - case RPC_FC_STRUCTPAD7: - pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1; - break; - case RPC_FC_EMBEDDED_COMPLEX: - pMemory += pFormat[1]; - pFormat += 2; - desc = pFormat + *(const SHORT*)pFormat; - size = EmbeddedComplexSize(pStubMsg, desc); - m = NdrFreer[*desc & NDR_TABLE_MASK]; - if (m) - { - /* for some reason interface pointers aren't generated as - * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet - * they still need the derefencing treatment that pointers are - * given */ - if (*desc == RPC_FC_IP) - m(pStubMsg, *(unsigned char **)pMemory, desc); - else - m(pStubMsg, pMemory, desc); - } - else FIXME("no freer for embedded type %02x\n", *desc); - pMemory += size; - pFormat += 2; - continue; - case RPC_FC_PAD: - break; - default: - FIXME("unhandled format 0x%02x\n", *pFormat); - } - pFormat++; - } - - return pMemory; -} - -static unsigned long ComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat) -{ - PFORMAT_STRING desc; - unsigned long size = 0; - - while (*pFormat != RPC_FC_END) { - switch (*pFormat) { - case RPC_FC_BYTE: - case RPC_FC_CHAR: - case RPC_FC_SMALL: - case RPC_FC_USMALL: - size += 1; - safe_buffer_increment(pStubMsg, 1); - break; - case RPC_FC_WCHAR: - case RPC_FC_SHORT: - case RPC_FC_USHORT: - size += 2; - safe_buffer_increment(pStubMsg, 2); - break; - case RPC_FC_LONG: - case RPC_FC_ULONG: - case RPC_FC_ENUM32: - size += 4; - safe_buffer_increment(pStubMsg, 4); - break; - case RPC_FC_HYPER: - size += 8; - safe_buffer_increment(pStubMsg, 8); - break; - case RPC_FC_POINTER: - size += 4; - safe_buffer_increment(pStubMsg, 4); - if (!pStubMsg->IgnoreEmbeddedPointers) - FIXME("embedded pointers\n"); - break; - case RPC_FC_ALIGNM4: - ALIGN_LENGTH(size, 4); - ALIGN_POINTER(pStubMsg->Buffer, 4); - break; - case RPC_FC_ALIGNM8: - ALIGN_LENGTH(size, 8); - ALIGN_POINTER(pStubMsg->Buffer, 8); - break; - case RPC_FC_STRUCTPAD1: - case RPC_FC_STRUCTPAD2: - case RPC_FC_STRUCTPAD3: - case RPC_FC_STRUCTPAD4: - case RPC_FC_STRUCTPAD5: - case RPC_FC_STRUCTPAD6: - case RPC_FC_STRUCTPAD7: - size += *pFormat - RPC_FC_STRUCTPAD1 + 1; - break; - case RPC_FC_EMBEDDED_COMPLEX: - size += pFormat[1]; - pFormat += 2; - desc = pFormat + *(const SHORT*)pFormat; - size += EmbeddedComplexMemorySize(pStubMsg, desc); - pFormat += 2; - continue; - case RPC_FC_PAD: - break; - default: - FIXME("unhandled format 0x%02x\n", *pFormat); - } - pFormat++; - } - - return size; -} - -/*********************************************************************** - * NdrComplexStructMarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrComplexStructMarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - PFORMAT_STRING conf_array = NULL; - PFORMAT_STRING pointer_desc = NULL; - unsigned char *OldMemory = pStubMsg->Memory; - int pointer_buffer_mark_set = 0; - - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - - if (!pStubMsg->PointerBufferMark) - { - int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers; - /* save buffer length */ - unsigned long saved_buffer_length = pStubMsg->BufferLength; - - /* get the buffer pointer after complex array data, but before - * pointer data */ - pStubMsg->BufferLength = pStubMsg->Buffer - pStubMsg->BufferStart; - pStubMsg->IgnoreEmbeddedPointers = 1; - NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat); - pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded; - - /* save it for use by embedded pointer code later */ - pStubMsg->PointerBufferMark = pStubMsg->BufferStart + pStubMsg->BufferLength; - TRACE("difference = 0x%x\n", pStubMsg->PointerBufferMark - pStubMsg->Buffer); - pointer_buffer_mark_set = 1; - - /* restore the original buffer length */ - pStubMsg->BufferLength = saved_buffer_length; - } - - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pFormat[1] + 1); - - pFormat += 4; - if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat; - pFormat += 2; - if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat; - pFormat += 2; - - pStubMsg->Memory = pMemory; - - ComplexMarshall(pStubMsg, pMemory, pFormat, pointer_desc); - - if (conf_array) - NdrConformantArrayMarshall(pStubMsg, pMemory, conf_array); - - pStubMsg->Memory = OldMemory; - - if (pointer_buffer_mark_set) - { - pStubMsg->Buffer = pStubMsg->PointerBufferMark; - pStubMsg->PointerBufferMark = NULL; - } - - STD_OVERFLOW_CHECK(pStubMsg); - - return NULL; -} - -/*********************************************************************** - * NdrComplexStructUnmarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrComplexStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char **ppMemory, - PFORMAT_STRING pFormat, - unsigned char fMustAlloc) -{ - unsigned size = *(const WORD*)(pFormat+2); - PFORMAT_STRING conf_array = NULL; - PFORMAT_STRING pointer_desc = NULL; - unsigned char *pMemory; - int pointer_buffer_mark_set = 0; - - TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); - - if (!pStubMsg->PointerBufferMark) - { - int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers; - /* save buffer pointer */ - unsigned char *saved_buffer = pStubMsg->Buffer; - - /* get the buffer pointer after complex array data, but before - * pointer data */ - pStubMsg->IgnoreEmbeddedPointers = 1; - NdrComplexStructMemorySize(pStubMsg, pFormat); - pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded; - - /* save it for use by embedded pointer code later */ - pStubMsg->PointerBufferMark = pStubMsg->Buffer; - TRACE("difference = 0x%lx\n", (unsigned long)(pStubMsg->PointerBufferMark - saved_buffer)); - pointer_buffer_mark_set = 1; - - /* restore the original buffer */ - pStubMsg->Buffer = saved_buffer; - } - - ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1); - - if (fMustAlloc || !*ppMemory) - { - *ppMemory = NdrAllocate(pStubMsg, size); - memset(*ppMemory, 0, size); - } - - pFormat += 4; - if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat; - pFormat += 2; - if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat; - pFormat += 2; - - pMemory = ComplexUnmarshall(pStubMsg, *ppMemory, pFormat, pointer_desc); - - if (conf_array) - NdrConformantArrayUnmarshall(pStubMsg, &pMemory, conf_array, fMustAlloc); - - if (pointer_buffer_mark_set) - { - pStubMsg->Buffer = pStubMsg->PointerBufferMark; - pStubMsg->PointerBufferMark = NULL; - } - - return NULL; -} - -/*********************************************************************** - * NdrComplexStructBufferSize [RPCRT4.@] - */ -void WINAPI NdrComplexStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - PFORMAT_STRING conf_array = NULL; - PFORMAT_STRING pointer_desc = NULL; - unsigned char *OldMemory = pStubMsg->Memory; - int pointer_length_set = 0; - - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - - ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1); - - if(!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength) - { - int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers; - unsigned long saved_buffer_length = pStubMsg->BufferLength; - - /* get the buffer length after complex struct data, but before - * pointer data */ - pStubMsg->IgnoreEmbeddedPointers = 1; - NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat); - pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded; - - /* save it for use by embedded pointer code later */ - pStubMsg->PointerLength = pStubMsg->BufferLength; - pointer_length_set = 1; - TRACE("difference = 0x%lx\n", pStubMsg->PointerLength - saved_buffer_length); - - /* restore the original buffer length */ - pStubMsg->BufferLength = saved_buffer_length; - } - - pFormat += 4; - if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat; - pFormat += 2; - if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat; - pFormat += 2; - - pStubMsg->Memory = pMemory; - - pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, pointer_desc); - - if (conf_array) - NdrConformantArrayBufferSize(pStubMsg, pMemory, conf_array); - - pStubMsg->Memory = OldMemory; - - if(pointer_length_set) - { - pStubMsg->BufferLength = pStubMsg->PointerLength; - pStubMsg->PointerLength = 0; - } - -} - -/*********************************************************************** - * NdrComplexStructMemorySize [RPCRT4.@] - */ -ULONG WINAPI NdrComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat) -{ - unsigned size = *(const WORD*)(pFormat+2); - PFORMAT_STRING conf_array = NULL; - PFORMAT_STRING pointer_desc = NULL; - - TRACE("(%p,%p)\n", pStubMsg, pFormat); - - ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1); - - pFormat += 4; - if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat; - pFormat += 2; - if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat; - pFormat += 2; - - ComplexStructMemorySize(pStubMsg, pFormat); - - if (conf_array) - NdrConformantArrayMemorySize(pStubMsg, conf_array); - - return size; -} - -/*********************************************************************** - * NdrComplexStructFree [RPCRT4.@] - */ -void WINAPI NdrComplexStructFree(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - PFORMAT_STRING conf_array = NULL; - PFORMAT_STRING pointer_desc = NULL; - unsigned char *OldMemory = pStubMsg->Memory; - - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - - pFormat += 4; - if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat; - pFormat += 2; - if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat; - pFormat += 2; - - pStubMsg->Memory = pMemory; - - pMemory = ComplexFree(pStubMsg, pMemory, pFormat, pointer_desc); - - if (conf_array) - NdrConformantArrayFree(pStubMsg, pMemory, conf_array); - - pStubMsg->Memory = OldMemory; -} - -/*********************************************************************** - * NdrConformantArrayMarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrConformantArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - DWORD size = 0, esize = *(const WORD*)(pFormat+2); - unsigned char alignment = pFormat[1] + 1; - - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]); - - pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0); - - WriteConformance(pStubMsg); - - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment); - - size = safe_multiply(esize, pStubMsg->MaxCount); - pStubMsg->BufferMark = pStubMsg->Buffer; - safe_copy_to_buffer(pStubMsg, pMemory, size); - - EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat); - - return NULL; -} - -/*********************************************************************** - * NdrConformantArrayUnmarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrConformantArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char **ppMemory, - PFORMAT_STRING pFormat, - unsigned char fMustAlloc) -{ - DWORD size, esize = *(const WORD*)(pFormat+2); - unsigned char alignment = pFormat[1] + 1; - unsigned char *saved_buffer; - - TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); - if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]); - - pFormat = ReadConformance(pStubMsg, pFormat+4); - - size = safe_multiply(esize, pStubMsg->MaxCount); - ALIGN_POINTER(pStubMsg->Buffer, alignment); - - if (fMustAlloc) - *ppMemory = NdrAllocate(pStubMsg, size); - else - { - if (!pStubMsg->IsClient && !*ppMemory) - /* for servers, we just point straight into the RPC buffer */ - *ppMemory = pStubMsg->Buffer; - } - - saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer; - safe_buffer_increment(pStubMsg, size); - EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc); - - TRACE("copying %p to %p\n", saved_buffer, *ppMemory); - if (*ppMemory != saved_buffer) - memcpy(*ppMemory, saved_buffer, size); - - return NULL; -} - -/*********************************************************************** - * NdrConformantArrayBufferSize [RPCRT4.@] - */ -void WINAPI NdrConformantArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - DWORD size, esize = *(const WORD*)(pFormat+2); - unsigned char alignment = pFormat[1] + 1; - - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]); - - pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0); - - SizeConformance(pStubMsg); - - ALIGN_LENGTH(pStubMsg->BufferLength, alignment); - - size = safe_multiply(esize, pStubMsg->MaxCount); - /* conformance value plus array */ - safe_buffer_length_increment(pStubMsg, size); - - EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat); -} - -/*********************************************************************** - * NdrConformantArrayMemorySize [RPCRT4.@] - */ -ULONG WINAPI NdrConformantArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat) -{ - DWORD size = 0, esize = *(const WORD*)(pFormat+2); - unsigned char alignment = pFormat[1] + 1; - - TRACE("(%p,%p)\n", pStubMsg, pFormat); - if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]); - - pFormat = ReadConformance(pStubMsg, pFormat+4); - size = safe_multiply(esize, pStubMsg->MaxCount); - pStubMsg->MemorySize += size; - - ALIGN_POINTER(pStubMsg->Buffer, alignment); - pStubMsg->BufferMark = pStubMsg->Buffer; - safe_buffer_increment(pStubMsg, size); - - EmbeddedPointerMemorySize(pStubMsg, pFormat); - - return pStubMsg->MemorySize; -} - -/*********************************************************************** - * NdrConformantArrayFree [RPCRT4.@] - */ -void WINAPI NdrConformantArrayFree(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]); - - pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0); - - EmbeddedPointerFree(pStubMsg, pMemory, pFormat); -} - - -/*********************************************************************** - * NdrConformantVaryingArrayMarshall [RPCRT4.@] - */ -unsigned char* WINAPI NdrConformantVaryingArrayMarshall( PMIDL_STUB_MESSAGE pStubMsg, - unsigned char* pMemory, - PFORMAT_STRING pFormat ) -{ - ULONG bufsize; - unsigned char alignment = pFormat[1] + 1; - DWORD esize = *(const WORD*)(pFormat+2); - - TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); - - if (pFormat[0] != RPC_FC_CVARRAY) - { - ERR("invalid format type %x\n", pFormat[0]); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return NULL; - } - - pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0); - pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0); - - WriteConformance(pStubMsg); - WriteVariance(pStubMsg); - - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment); - - bufsize = safe_multiply(esize, pStubMsg->ActualCount); - - pStubMsg->BufferMark = pStubMsg->Buffer; - safe_copy_to_buffer(pStubMsg, pMemory + pStubMsg->Offset, bufsize); - - EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat); - - return NULL; -} - - -/*********************************************************************** - * NdrConformantVaryingArrayUnmarshall [RPCRT4.@] - */ -unsigned char* WINAPI NdrConformantVaryingArrayUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, - unsigned char** ppMemory, - PFORMAT_STRING pFormat, - unsigned char fMustAlloc ) -{ - ULONG bufsize, memsize; - unsigned char alignment = pFormat[1] + 1; - DWORD esize = *(const WORD*)(pFormat+2); - unsigned char *saved_buffer; - ULONG offset; - - TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); - - if (pFormat[0] != RPC_FC_CVARRAY) - { - ERR("invalid format type %x\n", pFormat[0]); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return NULL; - } - - pFormat = ReadConformance(pStubMsg, pFormat+4); - pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount); - - ALIGN_POINTER(pStubMsg->Buffer, alignment); - - bufsize = safe_multiply(esize, pStubMsg->ActualCount); - memsize = safe_multiply(esize, pStubMsg->MaxCount); - offset = pStubMsg->Offset; - - if (!*ppMemory || fMustAlloc) - *ppMemory = NdrAllocate(pStubMsg, memsize); - saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer; - safe_buffer_increment(pStubMsg, bufsize); - - EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc); - - memcpy(*ppMemory + offset, saved_buffer, bufsize); - - return NULL; -} - - -/*********************************************************************** - * NdrConformantVaryingArrayFree [RPCRT4.@] - */ -void WINAPI NdrConformantVaryingArrayFree( PMIDL_STUB_MESSAGE pStubMsg, - unsigned char* pMemory, - PFORMAT_STRING pFormat ) -{ - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - - if (pFormat[0] != RPC_FC_CVARRAY) - { - ERR("invalid format type %x\n", pFormat[0]); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return; - } - - pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0); - pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0); - - EmbeddedPointerFree(pStubMsg, pMemory, pFormat); -} - - -/*********************************************************************** - * NdrConformantVaryingArrayBufferSize [RPCRT4.@] - */ -void WINAPI NdrConformantVaryingArrayBufferSize( PMIDL_STUB_MESSAGE pStubMsg, - unsigned char* pMemory, PFORMAT_STRING pFormat ) -{ - unsigned char alignment = pFormat[1] + 1; - DWORD esize = *(const WORD*)(pFormat+2); - - TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); - - if (pFormat[0] != RPC_FC_CVARRAY) - { - ERR("invalid format type %x\n", pFormat[0]); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return; - } - - /* compute size */ - pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0); - /* compute length */ - pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0); - - SizeConformance(pStubMsg); - SizeVariance(pStubMsg); - - ALIGN_LENGTH(pStubMsg->BufferLength, alignment); - - safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount)); - - EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat); -} - - -/*********************************************************************** - * NdrConformantVaryingArrayMemorySize [RPCRT4.@] - */ -ULONG WINAPI NdrConformantVaryingArrayMemorySize( PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat ) -{ - ULONG bufsize, memsize; - unsigned char alignment = pFormat[1] + 1; - DWORD esize = *(const WORD*)(pFormat+2); - - TRACE("(%p, %p)\n", pStubMsg, pFormat); - - if (pFormat[0] != RPC_FC_CVARRAY) - { - ERR("invalid format type %x\n", pFormat[0]); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return pStubMsg->MemorySize; - } - - pFormat = ReadConformance(pStubMsg, pFormat+4); - pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount); - - ALIGN_POINTER(pStubMsg->Buffer, alignment); - - bufsize = safe_multiply(esize, pStubMsg->ActualCount); - memsize = safe_multiply(esize, pStubMsg->MaxCount); - - safe_buffer_increment(pStubMsg, bufsize); - pStubMsg->MemorySize += memsize; - - EmbeddedPointerMemorySize(pStubMsg, pFormat); - - return pStubMsg->MemorySize; -} - - -/*********************************************************************** - * NdrComplexArrayMarshall [RPCRT4.@] - */ -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); - - if (pFormat[0] != RPC_FC_BOGUS_ARRAY) - { - ERR("invalid format type %x\n", pFormat[0]); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return NULL; - } - - alignment = pFormat[1] + 1; - - if (!pStubMsg->PointerBufferMark) - { - /* save buffer fields that may be changed by buffer sizer functions - * and that may be needed later on */ - int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers; - unsigned long saved_buffer_length = pStubMsg->BufferLength; - unsigned long saved_max_count = pStubMsg->MaxCount; - unsigned long saved_offset = pStubMsg->Offset; - unsigned long saved_actual_count = pStubMsg->ActualCount; - - /* get the buffer pointer after complex array data, but before - * pointer data */ - pStubMsg->BufferLength = pStubMsg->Buffer - pStubMsg->BufferStart; - pStubMsg->IgnoreEmbeddedPointers = 1; - NdrComplexArrayBufferSize(pStubMsg, pMemory, pFormat); - pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded; - - /* save it for use by embedded pointer code later */ - pStubMsg->PointerBufferMark = pStubMsg->BufferStart + pStubMsg->BufferLength; - TRACE("difference = 0x%x\n", pStubMsg->Buffer - pStubMsg->BufferStart); - pointer_buffer_mark_set = 1; - - /* restore fields */ - pStubMsg->ActualCount = saved_actual_count; - pStubMsg->Offset = saved_offset; - 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); - - 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); - - STD_OVERFLOW_CHECK(pStubMsg); - - if (pointer_buffer_mark_set) - { - pStubMsg->Buffer = pStubMsg->PointerBufferMark; - pStubMsg->PointerBufferMark = NULL; - } - - return NULL; -} - -/*********************************************************************** - * NdrComplexArrayUnmarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrComplexArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char **ppMemory, - 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; - - TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); - - if (pFormat[0] != RPC_FC_BOGUS_ARRAY) - { - ERR("invalid format type %x\n", pFormat[0]); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return NULL; - } - - alignment = pFormat[1] + 1; - - saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers; - /* save buffer pointer */ - saved_buffer = pStubMsg->Buffer; - /* get the buffer pointer after complex array data, but before - * pointer data */ - pStubMsg->IgnoreEmbeddedPointers = 1; - pStubMsg->MemorySize = 0; - NdrComplexArrayMemorySize(pStubMsg, pFormat); - size = pStubMsg->MemorySize; - pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded; - - TRACE("difference = 0x%lx\n", (unsigned long)(pStubMsg->Buffer - saved_buffer)); - if (!pStubMsg->PointerBufferMark) - { - /* save it for use by embedded pointer code later */ - pStubMsg->PointerBufferMark = pStubMsg->Buffer; - pointer_buffer_mark_set = 1; - } - /* restore the original buffer */ - pStubMsg->Buffer = saved_buffer; - - pFormat += 4; - - pFormat = ReadConformance(pStubMsg, pFormat); - pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount); - - if (fMustAlloc || !*ppMemory) - { - *ppMemory = NdrAllocate(pStubMsg, size); - memset(*ppMemory, 0, size); - } - - ALIGN_POINTER(pStubMsg->Buffer, alignment); - - pMemory = *ppMemory; - count = pStubMsg->ActualCount; - for (i = 0; i < count; i++) - pMemory = ComplexUnmarshall(pStubMsg, pMemory, pFormat, NULL); - - if (pointer_buffer_mark_set) - { - pStubMsg->Buffer = pStubMsg->PointerBufferMark; - pStubMsg->PointerBufferMark = NULL; - } - - return NULL; -} - -/*********************************************************************** - * NdrComplexArrayBufferSize [RPCRT4.@] - */ -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); - - if (pFormat[0] != RPC_FC_BOGUS_ARRAY) - { - ERR("invalid format type %x\n", pFormat[0]); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return; - } - - alignment = pFormat[1] + 1; - - if (!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength) - { - /* save buffer fields that may be changed by buffer sizer functions - * and that may be needed later on */ - int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers; - unsigned long saved_buffer_length = pStubMsg->BufferLength; - unsigned long saved_max_count = pStubMsg->MaxCount; - unsigned long saved_offset = pStubMsg->Offset; - unsigned long saved_actual_count = pStubMsg->ActualCount; - - /* get the buffer pointer after complex array data, but before - * pointer data */ - pStubMsg->IgnoreEmbeddedPointers = 1; - NdrComplexArrayBufferSize(pStubMsg, pMemory, pFormat); - pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded; - - /* save it for use by embedded pointer code later */ - pStubMsg->PointerLength = pStubMsg->BufferLength; - pointer_length_set = 1; - - /* restore fields */ - pStubMsg->ActualCount = saved_actual_count; - pStubMsg->Offset = saved_offset; - 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); - - if(pointer_length_set) - { - pStubMsg->BufferLength = pStubMsg->PointerLength; - pStubMsg->PointerLength = 0; - } -} - -/*********************************************************************** - * NdrComplexArrayMemorySize [RPCRT4.@] - */ -ULONG WINAPI NdrComplexArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat) -{ - ULONG i, count, esize, SavedMemorySize, MemorySize; - unsigned char alignment; - unsigned char *Buffer; - - TRACE("(%p,%p)\n", pStubMsg, pFormat); - - if (pFormat[0] != RPC_FC_BOGUS_ARRAY) - { - ERR("invalid format type %x\n", pFormat[0]); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - 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; - - Buffer = pStubMsg->Buffer; - pStubMsg->MemorySize = 0; - esize = ComplexStructMemorySize(pStubMsg, pFormat); - pStubMsg->Buffer = Buffer; - - MemorySize = safe_multiply(pStubMsg->MaxCount, esize); - - count = pStubMsg->ActualCount; - for (i = 0; i < count; i++) - ComplexStructMemorySize(pStubMsg, pFormat); - - pStubMsg->MemorySize = SavedMemorySize; - - pStubMsg->MemorySize += MemorySize; - return MemorySize; -} - -/*********************************************************************** - * NdrComplexArrayFree [RPCRT4.@] - */ -void WINAPI NdrComplexArrayFree(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - ULONG i, count, def; - - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - - if (pFormat[0] != RPC_FC_BOGUS_ARRAY) - { - ERR("invalid format type %x\n", pFormat[0]); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return; - } - - def = *(const WORD*)&pFormat[2]; - pFormat += 4; - - pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def); - TRACE("conformance = %ld\n", pStubMsg->MaxCount); - - pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount); - TRACE("variance = %d\n", pStubMsg->ActualCount); - - count = pStubMsg->ActualCount; - for (i = 0; i < count; i++) - pMemory = ComplexFree(pStubMsg, pMemory, pFormat, NULL); -} - -static void UserMarshalCB(PMIDL_STUB_MESSAGE pStubMsg, - USER_MARSHAL_CB_TYPE cbtype, PFORMAT_STRING pFormat, - USER_MARSHAL_CB *umcb) -{ - umcb->Flags = MAKELONG(pStubMsg->dwDestContext, - pStubMsg->RpcMsg->DataRepresentation); - umcb->pStubMsg = pStubMsg; - umcb->pReserve = NULL; - umcb->Signature = USER_MARSHAL_CB_SIGNATURE; - umcb->CBType = cbtype; - umcb->pFormat = pFormat; - umcb->pTypeFormat = NULL /* FIXME */; -} - -#define USER_MARSHAL_PTR_PREFIX \ - ( (DWORD)'U' | ( (DWORD)'s' << 8 ) | \ - ( (DWORD)'e' << 16 ) | ( (DWORD)'r' << 24 ) ) - -/*********************************************************************** - * NdrUserMarshalMarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrUserMarshalMarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - unsigned flags = pFormat[1]; - unsigned index = *(const WORD*)&pFormat[2]; - unsigned char *saved_buffer = NULL; - USER_MARSHAL_CB umcb; - - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - TRACE("index=%d\n", index); - - UserMarshalCB(pStubMsg, USER_MARSHAL_CB_MARSHALL, pFormat, &umcb); - - if (flags & USER_MARSHAL_POINTER) - { - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4); - NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, USER_MARSHAL_PTR_PREFIX); - pStubMsg->Buffer += 4; - if (pStubMsg->PointerBufferMark) - { - saved_buffer = pStubMsg->Buffer; - pStubMsg->Buffer = pStubMsg->PointerBufferMark; - pStubMsg->PointerBufferMark = NULL; - } - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 8); - } - else - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, (flags & 0xf) + 1); - - pStubMsg->Buffer = - pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnMarshall( - &umcb.Flags, pStubMsg->Buffer, pMemory); - - if (saved_buffer) - { - STD_OVERFLOW_CHECK(pStubMsg); - pStubMsg->PointerBufferMark = pStubMsg->Buffer; - pStubMsg->Buffer = saved_buffer; - } - - STD_OVERFLOW_CHECK(pStubMsg); - - return NULL; -} - -/*********************************************************************** - * NdrUserMarshalUnmarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrUserMarshalUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char **ppMemory, - PFORMAT_STRING pFormat, - unsigned char fMustAlloc) -{ - unsigned flags = pFormat[1]; - unsigned index = *(const WORD*)&pFormat[2]; - DWORD memsize = *(const WORD*)&pFormat[4]; - unsigned char *saved_buffer = NULL; - USER_MARSHAL_CB umcb; - - TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); - TRACE("index=%d\n", index); - - UserMarshalCB(pStubMsg, USER_MARSHAL_CB_UNMARSHALL, pFormat, &umcb); - - if (flags & USER_MARSHAL_POINTER) - { - ALIGN_POINTER(pStubMsg->Buffer, 4); - /* skip pointer prefix */ - pStubMsg->Buffer += 4; - if (pStubMsg->PointerBufferMark) - { - saved_buffer = pStubMsg->Buffer; - pStubMsg->Buffer = pStubMsg->PointerBufferMark; - pStubMsg->PointerBufferMark = NULL; - } - ALIGN_POINTER(pStubMsg->Buffer, 8); - } - else - ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1); - - if (fMustAlloc || !*ppMemory) - *ppMemory = NdrAllocate(pStubMsg, memsize); - - pStubMsg->Buffer = - pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnUnmarshall( - &umcb.Flags, pStubMsg->Buffer, *ppMemory); - - if (saved_buffer) - { - STD_OVERFLOW_CHECK(pStubMsg); - pStubMsg->PointerBufferMark = pStubMsg->Buffer; - pStubMsg->Buffer = saved_buffer; - } - - return NULL; -} - -/*********************************************************************** - * NdrUserMarshalBufferSize [RPCRT4.@] - */ -void WINAPI NdrUserMarshalBufferSize(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - unsigned flags = pFormat[1]; - unsigned index = *(const WORD*)&pFormat[2]; - DWORD bufsize = *(const WORD*)&pFormat[6]; - USER_MARSHAL_CB umcb; - unsigned long saved_buffer_length = 0; - - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - TRACE("index=%d\n", index); - - UserMarshalCB(pStubMsg, USER_MARSHAL_CB_BUFFER_SIZE, pFormat, &umcb); - - if (flags & USER_MARSHAL_POINTER) - { - ALIGN_LENGTH(pStubMsg->BufferLength, 4); - /* skip pointer prefix */ - safe_buffer_length_increment(pStubMsg, 4); - if (pStubMsg->IgnoreEmbeddedPointers) - return; - if (pStubMsg->PointerLength) - { - saved_buffer_length = pStubMsg->BufferLength; - pStubMsg->BufferLength = pStubMsg->PointerLength; - pStubMsg->PointerLength = 0; - } - ALIGN_LENGTH(pStubMsg->BufferLength, 8); - } - else - ALIGN_LENGTH(pStubMsg->BufferLength, (flags & 0xf) + 1); - - if (bufsize) { - TRACE("size=%d\n", bufsize); - safe_buffer_length_increment(pStubMsg, bufsize); - } - else - pStubMsg->BufferLength = - pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnBufferSize( - &umcb.Flags, pStubMsg->BufferLength, pMemory); - - if (saved_buffer_length) - { - pStubMsg->PointerLength = pStubMsg->BufferLength; - pStubMsg->BufferLength = saved_buffer_length; - } - -} - -/*********************************************************************** - * NdrUserMarshalMemorySize [RPCRT4.@] - */ -ULONG WINAPI NdrUserMarshalMemorySize(PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat) -{ - unsigned flags = pFormat[1]; - unsigned index = *(const WORD*)&pFormat[2]; - DWORD memsize = *(const WORD*)&pFormat[4]; - DWORD bufsize = *(const WORD*)&pFormat[6]; - - TRACE("(%p,%p)\n", pStubMsg, pFormat); - TRACE("index=%d\n", index); - - pStubMsg->MemorySize += memsize; - - if (flags & USER_MARSHAL_POINTER) - { - ALIGN_POINTER(pStubMsg->Buffer, 4); - /* skip pointer prefix */ - pStubMsg->Buffer += 4; - if (pStubMsg->IgnoreEmbeddedPointers) - return pStubMsg->MemorySize; - ALIGN_POINTER(pStubMsg->Buffer, 8); - } - else - ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1); - - if (!bufsize) - FIXME("not implemented for varying buffer size\n"); - - pStubMsg->Buffer += bufsize; - - return pStubMsg->MemorySize; -} - -/*********************************************************************** - * NdrUserMarshalFree [RPCRT4.@] - */ -void WINAPI NdrUserMarshalFree(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ -/* unsigned flags = pFormat[1]; */ - unsigned index = *(const WORD*)&pFormat[2]; - USER_MARSHAL_CB umcb; - - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - TRACE("index=%d\n", index); - - UserMarshalCB(pStubMsg, USER_MARSHAL_CB_FREE, pFormat, &umcb); - - pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnFree( - &umcb.Flags, pMemory); -} - -/*********************************************************************** - * NdrClearOutParameters [RPCRT4.@] - */ -void WINAPI NdrClearOutParameters(PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat, - void *ArgAddr) -{ - FIXME("(%p,%p,%p): stub\n", pStubMsg, pFormat, ArgAddr); -} - -/*********************************************************************** - * NdrConvert [RPCRT4.@] - */ -void WINAPI NdrConvert( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat ) -{ - FIXME("(pStubMsg == ^%p, pFormat == ^%p): stub.\n", pStubMsg, pFormat); - /* FIXME: since this stub doesn't do any converting, the proper behavior - is to raise an exception */ -} - -/*********************************************************************** - * NdrConvert2 [RPCRT4.@] - */ -void WINAPI NdrConvert2( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, LONG NumberParams ) -{ - FIXME("(pStubMsg == ^%p, pFormat == ^%p, NumberParams == %d): stub.\n", - pStubMsg, pFormat, NumberParams); - /* FIXME: since this stub doesn't do any converting, the proper behavior - is to raise an exception */ -} - -#include "pshpack1.h" -typedef struct _NDR_CSTRUCT_FORMAT -{ - unsigned char type; - unsigned char alignment; - unsigned short memory_size; - short offset_to_array_description; -} NDR_CSTRUCT_FORMAT, NDR_CVSTRUCT_FORMAT; -#include "poppack.h" - -/*********************************************************************** - * NdrConformantStructMarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrConformantStructMarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat; - PFORMAT_STRING pCArrayFormat; - ULONG esize, bufsize; - - TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); - - pFormat += sizeof(NDR_CSTRUCT_FORMAT); - if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT)) - { - ERR("invalid format type %x\n", pCStructFormat->type); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return NULL; - } - - pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description + - pCStructFormat->offset_to_array_description; - if (*pCArrayFormat != RPC_FC_CARRAY) - { - ERR("invalid array format type %x\n", pCStructFormat->type); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return NULL; - } - esize = *(const WORD*)(pCArrayFormat+2); - - ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size, - pCArrayFormat + 4, 0); - - WriteConformance(pStubMsg); - - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pCStructFormat->alignment + 1); - - TRACE("memory_size = %d\n", pCStructFormat->memory_size); - - bufsize = safe_multiply(esize, pStubMsg->MaxCount); - if (pCStructFormat->memory_size + bufsize < pCStructFormat->memory_size) /* integer overflow */ - { - ERR("integer overflow of memory_size %u with bufsize %u\n", - pCStructFormat->memory_size, bufsize); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - } - /* copy constant sized part of struct */ - pStubMsg->BufferMark = pStubMsg->Buffer; - safe_copy_to_buffer(pStubMsg, pMemory, pCStructFormat->memory_size + bufsize); - - if (pCStructFormat->type == RPC_FC_CPSTRUCT) - EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat); - - return NULL; -} - -/*********************************************************************** - * NdrConformantStructUnmarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrConformantStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char **ppMemory, - PFORMAT_STRING pFormat, - unsigned char fMustAlloc) -{ - const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat; - PFORMAT_STRING pCArrayFormat; - ULONG esize, bufsize; - unsigned char *saved_buffer; - - TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); - - pFormat += sizeof(NDR_CSTRUCT_FORMAT); - if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT)) - { - ERR("invalid format type %x\n", pCStructFormat->type); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return NULL; - } - pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description + - pCStructFormat->offset_to_array_description; - if (*pCArrayFormat != RPC_FC_CARRAY) - { - ERR("invalid array format type %x\n", pCStructFormat->type); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return NULL; - } - esize = *(const WORD*)(pCArrayFormat+2); - - pCArrayFormat = ReadConformance(pStubMsg, pCArrayFormat + 4); - - ALIGN_POINTER(pStubMsg->Buffer, pCStructFormat->alignment + 1); - - TRACE("memory_size = %d\n", pCStructFormat->memory_size); - - bufsize = safe_multiply(esize, pStubMsg->MaxCount); - if (pCStructFormat->memory_size + bufsize < pCStructFormat->memory_size) /* integer overflow */ - { - ERR("integer overflow of memory_size %u with bufsize %u\n", - pCStructFormat->memory_size, bufsize); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - } - - if (fMustAlloc) - { - SIZE_T size = pCStructFormat->memory_size + bufsize; - *ppMemory = NdrAllocate(pStubMsg, size); - } - else - { - if (!pStubMsg->IsClient && !*ppMemory) - /* for servers, we just point straight into the RPC buffer */ - *ppMemory = pStubMsg->Buffer; - } - - saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer; - safe_buffer_increment(pStubMsg, pCStructFormat->memory_size + bufsize); - if (pCStructFormat->type == RPC_FC_CPSTRUCT) - EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc); - - TRACE("copying %p to %p\n", saved_buffer, *ppMemory); - if (*ppMemory != saved_buffer) - memcpy(*ppMemory, saved_buffer, pCStructFormat->memory_size + bufsize); - - return NULL; -} - -/*********************************************************************** - * NdrConformantStructBufferSize [RPCRT4.@] - */ -void WINAPI NdrConformantStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - const NDR_CSTRUCT_FORMAT * pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat; - PFORMAT_STRING pCArrayFormat; - ULONG esize; - - TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); - - pFormat += sizeof(NDR_CSTRUCT_FORMAT); - if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT)) - { - ERR("invalid format type %x\n", pCStructFormat->type); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return; - } - pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description + - pCStructFormat->offset_to_array_description; - if (*pCArrayFormat != RPC_FC_CARRAY) - { - ERR("invalid array format type %x\n", pCStructFormat->type); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return; - } - esize = *(const WORD*)(pCArrayFormat+2); - - pCArrayFormat = ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size, pCArrayFormat+4, 0); - SizeConformance(pStubMsg); - - ALIGN_LENGTH(pStubMsg->BufferLength, pCStructFormat->alignment + 1); - - TRACE("memory_size = %d\n", pCStructFormat->memory_size); - - safe_buffer_length_increment(pStubMsg, pCStructFormat->memory_size); - safe_buffer_length_increment(pStubMsg, safe_multiply(pStubMsg->MaxCount, esize)); - - if (pCStructFormat->type == RPC_FC_CPSTRUCT) - EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat); -} - -/*********************************************************************** - * NdrConformantStructMemorySize [RPCRT4.@] - */ -ULONG WINAPI NdrConformantStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat) -{ - FIXME("stub\n"); - return 0; -} - -/*********************************************************************** - * NdrConformantStructFree [RPCRT4.@] - */ -void WINAPI NdrConformantStructFree(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat; - PFORMAT_STRING pCArrayFormat; - ULONG esize; - - TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); - - pFormat += sizeof(NDR_CSTRUCT_FORMAT); - if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT)) - { - ERR("invalid format type %x\n", pCStructFormat->type); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return; - } - - pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description + - pCStructFormat->offset_to_array_description; - if (*pCArrayFormat != RPC_FC_CARRAY) - { - ERR("invalid array format type %x\n", pCStructFormat->type); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return; - } - esize = *(const WORD*)(pCArrayFormat+2); - - ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size, - pCArrayFormat + 4, 0); - - TRACE("memory_size = %d\n", pCStructFormat->memory_size); - - /* copy constant sized part of struct */ - pStubMsg->BufferMark = pStubMsg->Buffer; - - if (pCStructFormat->type == RPC_FC_CPSTRUCT) - EmbeddedPointerFree(pStubMsg, pMemory, pFormat); -} - -/*********************************************************************** - * NdrConformantVaryingStructMarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrConformantVaryingStructMarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat; - PFORMAT_STRING pCVArrayFormat; - ULONG esize, bufsize; - - TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); - - pFormat += sizeof(NDR_CVSTRUCT_FORMAT); - if (pCVStructFormat->type != RPC_FC_CVSTRUCT) - { - ERR("invalid format type %x\n", pCVStructFormat->type); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return NULL; - } - - pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description + - pCVStructFormat->offset_to_array_description; - switch (*pCVArrayFormat) - { - case RPC_FC_CVARRAY: - esize = *(const WORD*)(pCVArrayFormat+2); - - pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size, - pCVArrayFormat + 4, 0); - pCVArrayFormat = ComputeVariance(pStubMsg, pMemory + pCVStructFormat->memory_size, - pCVArrayFormat, 0); - break; - case RPC_FC_C_CSTRING: - TRACE("string=%s\n", debugstr_a((char*)pMemory + pCVStructFormat->memory_size)); - pStubMsg->ActualCount = strlen((char*)pMemory + pCVStructFormat->memory_size)+1; - esize = sizeof(char); - if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) - pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size, - pCVArrayFormat + 2, 0); - else - pStubMsg->MaxCount = pStubMsg->ActualCount; - break; - case RPC_FC_C_WSTRING: - TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory + pCVStructFormat->memory_size)); - pStubMsg->ActualCount = strlenW((LPWSTR)pMemory + pCVStructFormat->memory_size)+1; - esize = sizeof(WCHAR); - if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) - pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size, - pCVArrayFormat + 2, 0); - else - pStubMsg->MaxCount = pStubMsg->ActualCount; - break; - default: - ERR("invalid array format type %x\n", *pCVArrayFormat); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return NULL; - } - - WriteConformance(pStubMsg); - - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pCVStructFormat->alignment + 1); - - TRACE("memory_size = %d\n", pCVStructFormat->memory_size); - - /* write constant sized part */ - pStubMsg->BufferMark = pStubMsg->Buffer; - safe_copy_to_buffer(pStubMsg, pMemory, pCVStructFormat->memory_size); - - WriteVariance(pStubMsg); - - bufsize = safe_multiply(esize, pStubMsg->ActualCount); - - /* write array part */ - safe_copy_to_buffer(pStubMsg, pMemory + pCVStructFormat->memory_size, bufsize); - - EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat); - - return NULL; -} - -/*********************************************************************** - * NdrConformantVaryingStructUnmarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrConformantVaryingStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char **ppMemory, - PFORMAT_STRING pFormat, - unsigned char fMustAlloc) -{ - const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat; - PFORMAT_STRING pCVArrayFormat; - ULONG esize, bufsize; - unsigned char cvarray_type; - - TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); - - pFormat += sizeof(NDR_CVSTRUCT_FORMAT); - if (pCVStructFormat->type != RPC_FC_CVSTRUCT) - { - ERR("invalid format type %x\n", pCVStructFormat->type); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return NULL; - } - - pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description + - pCVStructFormat->offset_to_array_description; - cvarray_type = *pCVArrayFormat; - switch (cvarray_type) - { - case RPC_FC_CVARRAY: - esize = *(const WORD*)(pCVArrayFormat+2); - pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 4); - break; - case RPC_FC_C_CSTRING: - esize = sizeof(char); - if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) - pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2); - else - pCVArrayFormat = ReadConformance(pStubMsg, NULL); - break; - case RPC_FC_C_WSTRING: - esize = sizeof(WCHAR); - if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) - pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2); - else - pCVArrayFormat = ReadConformance(pStubMsg, NULL); - break; - default: - ERR("invalid array format type %x\n", *pCVArrayFormat); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return NULL; - } - - ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1); - - TRACE("memory_size = %d\n", pCVStructFormat->memory_size); - - /* work out how much memory to allocate if we need to do so */ - if (!*ppMemory || fMustAlloc) - { - SIZE_T size = pCVStructFormat->memory_size + safe_multiply(esize, pStubMsg->MaxCount); - *ppMemory = NdrAllocate(pStubMsg, size); - } - - /* copy the constant data */ - pStubMsg->BufferMark = pStubMsg->Buffer; - safe_copy_from_buffer(pStubMsg, *ppMemory, pCVStructFormat->memory_size); - - pCVArrayFormat = ReadVariance(pStubMsg, pCVArrayFormat, pStubMsg->MaxCount); - - bufsize = safe_multiply(esize, pStubMsg->ActualCount); - - if ((cvarray_type == RPC_FC_C_CSTRING) || - (cvarray_type == RPC_FC_C_WSTRING)) - { - ULONG i; - /* strings must always have null terminating bytes */ - if (bufsize < esize) - { - ERR("invalid string length of %d\n", pStubMsg->ActualCount); - RpcRaiseException(RPC_S_INVALID_BOUND); - return NULL; - } - for (i = bufsize - esize; i < bufsize; i++) - if (pStubMsg->Buffer[i] != 0) - { - ERR("string not null-terminated at byte position %d, data is 0x%x\n", - i, pStubMsg->Buffer[i]); - RpcRaiseException(RPC_S_INVALID_BOUND); - return NULL; - } - } - - /* copy the array data */ - safe_copy_from_buffer(pStubMsg, *ppMemory + pCVStructFormat->memory_size, bufsize); - - if (cvarray_type == RPC_FC_C_CSTRING) - TRACE("string=%s\n", debugstr_a((char *)(*ppMemory + pCVStructFormat->memory_size))); - else if (cvarray_type == RPC_FC_C_WSTRING) - TRACE("string=%s\n", debugstr_w((WCHAR *)(*ppMemory + pCVStructFormat->memory_size))); - - EmbeddedPointerUnmarshall(pStubMsg, *ppMemory, *ppMemory, pFormat, TRUE /* FIXME */); - - return NULL; -} - -/*********************************************************************** - * NdrConformantVaryingStructBufferSize [RPCRT4.@] - */ -void WINAPI NdrConformantVaryingStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat; - PFORMAT_STRING pCVArrayFormat; - ULONG esize; - - TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); - - pFormat += sizeof(NDR_CVSTRUCT_FORMAT); - if (pCVStructFormat->type != RPC_FC_CVSTRUCT) - { - ERR("invalid format type %x\n", pCVStructFormat->type); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return; - } - - pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description + - pCVStructFormat->offset_to_array_description; - switch (*pCVArrayFormat) - { - case RPC_FC_CVARRAY: - esize = *(const WORD*)(pCVArrayFormat+2); - - pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size, - pCVArrayFormat + 4, 0); - pCVArrayFormat = ComputeVariance(pStubMsg, pMemory + pCVStructFormat->memory_size, - pCVArrayFormat, 0); - break; - case RPC_FC_C_CSTRING: - TRACE("string=%s\n", debugstr_a((char*)pMemory + pCVStructFormat->memory_size)); - pStubMsg->ActualCount = strlen((char*)pMemory + pCVStructFormat->memory_size)+1; - esize = sizeof(char); - if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) - pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size, - pCVArrayFormat + 2, 0); - else - pStubMsg->MaxCount = pStubMsg->ActualCount; - break; - case RPC_FC_C_WSTRING: - TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory + pCVStructFormat->memory_size)); - pStubMsg->ActualCount = strlenW((LPWSTR)pMemory + pCVStructFormat->memory_size)+1; - esize = sizeof(WCHAR); - if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) - pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size, - pCVArrayFormat + 2, 0); - else - pStubMsg->MaxCount = pStubMsg->ActualCount; - break; - default: - ERR("invalid array format type %x\n", *pCVArrayFormat); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return; - } - - SizeConformance(pStubMsg); - - ALIGN_LENGTH(pStubMsg->BufferLength, pCVStructFormat->alignment + 1); - - TRACE("memory_size = %d\n", pCVStructFormat->memory_size); - - safe_buffer_length_increment(pStubMsg, pCVStructFormat->memory_size); - SizeVariance(pStubMsg); - safe_buffer_length_increment(pStubMsg, safe_multiply(pStubMsg->MaxCount, esize)); - - EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat); -} - -/*********************************************************************** - * NdrConformantVaryingStructMemorySize [RPCRT4.@] - */ -ULONG WINAPI NdrConformantVaryingStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat) -{ - const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat; - PFORMAT_STRING pCVArrayFormat; - ULONG esize; - unsigned char cvarray_type; - - TRACE("(%p, %p)\n", pStubMsg, pFormat); - - pFormat += sizeof(NDR_CVSTRUCT_FORMAT); - if (pCVStructFormat->type != RPC_FC_CVSTRUCT) - { - ERR("invalid format type %x\n", pCVStructFormat->type); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return 0; - } - - pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description + - pCVStructFormat->offset_to_array_description; - cvarray_type = *pCVArrayFormat; - switch (cvarray_type) - { - case RPC_FC_CVARRAY: - esize = *(const WORD*)(pCVArrayFormat+2); - pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 4); - break; - case RPC_FC_C_CSTRING: - esize = sizeof(char); - if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) - pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2); - else - pCVArrayFormat = ReadConformance(pStubMsg, NULL); - break; - case RPC_FC_C_WSTRING: - esize = sizeof(WCHAR); - if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) - pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2); - else - pCVArrayFormat = ReadConformance(pStubMsg, NULL); - break; - default: - ERR("invalid array format type %x\n", *pCVArrayFormat); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return 0; - } - - ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1); - - TRACE("memory_size = %d\n", pCVStructFormat->memory_size); - - safe_buffer_increment(pStubMsg, pCVStructFormat->memory_size); - pCVArrayFormat = ReadVariance(pStubMsg, pCVArrayFormat, pStubMsg->MaxCount); - safe_buffer_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount)); - - pStubMsg->MemorySize += pCVStructFormat->memory_size + safe_multiply(esize, pStubMsg->MaxCount); - - EmbeddedPointerMemorySize(pStubMsg, pFormat); - - return pCVStructFormat->memory_size + pStubMsg->MaxCount * esize; -} - -/*********************************************************************** - * NdrConformantVaryingStructFree [RPCRT4.@] - */ -void WINAPI NdrConformantVaryingStructFree(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat; - PFORMAT_STRING pCVArrayFormat; - ULONG esize; - - TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); - - pFormat += sizeof(NDR_CVSTRUCT_FORMAT); - if (pCVStructFormat->type != RPC_FC_CVSTRUCT) - { - ERR("invalid format type %x\n", pCVStructFormat->type); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return; - } - - pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description + - pCVStructFormat->offset_to_array_description; - switch (*pCVArrayFormat) - { - case RPC_FC_CVARRAY: - esize = *(const WORD*)(pCVArrayFormat+2); - - pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size, - pCVArrayFormat + 4, 0); - pCVArrayFormat = ComputeVariance(pStubMsg, pMemory + pCVStructFormat->memory_size, - pCVArrayFormat, 0); - break; - case RPC_FC_C_CSTRING: - TRACE("string=%s\n", debugstr_a((char*)pMemory + pCVStructFormat->memory_size)); - pStubMsg->ActualCount = strlen((char*)pMemory + pCVStructFormat->memory_size)+1; - esize = sizeof(char); - if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) - pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size, - pCVArrayFormat + 2, 0); - else - pStubMsg->MaxCount = pStubMsg->ActualCount; - break; - case RPC_FC_C_WSTRING: - TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory + pCVStructFormat->memory_size)); - pStubMsg->ActualCount = strlenW((LPWSTR)pMemory + pCVStructFormat->memory_size)+1; - esize = sizeof(WCHAR); - if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) - pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size, - pCVArrayFormat + 2, 0); - else - pStubMsg->MaxCount = pStubMsg->ActualCount; - break; - default: - ERR("invalid array format type %x\n", *pCVArrayFormat); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return; - } - - TRACE("memory_size = %d\n", pCVStructFormat->memory_size); - - EmbeddedPointerFree(pStubMsg, pMemory, pFormat); -} - -#include "pshpack1.h" -typedef struct -{ - unsigned char type; - unsigned char alignment; - unsigned short total_size; -} NDR_SMFARRAY_FORMAT; - -typedef struct -{ - unsigned char type; - unsigned char alignment; - unsigned long total_size; -} NDR_LGFARRAY_FORMAT; -#include "poppack.h" - -/*********************************************************************** - * NdrFixedArrayMarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrFixedArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat; - unsigned long total_size; - - TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); - - if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) && - (pSmFArrayFormat->type != RPC_FC_LGFARRAY)) - { - ERR("invalid format type %x\n", pSmFArrayFormat->type); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return NULL; - } - - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1); - - if (pSmFArrayFormat->type == RPC_FC_SMFARRAY) - { - total_size = pSmFArrayFormat->total_size; - pFormat = (const unsigned char *)(pSmFArrayFormat + 1); - } - else - { - const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat; - total_size = pLgFArrayFormat->total_size; - pFormat = (const unsigned char *)(pLgFArrayFormat + 1); - } - - pStubMsg->BufferMark = pStubMsg->Buffer; - safe_copy_to_buffer(pStubMsg, pMemory, total_size); - - pFormat = EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat); - - return NULL; -} - -/*********************************************************************** - * NdrFixedArrayUnmarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrFixedArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char **ppMemory, - PFORMAT_STRING pFormat, - unsigned char fMustAlloc) -{ - const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat; - unsigned long total_size; - unsigned char *saved_buffer; - - TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); - - if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) && - (pSmFArrayFormat->type != RPC_FC_LGFARRAY)) - { - ERR("invalid format type %x\n", pSmFArrayFormat->type); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return NULL; - } - - ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1); - - if (pSmFArrayFormat->type == RPC_FC_SMFARRAY) - { - total_size = pSmFArrayFormat->total_size; - pFormat = (const unsigned char *)(pSmFArrayFormat + 1); - } - else - { - const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat; - total_size = pLgFArrayFormat->total_size; - pFormat = (const unsigned char *)(pLgFArrayFormat + 1); - } - - if (fMustAlloc) - *ppMemory = NdrAllocate(pStubMsg, total_size); - else - { - if (!pStubMsg->IsClient && !*ppMemory) - /* for servers, we just point straight into the RPC buffer */ - *ppMemory = pStubMsg->Buffer; - } - - saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer; - safe_buffer_increment(pStubMsg, total_size); - pFormat = EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc); - - TRACE("copying %p to %p\n", saved_buffer, *ppMemory); - if (*ppMemory != saved_buffer) - memcpy(*ppMemory, saved_buffer, total_size); - - return NULL; -} - -/*********************************************************************** - * NdrFixedArrayBufferSize [RPCRT4.@] - */ -void WINAPI NdrFixedArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat; - unsigned long total_size; - - TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); - - if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) && - (pSmFArrayFormat->type != RPC_FC_LGFARRAY)) - { - ERR("invalid format type %x\n", pSmFArrayFormat->type); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return; - } - - ALIGN_LENGTH(pStubMsg->BufferLength, pSmFArrayFormat->alignment + 1); - - if (pSmFArrayFormat->type == RPC_FC_SMFARRAY) - { - total_size = pSmFArrayFormat->total_size; - pFormat = (const unsigned char *)(pSmFArrayFormat + 1); - } - else - { - const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat; - total_size = pLgFArrayFormat->total_size; - pFormat = (const unsigned char *)(pLgFArrayFormat + 1); - } - safe_buffer_length_increment(pStubMsg, total_size); - - EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat); -} - -/*********************************************************************** - * NdrFixedArrayMemorySize [RPCRT4.@] - */ -ULONG WINAPI NdrFixedArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat) -{ - const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat; - ULONG total_size; - - TRACE("(%p, %p)\n", pStubMsg, pFormat); - - if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) && - (pSmFArrayFormat->type != RPC_FC_LGFARRAY)) - { - ERR("invalid format type %x\n", pSmFArrayFormat->type); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return 0; - } - - ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1); - - if (pSmFArrayFormat->type == RPC_FC_SMFARRAY) - { - total_size = pSmFArrayFormat->total_size; - pFormat = (const unsigned char *)(pSmFArrayFormat + 1); - } - else - { - const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat; - total_size = pLgFArrayFormat->total_size; - pFormat = (const unsigned char *)(pLgFArrayFormat + 1); - } - pStubMsg->BufferMark = pStubMsg->Buffer; - safe_buffer_increment(pStubMsg, total_size); - pStubMsg->MemorySize += total_size; - - EmbeddedPointerMemorySize(pStubMsg, pFormat); - - return total_size; -} - -/*********************************************************************** - * NdrFixedArrayFree [RPCRT4.@] - */ -void WINAPI NdrFixedArrayFree(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat; - - TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); - - if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) && - (pSmFArrayFormat->type != RPC_FC_LGFARRAY)) - { - ERR("invalid format type %x\n", pSmFArrayFormat->type); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return; - } - - if (pSmFArrayFormat->type == RPC_FC_SMFARRAY) - pFormat = (const unsigned char *)(pSmFArrayFormat + 1); - else - { - const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat; - pFormat = (const unsigned char *)(pLgFArrayFormat + 1); - } - - EmbeddedPointerFree(pStubMsg, pMemory, pFormat); -} - -/*********************************************************************** - * NdrVaryingArrayMarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrVaryingArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - unsigned char alignment; - DWORD elements, esize; - ULONG bufsize; - - TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); - - if ((pFormat[0] != RPC_FC_SMVARRAY) && - (pFormat[0] != RPC_FC_LGVARRAY)) - { - ERR("invalid format type %x\n", pFormat[0]); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return NULL; - } - - alignment = pFormat[1] + 1; - - if (pFormat[0] == RPC_FC_SMVARRAY) - { - pFormat += 2; - pFormat += sizeof(WORD); - elements = *(const WORD*)pFormat; - pFormat += sizeof(WORD); - } - else - { - pFormat += 2; - pFormat += sizeof(DWORD); - elements = *(const DWORD*)pFormat; - pFormat += sizeof(DWORD); - } - - esize = *(const WORD*)pFormat; - pFormat += sizeof(WORD); - - pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0); - if ((pStubMsg->ActualCount > elements) || - (pStubMsg->ActualCount + pStubMsg->Offset > elements)) - { - RpcRaiseException(RPC_S_INVALID_BOUND); - return NULL; - } - - WriteVariance(pStubMsg); - - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment); - - bufsize = safe_multiply(esize, pStubMsg->ActualCount); - pStubMsg->BufferMark = pStubMsg->Buffer; - safe_copy_to_buffer(pStubMsg, pMemory + pStubMsg->Offset, bufsize); - - EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat); - - return NULL; -} - -/*********************************************************************** - * NdrVaryingArrayUnmarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrVaryingArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char **ppMemory, - PFORMAT_STRING pFormat, - unsigned char fMustAlloc) -{ - unsigned char alignment; - DWORD size, elements, esize; - ULONG bufsize; - unsigned char *saved_buffer; - ULONG offset; - - TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); - - if ((pFormat[0] != RPC_FC_SMVARRAY) && - (pFormat[0] != RPC_FC_LGVARRAY)) - { - ERR("invalid format type %x\n", pFormat[0]); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return NULL; - } - - alignment = pFormat[1] + 1; - - if (pFormat[0] == RPC_FC_SMVARRAY) - { - pFormat += 2; - size = *(const WORD*)pFormat; - pFormat += sizeof(WORD); - elements = *(const WORD*)pFormat; - pFormat += sizeof(WORD); - } - else - { - pFormat += 2; - size = *(const DWORD*)pFormat; - pFormat += sizeof(DWORD); - elements = *(const DWORD*)pFormat; - pFormat += sizeof(DWORD); - } - - esize = *(const WORD*)pFormat; - pFormat += sizeof(WORD); - - pFormat = ReadVariance(pStubMsg, pFormat, elements); - - ALIGN_POINTER(pStubMsg->Buffer, alignment); - - bufsize = safe_multiply(esize, pStubMsg->ActualCount); - offset = pStubMsg->Offset; - - if (!*ppMemory || fMustAlloc) - *ppMemory = NdrAllocate(pStubMsg, size); - saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer; - safe_buffer_increment(pStubMsg, bufsize); - - EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc); - - memcpy(*ppMemory + offset, saved_buffer, bufsize); - - return NULL; -} - -/*********************************************************************** - * NdrVaryingArrayBufferSize [RPCRT4.@] - */ -void WINAPI NdrVaryingArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - unsigned char alignment; - DWORD elements, esize; - - TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); - - if ((pFormat[0] != RPC_FC_SMVARRAY) && - (pFormat[0] != RPC_FC_LGVARRAY)) - { - ERR("invalid format type %x\n", pFormat[0]); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return; - } - - alignment = pFormat[1] + 1; - - if (pFormat[0] == RPC_FC_SMVARRAY) - { - pFormat += 2; - pFormat += sizeof(WORD); - elements = *(const WORD*)pFormat; - pFormat += sizeof(WORD); - } - else - { - pFormat += 2; - pFormat += sizeof(DWORD); - elements = *(const DWORD*)pFormat; - pFormat += sizeof(DWORD); - } - - esize = *(const WORD*)pFormat; - pFormat += sizeof(WORD); - - pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0); - if ((pStubMsg->ActualCount > elements) || - (pStubMsg->ActualCount + pStubMsg->Offset > elements)) - { - RpcRaiseException(RPC_S_INVALID_BOUND); - return; - } - - SizeVariance(pStubMsg); - - ALIGN_LENGTH(pStubMsg->BufferLength, alignment); - - safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount)); - - EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat); -} - -/*********************************************************************** - * NdrVaryingArrayMemorySize [RPCRT4.@] - */ -ULONG WINAPI NdrVaryingArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat) -{ - unsigned char alignment; - DWORD size, elements, esize; - - TRACE("(%p, %p)\n", pStubMsg, pFormat); - - if ((pFormat[0] != RPC_FC_SMVARRAY) && - (pFormat[0] != RPC_FC_LGVARRAY)) - { - ERR("invalid format type %x\n", pFormat[0]); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return 0; - } - - alignment = pFormat[1] + 1; - - if (pFormat[0] == RPC_FC_SMVARRAY) - { - pFormat += 2; - size = *(const WORD*)pFormat; - pFormat += sizeof(WORD); - elements = *(const WORD*)pFormat; - pFormat += sizeof(WORD); - } - else - { - pFormat += 2; - size = *(const DWORD*)pFormat; - pFormat += sizeof(DWORD); - elements = *(const DWORD*)pFormat; - pFormat += sizeof(DWORD); - } - - esize = *(const WORD*)pFormat; - pFormat += sizeof(WORD); - - pFormat = ReadVariance(pStubMsg, pFormat, elements); - - ALIGN_POINTER(pStubMsg->Buffer, alignment); - - safe_buffer_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount)); - pStubMsg->MemorySize += size; - - EmbeddedPointerMemorySize(pStubMsg, pFormat); - - return pStubMsg->MemorySize; -} - -/*********************************************************************** - * NdrVaryingArrayFree [RPCRT4.@] - */ -void WINAPI NdrVaryingArrayFree(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - unsigned char alignment; - DWORD elements; - - TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); - - if ((pFormat[0] != RPC_FC_SMVARRAY) && - (pFormat[0] != RPC_FC_LGVARRAY)) - { - ERR("invalid format type %x\n", pFormat[0]); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return; - } - - alignment = pFormat[1] + 1; - - if (pFormat[0] == RPC_FC_SMVARRAY) - { - pFormat += 2; - pFormat += sizeof(WORD); - elements = *(const WORD*)pFormat; - pFormat += sizeof(WORD); - } - else - { - pFormat += 2; - pFormat += sizeof(DWORD); - elements = *(const DWORD*)pFormat; - pFormat += sizeof(DWORD); - } - - pFormat += sizeof(WORD); - - pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0); - if ((pStubMsg->ActualCount > elements) || - (pStubMsg->ActualCount + pStubMsg->Offset > elements)) - { - RpcRaiseException(RPC_S_INVALID_BOUND); - return; - } - - EmbeddedPointerFree(pStubMsg, pMemory, pFormat); -} - -static ULONG get_discriminant(unsigned char fc, const unsigned char *pMemory) -{ - switch (fc) - { - case RPC_FC_BYTE: - case RPC_FC_CHAR: - case RPC_FC_SMALL: - case RPC_FC_USMALL: - return *(const UCHAR *)pMemory; - case RPC_FC_WCHAR: - case RPC_FC_SHORT: - case RPC_FC_USHORT: - case RPC_FC_ENUM16: - return *(const USHORT *)pMemory; - case RPC_FC_LONG: - case RPC_FC_ULONG: - case RPC_FC_ENUM32: - return *(const ULONG *)pMemory; - default: - FIXME("Unhandled base type: 0x%02x\n", fc); - return 0; - } -} - -static PFORMAT_STRING get_arm_offset_from_union_arm_selector(PMIDL_STUB_MESSAGE pStubMsg, - unsigned long discriminant, - PFORMAT_STRING pFormat) -{ - unsigned short num_arms, arm, type; - - num_arms = *(const SHORT*)pFormat & 0x0fff; - pFormat += 2; - for(arm = 0; arm < num_arms; arm++) - { - if(discriminant == *(const ULONG*)pFormat) - { - pFormat += 4; - break; - } - pFormat += 6; - } - - type = *(const unsigned short*)pFormat; - TRACE("type %04x\n", type); - if(arm == num_arms) /* default arm extras */ - { - if(type == 0xffff) - { - ERR("no arm for 0x%lx and no default case\n", discriminant); - RpcRaiseException(RPC_S_INVALID_TAG); - return NULL; - } - if(type == 0) - { - TRACE("falling back to empty default case for 0x%lx\n", discriminant); - return NULL; - } - } - return pFormat; -} - -static unsigned char *union_arm_marshall(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, ULONG discriminant, PFORMAT_STRING pFormat) -{ - unsigned short type; - - pFormat += 2; - - pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat); - if(!pFormat) - return NULL; - - type = *(const unsigned short*)pFormat; - if((type & 0xff00) == 0x8000) - { - unsigned char basetype = LOBYTE(type); - return NdrBaseTypeMarshall(pStubMsg, pMemory, &basetype); - } - else - { - PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat; - NDR_MARSHALL m = NdrMarshaller[*desc & NDR_TABLE_MASK]; - if (m) - { - unsigned char *saved_buffer = NULL; - int pointer_buffer_mark_set = 0; - switch(*desc) - { - case RPC_FC_RP: - case RPC_FC_UP: - case RPC_FC_OP: - case RPC_FC_FP: - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4); - saved_buffer = pStubMsg->Buffer; - if (pStubMsg->PointerBufferMark) - { - pStubMsg->Buffer = pStubMsg->PointerBufferMark; - pStubMsg->PointerBufferMark = NULL; - pointer_buffer_mark_set = 1; - } - else - safe_buffer_increment(pStubMsg, 4); /* for pointer ID */ - - PointerMarshall(pStubMsg, saved_buffer, *(unsigned char **)pMemory, desc); - if (pointer_buffer_mark_set) - { - STD_OVERFLOW_CHECK(pStubMsg); - pStubMsg->PointerBufferMark = pStubMsg->Buffer; - if (saved_buffer + 4 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) - { - ERR("buffer overflow - saved_buffer = %p, BufferEnd = %p\n", - saved_buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - } - pStubMsg->Buffer = saved_buffer + 4; - } - break; - default: - m(pStubMsg, pMemory, desc); - } - } - else FIXME("no marshaller for embedded type %02x\n", *desc); - } - return NULL; -} - -static unsigned char *union_arm_unmarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char **ppMemory, - ULONG discriminant, - PFORMAT_STRING pFormat, - unsigned char fMustAlloc) -{ - unsigned short type; - - pFormat += 2; - - pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat); - if(!pFormat) - return NULL; - - type = *(const unsigned short*)pFormat; - if((type & 0xff00) == 0x8000) - { - unsigned char basetype = LOBYTE(type); - return NdrBaseTypeUnmarshall(pStubMsg, ppMemory, &basetype, FALSE); - } - else - { - PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat; - NDR_UNMARSHALL m = NdrUnmarshaller[*desc & NDR_TABLE_MASK]; - if (m) - { - unsigned char *saved_buffer = NULL; - int pointer_buffer_mark_set = 0; - switch(*desc) - { - case RPC_FC_RP: - case RPC_FC_UP: - case RPC_FC_OP: - case RPC_FC_FP: - **(void***)ppMemory = NULL; - ALIGN_POINTER(pStubMsg->Buffer, 4); - saved_buffer = pStubMsg->Buffer; - if (pStubMsg->PointerBufferMark) - { - pStubMsg->Buffer = pStubMsg->PointerBufferMark; - pStubMsg->PointerBufferMark = NULL; - pointer_buffer_mark_set = 1; - } - else - pStubMsg->Buffer += 4; /* for pointer ID */ - - if (saved_buffer + 4 > pStubMsg->BufferEnd) - { - ERR("buffer overflow - saved_buffer = %p, BufferEnd = %p\n", - saved_buffer, pStubMsg->BufferEnd); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - } - - PointerUnmarshall(pStubMsg, saved_buffer, *(unsigned char ***)ppMemory, **(unsigned char ***)ppMemory, desc, fMustAlloc); - if (pointer_buffer_mark_set) - { - STD_OVERFLOW_CHECK(pStubMsg); - pStubMsg->PointerBufferMark = pStubMsg->Buffer; - pStubMsg->Buffer = saved_buffer + 4; - } - break; - default: - m(pStubMsg, ppMemory, desc, fMustAlloc); - } - } - else FIXME("no marshaller for embedded type %02x\n", *desc); - } - return NULL; -} - -static void union_arm_buffer_size(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - ULONG discriminant, - PFORMAT_STRING pFormat) -{ - unsigned short type; - - pFormat += 2; - - pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat); - if(!pFormat) - return; - - type = *(const unsigned short*)pFormat; - if((type & 0xff00) == 0x8000) - { - unsigned char basetype = LOBYTE(type); - NdrBaseTypeBufferSize(pStubMsg, pMemory, &basetype); - } - else - { - PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat; - NDR_BUFFERSIZE m = NdrBufferSizer[*desc & NDR_TABLE_MASK]; - if (m) - { - switch(*desc) - { - case RPC_FC_RP: - case RPC_FC_UP: - case RPC_FC_OP: - case RPC_FC_FP: - ALIGN_LENGTH(pStubMsg->BufferLength, 4); - safe_buffer_length_increment(pStubMsg, 4); /* for pointer ID */ - if (!pStubMsg->IgnoreEmbeddedPointers) - { - int saved_buffer_length = pStubMsg->BufferLength; - pStubMsg->BufferLength = pStubMsg->PointerLength; - pStubMsg->PointerLength = 0; - if(!pStubMsg->BufferLength) - ERR("BufferLength == 0??\n"); - PointerBufferSize(pStubMsg, *(unsigned char **)pMemory, desc); - pStubMsg->PointerLength = pStubMsg->BufferLength; - pStubMsg->BufferLength = saved_buffer_length; - } - break; - default: - m(pStubMsg, pMemory, desc); - } - } - else FIXME("no buffersizer for embedded type %02x\n", *desc); - } -} - -static ULONG union_arm_memory_size(PMIDL_STUB_MESSAGE pStubMsg, - ULONG discriminant, - PFORMAT_STRING pFormat) -{ - unsigned short type, size; - - size = *(const unsigned short*)pFormat; - pStubMsg->Memory += size; - pFormat += 2; - - pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat); - if(!pFormat) - return 0; - - type = *(const unsigned short*)pFormat; - if((type & 0xff00) == 0x8000) - { - return NdrBaseTypeMemorySize(pStubMsg, pFormat); - } - else - { - PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat; - NDR_MEMORYSIZE m = NdrMemorySizer[*desc & NDR_TABLE_MASK]; - unsigned char *saved_buffer; - if (m) - { - switch(*desc) - { - case RPC_FC_RP: - case RPC_FC_UP: - case RPC_FC_OP: - case RPC_FC_FP: - ALIGN_POINTER(pStubMsg->Buffer, 4); - saved_buffer = pStubMsg->Buffer; - safe_buffer_increment(pStubMsg, 4); - ALIGN_LENGTH(pStubMsg->MemorySize, 4); - pStubMsg->MemorySize += 4; - if (!pStubMsg->IgnoreEmbeddedPointers) - PointerMemorySize(pStubMsg, saved_buffer, pFormat); - break; - default: - return m(pStubMsg, desc); - } - } - else FIXME("no marshaller for embedded type %02x\n", *desc); - } - - TRACE("size %d\n", size); - return size; -} - -static void union_arm_free(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - ULONG discriminant, - PFORMAT_STRING pFormat) -{ - unsigned short type; - - pFormat += 2; - - pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat); - if(!pFormat) - return; - - type = *(const unsigned short*)pFormat; - if((type & 0xff00) != 0x8000) - { - PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat; - NDR_FREE m = NdrFreer[*desc & NDR_TABLE_MASK]; - if (m) - { - switch(*desc) - { - case RPC_FC_RP: - case RPC_FC_UP: - case RPC_FC_OP: - case RPC_FC_FP: - PointerFree(pStubMsg, *(unsigned char **)pMemory, desc); - break; - default: - m(pStubMsg, pMemory, desc); - } - } - else FIXME("no freer for embedded type %02x\n", *desc); - } -} - -/*********************************************************************** - * NdrEncapsulatedUnionMarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - unsigned char switch_type; - unsigned char increment; - ULONG switch_value; - - TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); - pFormat++; - - switch_type = *pFormat & 0xf; - increment = (*pFormat & 0xf0) >> 4; - pFormat++; - - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, increment); - - switch_value = get_discriminant(switch_type, pMemory); - TRACE("got switch value 0x%x\n", switch_value); - - NdrBaseTypeMarshall(pStubMsg, pMemory, &switch_type); - pMemory += increment; - - return union_arm_marshall(pStubMsg, pMemory, switch_value, pFormat); -} - -/*********************************************************************** - * NdrEncapsulatedUnionUnmarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char **ppMemory, - PFORMAT_STRING pFormat, - unsigned char fMustAlloc) -{ - unsigned char switch_type; - unsigned char increment; - ULONG switch_value; - unsigned short size; - unsigned char *pMemoryArm; - - TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); - pFormat++; - - switch_type = *pFormat & 0xf; - increment = (*pFormat & 0xf0) >> 4; - pFormat++; - - ALIGN_POINTER(pStubMsg->Buffer, increment); - switch_value = get_discriminant(switch_type, pStubMsg->Buffer); - TRACE("got switch value 0x%x\n", switch_value); - - size = *(const unsigned short*)pFormat + increment; - if(!*ppMemory || fMustAlloc) - *ppMemory = NdrAllocate(pStubMsg, size); - - NdrBaseTypeUnmarshall(pStubMsg, ppMemory, &switch_type, FALSE); - pMemoryArm = *ppMemory + increment; - - return union_arm_unmarshall(pStubMsg, &pMemoryArm, switch_value, pFormat, fMustAlloc); -} - -/*********************************************************************** - * NdrEncapsulatedUnionBufferSize [RPCRT4.@] - */ -void WINAPI NdrEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - unsigned char switch_type; - unsigned char increment; - ULONG switch_value; - - TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); - pFormat++; - - switch_type = *pFormat & 0xf; - increment = (*pFormat & 0xf0) >> 4; - pFormat++; - - ALIGN_LENGTH(pStubMsg->BufferLength, increment); - switch_value = get_discriminant(switch_type, pMemory); - TRACE("got switch value 0x%x\n", switch_value); - - /* Add discriminant size */ - NdrBaseTypeBufferSize(pStubMsg, (unsigned char *)&switch_value, &switch_type); - pMemory += increment; - - union_arm_buffer_size(pStubMsg, pMemory, switch_value, pFormat); -} - -/*********************************************************************** - * NdrEncapsulatedUnionMemorySize [RPCRT4.@] - */ -ULONG WINAPI NdrEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat) -{ - unsigned char switch_type; - unsigned char increment; - ULONG switch_value; - - switch_type = *pFormat & 0xf; - increment = (*pFormat & 0xf0) >> 4; - pFormat++; - - ALIGN_POINTER(pStubMsg->Buffer, increment); - switch_value = get_discriminant(switch_type, pStubMsg->Buffer); - TRACE("got switch value 0x%x\n", switch_value); - - pStubMsg->Memory += increment; - - return increment + union_arm_memory_size(pStubMsg, switch_value, pFormat + *(const SHORT*)pFormat); -} - -/*********************************************************************** - * NdrEncapsulatedUnionFree [RPCRT4.@] - */ -void WINAPI NdrEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - unsigned char switch_type; - unsigned char increment; - ULONG switch_value; - - TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); - pFormat++; - - switch_type = *pFormat & 0xf; - increment = (*pFormat & 0xf0) >> 4; - pFormat++; - - switch_value = get_discriminant(switch_type, pMemory); - TRACE("got switch value 0x%x\n", switch_value); - - pMemory += increment; - - return union_arm_free(pStubMsg, pMemory, switch_value, pFormat); -} - -/*********************************************************************** - * NdrNonEncapsulatedUnionMarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrNonEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - unsigned char switch_type; - - TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); - pFormat++; - - switch_type = *pFormat; - pFormat++; - - pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0); - TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount); - /* Marshall discriminant */ - NdrBaseTypeMarshall(pStubMsg, (unsigned char *)&pStubMsg->MaxCount, &switch_type); - - return union_arm_marshall(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat); -} - -static long unmarshall_discriminant(PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING *ppFormat) -{ - long discriminant = 0; - - switch(**ppFormat) - { - case RPC_FC_BYTE: - case RPC_FC_CHAR: - case RPC_FC_SMALL: - case RPC_FC_USMALL: - { - UCHAR d; - safe_copy_from_buffer(pStubMsg, &d, sizeof(d)); - discriminant = d; - break; - } - case RPC_FC_WCHAR: - case RPC_FC_SHORT: - case RPC_FC_USHORT: - { - USHORT d; - ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT)); - safe_copy_from_buffer(pStubMsg, &d, sizeof(d)); - discriminant = d; - break; - } - case RPC_FC_LONG: - case RPC_FC_ULONG: - { - ULONG d; - ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONG)); - safe_copy_from_buffer(pStubMsg, &d, sizeof(d)); - discriminant = d; - break; - } - default: - FIXME("Unhandled base type: 0x%02x\n", **ppFormat); - } - (*ppFormat)++; - - if (pStubMsg->fHasNewCorrDesc) - *ppFormat += 6; - else - *ppFormat += 4; - return discriminant; -} - -/********************************************************************** - * NdrNonEncapsulatedUnionUnmarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrNonEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char **ppMemory, - PFORMAT_STRING pFormat, - unsigned char fMustAlloc) -{ - long discriminant; - unsigned short size; - - TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); - pFormat++; - - /* Unmarshall discriminant */ - discriminant = unmarshall_discriminant(pStubMsg, &pFormat); - TRACE("unmarshalled discriminant %lx\n", discriminant); - - pFormat += *(const SHORT*)pFormat; - - size = *(const unsigned short*)pFormat; - - if(!*ppMemory || fMustAlloc) - *ppMemory = NdrAllocate(pStubMsg, size); - - return union_arm_unmarshall(pStubMsg, ppMemory, discriminant, pFormat, fMustAlloc); -} - -/*********************************************************************** - * NdrNonEncapsulatedUnionBufferSize [RPCRT4.@] - */ -void WINAPI NdrNonEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - unsigned char switch_type; - - TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); - pFormat++; - - switch_type = *pFormat; - pFormat++; - - pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0); - TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount); - /* Add discriminant size */ - NdrBaseTypeBufferSize(pStubMsg, (unsigned char *)&pStubMsg->MaxCount, &switch_type); - - union_arm_buffer_size(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat); -} - -/*********************************************************************** - * NdrNonEncapsulatedUnionMemorySize [RPCRT4.@] - */ -ULONG WINAPI NdrNonEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat) -{ - ULONG discriminant; - - pFormat++; - /* Unmarshall discriminant */ - discriminant = unmarshall_discriminant(pStubMsg, &pFormat); - TRACE("unmarshalled discriminant 0x%x\n", discriminant); - - return union_arm_memory_size(pStubMsg, discriminant, pFormat + *(const SHORT*)pFormat); -} - -/*********************************************************************** - * NdrNonEncapsulatedUnionFree [RPCRT4.@] - */ -void WINAPI NdrNonEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); - pFormat++; - pFormat++; - - pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0); - TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount); - - return union_arm_free(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat); -} - -/*********************************************************************** - * NdrByteCountPointerMarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrByteCountPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - FIXME("stub\n"); - return NULL; -} - -/*********************************************************************** - * NdrByteCountPointerUnmarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrByteCountPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char **ppMemory, - PFORMAT_STRING pFormat, - unsigned char fMustAlloc) -{ - FIXME("stub\n"); - return NULL; -} - -/*********************************************************************** - * NdrByteCountPointerBufferSize [RPCRT4.@] - */ -void WINAPI NdrByteCountPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - FIXME("stub\n"); -} - -/*********************************************************************** - * NdrByteCountPointerMemorySize [RPCRT4.@] - */ -ULONG WINAPI NdrByteCountPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat) -{ - FIXME("stub\n"); - return 0; -} - -/*********************************************************************** - * NdrByteCountPointerFree [RPCRT4.@] - */ -void WINAPI NdrByteCountPointerFree(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - FIXME("stub\n"); -} - -/*********************************************************************** - * NdrXmitOrRepAsMarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrXmitOrRepAsMarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - FIXME("stub\n"); - return NULL; -} - -/*********************************************************************** - * NdrXmitOrRepAsUnmarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrXmitOrRepAsUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char **ppMemory, - PFORMAT_STRING pFormat, - unsigned char fMustAlloc) -{ - FIXME("stub\n"); - return NULL; -} - -/*********************************************************************** - * NdrXmitOrRepAsBufferSize [RPCRT4.@] - */ -void WINAPI NdrXmitOrRepAsBufferSize(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - FIXME("stub\n"); -} - -/*********************************************************************** - * NdrXmitOrRepAsMemorySize [RPCRT4.@] - */ -ULONG WINAPI NdrXmitOrRepAsMemorySize(PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat) -{ - FIXME("stub\n"); - return 0; -} - -/*********************************************************************** - * NdrXmitOrRepAsFree [RPCRT4.@] - */ -void WINAPI NdrXmitOrRepAsFree(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - FIXME("stub\n"); -} - -#include "pshpack1.h" -typedef struct -{ - unsigned char type; - unsigned char flags_type; /* flags in upper nibble, type in lower nibble */ - ULONG low_value; - ULONG high_value; -} NDR_RANGE; -#include "poppack.h" - -/*********************************************************************** - * NdrRangeMarshall [internal] - */ -unsigned char *WINAPI NdrRangeMarshall( - PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - NDR_RANGE *pRange = (NDR_RANGE *)pFormat; - unsigned char base_type; - - TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat); - - if (pRange->type != RPC_FC_RANGE) - { - ERR("invalid format type %x\n", pRange->type); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return NULL; - } - - base_type = pRange->flags_type & 0xf; - - return NdrBaseTypeMarshall(pStubMsg, pMemory, &base_type); -} - -/*********************************************************************** - * NdrRangeUnmarshall - */ -unsigned char *WINAPI NdrRangeUnmarshall( - PMIDL_STUB_MESSAGE pStubMsg, - unsigned char **ppMemory, - PFORMAT_STRING pFormat, - unsigned char fMustAlloc) -{ - NDR_RANGE *pRange = (NDR_RANGE *)pFormat; - unsigned char base_type; - - TRACE("pStubMsg: %p, ppMemory: %p, type: 0x%02x, fMustAlloc: %s\n", pStubMsg, ppMemory, *pFormat, fMustAlloc ? "true" : "false"); - - if (pRange->type != RPC_FC_RANGE) - { - ERR("invalid format type %x\n", pRange->type); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return NULL; - } - base_type = pRange->flags_type & 0xf; - - TRACE("base_type = 0x%02x, low_value = %d, high_value = %d\n", - base_type, pRange->low_value, pRange->high_value); - -#define RANGE_UNMARSHALL(type, format_spec) \ - do \ - { \ - ALIGN_POINTER(pStubMsg->Buffer, sizeof(type)); \ - if (fMustAlloc || !*ppMemory) \ - *ppMemory = NdrAllocate(pStubMsg, sizeof(type)); \ - if (pStubMsg->Buffer + sizeof(type) > pStubMsg->BufferEnd) \ - { \ - ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n", \ - pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength); \ - RpcRaiseException(RPC_X_BAD_STUB_DATA); \ - } \ - if ((*(type *)pStubMsg->Buffer < (type)pRange->low_value) || \ - (*(type *)pStubMsg->Buffer > (type)pRange->high_value)) \ - { \ - ERR("value exceeded bounds: " format_spec ", low: " format_spec ", high: " format_spec "\n", \ - *(type *)pStubMsg->Buffer, (type)pRange->low_value, \ - (type)pRange->high_value); \ - RpcRaiseException(RPC_S_INVALID_BOUND); \ - return NULL; \ - } \ - TRACE("*ppMemory: %p\n", *ppMemory); \ - **(type **)ppMemory = *(type *)pStubMsg->Buffer; \ - pStubMsg->Buffer += sizeof(type); \ - } while (0) - - switch(base_type) - { - case RPC_FC_CHAR: - case RPC_FC_SMALL: - RANGE_UNMARSHALL(UCHAR, "%d"); - TRACE("value: 0x%02x\n", **(UCHAR **)ppMemory); - break; - case RPC_FC_BYTE: - case RPC_FC_USMALL: - RANGE_UNMARSHALL(CHAR, "%u"); - TRACE("value: 0x%02x\n", **(UCHAR **)ppMemory); - break; - case RPC_FC_WCHAR: /* FIXME: valid? */ - case RPC_FC_USHORT: - RANGE_UNMARSHALL(USHORT, "%u"); - TRACE("value: 0x%04x\n", **(USHORT **)ppMemory); - break; - case RPC_FC_SHORT: - RANGE_UNMARSHALL(SHORT, "%d"); - TRACE("value: 0x%04x\n", **(USHORT **)ppMemory); - break; - case RPC_FC_LONG: - RANGE_UNMARSHALL(LONG, "%d"); - TRACE("value: 0x%08x\n", **(ULONG **)ppMemory); - break; - case RPC_FC_ULONG: - RANGE_UNMARSHALL(ULONG, "%u"); - TRACE("value: 0x%08x\n", **(ULONG **)ppMemory); - break; - case RPC_FC_ENUM16: - case RPC_FC_ENUM32: - FIXME("Unhandled enum type\n"); - break; - case RPC_FC_ERROR_STATUS_T: /* FIXME: valid? */ - case RPC_FC_FLOAT: - case RPC_FC_DOUBLE: - case RPC_FC_HYPER: - default: - ERR("invalid range base type: 0x%02x\n", base_type); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - } - - return NULL; -} - -/*********************************************************************** - * NdrRangeBufferSize [internal] - */ -void WINAPI NdrRangeBufferSize( - PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - NDR_RANGE *pRange = (NDR_RANGE *)pFormat; - unsigned char base_type; - - TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat); - - if (pRange->type != RPC_FC_RANGE) - { - ERR("invalid format type %x\n", pRange->type); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - } - base_type = pRange->flags_type & 0xf; - - NdrBaseTypeBufferSize(pStubMsg, pMemory, &base_type); -} - -/*********************************************************************** - * NdrRangeMemorySize [internal] - */ -ULONG WINAPI NdrRangeMemorySize( - PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat) -{ - NDR_RANGE *pRange = (NDR_RANGE *)pFormat; - unsigned char base_type; - - if (pRange->type != RPC_FC_RANGE) - { - ERR("invalid format type %x\n", pRange->type); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - return 0; - } - base_type = pRange->flags_type & 0xf; - - return NdrBaseTypeMemorySize(pStubMsg, &base_type); -} - -/*********************************************************************** - * NdrRangeFree [internal] - */ -void WINAPI NdrRangeFree(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - TRACE("pStubMsg %p pMemory %p type 0x%02x\n", pStubMsg, pMemory, *pFormat); - - /* nothing to do */ -} - -/*********************************************************************** - * NdrBaseTypeMarshall [internal] - */ -static unsigned char *WINAPI NdrBaseTypeMarshall( - PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat); - - switch(*pFormat) - { - case RPC_FC_BYTE: - case RPC_FC_CHAR: - case RPC_FC_SMALL: - case RPC_FC_USMALL: - safe_copy_to_buffer(pStubMsg, pMemory, sizeof(UCHAR)); - TRACE("value: 0x%02x\n", *(UCHAR *)pMemory); - break; - case RPC_FC_WCHAR: - case RPC_FC_SHORT: - case RPC_FC_USHORT: - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(USHORT)); - safe_copy_to_buffer(pStubMsg, pMemory, sizeof(USHORT)); - TRACE("value: 0x%04x\n", *(USHORT *)pMemory); - break; - case RPC_FC_LONG: - case RPC_FC_ULONG: - case RPC_FC_ERROR_STATUS_T: - case RPC_FC_ENUM32: - 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)); - safe_copy_to_buffer(pStubMsg, pMemory, sizeof(float)); - break; - case RPC_FC_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)); - safe_copy_to_buffer(pStubMsg, pMemory, sizeof(ULONGLONG)); - TRACE("value: %s\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory)); - break; - case RPC_FC_ENUM16: - /* 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); - TRACE("value: 0x%04x\n", *(UINT *)pMemory); - break; - case RPC_FC_IGNORE: - break; - default: - FIXME("Unhandled base type: 0x%02x\n", *pFormat); - } - - /* FIXME: what is the correct return value? */ - return NULL; -} - -/*********************************************************************** - * NdrBaseTypeUnmarshall [internal] - */ -static unsigned char *WINAPI NdrBaseTypeUnmarshall( - PMIDL_STUB_MESSAGE pStubMsg, - unsigned char **ppMemory, - PFORMAT_STRING pFormat, - unsigned char fMustAlloc) -{ - 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)); \ - if (!fMustAlloc && !pStubMsg->IsClient && !*ppMemory) \ - { \ - *ppMemory = pStubMsg->Buffer; \ - TRACE("*ppMemory: %p\n", *ppMemory); \ - } \ - else \ - { \ - if (fMustAlloc) \ - *ppMemory = NdrAllocate(pStubMsg, sizeof(type)); \ - TRACE("*ppMemory: %p\n", *ppMemory); \ - **(type **)ppMemory = *(type *)pStubMsg->Buffer; \ - } \ - pStubMsg->Buffer += sizeof(type); - - switch(*pFormat) - { - case RPC_FC_BYTE: - case RPC_FC_CHAR: - case RPC_FC_SMALL: - case RPC_FC_USMALL: - BASE_TYPE_UNMARSHALL(UCHAR); - TRACE("value: 0x%02x\n", **(UCHAR **)ppMemory); - break; - case RPC_FC_WCHAR: - case RPC_FC_SHORT: - case RPC_FC_USHORT: - BASE_TYPE_UNMARSHALL(USHORT); - TRACE("value: 0x%04x\n", **(USHORT **)ppMemory); - break; - case RPC_FC_LONG: - case RPC_FC_ULONG: - case RPC_FC_ERROR_STATUS_T: - case RPC_FC_ENUM32: - BASE_TYPE_UNMARSHALL(ULONG); - TRACE("value: 0x%08x\n", **(ULONG **)ppMemory); - break; - case RPC_FC_FLOAT: - BASE_TYPE_UNMARSHALL(float); - TRACE("value: %f\n", **(float **)ppMemory); - break; - case RPC_FC_DOUBLE: - BASE_TYPE_UNMARSHALL(double); - TRACE("value: %f\n", **(double **)ppMemory); - break; - case RPC_FC_HYPER: - BASE_TYPE_UNMARSHALL(ULONGLONG); - TRACE("value: %s\n", wine_dbgstr_longlong(**(ULONGLONG **)ppMemory)); - break; - case RPC_FC_ENUM16: - ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT)); - if (fMustAlloc || !*ppMemory) - *ppMemory = NdrAllocate(pStubMsg, sizeof(UINT)); - if (pStubMsg->Buffer + sizeof(USHORT) > pStubMsg->BufferEnd) - RpcRaiseException(RPC_X_BAD_STUB_DATA); - TRACE("*ppMemory: %p\n", *ppMemory); - /* 16-bits on the wire, but int in memory */ - **(UINT **)ppMemory = *(USHORT *)pStubMsg->Buffer; - pStubMsg->Buffer += sizeof(USHORT); - TRACE("value: 0x%08x\n", **(UINT **)ppMemory); - break; - case RPC_FC_IGNORE: - break; - default: - FIXME("Unhandled base type: 0x%02x\n", *pFormat); - } -#undef BASE_TYPE_UNMARSHALL - - /* FIXME: what is the correct return value? */ - - return NULL; -} - -/*********************************************************************** - * NdrBaseTypeBufferSize [internal] - */ -static void WINAPI NdrBaseTypeBufferSize( - PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat); - - switch(*pFormat) - { - case RPC_FC_BYTE: - case RPC_FC_CHAR: - case RPC_FC_SMALL: - case RPC_FC_USMALL: - safe_buffer_length_increment(pStubMsg, sizeof(UCHAR)); - break; - case RPC_FC_WCHAR: - case RPC_FC_SHORT: - case RPC_FC_USHORT: - case RPC_FC_ENUM16: - 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)); - safe_buffer_length_increment(pStubMsg, sizeof(ULONG)); - break; - case RPC_FC_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)); - safe_buffer_length_increment(pStubMsg, sizeof(double)); - break; - case RPC_FC_HYPER: - 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)); - safe_buffer_length_increment(pStubMsg, sizeof(error_status_t)); - break; - case RPC_FC_IGNORE: - break; - default: - FIXME("Unhandled base type: 0x%02x\n", *pFormat); - } -} - -/*********************************************************************** - * NdrBaseTypeMemorySize [internal] - */ -static ULONG WINAPI NdrBaseTypeMemorySize( - PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat) -{ - TRACE("pStubMsg %p, type 0x%02x\n", pStubMsg, *pFormat); - - switch(*pFormat) - { - case RPC_FC_BYTE: - case RPC_FC_CHAR: - case RPC_FC_SMALL: - case RPC_FC_USMALL: - safe_buffer_increment(pStubMsg, sizeof(UCHAR)); - pStubMsg->MemorySize += sizeof(UCHAR); - return sizeof(UCHAR); - case RPC_FC_WCHAR: - case RPC_FC_SHORT: - case RPC_FC_USHORT: - safe_buffer_increment(pStubMsg, sizeof(USHORT)); - pStubMsg->MemorySize += sizeof(USHORT); - return sizeof(USHORT); - case RPC_FC_LONG: - case RPC_FC_ULONG: - case RPC_FC_ENUM32: - safe_buffer_increment(pStubMsg, sizeof(ULONG)); - pStubMsg->MemorySize += sizeof(ULONG); - return sizeof(ULONG); - case RPC_FC_FLOAT: - safe_buffer_increment(pStubMsg, sizeof(float)); - pStubMsg->MemorySize += sizeof(float); - return sizeof(float); - case RPC_FC_DOUBLE: - safe_buffer_increment(pStubMsg, sizeof(double)); - pStubMsg->MemorySize += sizeof(double); - return sizeof(double); - case RPC_FC_HYPER: - safe_buffer_increment(pStubMsg, sizeof(ULONGLONG)); - pStubMsg->MemorySize += sizeof(ULONGLONG); - return sizeof(ULONGLONG); - case RPC_FC_ERROR_STATUS_T: - safe_buffer_increment(pStubMsg, sizeof(error_status_t)); - pStubMsg->MemorySize += sizeof(error_status_t); - return sizeof(error_status_t); - case RPC_FC_ENUM16: - safe_buffer_increment(pStubMsg, sizeof(USHORT)); - pStubMsg->MemorySize += sizeof(UINT); - return sizeof(UINT); - case RPC_FC_IGNORE: - pStubMsg->MemorySize += sizeof(void *); - return sizeof(void *); - default: - FIXME("Unhandled base type: 0x%02x\n", *pFormat); - return 0; - } -} - -/*********************************************************************** - * NdrBaseTypeFree [internal] - */ -static void WINAPI NdrBaseTypeFree(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - TRACE("pStubMsg %p pMemory %p type 0x%02x\n", pStubMsg, pMemory, *pFormat); - - /* nothing to do */ -} - -/*********************************************************************** - * NdrContextHandleBufferSize [internal] - */ -static void WINAPI NdrContextHandleBufferSize( - PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat); - - if (*pFormat != RPC_FC_BIND_CONTEXT) - { - ERR("invalid format type %x\n", *pFormat); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - } - ALIGN_LENGTH(pStubMsg->BufferLength, 4); - safe_buffer_length_increment(pStubMsg, cbNDRContext); -} - -/*********************************************************************** - * NdrContextHandleMarshall [internal] - */ -static unsigned char *WINAPI NdrContextHandleMarshall( - PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat); - - if (*pFormat != RPC_FC_BIND_CONTEXT) - { - ERR("invalid format type %x\n", *pFormat); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - } - - if (pFormat[1] & 0x80) - NdrClientContextMarshall(pStubMsg, *(NDR_CCONTEXT **)pMemory, FALSE); - else - NdrClientContextMarshall(pStubMsg, (NDR_CCONTEXT *)pMemory, FALSE); - - return NULL; -} - -/*********************************************************************** - * NdrContextHandleUnmarshall [internal] - */ -static unsigned char *WINAPI NdrContextHandleUnmarshall( - PMIDL_STUB_MESSAGE pStubMsg, - unsigned char **ppMemory, - PFORMAT_STRING pFormat, - unsigned char fMustAlloc) -{ - if (*pFormat != RPC_FC_BIND_CONTEXT) - { - ERR("invalid format type %x\n", *pFormat); - RpcRaiseException(RPC_S_INTERNAL_ERROR); - } - - **(NDR_CCONTEXT **)ppMemory = NULL; - NdrClientContextUnmarshall(pStubMsg, *(NDR_CCONTEXT **)ppMemory, pStubMsg->RpcMsg->Handle); - - return NULL; -} - -/*********************************************************************** - * NdrClientContextMarshall [RPCRT4.@] - */ -void WINAPI NdrClientContextMarshall(PMIDL_STUB_MESSAGE pStubMsg, - NDR_CCONTEXT ContextHandle, - int fCheck) -{ - TRACE("(%p, %p, %d)\n", pStubMsg, ContextHandle, fCheck); - - ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4); - - if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) - { - ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n", - pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - } - - /* FIXME: what does fCheck do? */ - NDRCContextMarshall(ContextHandle, - pStubMsg->Buffer); - - pStubMsg->Buffer += cbNDRContext; -} - -/*********************************************************************** - * NdrClientContextUnmarshall [RPCRT4.@] - */ -void WINAPI NdrClientContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, - NDR_CCONTEXT * pContextHandle, - RPC_BINDING_HANDLE BindHandle) -{ - TRACE("(%p, %p, %p)\n", pStubMsg, pContextHandle, BindHandle); - - ALIGN_POINTER(pStubMsg->Buffer, 4); - - if (pStubMsg->Buffer + cbNDRContext > pStubMsg->BufferEnd) - RpcRaiseException(RPC_X_BAD_STUB_DATA); - - NDRCContextUnmarshall(pContextHandle, - BindHandle, - pStubMsg->Buffer, - pStubMsg->RpcMsg->DataRepresentation); - - pStubMsg->Buffer += cbNDRContext; -} - -void WINAPI NdrServerContextMarshall(PMIDL_STUB_MESSAGE pStubMsg, - NDR_SCONTEXT ContextHandle, - NDR_RUNDOWN RundownRoutine ) -{ - TRACE("(%p, %p, %p)\n", pStubMsg, ContextHandle, RundownRoutine); - - ALIGN_POINTER(pStubMsg->Buffer, 4); - - if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) - { - ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n", - pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - } - - NDRSContextMarshall2(pStubMsg->RpcMsg->Handle, ContextHandle, - pStubMsg->Buffer, RundownRoutine, NULL, 0); - pStubMsg->Buffer += cbNDRContext; -} - -NDR_SCONTEXT WINAPI NdrServerContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg) -{ - NDR_SCONTEXT ContextHandle; - - TRACE("(%p)\n", pStubMsg); - - ALIGN_POINTER(pStubMsg->Buffer, 4); - - if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) - { - ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n", - pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - } - - ContextHandle = NDRSContextUnmarshall2(pStubMsg->RpcMsg->Handle, - pStubMsg->Buffer, - pStubMsg->RpcMsg->DataRepresentation, - NULL, 0); - pStubMsg->Buffer += cbNDRContext; - - return ContextHandle; -} - -void WINAPI NdrContextHandleSize(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char* pMemory, - PFORMAT_STRING pFormat) -{ - FIXME("(%p, %p, %p): stub\n", pStubMsg, pMemory, pFormat); -} - -NDR_SCONTEXT WINAPI NdrContextHandleInitialize(PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat) -{ - TRACE("(%p, %p)\n", pStubMsg, pFormat); - return NDRSContextUnmarshall2(pStubMsg->RpcMsg->Handle, NULL, - pStubMsg->RpcMsg->DataRepresentation, NULL, 0); -} - -void WINAPI NdrServerContextNewMarshall(PMIDL_STUB_MESSAGE pStubMsg, - NDR_SCONTEXT ContextHandle, - NDR_RUNDOWN RundownRoutine, - PFORMAT_STRING pFormat) -{ - TRACE("(%p, %p, %p, %p)\n", pStubMsg, ContextHandle, RundownRoutine, pFormat); - - ALIGN_POINTER(pStubMsg->Buffer, 4); - - if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) - { - ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n", - pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - } - - /* FIXME: do something with pFormat */ - NDRSContextMarshall2(pStubMsg->RpcMsg->Handle, ContextHandle, - pStubMsg->Buffer, RundownRoutine, NULL, 0); - pStubMsg->Buffer += cbNDRContext; -} - -NDR_SCONTEXT WINAPI NdrServerContextNewUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat) -{ - NDR_SCONTEXT ContextHandle; - - TRACE("(%p, %p)\n", pStubMsg, pFormat); - - ALIGN_POINTER(pStubMsg->Buffer, 4); - - if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) - { - ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n", - pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - } - - /* FIXME: do something with pFormat */ - ContextHandle = NDRSContextUnmarshall2(pStubMsg->RpcMsg->Handle, - pStubMsg->Buffer, - pStubMsg->RpcMsg->DataRepresentation, - NULL, 0); - pStubMsg->Buffer += cbNDRContext; - - return ContextHandle; -} +/* + * NDR data marshalling + * + * Copyright 2002 Greg Turner + * Copyright 2003-2006 CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + * + * TODO: + * - Non-conformant strings + * - String structs + * - Byte count pointers + * - transmit_as/represent as + * - Multi-dimensional arrays + * - Conversion functions (NdrConvert) + * - Checks for integer addition overflow in base type and user marshall functions + */ + +#include +#include +#include +#include +#include + +#include "windef.h" +#include "winbase.h" +#include "winerror.h" + +#include "ndr_misc.h" +#include "rpcndr.h" + +#include "wine/unicode.h" +#include "wine/rpcfc.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(ole); + +#if defined(__i386__) +# define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \ + (*((UINT32 *)(pchar)) = (uint32)) + +# define LITTLE_ENDIAN_UINT32_READ(pchar) \ + (*((UINT32 *)(pchar))) +#else + /* these would work for i386 too, but less efficient */ +# define LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) \ + (*(pchar) = LOBYTE(LOWORD(uint32)), \ + *((pchar)+1) = HIBYTE(LOWORD(uint32)), \ + *((pchar)+2) = LOBYTE(HIWORD(uint32)), \ + *((pchar)+3) = HIBYTE(HIWORD(uint32)), \ + (uint32)) /* allow as r-value */ + +# define LITTLE_ENDIAN_UINT32_READ(pchar) \ + (MAKELONG( \ + MAKEWORD(*(pchar), *((pchar)+1)), \ + MAKEWORD(*((pchar)+2), *((pchar)+3)))) +#endif + +#define BIG_ENDIAN_UINT32_WRITE(pchar, uint32) \ + (*((pchar)+3) = LOBYTE(LOWORD(uint32)), \ + *((pchar)+2) = HIBYTE(LOWORD(uint32)), \ + *((pchar)+1) = LOBYTE(HIWORD(uint32)), \ + *(pchar) = HIBYTE(HIWORD(uint32)), \ + (uint32)) /* allow as r-value */ + +#define BIG_ENDIAN_UINT32_READ(pchar) \ + (MAKELONG( \ + MAKEWORD(*((pchar)+3), *((pchar)+2)), \ + MAKEWORD(*((pchar)+1), *(pchar)))) + +#ifdef NDR_LOCAL_IS_BIG_ENDIAN +# define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \ + BIG_ENDIAN_UINT32_WRITE(pchar, uint32) +# define NDR_LOCAL_UINT32_READ(pchar) \ + BIG_ENDIAN_UINT32_READ(pchar) +#else +# define NDR_LOCAL_UINT32_WRITE(pchar, uint32) \ + LITTLE_ENDIAN_UINT32_WRITE(pchar, uint32) +# define NDR_LOCAL_UINT32_READ(pchar) \ + 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) + +#define STD_OVERFLOW_CHECK(_Msg) do { \ + TRACE("buffer=%d/%d\n", _Msg->Buffer - (unsigned char *)_Msg->RpcMsg->Buffer, _Msg->BufferLength); \ + if (_Msg->Buffer > (unsigned char *)_Msg->RpcMsg->Buffer + _Msg->BufferLength) \ + ERR("buffer overflow %d bytes\n", _Msg->Buffer - ((unsigned char *)_Msg->RpcMsg->Buffer + _Msg->BufferLength)); \ + } while (0) + +#define NDR_TABLE_SIZE 128 +#define NDR_TABLE_MASK 127 + +static unsigned char *WINAPI NdrBaseTypeMarshall(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING); +static unsigned char *WINAPI NdrBaseTypeUnmarshall(PMIDL_STUB_MESSAGE, unsigned char **, PFORMAT_STRING, unsigned char); +static void WINAPI NdrBaseTypeBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING); +static void WINAPI NdrBaseTypeFree(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING); +static ULONG WINAPI NdrBaseTypeMemorySize(PMIDL_STUB_MESSAGE, PFORMAT_STRING); + +static unsigned char *WINAPI NdrContextHandleMarshall(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING); +static void WINAPI NdrContextHandleBufferSize(PMIDL_STUB_MESSAGE, unsigned char *, PFORMAT_STRING); +static unsigned char *WINAPI NdrContextHandleUnmarshall(PMIDL_STUB_MESSAGE, unsigned char **, PFORMAT_STRING, unsigned char); + +const NDR_MARSHALL NdrMarshaller[NDR_TABLE_SIZE] = { + 0, + NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, + NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, + NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, + NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, NdrBaseTypeMarshall, + /* 0x10 */ + NdrBaseTypeMarshall, + /* 0x11 */ + NdrPointerMarshall, NdrPointerMarshall, + NdrPointerMarshall, NdrPointerMarshall, + /* 0x15 */ + NdrSimpleStructMarshall, NdrSimpleStructMarshall, + NdrConformantStructMarshall, NdrConformantStructMarshall, + NdrConformantVaryingStructMarshall, + NdrComplexStructMarshall, + /* 0x1b */ + NdrConformantArrayMarshall, + NdrConformantVaryingArrayMarshall, + NdrFixedArrayMarshall, NdrFixedArrayMarshall, + NdrVaryingArrayMarshall, NdrVaryingArrayMarshall, + NdrComplexArrayMarshall, + /* 0x22 */ + NdrConformantStringMarshall, 0, 0, + NdrConformantStringMarshall, + NdrNonConformantStringMarshall, 0, 0, 0, + /* 0x2a */ + NdrEncapsulatedUnionMarshall, + NdrNonEncapsulatedUnionMarshall, + NdrByteCountPointerMarshall, + NdrXmitOrRepAsMarshall, NdrXmitOrRepAsMarshall, + /* 0x2f */ + NdrInterfacePointerMarshall, + /* 0x30 */ + NdrContextHandleMarshall, + /* 0xb1 */ + 0, 0, 0, + NdrUserMarshalMarshall, + 0, 0, + /* 0xb7 */ + NdrRangeMarshall +}; +const NDR_UNMARSHALL NdrUnmarshaller[NDR_TABLE_SIZE] = { + 0, + NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, + NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, + NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, + NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, NdrBaseTypeUnmarshall, + /* 0x10 */ + NdrBaseTypeUnmarshall, + /* 0x11 */ + NdrPointerUnmarshall, NdrPointerUnmarshall, + NdrPointerUnmarshall, NdrPointerUnmarshall, + /* 0x15 */ + NdrSimpleStructUnmarshall, NdrSimpleStructUnmarshall, + NdrConformantStructUnmarshall, NdrConformantStructUnmarshall, + NdrConformantVaryingStructUnmarshall, + NdrComplexStructUnmarshall, + /* 0x1b */ + NdrConformantArrayUnmarshall, + NdrConformantVaryingArrayUnmarshall, + NdrFixedArrayUnmarshall, NdrFixedArrayUnmarshall, + NdrVaryingArrayUnmarshall, NdrVaryingArrayUnmarshall, + NdrComplexArrayUnmarshall, + /* 0x22 */ + NdrConformantStringUnmarshall, 0, 0, + NdrConformantStringUnmarshall, + NdrNonConformantStringUnmarshall, 0, 0, 0, + /* 0x2a */ + NdrEncapsulatedUnionUnmarshall, + NdrNonEncapsulatedUnionUnmarshall, + NdrByteCountPointerUnmarshall, + NdrXmitOrRepAsUnmarshall, NdrXmitOrRepAsUnmarshall, + /* 0x2f */ + NdrInterfacePointerUnmarshall, + /* 0x30 */ + NdrContextHandleUnmarshall, + /* 0xb1 */ + 0, 0, 0, + NdrUserMarshalUnmarshall, + 0, 0, + /* 0xb7 */ + NdrRangeUnmarshall +}; +const NDR_BUFFERSIZE NdrBufferSizer[NDR_TABLE_SIZE] = { + 0, + NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, + NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, + NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, + NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, NdrBaseTypeBufferSize, + /* 0x10 */ + NdrBaseTypeBufferSize, + /* 0x11 */ + NdrPointerBufferSize, NdrPointerBufferSize, + NdrPointerBufferSize, NdrPointerBufferSize, + /* 0x15 */ + NdrSimpleStructBufferSize, NdrSimpleStructBufferSize, + NdrConformantStructBufferSize, NdrConformantStructBufferSize, + NdrConformantVaryingStructBufferSize, + NdrComplexStructBufferSize, + /* 0x1b */ + NdrConformantArrayBufferSize, + NdrConformantVaryingArrayBufferSize, + NdrFixedArrayBufferSize, NdrFixedArrayBufferSize, + NdrVaryingArrayBufferSize, NdrVaryingArrayBufferSize, + NdrComplexArrayBufferSize, + /* 0x22 */ + NdrConformantStringBufferSize, 0, 0, + NdrConformantStringBufferSize, + NdrNonConformantStringBufferSize, 0, 0, 0, + /* 0x2a */ + NdrEncapsulatedUnionBufferSize, + NdrNonEncapsulatedUnionBufferSize, + NdrByteCountPointerBufferSize, + NdrXmitOrRepAsBufferSize, NdrXmitOrRepAsBufferSize, + /* 0x2f */ + NdrInterfacePointerBufferSize, + /* 0x30 */ + NdrContextHandleBufferSize, + /* 0xb1 */ + 0, 0, 0, + NdrUserMarshalBufferSize, + 0, 0, + /* 0xb7 */ + NdrRangeBufferSize +}; +const NDR_MEMORYSIZE NdrMemorySizer[NDR_TABLE_SIZE] = { + 0, + NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, + NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, + NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, + NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, NdrBaseTypeMemorySize, + /* 0x10 */ + NdrBaseTypeMemorySize, + /* 0x11 */ + NdrPointerMemorySize, NdrPointerMemorySize, + NdrPointerMemorySize, NdrPointerMemorySize, + /* 0x15 */ + NdrSimpleStructMemorySize, NdrSimpleStructMemorySize, + NdrConformantStructMemorySize, NdrConformantStructMemorySize, + NdrConformantVaryingStructMemorySize, + NdrComplexStructMemorySize, + /* 0x1b */ + NdrConformantArrayMemorySize, + NdrConformantVaryingArrayMemorySize, + NdrFixedArrayMemorySize, NdrFixedArrayMemorySize, + NdrVaryingArrayMemorySize, NdrVaryingArrayMemorySize, + NdrComplexArrayMemorySize, + /* 0x22 */ + NdrConformantStringMemorySize, 0, 0, + NdrConformantStringMemorySize, + NdrNonConformantStringMemorySize, 0, 0, 0, + /* 0x2a */ + NdrEncapsulatedUnionMemorySize, + NdrNonEncapsulatedUnionMemorySize, + NdrByteCountPointerMemorySize, + NdrXmitOrRepAsMemorySize, NdrXmitOrRepAsMemorySize, + /* 0x2f */ + NdrInterfacePointerMemorySize, + /* 0x30 */ + 0, + /* 0xb1 */ + 0, 0, 0, + NdrUserMarshalMemorySize, + 0, 0, + /* 0xb7 */ + NdrRangeMemorySize +}; +const NDR_FREE NdrFreer[NDR_TABLE_SIZE] = { + 0, + NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, + NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, + NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, + NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, NdrBaseTypeFree, + /* 0x10 */ + NdrBaseTypeFree, + /* 0x11 */ + NdrPointerFree, NdrPointerFree, + NdrPointerFree, NdrPointerFree, + /* 0x15 */ + NdrSimpleStructFree, NdrSimpleStructFree, + NdrConformantStructFree, NdrConformantStructFree, + NdrConformantVaryingStructFree, + NdrComplexStructFree, + /* 0x1b */ + NdrConformantArrayFree, + NdrConformantVaryingArrayFree, + NdrFixedArrayFree, NdrFixedArrayFree, + NdrVaryingArrayFree, NdrVaryingArrayFree, + NdrComplexArrayFree, + /* 0x22 */ + 0, 0, 0, + 0, 0, 0, 0, 0, + /* 0x2a */ + NdrEncapsulatedUnionFree, + NdrNonEncapsulatedUnionFree, + 0, + NdrXmitOrRepAsFree, NdrXmitOrRepAsFree, + /* 0x2f */ + NdrInterfacePointerFree, + /* 0x30 */ + 0, + /* 0xb1 */ + 0, 0, 0, + NdrUserMarshalFree, + 0, 0, + /* 0xb7 */ + NdrRangeFree +}; + +typedef struct _NDR_MEMORY_LIST +{ + ULONG magic; + ULONG size; + ULONG reserved; + struct _NDR_MEMORY_LIST *next; +} NDR_MEMORY_LIST; + +#define MEML_MAGIC ('M' << 24 | 'E' << 16 | 'M' << 8 | 'L') + +/*********************************************************************** + * NdrAllocate [RPCRT4.@] + * + * Allocates a block of memory using pStubMsg->pfnAllocate. + * + * PARAMS + * pStubMsg [I/O] MIDL_STUB_MESSAGE structure. + * len [I] Size of memory block to allocate. + * + * RETURNS + * The memory block of size len that was allocated. + * + * NOTES + * The memory block is always 8-byte aligned. + * If the function is unable to allocate memory an ERROR_OUTOFMEMORY + * exception is raised. + */ +void * WINAPI NdrAllocate(MIDL_STUB_MESSAGE *pStubMsg, size_t len) +{ + size_t aligned_len; + size_t adjusted_len; + void *p; + NDR_MEMORY_LIST *mem_list; + + aligned_len = ALIGNED_LENGTH(len, 8); + adjusted_len = aligned_len + sizeof(NDR_MEMORY_LIST); + /* check for overflow */ + if (adjusted_len < len) + { + ERR("overflow of adjusted_len %d, len %d\n", adjusted_len, len); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + + p = pStubMsg->pfnAllocate(adjusted_len); + if (!p) RpcRaiseException(ERROR_OUTOFMEMORY); + + mem_list = (NDR_MEMORY_LIST *)((char *)p + aligned_len); + mem_list->magic = MEML_MAGIC; + mem_list->size = aligned_len; + mem_list->reserved = 0; + mem_list->next = pStubMsg->pMemoryList; + pStubMsg->pMemoryList = mem_list; + + TRACE("-- %p\n", p); + return p; +} + +static void WINAPI NdrFree(MIDL_STUB_MESSAGE *pStubMsg, unsigned char *Pointer) +{ + TRACE("(%p, %p)\n", pStubMsg, Pointer); + + pStubMsg->pfnFree(Pointer); +} + +static inline BOOL IsConformanceOrVariancePresent(PFORMAT_STRING pFormat) +{ + return (*(const ULONG *)pFormat != -1); +} + +static PFORMAT_STRING ReadConformance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat) +{ + 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); + pStubMsg->Buffer += 4; + TRACE("unmarshalled conformance is %ld\n", pStubMsg->MaxCount); + if (pStubMsg->fHasNewCorrDesc) + return pFormat+6; + else + return pFormat+4; +} + +static inline PFORMAT_STRING ReadVariance(MIDL_STUB_MESSAGE *pStubMsg, PFORMAT_STRING pFormat, ULONG MaxValue) +{ + if (pFormat && !IsConformanceOrVariancePresent(pFormat)) + { + pStubMsg->Offset = 0; + pStubMsg->ActualCount = pStubMsg->MaxCount; + goto done; + } + + 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); + pStubMsg->Buffer += 4; + TRACE("offset is %d\n", pStubMsg->Offset); + pStubMsg->ActualCount = NDR_LOCAL_UINT32_READ(pStubMsg->Buffer); + pStubMsg->Buffer += 4; + TRACE("variance is %d\n", pStubMsg->ActualCount); + + if ((pStubMsg->ActualCount > MaxValue) || + (pStubMsg->ActualCount + pStubMsg->Offset > MaxValue)) + { + ERR("invalid array bound(s): ActualCount = %d, Offset = %d, MaxValue = %d\n", + pStubMsg->ActualCount, pStubMsg->Offset, MaxValue); + RpcRaiseException(RPC_S_INVALID_BOUND); + return NULL; + } + +done: + if (pStubMsg->fHasNewCorrDesc) + return pFormat+6; + else + return pFormat+4; +} + +/* writes the conformance value to the buffer */ +static inline void WriteConformance(MIDL_STUB_MESSAGE *pStubMsg) +{ + 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); + pStubMsg->Buffer += 4; +} + +/* writes the variance values to the buffer */ +static inline void WriteVariance(MIDL_STUB_MESSAGE *pStubMsg) +{ + 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); + pStubMsg->Buffer += 4; + NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, pStubMsg->ActualCount); + pStubMsg->Buffer += 4; +} + +/* requests buffer space for the conformance value */ +static inline void SizeConformance(MIDL_STUB_MESSAGE *pStubMsg) +{ + ALIGN_LENGTH(pStubMsg->BufferLength, 4); + if (pStubMsg->BufferLength + 4 < pStubMsg->BufferLength) + RpcRaiseException(RPC_X_BAD_STUB_DATA); + pStubMsg->BufferLength += 4; +} + +/* requests buffer space for the variance values */ +static inline void SizeVariance(MIDL_STUB_MESSAGE *pStubMsg) +{ + ALIGN_LENGTH(pStubMsg->BufferLength, 4); + if (pStubMsg->BufferLength + 8 < pStubMsg->BufferLength) + RpcRaiseException(RPC_X_BAD_STUB_DATA); + pStubMsg->BufferLength += 8; +} + +PFORMAT_STRING ComputeConformanceOrVariance( + MIDL_STUB_MESSAGE *pStubMsg, unsigned char *pMemory, + PFORMAT_STRING pFormat, ULONG_PTR def, ULONG_PTR *pCount) +{ + BYTE dtype = pFormat[0] & 0xf; + short ofs = *(const short *)&pFormat[2]; + LPVOID ptr = NULL; + DWORD data = 0; + + if (!IsConformanceOrVariancePresent(pFormat)) { + /* null descriptor */ + *pCount = def; + goto finish_conf; + } + + switch (pFormat[0] & 0xf0) { + case RPC_FC_NORMAL_CONFORMANCE: + TRACE("normal conformance, ofs=%d\n", ofs); + ptr = pMemory; + break; + case RPC_FC_POINTER_CONFORMANCE: + TRACE("pointer conformance, ofs=%d\n", ofs); + ptr = pStubMsg->Memory; + break; + case RPC_FC_TOP_LEVEL_CONFORMANCE: + TRACE("toplevel conformance, ofs=%d\n", ofs); + if (pStubMsg->StackTop) { + ptr = pStubMsg->StackTop; + } + else { + /* -Os mode, *pCount is already set */ + goto finish_conf; + } + break; + case RPC_FC_CONSTANT_CONFORMANCE: + data = ofs | ((DWORD)pFormat[1] << 16); + TRACE("constant conformance, val=%d\n", data); + *pCount = data; + goto finish_conf; + case RPC_FC_TOP_LEVEL_MULTID_CONFORMANCE: + FIXME("toplevel multidimensional conformance, ofs=%d\n", ofs); + if (pStubMsg->StackTop) { + ptr = pStubMsg->StackTop; + } + else { + /* ? */ + goto done_conf_grab; + } + break; + default: + FIXME("unknown conformance type %x\n", pFormat[0] & 0xf0); + } + + switch (pFormat[1]) { + case RPC_FC_DEREFERENCE: + ptr = *(LPVOID*)((char *)ptr + ofs); + break; + case RPC_FC_CALLBACK: + { + unsigned char *old_stack_top = pStubMsg->StackTop; + pStubMsg->StackTop = ptr; + + /* ofs is index into StubDesc->apfnExprEval */ + TRACE("callback conformance into apfnExprEval[%d]\n", ofs); + pStubMsg->StubDesc->apfnExprEval[ofs](pStubMsg); + + pStubMsg->StackTop = old_stack_top; + + /* the callback function always stores the computed value in MaxCount */ + *pCount = pStubMsg->MaxCount; + goto finish_conf; + } + default: + ptr = (char *)ptr + ofs; + break; + } + + switch (dtype) { + case RPC_FC_LONG: + case RPC_FC_ULONG: + data = *(DWORD*)ptr; + break; + case RPC_FC_SHORT: + data = *(SHORT*)ptr; + break; + case RPC_FC_USHORT: + data = *(USHORT*)ptr; + break; + case RPC_FC_CHAR: + case RPC_FC_SMALL: + data = *(CHAR*)ptr; + break; + case RPC_FC_BYTE: + case RPC_FC_USMALL: + data = *(UCHAR*)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); + +done_conf_grab: + switch (pFormat[1]) { + case RPC_FC_DEREFERENCE: /* already handled */ + case 0: /* no op */ + *pCount = data; + break; + case RPC_FC_ADD_1: + *pCount = data + 1; + break; + case RPC_FC_SUB_1: + *pCount = data - 1; + break; + case RPC_FC_MULT_2: + *pCount = data * 2; + break; + case RPC_FC_DIV_2: + *pCount = data / 2; + break; + default: + FIXME("unknown conformance op %d\n", pFormat[1]); + goto finish_conf; + } + +finish_conf: + TRACE("resulting conformance is %ld\n", *pCount); + if (pStubMsg->fHasNewCorrDesc) + return pFormat+6; + else + return pFormat+4; +} + +/* multiply two numbers together, raising an RPC_S_INVALID_BOUND exception if + * the result overflows 32-bits */ +static inline ULONG safe_multiply(ULONG a, ULONG b) +{ + ULONGLONG ret = (ULONGLONG)a * b; + if (ret > 0xffffffff) + { + RpcRaiseException(RPC_S_INVALID_BOUND); + return 0; + } + return ret; +} + +static inline void safe_buffer_increment(MIDL_STUB_MESSAGE *pStubMsg, ULONG size) +{ + if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */ + (pStubMsg->Buffer + size > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)) + RpcRaiseException(RPC_X_BAD_STUB_DATA); + pStubMsg->Buffer += size; +} + +static inline void safe_buffer_length_increment(MIDL_STUB_MESSAGE *pStubMsg, ULONG size) +{ + if (pStubMsg->BufferLength + size < pStubMsg->BufferLength) /* integer overflow of pStubMsg->BufferSize */ + { + ERR("buffer length overflow - BufferLength = %u, size = %u\n", + pStubMsg->BufferLength, size); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + pStubMsg->BufferLength += size; +} + +/* copies data from the buffer, checking that there is enough data in the buffer + * to do so */ +static inline void safe_copy_from_buffer(MIDL_STUB_MESSAGE *pStubMsg, void *p, ULONG size) +{ + if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */ + (pStubMsg->Buffer + size > pStubMsg->BufferEnd)) + { + ERR("buffer overflow - Buffer = %p, BufferEnd = %p, size = %u\n", + pStubMsg->Buffer, pStubMsg->BufferEnd, size); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + if (p == pStubMsg->Buffer) + ERR("pointer is the same as the buffer\n"); + memcpy(p, pStubMsg->Buffer, size); + pStubMsg->Buffer += size; +} + +/* copies data to the buffer, checking that there is enough space to do so */ +static inline void safe_copy_to_buffer(MIDL_STUB_MESSAGE *pStubMsg, const void *p, ULONG size) +{ + if ((pStubMsg->Buffer + size < pStubMsg->Buffer) || /* integer overflow of pStubMsg->Buffer */ + (pStubMsg->Buffer + size > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength)) + { + ERR("buffer overflow - Buffer = %p, BufferEnd = %p, size = %u\n", + pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength, + size); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + memcpy(pStubMsg->Buffer, p, size); + pStubMsg->Buffer += size; +} + +/* + * NdrConformantString: + * + * What MS calls a ConformantString is, in DCE terminology, + * a Varying-Conformant String. + * [ + * maxlen: DWORD (max # of CHARTYPE characters, inclusive of '\0') + * offset: DWORD (actual string data begins at (offset) CHARTYPE's + * into unmarshalled string) + * length: DWORD (# of CHARTYPE characters, inclusive of '\0') + * [ + * data: CHARTYPE[maxlen] + * ] + * ], where CHARTYPE is the appropriate character type (specified externally) + * + */ + +/*********************************************************************** + * NdrConformantStringMarshall [RPCRT4.@] + */ +unsigned char *WINAPI NdrConformantStringMarshall(MIDL_STUB_MESSAGE *pStubMsg, + unsigned char *pszMessage, PFORMAT_STRING pFormat) +{ + ULONG esize, size; + + TRACE("(pStubMsg == ^%p, pszMessage == ^%p, pFormat == ^%p)\n", pStubMsg, pszMessage, pFormat); + + if (*pFormat == RPC_FC_C_CSTRING) { + TRACE("string=%s\n", debugstr_a((char*)pszMessage)); + pStubMsg->ActualCount = strlen((char*)pszMessage)+1; + esize = 1; + } + else if (*pFormat == RPC_FC_C_WSTRING) { + TRACE("string=%s\n", debugstr_w((LPWSTR)pszMessage)); + pStubMsg->ActualCount = strlenW((LPWSTR)pszMessage)+1; + esize = 2; + } + else { + ERR("Unhandled string type: %#x\n", *pFormat); + /* FIXME: raise an exception. */ + return NULL; + } + + if (pFormat[1] == RPC_FC_STRING_SIZED) + pFormat = ComputeConformance(pStubMsg, pszMessage, pFormat + 2, 0); + else + pStubMsg->MaxCount = pStubMsg->ActualCount; + pStubMsg->Offset = 0; + WriteConformance(pStubMsg); + WriteVariance(pStubMsg); + + size = safe_multiply(esize, pStubMsg->ActualCount); + safe_copy_to_buffer(pStubMsg, pszMessage, size); /* the string itself */ + + /* success */ + return NULL; /* is this always right? */ +} + +/*********************************************************************** + * NdrConformantStringBufferSize [RPCRT4.@] + */ +void WINAPI NdrConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char* pMemory, PFORMAT_STRING pFormat) +{ + ULONG esize; + + TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat); + + SizeConformance(pStubMsg); + SizeVariance(pStubMsg); + + if (*pFormat == RPC_FC_C_CSTRING) { + TRACE("string=%s\n", debugstr_a((char*)pMemory)); + pStubMsg->ActualCount = strlen((char*)pMemory)+1; + esize = 1; + } + else if (*pFormat == RPC_FC_C_WSTRING) { + TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory)); + pStubMsg->ActualCount = strlenW((LPWSTR)pMemory)+1; + esize = 2; + } + else { + ERR("Unhandled string type: %#x\n", *pFormat); + /* FIXME: raise an exception */ + return; + } + + if (pFormat[1] == RPC_FC_STRING_SIZED) + pFormat = ComputeConformance(pStubMsg, pMemory, pFormat + 2, 0); + else + pStubMsg->MaxCount = pStubMsg->ActualCount; + + safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount)); +} + +/************************************************************************ + * NdrConformantStringMemorySize [RPCRT4.@] + */ +ULONG WINAPI NdrConformantStringMemorySize( PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat ) +{ + ULONG bufsize, memsize, esize, i; + + TRACE("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat); + + ReadConformance(pStubMsg, NULL); + ReadVariance(pStubMsg, NULL, pStubMsg->MaxCount); + + if (pFormat[1] != RPC_FC_STRING_SIZED && (pStubMsg->MaxCount != pStubMsg->ActualCount)) + { + ERR("buffer size %d must equal memory size %ld for non-sized conformant strings\n", + pStubMsg->ActualCount, pStubMsg->MaxCount); + RpcRaiseException(RPC_S_INVALID_BOUND); + } + if (pStubMsg->Offset) + { + ERR("conformant strings can't have Offset (%d)\n", pStubMsg->Offset); + RpcRaiseException(RPC_S_INVALID_BOUND); + } + + if (*pFormat == RPC_FC_C_CSTRING) esize = 1; + else if (*pFormat == RPC_FC_C_WSTRING) esize = 2; + else { + ERR("Unhandled string type: %#x\n", *pFormat); + /* FIXME: raise an exception */ + esize = 0; + } + + memsize = safe_multiply(esize, pStubMsg->MaxCount); + bufsize = safe_multiply(esize, pStubMsg->ActualCount); + + /* strings must always have null terminating bytes */ + if (bufsize < esize) + { + ERR("invalid string length of %d\n", pStubMsg->ActualCount); + RpcRaiseException(RPC_S_INVALID_BOUND); + } + + /* verify the buffer is safe to access */ + if ((pStubMsg->Buffer + bufsize < pStubMsg->Buffer) || + (pStubMsg->Buffer + bufsize > pStubMsg->BufferEnd)) + { + ERR("bufsize 0x%x exceeded buffer end %p of buffer %p\n", bufsize, + pStubMsg->BufferEnd, pStubMsg->Buffer); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + + for (i = bufsize - esize; i < bufsize; i++) + if (pStubMsg->Buffer[i] != 0) + { + ERR("string not null-terminated at byte position %d, data is 0x%x\n", + i, pStubMsg->Buffer[i]); + RpcRaiseException(RPC_S_INVALID_BOUND); + } + + safe_buffer_increment(pStubMsg, bufsize); + pStubMsg->MemorySize += memsize; + + return pStubMsg->MemorySize; +} + +/************************************************************************ + * NdrConformantStringUnmarshall [RPCRT4.@] + */ +unsigned char *WINAPI NdrConformantStringUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, + unsigned char** ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc ) +{ + ULONG bufsize, memsize, esize, i; + + TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n", + pStubMsg, *ppMemory, pFormat, fMustAlloc); + + assert(pFormat && ppMemory && pStubMsg); + + ReadConformance(pStubMsg, NULL); + ReadVariance(pStubMsg, NULL, pStubMsg->MaxCount); + + if (pFormat[1] != RPC_FC_STRING_SIZED && (pStubMsg->MaxCount != pStubMsg->ActualCount)) + { + ERR("buffer size %d must equal memory size %ld for non-sized conformant strings\n", + pStubMsg->ActualCount, pStubMsg->MaxCount); + RpcRaiseException(RPC_S_INVALID_BOUND); + return NULL; + } + if (pStubMsg->Offset) + { + ERR("conformant strings can't have Offset (%d)\n", pStubMsg->Offset); + RpcRaiseException(RPC_S_INVALID_BOUND); + return NULL; + } + + if (*pFormat == RPC_FC_C_CSTRING) esize = 1; + else if (*pFormat == RPC_FC_C_WSTRING) esize = 2; + else { + ERR("Unhandled string type: %#x\n", *pFormat); + /* FIXME: raise an exception */ + esize = 0; + } + + memsize = safe_multiply(esize, pStubMsg->MaxCount); + bufsize = safe_multiply(esize, pStubMsg->ActualCount); + + /* strings must always have null terminating bytes */ + if (bufsize < esize) + { + ERR("invalid string length of %d\n", pStubMsg->ActualCount); + RpcRaiseException(RPC_S_INVALID_BOUND); + return NULL; + } + + /* verify the buffer is safe to access */ + if ((pStubMsg->Buffer + bufsize < pStubMsg->Buffer) || + (pStubMsg->Buffer + bufsize > pStubMsg->BufferEnd)) + { + ERR("bufsize 0x%x exceeded buffer end %p of buffer %p\n", bufsize, + pStubMsg->BufferEnd, pStubMsg->Buffer); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + return NULL; + } + + for (i = bufsize - esize; i < bufsize; i++) + if (pStubMsg->Buffer[i] != 0) + { + ERR("string not null-terminated at byte position %d, data is 0x%x\n", + i, pStubMsg->Buffer[i]); + RpcRaiseException(RPC_S_INVALID_BOUND); + return NULL; + } + + if (fMustAlloc) + *ppMemory = NdrAllocate(pStubMsg, memsize); + else + { + if (!pStubMsg->IsClient && !*ppMemory && (pStubMsg->MaxCount == pStubMsg->ActualCount)) + /* if the data in the RPC buffer is big enough, we just point straight + * into it */ + *ppMemory = pStubMsg->Buffer; + else if (!*ppMemory) + *ppMemory = NdrAllocate(pStubMsg, memsize); + } + + if (*ppMemory == pStubMsg->Buffer) + safe_buffer_increment(pStubMsg, bufsize); + else + safe_copy_from_buffer(pStubMsg, *ppMemory, bufsize); + + if (*pFormat == RPC_FC_C_CSTRING) { + TRACE("string=%s\n", debugstr_a((char*)*ppMemory)); + } + else if (*pFormat == RPC_FC_C_WSTRING) { + TRACE("string=%s\n", debugstr_w((LPWSTR)*ppMemory)); + } + + return NULL; /* FIXME: is this always right? */ +} + +/*********************************************************************** + * NdrNonConformantStringMarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrNonConformantStringMarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + ULONG esize, size, maxsize; + + TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat); + + maxsize = *(USHORT *)&pFormat[2]; + + if (*pFormat == RPC_FC_CSTRING) + { + ULONG i; + const char *str = (const char *)pMemory; + for (i = 0; i < maxsize && *str; i++, str++) + ; + TRACE("string=%s\n", debugstr_an(str, i)); + pStubMsg->ActualCount = i + 1; + esize = 1; + } + else if (*pFormat == RPC_FC_WSTRING) + { + ULONG i; + const WCHAR *str = (const WCHAR *)pMemory; + for (i = 0; i < maxsize && *str; i++, str++) + ; + TRACE("string=%s\n", debugstr_wn(str, i)); + pStubMsg->ActualCount = i + 1; + esize = 2; + } + else + { + ERR("Unhandled string type: %#x\n", *pFormat); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + + pStubMsg->Offset = 0; + WriteVariance(pStubMsg); + + size = safe_multiply(esize, pStubMsg->ActualCount); + safe_copy_to_buffer(pStubMsg, pMemory, size); /* the string itself */ + + return NULL; +} + +/*********************************************************************** + * NdrNonConformantStringUnmarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrNonConformantStringUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char **ppMemory, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) +{ + ULONG bufsize, memsize, esize, i, maxsize; + + TRACE("(pStubMsg == ^%p, *pMemory == ^%p, pFormat == ^%p, fMustAlloc == %u)\n", + pStubMsg, *ppMemory, pFormat, fMustAlloc); + + maxsize = *(USHORT *)&pFormat[2]; + + ReadVariance(pStubMsg, NULL, maxsize); + if (pStubMsg->Offset) + { + ERR("non-conformant strings can't have Offset (%d)\n", pStubMsg->Offset); + RpcRaiseException(RPC_S_INVALID_BOUND); + } + + if (*pFormat == RPC_FC_CSTRING) esize = 1; + else if (*pFormat == RPC_FC_WSTRING) esize = 2; + else + { + ERR("Unhandled string type: %#x\n", *pFormat); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + + memsize = esize * maxsize; + bufsize = safe_multiply(esize, pStubMsg->ActualCount); + + if (bufsize < esize) + { + ERR("invalid string length of %d\n", pStubMsg->ActualCount); + RpcRaiseException(RPC_S_INVALID_BOUND); + return NULL; + } + + /* verify the buffer is safe to access */ + if ((pStubMsg->Buffer + bufsize < pStubMsg->Buffer) || + (pStubMsg->Buffer + bufsize > pStubMsg->BufferEnd)) + { + ERR("bufsize 0x%x exceeded buffer end %p of buffer %p\n", bufsize, + pStubMsg->BufferEnd, pStubMsg->Buffer); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + return NULL; + } + + /* strings must always have null terminating bytes */ + for (i = bufsize - esize; i < bufsize; i++) + if (pStubMsg->Buffer[i] != 0) + { + ERR("string not null-terminated at byte position %d, data is 0x%x\n", + i, pStubMsg->Buffer[i]); + RpcRaiseException(RPC_S_INVALID_BOUND); + } + + if (fMustAlloc || !*ppMemory) + *ppMemory = NdrAllocate(pStubMsg, memsize); + + safe_copy_from_buffer(pStubMsg, *ppMemory, bufsize); + + if (*pFormat == RPC_FC_CSTRING) { + TRACE("string=%s\n", debugstr_an((char*)*ppMemory, pStubMsg->ActualCount)); + } + else if (*pFormat == RPC_FC_WSTRING) { + TRACE("string=%s\n", debugstr_wn((LPWSTR)*ppMemory, pStubMsg->ActualCount)); + } + + return NULL; +} + +/*********************************************************************** + * NdrNonConformantStringBufferSize [RPCRT4.@] + */ +void WINAPI NdrNonConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + ULONG esize, maxsize; + + TRACE("(pStubMsg == ^%p, pMemory == ^%p, pFormat == ^%p)\n", pStubMsg, pMemory, pFormat); + + maxsize = *(USHORT *)&pFormat[2]; + + SizeVariance(pStubMsg); + + if (*pFormat == RPC_FC_CSTRING) + { + ULONG i; + const char *str = (const char *)pMemory; + for (i = 0; i < maxsize && *str; i++, str++) + ; + TRACE("string=%s\n", debugstr_an(str, i)); + pStubMsg->ActualCount = i + 1; + esize = 1; + } + else if (*pFormat == RPC_FC_WSTRING) + { + ULONG i; + const WCHAR *str = (const WCHAR *)pMemory; + for (i = 0; i < maxsize && *str; i++, str++) + ; + TRACE("string=%s\n", debugstr_wn(str, i)); + pStubMsg->ActualCount = i + 1; + esize = 2; + } + else + { + ERR("Unhandled string type: %#x\n", *pFormat); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + + safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount)); +} + +/*********************************************************************** + * NdrNonConformantStringMemorySize [RPCRT4.@] + */ +ULONG WINAPI NdrNonConformantStringMemorySize(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + ULONG bufsize, memsize, esize, i, maxsize; + + TRACE("(pStubMsg == ^%p, pFormat == ^%p)\n", pStubMsg, pFormat); + + maxsize = *(USHORT *)&pFormat[2]; + + ReadVariance(pStubMsg, NULL, maxsize); + + if (pStubMsg->Offset) + { + ERR("non-conformant strings can't have Offset (%d)\n", pStubMsg->Offset); + RpcRaiseException(RPC_S_INVALID_BOUND); + } + + if (*pFormat == RPC_FC_CSTRING) esize = 1; + else if (*pFormat == RPC_FC_WSTRING) esize = 2; + else + { + ERR("Unhandled string type: %#x\n", *pFormat); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + + memsize = esize * maxsize; + bufsize = safe_multiply(esize, pStubMsg->ActualCount); + + /* strings must always have null terminating bytes */ + if (bufsize < esize) + { + ERR("invalid string length of %d\n", pStubMsg->ActualCount); + RpcRaiseException(RPC_S_INVALID_BOUND); + } + + /* verify the buffer is safe to access */ + if ((pStubMsg->Buffer + bufsize < pStubMsg->Buffer) || + (pStubMsg->Buffer + bufsize > pStubMsg->BufferEnd)) + { + ERR("bufsize 0x%x exceeded buffer end %p of buffer %p\n", bufsize, + pStubMsg->BufferEnd, pStubMsg->Buffer); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + + for (i = bufsize - esize; i < bufsize; i++) + if (pStubMsg->Buffer[i] != 0) + { + ERR("string not null-terminated at byte position %d, data is 0x%x\n", + i, pStubMsg->Buffer[i]); + RpcRaiseException(RPC_S_INVALID_BOUND); + } + + safe_buffer_increment(pStubMsg, bufsize); + pStubMsg->MemorySize += memsize; + + return pStubMsg->MemorySize; +} + +static inline void dump_pointer_attr(unsigned char attr) +{ + if (attr & RPC_FC_P_ALLOCALLNODES) + TRACE(" RPC_FC_P_ALLOCALLNODES"); + if (attr & RPC_FC_P_DONTFREE) + TRACE(" RPC_FC_P_DONTFREE"); + if (attr & RPC_FC_P_ONSTACK) + TRACE(" RPC_FC_P_ONSTACK"); + if (attr & RPC_FC_P_SIMPLEPOINTER) + TRACE(" RPC_FC_P_SIMPLEPOINTER"); + if (attr & RPC_FC_P_DEREF) + TRACE(" RPC_FC_P_DEREF"); + TRACE("\n"); +} + +/*********************************************************************** + * PointerMarshall [internal] + */ +static void PointerMarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *Buffer, + unsigned char *Pointer, + PFORMAT_STRING pFormat) +{ + unsigned type = pFormat[0], attr = pFormat[1]; + PFORMAT_STRING desc; + NDR_MARSHALL m; + ULONG pointer_id; + int pointer_needs_marshaling; + + TRACE("(%p,%p,%p,%p)\n", pStubMsg, Buffer, Pointer, pFormat); + TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr); + pFormat += 2; + if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat; + else desc = pFormat + *(const SHORT*)pFormat; + + switch (type) { + case RPC_FC_RP: /* ref pointer (always non-null) */ + if (!Pointer) + { + ERR("NULL ref pointer is not allowed\n"); + RpcRaiseException(RPC_X_NULL_REF_POINTER); + } + pointer_needs_marshaling = 1; + break; + case RPC_FC_UP: /* unique pointer */ + case RPC_FC_OP: /* object pointer - same as unique here */ + if (Pointer) + pointer_needs_marshaling = 1; + else + pointer_needs_marshaling = 0; + pointer_id = (ULONG)Pointer; + TRACE("writing 0x%08x to buffer\n", pointer_id); + NDR_LOCAL_UINT32_WRITE(Buffer, pointer_id); + break; + case RPC_FC_FP: + pointer_needs_marshaling = !NdrFullPointerQueryPointer( + pStubMsg->FullPtrXlatTables, Pointer, 1, &pointer_id); + TRACE("writing 0x%08x to buffer\n", pointer_id); + NDR_LOCAL_UINT32_WRITE(Buffer, pointer_id); + break; + default: + FIXME("unhandled ptr type=%02x\n", type); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + return; + } + + TRACE("calling marshaller for type 0x%x\n", (int)*desc); + + if (pointer_needs_marshaling) { + if (attr & RPC_FC_P_DEREF) { + Pointer = *(unsigned char**)Pointer; + TRACE("deref => %p\n", Pointer); + } + m = NdrMarshaller[*desc & NDR_TABLE_MASK]; + if (m) m(pStubMsg, Pointer, desc); + else FIXME("no marshaller for data type=%02x\n", *desc); + } + + STD_OVERFLOW_CHECK(pStubMsg); +} + +/*********************************************************************** + * PointerUnmarshall [internal] + */ +static void PointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *Buffer, + unsigned char **pPointer, + unsigned char *pSrcPointer, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) +{ + unsigned type = pFormat[0], attr = pFormat[1]; + PFORMAT_STRING desc; + NDR_UNMARSHALL m; + DWORD pointer_id = 0; + int pointer_needs_unmarshaling; + + TRACE("(%p,%p,%p,%p,%p,%d)\n", pStubMsg, Buffer, pPointer, pSrcPointer, pFormat, fMustAlloc); + TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr); + pFormat += 2; + if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat; + else desc = pFormat + *(const SHORT*)pFormat; + + switch (type) { + case RPC_FC_RP: /* ref pointer (always non-null) */ + pointer_needs_unmarshaling = 1; + break; + case RPC_FC_UP: /* unique pointer */ + pointer_id = NDR_LOCAL_UINT32_READ(Buffer); + TRACE("pointer_id is 0x%08x\n", pointer_id); + if (pointer_id) + pointer_needs_unmarshaling = 1; + else { + *pPointer = NULL; + pointer_needs_unmarshaling = 0; + } + break; + case RPC_FC_OP: /* object pointer - we must free data before overwriting it */ + pointer_id = NDR_LOCAL_UINT32_READ(Buffer); + TRACE("pointer_id is 0x%08x\n", pointer_id); + if (!fMustAlloc && pSrcPointer) + { + FIXME("free object pointer %p\n", pSrcPointer); + fMustAlloc = TRUE; + } + if (pointer_id) + pointer_needs_unmarshaling = 1; + else + pointer_needs_unmarshaling = 0; + break; + case RPC_FC_FP: + pointer_id = NDR_LOCAL_UINT32_READ(Buffer); + TRACE("pointer_id is 0x%08x\n", pointer_id); + pointer_needs_unmarshaling = !NdrFullPointerQueryRefId( + pStubMsg->FullPtrXlatTables, pointer_id, 1, (void **)pPointer); + break; + default: + FIXME("unhandled ptr type=%02x\n", type); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + return; + } + + if (pointer_needs_unmarshaling) { + unsigned char *base_ptr_val = *pPointer; + unsigned char **current_ptr = pPointer; + if (pStubMsg->IsClient) { + TRACE("client\n"); + /* if we aren't forcing allocation of memory then try to use the existing + * (source) pointer to unmarshall the data into so that [in,out] + * parameters behave correctly. it doesn't matter if the parameter is + * [out] only since in that case the pointer will be NULL. we force + * allocation when the source pointer is NULL here instead of in the type + * unmarshalling routine for the benefit of the deref code below */ + if (!fMustAlloc) { + if (pSrcPointer) { + TRACE("setting *pPointer to %p\n", pSrcPointer); + *pPointer = base_ptr_val = pSrcPointer; + } else + fMustAlloc = TRUE; + } + } else { + TRACE("server\n"); + /* the memory in a stub is never initialised, so we have to work out here + * whether we have to initialise it so we can use the optimisation of + * setting the pointer to the buffer, if possible, or set fMustAlloc to + * TRUE. */ + if (attr & RPC_FC_P_DEREF) { + fMustAlloc = TRUE; + } else { + base_ptr_val = NULL; + *current_ptr = NULL; + } + } + + if (attr & RPC_FC_P_ALLOCALLNODES) + FIXME("RPC_FC_P_ALLOCALLNODES not implemented\n"); + + if (attr & RPC_FC_P_DEREF) { + if (fMustAlloc) { + base_ptr_val = NdrAllocate(pStubMsg, sizeof(void *)); + *pPointer = base_ptr_val; + current_ptr = (unsigned char **)base_ptr_val; + } else + current_ptr = *(unsigned char***)current_ptr; + TRACE("deref => %p\n", current_ptr); + if (!fMustAlloc && !*current_ptr) fMustAlloc = TRUE; + } + m = NdrUnmarshaller[*desc & NDR_TABLE_MASK]; + if (m) m(pStubMsg, current_ptr, desc, fMustAlloc); + else FIXME("no unmarshaller for data type=%02x\n", *desc); + + if (type == RPC_FC_FP) + NdrFullPointerInsertRefId(pStubMsg->FullPtrXlatTables, pointer_id, + base_ptr_val); + } + + TRACE("pointer=%p\n", *pPointer); +} + +/*********************************************************************** + * PointerBufferSize [internal] + */ +static void PointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *Pointer, + PFORMAT_STRING pFormat) +{ + unsigned type = pFormat[0], attr = pFormat[1]; + PFORMAT_STRING desc; + NDR_BUFFERSIZE m; + int pointer_needs_sizing; + ULONG pointer_id; + + TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat); + TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr); + pFormat += 2; + if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat; + else desc = pFormat + *(const SHORT*)pFormat; + + switch (type) { + case RPC_FC_RP: /* ref pointer (always non-null) */ + if (!Pointer) + { + ERR("NULL ref pointer is not allowed\n"); + RpcRaiseException(RPC_X_NULL_REF_POINTER); + } + break; + case RPC_FC_OP: + case RPC_FC_UP: + /* NULL pointer has no further representation */ + if (!Pointer) + return; + break; + case RPC_FC_FP: + pointer_needs_sizing = !NdrFullPointerQueryPointer( + pStubMsg->FullPtrXlatTables, Pointer, 0, &pointer_id); + if (!pointer_needs_sizing) + return; + break; + default: + FIXME("unhandled ptr type=%02x\n", type); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + return; + } + + if (attr & RPC_FC_P_DEREF) { + Pointer = *(unsigned char**)Pointer; + TRACE("deref => %p\n", Pointer); + } + + m = NdrBufferSizer[*desc & NDR_TABLE_MASK]; + if (m) m(pStubMsg, Pointer, desc); + else FIXME("no buffersizer for data type=%02x\n", *desc); +} + +/*********************************************************************** + * PointerMemorySize [internal] + */ +static unsigned long PointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *Buffer, + PFORMAT_STRING pFormat) +{ + unsigned type = pFormat[0], attr = pFormat[1]; + PFORMAT_STRING desc; + NDR_MEMORYSIZE m; + DWORD pointer_id = 0; + int pointer_needs_sizing; + + TRACE("(%p,%p,%p)\n", pStubMsg, Buffer, pFormat); + TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr); + pFormat += 2; + if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat; + else desc = pFormat + *(const SHORT*)pFormat; + + switch (type) { + case RPC_FC_RP: /* ref pointer (always non-null) */ + pointer_needs_sizing = 1; + break; + case RPC_FC_UP: /* unique pointer */ + case RPC_FC_OP: /* object pointer - we must free data before overwriting it */ + pointer_id = NDR_LOCAL_UINT32_READ(Buffer); + TRACE("pointer_id is 0x%08x\n", pointer_id); + if (pointer_id) + pointer_needs_sizing = 1; + else + pointer_needs_sizing = 0; + break; + case RPC_FC_FP: + { + void *pointer; + pointer_id = NDR_LOCAL_UINT32_READ(Buffer); + TRACE("pointer_id is 0x%08x\n", pointer_id); + pointer_needs_sizing = !NdrFullPointerQueryRefId( + pStubMsg->FullPtrXlatTables, pointer_id, 1, &pointer); + break; + } + default: + FIXME("unhandled ptr type=%02x\n", type); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + return 0; + } + + if (attr & RPC_FC_P_DEREF) { + TRACE("deref\n"); + } + + if (pointer_needs_sizing) { + m = NdrMemorySizer[*desc & NDR_TABLE_MASK]; + if (m) m(pStubMsg, desc); + else FIXME("no memorysizer for data type=%02x\n", *desc); + } + + return pStubMsg->MemorySize; +} + +/*********************************************************************** + * PointerFree [internal] + */ +static void PointerFree(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *Pointer, + PFORMAT_STRING pFormat) +{ + unsigned type = pFormat[0], attr = pFormat[1]; + PFORMAT_STRING desc; + NDR_FREE m; + unsigned char *current_pointer = Pointer; + + TRACE("(%p,%p,%p)\n", pStubMsg, Pointer, pFormat); + TRACE("type=0x%x, attr=", type); dump_pointer_attr(attr); + if (attr & RPC_FC_P_DONTFREE) return; + pFormat += 2; + if (attr & RPC_FC_P_SIMPLEPOINTER) desc = pFormat; + else desc = pFormat + *(const SHORT*)pFormat; + + if (!Pointer) return; + + if (type == RPC_FC_FP) { + int pointer_needs_freeing = NdrFullPointerFree( + pStubMsg->FullPtrXlatTables, Pointer); + if (!pointer_needs_freeing) + return; + } + + if (attr & RPC_FC_P_DEREF) { + current_pointer = *(unsigned char**)Pointer; + TRACE("deref => %p\n", current_pointer); + } + + m = NdrFreer[*desc & NDR_TABLE_MASK]; + if (m) m(pStubMsg, current_pointer, desc); + + /* this check stops us from trying to free buffer memory. we don't have to + * worry about clients, since they won't call this function. + * we don't have to check for the buffer being reallocated because + * BufferStart and BufferEnd won't be reset when allocating memory for + * sending the response. we don't have to check for the new buffer here as + * it won't be used a type memory, only for buffer memory */ + if (Pointer >= (unsigned char *)pStubMsg->BufferStart && + Pointer < (unsigned char *)pStubMsg->BufferEnd) + goto notfree; + + if (attr & RPC_FC_P_ONSTACK) { + TRACE("not freeing stack ptr %p\n", Pointer); + return; + } + TRACE("freeing %p\n", Pointer); + NdrFree(pStubMsg, Pointer); + return; +notfree: + TRACE("not freeing %p\n", Pointer); +} + +/*********************************************************************** + * EmbeddedPointerMarshall + */ +static unsigned char * EmbeddedPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + unsigned char *Mark = pStubMsg->BufferMark; + unsigned rep, count, stride; + unsigned i; + unsigned char *saved_buffer = NULL; + + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + + if (*pFormat != RPC_FC_PP) return NULL; + pFormat += 2; + + if (pStubMsg->PointerBufferMark) + { + saved_buffer = pStubMsg->Buffer; + pStubMsg->Buffer = pStubMsg->PointerBufferMark; + pStubMsg->PointerBufferMark = NULL; + } + + while (pFormat[0] != RPC_FC_END) { + switch (pFormat[0]) { + default: + FIXME("unknown repeat type %d\n", pFormat[0]); + case RPC_FC_NO_REPEAT: + rep = 1; + stride = 0; + count = 1; + pFormat += 2; + break; + case RPC_FC_FIXED_REPEAT: + rep = *(const WORD*)&pFormat[2]; + stride = *(const WORD*)&pFormat[4]; + count = *(const WORD*)&pFormat[8]; + pFormat += 10; + break; + case RPC_FC_VARIABLE_REPEAT: + rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount; + stride = *(const WORD*)&pFormat[2]; + count = *(const WORD*)&pFormat[6]; + pFormat += 8; + break; + } + for (i = 0; i < rep; i++) { + PFORMAT_STRING info = pFormat; + unsigned char *membase = pMemory + (i * stride); + unsigned char *bufbase = Mark + (i * stride); + unsigned u; + + for (u=0; uMemory; + + pStubMsg->Memory = pMemory; + PointerMarshall(pStubMsg, bufptr, *(unsigned char**)memptr, info+4); + pStubMsg->Memory = saved_memory; + } + } + pFormat += 8 * count; + } + + if (saved_buffer) + { + pStubMsg->PointerBufferMark = pStubMsg->Buffer; + pStubMsg->Buffer = saved_buffer; + } + + STD_OVERFLOW_CHECK(pStubMsg); + + return NULL; +} + +/*********************************************************************** + * EmbeddedPointerUnmarshall + */ +static unsigned char * EmbeddedPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pDstMemoryPtrs, + unsigned char *pSrcMemoryPtrs, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) +{ + unsigned char *Mark = pStubMsg->BufferMark; + unsigned rep, count, stride; + unsigned i; + unsigned char *saved_buffer = NULL; + + TRACE("(%p,%p,%p,%p,%d)\n", pStubMsg, pDstMemoryPtrs, pSrcMemoryPtrs, pFormat, fMustAlloc); + + if (*pFormat != RPC_FC_PP) return NULL; + pFormat += 2; + + if (pStubMsg->PointerBufferMark) + { + saved_buffer = pStubMsg->Buffer; + pStubMsg->Buffer = pStubMsg->PointerBufferMark; + pStubMsg->PointerBufferMark = NULL; + } + + while (pFormat[0] != RPC_FC_END) { + TRACE("pFormat[0] = 0x%x\n", pFormat[0]); + switch (pFormat[0]) { + default: + FIXME("unknown repeat type %d\n", pFormat[0]); + case RPC_FC_NO_REPEAT: + rep = 1; + stride = 0; + count = 1; + pFormat += 2; + break; + case RPC_FC_FIXED_REPEAT: + rep = *(const WORD*)&pFormat[2]; + stride = *(const WORD*)&pFormat[4]; + count = *(const WORD*)&pFormat[8]; + pFormat += 10; + break; + case RPC_FC_VARIABLE_REPEAT: + rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount; + stride = *(const WORD*)&pFormat[2]; + count = *(const WORD*)&pFormat[6]; + pFormat += 8; + break; + } + for (i = 0; i < rep; i++) { + PFORMAT_STRING info = pFormat; + unsigned char *memdstbase = pDstMemoryPtrs + (i * stride); + unsigned char *memsrcbase = pSrcMemoryPtrs + (i * stride); + unsigned char *bufbase = Mark + (i * stride); + unsigned u; + + for (u=0; uPointerBufferMark = pStubMsg->Buffer; + pStubMsg->Buffer = saved_buffer; + } + + return NULL; +} + +/*********************************************************************** + * EmbeddedPointerBufferSize + */ +static void EmbeddedPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + unsigned rep, count, stride; + unsigned i; + ULONG saved_buffer_length = 0; + + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + + if (pStubMsg->IgnoreEmbeddedPointers) return; + + if (*pFormat != RPC_FC_PP) return; + pFormat += 2; + + if (pStubMsg->PointerLength) + { + saved_buffer_length = pStubMsg->BufferLength; + pStubMsg->BufferLength = pStubMsg->PointerLength; + pStubMsg->PointerLength = 0; + } + + while (pFormat[0] != RPC_FC_END) { + switch (pFormat[0]) { + default: + FIXME("unknown repeat type %d\n", pFormat[0]); + case RPC_FC_NO_REPEAT: + rep = 1; + stride = 0; + count = 1; + pFormat += 2; + break; + case RPC_FC_FIXED_REPEAT: + rep = *(const WORD*)&pFormat[2]; + stride = *(const WORD*)&pFormat[4]; + count = *(const WORD*)&pFormat[8]; + pFormat += 10; + break; + case RPC_FC_VARIABLE_REPEAT: + rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount; + stride = *(const WORD*)&pFormat[2]; + count = *(const WORD*)&pFormat[6]; + pFormat += 8; + break; + } + for (i = 0; i < rep; i++) { + PFORMAT_STRING info = pFormat; + unsigned char *membase = pMemory + (i * stride); + unsigned u; + + for (u=0; uMemory; + + pStubMsg->Memory = pMemory; + PointerBufferSize(pStubMsg, *(unsigned char**)memptr, info+4); + pStubMsg->Memory = saved_memory; + } + } + pFormat += 8 * count; + } + + if (saved_buffer_length) + { + pStubMsg->PointerLength = pStubMsg->BufferLength; + pStubMsg->BufferLength = saved_buffer_length; + } +} + +/*********************************************************************** + * EmbeddedPointerMemorySize [internal] + */ +static unsigned long EmbeddedPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + unsigned char *Mark = pStubMsg->BufferMark; + unsigned rep, count, stride; + unsigned i; + unsigned char *saved_buffer = NULL; + + TRACE("(%p,%p)\n", pStubMsg, pFormat); + + if (pStubMsg->IgnoreEmbeddedPointers) return 0; + + if (pStubMsg->PointerBufferMark) + { + saved_buffer = pStubMsg->Buffer; + pStubMsg->Buffer = pStubMsg->PointerBufferMark; + pStubMsg->PointerBufferMark = NULL; + } + + if (*pFormat != RPC_FC_PP) return 0; + pFormat += 2; + + while (pFormat[0] != RPC_FC_END) { + switch (pFormat[0]) { + default: + FIXME("unknown repeat type %d\n", pFormat[0]); + case RPC_FC_NO_REPEAT: + rep = 1; + stride = 0; + count = 1; + pFormat += 2; + break; + case RPC_FC_FIXED_REPEAT: + rep = *(const WORD*)&pFormat[2]; + stride = *(const WORD*)&pFormat[4]; + count = *(const WORD*)&pFormat[8]; + pFormat += 10; + break; + case RPC_FC_VARIABLE_REPEAT: + rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount; + stride = *(const WORD*)&pFormat[2]; + count = *(const WORD*)&pFormat[6]; + pFormat += 8; + break; + } + for (i = 0; i < rep; i++) { + PFORMAT_STRING info = pFormat; + unsigned char *bufbase = Mark + (i * stride); + unsigned u; + for (u=0; uPointerBufferMark = pStubMsg->Buffer; + pStubMsg->Buffer = saved_buffer; + } + + return 0; +} + +/*********************************************************************** + * EmbeddedPointerFree [internal] + */ +static void EmbeddedPointerFree(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + unsigned rep, count, stride; + unsigned i; + + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + if (*pFormat != RPC_FC_PP) return; + pFormat += 2; + + while (pFormat[0] != RPC_FC_END) { + switch (pFormat[0]) { + default: + FIXME("unknown repeat type %d\n", pFormat[0]); + case RPC_FC_NO_REPEAT: + rep = 1; + stride = 0; + count = 1; + pFormat += 2; + break; + case RPC_FC_FIXED_REPEAT: + rep = *(const WORD*)&pFormat[2]; + stride = *(const WORD*)&pFormat[4]; + count = *(const WORD*)&pFormat[8]; + pFormat += 10; + break; + case RPC_FC_VARIABLE_REPEAT: + rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount; + stride = *(const WORD*)&pFormat[2]; + count = *(const WORD*)&pFormat[6]; + pFormat += 8; + break; + } + for (i = 0; i < rep; i++) { + PFORMAT_STRING info = pFormat; + unsigned char *membase = pMemory + (i * stride); + unsigned u; + + for (u=0; uMemory; + + pStubMsg->Memory = pMemory; + PointerFree(pStubMsg, *(unsigned char**)memptr, info+4); + pStubMsg->Memory = saved_memory; + } + } + pFormat += 8 * count; + } +} + +/*********************************************************************** + * NdrPointerMarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + unsigned char *Buffer; + + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + + /* incremement the buffer here instead of in PointerMarshall, + * as that is used by embedded pointers which already handle the incrementing + * the buffer, and shouldn't write any additional pointer data to the wire */ + if (*pFormat != RPC_FC_RP) + { + ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4); + Buffer = pStubMsg->Buffer; + safe_buffer_increment(pStubMsg, 4); + } + else + Buffer = pStubMsg->Buffer; + + PointerMarshall(pStubMsg, Buffer, pMemory, pFormat); + + return NULL; +} + +/*********************************************************************** + * NdrPointerUnmarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char **ppMemory, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) +{ + unsigned char *Buffer; + + TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); + + /* incremement the buffer here instead of in PointerUnmarshall, + * 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 */ + if (*pFormat != RPC_FC_RP) + { + ALIGN_POINTER(pStubMsg->Buffer, 4); + Buffer = pStubMsg->Buffer; + safe_buffer_increment(pStubMsg, 4); + } + else + Buffer = pStubMsg->Buffer; + + PointerUnmarshall(pStubMsg, Buffer, ppMemory, *ppMemory, pFormat, fMustAlloc); + + return NULL; +} + +/*********************************************************************** + * NdrPointerBufferSize [RPCRT4.@] + */ +void WINAPI NdrPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + + /* incremement the buffer length here instead of in PointerBufferSize, + * as that is used by embedded pointers which already handle the buffer + * length, and shouldn't write anything more to the wire */ + if (*pFormat != RPC_FC_RP) + { + ALIGN_LENGTH(pStubMsg->BufferLength, 4); + safe_buffer_length_increment(pStubMsg, 4); + } + + PointerBufferSize(pStubMsg, pMemory, pFormat); +} + +/*********************************************************************** + * NdrPointerMemorySize [RPCRT4.@] + */ +ULONG WINAPI NdrPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + /* unsigned size = *(LPWORD)(pFormat+2); */ + FIXME("(%p,%p): stub\n", pStubMsg, pFormat); + PointerMemorySize(pStubMsg, pStubMsg->Buffer, pFormat); + return 0; +} + +/*********************************************************************** + * NdrPointerFree [RPCRT4.@] + */ +void WINAPI NdrPointerFree(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + PointerFree(pStubMsg, pMemory, pFormat); +} + +/*********************************************************************** + * NdrSimpleTypeMarshall [RPCRT4.@] + */ +void WINAPI NdrSimpleTypeMarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, + unsigned char FormatChar ) +{ + NdrBaseTypeMarshall(pStubMsg, pMemory, &FormatChar); +} + +/*********************************************************************** + * NdrSimpleTypeUnmarshall [RPCRT4.@] + */ +void WINAPI NdrSimpleTypeUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, + unsigned char FormatChar ) +{ + NdrBaseTypeUnmarshall(pStubMsg, &pMemory, &FormatChar, 0); +} + +/*********************************************************************** + * NdrSimpleStructMarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrSimpleStructMarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + unsigned size = *(const WORD*)(pFormat+2); + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + + ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pFormat[1] + 1); + + pStubMsg->BufferMark = pStubMsg->Buffer; + safe_copy_to_buffer(pStubMsg, pMemory, size); + + if (pFormat[0] != RPC_FC_STRUCT) + EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat+4); + + return NULL; +} + +/*********************************************************************** + * NdrSimpleStructUnmarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrSimpleStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char **ppMemory, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) +{ + unsigned size = *(const WORD*)(pFormat+2); + unsigned char *saved_buffer; + TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); + + ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1); + + if (fMustAlloc) + *ppMemory = NdrAllocate(pStubMsg, size); + else + { + if (!pStubMsg->IsClient && !*ppMemory) + /* for servers, we just point straight into the RPC buffer */ + *ppMemory = pStubMsg->Buffer; + } + + saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer; + safe_buffer_increment(pStubMsg, size); + if (pFormat[0] == RPC_FC_PSTRUCT) + EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat+4, fMustAlloc); + + TRACE("copying %p to %p\n", saved_buffer, *ppMemory); + if (*ppMemory != saved_buffer) + memcpy(*ppMemory, saved_buffer, size); + + return NULL; +} + +/*********************************************************************** + * NdrSimpleStructBufferSize [RPCRT4.@] + */ +void WINAPI NdrSimpleStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + unsigned size = *(const WORD*)(pFormat+2); + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + + ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1); + + safe_buffer_length_increment(pStubMsg, size); + if (pFormat[0] != RPC_FC_STRUCT) + EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat+4); +} + +/*********************************************************************** + * NdrSimpleStructMemorySize [RPCRT4.@] + */ +ULONG WINAPI NdrSimpleStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + unsigned short size = *(const WORD *)(pFormat+2); + + TRACE("(%p,%p)\n", pStubMsg, pFormat); + + ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1); + pStubMsg->MemorySize += size; + safe_buffer_increment(pStubMsg, size); + + if (pFormat[0] != RPC_FC_STRUCT) + EmbeddedPointerMemorySize(pStubMsg, pFormat+4); + return pStubMsg->MemorySize; +} + +/*********************************************************************** + * NdrSimpleStructFree [RPCRT4.@] + */ +void WINAPI NdrSimpleStructFree(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + if (pFormat[0] != RPC_FC_STRUCT) + EmbeddedPointerFree(pStubMsg, pMemory, pFormat+4); +} + + +static unsigned long EmbeddedComplexSize(const MIDL_STUB_MESSAGE *pStubMsg, + PFORMAT_STRING pFormat) +{ + switch (*pFormat) { + case RPC_FC_STRUCT: + case RPC_FC_PSTRUCT: + case RPC_FC_CSTRUCT: + case RPC_FC_BOGUS_STRUCT: + case RPC_FC_SMFARRAY: + case RPC_FC_SMVARRAY: + return *(const WORD*)&pFormat[2]; + case RPC_FC_USER_MARSHAL: + return *(const WORD*)&pFormat[4]; + case RPC_FC_NON_ENCAPSULATED_UNION: + pFormat += 2; + if (pStubMsg->fHasNewCorrDesc) + pFormat += 6; + else + pFormat += 4; + + pFormat += *(const SHORT*)pFormat; + return *(const SHORT*)pFormat; + case RPC_FC_IP: + return sizeof(void *); + default: + FIXME("unhandled embedded type %02x\n", *pFormat); + } + return 0; +} + + +static unsigned long EmbeddedComplexMemorySize(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + NDR_MEMORYSIZE m = NdrMemorySizer[*pFormat & NDR_TABLE_MASK]; + + if (!m) + { + FIXME("no memorysizer for data type=%02x\n", *pFormat); + return 0; + } + + return m(pStubMsg, pFormat); +} + + +static unsigned char * ComplexMarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat, + PFORMAT_STRING pPointer) +{ + PFORMAT_STRING desc; + NDR_MARSHALL m; + unsigned long size; + + while (*pFormat != RPC_FC_END) { + switch (*pFormat) { + case RPC_FC_BYTE: + case RPC_FC_CHAR: + case RPC_FC_SMALL: + case RPC_FC_USMALL: + TRACE("byte=%d <= %p\n", *(WORD*)pMemory, pMemory); + safe_copy_to_buffer(pStubMsg, pMemory, 1); + pMemory += 1; + break; + case RPC_FC_WCHAR: + case RPC_FC_SHORT: + case RPC_FC_USHORT: + TRACE("short=%d <= %p\n", *(WORD*)pMemory, pMemory); + safe_copy_to_buffer(pStubMsg, pMemory, 2); + pMemory += 2; + break; + case RPC_FC_LONG: + case RPC_FC_ULONG: + case RPC_FC_ENUM32: + TRACE("long=%d <= %p\n", *(DWORD*)pMemory, pMemory); + safe_copy_to_buffer(pStubMsg, pMemory, 4); + pMemory += 4; + break; + case RPC_FC_HYPER: + TRACE("longlong=%s <= %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory); + safe_copy_to_buffer(pStubMsg, pMemory, 8); + pMemory += 8; + break; + case RPC_FC_POINTER: + { + unsigned char *saved_buffer; + int pointer_buffer_mark_set = 0; + TRACE("pointer=%p <= %p\n", *(unsigned char**)pMemory, pMemory); + ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4); + saved_buffer = pStubMsg->Buffer; + if (pStubMsg->PointerBufferMark) + { + pStubMsg->Buffer = pStubMsg->PointerBufferMark; + pStubMsg->PointerBufferMark = NULL; + pointer_buffer_mark_set = 1; + } + else + safe_buffer_increment(pStubMsg, 4); /* for pointer ID */ + PointerMarshall(pStubMsg, saved_buffer, *(unsigned char**)pMemory, pPointer); + if (pointer_buffer_mark_set) + { + STD_OVERFLOW_CHECK(pStubMsg); + pStubMsg->PointerBufferMark = pStubMsg->Buffer; + if (saved_buffer + 4 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) + { + ERR("buffer overflow - saved_buffer = %p, BufferEnd = %p\n", + saved_buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + pStubMsg->Buffer = saved_buffer + 4; + } + pPointer += 4; + pMemory += 4; + break; + } + case RPC_FC_ALIGNM4: + ALIGN_POINTER(pMemory, 4); + break; + case RPC_FC_ALIGNM8: + ALIGN_POINTER(pMemory, 8); + break; + case RPC_FC_STRUCTPAD1: + case RPC_FC_STRUCTPAD2: + case RPC_FC_STRUCTPAD3: + case RPC_FC_STRUCTPAD4: + case RPC_FC_STRUCTPAD5: + case RPC_FC_STRUCTPAD6: + case RPC_FC_STRUCTPAD7: + pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1; + break; + case RPC_FC_EMBEDDED_COMPLEX: + pMemory += pFormat[1]; + pFormat += 2; + desc = pFormat + *(const SHORT*)pFormat; + size = EmbeddedComplexSize(pStubMsg, desc); + TRACE("embedded complex (size=%ld) <= %p\n", size, pMemory); + m = NdrMarshaller[*desc & NDR_TABLE_MASK]; + if (m) + { + /* for some reason interface pointers aren't generated as + * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet + * they still need the derefencing treatment that pointers are + * given */ + if (*desc == RPC_FC_IP) + m(pStubMsg, *(unsigned char **)pMemory, desc); + else + m(pStubMsg, pMemory, desc); + } + else FIXME("no marshaller for embedded type %02x\n", *desc); + pMemory += size; + pFormat += 2; + continue; + case RPC_FC_PAD: + break; + default: + FIXME("unhandled format 0x%02x\n", *pFormat); + } + pFormat++; + } + + return pMemory; +} + +static unsigned char * ComplexUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat, + PFORMAT_STRING pPointer) +{ + PFORMAT_STRING desc; + NDR_UNMARSHALL m; + unsigned long size; + + while (*pFormat != RPC_FC_END) { + switch (*pFormat) { + case RPC_FC_BYTE: + case RPC_FC_CHAR: + case RPC_FC_SMALL: + case RPC_FC_USMALL: + safe_copy_from_buffer(pStubMsg, pMemory, 1); + TRACE("byte=%d => %p\n", *(WORD*)pMemory, pMemory); + pMemory += 1; + break; + case RPC_FC_WCHAR: + case RPC_FC_SHORT: + case RPC_FC_USHORT: + safe_copy_from_buffer(pStubMsg, pMemory, 2); + TRACE("short=%d => %p\n", *(WORD*)pMemory, pMemory); + pMemory += 2; + break; + case RPC_FC_LONG: + case RPC_FC_ULONG: + case RPC_FC_ENUM32: + safe_copy_from_buffer(pStubMsg, pMemory, 4); + TRACE("long=%d => %p\n", *(DWORD*)pMemory, pMemory); + pMemory += 4; + break; + case RPC_FC_HYPER: + safe_copy_from_buffer(pStubMsg, pMemory, 8); + TRACE("longlong=%s => %p\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory), pMemory); + pMemory += 8; + break; + case RPC_FC_POINTER: + { + unsigned char *saved_buffer; + int pointer_buffer_mark_set = 0; + TRACE("pointer => %p\n", pMemory); + ALIGN_POINTER(pStubMsg->Buffer, 4); + saved_buffer = pStubMsg->Buffer; + if (pStubMsg->PointerBufferMark) + { + pStubMsg->Buffer = pStubMsg->PointerBufferMark; + pStubMsg->PointerBufferMark = NULL; + pointer_buffer_mark_set = 1; + } + else + safe_buffer_increment(pStubMsg, 4); /* for pointer ID */ + + PointerUnmarshall(pStubMsg, saved_buffer, (unsigned char**)pMemory, *(unsigned char**)pMemory, pPointer, TRUE); + if (pointer_buffer_mark_set) + { + STD_OVERFLOW_CHECK(pStubMsg); + pStubMsg->PointerBufferMark = pStubMsg->Buffer; + if (saved_buffer + 4 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) + { + ERR("buffer overflow - saved_buffer = %p, BufferEnd = %p\n", + saved_buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + pStubMsg->Buffer = saved_buffer + 4; + } + pPointer += 4; + pMemory += 4; + break; + } + case RPC_FC_ALIGNM4: + ALIGN_POINTER_CLEAR(pMemory, 4); + break; + case RPC_FC_ALIGNM8: + ALIGN_POINTER_CLEAR(pMemory, 8); + break; + case RPC_FC_STRUCTPAD1: + case RPC_FC_STRUCTPAD2: + case RPC_FC_STRUCTPAD3: + case RPC_FC_STRUCTPAD4: + case RPC_FC_STRUCTPAD5: + case RPC_FC_STRUCTPAD6: + case RPC_FC_STRUCTPAD7: + memset(pMemory, 0, *pFormat - RPC_FC_STRUCTPAD1 + 1); + pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1; + break; + case RPC_FC_EMBEDDED_COMPLEX: + pMemory += pFormat[1]; + pFormat += 2; + desc = pFormat + *(const SHORT*)pFormat; + size = EmbeddedComplexSize(pStubMsg, desc); + TRACE("embedded complex (size=%ld) => %p\n", size, pMemory); + m = NdrUnmarshaller[*desc & NDR_TABLE_MASK]; + memset(pMemory, 0, size); /* just in case */ + if (m) + { + /* for some reason interface pointers aren't generated as + * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet + * they still need the derefencing treatment that pointers are + * given */ + if (*desc == RPC_FC_IP) + m(pStubMsg, (unsigned char **)pMemory, desc, FALSE); + else + m(pStubMsg, &pMemory, desc, FALSE); + } + else FIXME("no unmarshaller for embedded type %02x\n", *desc); + pMemory += size; + pFormat += 2; + continue; + case RPC_FC_PAD: + break; + default: + FIXME("unhandled format %d\n", *pFormat); + } + pFormat++; + } + + return pMemory; +} + +static unsigned char * ComplexBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat, + PFORMAT_STRING pPointer) +{ + PFORMAT_STRING desc; + NDR_BUFFERSIZE m; + unsigned long size; + + while (*pFormat != RPC_FC_END) { + switch (*pFormat) { + case RPC_FC_BYTE: + case RPC_FC_CHAR: + case RPC_FC_SMALL: + case RPC_FC_USMALL: + safe_buffer_length_increment(pStubMsg, 1); + pMemory += 1; + break; + case RPC_FC_WCHAR: + case RPC_FC_SHORT: + case RPC_FC_USHORT: + safe_buffer_length_increment(pStubMsg, 2); + pMemory += 2; + break; + case RPC_FC_LONG: + case RPC_FC_ULONG: + case RPC_FC_ENUM32: + safe_buffer_length_increment(pStubMsg, 4); + pMemory += 4; + break; + case RPC_FC_HYPER: + safe_buffer_length_increment(pStubMsg, 8); + pMemory += 8; + break; + case RPC_FC_POINTER: + if (!pStubMsg->IgnoreEmbeddedPointers) + { + int saved_buffer_length = pStubMsg->BufferLength; + pStubMsg->BufferLength = pStubMsg->PointerLength; + pStubMsg->PointerLength = 0; + if(!pStubMsg->BufferLength) + ERR("BufferLength == 0??\n"); + PointerBufferSize(pStubMsg, *(unsigned char**)pMemory, pPointer); + pStubMsg->PointerLength = pStubMsg->BufferLength; + pStubMsg->BufferLength = saved_buffer_length; + } + safe_buffer_length_increment(pStubMsg, 4); + pPointer += 4; + pMemory += 4; + break; + case RPC_FC_ALIGNM4: + ALIGN_POINTER(pMemory, 4); + break; + case RPC_FC_ALIGNM8: + ALIGN_POINTER(pMemory, 8); + break; + case RPC_FC_STRUCTPAD1: + case RPC_FC_STRUCTPAD2: + case RPC_FC_STRUCTPAD3: + case RPC_FC_STRUCTPAD4: + case RPC_FC_STRUCTPAD5: + case RPC_FC_STRUCTPAD6: + case RPC_FC_STRUCTPAD7: + pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1; + break; + case RPC_FC_EMBEDDED_COMPLEX: + pMemory += pFormat[1]; + pFormat += 2; + desc = pFormat + *(const SHORT*)pFormat; + size = EmbeddedComplexSize(pStubMsg, desc); + m = NdrBufferSizer[*desc & NDR_TABLE_MASK]; + if (m) + { + /* for some reason interface pointers aren't generated as + * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet + * they still need the derefencing treatment that pointers are + * given */ + if (*desc == RPC_FC_IP) + m(pStubMsg, *(unsigned char **)pMemory, desc); + else + m(pStubMsg, pMemory, desc); + } + else FIXME("no buffersizer for embedded type %02x\n", *desc); + pMemory += size; + pFormat += 2; + continue; + case RPC_FC_PAD: + break; + default: + FIXME("unhandled format 0x%02x\n", *pFormat); + } + pFormat++; + } + + return pMemory; +} + +static unsigned char * ComplexFree(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat, + PFORMAT_STRING pPointer) +{ + PFORMAT_STRING desc; + NDR_FREE m; + unsigned long size; + + while (*pFormat != RPC_FC_END) { + switch (*pFormat) { + case RPC_FC_BYTE: + case RPC_FC_CHAR: + case RPC_FC_SMALL: + case RPC_FC_USMALL: + pMemory += 1; + break; + case RPC_FC_WCHAR: + case RPC_FC_SHORT: + case RPC_FC_USHORT: + pMemory += 2; + break; + case RPC_FC_LONG: + case RPC_FC_ULONG: + case RPC_FC_ENUM32: + pMemory += 4; + break; + case RPC_FC_HYPER: + pMemory += 8; + break; + case RPC_FC_POINTER: + NdrPointerFree(pStubMsg, *(unsigned char**)pMemory, pPointer); + pPointer += 4; + pMemory += 4; + break; + case RPC_FC_ALIGNM4: + ALIGN_POINTER(pMemory, 4); + break; + case RPC_FC_ALIGNM8: + ALIGN_POINTER(pMemory, 8); + break; + case RPC_FC_STRUCTPAD1: + case RPC_FC_STRUCTPAD2: + case RPC_FC_STRUCTPAD3: + case RPC_FC_STRUCTPAD4: + case RPC_FC_STRUCTPAD5: + case RPC_FC_STRUCTPAD6: + case RPC_FC_STRUCTPAD7: + pMemory += *pFormat - RPC_FC_STRUCTPAD1 + 1; + break; + case RPC_FC_EMBEDDED_COMPLEX: + pMemory += pFormat[1]; + pFormat += 2; + desc = pFormat + *(const SHORT*)pFormat; + size = EmbeddedComplexSize(pStubMsg, desc); + m = NdrFreer[*desc & NDR_TABLE_MASK]; + if (m) + { + /* for some reason interface pointers aren't generated as + * RPC_FC_POINTER, but instead as RPC_FC_EMBEDDED_COMPLEX, yet + * they still need the derefencing treatment that pointers are + * given */ + if (*desc == RPC_FC_IP) + m(pStubMsg, *(unsigned char **)pMemory, desc); + else + m(pStubMsg, pMemory, desc); + } + else FIXME("no freer for embedded type %02x\n", *desc); + pMemory += size; + pFormat += 2; + continue; + case RPC_FC_PAD: + break; + default: + FIXME("unhandled format 0x%02x\n", *pFormat); + } + pFormat++; + } + + return pMemory; +} + +static unsigned long ComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + PFORMAT_STRING desc; + unsigned long size = 0; + + while (*pFormat != RPC_FC_END) { + switch (*pFormat) { + case RPC_FC_BYTE: + case RPC_FC_CHAR: + case RPC_FC_SMALL: + case RPC_FC_USMALL: + size += 1; + safe_buffer_increment(pStubMsg, 1); + break; + case RPC_FC_WCHAR: + case RPC_FC_SHORT: + case RPC_FC_USHORT: + size += 2; + safe_buffer_increment(pStubMsg, 2); + break; + case RPC_FC_LONG: + case RPC_FC_ULONG: + case RPC_FC_ENUM32: + size += 4; + safe_buffer_increment(pStubMsg, 4); + break; + case RPC_FC_HYPER: + size += 8; + safe_buffer_increment(pStubMsg, 8); + break; + case RPC_FC_POINTER: + size += 4; + safe_buffer_increment(pStubMsg, 4); + if (!pStubMsg->IgnoreEmbeddedPointers) + FIXME("embedded pointers\n"); + break; + case RPC_FC_ALIGNM4: + ALIGN_LENGTH(size, 4); + ALIGN_POINTER(pStubMsg->Buffer, 4); + break; + case RPC_FC_ALIGNM8: + ALIGN_LENGTH(size, 8); + ALIGN_POINTER(pStubMsg->Buffer, 8); + break; + case RPC_FC_STRUCTPAD1: + case RPC_FC_STRUCTPAD2: + case RPC_FC_STRUCTPAD3: + case RPC_FC_STRUCTPAD4: + case RPC_FC_STRUCTPAD5: + case RPC_FC_STRUCTPAD6: + case RPC_FC_STRUCTPAD7: + size += *pFormat - RPC_FC_STRUCTPAD1 + 1; + break; + case RPC_FC_EMBEDDED_COMPLEX: + size += pFormat[1]; + pFormat += 2; + desc = pFormat + *(const SHORT*)pFormat; + size += EmbeddedComplexMemorySize(pStubMsg, desc); + pFormat += 2; + continue; + case RPC_FC_PAD: + break; + default: + FIXME("unhandled format 0x%02x\n", *pFormat); + } + pFormat++; + } + + return size; +} + +/*********************************************************************** + * NdrComplexStructMarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrComplexStructMarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + PFORMAT_STRING conf_array = NULL; + PFORMAT_STRING pointer_desc = NULL; + unsigned char *OldMemory = pStubMsg->Memory; + int pointer_buffer_mark_set = 0; + + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + + if (!pStubMsg->PointerBufferMark) + { + int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers; + /* save buffer length */ + unsigned long saved_buffer_length = pStubMsg->BufferLength; + + /* get the buffer pointer after complex array data, but before + * pointer data */ + pStubMsg->BufferLength = pStubMsg->Buffer - pStubMsg->BufferStart; + pStubMsg->IgnoreEmbeddedPointers = 1; + NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat); + pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded; + + /* save it for use by embedded pointer code later */ + pStubMsg->PointerBufferMark = pStubMsg->BufferStart + pStubMsg->BufferLength; + TRACE("difference = 0x%x\n", pStubMsg->PointerBufferMark - pStubMsg->Buffer); + pointer_buffer_mark_set = 1; + + /* restore the original buffer length */ + pStubMsg->BufferLength = saved_buffer_length; + } + + ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pFormat[1] + 1); + + pFormat += 4; + if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat; + pFormat += 2; + if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat; + pFormat += 2; + + pStubMsg->Memory = pMemory; + + ComplexMarshall(pStubMsg, pMemory, pFormat, pointer_desc); + + if (conf_array) + NdrConformantArrayMarshall(pStubMsg, pMemory, conf_array); + + pStubMsg->Memory = OldMemory; + + if (pointer_buffer_mark_set) + { + pStubMsg->Buffer = pStubMsg->PointerBufferMark; + pStubMsg->PointerBufferMark = NULL; + } + + STD_OVERFLOW_CHECK(pStubMsg); + + return NULL; +} + +/*********************************************************************** + * NdrComplexStructUnmarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrComplexStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char **ppMemory, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) +{ + unsigned size = *(const WORD*)(pFormat+2); + PFORMAT_STRING conf_array = NULL; + PFORMAT_STRING pointer_desc = NULL; + unsigned char *pMemory; + int pointer_buffer_mark_set = 0; + + TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); + + if (!pStubMsg->PointerBufferMark) + { + int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers; + /* save buffer pointer */ + unsigned char *saved_buffer = pStubMsg->Buffer; + + /* get the buffer pointer after complex array data, but before + * pointer data */ + pStubMsg->IgnoreEmbeddedPointers = 1; + NdrComplexStructMemorySize(pStubMsg, pFormat); + pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded; + + /* save it for use by embedded pointer code later */ + pStubMsg->PointerBufferMark = pStubMsg->Buffer; + TRACE("difference = 0x%lx\n", (unsigned long)(pStubMsg->PointerBufferMark - saved_buffer)); + pointer_buffer_mark_set = 1; + + /* restore the original buffer */ + pStubMsg->Buffer = saved_buffer; + } + + ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1); + + if (fMustAlloc || !*ppMemory) + { + *ppMemory = NdrAllocate(pStubMsg, size); + memset(*ppMemory, 0, size); + } + + pFormat += 4; + if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat; + pFormat += 2; + if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat; + pFormat += 2; + + pMemory = ComplexUnmarshall(pStubMsg, *ppMemory, pFormat, pointer_desc); + + if (conf_array) + NdrConformantArrayUnmarshall(pStubMsg, &pMemory, conf_array, fMustAlloc); + + if (pointer_buffer_mark_set) + { + pStubMsg->Buffer = pStubMsg->PointerBufferMark; + pStubMsg->PointerBufferMark = NULL; + } + + return NULL; +} + +/*********************************************************************** + * NdrComplexStructBufferSize [RPCRT4.@] + */ +void WINAPI NdrComplexStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + PFORMAT_STRING conf_array = NULL; + PFORMAT_STRING pointer_desc = NULL; + unsigned char *OldMemory = pStubMsg->Memory; + int pointer_length_set = 0; + + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + + ALIGN_LENGTH(pStubMsg->BufferLength, pFormat[1] + 1); + + if(!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength) + { + int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers; + unsigned long saved_buffer_length = pStubMsg->BufferLength; + + /* get the buffer length after complex struct data, but before + * pointer data */ + pStubMsg->IgnoreEmbeddedPointers = 1; + NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat); + pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded; + + /* save it for use by embedded pointer code later */ + pStubMsg->PointerLength = pStubMsg->BufferLength; + pointer_length_set = 1; + TRACE("difference = 0x%lx\n", pStubMsg->PointerLength - saved_buffer_length); + + /* restore the original buffer length */ + pStubMsg->BufferLength = saved_buffer_length; + } + + pFormat += 4; + if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat; + pFormat += 2; + if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat; + pFormat += 2; + + pStubMsg->Memory = pMemory; + + pMemory = ComplexBufferSize(pStubMsg, pMemory, pFormat, pointer_desc); + + if (conf_array) + NdrConformantArrayBufferSize(pStubMsg, pMemory, conf_array); + + pStubMsg->Memory = OldMemory; + + if(pointer_length_set) + { + pStubMsg->BufferLength = pStubMsg->PointerLength; + pStubMsg->PointerLength = 0; + } + +} + +/*********************************************************************** + * NdrComplexStructMemorySize [RPCRT4.@] + */ +ULONG WINAPI NdrComplexStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + unsigned size = *(const WORD*)(pFormat+2); + PFORMAT_STRING conf_array = NULL; + PFORMAT_STRING pointer_desc = NULL; + + TRACE("(%p,%p)\n", pStubMsg, pFormat); + + ALIGN_POINTER(pStubMsg->Buffer, pFormat[1] + 1); + + pFormat += 4; + if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat; + pFormat += 2; + if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat; + pFormat += 2; + + ComplexStructMemorySize(pStubMsg, pFormat); + + if (conf_array) + NdrConformantArrayMemorySize(pStubMsg, conf_array); + + return size; +} + +/*********************************************************************** + * NdrComplexStructFree [RPCRT4.@] + */ +void WINAPI NdrComplexStructFree(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + PFORMAT_STRING conf_array = NULL; + PFORMAT_STRING pointer_desc = NULL; + unsigned char *OldMemory = pStubMsg->Memory; + + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + + pFormat += 4; + if (*(const WORD*)pFormat) conf_array = pFormat + *(const WORD*)pFormat; + pFormat += 2; + if (*(const WORD*)pFormat) pointer_desc = pFormat + *(const WORD*)pFormat; + pFormat += 2; + + pStubMsg->Memory = pMemory; + + pMemory = ComplexFree(pStubMsg, pMemory, pFormat, pointer_desc); + + if (conf_array) + NdrConformantArrayFree(pStubMsg, pMemory, conf_array); + + pStubMsg->Memory = OldMemory; +} + +/*********************************************************************** + * NdrConformantArrayMarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrConformantArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + DWORD size = 0, esize = *(const WORD*)(pFormat+2); + unsigned char alignment = pFormat[1] + 1; + + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]); + + pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0); + + WriteConformance(pStubMsg); + + ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment); + + size = safe_multiply(esize, pStubMsg->MaxCount); + pStubMsg->BufferMark = pStubMsg->Buffer; + safe_copy_to_buffer(pStubMsg, pMemory, size); + + EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat); + + return NULL; +} + +/*********************************************************************** + * NdrConformantArrayUnmarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrConformantArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char **ppMemory, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) +{ + DWORD size, esize = *(const WORD*)(pFormat+2); + unsigned char alignment = pFormat[1] + 1; + unsigned char *saved_buffer; + + TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); + if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]); + + pFormat = ReadConformance(pStubMsg, pFormat+4); + + size = safe_multiply(esize, pStubMsg->MaxCount); + ALIGN_POINTER(pStubMsg->Buffer, alignment); + + if (fMustAlloc) + *ppMemory = NdrAllocate(pStubMsg, size); + else + { + if (!pStubMsg->IsClient && !*ppMemory) + /* for servers, we just point straight into the RPC buffer */ + *ppMemory = pStubMsg->Buffer; + } + + saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer; + safe_buffer_increment(pStubMsg, size); + EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc); + + TRACE("copying %p to %p\n", saved_buffer, *ppMemory); + if (*ppMemory != saved_buffer) + memcpy(*ppMemory, saved_buffer, size); + + return NULL; +} + +/*********************************************************************** + * NdrConformantArrayBufferSize [RPCRT4.@] + */ +void WINAPI NdrConformantArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + DWORD size, esize = *(const WORD*)(pFormat+2); + unsigned char alignment = pFormat[1] + 1; + + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]); + + pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0); + + SizeConformance(pStubMsg); + + ALIGN_LENGTH(pStubMsg->BufferLength, alignment); + + size = safe_multiply(esize, pStubMsg->MaxCount); + /* conformance value plus array */ + safe_buffer_length_increment(pStubMsg, size); + + EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat); +} + +/*********************************************************************** + * NdrConformantArrayMemorySize [RPCRT4.@] + */ +ULONG WINAPI NdrConformantArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + DWORD size = 0, esize = *(const WORD*)(pFormat+2); + unsigned char alignment = pFormat[1] + 1; + + TRACE("(%p,%p)\n", pStubMsg, pFormat); + if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]); + + pFormat = ReadConformance(pStubMsg, pFormat+4); + size = safe_multiply(esize, pStubMsg->MaxCount); + pStubMsg->MemorySize += size; + + ALIGN_POINTER(pStubMsg->Buffer, alignment); + pStubMsg->BufferMark = pStubMsg->Buffer; + safe_buffer_increment(pStubMsg, size); + + EmbeddedPointerMemorySize(pStubMsg, pFormat); + + return pStubMsg->MemorySize; +} + +/*********************************************************************** + * NdrConformantArrayFree [RPCRT4.@] + */ +void WINAPI NdrConformantArrayFree(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + if (pFormat[0] != RPC_FC_CARRAY) FIXME("format=%d\n", pFormat[0]); + + pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0); + + EmbeddedPointerFree(pStubMsg, pMemory, pFormat); +} + + +/*********************************************************************** + * NdrConformantVaryingArrayMarshall [RPCRT4.@] + */ +unsigned char* WINAPI NdrConformantVaryingArrayMarshall( PMIDL_STUB_MESSAGE pStubMsg, + unsigned char* pMemory, + PFORMAT_STRING pFormat ) +{ + ULONG bufsize; + unsigned char alignment = pFormat[1] + 1; + DWORD esize = *(const WORD*)(pFormat+2); + + TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); + + if (pFormat[0] != RPC_FC_CVARRAY) + { + ERR("invalid format type %x\n", pFormat[0]); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return NULL; + } + + pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0); + pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0); + + WriteConformance(pStubMsg); + WriteVariance(pStubMsg); + + ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment); + + bufsize = safe_multiply(esize, pStubMsg->ActualCount); + + pStubMsg->BufferMark = pStubMsg->Buffer; + safe_copy_to_buffer(pStubMsg, pMemory + pStubMsg->Offset, bufsize); + + EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat); + + return NULL; +} + + +/*********************************************************************** + * NdrConformantVaryingArrayUnmarshall [RPCRT4.@] + */ +unsigned char* WINAPI NdrConformantVaryingArrayUnmarshall( PMIDL_STUB_MESSAGE pStubMsg, + unsigned char** ppMemory, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc ) +{ + ULONG bufsize, memsize; + unsigned char alignment = pFormat[1] + 1; + DWORD esize = *(const WORD*)(pFormat+2); + unsigned char *saved_buffer; + ULONG offset; + + TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); + + if (pFormat[0] != RPC_FC_CVARRAY) + { + ERR("invalid format type %x\n", pFormat[0]); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return NULL; + } + + pFormat = ReadConformance(pStubMsg, pFormat+4); + pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount); + + ALIGN_POINTER(pStubMsg->Buffer, alignment); + + bufsize = safe_multiply(esize, pStubMsg->ActualCount); + memsize = safe_multiply(esize, pStubMsg->MaxCount); + offset = pStubMsg->Offset; + + if (!*ppMemory || fMustAlloc) + *ppMemory = NdrAllocate(pStubMsg, memsize); + saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer; + safe_buffer_increment(pStubMsg, bufsize); + + EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc); + + memcpy(*ppMemory + offset, saved_buffer, bufsize); + + return NULL; +} + + +/*********************************************************************** + * NdrConformantVaryingArrayFree [RPCRT4.@] + */ +void WINAPI NdrConformantVaryingArrayFree( PMIDL_STUB_MESSAGE pStubMsg, + unsigned char* pMemory, + PFORMAT_STRING pFormat ) +{ + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + + if (pFormat[0] != RPC_FC_CVARRAY) + { + ERR("invalid format type %x\n", pFormat[0]); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return; + } + + pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0); + pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0); + + EmbeddedPointerFree(pStubMsg, pMemory, pFormat); +} + + +/*********************************************************************** + * NdrConformantVaryingArrayBufferSize [RPCRT4.@] + */ +void WINAPI NdrConformantVaryingArrayBufferSize( PMIDL_STUB_MESSAGE pStubMsg, + unsigned char* pMemory, PFORMAT_STRING pFormat ) +{ + unsigned char alignment = pFormat[1] + 1; + DWORD esize = *(const WORD*)(pFormat+2); + + TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); + + if (pFormat[0] != RPC_FC_CVARRAY) + { + ERR("invalid format type %x\n", pFormat[0]); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return; + } + + /* compute size */ + pFormat = ComputeConformance(pStubMsg, pMemory, pFormat+4, 0); + /* compute length */ + pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0); + + SizeConformance(pStubMsg); + SizeVariance(pStubMsg); + + ALIGN_LENGTH(pStubMsg->BufferLength, alignment); + + safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount)); + + EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat); +} + + +/*********************************************************************** + * NdrConformantVaryingArrayMemorySize [RPCRT4.@] + */ +ULONG WINAPI NdrConformantVaryingArrayMemorySize( PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat ) +{ + ULONG bufsize, memsize; + unsigned char alignment = pFormat[1] + 1; + DWORD esize = *(const WORD*)(pFormat+2); + + TRACE("(%p, %p)\n", pStubMsg, pFormat); + + if (pFormat[0] != RPC_FC_CVARRAY) + { + ERR("invalid format type %x\n", pFormat[0]); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return pStubMsg->MemorySize; + } + + pFormat = ReadConformance(pStubMsg, pFormat+4); + pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount); + + ALIGN_POINTER(pStubMsg->Buffer, alignment); + + bufsize = safe_multiply(esize, pStubMsg->ActualCount); + memsize = safe_multiply(esize, pStubMsg->MaxCount); + + safe_buffer_increment(pStubMsg, bufsize); + pStubMsg->MemorySize += memsize; + + EmbeddedPointerMemorySize(pStubMsg, pFormat); + + return pStubMsg->MemorySize; +} + + +/*********************************************************************** + * NdrComplexArrayMarshall [RPCRT4.@] + */ +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); + + if (pFormat[0] != RPC_FC_BOGUS_ARRAY) + { + ERR("invalid format type %x\n", pFormat[0]); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return NULL; + } + + alignment = pFormat[1] + 1; + + if (!pStubMsg->PointerBufferMark) + { + /* save buffer fields that may be changed by buffer sizer functions + * and that may be needed later on */ + int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers; + unsigned long saved_buffer_length = pStubMsg->BufferLength; + unsigned long saved_max_count = pStubMsg->MaxCount; + unsigned long saved_offset = pStubMsg->Offset; + unsigned long saved_actual_count = pStubMsg->ActualCount; + + /* get the buffer pointer after complex array data, but before + * pointer data */ + pStubMsg->BufferLength = pStubMsg->Buffer - pStubMsg->BufferStart; + pStubMsg->IgnoreEmbeddedPointers = 1; + NdrComplexArrayBufferSize(pStubMsg, pMemory, pFormat); + pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded; + + /* save it for use by embedded pointer code later */ + pStubMsg->PointerBufferMark = pStubMsg->BufferStart + pStubMsg->BufferLength; + TRACE("difference = 0x%x\n", pStubMsg->Buffer - pStubMsg->BufferStart); + pointer_buffer_mark_set = 1; + + /* restore fields */ + pStubMsg->ActualCount = saved_actual_count; + pStubMsg->Offset = saved_offset; + 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); + + 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); + + STD_OVERFLOW_CHECK(pStubMsg); + + if (pointer_buffer_mark_set) + { + pStubMsg->Buffer = pStubMsg->PointerBufferMark; + pStubMsg->PointerBufferMark = NULL; + } + + return NULL; +} + +/*********************************************************************** + * NdrComplexArrayUnmarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrComplexArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char **ppMemory, + 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; + + TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); + + if (pFormat[0] != RPC_FC_BOGUS_ARRAY) + { + ERR("invalid format type %x\n", pFormat[0]); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return NULL; + } + + alignment = pFormat[1] + 1; + + saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers; + /* save buffer pointer */ + saved_buffer = pStubMsg->Buffer; + /* get the buffer pointer after complex array data, but before + * pointer data */ + pStubMsg->IgnoreEmbeddedPointers = 1; + pStubMsg->MemorySize = 0; + NdrComplexArrayMemorySize(pStubMsg, pFormat); + size = pStubMsg->MemorySize; + pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded; + + TRACE("difference = 0x%lx\n", (unsigned long)(pStubMsg->Buffer - saved_buffer)); + if (!pStubMsg->PointerBufferMark) + { + /* save it for use by embedded pointer code later */ + pStubMsg->PointerBufferMark = pStubMsg->Buffer; + pointer_buffer_mark_set = 1; + } + /* restore the original buffer */ + pStubMsg->Buffer = saved_buffer; + + pFormat += 4; + + pFormat = ReadConformance(pStubMsg, pFormat); + pFormat = ReadVariance(pStubMsg, pFormat, pStubMsg->MaxCount); + + if (fMustAlloc || !*ppMemory) + { + *ppMemory = NdrAllocate(pStubMsg, size); + memset(*ppMemory, 0, size); + } + + ALIGN_POINTER(pStubMsg->Buffer, alignment); + + pMemory = *ppMemory; + count = pStubMsg->ActualCount; + for (i = 0; i < count; i++) + pMemory = ComplexUnmarshall(pStubMsg, pMemory, pFormat, NULL); + + if (pointer_buffer_mark_set) + { + pStubMsg->Buffer = pStubMsg->PointerBufferMark; + pStubMsg->PointerBufferMark = NULL; + } + + return NULL; +} + +/*********************************************************************** + * NdrComplexArrayBufferSize [RPCRT4.@] + */ +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); + + if (pFormat[0] != RPC_FC_BOGUS_ARRAY) + { + ERR("invalid format type %x\n", pFormat[0]); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return; + } + + alignment = pFormat[1] + 1; + + if (!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength) + { + /* save buffer fields that may be changed by buffer sizer functions + * and that may be needed later on */ + int saved_ignore_embedded = pStubMsg->IgnoreEmbeddedPointers; + unsigned long saved_buffer_length = pStubMsg->BufferLength; + unsigned long saved_max_count = pStubMsg->MaxCount; + unsigned long saved_offset = pStubMsg->Offset; + unsigned long saved_actual_count = pStubMsg->ActualCount; + + /* get the buffer pointer after complex array data, but before + * pointer data */ + pStubMsg->IgnoreEmbeddedPointers = 1; + NdrComplexArrayBufferSize(pStubMsg, pMemory, pFormat); + pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded; + + /* save it for use by embedded pointer code later */ + pStubMsg->PointerLength = pStubMsg->BufferLength; + pointer_length_set = 1; + + /* restore fields */ + pStubMsg->ActualCount = saved_actual_count; + pStubMsg->Offset = saved_offset; + 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); + + if(pointer_length_set) + { + pStubMsg->BufferLength = pStubMsg->PointerLength; + pStubMsg->PointerLength = 0; + } +} + +/*********************************************************************** + * NdrComplexArrayMemorySize [RPCRT4.@] + */ +ULONG WINAPI NdrComplexArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + ULONG i, count, esize, SavedMemorySize, MemorySize; + unsigned char alignment; + unsigned char *Buffer; + + TRACE("(%p,%p)\n", pStubMsg, pFormat); + + if (pFormat[0] != RPC_FC_BOGUS_ARRAY) + { + ERR("invalid format type %x\n", pFormat[0]); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + 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; + + Buffer = pStubMsg->Buffer; + pStubMsg->MemorySize = 0; + esize = ComplexStructMemorySize(pStubMsg, pFormat); + pStubMsg->Buffer = Buffer; + + MemorySize = safe_multiply(pStubMsg->MaxCount, esize); + + count = pStubMsg->ActualCount; + for (i = 0; i < count; i++) + ComplexStructMemorySize(pStubMsg, pFormat); + + pStubMsg->MemorySize = SavedMemorySize; + + pStubMsg->MemorySize += MemorySize; + return MemorySize; +} + +/*********************************************************************** + * NdrComplexArrayFree [RPCRT4.@] + */ +void WINAPI NdrComplexArrayFree(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + ULONG i, count, def; + + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + + if (pFormat[0] != RPC_FC_BOGUS_ARRAY) + { + ERR("invalid format type %x\n", pFormat[0]); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return; + } + + def = *(const WORD*)&pFormat[2]; + pFormat += 4; + + pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, def); + TRACE("conformance = %ld\n", pStubMsg->MaxCount); + + pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, pStubMsg->MaxCount); + TRACE("variance = %d\n", pStubMsg->ActualCount); + + count = pStubMsg->ActualCount; + for (i = 0; i < count; i++) + pMemory = ComplexFree(pStubMsg, pMemory, pFormat, NULL); +} + +static void UserMarshalCB(PMIDL_STUB_MESSAGE pStubMsg, + USER_MARSHAL_CB_TYPE cbtype, PFORMAT_STRING pFormat, + USER_MARSHAL_CB *umcb) +{ + umcb->Flags = MAKELONG(pStubMsg->dwDestContext, + pStubMsg->RpcMsg->DataRepresentation); + umcb->pStubMsg = pStubMsg; + umcb->pReserve = NULL; + umcb->Signature = USER_MARSHAL_CB_SIGNATURE; + umcb->CBType = cbtype; + umcb->pFormat = pFormat; + umcb->pTypeFormat = NULL /* FIXME */; +} + +#define USER_MARSHAL_PTR_PREFIX \ + ( (DWORD)'U' | ( (DWORD)'s' << 8 ) | \ + ( (DWORD)'e' << 16 ) | ( (DWORD)'r' << 24 ) ) + +/*********************************************************************** + * NdrUserMarshalMarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrUserMarshalMarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + unsigned flags = pFormat[1]; + unsigned index = *(const WORD*)&pFormat[2]; + unsigned char *saved_buffer = NULL; + USER_MARSHAL_CB umcb; + + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + TRACE("index=%d\n", index); + + UserMarshalCB(pStubMsg, USER_MARSHAL_CB_MARSHALL, pFormat, &umcb); + + if (flags & USER_MARSHAL_POINTER) + { + ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4); + NDR_LOCAL_UINT32_WRITE(pStubMsg->Buffer, USER_MARSHAL_PTR_PREFIX); + pStubMsg->Buffer += 4; + if (pStubMsg->PointerBufferMark) + { + saved_buffer = pStubMsg->Buffer; + pStubMsg->Buffer = pStubMsg->PointerBufferMark; + pStubMsg->PointerBufferMark = NULL; + } + ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 8); + } + else + ALIGN_POINTER_CLEAR(pStubMsg->Buffer, (flags & 0xf) + 1); + + pStubMsg->Buffer = + pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnMarshall( + &umcb.Flags, pStubMsg->Buffer, pMemory); + + if (saved_buffer) + { + STD_OVERFLOW_CHECK(pStubMsg); + pStubMsg->PointerBufferMark = pStubMsg->Buffer; + pStubMsg->Buffer = saved_buffer; + } + + STD_OVERFLOW_CHECK(pStubMsg); + + return NULL; +} + +/*********************************************************************** + * NdrUserMarshalUnmarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrUserMarshalUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char **ppMemory, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) +{ + unsigned flags = pFormat[1]; + unsigned index = *(const WORD*)&pFormat[2]; + DWORD memsize = *(const WORD*)&pFormat[4]; + unsigned char *saved_buffer = NULL; + USER_MARSHAL_CB umcb; + + TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); + TRACE("index=%d\n", index); + + UserMarshalCB(pStubMsg, USER_MARSHAL_CB_UNMARSHALL, pFormat, &umcb); + + if (flags & USER_MARSHAL_POINTER) + { + ALIGN_POINTER(pStubMsg->Buffer, 4); + /* skip pointer prefix */ + pStubMsg->Buffer += 4; + if (pStubMsg->PointerBufferMark) + { + saved_buffer = pStubMsg->Buffer; + pStubMsg->Buffer = pStubMsg->PointerBufferMark; + pStubMsg->PointerBufferMark = NULL; + } + ALIGN_POINTER(pStubMsg->Buffer, 8); + } + else + ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1); + + if (fMustAlloc || !*ppMemory) + *ppMemory = NdrAllocate(pStubMsg, memsize); + + pStubMsg->Buffer = + pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnUnmarshall( + &umcb.Flags, pStubMsg->Buffer, *ppMemory); + + if (saved_buffer) + { + STD_OVERFLOW_CHECK(pStubMsg); + pStubMsg->PointerBufferMark = pStubMsg->Buffer; + pStubMsg->Buffer = saved_buffer; + } + + return NULL; +} + +/*********************************************************************** + * NdrUserMarshalBufferSize [RPCRT4.@] + */ +void WINAPI NdrUserMarshalBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + unsigned flags = pFormat[1]; + unsigned index = *(const WORD*)&pFormat[2]; + DWORD bufsize = *(const WORD*)&pFormat[6]; + USER_MARSHAL_CB umcb; + unsigned long saved_buffer_length = 0; + + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + TRACE("index=%d\n", index); + + UserMarshalCB(pStubMsg, USER_MARSHAL_CB_BUFFER_SIZE, pFormat, &umcb); + + if (flags & USER_MARSHAL_POINTER) + { + ALIGN_LENGTH(pStubMsg->BufferLength, 4); + /* skip pointer prefix */ + safe_buffer_length_increment(pStubMsg, 4); + if (pStubMsg->IgnoreEmbeddedPointers) + return; + if (pStubMsg->PointerLength) + { + saved_buffer_length = pStubMsg->BufferLength; + pStubMsg->BufferLength = pStubMsg->PointerLength; + pStubMsg->PointerLength = 0; + } + ALIGN_LENGTH(pStubMsg->BufferLength, 8); + } + else + ALIGN_LENGTH(pStubMsg->BufferLength, (flags & 0xf) + 1); + + if (bufsize) { + TRACE("size=%d\n", bufsize); + safe_buffer_length_increment(pStubMsg, bufsize); + } + else + pStubMsg->BufferLength = + pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnBufferSize( + &umcb.Flags, pStubMsg->BufferLength, pMemory); + + if (saved_buffer_length) + { + pStubMsg->PointerLength = pStubMsg->BufferLength; + pStubMsg->BufferLength = saved_buffer_length; + } + +} + +/*********************************************************************** + * NdrUserMarshalMemorySize [RPCRT4.@] + */ +ULONG WINAPI NdrUserMarshalMemorySize(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + unsigned flags = pFormat[1]; + unsigned index = *(const WORD*)&pFormat[2]; + DWORD memsize = *(const WORD*)&pFormat[4]; + DWORD bufsize = *(const WORD*)&pFormat[6]; + + TRACE("(%p,%p)\n", pStubMsg, pFormat); + TRACE("index=%d\n", index); + + pStubMsg->MemorySize += memsize; + + if (flags & USER_MARSHAL_POINTER) + { + ALIGN_POINTER(pStubMsg->Buffer, 4); + /* skip pointer prefix */ + pStubMsg->Buffer += 4; + if (pStubMsg->IgnoreEmbeddedPointers) + return pStubMsg->MemorySize; + ALIGN_POINTER(pStubMsg->Buffer, 8); + } + else + ALIGN_POINTER(pStubMsg->Buffer, (flags & 0xf) + 1); + + if (!bufsize) + FIXME("not implemented for varying buffer size\n"); + + pStubMsg->Buffer += bufsize; + + return pStubMsg->MemorySize; +} + +/*********************************************************************** + * NdrUserMarshalFree [RPCRT4.@] + */ +void WINAPI NdrUserMarshalFree(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ +/* unsigned flags = pFormat[1]; */ + unsigned index = *(const WORD*)&pFormat[2]; + USER_MARSHAL_CB umcb; + + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + TRACE("index=%d\n", index); + + UserMarshalCB(pStubMsg, USER_MARSHAL_CB_FREE, pFormat, &umcb); + + pStubMsg->StubDesc->aUserMarshalQuadruple[index].pfnFree( + &umcb.Flags, pMemory); +} + +/*********************************************************************** + * NdrClearOutParameters [RPCRT4.@] + */ +void WINAPI NdrClearOutParameters(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat, + void *ArgAddr) +{ + FIXME("(%p,%p,%p): stub\n", pStubMsg, pFormat, ArgAddr); +} + +/*********************************************************************** + * NdrConvert [RPCRT4.@] + */ +void WINAPI NdrConvert( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat ) +{ + FIXME("(pStubMsg == ^%p, pFormat == ^%p): stub.\n", pStubMsg, pFormat); + /* FIXME: since this stub doesn't do any converting, the proper behavior + is to raise an exception */ +} + +/*********************************************************************** + * NdrConvert2 [RPCRT4.@] + */ +void WINAPI NdrConvert2( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, LONG NumberParams ) +{ + FIXME("(pStubMsg == ^%p, pFormat == ^%p, NumberParams == %d): stub.\n", + pStubMsg, pFormat, NumberParams); + /* FIXME: since this stub doesn't do any converting, the proper behavior + is to raise an exception */ +} + +#include "pshpack1.h" +typedef struct _NDR_CSTRUCT_FORMAT +{ + unsigned char type; + unsigned char alignment; + unsigned short memory_size; + short offset_to_array_description; +} NDR_CSTRUCT_FORMAT, NDR_CVSTRUCT_FORMAT; +#include "poppack.h" + +/*********************************************************************** + * NdrConformantStructMarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrConformantStructMarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat; + PFORMAT_STRING pCArrayFormat; + ULONG esize, bufsize; + + TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); + + pFormat += sizeof(NDR_CSTRUCT_FORMAT); + if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT)) + { + ERR("invalid format type %x\n", pCStructFormat->type); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return NULL; + } + + pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description + + pCStructFormat->offset_to_array_description; + if (*pCArrayFormat != RPC_FC_CARRAY) + { + ERR("invalid array format type %x\n", pCStructFormat->type); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return NULL; + } + esize = *(const WORD*)(pCArrayFormat+2); + + ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size, + pCArrayFormat + 4, 0); + + WriteConformance(pStubMsg); + + ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pCStructFormat->alignment + 1); + + TRACE("memory_size = %d\n", pCStructFormat->memory_size); + + bufsize = safe_multiply(esize, pStubMsg->MaxCount); + if (pCStructFormat->memory_size + bufsize < pCStructFormat->memory_size) /* integer overflow */ + { + ERR("integer overflow of memory_size %u with bufsize %u\n", + pCStructFormat->memory_size, bufsize); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + /* copy constant sized part of struct */ + pStubMsg->BufferMark = pStubMsg->Buffer; + safe_copy_to_buffer(pStubMsg, pMemory, pCStructFormat->memory_size + bufsize); + + if (pCStructFormat->type == RPC_FC_CPSTRUCT) + EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat); + + return NULL; +} + +/*********************************************************************** + * NdrConformantStructUnmarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrConformantStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char **ppMemory, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) +{ + const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat; + PFORMAT_STRING pCArrayFormat; + ULONG esize, bufsize; + unsigned char *saved_buffer; + + TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); + + pFormat += sizeof(NDR_CSTRUCT_FORMAT); + if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT)) + { + ERR("invalid format type %x\n", pCStructFormat->type); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return NULL; + } + pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description + + pCStructFormat->offset_to_array_description; + if (*pCArrayFormat != RPC_FC_CARRAY) + { + ERR("invalid array format type %x\n", pCStructFormat->type); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return NULL; + } + esize = *(const WORD*)(pCArrayFormat+2); + + pCArrayFormat = ReadConformance(pStubMsg, pCArrayFormat + 4); + + ALIGN_POINTER(pStubMsg->Buffer, pCStructFormat->alignment + 1); + + TRACE("memory_size = %d\n", pCStructFormat->memory_size); + + bufsize = safe_multiply(esize, pStubMsg->MaxCount); + if (pCStructFormat->memory_size + bufsize < pCStructFormat->memory_size) /* integer overflow */ + { + ERR("integer overflow of memory_size %u with bufsize %u\n", + pCStructFormat->memory_size, bufsize); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + + if (fMustAlloc) + { + SIZE_T size = pCStructFormat->memory_size + bufsize; + *ppMemory = NdrAllocate(pStubMsg, size); + } + else + { + if (!pStubMsg->IsClient && !*ppMemory) + /* for servers, we just point straight into the RPC buffer */ + *ppMemory = pStubMsg->Buffer; + } + + saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer; + safe_buffer_increment(pStubMsg, pCStructFormat->memory_size + bufsize); + if (pCStructFormat->type == RPC_FC_CPSTRUCT) + EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc); + + TRACE("copying %p to %p\n", saved_buffer, *ppMemory); + if (*ppMemory != saved_buffer) + memcpy(*ppMemory, saved_buffer, pCStructFormat->memory_size + bufsize); + + return NULL; +} + +/*********************************************************************** + * NdrConformantStructBufferSize [RPCRT4.@] + */ +void WINAPI NdrConformantStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + const NDR_CSTRUCT_FORMAT * pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat; + PFORMAT_STRING pCArrayFormat; + ULONG esize; + + TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); + + pFormat += sizeof(NDR_CSTRUCT_FORMAT); + if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT)) + { + ERR("invalid format type %x\n", pCStructFormat->type); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return; + } + pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description + + pCStructFormat->offset_to_array_description; + if (*pCArrayFormat != RPC_FC_CARRAY) + { + ERR("invalid array format type %x\n", pCStructFormat->type); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return; + } + esize = *(const WORD*)(pCArrayFormat+2); + + pCArrayFormat = ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size, pCArrayFormat+4, 0); + SizeConformance(pStubMsg); + + ALIGN_LENGTH(pStubMsg->BufferLength, pCStructFormat->alignment + 1); + + TRACE("memory_size = %d\n", pCStructFormat->memory_size); + + safe_buffer_length_increment(pStubMsg, pCStructFormat->memory_size); + safe_buffer_length_increment(pStubMsg, safe_multiply(pStubMsg->MaxCount, esize)); + + if (pCStructFormat->type == RPC_FC_CPSTRUCT) + EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat); +} + +/*********************************************************************** + * NdrConformantStructMemorySize [RPCRT4.@] + */ +ULONG WINAPI NdrConformantStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + FIXME("stub\n"); + return 0; +} + +/*********************************************************************** + * NdrConformantStructFree [RPCRT4.@] + */ +void WINAPI NdrConformantStructFree(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + const NDR_CSTRUCT_FORMAT *pCStructFormat = (const NDR_CSTRUCT_FORMAT *)pFormat; + PFORMAT_STRING pCArrayFormat; + ULONG esize; + + TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); + + pFormat += sizeof(NDR_CSTRUCT_FORMAT); + if ((pCStructFormat->type != RPC_FC_CPSTRUCT) && (pCStructFormat->type != RPC_FC_CSTRUCT)) + { + ERR("invalid format type %x\n", pCStructFormat->type); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return; + } + + pCArrayFormat = (const unsigned char *)&pCStructFormat->offset_to_array_description + + pCStructFormat->offset_to_array_description; + if (*pCArrayFormat != RPC_FC_CARRAY) + { + ERR("invalid array format type %x\n", pCStructFormat->type); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return; + } + esize = *(const WORD*)(pCArrayFormat+2); + + ComputeConformance(pStubMsg, pMemory + pCStructFormat->memory_size, + pCArrayFormat + 4, 0); + + TRACE("memory_size = %d\n", pCStructFormat->memory_size); + + /* copy constant sized part of struct */ + pStubMsg->BufferMark = pStubMsg->Buffer; + + if (pCStructFormat->type == RPC_FC_CPSTRUCT) + EmbeddedPointerFree(pStubMsg, pMemory, pFormat); +} + +/*********************************************************************** + * NdrConformantVaryingStructMarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrConformantVaryingStructMarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat; + PFORMAT_STRING pCVArrayFormat; + ULONG esize, bufsize; + + TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); + + pFormat += sizeof(NDR_CVSTRUCT_FORMAT); + if (pCVStructFormat->type != RPC_FC_CVSTRUCT) + { + ERR("invalid format type %x\n", pCVStructFormat->type); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return NULL; + } + + pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description + + pCVStructFormat->offset_to_array_description; + switch (*pCVArrayFormat) + { + case RPC_FC_CVARRAY: + esize = *(const WORD*)(pCVArrayFormat+2); + + pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size, + pCVArrayFormat + 4, 0); + pCVArrayFormat = ComputeVariance(pStubMsg, pMemory + pCVStructFormat->memory_size, + pCVArrayFormat, 0); + break; + case RPC_FC_C_CSTRING: + TRACE("string=%s\n", debugstr_a((char*)pMemory + pCVStructFormat->memory_size)); + pStubMsg->ActualCount = strlen((char*)pMemory + pCVStructFormat->memory_size)+1; + esize = sizeof(char); + if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) + pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size, + pCVArrayFormat + 2, 0); + else + pStubMsg->MaxCount = pStubMsg->ActualCount; + break; + case RPC_FC_C_WSTRING: + TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory + pCVStructFormat->memory_size)); + pStubMsg->ActualCount = strlenW((LPWSTR)pMemory + pCVStructFormat->memory_size)+1; + esize = sizeof(WCHAR); + if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) + pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size, + pCVArrayFormat + 2, 0); + else + pStubMsg->MaxCount = pStubMsg->ActualCount; + break; + default: + ERR("invalid array format type %x\n", *pCVArrayFormat); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return NULL; + } + + WriteConformance(pStubMsg); + + ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pCVStructFormat->alignment + 1); + + TRACE("memory_size = %d\n", pCVStructFormat->memory_size); + + /* write constant sized part */ + pStubMsg->BufferMark = pStubMsg->Buffer; + safe_copy_to_buffer(pStubMsg, pMemory, pCVStructFormat->memory_size); + + WriteVariance(pStubMsg); + + bufsize = safe_multiply(esize, pStubMsg->ActualCount); + + /* write array part */ + safe_copy_to_buffer(pStubMsg, pMemory + pCVStructFormat->memory_size, bufsize); + + EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat); + + return NULL; +} + +/*********************************************************************** + * NdrConformantVaryingStructUnmarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrConformantVaryingStructUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char **ppMemory, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) +{ + const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat; + PFORMAT_STRING pCVArrayFormat; + ULONG esize, bufsize; + unsigned char cvarray_type; + + TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); + + pFormat += sizeof(NDR_CVSTRUCT_FORMAT); + if (pCVStructFormat->type != RPC_FC_CVSTRUCT) + { + ERR("invalid format type %x\n", pCVStructFormat->type); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return NULL; + } + + pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description + + pCVStructFormat->offset_to_array_description; + cvarray_type = *pCVArrayFormat; + switch (cvarray_type) + { + case RPC_FC_CVARRAY: + esize = *(const WORD*)(pCVArrayFormat+2); + pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 4); + break; + case RPC_FC_C_CSTRING: + esize = sizeof(char); + if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) + pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2); + else + pCVArrayFormat = ReadConformance(pStubMsg, NULL); + break; + case RPC_FC_C_WSTRING: + esize = sizeof(WCHAR); + if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) + pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2); + else + pCVArrayFormat = ReadConformance(pStubMsg, NULL); + break; + default: + ERR("invalid array format type %x\n", *pCVArrayFormat); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return NULL; + } + + ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1); + + TRACE("memory_size = %d\n", pCVStructFormat->memory_size); + + /* work out how much memory to allocate if we need to do so */ + if (!*ppMemory || fMustAlloc) + { + SIZE_T size = pCVStructFormat->memory_size + safe_multiply(esize, pStubMsg->MaxCount); + *ppMemory = NdrAllocate(pStubMsg, size); + } + + /* copy the constant data */ + pStubMsg->BufferMark = pStubMsg->Buffer; + safe_copy_from_buffer(pStubMsg, *ppMemory, pCVStructFormat->memory_size); + + pCVArrayFormat = ReadVariance(pStubMsg, pCVArrayFormat, pStubMsg->MaxCount); + + bufsize = safe_multiply(esize, pStubMsg->ActualCount); + + if ((cvarray_type == RPC_FC_C_CSTRING) || + (cvarray_type == RPC_FC_C_WSTRING)) + { + ULONG i; + /* strings must always have null terminating bytes */ + if (bufsize < esize) + { + ERR("invalid string length of %d\n", pStubMsg->ActualCount); + RpcRaiseException(RPC_S_INVALID_BOUND); + return NULL; + } + for (i = bufsize - esize; i < bufsize; i++) + if (pStubMsg->Buffer[i] != 0) + { + ERR("string not null-terminated at byte position %d, data is 0x%x\n", + i, pStubMsg->Buffer[i]); + RpcRaiseException(RPC_S_INVALID_BOUND); + return NULL; + } + } + + /* copy the array data */ + safe_copy_from_buffer(pStubMsg, *ppMemory + pCVStructFormat->memory_size, bufsize); + + if (cvarray_type == RPC_FC_C_CSTRING) + TRACE("string=%s\n", debugstr_a((char *)(*ppMemory + pCVStructFormat->memory_size))); + else if (cvarray_type == RPC_FC_C_WSTRING) + TRACE("string=%s\n", debugstr_w((WCHAR *)(*ppMemory + pCVStructFormat->memory_size))); + + EmbeddedPointerUnmarshall(pStubMsg, *ppMemory, *ppMemory, pFormat, TRUE /* FIXME */); + + return NULL; +} + +/*********************************************************************** + * NdrConformantVaryingStructBufferSize [RPCRT4.@] + */ +void WINAPI NdrConformantVaryingStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat; + PFORMAT_STRING pCVArrayFormat; + ULONG esize; + + TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); + + pFormat += sizeof(NDR_CVSTRUCT_FORMAT); + if (pCVStructFormat->type != RPC_FC_CVSTRUCT) + { + ERR("invalid format type %x\n", pCVStructFormat->type); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return; + } + + pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description + + pCVStructFormat->offset_to_array_description; + switch (*pCVArrayFormat) + { + case RPC_FC_CVARRAY: + esize = *(const WORD*)(pCVArrayFormat+2); + + pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size, + pCVArrayFormat + 4, 0); + pCVArrayFormat = ComputeVariance(pStubMsg, pMemory + pCVStructFormat->memory_size, + pCVArrayFormat, 0); + break; + case RPC_FC_C_CSTRING: + TRACE("string=%s\n", debugstr_a((char*)pMemory + pCVStructFormat->memory_size)); + pStubMsg->ActualCount = strlen((char*)pMemory + pCVStructFormat->memory_size)+1; + esize = sizeof(char); + if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) + pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size, + pCVArrayFormat + 2, 0); + else + pStubMsg->MaxCount = pStubMsg->ActualCount; + break; + case RPC_FC_C_WSTRING: + TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory + pCVStructFormat->memory_size)); + pStubMsg->ActualCount = strlenW((LPWSTR)pMemory + pCVStructFormat->memory_size)+1; + esize = sizeof(WCHAR); + if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) + pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size, + pCVArrayFormat + 2, 0); + else + pStubMsg->MaxCount = pStubMsg->ActualCount; + break; + default: + ERR("invalid array format type %x\n", *pCVArrayFormat); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return; + } + + SizeConformance(pStubMsg); + + ALIGN_LENGTH(pStubMsg->BufferLength, pCVStructFormat->alignment + 1); + + TRACE("memory_size = %d\n", pCVStructFormat->memory_size); + + safe_buffer_length_increment(pStubMsg, pCVStructFormat->memory_size); + SizeVariance(pStubMsg); + safe_buffer_length_increment(pStubMsg, safe_multiply(pStubMsg->MaxCount, esize)); + + EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat); +} + +/*********************************************************************** + * NdrConformantVaryingStructMemorySize [RPCRT4.@] + */ +ULONG WINAPI NdrConformantVaryingStructMemorySize(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat; + PFORMAT_STRING pCVArrayFormat; + ULONG esize; + unsigned char cvarray_type; + + TRACE("(%p, %p)\n", pStubMsg, pFormat); + + pFormat += sizeof(NDR_CVSTRUCT_FORMAT); + if (pCVStructFormat->type != RPC_FC_CVSTRUCT) + { + ERR("invalid format type %x\n", pCVStructFormat->type); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return 0; + } + + pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description + + pCVStructFormat->offset_to_array_description; + cvarray_type = *pCVArrayFormat; + switch (cvarray_type) + { + case RPC_FC_CVARRAY: + esize = *(const WORD*)(pCVArrayFormat+2); + pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 4); + break; + case RPC_FC_C_CSTRING: + esize = sizeof(char); + if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) + pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2); + else + pCVArrayFormat = ReadConformance(pStubMsg, NULL); + break; + case RPC_FC_C_WSTRING: + esize = sizeof(WCHAR); + if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) + pCVArrayFormat = ReadConformance(pStubMsg, pCVArrayFormat + 2); + else + pCVArrayFormat = ReadConformance(pStubMsg, NULL); + break; + default: + ERR("invalid array format type %x\n", *pCVArrayFormat); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return 0; + } + + ALIGN_POINTER(pStubMsg->Buffer, pCVStructFormat->alignment + 1); + + TRACE("memory_size = %d\n", pCVStructFormat->memory_size); + + safe_buffer_increment(pStubMsg, pCVStructFormat->memory_size); + pCVArrayFormat = ReadVariance(pStubMsg, pCVArrayFormat, pStubMsg->MaxCount); + safe_buffer_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount)); + + pStubMsg->MemorySize += pCVStructFormat->memory_size + safe_multiply(esize, pStubMsg->MaxCount); + + EmbeddedPointerMemorySize(pStubMsg, pFormat); + + return pCVStructFormat->memory_size + pStubMsg->MaxCount * esize; +} + +/*********************************************************************** + * NdrConformantVaryingStructFree [RPCRT4.@] + */ +void WINAPI NdrConformantVaryingStructFree(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + const NDR_CVSTRUCT_FORMAT *pCVStructFormat = (const NDR_CVSTRUCT_FORMAT *)pFormat; + PFORMAT_STRING pCVArrayFormat; + ULONG esize; + + TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); + + pFormat += sizeof(NDR_CVSTRUCT_FORMAT); + if (pCVStructFormat->type != RPC_FC_CVSTRUCT) + { + ERR("invalid format type %x\n", pCVStructFormat->type); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return; + } + + pCVArrayFormat = (const unsigned char *)&pCVStructFormat->offset_to_array_description + + pCVStructFormat->offset_to_array_description; + switch (*pCVArrayFormat) + { + case RPC_FC_CVARRAY: + esize = *(const WORD*)(pCVArrayFormat+2); + + pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size, + pCVArrayFormat + 4, 0); + pCVArrayFormat = ComputeVariance(pStubMsg, pMemory + pCVStructFormat->memory_size, + pCVArrayFormat, 0); + break; + case RPC_FC_C_CSTRING: + TRACE("string=%s\n", debugstr_a((char*)pMemory + pCVStructFormat->memory_size)); + pStubMsg->ActualCount = strlen((char*)pMemory + pCVStructFormat->memory_size)+1; + esize = sizeof(char); + if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) + pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size, + pCVArrayFormat + 2, 0); + else + pStubMsg->MaxCount = pStubMsg->ActualCount; + break; + case RPC_FC_C_WSTRING: + TRACE("string=%s\n", debugstr_w((LPWSTR)pMemory + pCVStructFormat->memory_size)); + pStubMsg->ActualCount = strlenW((LPWSTR)pMemory + pCVStructFormat->memory_size)+1; + esize = sizeof(WCHAR); + if (pCVArrayFormat[1] == RPC_FC_STRING_SIZED) + pCVArrayFormat = ComputeConformance(pStubMsg, pMemory + pCVStructFormat->memory_size, + pCVArrayFormat + 2, 0); + else + pStubMsg->MaxCount = pStubMsg->ActualCount; + break; + default: + ERR("invalid array format type %x\n", *pCVArrayFormat); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return; + } + + TRACE("memory_size = %d\n", pCVStructFormat->memory_size); + + EmbeddedPointerFree(pStubMsg, pMemory, pFormat); +} + +#include "pshpack1.h" +typedef struct +{ + unsigned char type; + unsigned char alignment; + unsigned short total_size; +} NDR_SMFARRAY_FORMAT; + +typedef struct +{ + unsigned char type; + unsigned char alignment; + unsigned long total_size; +} NDR_LGFARRAY_FORMAT; +#include "poppack.h" + +/*********************************************************************** + * NdrFixedArrayMarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrFixedArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat; + unsigned long total_size; + + TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); + + if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) && + (pSmFArrayFormat->type != RPC_FC_LGFARRAY)) + { + ERR("invalid format type %x\n", pSmFArrayFormat->type); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return NULL; + } + + ALIGN_POINTER_CLEAR(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1); + + if (pSmFArrayFormat->type == RPC_FC_SMFARRAY) + { + total_size = pSmFArrayFormat->total_size; + pFormat = (const unsigned char *)(pSmFArrayFormat + 1); + } + else + { + const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat; + total_size = pLgFArrayFormat->total_size; + pFormat = (const unsigned char *)(pLgFArrayFormat + 1); + } + + pStubMsg->BufferMark = pStubMsg->Buffer; + safe_copy_to_buffer(pStubMsg, pMemory, total_size); + + pFormat = EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat); + + return NULL; +} + +/*********************************************************************** + * NdrFixedArrayUnmarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrFixedArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char **ppMemory, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) +{ + const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat; + unsigned long total_size; + unsigned char *saved_buffer; + + TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); + + if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) && + (pSmFArrayFormat->type != RPC_FC_LGFARRAY)) + { + ERR("invalid format type %x\n", pSmFArrayFormat->type); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return NULL; + } + + ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1); + + if (pSmFArrayFormat->type == RPC_FC_SMFARRAY) + { + total_size = pSmFArrayFormat->total_size; + pFormat = (const unsigned char *)(pSmFArrayFormat + 1); + } + else + { + const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat; + total_size = pLgFArrayFormat->total_size; + pFormat = (const unsigned char *)(pLgFArrayFormat + 1); + } + + if (fMustAlloc) + *ppMemory = NdrAllocate(pStubMsg, total_size); + else + { + if (!pStubMsg->IsClient && !*ppMemory) + /* for servers, we just point straight into the RPC buffer */ + *ppMemory = pStubMsg->Buffer; + } + + saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer; + safe_buffer_increment(pStubMsg, total_size); + pFormat = EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc); + + TRACE("copying %p to %p\n", saved_buffer, *ppMemory); + if (*ppMemory != saved_buffer) + memcpy(*ppMemory, saved_buffer, total_size); + + return NULL; +} + +/*********************************************************************** + * NdrFixedArrayBufferSize [RPCRT4.@] + */ +void WINAPI NdrFixedArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat; + unsigned long total_size; + + TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); + + if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) && + (pSmFArrayFormat->type != RPC_FC_LGFARRAY)) + { + ERR("invalid format type %x\n", pSmFArrayFormat->type); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return; + } + + ALIGN_LENGTH(pStubMsg->BufferLength, pSmFArrayFormat->alignment + 1); + + if (pSmFArrayFormat->type == RPC_FC_SMFARRAY) + { + total_size = pSmFArrayFormat->total_size; + pFormat = (const unsigned char *)(pSmFArrayFormat + 1); + } + else + { + const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat; + total_size = pLgFArrayFormat->total_size; + pFormat = (const unsigned char *)(pLgFArrayFormat + 1); + } + safe_buffer_length_increment(pStubMsg, total_size); + + EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat); +} + +/*********************************************************************** + * NdrFixedArrayMemorySize [RPCRT4.@] + */ +ULONG WINAPI NdrFixedArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat; + ULONG total_size; + + TRACE("(%p, %p)\n", pStubMsg, pFormat); + + if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) && + (pSmFArrayFormat->type != RPC_FC_LGFARRAY)) + { + ERR("invalid format type %x\n", pSmFArrayFormat->type); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return 0; + } + + ALIGN_POINTER(pStubMsg->Buffer, pSmFArrayFormat->alignment + 1); + + if (pSmFArrayFormat->type == RPC_FC_SMFARRAY) + { + total_size = pSmFArrayFormat->total_size; + pFormat = (const unsigned char *)(pSmFArrayFormat + 1); + } + else + { + const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat; + total_size = pLgFArrayFormat->total_size; + pFormat = (const unsigned char *)(pLgFArrayFormat + 1); + } + pStubMsg->BufferMark = pStubMsg->Buffer; + safe_buffer_increment(pStubMsg, total_size); + pStubMsg->MemorySize += total_size; + + EmbeddedPointerMemorySize(pStubMsg, pFormat); + + return total_size; +} + +/*********************************************************************** + * NdrFixedArrayFree [RPCRT4.@] + */ +void WINAPI NdrFixedArrayFree(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + const NDR_SMFARRAY_FORMAT *pSmFArrayFormat = (const NDR_SMFARRAY_FORMAT *)pFormat; + + TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); + + if ((pSmFArrayFormat->type != RPC_FC_SMFARRAY) && + (pSmFArrayFormat->type != RPC_FC_LGFARRAY)) + { + ERR("invalid format type %x\n", pSmFArrayFormat->type); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return; + } + + if (pSmFArrayFormat->type == RPC_FC_SMFARRAY) + pFormat = (const unsigned char *)(pSmFArrayFormat + 1); + else + { + const NDR_LGFARRAY_FORMAT *pLgFArrayFormat = (const NDR_LGFARRAY_FORMAT *)pFormat; + pFormat = (const unsigned char *)(pLgFArrayFormat + 1); + } + + EmbeddedPointerFree(pStubMsg, pMemory, pFormat); +} + +/*********************************************************************** + * NdrVaryingArrayMarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrVaryingArrayMarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + unsigned char alignment; + DWORD elements, esize; + ULONG bufsize; + + TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); + + if ((pFormat[0] != RPC_FC_SMVARRAY) && + (pFormat[0] != RPC_FC_LGVARRAY)) + { + ERR("invalid format type %x\n", pFormat[0]); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return NULL; + } + + alignment = pFormat[1] + 1; + + if (pFormat[0] == RPC_FC_SMVARRAY) + { + pFormat += 2; + pFormat += sizeof(WORD); + elements = *(const WORD*)pFormat; + pFormat += sizeof(WORD); + } + else + { + pFormat += 2; + pFormat += sizeof(DWORD); + elements = *(const DWORD*)pFormat; + pFormat += sizeof(DWORD); + } + + esize = *(const WORD*)pFormat; + pFormat += sizeof(WORD); + + pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0); + if ((pStubMsg->ActualCount > elements) || + (pStubMsg->ActualCount + pStubMsg->Offset > elements)) + { + RpcRaiseException(RPC_S_INVALID_BOUND); + return NULL; + } + + WriteVariance(pStubMsg); + + ALIGN_POINTER_CLEAR(pStubMsg->Buffer, alignment); + + bufsize = safe_multiply(esize, pStubMsg->ActualCount); + pStubMsg->BufferMark = pStubMsg->Buffer; + safe_copy_to_buffer(pStubMsg, pMemory + pStubMsg->Offset, bufsize); + + EmbeddedPointerMarshall(pStubMsg, pMemory, pFormat); + + return NULL; +} + +/*********************************************************************** + * NdrVaryingArrayUnmarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrVaryingArrayUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char **ppMemory, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) +{ + unsigned char alignment; + DWORD size, elements, esize; + ULONG bufsize; + unsigned char *saved_buffer; + ULONG offset; + + TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); + + if ((pFormat[0] != RPC_FC_SMVARRAY) && + (pFormat[0] != RPC_FC_LGVARRAY)) + { + ERR("invalid format type %x\n", pFormat[0]); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return NULL; + } + + alignment = pFormat[1] + 1; + + if (pFormat[0] == RPC_FC_SMVARRAY) + { + pFormat += 2; + size = *(const WORD*)pFormat; + pFormat += sizeof(WORD); + elements = *(const WORD*)pFormat; + pFormat += sizeof(WORD); + } + else + { + pFormat += 2; + size = *(const DWORD*)pFormat; + pFormat += sizeof(DWORD); + elements = *(const DWORD*)pFormat; + pFormat += sizeof(DWORD); + } + + esize = *(const WORD*)pFormat; + pFormat += sizeof(WORD); + + pFormat = ReadVariance(pStubMsg, pFormat, elements); + + ALIGN_POINTER(pStubMsg->Buffer, alignment); + + bufsize = safe_multiply(esize, pStubMsg->ActualCount); + offset = pStubMsg->Offset; + + if (!*ppMemory || fMustAlloc) + *ppMemory = NdrAllocate(pStubMsg, size); + saved_buffer = pStubMsg->BufferMark = pStubMsg->Buffer; + safe_buffer_increment(pStubMsg, bufsize); + + EmbeddedPointerUnmarshall(pStubMsg, saved_buffer, *ppMemory, pFormat, fMustAlloc); + + memcpy(*ppMemory + offset, saved_buffer, bufsize); + + return NULL; +} + +/*********************************************************************** + * NdrVaryingArrayBufferSize [RPCRT4.@] + */ +void WINAPI NdrVaryingArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + unsigned char alignment; + DWORD elements, esize; + + TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); + + if ((pFormat[0] != RPC_FC_SMVARRAY) && + (pFormat[0] != RPC_FC_LGVARRAY)) + { + ERR("invalid format type %x\n", pFormat[0]); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return; + } + + alignment = pFormat[1] + 1; + + if (pFormat[0] == RPC_FC_SMVARRAY) + { + pFormat += 2; + pFormat += sizeof(WORD); + elements = *(const WORD*)pFormat; + pFormat += sizeof(WORD); + } + else + { + pFormat += 2; + pFormat += sizeof(DWORD); + elements = *(const DWORD*)pFormat; + pFormat += sizeof(DWORD); + } + + esize = *(const WORD*)pFormat; + pFormat += sizeof(WORD); + + pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0); + if ((pStubMsg->ActualCount > elements) || + (pStubMsg->ActualCount + pStubMsg->Offset > elements)) + { + RpcRaiseException(RPC_S_INVALID_BOUND); + return; + } + + SizeVariance(pStubMsg); + + ALIGN_LENGTH(pStubMsg->BufferLength, alignment); + + safe_buffer_length_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount)); + + EmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat); +} + +/*********************************************************************** + * NdrVaryingArrayMemorySize [RPCRT4.@] + */ +ULONG WINAPI NdrVaryingArrayMemorySize(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + unsigned char alignment; + DWORD size, elements, esize; + + TRACE("(%p, %p)\n", pStubMsg, pFormat); + + if ((pFormat[0] != RPC_FC_SMVARRAY) && + (pFormat[0] != RPC_FC_LGVARRAY)) + { + ERR("invalid format type %x\n", pFormat[0]); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return 0; + } + + alignment = pFormat[1] + 1; + + if (pFormat[0] == RPC_FC_SMVARRAY) + { + pFormat += 2; + size = *(const WORD*)pFormat; + pFormat += sizeof(WORD); + elements = *(const WORD*)pFormat; + pFormat += sizeof(WORD); + } + else + { + pFormat += 2; + size = *(const DWORD*)pFormat; + pFormat += sizeof(DWORD); + elements = *(const DWORD*)pFormat; + pFormat += sizeof(DWORD); + } + + esize = *(const WORD*)pFormat; + pFormat += sizeof(WORD); + + pFormat = ReadVariance(pStubMsg, pFormat, elements); + + ALIGN_POINTER(pStubMsg->Buffer, alignment); + + safe_buffer_increment(pStubMsg, safe_multiply(esize, pStubMsg->ActualCount)); + pStubMsg->MemorySize += size; + + EmbeddedPointerMemorySize(pStubMsg, pFormat); + + return pStubMsg->MemorySize; +} + +/*********************************************************************** + * NdrVaryingArrayFree [RPCRT4.@] + */ +void WINAPI NdrVaryingArrayFree(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + unsigned char alignment; + DWORD elements; + + TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); + + if ((pFormat[0] != RPC_FC_SMVARRAY) && + (pFormat[0] != RPC_FC_LGVARRAY)) + { + ERR("invalid format type %x\n", pFormat[0]); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return; + } + + alignment = pFormat[1] + 1; + + if (pFormat[0] == RPC_FC_SMVARRAY) + { + pFormat += 2; + pFormat += sizeof(WORD); + elements = *(const WORD*)pFormat; + pFormat += sizeof(WORD); + } + else + { + pFormat += 2; + pFormat += sizeof(DWORD); + elements = *(const DWORD*)pFormat; + pFormat += sizeof(DWORD); + } + + pFormat += sizeof(WORD); + + pFormat = ComputeVariance(pStubMsg, pMemory, pFormat, 0); + if ((pStubMsg->ActualCount > elements) || + (pStubMsg->ActualCount + pStubMsg->Offset > elements)) + { + RpcRaiseException(RPC_S_INVALID_BOUND); + return; + } + + EmbeddedPointerFree(pStubMsg, pMemory, pFormat); +} + +static ULONG get_discriminant(unsigned char fc, const unsigned char *pMemory) +{ + switch (fc) + { + case RPC_FC_BYTE: + case RPC_FC_CHAR: + case RPC_FC_SMALL: + case RPC_FC_USMALL: + return *(const UCHAR *)pMemory; + case RPC_FC_WCHAR: + case RPC_FC_SHORT: + case RPC_FC_USHORT: + case RPC_FC_ENUM16: + return *(const USHORT *)pMemory; + case RPC_FC_LONG: + case RPC_FC_ULONG: + case RPC_FC_ENUM32: + return *(const ULONG *)pMemory; + default: + FIXME("Unhandled base type: 0x%02x\n", fc); + return 0; + } +} + +static PFORMAT_STRING get_arm_offset_from_union_arm_selector(PMIDL_STUB_MESSAGE pStubMsg, + unsigned long discriminant, + PFORMAT_STRING pFormat) +{ + unsigned short num_arms, arm, type; + + num_arms = *(const SHORT*)pFormat & 0x0fff; + pFormat += 2; + for(arm = 0; arm < num_arms; arm++) + { + if(discriminant == *(const ULONG*)pFormat) + { + pFormat += 4; + break; + } + pFormat += 6; + } + + type = *(const unsigned short*)pFormat; + TRACE("type %04x\n", type); + if(arm == num_arms) /* default arm extras */ + { + if(type == 0xffff) + { + ERR("no arm for 0x%lx and no default case\n", discriminant); + RpcRaiseException(RPC_S_INVALID_TAG); + return NULL; + } + if(type == 0) + { + TRACE("falling back to empty default case for 0x%lx\n", discriminant); + return NULL; + } + } + return pFormat; +} + +static unsigned char *union_arm_marshall(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, ULONG discriminant, PFORMAT_STRING pFormat) +{ + unsigned short type; + + pFormat += 2; + + pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat); + if(!pFormat) + return NULL; + + type = *(const unsigned short*)pFormat; + if((type & 0xff00) == 0x8000) + { + unsigned char basetype = LOBYTE(type); + return NdrBaseTypeMarshall(pStubMsg, pMemory, &basetype); + } + else + { + PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat; + NDR_MARSHALL m = NdrMarshaller[*desc & NDR_TABLE_MASK]; + if (m) + { + unsigned char *saved_buffer = NULL; + int pointer_buffer_mark_set = 0; + switch(*desc) + { + case RPC_FC_RP: + case RPC_FC_UP: + case RPC_FC_OP: + case RPC_FC_FP: + ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4); + saved_buffer = pStubMsg->Buffer; + if (pStubMsg->PointerBufferMark) + { + pStubMsg->Buffer = pStubMsg->PointerBufferMark; + pStubMsg->PointerBufferMark = NULL; + pointer_buffer_mark_set = 1; + } + else + safe_buffer_increment(pStubMsg, 4); /* for pointer ID */ + + PointerMarshall(pStubMsg, saved_buffer, *(unsigned char **)pMemory, desc); + if (pointer_buffer_mark_set) + { + STD_OVERFLOW_CHECK(pStubMsg); + pStubMsg->PointerBufferMark = pStubMsg->Buffer; + if (saved_buffer + 4 > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) + { + ERR("buffer overflow - saved_buffer = %p, BufferEnd = %p\n", + saved_buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + pStubMsg->Buffer = saved_buffer + 4; + } + break; + default: + m(pStubMsg, pMemory, desc); + } + } + else FIXME("no marshaller for embedded type %02x\n", *desc); + } + return NULL; +} + +static unsigned char *union_arm_unmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char **ppMemory, + ULONG discriminant, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) +{ + unsigned short type; + + pFormat += 2; + + pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat); + if(!pFormat) + return NULL; + + type = *(const unsigned short*)pFormat; + if((type & 0xff00) == 0x8000) + { + unsigned char basetype = LOBYTE(type); + return NdrBaseTypeUnmarshall(pStubMsg, ppMemory, &basetype, FALSE); + } + else + { + PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat; + NDR_UNMARSHALL m = NdrUnmarshaller[*desc & NDR_TABLE_MASK]; + if (m) + { + unsigned char *saved_buffer = NULL; + int pointer_buffer_mark_set = 0; + switch(*desc) + { + case RPC_FC_RP: + case RPC_FC_UP: + case RPC_FC_OP: + case RPC_FC_FP: + **(void***)ppMemory = NULL; + ALIGN_POINTER(pStubMsg->Buffer, 4); + saved_buffer = pStubMsg->Buffer; + if (pStubMsg->PointerBufferMark) + { + pStubMsg->Buffer = pStubMsg->PointerBufferMark; + pStubMsg->PointerBufferMark = NULL; + pointer_buffer_mark_set = 1; + } + else + pStubMsg->Buffer += 4; /* for pointer ID */ + + if (saved_buffer + 4 > pStubMsg->BufferEnd) + { + ERR("buffer overflow - saved_buffer = %p, BufferEnd = %p\n", + saved_buffer, pStubMsg->BufferEnd); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + + PointerUnmarshall(pStubMsg, saved_buffer, *(unsigned char ***)ppMemory, **(unsigned char ***)ppMemory, desc, fMustAlloc); + if (pointer_buffer_mark_set) + { + STD_OVERFLOW_CHECK(pStubMsg); + pStubMsg->PointerBufferMark = pStubMsg->Buffer; + pStubMsg->Buffer = saved_buffer + 4; + } + break; + default: + m(pStubMsg, ppMemory, desc, fMustAlloc); + } + } + else FIXME("no marshaller for embedded type %02x\n", *desc); + } + return NULL; +} + +static void union_arm_buffer_size(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + ULONG discriminant, + PFORMAT_STRING pFormat) +{ + unsigned short type; + + pFormat += 2; + + pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat); + if(!pFormat) + return; + + type = *(const unsigned short*)pFormat; + if((type & 0xff00) == 0x8000) + { + unsigned char basetype = LOBYTE(type); + NdrBaseTypeBufferSize(pStubMsg, pMemory, &basetype); + } + else + { + PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat; + NDR_BUFFERSIZE m = NdrBufferSizer[*desc & NDR_TABLE_MASK]; + if (m) + { + switch(*desc) + { + case RPC_FC_RP: + case RPC_FC_UP: + case RPC_FC_OP: + case RPC_FC_FP: + ALIGN_LENGTH(pStubMsg->BufferLength, 4); + safe_buffer_length_increment(pStubMsg, 4); /* for pointer ID */ + if (!pStubMsg->IgnoreEmbeddedPointers) + { + int saved_buffer_length = pStubMsg->BufferLength; + pStubMsg->BufferLength = pStubMsg->PointerLength; + pStubMsg->PointerLength = 0; + if(!pStubMsg->BufferLength) + ERR("BufferLength == 0??\n"); + PointerBufferSize(pStubMsg, *(unsigned char **)pMemory, desc); + pStubMsg->PointerLength = pStubMsg->BufferLength; + pStubMsg->BufferLength = saved_buffer_length; + } + break; + default: + m(pStubMsg, pMemory, desc); + } + } + else FIXME("no buffersizer for embedded type %02x\n", *desc); + } +} + +static ULONG union_arm_memory_size(PMIDL_STUB_MESSAGE pStubMsg, + ULONG discriminant, + PFORMAT_STRING pFormat) +{ + unsigned short type, size; + + size = *(const unsigned short*)pFormat; + pStubMsg->Memory += size; + pFormat += 2; + + pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat); + if(!pFormat) + return 0; + + type = *(const unsigned short*)pFormat; + if((type & 0xff00) == 0x8000) + { + return NdrBaseTypeMemorySize(pStubMsg, pFormat); + } + else + { + PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat; + NDR_MEMORYSIZE m = NdrMemorySizer[*desc & NDR_TABLE_MASK]; + unsigned char *saved_buffer; + if (m) + { + switch(*desc) + { + case RPC_FC_RP: + case RPC_FC_UP: + case RPC_FC_OP: + case RPC_FC_FP: + ALIGN_POINTER(pStubMsg->Buffer, 4); + saved_buffer = pStubMsg->Buffer; + safe_buffer_increment(pStubMsg, 4); + ALIGN_LENGTH(pStubMsg->MemorySize, 4); + pStubMsg->MemorySize += 4; + if (!pStubMsg->IgnoreEmbeddedPointers) + PointerMemorySize(pStubMsg, saved_buffer, pFormat); + break; + default: + return m(pStubMsg, desc); + } + } + else FIXME("no marshaller for embedded type %02x\n", *desc); + } + + TRACE("size %d\n", size); + return size; +} + +static void union_arm_free(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + ULONG discriminant, + PFORMAT_STRING pFormat) +{ + unsigned short type; + + pFormat += 2; + + pFormat = get_arm_offset_from_union_arm_selector(pStubMsg, discriminant, pFormat); + if(!pFormat) + return; + + type = *(const unsigned short*)pFormat; + if((type & 0xff00) != 0x8000) + { + PFORMAT_STRING desc = pFormat + *(const SHORT*)pFormat; + NDR_FREE m = NdrFreer[*desc & NDR_TABLE_MASK]; + if (m) + { + switch(*desc) + { + case RPC_FC_RP: + case RPC_FC_UP: + case RPC_FC_OP: + case RPC_FC_FP: + PointerFree(pStubMsg, *(unsigned char **)pMemory, desc); + break; + default: + m(pStubMsg, pMemory, desc); + } + } + else FIXME("no freer for embedded type %02x\n", *desc); + } +} + +/*********************************************************************** + * NdrEncapsulatedUnionMarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + unsigned char switch_type; + unsigned char increment; + ULONG switch_value; + + TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); + pFormat++; + + switch_type = *pFormat & 0xf; + increment = (*pFormat & 0xf0) >> 4; + pFormat++; + + ALIGN_POINTER_CLEAR(pStubMsg->Buffer, increment); + + switch_value = get_discriminant(switch_type, pMemory); + TRACE("got switch value 0x%x\n", switch_value); + + NdrBaseTypeMarshall(pStubMsg, pMemory, &switch_type); + pMemory += increment; + + return union_arm_marshall(pStubMsg, pMemory, switch_value, pFormat); +} + +/*********************************************************************** + * NdrEncapsulatedUnionUnmarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char **ppMemory, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) +{ + unsigned char switch_type; + unsigned char increment; + ULONG switch_value; + unsigned short size; + unsigned char *pMemoryArm; + + TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); + pFormat++; + + switch_type = *pFormat & 0xf; + increment = (*pFormat & 0xf0) >> 4; + pFormat++; + + ALIGN_POINTER(pStubMsg->Buffer, increment); + switch_value = get_discriminant(switch_type, pStubMsg->Buffer); + TRACE("got switch value 0x%x\n", switch_value); + + size = *(const unsigned short*)pFormat + increment; + if(!*ppMemory || fMustAlloc) + *ppMemory = NdrAllocate(pStubMsg, size); + + NdrBaseTypeUnmarshall(pStubMsg, ppMemory, &switch_type, FALSE); + pMemoryArm = *ppMemory + increment; + + return union_arm_unmarshall(pStubMsg, &pMemoryArm, switch_value, pFormat, fMustAlloc); +} + +/*********************************************************************** + * NdrEncapsulatedUnionBufferSize [RPCRT4.@] + */ +void WINAPI NdrEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + unsigned char switch_type; + unsigned char increment; + ULONG switch_value; + + TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); + pFormat++; + + switch_type = *pFormat & 0xf; + increment = (*pFormat & 0xf0) >> 4; + pFormat++; + + ALIGN_LENGTH(pStubMsg->BufferLength, increment); + switch_value = get_discriminant(switch_type, pMemory); + TRACE("got switch value 0x%x\n", switch_value); + + /* Add discriminant size */ + NdrBaseTypeBufferSize(pStubMsg, (unsigned char *)&switch_value, &switch_type); + pMemory += increment; + + union_arm_buffer_size(pStubMsg, pMemory, switch_value, pFormat); +} + +/*********************************************************************** + * NdrEncapsulatedUnionMemorySize [RPCRT4.@] + */ +ULONG WINAPI NdrEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + unsigned char switch_type; + unsigned char increment; + ULONG switch_value; + + switch_type = *pFormat & 0xf; + increment = (*pFormat & 0xf0) >> 4; + pFormat++; + + ALIGN_POINTER(pStubMsg->Buffer, increment); + switch_value = get_discriminant(switch_type, pStubMsg->Buffer); + TRACE("got switch value 0x%x\n", switch_value); + + pStubMsg->Memory += increment; + + return increment + union_arm_memory_size(pStubMsg, switch_value, pFormat + *(const SHORT*)pFormat); +} + +/*********************************************************************** + * NdrEncapsulatedUnionFree [RPCRT4.@] + */ +void WINAPI NdrEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + unsigned char switch_type; + unsigned char increment; + ULONG switch_value; + + TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); + pFormat++; + + switch_type = *pFormat & 0xf; + increment = (*pFormat & 0xf0) >> 4; + pFormat++; + + switch_value = get_discriminant(switch_type, pMemory); + TRACE("got switch value 0x%x\n", switch_value); + + pMemory += increment; + + return union_arm_free(pStubMsg, pMemory, switch_value, pFormat); +} + +/*********************************************************************** + * NdrNonEncapsulatedUnionMarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrNonEncapsulatedUnionMarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + unsigned char switch_type; + + TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); + pFormat++; + + switch_type = *pFormat; + pFormat++; + + pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0); + TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount); + /* Marshall discriminant */ + NdrBaseTypeMarshall(pStubMsg, (unsigned char *)&pStubMsg->MaxCount, &switch_type); + + return union_arm_marshall(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat); +} + +static long unmarshall_discriminant(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING *ppFormat) +{ + long discriminant = 0; + + switch(**ppFormat) + { + case RPC_FC_BYTE: + case RPC_FC_CHAR: + case RPC_FC_SMALL: + case RPC_FC_USMALL: + { + UCHAR d; + safe_copy_from_buffer(pStubMsg, &d, sizeof(d)); + discriminant = d; + break; + } + case RPC_FC_WCHAR: + case RPC_FC_SHORT: + case RPC_FC_USHORT: + { + USHORT d; + ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT)); + safe_copy_from_buffer(pStubMsg, &d, sizeof(d)); + discriminant = d; + break; + } + case RPC_FC_LONG: + case RPC_FC_ULONG: + { + ULONG d; + ALIGN_POINTER(pStubMsg->Buffer, sizeof(ULONG)); + safe_copy_from_buffer(pStubMsg, &d, sizeof(d)); + discriminant = d; + break; + } + default: + FIXME("Unhandled base type: 0x%02x\n", **ppFormat); + } + (*ppFormat)++; + + if (pStubMsg->fHasNewCorrDesc) + *ppFormat += 6; + else + *ppFormat += 4; + return discriminant; +} + +/********************************************************************** + * NdrNonEncapsulatedUnionUnmarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrNonEncapsulatedUnionUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char **ppMemory, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) +{ + long discriminant; + unsigned short size; + + TRACE("(%p, %p, %p, %d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); + pFormat++; + + /* Unmarshall discriminant */ + discriminant = unmarshall_discriminant(pStubMsg, &pFormat); + TRACE("unmarshalled discriminant %lx\n", discriminant); + + pFormat += *(const SHORT*)pFormat; + + size = *(const unsigned short*)pFormat; + + if(!*ppMemory || fMustAlloc) + *ppMemory = NdrAllocate(pStubMsg, size); + + return union_arm_unmarshall(pStubMsg, ppMemory, discriminant, pFormat, fMustAlloc); +} + +/*********************************************************************** + * NdrNonEncapsulatedUnionBufferSize [RPCRT4.@] + */ +void WINAPI NdrNonEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + unsigned char switch_type; + + TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); + pFormat++; + + switch_type = *pFormat; + pFormat++; + + pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0); + TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount); + /* Add discriminant size */ + NdrBaseTypeBufferSize(pStubMsg, (unsigned char *)&pStubMsg->MaxCount, &switch_type); + + union_arm_buffer_size(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat); +} + +/*********************************************************************** + * NdrNonEncapsulatedUnionMemorySize [RPCRT4.@] + */ +ULONG WINAPI NdrNonEncapsulatedUnionMemorySize(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + ULONG discriminant; + + pFormat++; + /* Unmarshall discriminant */ + discriminant = unmarshall_discriminant(pStubMsg, &pFormat); + TRACE("unmarshalled discriminant 0x%x\n", discriminant); + + return union_arm_memory_size(pStubMsg, discriminant, pFormat + *(const SHORT*)pFormat); +} + +/*********************************************************************** + * NdrNonEncapsulatedUnionFree [RPCRT4.@] + */ +void WINAPI NdrNonEncapsulatedUnionFree(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + TRACE("(%p, %p, %p)\n", pStubMsg, pMemory, pFormat); + pFormat++; + pFormat++; + + pFormat = ComputeConformance(pStubMsg, pMemory, pFormat, 0); + TRACE("got switch value 0x%lx\n", pStubMsg->MaxCount); + + return union_arm_free(pStubMsg, pMemory, pStubMsg->MaxCount, pFormat + *(const SHORT*)pFormat); +} + +/*********************************************************************** + * NdrByteCountPointerMarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrByteCountPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + FIXME("stub\n"); + return NULL; +} + +/*********************************************************************** + * NdrByteCountPointerUnmarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrByteCountPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char **ppMemory, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) +{ + FIXME("stub\n"); + return NULL; +} + +/*********************************************************************** + * NdrByteCountPointerBufferSize [RPCRT4.@] + */ +void WINAPI NdrByteCountPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + FIXME("stub\n"); +} + +/*********************************************************************** + * NdrByteCountPointerMemorySize [RPCRT4.@] + */ +ULONG WINAPI NdrByteCountPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + FIXME("stub\n"); + return 0; +} + +/*********************************************************************** + * NdrByteCountPointerFree [RPCRT4.@] + */ +void WINAPI NdrByteCountPointerFree(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + FIXME("stub\n"); +} + +/*********************************************************************** + * NdrXmitOrRepAsMarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrXmitOrRepAsMarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + FIXME("stub\n"); + return NULL; +} + +/*********************************************************************** + * NdrXmitOrRepAsUnmarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrXmitOrRepAsUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char **ppMemory, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) +{ + FIXME("stub\n"); + return NULL; +} + +/*********************************************************************** + * NdrXmitOrRepAsBufferSize [RPCRT4.@] + */ +void WINAPI NdrXmitOrRepAsBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + FIXME("stub\n"); +} + +/*********************************************************************** + * NdrXmitOrRepAsMemorySize [RPCRT4.@] + */ +ULONG WINAPI NdrXmitOrRepAsMemorySize(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + FIXME("stub\n"); + return 0; +} + +/*********************************************************************** + * NdrXmitOrRepAsFree [RPCRT4.@] + */ +void WINAPI NdrXmitOrRepAsFree(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + FIXME("stub\n"); +} + +#include "pshpack1.h" +typedef struct +{ + unsigned char type; + unsigned char flags_type; /* flags in upper nibble, type in lower nibble */ + ULONG low_value; + ULONG high_value; +} NDR_RANGE; +#include "poppack.h" + +/*********************************************************************** + * NdrRangeMarshall [internal] + */ +unsigned char *WINAPI NdrRangeMarshall( + PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + NDR_RANGE *pRange = (NDR_RANGE *)pFormat; + unsigned char base_type; + + TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat); + + if (pRange->type != RPC_FC_RANGE) + { + ERR("invalid format type %x\n", pRange->type); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return NULL; + } + + base_type = pRange->flags_type & 0xf; + + return NdrBaseTypeMarshall(pStubMsg, pMemory, &base_type); +} + +/*********************************************************************** + * NdrRangeUnmarshall + */ +unsigned char *WINAPI NdrRangeUnmarshall( + PMIDL_STUB_MESSAGE pStubMsg, + unsigned char **ppMemory, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) +{ + NDR_RANGE *pRange = (NDR_RANGE *)pFormat; + unsigned char base_type; + + TRACE("pStubMsg: %p, ppMemory: %p, type: 0x%02x, fMustAlloc: %s\n", pStubMsg, ppMemory, *pFormat, fMustAlloc ? "true" : "false"); + + if (pRange->type != RPC_FC_RANGE) + { + ERR("invalid format type %x\n", pRange->type); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return NULL; + } + base_type = pRange->flags_type & 0xf; + + TRACE("base_type = 0x%02x, low_value = %d, high_value = %d\n", + base_type, pRange->low_value, pRange->high_value); + +#define RANGE_UNMARSHALL(type, format_spec) \ + do \ + { \ + ALIGN_POINTER(pStubMsg->Buffer, sizeof(type)); \ + if (fMustAlloc || !*ppMemory) \ + *ppMemory = NdrAllocate(pStubMsg, sizeof(type)); \ + if (pStubMsg->Buffer + sizeof(type) > pStubMsg->BufferEnd) \ + { \ + ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n", \ + pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength); \ + RpcRaiseException(RPC_X_BAD_STUB_DATA); \ + } \ + if ((*(type *)pStubMsg->Buffer < (type)pRange->low_value) || \ + (*(type *)pStubMsg->Buffer > (type)pRange->high_value)) \ + { \ + ERR("value exceeded bounds: " format_spec ", low: " format_spec ", high: " format_spec "\n", \ + *(type *)pStubMsg->Buffer, (type)pRange->low_value, \ + (type)pRange->high_value); \ + RpcRaiseException(RPC_S_INVALID_BOUND); \ + return NULL; \ + } \ + TRACE("*ppMemory: %p\n", *ppMemory); \ + **(type **)ppMemory = *(type *)pStubMsg->Buffer; \ + pStubMsg->Buffer += sizeof(type); \ + } while (0) + + switch(base_type) + { + case RPC_FC_CHAR: + case RPC_FC_SMALL: + RANGE_UNMARSHALL(UCHAR, "%d"); + TRACE("value: 0x%02x\n", **(UCHAR **)ppMemory); + break; + case RPC_FC_BYTE: + case RPC_FC_USMALL: + RANGE_UNMARSHALL(CHAR, "%u"); + TRACE("value: 0x%02x\n", **(UCHAR **)ppMemory); + break; + case RPC_FC_WCHAR: /* FIXME: valid? */ + case RPC_FC_USHORT: + RANGE_UNMARSHALL(USHORT, "%u"); + TRACE("value: 0x%04x\n", **(USHORT **)ppMemory); + break; + case RPC_FC_SHORT: + RANGE_UNMARSHALL(SHORT, "%d"); + TRACE("value: 0x%04x\n", **(USHORT **)ppMemory); + break; + case RPC_FC_LONG: + RANGE_UNMARSHALL(LONG, "%d"); + TRACE("value: 0x%08x\n", **(ULONG **)ppMemory); + break; + case RPC_FC_ULONG: + RANGE_UNMARSHALL(ULONG, "%u"); + TRACE("value: 0x%08x\n", **(ULONG **)ppMemory); + break; + case RPC_FC_ENUM16: + case RPC_FC_ENUM32: + FIXME("Unhandled enum type\n"); + break; + case RPC_FC_ERROR_STATUS_T: /* FIXME: valid? */ + case RPC_FC_FLOAT: + case RPC_FC_DOUBLE: + case RPC_FC_HYPER: + default: + ERR("invalid range base type: 0x%02x\n", base_type); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + } + + return NULL; +} + +/*********************************************************************** + * NdrRangeBufferSize [internal] + */ +void WINAPI NdrRangeBufferSize( + PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + NDR_RANGE *pRange = (NDR_RANGE *)pFormat; + unsigned char base_type; + + TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat); + + if (pRange->type != RPC_FC_RANGE) + { + ERR("invalid format type %x\n", pRange->type); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + } + base_type = pRange->flags_type & 0xf; + + NdrBaseTypeBufferSize(pStubMsg, pMemory, &base_type); +} + +/*********************************************************************** + * NdrRangeMemorySize [internal] + */ +ULONG WINAPI NdrRangeMemorySize( + PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + NDR_RANGE *pRange = (NDR_RANGE *)pFormat; + unsigned char base_type; + + if (pRange->type != RPC_FC_RANGE) + { + ERR("invalid format type %x\n", pRange->type); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + return 0; + } + base_type = pRange->flags_type & 0xf; + + return NdrBaseTypeMemorySize(pStubMsg, &base_type); +} + +/*********************************************************************** + * NdrRangeFree [internal] + */ +void WINAPI NdrRangeFree(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + TRACE("pStubMsg %p pMemory %p type 0x%02x\n", pStubMsg, pMemory, *pFormat); + + /* nothing to do */ +} + +/*********************************************************************** + * NdrBaseTypeMarshall [internal] + */ +static unsigned char *WINAPI NdrBaseTypeMarshall( + PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat); + + switch(*pFormat) + { + case RPC_FC_BYTE: + case RPC_FC_CHAR: + case RPC_FC_SMALL: + case RPC_FC_USMALL: + safe_copy_to_buffer(pStubMsg, pMemory, sizeof(UCHAR)); + TRACE("value: 0x%02x\n", *(UCHAR *)pMemory); + break; + case RPC_FC_WCHAR: + case RPC_FC_SHORT: + case RPC_FC_USHORT: + ALIGN_POINTER_CLEAR(pStubMsg->Buffer, sizeof(USHORT)); + safe_copy_to_buffer(pStubMsg, pMemory, sizeof(USHORT)); + TRACE("value: 0x%04x\n", *(USHORT *)pMemory); + break; + case RPC_FC_LONG: + case RPC_FC_ULONG: + case RPC_FC_ERROR_STATUS_T: + case RPC_FC_ENUM32: + 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)); + safe_copy_to_buffer(pStubMsg, pMemory, sizeof(float)); + break; + case RPC_FC_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)); + safe_copy_to_buffer(pStubMsg, pMemory, sizeof(ULONGLONG)); + TRACE("value: %s\n", wine_dbgstr_longlong(*(ULONGLONG*)pMemory)); + break; + case RPC_FC_ENUM16: + /* 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); + TRACE("value: 0x%04x\n", *(UINT *)pMemory); + break; + case RPC_FC_IGNORE: + break; + default: + FIXME("Unhandled base type: 0x%02x\n", *pFormat); + } + + /* FIXME: what is the correct return value? */ + return NULL; +} + +/*********************************************************************** + * NdrBaseTypeUnmarshall [internal] + */ +static unsigned char *WINAPI NdrBaseTypeUnmarshall( + PMIDL_STUB_MESSAGE pStubMsg, + unsigned char **ppMemory, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) +{ + 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)); \ + if (!fMustAlloc && !pStubMsg->IsClient && !*ppMemory) \ + { \ + *ppMemory = pStubMsg->Buffer; \ + TRACE("*ppMemory: %p\n", *ppMemory); \ + } \ + else \ + { \ + if (fMustAlloc) \ + *ppMemory = NdrAllocate(pStubMsg, sizeof(type)); \ + TRACE("*ppMemory: %p\n", *ppMemory); \ + **(type **)ppMemory = *(type *)pStubMsg->Buffer; \ + } \ + pStubMsg->Buffer += sizeof(type); + + switch(*pFormat) + { + case RPC_FC_BYTE: + case RPC_FC_CHAR: + case RPC_FC_SMALL: + case RPC_FC_USMALL: + BASE_TYPE_UNMARSHALL(UCHAR); + TRACE("value: 0x%02x\n", **(UCHAR **)ppMemory); + break; + case RPC_FC_WCHAR: + case RPC_FC_SHORT: + case RPC_FC_USHORT: + BASE_TYPE_UNMARSHALL(USHORT); + TRACE("value: 0x%04x\n", **(USHORT **)ppMemory); + break; + case RPC_FC_LONG: + case RPC_FC_ULONG: + case RPC_FC_ERROR_STATUS_T: + case RPC_FC_ENUM32: + BASE_TYPE_UNMARSHALL(ULONG); + TRACE("value: 0x%08x\n", **(ULONG **)ppMemory); + break; + case RPC_FC_FLOAT: + BASE_TYPE_UNMARSHALL(float); + TRACE("value: %f\n", **(float **)ppMemory); + break; + case RPC_FC_DOUBLE: + BASE_TYPE_UNMARSHALL(double); + TRACE("value: %f\n", **(double **)ppMemory); + break; + case RPC_FC_HYPER: + BASE_TYPE_UNMARSHALL(ULONGLONG); + TRACE("value: %s\n", wine_dbgstr_longlong(**(ULONGLONG **)ppMemory)); + break; + case RPC_FC_ENUM16: + ALIGN_POINTER(pStubMsg->Buffer, sizeof(USHORT)); + if (fMustAlloc || !*ppMemory) + *ppMemory = NdrAllocate(pStubMsg, sizeof(UINT)); + if (pStubMsg->Buffer + sizeof(USHORT) > pStubMsg->BufferEnd) + RpcRaiseException(RPC_X_BAD_STUB_DATA); + TRACE("*ppMemory: %p\n", *ppMemory); + /* 16-bits on the wire, but int in memory */ + **(UINT **)ppMemory = *(USHORT *)pStubMsg->Buffer; + pStubMsg->Buffer += sizeof(USHORT); + TRACE("value: 0x%08x\n", **(UINT **)ppMemory); + break; + case RPC_FC_IGNORE: + break; + default: + FIXME("Unhandled base type: 0x%02x\n", *pFormat); + } +#undef BASE_TYPE_UNMARSHALL + + /* FIXME: what is the correct return value? */ + + return NULL; +} + +/*********************************************************************** + * NdrBaseTypeBufferSize [internal] + */ +static void WINAPI NdrBaseTypeBufferSize( + PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat); + + switch(*pFormat) + { + case RPC_FC_BYTE: + case RPC_FC_CHAR: + case RPC_FC_SMALL: + case RPC_FC_USMALL: + safe_buffer_length_increment(pStubMsg, sizeof(UCHAR)); + break; + case RPC_FC_WCHAR: + case RPC_FC_SHORT: + case RPC_FC_USHORT: + case RPC_FC_ENUM16: + 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)); + safe_buffer_length_increment(pStubMsg, sizeof(ULONG)); + break; + case RPC_FC_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)); + safe_buffer_length_increment(pStubMsg, sizeof(double)); + break; + case RPC_FC_HYPER: + 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)); + safe_buffer_length_increment(pStubMsg, sizeof(error_status_t)); + break; + case RPC_FC_IGNORE: + break; + default: + FIXME("Unhandled base type: 0x%02x\n", *pFormat); + } +} + +/*********************************************************************** + * NdrBaseTypeMemorySize [internal] + */ +static ULONG WINAPI NdrBaseTypeMemorySize( + PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + TRACE("pStubMsg %p, type 0x%02x\n", pStubMsg, *pFormat); + + switch(*pFormat) + { + case RPC_FC_BYTE: + case RPC_FC_CHAR: + case RPC_FC_SMALL: + case RPC_FC_USMALL: + safe_buffer_increment(pStubMsg, sizeof(UCHAR)); + pStubMsg->MemorySize += sizeof(UCHAR); + return sizeof(UCHAR); + case RPC_FC_WCHAR: + case RPC_FC_SHORT: + case RPC_FC_USHORT: + safe_buffer_increment(pStubMsg, sizeof(USHORT)); + pStubMsg->MemorySize += sizeof(USHORT); + return sizeof(USHORT); + case RPC_FC_LONG: + case RPC_FC_ULONG: + case RPC_FC_ENUM32: + safe_buffer_increment(pStubMsg, sizeof(ULONG)); + pStubMsg->MemorySize += sizeof(ULONG); + return sizeof(ULONG); + case RPC_FC_FLOAT: + safe_buffer_increment(pStubMsg, sizeof(float)); + pStubMsg->MemorySize += sizeof(float); + return sizeof(float); + case RPC_FC_DOUBLE: + safe_buffer_increment(pStubMsg, sizeof(double)); + pStubMsg->MemorySize += sizeof(double); + return sizeof(double); + case RPC_FC_HYPER: + safe_buffer_increment(pStubMsg, sizeof(ULONGLONG)); + pStubMsg->MemorySize += sizeof(ULONGLONG); + return sizeof(ULONGLONG); + case RPC_FC_ERROR_STATUS_T: + safe_buffer_increment(pStubMsg, sizeof(error_status_t)); + pStubMsg->MemorySize += sizeof(error_status_t); + return sizeof(error_status_t); + case RPC_FC_ENUM16: + safe_buffer_increment(pStubMsg, sizeof(USHORT)); + pStubMsg->MemorySize += sizeof(UINT); + return sizeof(UINT); + case RPC_FC_IGNORE: + pStubMsg->MemorySize += sizeof(void *); + return sizeof(void *); + default: + FIXME("Unhandled base type: 0x%02x\n", *pFormat); + return 0; + } +} + +/*********************************************************************** + * NdrBaseTypeFree [internal] + */ +static void WINAPI NdrBaseTypeFree(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + TRACE("pStubMsg %p pMemory %p type 0x%02x\n", pStubMsg, pMemory, *pFormat); + + /* nothing to do */ +} + +/*********************************************************************** + * NdrContextHandleBufferSize [internal] + */ +static void WINAPI NdrContextHandleBufferSize( + PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat); + + if (*pFormat != RPC_FC_BIND_CONTEXT) + { + ERR("invalid format type %x\n", *pFormat); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + } + ALIGN_LENGTH(pStubMsg->BufferLength, 4); + safe_buffer_length_increment(pStubMsg, cbNDRContext); +} + +/*********************************************************************** + * NdrContextHandleMarshall [internal] + */ +static unsigned char *WINAPI NdrContextHandleMarshall( + PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + TRACE("pStubMsg %p, pMemory %p, type 0x%02x\n", pStubMsg, pMemory, *pFormat); + + if (*pFormat != RPC_FC_BIND_CONTEXT) + { + ERR("invalid format type %x\n", *pFormat); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + } + + if (pFormat[1] & 0x80) + NdrClientContextMarshall(pStubMsg, *(NDR_CCONTEXT **)pMemory, FALSE); + else + NdrClientContextMarshall(pStubMsg, (NDR_CCONTEXT *)pMemory, FALSE); + + return NULL; +} + +/*********************************************************************** + * NdrContextHandleUnmarshall [internal] + */ +static unsigned char *WINAPI NdrContextHandleUnmarshall( + PMIDL_STUB_MESSAGE pStubMsg, + unsigned char **ppMemory, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) +{ + if (*pFormat != RPC_FC_BIND_CONTEXT) + { + ERR("invalid format type %x\n", *pFormat); + RpcRaiseException(RPC_S_INTERNAL_ERROR); + } + + **(NDR_CCONTEXT **)ppMemory = NULL; + NdrClientContextUnmarshall(pStubMsg, *(NDR_CCONTEXT **)ppMemory, pStubMsg->RpcMsg->Handle); + + return NULL; +} + +/*********************************************************************** + * NdrClientContextMarshall [RPCRT4.@] + */ +void WINAPI NdrClientContextMarshall(PMIDL_STUB_MESSAGE pStubMsg, + NDR_CCONTEXT ContextHandle, + int fCheck) +{ + TRACE("(%p, %p, %d)\n", pStubMsg, ContextHandle, fCheck); + + ALIGN_POINTER_CLEAR(pStubMsg->Buffer, 4); + + if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) + { + ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n", + pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + + /* FIXME: what does fCheck do? */ + NDRCContextMarshall(ContextHandle, + pStubMsg->Buffer); + + pStubMsg->Buffer += cbNDRContext; +} + +/*********************************************************************** + * NdrClientContextUnmarshall [RPCRT4.@] + */ +void WINAPI NdrClientContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + NDR_CCONTEXT * pContextHandle, + RPC_BINDING_HANDLE BindHandle) +{ + TRACE("(%p, %p, %p)\n", pStubMsg, pContextHandle, BindHandle); + + ALIGN_POINTER(pStubMsg->Buffer, 4); + + if (pStubMsg->Buffer + cbNDRContext > pStubMsg->BufferEnd) + RpcRaiseException(RPC_X_BAD_STUB_DATA); + + NDRCContextUnmarshall(pContextHandle, + BindHandle, + pStubMsg->Buffer, + pStubMsg->RpcMsg->DataRepresentation); + + pStubMsg->Buffer += cbNDRContext; +} + +void WINAPI NdrServerContextMarshall(PMIDL_STUB_MESSAGE pStubMsg, + NDR_SCONTEXT ContextHandle, + NDR_RUNDOWN RundownRoutine ) +{ + TRACE("(%p, %p, %p)\n", pStubMsg, ContextHandle, RundownRoutine); + + ALIGN_POINTER(pStubMsg->Buffer, 4); + + if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) + { + ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n", + pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + + NDRSContextMarshall2(pStubMsg->RpcMsg->Handle, ContextHandle, + pStubMsg->Buffer, RundownRoutine, NULL, 0); + pStubMsg->Buffer += cbNDRContext; +} + +NDR_SCONTEXT WINAPI NdrServerContextUnmarshall(PMIDL_STUB_MESSAGE pStubMsg) +{ + NDR_SCONTEXT ContextHandle; + + TRACE("(%p)\n", pStubMsg); + + ALIGN_POINTER(pStubMsg->Buffer, 4); + + if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) + { + ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n", + pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + + ContextHandle = NDRSContextUnmarshall2(pStubMsg->RpcMsg->Handle, + pStubMsg->Buffer, + pStubMsg->RpcMsg->DataRepresentation, + NULL, 0); + pStubMsg->Buffer += cbNDRContext; + + return ContextHandle; +} + +void WINAPI NdrContextHandleSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char* pMemory, + PFORMAT_STRING pFormat) +{ + FIXME("(%p, %p, %p): stub\n", pStubMsg, pMemory, pFormat); +} + +NDR_SCONTEXT WINAPI NdrContextHandleInitialize(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + TRACE("(%p, %p)\n", pStubMsg, pFormat); + return NDRSContextUnmarshall2(pStubMsg->RpcMsg->Handle, NULL, + pStubMsg->RpcMsg->DataRepresentation, NULL, 0); +} + +void WINAPI NdrServerContextNewMarshall(PMIDL_STUB_MESSAGE pStubMsg, + NDR_SCONTEXT ContextHandle, + NDR_RUNDOWN RundownRoutine, + PFORMAT_STRING pFormat) +{ + TRACE("(%p, %p, %p, %p)\n", pStubMsg, ContextHandle, RundownRoutine, pFormat); + + ALIGN_POINTER(pStubMsg->Buffer, 4); + + if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) + { + ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n", + pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + + /* FIXME: do something with pFormat */ + NDRSContextMarshall2(pStubMsg->RpcMsg->Handle, ContextHandle, + pStubMsg->Buffer, RundownRoutine, NULL, 0); + pStubMsg->Buffer += cbNDRContext; +} + +NDR_SCONTEXT WINAPI NdrServerContextNewUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + NDR_SCONTEXT ContextHandle; + + TRACE("(%p, %p)\n", pStubMsg, pFormat); + + ALIGN_POINTER(pStubMsg->Buffer, 4); + + if (pStubMsg->Buffer + cbNDRContext > (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) + { + ERR("buffer overflow - Buffer = %p, BufferEnd = %p\n", + pStubMsg->Buffer, (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + + /* FIXME: do something with pFormat */ + ContextHandle = NDRSContextUnmarshall2(pStubMsg->RpcMsg->Handle, + pStubMsg->Buffer, + pStubMsg->RpcMsg->DataRepresentation, + NULL, 0); + pStubMsg->Buffer += cbNDRContext; + + return ContextHandle; +} diff --git a/reactos/dll/win32/rpcrt4_new/ndr_misc.h b/reactos/dll/win32/rpcrt4_new/ndr_misc.h index 45dbd87624b..ebd70b8d826 100644 --- a/reactos/dll/win32/rpcrt4_new/ndr_misc.h +++ b/reactos/dll/win32/rpcrt4_new/ndr_misc.h @@ -1,65 +1,65 @@ -/* - * NDR definitions - * - * Copyright 2001 Ove Kåven, TransGaming Technologies - * - * 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 - */ - -#ifndef __WINE_NDR_MISC_H -#define __WINE_NDR_MISC_H - -#include - -#include "windef.h" -#include "winbase.h" -#include "rpc.h" -#include "rpcndr.h" - -struct IPSFactoryBuffer; - -PFORMAT_STRING ComputeConformanceOrVariance( - MIDL_STUB_MESSAGE *pStubMsg, unsigned char *pMemory, - PFORMAT_STRING pFormat, ULONG_PTR def, ULONG_PTR *pCount); - -static inline PFORMAT_STRING ComputeConformance(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat, ULONG def) -{ - return ComputeConformanceOrVariance(pStubMsg, pMemory, pFormat, def, &pStubMsg->MaxCount); -} - -static inline PFORMAT_STRING ComputeVariance(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat, ULONG def) -{ - PFORMAT_STRING ret; - ULONG_PTR ActualCount = pStubMsg->ActualCount; - - pStubMsg->Offset = 0; - ret = ComputeConformanceOrVariance(pStubMsg, pMemory, pFormat, def, &ActualCount); - pStubMsg->ActualCount = (ULONG)ActualCount; - return ret; -} - -typedef unsigned char* (WINAPI *NDR_MARSHALL) (PMIDL_STUB_MESSAGE, unsigned char*, PFORMAT_STRING); -typedef unsigned char* (WINAPI *NDR_UNMARSHALL)(PMIDL_STUB_MESSAGE, unsigned char**,PFORMAT_STRING, unsigned char); -typedef void (WINAPI *NDR_BUFFERSIZE)(PMIDL_STUB_MESSAGE, unsigned char*, PFORMAT_STRING); -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[]; - -#endif /* __WINE_NDR_MISC_H */ +/* + * NDR definitions + * + * Copyright 2001 Ove Kåven, TransGaming Technologies + * + * 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 + */ + +#ifndef __WINE_NDR_MISC_H +#define __WINE_NDR_MISC_H + +#include + +#include "windef.h" +#include "winbase.h" +#include "rpc.h" +#include "rpcndr.h" + +struct IPSFactoryBuffer; + +PFORMAT_STRING ComputeConformanceOrVariance( + MIDL_STUB_MESSAGE *pStubMsg, unsigned char *pMemory, + PFORMAT_STRING pFormat, ULONG_PTR def, ULONG_PTR *pCount); + +static inline PFORMAT_STRING ComputeConformance(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat, ULONG def) +{ + return ComputeConformanceOrVariance(pStubMsg, pMemory, pFormat, def, &pStubMsg->MaxCount); +} + +static inline PFORMAT_STRING ComputeVariance(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat, ULONG def) +{ + PFORMAT_STRING ret; + ULONG_PTR ActualCount = pStubMsg->ActualCount; + + pStubMsg->Offset = 0; + ret = ComputeConformanceOrVariance(pStubMsg, pMemory, pFormat, def, &ActualCount); + pStubMsg->ActualCount = (ULONG)ActualCount; + return ret; +} + +typedef unsigned char* (WINAPI *NDR_MARSHALL) (PMIDL_STUB_MESSAGE, unsigned char*, PFORMAT_STRING); +typedef unsigned char* (WINAPI *NDR_UNMARSHALL)(PMIDL_STUB_MESSAGE, unsigned char**,PFORMAT_STRING, unsigned char); +typedef void (WINAPI *NDR_BUFFERSIZE)(PMIDL_STUB_MESSAGE, unsigned char*, PFORMAT_STRING); +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[]; + +#endif /* __WINE_NDR_MISC_H */ diff --git a/reactos/dll/win32/rpcrt4_new/ndr_ole.c b/reactos/dll/win32/rpcrt4_new/ndr_ole.c index 8b37432e1e7..5c1845a2e1d 100644 --- a/reactos/dll/win32/rpcrt4_new/ndr_ole.c +++ b/reactos/dll/win32/rpcrt4_new/ndr_ole.c @@ -1,393 +1,393 @@ -/* - * OLE32 callouts, COM interface marshalling - * - * Copyright 2001 Ove Kåven, TransGaming Technologies - * - * 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 - * - * TODO: - * - fix the wire-protocol to match MS/RPC - * - finish RpcStream_Vtbl - */ - -#include -#include -#include - -#define COBJMACROS -#define NONAMELESSUNION -#define NONAMELESSSTRUCT - -#include "windef.h" -#include "winbase.h" -#include "winerror.h" - -#include "objbase.h" - -#include "ndr_misc.h" -#include "rpcndr.h" -#include "rpcproxy.h" -#include "wine/rpcfc.h" -#include "cpsf.h" - -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(ole); - -static HMODULE hOLE; - -static HRESULT (WINAPI *COM_GetMarshalSizeMax)(ULONG *,REFIID,LPUNKNOWN,DWORD,LPVOID,DWORD); -static HRESULT (WINAPI *COM_MarshalInterface)(LPSTREAM,REFIID,LPUNKNOWN,DWORD,LPVOID,DWORD); -static HRESULT (WINAPI *COM_UnmarshalInterface)(LPSTREAM,REFIID,LPVOID*); -static HRESULT (WINAPI *COM_ReleaseMarshalData)(LPSTREAM); -static HRESULT (WINAPI *COM_GetClassObject)(REFCLSID,DWORD,COSERVERINFO *,REFIID,LPVOID *); -static HRESULT (WINAPI *COM_GetPSClsid)(REFIID,CLSID *); -static LPVOID (WINAPI *COM_MemAlloc)(ULONG); -static void (WINAPI *COM_MemFree)(LPVOID); - -static HMODULE LoadCOM(void) -{ - if (hOLE) return hOLE; - hOLE = LoadLibraryA("OLE32.DLL"); - if (!hOLE) return 0; - COM_GetMarshalSizeMax = (LPVOID)GetProcAddress(hOLE, "CoGetMarshalSizeMax"); - COM_MarshalInterface = (LPVOID)GetProcAddress(hOLE, "CoMarshalInterface"); - COM_UnmarshalInterface = (LPVOID)GetProcAddress(hOLE, "CoUnmarshalInterface"); - COM_ReleaseMarshalData = (LPVOID)GetProcAddress(hOLE, "CoReleaseMarshalData"); - COM_GetClassObject = (LPVOID)GetProcAddress(hOLE, "CoGetClassObject"); - COM_GetPSClsid = (LPVOID)GetProcAddress(hOLE, "CoGetPSClsid"); - COM_MemAlloc = (LPVOID)GetProcAddress(hOLE, "CoTaskMemAlloc"); - COM_MemFree = (LPVOID)GetProcAddress(hOLE, "CoTaskMemFree"); - return hOLE; -} - -/* CoMarshalInterface/CoUnmarshalInterface works on streams, - * so implement a simple stream on top of the RPC buffer - * (which also implements the MInterfacePointer structure) */ -typedef struct RpcStreamImpl -{ - const IStreamVtbl *lpVtbl; - DWORD RefCount; - PMIDL_STUB_MESSAGE pMsg; - LPDWORD size; - unsigned char *data; - DWORD pos; -} RpcStreamImpl; - -static HRESULT WINAPI RpcStream_QueryInterface(LPSTREAM iface, - REFIID riid, - LPVOID *obj) -{ - RpcStreamImpl *This = (RpcStreamImpl *)iface; - if (IsEqualGUID(&IID_IUnknown, riid) || - IsEqualGUID(&IID_ISequentialStream, riid) || - IsEqualGUID(&IID_IStream, riid)) { - *obj = This; - This->RefCount++; - return S_OK; - } - return E_NOINTERFACE; -} - -static ULONG WINAPI RpcStream_AddRef(LPSTREAM iface) -{ - RpcStreamImpl *This = (RpcStreamImpl *)iface; - return ++(This->RefCount); -} - -static ULONG WINAPI RpcStream_Release(LPSTREAM iface) -{ - RpcStreamImpl *This = (RpcStreamImpl *)iface; - if (!--(This->RefCount)) { - TRACE("size=%d\n", *This->size); - This->pMsg->Buffer = (unsigned char*)This->data + *This->size; - HeapFree(GetProcessHeap(),0,This); - return 0; - } - return This->RefCount; -} - -static HRESULT WINAPI RpcStream_Read(LPSTREAM iface, - void *pv, - ULONG cb, - ULONG *pcbRead) -{ - RpcStreamImpl *This = (RpcStreamImpl *)iface; - HRESULT hr = S_OK; - if (This->pos + cb > *This->size) - { - cb = *This->size - This->pos; - hr = S_FALSE; - } - if (cb) { - memcpy(pv, This->data + This->pos, cb); - This->pos += cb; - } - if (pcbRead) *pcbRead = cb; - return hr; -} - -static HRESULT WINAPI RpcStream_Write(LPSTREAM iface, - const void *pv, - ULONG cb, - ULONG *pcbWritten) -{ - RpcStreamImpl *This = (RpcStreamImpl *)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); - This->pos += cb; - if (This->pos > *This->size) *This->size = This->pos; - if (pcbWritten) *pcbWritten = cb; - return S_OK; -} - -static HRESULT WINAPI RpcStream_Seek(LPSTREAM iface, - LARGE_INTEGER move, - DWORD origin, - ULARGE_INTEGER *newPos) -{ - RpcStreamImpl *This = (RpcStreamImpl *)iface; - switch (origin) { - case STREAM_SEEK_SET: - This->pos = move.u.LowPart; - break; - case STREAM_SEEK_CUR: - This->pos = This->pos + move.u.LowPart; - break; - case STREAM_SEEK_END: - This->pos = *This->size + move.u.LowPart; - break; - default: - return STG_E_INVALIDFUNCTION; - } - if (newPos) { - newPos->u.LowPart = This->pos; - newPos->u.HighPart = 0; - } - return S_OK; -} - -static HRESULT WINAPI RpcStream_SetSize(LPSTREAM iface, - ULARGE_INTEGER newSize) -{ - RpcStreamImpl *This = (RpcStreamImpl *)iface; - *This->size = newSize.u.LowPart; - return S_OK; -} - -static const IStreamVtbl RpcStream_Vtbl = -{ - RpcStream_QueryInterface, - RpcStream_AddRef, - RpcStream_Release, - RpcStream_Read, - RpcStream_Write, - RpcStream_Seek, - RpcStream_SetSize, - NULL, /* CopyTo */ - NULL, /* Commit */ - NULL, /* Revert */ - NULL, /* LockRegion */ - NULL, /* UnlockRegion */ - NULL, /* Stat */ - NULL /* Clone */ -}; - -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->RefCount = 1; - This->pMsg = pStubMsg; - This->size = (LPDWORD)pStubMsg->Buffer; - This->data = (unsigned char*)(This->size + 1); - This->pos = 0; - if (init) *This->size = 0; - TRACE("init size=%d\n", *This->size); - return (LPSTREAM)This; -} - -static const IID* get_ip_iid(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat) -{ - const IID *riid; - if (!pFormat) return &IID_IUnknown; - TRACE("format=%02x %02x\n", pFormat[0], pFormat[1]); - if (pFormat[0] != RPC_FC_IP) FIXME("format=%d\n", pFormat[0]); - if (pFormat[1] == RPC_FC_CONSTANT_IID) { - riid = (const IID *)&pFormat[2]; - } else { - ComputeConformance(pStubMsg, pMemory, pFormat+2, 0); - riid = (const IID *)pStubMsg->MaxCount; - } - if (!riid) riid = &IID_IUnknown; - TRACE("got %s\n", debugstr_guid(riid)); - return riid; -} - -/*********************************************************************** - * NdrInterfacePointerMarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrInterfacePointerMarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - const IID *riid = get_ip_iid(pStubMsg, pMemory, pFormat); - LPSTREAM stream; - HRESULT hr; - - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - pStubMsg->MaxCount = 0; - if (!LoadCOM()) return NULL; - if (pStubMsg->Buffer + sizeof(DWORD) <= (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) { - stream = RpcStream_Create(pStubMsg, TRUE); - if (stream) { - if (pMemory) - hr = COM_MarshalInterface(stream, riid, (LPUNKNOWN)pMemory, - pStubMsg->dwDestContext, pStubMsg->pvDestContext, - MSHLFLAGS_NORMAL); - else - hr = S_OK; - - IStream_Release(stream); - if (FAILED(hr)) - RpcRaiseException(hr); - } - } - return NULL; -} - -/*********************************************************************** - * NdrInterfacePointerUnmarshall [RPCRT4.@] - */ -unsigned char * WINAPI NdrInterfacePointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char **ppMemory, - PFORMAT_STRING pFormat, - unsigned char fMustAlloc) -{ - LPSTREAM stream; - HRESULT hr; - - TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); - if (!LoadCOM()) return NULL; - *(LPVOID*)ppMemory = NULL; - if (pStubMsg->Buffer + sizeof(DWORD) < (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) { - stream = RpcStream_Create(pStubMsg, FALSE); - if (!stream) RpcRaiseException(E_OUTOFMEMORY); - if (*((RpcStreamImpl *)stream)->size != 0) - hr = COM_UnmarshalInterface(stream, &IID_NULL, (LPVOID*)ppMemory); - else - hr = S_OK; - IStream_Release(stream); - if (FAILED(hr)) - RpcRaiseException(hr); - } - return NULL; -} - -/*********************************************************************** - * NdrInterfacePointerBufferSize [RPCRT4.@] - */ -void WINAPI NdrInterfacePointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - 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); - TRACE("size=%d\n", size); - pStubMsg->BufferLength += sizeof(DWORD) + size; -} - -/*********************************************************************** - * NdrInterfacePointerMemorySize [RPCRT4.@] - */ -ULONG WINAPI NdrInterfacePointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat) -{ - ULONG size; - - TRACE("(%p,%p)\n", pStubMsg, pFormat); - - size = *(ULONG *)pStubMsg->Buffer; - pStubMsg->Buffer += 4; - pStubMsg->MemorySize += 4; - - pStubMsg->Buffer += size; - - return pStubMsg->MemorySize; -} - -/*********************************************************************** - * NdrInterfacePointerFree [RPCRT4.@] - */ -void WINAPI NdrInterfacePointerFree(PMIDL_STUB_MESSAGE pStubMsg, - unsigned char *pMemory, - PFORMAT_STRING pFormat) -{ - LPUNKNOWN pUnk = (LPUNKNOWN)pMemory; - TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); - if (pUnk) IUnknown_Release(pUnk); -} - -/*********************************************************************** - * NdrOleAllocate [RPCRT4.@] - */ -void * WINAPI NdrOleAllocate(size_t Size) -{ - if (!LoadCOM()) return NULL; - return COM_MemAlloc(Size); -} - -/*********************************************************************** - * NdrOleFree [RPCRT4.@] - */ -void WINAPI NdrOleFree(void *NodeToFree) -{ - if (!LoadCOM()) return; - COM_MemFree(NodeToFree); -} - -/*********************************************************************** - * Helper function to create a stub. - * This probably looks very much like NdrpCreateStub. - */ -HRESULT create_stub(REFIID iid, IUnknown *pUnk, IRpcStubBuffer **ppstub) -{ - CLSID clsid; - IPSFactoryBuffer *psfac; - HRESULT r; - - if(!LoadCOM()) return E_FAIL; - - r = COM_GetPSClsid( iid, &clsid ); - if(FAILED(r)) return r; - - r = COM_GetClassObject( &clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IPSFactoryBuffer, (void**)&psfac ); - if(FAILED(r)) return r; - - r = IPSFactoryBuffer_CreateStub(psfac, iid, pUnk, ppstub); - - IPSFactoryBuffer_Release(psfac); - return r; -} +/* + * OLE32 callouts, COM interface marshalling + * + * Copyright 2001 Ove Kåven, TransGaming Technologies + * + * 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 + * + * TODO: + * - fix the wire-protocol to match MS/RPC + * - finish RpcStream_Vtbl + */ + +#include +#include +#include + +#define COBJMACROS +#define NONAMELESSUNION +#define NONAMELESSSTRUCT + +#include "windef.h" +#include "winbase.h" +#include "winerror.h" + +#include "objbase.h" + +#include "ndr_misc.h" +#include "rpcndr.h" +#include "rpcproxy.h" +#include "wine/rpcfc.h" +#include "cpsf.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(ole); + +static HMODULE hOLE; + +static HRESULT (WINAPI *COM_GetMarshalSizeMax)(ULONG *,REFIID,LPUNKNOWN,DWORD,LPVOID,DWORD); +static HRESULT (WINAPI *COM_MarshalInterface)(LPSTREAM,REFIID,LPUNKNOWN,DWORD,LPVOID,DWORD); +static HRESULT (WINAPI *COM_UnmarshalInterface)(LPSTREAM,REFIID,LPVOID*); +static HRESULT (WINAPI *COM_ReleaseMarshalData)(LPSTREAM); +static HRESULT (WINAPI *COM_GetClassObject)(REFCLSID,DWORD,COSERVERINFO *,REFIID,LPVOID *); +static HRESULT (WINAPI *COM_GetPSClsid)(REFIID,CLSID *); +static LPVOID (WINAPI *COM_MemAlloc)(ULONG); +static void (WINAPI *COM_MemFree)(LPVOID); + +static HMODULE LoadCOM(void) +{ + if (hOLE) return hOLE; + hOLE = LoadLibraryA("OLE32.DLL"); + if (!hOLE) return 0; + COM_GetMarshalSizeMax = (LPVOID)GetProcAddress(hOLE, "CoGetMarshalSizeMax"); + COM_MarshalInterface = (LPVOID)GetProcAddress(hOLE, "CoMarshalInterface"); + COM_UnmarshalInterface = (LPVOID)GetProcAddress(hOLE, "CoUnmarshalInterface"); + COM_ReleaseMarshalData = (LPVOID)GetProcAddress(hOLE, "CoReleaseMarshalData"); + COM_GetClassObject = (LPVOID)GetProcAddress(hOLE, "CoGetClassObject"); + COM_GetPSClsid = (LPVOID)GetProcAddress(hOLE, "CoGetPSClsid"); + COM_MemAlloc = (LPVOID)GetProcAddress(hOLE, "CoTaskMemAlloc"); + COM_MemFree = (LPVOID)GetProcAddress(hOLE, "CoTaskMemFree"); + return hOLE; +} + +/* CoMarshalInterface/CoUnmarshalInterface works on streams, + * so implement a simple stream on top of the RPC buffer + * (which also implements the MInterfacePointer structure) */ +typedef struct RpcStreamImpl +{ + const IStreamVtbl *lpVtbl; + DWORD RefCount; + PMIDL_STUB_MESSAGE pMsg; + LPDWORD size; + unsigned char *data; + DWORD pos; +} RpcStreamImpl; + +static HRESULT WINAPI RpcStream_QueryInterface(LPSTREAM iface, + REFIID riid, + LPVOID *obj) +{ + RpcStreamImpl *This = (RpcStreamImpl *)iface; + if (IsEqualGUID(&IID_IUnknown, riid) || + IsEqualGUID(&IID_ISequentialStream, riid) || + IsEqualGUID(&IID_IStream, riid)) { + *obj = This; + This->RefCount++; + return S_OK; + } + return E_NOINTERFACE; +} + +static ULONG WINAPI RpcStream_AddRef(LPSTREAM iface) +{ + RpcStreamImpl *This = (RpcStreamImpl *)iface; + return ++(This->RefCount); +} + +static ULONG WINAPI RpcStream_Release(LPSTREAM iface) +{ + RpcStreamImpl *This = (RpcStreamImpl *)iface; + if (!--(This->RefCount)) { + TRACE("size=%d\n", *This->size); + This->pMsg->Buffer = (unsigned char*)This->data + *This->size; + HeapFree(GetProcessHeap(),0,This); + return 0; + } + return This->RefCount; +} + +static HRESULT WINAPI RpcStream_Read(LPSTREAM iface, + void *pv, + ULONG cb, + ULONG *pcbRead) +{ + RpcStreamImpl *This = (RpcStreamImpl *)iface; + HRESULT hr = S_OK; + if (This->pos + cb > *This->size) + { + cb = *This->size - This->pos; + hr = S_FALSE; + } + if (cb) { + memcpy(pv, This->data + This->pos, cb); + This->pos += cb; + } + if (pcbRead) *pcbRead = cb; + return hr; +} + +static HRESULT WINAPI RpcStream_Write(LPSTREAM iface, + const void *pv, + ULONG cb, + ULONG *pcbWritten) +{ + RpcStreamImpl *This = (RpcStreamImpl *)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); + This->pos += cb; + if (This->pos > *This->size) *This->size = This->pos; + if (pcbWritten) *pcbWritten = cb; + return S_OK; +} + +static HRESULT WINAPI RpcStream_Seek(LPSTREAM iface, + LARGE_INTEGER move, + DWORD origin, + ULARGE_INTEGER *newPos) +{ + RpcStreamImpl *This = (RpcStreamImpl *)iface; + switch (origin) { + case STREAM_SEEK_SET: + This->pos = move.u.LowPart; + break; + case STREAM_SEEK_CUR: + This->pos = This->pos + move.u.LowPart; + break; + case STREAM_SEEK_END: + This->pos = *This->size + move.u.LowPart; + break; + default: + return STG_E_INVALIDFUNCTION; + } + if (newPos) { + newPos->u.LowPart = This->pos; + newPos->u.HighPart = 0; + } + return S_OK; +} + +static HRESULT WINAPI RpcStream_SetSize(LPSTREAM iface, + ULARGE_INTEGER newSize) +{ + RpcStreamImpl *This = (RpcStreamImpl *)iface; + *This->size = newSize.u.LowPart; + return S_OK; +} + +static const IStreamVtbl RpcStream_Vtbl = +{ + RpcStream_QueryInterface, + RpcStream_AddRef, + RpcStream_Release, + RpcStream_Read, + RpcStream_Write, + RpcStream_Seek, + RpcStream_SetSize, + NULL, /* CopyTo */ + NULL, /* Commit */ + NULL, /* Revert */ + NULL, /* LockRegion */ + NULL, /* UnlockRegion */ + NULL, /* Stat */ + NULL /* Clone */ +}; + +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->RefCount = 1; + This->pMsg = pStubMsg; + This->size = (LPDWORD)pStubMsg->Buffer; + This->data = (unsigned char*)(This->size + 1); + This->pos = 0; + if (init) *This->size = 0; + TRACE("init size=%d\n", *This->size); + return (LPSTREAM)This; +} + +static const IID* get_ip_iid(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat) +{ + const IID *riid; + if (!pFormat) return &IID_IUnknown; + TRACE("format=%02x %02x\n", pFormat[0], pFormat[1]); + if (pFormat[0] != RPC_FC_IP) FIXME("format=%d\n", pFormat[0]); + if (pFormat[1] == RPC_FC_CONSTANT_IID) { + riid = (const IID *)&pFormat[2]; + } else { + ComputeConformance(pStubMsg, pMemory, pFormat+2, 0); + riid = (const IID *)pStubMsg->MaxCount; + } + if (!riid) riid = &IID_IUnknown; + TRACE("got %s\n", debugstr_guid(riid)); + return riid; +} + +/*********************************************************************** + * NdrInterfacePointerMarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrInterfacePointerMarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + const IID *riid = get_ip_iid(pStubMsg, pMemory, pFormat); + LPSTREAM stream; + HRESULT hr; + + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + pStubMsg->MaxCount = 0; + if (!LoadCOM()) return NULL; + if (pStubMsg->Buffer + sizeof(DWORD) <= (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) { + stream = RpcStream_Create(pStubMsg, TRUE); + if (stream) { + if (pMemory) + hr = COM_MarshalInterface(stream, riid, (LPUNKNOWN)pMemory, + pStubMsg->dwDestContext, pStubMsg->pvDestContext, + MSHLFLAGS_NORMAL); + else + hr = S_OK; + + IStream_Release(stream); + if (FAILED(hr)) + RpcRaiseException(hr); + } + } + return NULL; +} + +/*********************************************************************** + * NdrInterfacePointerUnmarshall [RPCRT4.@] + */ +unsigned char * WINAPI NdrInterfacePointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char **ppMemory, + PFORMAT_STRING pFormat, + unsigned char fMustAlloc) +{ + LPSTREAM stream; + HRESULT hr; + + TRACE("(%p,%p,%p,%d)\n", pStubMsg, ppMemory, pFormat, fMustAlloc); + if (!LoadCOM()) return NULL; + *(LPVOID*)ppMemory = NULL; + if (pStubMsg->Buffer + sizeof(DWORD) < (unsigned char *)pStubMsg->RpcMsg->Buffer + pStubMsg->BufferLength) { + stream = RpcStream_Create(pStubMsg, FALSE); + if (!stream) RpcRaiseException(E_OUTOFMEMORY); + if (*((RpcStreamImpl *)stream)->size != 0) + hr = COM_UnmarshalInterface(stream, &IID_NULL, (LPVOID*)ppMemory); + else + hr = S_OK; + IStream_Release(stream); + if (FAILED(hr)) + RpcRaiseException(hr); + } + return NULL; +} + +/*********************************************************************** + * NdrInterfacePointerBufferSize [RPCRT4.@] + */ +void WINAPI NdrInterfacePointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + 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); + TRACE("size=%d\n", size); + pStubMsg->BufferLength += sizeof(DWORD) + size; +} + +/*********************************************************************** + * NdrInterfacePointerMemorySize [RPCRT4.@] + */ +ULONG WINAPI NdrInterfacePointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat) +{ + ULONG size; + + TRACE("(%p,%p)\n", pStubMsg, pFormat); + + size = *(ULONG *)pStubMsg->Buffer; + pStubMsg->Buffer += 4; + pStubMsg->MemorySize += 4; + + pStubMsg->Buffer += size; + + return pStubMsg->MemorySize; +} + +/*********************************************************************** + * NdrInterfacePointerFree [RPCRT4.@] + */ +void WINAPI NdrInterfacePointerFree(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char *pMemory, + PFORMAT_STRING pFormat) +{ + LPUNKNOWN pUnk = (LPUNKNOWN)pMemory; + TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat); + if (pUnk) IUnknown_Release(pUnk); +} + +/*********************************************************************** + * NdrOleAllocate [RPCRT4.@] + */ +void * WINAPI NdrOleAllocate(size_t Size) +{ + if (!LoadCOM()) return NULL; + return COM_MemAlloc(Size); +} + +/*********************************************************************** + * NdrOleFree [RPCRT4.@] + */ +void WINAPI NdrOleFree(void *NodeToFree) +{ + if (!LoadCOM()) return; + COM_MemFree(NodeToFree); +} + +/*********************************************************************** + * Helper function to create a stub. + * This probably looks very much like NdrpCreateStub. + */ +HRESULT create_stub(REFIID iid, IUnknown *pUnk, IRpcStubBuffer **ppstub) +{ + CLSID clsid; + IPSFactoryBuffer *psfac; + HRESULT r; + + if(!LoadCOM()) return E_FAIL; + + r = COM_GetPSClsid( iid, &clsid ); + if(FAILED(r)) return r; + + r = COM_GetClassObject( &clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IPSFactoryBuffer, (void**)&psfac ); + if(FAILED(r)) return r; + + r = IPSFactoryBuffer_CreateStub(psfac, iid, pUnk, ppstub); + + IPSFactoryBuffer_Release(psfac); + return r; +} diff --git a/reactos/dll/win32/rpcrt4_new/ndr_stubless.c b/reactos/dll/win32/rpcrt4_new/ndr_stubless.c index 0ca78c554f0..c21b8098198 100644 --- a/reactos/dll/win32/rpcrt4_new/ndr_stubless.c +++ b/reactos/dll/win32/rpcrt4_new/ndr_stubless.c @@ -1,1452 +1,1452 @@ -/* - * NDR -Oi,-Oif,-Oicf Interpreter - * - * Copyright 2001 Ove Kåven, TransGaming Technologies - * Copyright 2003-5 Robert Shearman (for CodeWeavers) - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - * - * TODO: - * - Pipes - * - Some types of binding handles - */ - -#include "config.h" -#include "wine/port.h" - -#include -#include -#include - -#include "windef.h" -#include "winbase.h" -#include "winerror.h" - -#include "objbase.h" -#include "rpc.h" -#include "rpcproxy.h" -#include "ndrtypes.h" - -#include "wine/debug.h" -#include "wine/rpcfc.h" - -#include "cpsf.h" -#include "ndr_misc.h" -#include "ndr_stubless.h" - -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) -{ - NDR_BUFFERSIZE m = NdrBufferSizer[pFormat[0] & NDR_TABLE_MASK]; - if (m) m(pStubMsg, pMemory, pFormat); - else - { - FIXME("format type 0x%x not implemented\n", pFormat[0]); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - } -} - -static inline unsigned char *call_marshaller(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat) -{ - NDR_MARSHALL m = NdrMarshaller[pFormat[0] & NDR_TABLE_MASK]; - if (m) return m(pStubMsg, pMemory, pFormat); - else - { - FIXME("format type 0x%x not implemented\n", pFormat[0]); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - return NULL; - } -} - -static inline unsigned char *call_unmarshaller(PMIDL_STUB_MESSAGE pStubMsg, unsigned char **ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc) -{ - NDR_UNMARSHALL m = NdrUnmarshaller[pFormat[0] & NDR_TABLE_MASK]; - if (m) return m(pStubMsg, ppMemory, pFormat, fMustAlloc); - else - { - FIXME("format type 0x%x not implemented\n", pFormat[0]); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - return NULL; - } -} - -static inline void call_freer(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat) -{ - NDR_FREE m = NdrFreer[pFormat[0] & NDR_TABLE_MASK]; - if (m) m(pStubMsg, pMemory, pFormat); -} - -static inline unsigned long call_memory_sizer(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat) -{ - NDR_MEMORYSIZE m = NdrMemorySizer[pFormat[0] & NDR_TABLE_MASK]; - if (m) - { - unsigned char *saved_buffer = pStubMsg->Buffer; - unsigned long ret; - int saved_ignore_embedded_pointers = pStubMsg->IgnoreEmbeddedPointers; - pStubMsg->MemorySize = 0; - pStubMsg->IgnoreEmbeddedPointers = 1; - ret = m(pStubMsg, pFormat); - pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded_pointers; - pStubMsg->Buffer = saved_buffer; - return ret; - } - else - { - FIXME("format type 0x%x not implemented\n", pFormat[0]); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - return 0; - } -} - -#define STUBLESS_UNMARSHAL 1 -#define STUBLESS_CALLSERVER 2 -#define STUBLESS_CALCSIZE 3 -#define STUBLESS_GETBUFFER 4 -#define STUBLESS_MARSHAL 5 -#define STUBLESS_FREE 6 - -void WINAPI NdrRpcSmSetClientToOsf(PMIDL_STUB_MESSAGE pMessage) -{ -#if 0 /* these functions are not defined yet */ - pMessage->pfnAllocate = NdrRpcSmClientAllocate; - pMessage->pfnFree = NdrRpcSmClientFree; -#endif -} - -static void WINAPI dump_RPC_FC_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); -} - -static void WINAPI dump_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"); -} - -#define ARG_FROM_OFFSET(stubMsg, offset) ((stubMsg).StackTop + (offset)) - -static PFORMAT_STRING client_get_handle( - PMIDL_STUB_MESSAGE pStubMsg, const NDR_PROC_HEADER *pProcHeader, - PFORMAT_STRING pFormat, handle_t *phBinding) -{ - /* binding */ - switch (pProcHeader->handle_type) - { - /* explicit binding: parse additional section */ - case RPC_FC_BIND_EXPLICIT: - switch (*pFormat) /* handle_type */ - { - case RPC_FC_BIND_PRIMITIVE: /* explicit primitive */ - { - const NDR_EHD_PRIMITIVE *pDesc = (const NDR_EHD_PRIMITIVE *)pFormat; - - TRACE("Explicit primitive handle @ %d\n", pDesc->offset); - - if (pDesc->flag) /* pointer to binding */ - *phBinding = **(handle_t **)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset); - else - *phBinding = *(handle_t *)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset); - return pFormat + sizeof(NDR_EHD_PRIMITIVE); - } - case RPC_FC_BIND_GENERIC: /* explicit generic */ - { - const NDR_EHD_GENERIC *pDesc = (const NDR_EHD_GENERIC *)pFormat; - void *pObject = NULL; - void *pArg; - const GENERIC_BINDING_ROUTINE_PAIR *pGenPair; - - TRACE("Explicit generic binding handle #%d\n", pDesc->binding_routine_pair_index); - - if (pDesc->flag_and_size & HANDLE_PARAM_IS_VIA_PTR) - pArg = *(void **)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset); - else - pArg = (void *)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset); - memcpy(&pObject, pArg, pDesc->flag_and_size & 0xf); - pGenPair = &pStubMsg->StubDesc->aGenericBindingRoutinePairs[pDesc->binding_routine_pair_index]; - *phBinding = pGenPair->pfnBind(pObject); - return pFormat + sizeof(NDR_EHD_GENERIC); - } - case RPC_FC_BIND_CONTEXT: /* explicit context */ - { - const NDR_EHD_CONTEXT *pDesc = (const NDR_EHD_CONTEXT *)pFormat; - NDR_CCONTEXT context_handle; - TRACE("Explicit bind context\n"); - if (pDesc->flags & HANDLE_PARAM_IS_VIA_PTR) - { - TRACE("\tHANDLE_PARAM_IS_VIA_PTR\n"); - context_handle = **(NDR_CCONTEXT **)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset); - } - else - context_handle = *(NDR_CCONTEXT *)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset); - if ((pDesc->flags & NDR_CONTEXT_HANDLE_CANNOT_BE_NULL) && - !context_handle) - { - 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); - } - default: - ERR("bad explicit binding handle type (0x%02x)\n", pProcHeader->handle_type); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - } - break; - case RPC_FC_BIND_GENERIC: /* implicit generic */ - FIXME("RPC_FC_BIND_GENERIC\n"); - RpcRaiseException(RPC_X_BAD_STUB_DATA); /* FIXME: remove when implemented */ - break; - case RPC_FC_BIND_PRIMITIVE: /* implicit primitive */ - TRACE("Implicit primitive handle\n"); - *phBinding = *pStubMsg->StubDesc->IMPLICIT_HANDLE_INFO.pPrimitiveHandle; - break; - case RPC_FC_CALLBACK_HANDLE: /* implicit callback */ - FIXME("RPC_FC_CALLBACK_HANDLE\n"); - break; - case RPC_FC_AUTO_HANDLE: /* implicit auto handle */ - /* strictly speaking, it isn't necessary to set hBinding here - * since it isn't actually used (hence the automatic in its name), - * but then why does MIDL generate a valid entry in the - * MIDL_STUB_DESC for it? */ - TRACE("Implicit auto handle\n"); - *phBinding = *pStubMsg->StubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle; - break; - default: - ERR("bad implicit binding handle type (0x%02x)\n", pProcHeader->handle_type); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - } - return pFormat; -} - -static void client_free_handle( - PMIDL_STUB_MESSAGE pStubMsg, const NDR_PROC_HEADER *pProcHeader, - PFORMAT_STRING pFormat, handle_t hBinding) -{ - /* binding */ - switch (pProcHeader->handle_type) - { - /* explicit binding: parse additional section */ - case RPC_FC_BIND_EXPLICIT: - switch (*pFormat) /* handle_type */ - { - case RPC_FC_BIND_GENERIC: /* explicit generic */ - { - const NDR_EHD_GENERIC *pDesc = (const NDR_EHD_GENERIC *)pFormat; - void *pObject = NULL; - void *pArg; - const GENERIC_BINDING_ROUTINE_PAIR *pGenPair; - - TRACE("Explicit generic binding handle #%d\n", pDesc->binding_routine_pair_index); - - if (pDesc->flag_and_size & HANDLE_PARAM_IS_VIA_PTR) - pArg = *(void **)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset); - else - pArg = (void *)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset); - memcpy(&pObject, pArg, pDesc->flag_and_size & 0xf); - pGenPair = &pStubMsg->StubDesc->aGenericBindingRoutinePairs[pDesc->binding_routine_pair_index]; - pGenPair->pfnUnbind(pObject, hBinding); - break; - } - case RPC_FC_BIND_CONTEXT: /* explicit context */ - case RPC_FC_BIND_PRIMITIVE: /* explicit primitive */ - break; - default: - ERR("bad explicit binding handle type (0x%02x)\n", pProcHeader->handle_type); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - } - break; - case RPC_FC_BIND_GENERIC: /* implicit generic */ - FIXME("RPC_FC_BIND_GENERIC\n"); - RpcRaiseException(RPC_X_BAD_STUB_DATA); /* FIXME: remove when implemented */ - break; - case RPC_FC_CALLBACK_HANDLE: /* implicit callback */ - case RPC_FC_BIND_PRIMITIVE: /* implicit primitive */ - case RPC_FC_AUTO_HANDLE: /* implicit auto handle */ - break; - default: - ERR("bad implicit binding handle type (0x%02x)\n", pProcHeader->handle_type); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - } -} - -static void client_do_args(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, - int phase, 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; - - for (i = 0; i < number_of_params; i++) - { - const NDR_PARAM_OIF_BASETYPE *pParam = - (const NDR_PARAM_OIF_BASETYPE *)&pFormat[current_offset]; - unsigned char * pArg; - - current_stack_offset = pParam->stack_offset; - pArg = ARG_FROM_OFFSET(*pStubMsg, current_stack_offset); - - TRACE("param[%d]: new format\n", i); - TRACE("\tparam_attributes:"); dump_RPC_FC_PROC_PF(pParam->param_attributes); TRACE("\n"); - TRACE("\tstack_offset: 0x%x\n", current_stack_offset); - TRACE("\tmemory addr (before): %p\n", pArg); - - if (pParam->param_attributes.IsBasetype) - { - 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); - } - 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]); - - /* if a simple ref pointer then we have to do the - * check for the pointer being non-NULL. */ - if (pParam->param_attributes.IsSimpleRef) - { - if (!*(unsigned char **)pArg) - RpcRaiseException(RPC_X_NULL_REF_POINTER); - } - - TRACE("\tcomplex type: 0x%02x\n", *pTypeFormat); - - switch (phase) - { - 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); - } - - current_offset += sizeof(NDR_PARAM_OIF_OTHER); - } - TRACE("\tmemory addr (after): %p\n", pArg); - } -} - -static void client_do_args_old_format(PMIDL_STUB_MESSAGE pStubMsg, - PFORMAT_STRING pFormat, int phase, unsigned short stack_size, - unsigned char *pRetVal, BOOL object_proc) -{ - /* 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 does't terminate on the number_of_params - * condition as it doesn't have this attribute. Instead it - * terminates when the stack size given in the header is exceeded. - */ - for (i = 0; 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_proc ? sizeof(void *) : 0); - unsigned char * pArg = ARG_FROM_OFFSET(*pStubMsg, 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 (pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE) - { - if (pParam->param_direction & RPC_FC_RETURN_PARAM) - call_unmarshaller(pStubMsg, (unsigned char **)pRetVal, pTypeFormat, 0); - else - call_unmarshaller(pStubMsg, &pArg, pTypeFormat, 0); - } - break; - default: - RpcRaiseException(RPC_S_INTERNAL_ERROR); - } - - current_stack_offset += call_memory_sizer(pStubMsg, pTypeFormat); - current_offset += sizeof(NDR_PARAM_OI_BASETYPE); - } - else - { - const NDR_PARAM_OI_OTHER *pParamOther = - (const NDR_PARAM_OI_OTHER *)&pFormat[current_offset]; - - const unsigned char *pTypeFormat = - &pStubMsg->StubDesc->pFormatTypes[pParamOther->type_offset]; - - TRACE("\tcomplex type 0x%02x\n", *pTypeFormat); - - switch (phase) - { - case 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); - } -} - -/* the return type should be CLIENT_CALL_RETURN, but this is incompatible - * with the way gcc returns structures. "void *" should be the largest type - * that MIDL should allow you to return anyway */ -LONG_PTR WINAPIV NdrClientCall2(PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pFormat, ...) -{ - /* pointer to start of stack where arguments start */ - RPC_MESSAGE rpcMsg; - MIDL_STUB_MESSAGE stubMsg; - handle_t hBinding = NULL; - /* procedure number */ - unsigned short procedure_number; - /* size of stack */ - unsigned short stack_size; - /* number of parameters. optional for client to give it to us */ - unsigned char number_of_params = ~0; - /* 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 */ - LONG_PTR RetVal = 0; - /* the pointer to the object when in OLE mode */ - void * This = NULL; - PFORMAT_STRING pHandleFormat; - - 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); - } - - 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; - procedure_number = pProcHeader->proc_num; - pFormat += sizeof(NDR_PROC_HEADER_RPC); - } - else - { - stack_size = pProcHeader->stack_size; - procedure_number = pProcHeader->proc_num; - pFormat += sizeof(NDR_PROC_HEADER); - } - TRACE("stack size: 0x%x\n", 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) - stubMsg.FullPtrXlatTables = NdrFullPointerXlatInit(0,XLAT_CLIENT); - - if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT) - { - /* object is always the first argument */ - This = **(void *const **)(&pFormat+1); - NdrProxyInitialize(This, &rpcMsg, &stubMsg, pStubDesc, procedure_number); - } - else - NdrClientInitializeNew(&rpcMsg, &stubMsg, pStubDesc, procedure_number); - - TRACE("Oi_flags = 0x%02x\n", pProcHeader->Oi_flags); - TRACE("MIDL stub version = 0x%x\n", pStubDesc->MIDLVersion); - - /* needed for conformance of top-level objects */ -#ifdef __i386__ - stubMsg.StackTop = *(unsigned char **)(&pFormat+1); -#else -# warning Stack not retrieved for your CPU architecture -#endif - - 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 0; - } - - bV2Format = (pStubDesc->Version >= 0x20000); - - if (bV2Format) - { - const NDR_PROC_PARTIAL_OIF_HEADER *pOIFHeader = - (const NDR_PROC_PARTIAL_OIF_HEADER *)pFormat; - - Oif_flags = pOIFHeader->Oi2Flags; - number_of_params = pOIFHeader->number_of_params; - - pFormat += sizeof(NDR_PROC_PARTIAL_OIF_HEADER); - } - - TRACE("Oif_flags = "); dump_INTERPRETER_OPT_FLAGS(Oif_flags); - - if (Oif_flags.HasExtensions) - { - const NDR_PROC_HEADER_EXTS *pExtensions = - (const NDR_PROC_HEADER_EXTS *)pFormat; - ext_flags = pExtensions->Flags2; - pFormat += pExtensions->Size; - } - - stubMsg.BufferLength = 0; - - /* store the RPC flags away */ - if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS) - rpcMsg.RpcFlags = ((const NDR_PROC_HEADER_RPC *)pProcHeader)->rpc_flags; - - /* use alternate memory allocation routines */ - if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCSSALLOC) - NdrRpcSmSetClientToOsf(&stubMsg); - - 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; - } - - /* 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) - { - case PROXY_GETBUFFER: - /* allocate the buffer */ - if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT) - NdrProxyGetBuffer(This, &stubMsg); - else 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); - } - break; - case PROXY_SENDRECEIVE: - /* send the [in] params and receive the [out] and [retval] - * params */ - if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT) - NdrProxySendReceive(This, &stubMsg); - else 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 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, number_of_params, - (unsigned char *)&RetVal); - else - client_do_args_old_format(&stubMsg, pFormat, phase, stack_size, - (unsigned char *)&RetVal, - (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)); - break; - default: - ERR("shouldn't reach here. phase %d\n", phase); - break; - } - } - - if (ext_flags.HasNewCorrDesc) - { - /* free extra correlation package */ - /* NdrCorrelationFree(&stubMsg); */ - } - - if (Oif_flags.HasPipes) - { - /* NdrPipesDone(...) */ - } - - /* free the full pointer translation tables */ - if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR) - NdrFullPointerXlatFree(stubMsg.FullPtrXlatTables); - - /* free marshalling buffer */ - if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT) - NdrProxyFreeBuffer(This, &stubMsg); - else - { - NdrFreeBuffer(&stubMsg); - client_free_handle(&stubMsg, pProcHeader, pHandleFormat, hBinding); - } - - TRACE("RetVal = 0x%lx\n", RetVal); - - return RetVal; -} - -/* calls a function with the specificed arguments, restoring the stack - * properly afterwards as we don't know the calling convention of the - * function */ -#if defined __i386__ && defined _MSC_VER -__declspec(naked) LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned int stack_size) -{ - __asm - { - push ebp - push edi ; Save registers - push esi - mov ebp, esp - mov eax, [ebp+16] ; Get stack size - sub esp, eax ; Make room in stack for arguments - mov edi, esp - mov ecx, eax - mov esi, [ebp+12] - shr ecx, 2 - cld - rep movsd ; Copy dword blocks - call [ebp+8] ; Call function - lea esp, [ebp-8] ; Restore stack - pop esi ; Restore registers - pop edi - pop ebp - ret - } -} -#elif defined __i386__ && defined __GNUC__ -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" - "pushl %edi\n\t" /* Save registers */ - "pushl %esi\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 */ - "movl %esp, %edi\n\t" - "movl %eax, %ecx\n\t" - "movl 12(%ebp), %esi\n\t" - "shrl $2, %ecx\n\t" /* divide by 4 */ - "cld\n\t" - "rep; movsl\n\t" /* Copy dword blocks */ - "call *8(%ebp)\n\t" /* Call function */ - "leal -8(%ebp), %esp\n\t" /* Restore stack */ - "popl %esi\n\t" /* Restore registers */ - "popl %edi\n\t" - "popl %ebp\n\t" - "ret\n" ) -#else -#warning call_server_func not implemented for your architecture -LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned short stack_size) -{ - FIXME("Not implemented for your architecture\n"); - return 0; -} -#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; - 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, - unsigned short number_of_params) -{ - /* counter */ - unsigned short i; - /* current format string offset */ - int current_offset = 0; - /* current stack offset */ - unsigned short current_stack_offset = 0; - /* location to put retval into */ - LONG_PTR *retval_ptr = NULL; - - for (i = 0; i < number_of_params; i++) - { - const NDR_PARAM_OIF_BASETYPE *pParam = - (const NDR_PARAM_OIF_BASETYPE *)&pFormat[current_offset]; - unsigned char *pArg; - - current_stack_offset = pParam->stack_offset; - pArg = (unsigned char *)(args+current_stack_offset); - - TRACE("param[%d]: new format\n", i); - TRACE("\tparam_attributes:"); dump_RPC_FC_PROC_PF(pParam->param_attributes); TRACE("\n"); - TRACE("\tstack_offset: 0x%x\n", current_stack_offset); - TRACE("\tmemory addr (before): %p -> %p\n", pArg, *(unsigned char **)pArg); - - if (pParam->param_attributes.IsBasetype) - { - const unsigned char *pTypeFormat = - &pParam->type_format_char; - - TRACE("\tbase type: 0x%02x\n", *pTypeFormat); - - switch (phase) - { - case STUBLESS_MARSHAL: - if (pParam->param_attributes.IsOut || pParam->param_attributes.IsReturn) - { - if (pParam->param_attributes.IsSimpleRef) - call_marshaller(pStubMsg, *(unsigned char **)pArg, pTypeFormat); - else - call_marshaller(pStubMsg, pArg, pTypeFormat); - } - break; - case STUBLESS_FREE: - if (pParam->param_attributes.ServerAllocSize) - HeapFree(GetProcessHeap(), 0, *(void **)pArg); - break; - case STUBLESS_UNMARSHAL: - if (pParam->param_attributes.ServerAllocSize) - *(void **)pArg = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, - pParam->param_attributes.ServerAllocSize * 8); - - if (pParam->param_attributes.IsIn) - { - if (pParam->param_attributes.IsSimpleRef) - call_unmarshaller(pStubMsg, (unsigned char **)pArg, pTypeFormat, 0); - else - call_unmarshaller(pStubMsg, &pArg, pTypeFormat, 0); - } - - /* make a note of the address of the return value parameter for later */ - if (pParam->param_attributes.IsReturn) - retval_ptr = (LONG_PTR *)pArg; - - break; - case STUBLESS_CALCSIZE: - if (pParam->param_attributes.IsOut || pParam->param_attributes.IsReturn) - { - if (pParam->param_attributes.IsSimpleRef) - call_buffer_sizer(pStubMsg, *(unsigned char **)pArg, pTypeFormat); - else - call_buffer_sizer(pStubMsg, pArg, pTypeFormat); - } - break; - default: - RpcRaiseException(RPC_S_INTERNAL_ERROR); - } - - current_offset += sizeof(NDR_PARAM_OIF_BASETYPE); - } - else - { - const NDR_PARAM_OIF_OTHER *pParamOther = - (const NDR_PARAM_OIF_OTHER *)&pFormat[current_offset]; - - const unsigned char * pTypeFormat = - &(pStubMsg->StubDesc->pFormatTypes[pParamOther->type_offset]); - - TRACE("\tcomplex type 0x%02x\n", *pTypeFormat); - - switch (phase) - { - case STUBLESS_MARSHAL: - if (pParam->param_attributes.IsOut || pParam->param_attributes.IsReturn) - { - if (pParam->param_attributes.IsByValue) - call_marshaller(pStubMsg, pArg, pTypeFormat); - else - call_marshaller(pStubMsg, *(unsigned char **)pArg, pTypeFormat); - } - break; - case STUBLESS_FREE: - if (pParam->param_attributes.MustFree) - { - if (pParam->param_attributes.IsByValue) - call_freer(pStubMsg, pArg, pTypeFormat); - else - call_freer(pStubMsg, *(unsigned char **)pArg, pTypeFormat); - } - - if (pParam->param_attributes.IsOut && - !pParam->param_attributes.IsIn && - !pParam->param_attributes.IsByValue && - !pParam->param_attributes.ServerAllocSize) - { - pStubMsg->pfnFree(*(void **)pArg); - } - - if (pParam->param_attributes.ServerAllocSize) - HeapFree(GetProcessHeap(), 0, *(void **)pArg); - /* FIXME: call call_freer here for IN types with MustFree set */ - break; - case STUBLESS_UNMARSHAL: - if (pParam->param_attributes.ServerAllocSize) - *(void **)pArg = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, - pParam->param_attributes.ServerAllocSize * 8); - - if (pParam->param_attributes.IsIn) - { - if (pParam->param_attributes.IsByValue) - call_unmarshaller(pStubMsg, &pArg, pTypeFormat, 0); - else - call_unmarshaller(pStubMsg, (unsigned char **)pArg, pTypeFormat, 0); - } - else if (pParam->param_attributes.IsOut && - !pParam->param_attributes.ServerAllocSize && - !pParam->param_attributes.IsByValue) - { - DWORD size = calc_arg_size(pStubMsg, pTypeFormat); - - if(size) - { - *(void **)pArg = NdrAllocate(pStubMsg, size); - memset(*(void **)pArg, 0, size); - } - } - break; - case STUBLESS_CALCSIZE: - if (pParam->param_attributes.IsOut || pParam->param_attributes.IsReturn) - { - if (pParam->param_attributes.IsByValue) - call_buffer_sizer(pStubMsg, pArg, pTypeFormat); - else - call_buffer_sizer(pStubMsg, *(unsigned char **)pArg, pTypeFormat); - } - break; - default: - RpcRaiseException(RPC_S_INTERNAL_ERROR); - } - - current_offset += sizeof(NDR_PARAM_OIF_OTHER); - } - TRACE("\tmemory addr (after): %p -> %p\n", pArg, *(unsigned char **)pArg); - } - - return retval_ptr; -} - -static LONG_PTR *stub_do_old_args(MIDL_STUB_MESSAGE *pStubMsg, - PFORMAT_STRING pFormat, int phase, - unsigned char *args, - unsigned short stack_size, BOOL object) -{ - /* counter */ - unsigned short i; - /* current format string offset */ - int current_offset = 0; - /* current stack offset */ - unsigned short current_stack_offset = 0; - /* location to put retval into */ - LONG_PTR *retval_ptr = NULL; - - for (i = 0; TRUE; i++) - { - const NDR_PARAM_OI_BASETYPE *pParam = - (const NDR_PARAM_OI_BASETYPE *)&pFormat[current_offset]; - /* note: current_stack_offset starts after the This pointer - * if present, so adjust this */ - unsigned short current_stack_offset_adjusted = current_stack_offset + - (object ? sizeof(void *) : 0); - unsigned char *pArg = (unsigned char *)(args+current_stack_offset_adjusted); - - /* no more parameters; exit loop */ - if (current_stack_offset_adjusted >= stack_size) - break; - - TRACE("param[%d]: old format\n", i); - TRACE("\tparam_direction: 0x%x\n", pParam->param_direction); - TRACE("\tstack_offset: 0x%x\n", current_stack_offset_adjusted); - - if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE || - pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE) - { - const unsigned char *pTypeFormat = - &pParam->type_format_char; - - TRACE("\tbase type 0x%02x\n", *pTypeFormat); - - switch (phase) - { - case STUBLESS_MARSHAL: - if (pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE) - call_marshaller(pStubMsg, pArg, pTypeFormat); - break; - case STUBLESS_FREE: - if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE) - call_freer(pStubMsg, pArg, pTypeFormat); - break; - case STUBLESS_UNMARSHAL: - if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE) - call_unmarshaller(pStubMsg, &pArg, pTypeFormat, 0); - else if (pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE) - retval_ptr = (LONG_PTR *)pArg; - break; - case STUBLESS_CALCSIZE: - if (pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE) - call_buffer_sizer(pStubMsg, pArg, pTypeFormat); - break; - default: - RpcRaiseException(RPC_S_INTERNAL_ERROR); - } - - current_stack_offset += call_memory_sizer(pStubMsg, pTypeFormat); - current_offset += sizeof(NDR_PARAM_OI_BASETYPE); - } - else - { - const NDR_PARAM_OI_OTHER *pParamOther = - (const NDR_PARAM_OI_OTHER *)&pFormat[current_offset]; - - const unsigned char * pTypeFormat = - &pStubMsg->StubDesc->pFormatTypes[pParamOther->type_offset]; - - TRACE("\tcomplex type 0x%02x\n", *pTypeFormat); - - switch (phase) - { - case STUBLESS_MARSHAL: - if (pParam->param_direction == RPC_FC_OUT_PARAM || - pParam->param_direction == RPC_FC_IN_OUT_PARAM || - pParam->param_direction == RPC_FC_RETURN_PARAM) - call_marshaller(pStubMsg, *(unsigned char **)pArg, pTypeFormat); - break; - case STUBLESS_FREE: - if (pParam->param_direction == RPC_FC_IN_OUT_PARAM || - pParam->param_direction == RPC_FC_IN_PARAM) - call_freer(pStubMsg, *(unsigned char **)pArg, pTypeFormat); - else if (pParam->param_direction == RPC_FC_OUT_PARAM) - pStubMsg->pfnFree(*(void **)pArg); - break; - case STUBLESS_UNMARSHAL: - if (pParam->param_direction == RPC_FC_IN_OUT_PARAM || - pParam->param_direction == RPC_FC_IN_PARAM) - call_unmarshaller(pStubMsg, (unsigned char **)pArg, pTypeFormat, 0); - else if (pParam->param_direction == RPC_FC_RETURN_PARAM) - retval_ptr = (LONG_PTR *)pArg; - else if (pParam->param_direction == RPC_FC_OUT_PARAM) - { - DWORD size = calc_arg_size(pStubMsg, pTypeFormat); - - if(size) - { - *(void **)pArg = NdrAllocate(pStubMsg, size); - memset(*(void **)pArg, 0, size); - } - } - break; - case STUBLESS_CALCSIZE: - if (pParam->param_direction == RPC_FC_OUT_PARAM || - pParam->param_direction == RPC_FC_IN_OUT_PARAM || - pParam->param_direction == RPC_FC_RETURN_PARAM) - call_buffer_sizer(pStubMsg, *(unsigned char **)pArg, pTypeFormat); - break; - default: - RpcRaiseException(RPC_S_INTERNAL_ERROR); - } - - current_stack_offset += pParamOther->stack_size * sizeof(INT); - current_offset += sizeof(NDR_PARAM_OI_OTHER); - } - } - - return retval_ptr; -} - -/*********************************************************************** - * NdrStubCall2 [RPCRT4.@] - * - * Unmarshals [in] parameters, calls either a method in an object or a server - * function, marshals any [out] parameters and frees any allocated data. - * - * NOTES - * Used by stubless MIDL-generated code. - */ -LONG WINAPI NdrStubCall2( - struct IRpcStubBuffer * pThis, - struct IRpcChannelBuffer * pChannel, - PRPC_MESSAGE pRpcMsg, - DWORD * pdwStubPhase) -{ - const MIDL_SERVER_INFO *pServerInfo; - const MIDL_STUB_DESC *pStubDesc; - PFORMAT_STRING pFormat; - MIDL_STUB_MESSAGE stubMsg; - /* pointer to start of stack to pass into stub implementation */ - unsigned char * args; - /* size of stack */ - unsigned short stack_size; - /* number of parameters. optional for client to give it to us */ - unsigned char number_of_params = ~0; - /* 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; - /* 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; - - TRACE("pThis %p, pChannel %p, pRpcMsg %p, pdwStubPhase %p\n", pThis, pChannel, pRpcMsg, pdwStubPhase); - - if (pThis) - pServerInfo = CStdStubBuffer_GetServerInfo(pThis); - else - pServerInfo = ((RPC_SERVER_INTERFACE *)pRpcMsg->RpcInterfaceInformation)->InterpreterInfo; - - pStubDesc = pServerInfo->pStubDesc; - pFormat = pServerInfo->ProcString + pServerInfo->FmtStringOffset[pRpcMsg->ProcNum]; - pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0]; - - /* 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); - } - - /* 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); - - } - else - { - stack_size = pProcHeader->stack_size; - current_offset = sizeof(NDR_PROC_HEADER); - } - - TRACE("Oi_flags = 0x%02x\n", pProcHeader->Oi_flags); - - /* binding */ - switch (pProcHeader->handle_type) - { - /* explicit binding: parse additional section */ - case RPC_FC_BIND_EXPLICIT: - switch (pFormat[current_offset]) /* handle_type */ - { - case RPC_FC_BIND_PRIMITIVE: /* explicit primitive */ - current_offset += sizeof(NDR_EHD_PRIMITIVE); - break; - case RPC_FC_BIND_GENERIC: /* explicit generic */ - current_offset += sizeof(NDR_EHD_GENERIC); - break; - case RPC_FC_BIND_CONTEXT: /* explicit context */ - current_offset += sizeof(NDR_EHD_CONTEXT); - break; - default: - ERR("bad explicit binding handle type (0x%02x)\n", pProcHeader->handle_type); - RpcRaiseException(RPC_X_BAD_STUB_DATA); - } - break; - case RPC_FC_BIND_GENERIC: /* implicit generic */ - case RPC_FC_BIND_PRIMITIVE: /* implicit primitive */ - case RPC_FC_CALLBACK_HANDLE: /* implicit callback */ - case RPC_FC_AUTO_HANDLE: /* implicit auto handle */ - break; - default: - ERR("bad implicit binding handle type (0x%02x)\n", pProcHeader->handle_type); - 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); - - /* 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) -#if 0 - NdrRpcSsEnableAllocate(&stubMsg); -#else - 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); - stubMsg.StackTop = args; /* used by conformance of top-level objects */ - - /* add the implicit This pointer as the first arg to the function if we - * are calling an object method */ - 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 - */ - for (phase = STUBLESS_UNMARSHAL; phase <= STUBLESS_FREE; phase++) - { - TRACE("phase = %d\n", phase); - switch (phase) - { - case STUBLESS_CALLSERVER: - /* call the server function */ - if (pServerInfo->ThunkTable && pServerInfo->ThunkTable[pRpcMsg->ProcNum]) - pServerInfo->ThunkTable[pRpcMsg->ProcNum](&stubMsg); - else - { - SERVER_ROUTINE func; - LONG_PTR retval; - - if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT) - { - SERVER_ROUTINE *vtbl = *(SERVER_ROUTINE **)((CStdStubBuffer *)pThis)->pvServerObject; - func = vtbl[pRpcMsg->ProcNum]; - } - else - func = pServerInfo->DispatchTable[pRpcMsg->ProcNum]; - - /* FIXME: what happens with return values that don't fit into a single register on x86? */ - retval = call_server_func(func, args, stack_size); - - if (retval_ptr) - { - TRACE("stub implementation returned 0x%lx\n", retval); - *retval_ptr = retval; - } - else - TRACE("void stub implementation\n"); - } - - stubMsg.Buffer = NULL; - stubMsg.BufferLength = 0; - - break; - case STUBLESS_GETBUFFER: - if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT) - NdrStubGetBuffer(pThis, pChannel, &stubMsg); - else - { - RPC_STATUS Status; - - pRpcMsg->BufferLength = stubMsg.BufferLength; - /* allocate buffer for [out] and [ret] params */ - Status = I_RpcGetBuffer(pRpcMsg); - if (Status) - RpcRaiseException(Status); - stubMsg.BufferStart = pRpcMsg->Buffer; - stubMsg.BufferEnd = stubMsg.BufferStart + stubMsg.BufferLength; - stubMsg.Buffer = stubMsg.BufferStart; - } - break; - case STUBLESS_MARSHAL: - case STUBLESS_UNMARSHAL: - case STUBLESS_CALCSIZE: - 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)); - - break; - default: - ERR("shouldn't reach here. phase %d\n", phase); - break; - } - } - - pRpcMsg->BufferLength = (unsigned int)(stubMsg.Buffer - (unsigned char *)pRpcMsg->Buffer); - - if (ext_flags.HasNewCorrDesc) - { - /* free extra correlation package */ - /* NdrCorrelationFree(&stubMsg); */ - } - - if (Oif_flags.HasPipes) - { - /* NdrPipesDone(...) */ - } - - /* free the full pointer translation tables */ - if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR) - NdrFullPointerXlatFree(stubMsg.FullPtrXlatTables); - - /* free server function stack */ - HeapFree(GetProcessHeap(), 0, args); - - return S_OK; -} - -/*********************************************************************** - * NdrServerCall2 [RPCRT4.@] - */ -void WINAPI NdrServerCall2(PRPC_MESSAGE pRpcMsg) -{ - DWORD dwPhase; - NdrStubCall2(NULL, NULL, pRpcMsg, &dwPhase); -} +/* + * NDR -Oi,-Oif,-Oicf Interpreter + * + * Copyright 2001 Ove Kåven, TransGaming Technologies + * Copyright 2003-5 Robert Shearman (for CodeWeavers) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + * + * TODO: + * - Pipes + * - Some types of binding handles + */ + +#include "config.h" +#include "wine/port.h" + +#include +#include +#include + +#include "windef.h" +#include "winbase.h" +#include "winerror.h" + +#include "objbase.h" +#include "rpc.h" +#include "rpcproxy.h" +#include "ndrtypes.h" + +#include "wine/debug.h" +#include "wine/rpcfc.h" + +#include "cpsf.h" +#include "ndr_misc.h" +#include "ndr_stubless.h" + +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) +{ + NDR_BUFFERSIZE m = NdrBufferSizer[pFormat[0] & NDR_TABLE_MASK]; + if (m) m(pStubMsg, pMemory, pFormat); + else + { + FIXME("format type 0x%x not implemented\n", pFormat[0]); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } +} + +static inline unsigned char *call_marshaller(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat) +{ + NDR_MARSHALL m = NdrMarshaller[pFormat[0] & NDR_TABLE_MASK]; + if (m) return m(pStubMsg, pMemory, pFormat); + else + { + FIXME("format type 0x%x not implemented\n", pFormat[0]); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + return NULL; + } +} + +static inline unsigned char *call_unmarshaller(PMIDL_STUB_MESSAGE pStubMsg, unsigned char **ppMemory, PFORMAT_STRING pFormat, unsigned char fMustAlloc) +{ + NDR_UNMARSHALL m = NdrUnmarshaller[pFormat[0] & NDR_TABLE_MASK]; + if (m) return m(pStubMsg, ppMemory, pFormat, fMustAlloc); + else + { + FIXME("format type 0x%x not implemented\n", pFormat[0]); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + return NULL; + } +} + +static inline void call_freer(PMIDL_STUB_MESSAGE pStubMsg, unsigned char *pMemory, PFORMAT_STRING pFormat) +{ + NDR_FREE m = NdrFreer[pFormat[0] & NDR_TABLE_MASK]; + if (m) m(pStubMsg, pMemory, pFormat); +} + +static inline unsigned long call_memory_sizer(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat) +{ + NDR_MEMORYSIZE m = NdrMemorySizer[pFormat[0] & NDR_TABLE_MASK]; + if (m) + { + unsigned char *saved_buffer = pStubMsg->Buffer; + unsigned long ret; + int saved_ignore_embedded_pointers = pStubMsg->IgnoreEmbeddedPointers; + pStubMsg->MemorySize = 0; + pStubMsg->IgnoreEmbeddedPointers = 1; + ret = m(pStubMsg, pFormat); + pStubMsg->IgnoreEmbeddedPointers = saved_ignore_embedded_pointers; + pStubMsg->Buffer = saved_buffer; + return ret; + } + else + { + FIXME("format type 0x%x not implemented\n", pFormat[0]); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + return 0; + } +} + +#define STUBLESS_UNMARSHAL 1 +#define STUBLESS_CALLSERVER 2 +#define STUBLESS_CALCSIZE 3 +#define STUBLESS_GETBUFFER 4 +#define STUBLESS_MARSHAL 5 +#define STUBLESS_FREE 6 + +void WINAPI NdrRpcSmSetClientToOsf(PMIDL_STUB_MESSAGE pMessage) +{ +#if 0 /* these functions are not defined yet */ + pMessage->pfnAllocate = NdrRpcSmClientAllocate; + pMessage->pfnFree = NdrRpcSmClientFree; +#endif +} + +static void WINAPI dump_RPC_FC_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); +} + +static void WINAPI dump_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"); +} + +#define ARG_FROM_OFFSET(stubMsg, offset) ((stubMsg).StackTop + (offset)) + +static PFORMAT_STRING client_get_handle( + PMIDL_STUB_MESSAGE pStubMsg, const NDR_PROC_HEADER *pProcHeader, + PFORMAT_STRING pFormat, handle_t *phBinding) +{ + /* binding */ + switch (pProcHeader->handle_type) + { + /* explicit binding: parse additional section */ + case RPC_FC_BIND_EXPLICIT: + switch (*pFormat) /* handle_type */ + { + case RPC_FC_BIND_PRIMITIVE: /* explicit primitive */ + { + const NDR_EHD_PRIMITIVE *pDesc = (const NDR_EHD_PRIMITIVE *)pFormat; + + TRACE("Explicit primitive handle @ %d\n", pDesc->offset); + + if (pDesc->flag) /* pointer to binding */ + *phBinding = **(handle_t **)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset); + else + *phBinding = *(handle_t *)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset); + return pFormat + sizeof(NDR_EHD_PRIMITIVE); + } + case RPC_FC_BIND_GENERIC: /* explicit generic */ + { + const NDR_EHD_GENERIC *pDesc = (const NDR_EHD_GENERIC *)pFormat; + void *pObject = NULL; + void *pArg; + const GENERIC_BINDING_ROUTINE_PAIR *pGenPair; + + TRACE("Explicit generic binding handle #%d\n", pDesc->binding_routine_pair_index); + + if (pDesc->flag_and_size & HANDLE_PARAM_IS_VIA_PTR) + pArg = *(void **)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset); + else + pArg = (void *)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset); + memcpy(&pObject, pArg, pDesc->flag_and_size & 0xf); + pGenPair = &pStubMsg->StubDesc->aGenericBindingRoutinePairs[pDesc->binding_routine_pair_index]; + *phBinding = pGenPair->pfnBind(pObject); + return pFormat + sizeof(NDR_EHD_GENERIC); + } + case RPC_FC_BIND_CONTEXT: /* explicit context */ + { + const NDR_EHD_CONTEXT *pDesc = (const NDR_EHD_CONTEXT *)pFormat; + NDR_CCONTEXT context_handle; + TRACE("Explicit bind context\n"); + if (pDesc->flags & HANDLE_PARAM_IS_VIA_PTR) + { + TRACE("\tHANDLE_PARAM_IS_VIA_PTR\n"); + context_handle = **(NDR_CCONTEXT **)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset); + } + else + context_handle = *(NDR_CCONTEXT *)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset); + if ((pDesc->flags & NDR_CONTEXT_HANDLE_CANNOT_BE_NULL) && + !context_handle) + { + 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); + } + default: + ERR("bad explicit binding handle type (0x%02x)\n", pProcHeader->handle_type); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + break; + case RPC_FC_BIND_GENERIC: /* implicit generic */ + FIXME("RPC_FC_BIND_GENERIC\n"); + RpcRaiseException(RPC_X_BAD_STUB_DATA); /* FIXME: remove when implemented */ + break; + case RPC_FC_BIND_PRIMITIVE: /* implicit primitive */ + TRACE("Implicit primitive handle\n"); + *phBinding = *pStubMsg->StubDesc->IMPLICIT_HANDLE_INFO.pPrimitiveHandle; + break; + case RPC_FC_CALLBACK_HANDLE: /* implicit callback */ + FIXME("RPC_FC_CALLBACK_HANDLE\n"); + break; + case RPC_FC_AUTO_HANDLE: /* implicit auto handle */ + /* strictly speaking, it isn't necessary to set hBinding here + * since it isn't actually used (hence the automatic in its name), + * but then why does MIDL generate a valid entry in the + * MIDL_STUB_DESC for it? */ + TRACE("Implicit auto handle\n"); + *phBinding = *pStubMsg->StubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle; + break; + default: + ERR("bad implicit binding handle type (0x%02x)\n", pProcHeader->handle_type); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + return pFormat; +} + +static void client_free_handle( + PMIDL_STUB_MESSAGE pStubMsg, const NDR_PROC_HEADER *pProcHeader, + PFORMAT_STRING pFormat, handle_t hBinding) +{ + /* binding */ + switch (pProcHeader->handle_type) + { + /* explicit binding: parse additional section */ + case RPC_FC_BIND_EXPLICIT: + switch (*pFormat) /* handle_type */ + { + case RPC_FC_BIND_GENERIC: /* explicit generic */ + { + const NDR_EHD_GENERIC *pDesc = (const NDR_EHD_GENERIC *)pFormat; + void *pObject = NULL; + void *pArg; + const GENERIC_BINDING_ROUTINE_PAIR *pGenPair; + + TRACE("Explicit generic binding handle #%d\n", pDesc->binding_routine_pair_index); + + if (pDesc->flag_and_size & HANDLE_PARAM_IS_VIA_PTR) + pArg = *(void **)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset); + else + pArg = (void *)ARG_FROM_OFFSET(*pStubMsg, pDesc->offset); + memcpy(&pObject, pArg, pDesc->flag_and_size & 0xf); + pGenPair = &pStubMsg->StubDesc->aGenericBindingRoutinePairs[pDesc->binding_routine_pair_index]; + pGenPair->pfnUnbind(pObject, hBinding); + break; + } + case RPC_FC_BIND_CONTEXT: /* explicit context */ + case RPC_FC_BIND_PRIMITIVE: /* explicit primitive */ + break; + default: + ERR("bad explicit binding handle type (0x%02x)\n", pProcHeader->handle_type); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + break; + case RPC_FC_BIND_GENERIC: /* implicit generic */ + FIXME("RPC_FC_BIND_GENERIC\n"); + RpcRaiseException(RPC_X_BAD_STUB_DATA); /* FIXME: remove when implemented */ + break; + case RPC_FC_CALLBACK_HANDLE: /* implicit callback */ + case RPC_FC_BIND_PRIMITIVE: /* implicit primitive */ + case RPC_FC_AUTO_HANDLE: /* implicit auto handle */ + break; + default: + ERR("bad implicit binding handle type (0x%02x)\n", pProcHeader->handle_type); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } +} + +static void client_do_args(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, + int phase, 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; + + for (i = 0; i < number_of_params; i++) + { + const NDR_PARAM_OIF_BASETYPE *pParam = + (const NDR_PARAM_OIF_BASETYPE *)&pFormat[current_offset]; + unsigned char * pArg; + + current_stack_offset = pParam->stack_offset; + pArg = ARG_FROM_OFFSET(*pStubMsg, current_stack_offset); + + TRACE("param[%d]: new format\n", i); + TRACE("\tparam_attributes:"); dump_RPC_FC_PROC_PF(pParam->param_attributes); TRACE("\n"); + TRACE("\tstack_offset: 0x%x\n", current_stack_offset); + TRACE("\tmemory addr (before): %p\n", pArg); + + if (pParam->param_attributes.IsBasetype) + { + 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); + } + 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]); + + /* if a simple ref pointer then we have to do the + * check for the pointer being non-NULL. */ + if (pParam->param_attributes.IsSimpleRef) + { + if (!*(unsigned char **)pArg) + RpcRaiseException(RPC_X_NULL_REF_POINTER); + } + + TRACE("\tcomplex type: 0x%02x\n", *pTypeFormat); + + switch (phase) + { + 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); + } + + current_offset += sizeof(NDR_PARAM_OIF_OTHER); + } + TRACE("\tmemory addr (after): %p\n", pArg); + } +} + +static void client_do_args_old_format(PMIDL_STUB_MESSAGE pStubMsg, + PFORMAT_STRING pFormat, int phase, unsigned short stack_size, + unsigned char *pRetVal, BOOL object_proc) +{ + /* 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 does't terminate on the number_of_params + * condition as it doesn't have this attribute. Instead it + * terminates when the stack size given in the header is exceeded. + */ + for (i = 0; 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_proc ? sizeof(void *) : 0); + unsigned char * pArg = ARG_FROM_OFFSET(*pStubMsg, 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 (pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE) + { + if (pParam->param_direction & RPC_FC_RETURN_PARAM) + call_unmarshaller(pStubMsg, (unsigned char **)pRetVal, pTypeFormat, 0); + else + call_unmarshaller(pStubMsg, &pArg, pTypeFormat, 0); + } + break; + default: + RpcRaiseException(RPC_S_INTERNAL_ERROR); + } + + current_stack_offset += call_memory_sizer(pStubMsg, pTypeFormat); + current_offset += sizeof(NDR_PARAM_OI_BASETYPE); + } + else + { + const NDR_PARAM_OI_OTHER *pParamOther = + (const NDR_PARAM_OI_OTHER *)&pFormat[current_offset]; + + const unsigned char *pTypeFormat = + &pStubMsg->StubDesc->pFormatTypes[pParamOther->type_offset]; + + TRACE("\tcomplex type 0x%02x\n", *pTypeFormat); + + switch (phase) + { + case 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); + } +} + +/* the return type should be CLIENT_CALL_RETURN, but this is incompatible + * with the way gcc returns structures. "void *" should be the largest type + * that MIDL should allow you to return anyway */ +LONG_PTR WINAPIV NdrClientCall2(PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pFormat, ...) +{ + /* pointer to start of stack where arguments start */ + RPC_MESSAGE rpcMsg; + MIDL_STUB_MESSAGE stubMsg; + handle_t hBinding = NULL; + /* procedure number */ + unsigned short procedure_number; + /* size of stack */ + unsigned short stack_size; + /* number of parameters. optional for client to give it to us */ + unsigned char number_of_params = ~0; + /* 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 */ + LONG_PTR RetVal = 0; + /* the pointer to the object when in OLE mode */ + void * This = NULL; + PFORMAT_STRING pHandleFormat; + + 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); + } + + 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; + procedure_number = pProcHeader->proc_num; + pFormat += sizeof(NDR_PROC_HEADER_RPC); + } + else + { + stack_size = pProcHeader->stack_size; + procedure_number = pProcHeader->proc_num; + pFormat += sizeof(NDR_PROC_HEADER); + } + TRACE("stack size: 0x%x\n", 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) + stubMsg.FullPtrXlatTables = NdrFullPointerXlatInit(0,XLAT_CLIENT); + + if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT) + { + /* object is always the first argument */ + This = **(void *const **)(&pFormat+1); + NdrProxyInitialize(This, &rpcMsg, &stubMsg, pStubDesc, procedure_number); + } + else + NdrClientInitializeNew(&rpcMsg, &stubMsg, pStubDesc, procedure_number); + + TRACE("Oi_flags = 0x%02x\n", pProcHeader->Oi_flags); + TRACE("MIDL stub version = 0x%x\n", pStubDesc->MIDLVersion); + + /* needed for conformance of top-level objects */ +#ifdef __i386__ + stubMsg.StackTop = *(unsigned char **)(&pFormat+1); +#else +# warning Stack not retrieved for your CPU architecture +#endif + + 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 0; + } + + bV2Format = (pStubDesc->Version >= 0x20000); + + if (bV2Format) + { + const NDR_PROC_PARTIAL_OIF_HEADER *pOIFHeader = + (const NDR_PROC_PARTIAL_OIF_HEADER *)pFormat; + + Oif_flags = pOIFHeader->Oi2Flags; + number_of_params = pOIFHeader->number_of_params; + + pFormat += sizeof(NDR_PROC_PARTIAL_OIF_HEADER); + } + + TRACE("Oif_flags = "); dump_INTERPRETER_OPT_FLAGS(Oif_flags); + + if (Oif_flags.HasExtensions) + { + const NDR_PROC_HEADER_EXTS *pExtensions = + (const NDR_PROC_HEADER_EXTS *)pFormat; + ext_flags = pExtensions->Flags2; + pFormat += pExtensions->Size; + } + + stubMsg.BufferLength = 0; + + /* store the RPC flags away */ + if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCFLAGS) + rpcMsg.RpcFlags = ((const NDR_PROC_HEADER_RPC *)pProcHeader)->rpc_flags; + + /* use alternate memory allocation routines */ + if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_RPCSSALLOC) + NdrRpcSmSetClientToOsf(&stubMsg); + + 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; + } + + /* 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) + { + case PROXY_GETBUFFER: + /* allocate the buffer */ + if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT) + NdrProxyGetBuffer(This, &stubMsg); + else 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); + } + break; + case PROXY_SENDRECEIVE: + /* send the [in] params and receive the [out] and [retval] + * params */ + if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT) + NdrProxySendReceive(This, &stubMsg); + else 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 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, number_of_params, + (unsigned char *)&RetVal); + else + client_do_args_old_format(&stubMsg, pFormat, phase, stack_size, + (unsigned char *)&RetVal, + (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT)); + break; + default: + ERR("shouldn't reach here. phase %d\n", phase); + break; + } + } + + if (ext_flags.HasNewCorrDesc) + { + /* free extra correlation package */ + /* NdrCorrelationFree(&stubMsg); */ + } + + if (Oif_flags.HasPipes) + { + /* NdrPipesDone(...) */ + } + + /* free the full pointer translation tables */ + if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR) + NdrFullPointerXlatFree(stubMsg.FullPtrXlatTables); + + /* free marshalling buffer */ + if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT) + NdrProxyFreeBuffer(This, &stubMsg); + else + { + NdrFreeBuffer(&stubMsg); + client_free_handle(&stubMsg, pProcHeader, pHandleFormat, hBinding); + } + + TRACE("RetVal = 0x%lx\n", RetVal); + + return RetVal; +} + +/* calls a function with the specificed arguments, restoring the stack + * properly afterwards as we don't know the calling convention of the + * function */ +#if defined __i386__ && defined _MSC_VER +__declspec(naked) LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned int stack_size) +{ + __asm + { + push ebp + push edi ; Save registers + push esi + mov ebp, esp + mov eax, [ebp+16] ; Get stack size + sub esp, eax ; Make room in stack for arguments + mov edi, esp + mov ecx, eax + mov esi, [ebp+12] + shr ecx, 2 + cld + rep movsd ; Copy dword blocks + call [ebp+8] ; Call function + lea esp, [ebp-8] ; Restore stack + pop esi ; Restore registers + pop edi + pop ebp + ret + } +} +#elif defined __i386__ && defined __GNUC__ +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" + "pushl %edi\n\t" /* Save registers */ + "pushl %esi\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 */ + "movl %esp, %edi\n\t" + "movl %eax, %ecx\n\t" + "movl 12(%ebp), %esi\n\t" + "shrl $2, %ecx\n\t" /* divide by 4 */ + "cld\n\t" + "rep; movsl\n\t" /* Copy dword blocks */ + "call *8(%ebp)\n\t" /* Call function */ + "leal -8(%ebp), %esp\n\t" /* Restore stack */ + "popl %esi\n\t" /* Restore registers */ + "popl %edi\n\t" + "popl %ebp\n\t" + "ret\n" ) +#else +#warning call_server_func not implemented for your architecture +LONG_PTR __cdecl call_server_func(SERVER_ROUTINE func, unsigned char * args, unsigned short stack_size) +{ + FIXME("Not implemented for your architecture\n"); + return 0; +} +#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; + 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, + unsigned short number_of_params) +{ + /* counter */ + unsigned short i; + /* current format string offset */ + int current_offset = 0; + /* current stack offset */ + unsigned short current_stack_offset = 0; + /* location to put retval into */ + LONG_PTR *retval_ptr = NULL; + + for (i = 0; i < number_of_params; i++) + { + const NDR_PARAM_OIF_BASETYPE *pParam = + (const NDR_PARAM_OIF_BASETYPE *)&pFormat[current_offset]; + unsigned char *pArg; + + current_stack_offset = pParam->stack_offset; + pArg = (unsigned char *)(args+current_stack_offset); + + TRACE("param[%d]: new format\n", i); + TRACE("\tparam_attributes:"); dump_RPC_FC_PROC_PF(pParam->param_attributes); TRACE("\n"); + TRACE("\tstack_offset: 0x%x\n", current_stack_offset); + TRACE("\tmemory addr (before): %p -> %p\n", pArg, *(unsigned char **)pArg); + + if (pParam->param_attributes.IsBasetype) + { + const unsigned char *pTypeFormat = + &pParam->type_format_char; + + TRACE("\tbase type: 0x%02x\n", *pTypeFormat); + + switch (phase) + { + case STUBLESS_MARSHAL: + if (pParam->param_attributes.IsOut || pParam->param_attributes.IsReturn) + { + if (pParam->param_attributes.IsSimpleRef) + call_marshaller(pStubMsg, *(unsigned char **)pArg, pTypeFormat); + else + call_marshaller(pStubMsg, pArg, pTypeFormat); + } + break; + case STUBLESS_FREE: + if (pParam->param_attributes.ServerAllocSize) + HeapFree(GetProcessHeap(), 0, *(void **)pArg); + break; + case STUBLESS_UNMARSHAL: + if (pParam->param_attributes.ServerAllocSize) + *(void **)pArg = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + pParam->param_attributes.ServerAllocSize * 8); + + if (pParam->param_attributes.IsIn) + { + if (pParam->param_attributes.IsSimpleRef) + call_unmarshaller(pStubMsg, (unsigned char **)pArg, pTypeFormat, 0); + else + call_unmarshaller(pStubMsg, &pArg, pTypeFormat, 0); + } + + /* make a note of the address of the return value parameter for later */ + if (pParam->param_attributes.IsReturn) + retval_ptr = (LONG_PTR *)pArg; + + break; + case STUBLESS_CALCSIZE: + if (pParam->param_attributes.IsOut || pParam->param_attributes.IsReturn) + { + if (pParam->param_attributes.IsSimpleRef) + call_buffer_sizer(pStubMsg, *(unsigned char **)pArg, pTypeFormat); + else + call_buffer_sizer(pStubMsg, pArg, pTypeFormat); + } + break; + default: + RpcRaiseException(RPC_S_INTERNAL_ERROR); + } + + current_offset += sizeof(NDR_PARAM_OIF_BASETYPE); + } + else + { + const NDR_PARAM_OIF_OTHER *pParamOther = + (const NDR_PARAM_OIF_OTHER *)&pFormat[current_offset]; + + const unsigned char * pTypeFormat = + &(pStubMsg->StubDesc->pFormatTypes[pParamOther->type_offset]); + + TRACE("\tcomplex type 0x%02x\n", *pTypeFormat); + + switch (phase) + { + case STUBLESS_MARSHAL: + if (pParam->param_attributes.IsOut || pParam->param_attributes.IsReturn) + { + if (pParam->param_attributes.IsByValue) + call_marshaller(pStubMsg, pArg, pTypeFormat); + else + call_marshaller(pStubMsg, *(unsigned char **)pArg, pTypeFormat); + } + break; + case STUBLESS_FREE: + if (pParam->param_attributes.MustFree) + { + if (pParam->param_attributes.IsByValue) + call_freer(pStubMsg, pArg, pTypeFormat); + else + call_freer(pStubMsg, *(unsigned char **)pArg, pTypeFormat); + } + + if (pParam->param_attributes.IsOut && + !pParam->param_attributes.IsIn && + !pParam->param_attributes.IsByValue && + !pParam->param_attributes.ServerAllocSize) + { + pStubMsg->pfnFree(*(void **)pArg); + } + + if (pParam->param_attributes.ServerAllocSize) + HeapFree(GetProcessHeap(), 0, *(void **)pArg); + /* FIXME: call call_freer here for IN types with MustFree set */ + break; + case STUBLESS_UNMARSHAL: + if (pParam->param_attributes.ServerAllocSize) + *(void **)pArg = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + pParam->param_attributes.ServerAllocSize * 8); + + if (pParam->param_attributes.IsIn) + { + if (pParam->param_attributes.IsByValue) + call_unmarshaller(pStubMsg, &pArg, pTypeFormat, 0); + else + call_unmarshaller(pStubMsg, (unsigned char **)pArg, pTypeFormat, 0); + } + else if (pParam->param_attributes.IsOut && + !pParam->param_attributes.ServerAllocSize && + !pParam->param_attributes.IsByValue) + { + DWORD size = calc_arg_size(pStubMsg, pTypeFormat); + + if(size) + { + *(void **)pArg = NdrAllocate(pStubMsg, size); + memset(*(void **)pArg, 0, size); + } + } + break; + case STUBLESS_CALCSIZE: + if (pParam->param_attributes.IsOut || pParam->param_attributes.IsReturn) + { + if (pParam->param_attributes.IsByValue) + call_buffer_sizer(pStubMsg, pArg, pTypeFormat); + else + call_buffer_sizer(pStubMsg, *(unsigned char **)pArg, pTypeFormat); + } + break; + default: + RpcRaiseException(RPC_S_INTERNAL_ERROR); + } + + current_offset += sizeof(NDR_PARAM_OIF_OTHER); + } + TRACE("\tmemory addr (after): %p -> %p\n", pArg, *(unsigned char **)pArg); + } + + return retval_ptr; +} + +static LONG_PTR *stub_do_old_args(MIDL_STUB_MESSAGE *pStubMsg, + PFORMAT_STRING pFormat, int phase, + unsigned char *args, + unsigned short stack_size, BOOL object) +{ + /* counter */ + unsigned short i; + /* current format string offset */ + int current_offset = 0; + /* current stack offset */ + unsigned short current_stack_offset = 0; + /* location to put retval into */ + LONG_PTR *retval_ptr = NULL; + + for (i = 0; TRUE; i++) + { + const NDR_PARAM_OI_BASETYPE *pParam = + (const NDR_PARAM_OI_BASETYPE *)&pFormat[current_offset]; + /* note: current_stack_offset starts after the This pointer + * if present, so adjust this */ + unsigned short current_stack_offset_adjusted = current_stack_offset + + (object ? sizeof(void *) : 0); + unsigned char *pArg = (unsigned char *)(args+current_stack_offset_adjusted); + + /* no more parameters; exit loop */ + if (current_stack_offset_adjusted >= stack_size) + break; + + TRACE("param[%d]: old format\n", i); + TRACE("\tparam_direction: 0x%x\n", pParam->param_direction); + TRACE("\tstack_offset: 0x%x\n", current_stack_offset_adjusted); + + if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE || + pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE) + { + const unsigned char *pTypeFormat = + &pParam->type_format_char; + + TRACE("\tbase type 0x%02x\n", *pTypeFormat); + + switch (phase) + { + case STUBLESS_MARSHAL: + if (pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE) + call_marshaller(pStubMsg, pArg, pTypeFormat); + break; + case STUBLESS_FREE: + if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE) + call_freer(pStubMsg, pArg, pTypeFormat); + break; + case STUBLESS_UNMARSHAL: + if (pParam->param_direction == RPC_FC_IN_PARAM_BASETYPE) + call_unmarshaller(pStubMsg, &pArg, pTypeFormat, 0); + else if (pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE) + retval_ptr = (LONG_PTR *)pArg; + break; + case STUBLESS_CALCSIZE: + if (pParam->param_direction == RPC_FC_RETURN_PARAM_BASETYPE) + call_buffer_sizer(pStubMsg, pArg, pTypeFormat); + break; + default: + RpcRaiseException(RPC_S_INTERNAL_ERROR); + } + + current_stack_offset += call_memory_sizer(pStubMsg, pTypeFormat); + current_offset += sizeof(NDR_PARAM_OI_BASETYPE); + } + else + { + const NDR_PARAM_OI_OTHER *pParamOther = + (const NDR_PARAM_OI_OTHER *)&pFormat[current_offset]; + + const unsigned char * pTypeFormat = + &pStubMsg->StubDesc->pFormatTypes[pParamOther->type_offset]; + + TRACE("\tcomplex type 0x%02x\n", *pTypeFormat); + + switch (phase) + { + case STUBLESS_MARSHAL: + if (pParam->param_direction == RPC_FC_OUT_PARAM || + pParam->param_direction == RPC_FC_IN_OUT_PARAM || + pParam->param_direction == RPC_FC_RETURN_PARAM) + call_marshaller(pStubMsg, *(unsigned char **)pArg, pTypeFormat); + break; + case STUBLESS_FREE: + if (pParam->param_direction == RPC_FC_IN_OUT_PARAM || + pParam->param_direction == RPC_FC_IN_PARAM) + call_freer(pStubMsg, *(unsigned char **)pArg, pTypeFormat); + else if (pParam->param_direction == RPC_FC_OUT_PARAM) + pStubMsg->pfnFree(*(void **)pArg); + break; + case STUBLESS_UNMARSHAL: + if (pParam->param_direction == RPC_FC_IN_OUT_PARAM || + pParam->param_direction == RPC_FC_IN_PARAM) + call_unmarshaller(pStubMsg, (unsigned char **)pArg, pTypeFormat, 0); + else if (pParam->param_direction == RPC_FC_RETURN_PARAM) + retval_ptr = (LONG_PTR *)pArg; + else if (pParam->param_direction == RPC_FC_OUT_PARAM) + { + DWORD size = calc_arg_size(pStubMsg, pTypeFormat); + + if(size) + { + *(void **)pArg = NdrAllocate(pStubMsg, size); + memset(*(void **)pArg, 0, size); + } + } + break; + case STUBLESS_CALCSIZE: + if (pParam->param_direction == RPC_FC_OUT_PARAM || + pParam->param_direction == RPC_FC_IN_OUT_PARAM || + pParam->param_direction == RPC_FC_RETURN_PARAM) + call_buffer_sizer(pStubMsg, *(unsigned char **)pArg, pTypeFormat); + break; + default: + RpcRaiseException(RPC_S_INTERNAL_ERROR); + } + + current_stack_offset += pParamOther->stack_size * sizeof(INT); + current_offset += sizeof(NDR_PARAM_OI_OTHER); + } + } + + return retval_ptr; +} + +/*********************************************************************** + * NdrStubCall2 [RPCRT4.@] + * + * Unmarshals [in] parameters, calls either a method in an object or a server + * function, marshals any [out] parameters and frees any allocated data. + * + * NOTES + * Used by stubless MIDL-generated code. + */ +LONG WINAPI NdrStubCall2( + struct IRpcStubBuffer * pThis, + struct IRpcChannelBuffer * pChannel, + PRPC_MESSAGE pRpcMsg, + DWORD * pdwStubPhase) +{ + const MIDL_SERVER_INFO *pServerInfo; + const MIDL_STUB_DESC *pStubDesc; + PFORMAT_STRING pFormat; + MIDL_STUB_MESSAGE stubMsg; + /* pointer to start of stack to pass into stub implementation */ + unsigned char * args; + /* size of stack */ + unsigned short stack_size; + /* number of parameters. optional for client to give it to us */ + unsigned char number_of_params = ~0; + /* 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; + /* 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; + + TRACE("pThis %p, pChannel %p, pRpcMsg %p, pdwStubPhase %p\n", pThis, pChannel, pRpcMsg, pdwStubPhase); + + if (pThis) + pServerInfo = CStdStubBuffer_GetServerInfo(pThis); + else + pServerInfo = ((RPC_SERVER_INTERFACE *)pRpcMsg->RpcInterfaceInformation)->InterpreterInfo; + + pStubDesc = pServerInfo->pStubDesc; + pFormat = pServerInfo->ProcString + pServerInfo->FmtStringOffset[pRpcMsg->ProcNum]; + pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0]; + + /* 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); + } + + /* 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); + + } + else + { + stack_size = pProcHeader->stack_size; + current_offset = sizeof(NDR_PROC_HEADER); + } + + TRACE("Oi_flags = 0x%02x\n", pProcHeader->Oi_flags); + + /* binding */ + switch (pProcHeader->handle_type) + { + /* explicit binding: parse additional section */ + case RPC_FC_BIND_EXPLICIT: + switch (pFormat[current_offset]) /* handle_type */ + { + case RPC_FC_BIND_PRIMITIVE: /* explicit primitive */ + current_offset += sizeof(NDR_EHD_PRIMITIVE); + break; + case RPC_FC_BIND_GENERIC: /* explicit generic */ + current_offset += sizeof(NDR_EHD_GENERIC); + break; + case RPC_FC_BIND_CONTEXT: /* explicit context */ + current_offset += sizeof(NDR_EHD_CONTEXT); + break; + default: + ERR("bad explicit binding handle type (0x%02x)\n", pProcHeader->handle_type); + RpcRaiseException(RPC_X_BAD_STUB_DATA); + } + break; + case RPC_FC_BIND_GENERIC: /* implicit generic */ + case RPC_FC_BIND_PRIMITIVE: /* implicit primitive */ + case RPC_FC_CALLBACK_HANDLE: /* implicit callback */ + case RPC_FC_AUTO_HANDLE: /* implicit auto handle */ + break; + default: + ERR("bad implicit binding handle type (0x%02x)\n", pProcHeader->handle_type); + 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); + + /* 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) +#if 0 + NdrRpcSsEnableAllocate(&stubMsg); +#else + 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); + stubMsg.StackTop = args; /* used by conformance of top-level objects */ + + /* add the implicit This pointer as the first arg to the function if we + * are calling an object method */ + 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 + */ + for (phase = STUBLESS_UNMARSHAL; phase <= STUBLESS_FREE; phase++) + { + TRACE("phase = %d\n", phase); + switch (phase) + { + case STUBLESS_CALLSERVER: + /* call the server function */ + if (pServerInfo->ThunkTable && pServerInfo->ThunkTable[pRpcMsg->ProcNum]) + pServerInfo->ThunkTable[pRpcMsg->ProcNum](&stubMsg); + else + { + SERVER_ROUTINE func; + LONG_PTR retval; + + if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT) + { + SERVER_ROUTINE *vtbl = *(SERVER_ROUTINE **)((CStdStubBuffer *)pThis)->pvServerObject; + func = vtbl[pRpcMsg->ProcNum]; + } + else + func = pServerInfo->DispatchTable[pRpcMsg->ProcNum]; + + /* FIXME: what happens with return values that don't fit into a single register on x86? */ + retval = call_server_func(func, args, stack_size); + + if (retval_ptr) + { + TRACE("stub implementation returned 0x%lx\n", retval); + *retval_ptr = retval; + } + else + TRACE("void stub implementation\n"); + } + + stubMsg.Buffer = NULL; + stubMsg.BufferLength = 0; + + break; + case STUBLESS_GETBUFFER: + if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_OBJECT) + NdrStubGetBuffer(pThis, pChannel, &stubMsg); + else + { + RPC_STATUS Status; + + pRpcMsg->BufferLength = stubMsg.BufferLength; + /* allocate buffer for [out] and [ret] params */ + Status = I_RpcGetBuffer(pRpcMsg); + if (Status) + RpcRaiseException(Status); + stubMsg.BufferStart = pRpcMsg->Buffer; + stubMsg.BufferEnd = stubMsg.BufferStart + stubMsg.BufferLength; + stubMsg.Buffer = stubMsg.BufferStart; + } + break; + case STUBLESS_MARSHAL: + case STUBLESS_UNMARSHAL: + case STUBLESS_CALCSIZE: + 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)); + + break; + default: + ERR("shouldn't reach here. phase %d\n", phase); + break; + } + } + + pRpcMsg->BufferLength = (unsigned int)(stubMsg.Buffer - (unsigned char *)pRpcMsg->Buffer); + + if (ext_flags.HasNewCorrDesc) + { + /* free extra correlation package */ + /* NdrCorrelationFree(&stubMsg); */ + } + + if (Oif_flags.HasPipes) + { + /* NdrPipesDone(...) */ + } + + /* free the full pointer translation tables */ + if (pProcHeader->Oi_flags & RPC_FC_PROC_OIF_FULLPTR) + NdrFullPointerXlatFree(stubMsg.FullPtrXlatTables); + + /* free server function stack */ + HeapFree(GetProcessHeap(), 0, args); + + return S_OK; +} + +/*********************************************************************** + * NdrServerCall2 [RPCRT4.@] + */ +void WINAPI NdrServerCall2(PRPC_MESSAGE pRpcMsg) +{ + DWORD dwPhase; + NdrStubCall2(NULL, NULL, pRpcMsg, &dwPhase); +} diff --git a/reactos/dll/win32/rpcrt4_new/rpc_binding.c b/reactos/dll/win32/rpcrt4_new/rpc_binding.c index e1d06f95736..24769e2ce60 100644 --- a/reactos/dll/win32/rpcrt4_new/rpc_binding.c +++ b/reactos/dll/win32/rpcrt4_new/rpc_binding.c @@ -1,1586 +1,1586 @@ -/* - * RPC binding API - * - * Copyright 2001 Ove Kåven, TransGaming Technologies - * Copyright 2003 Mike Hearn - * Copyright 2004 Filip Navara - * Copyright 2006 CodeWeavers - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include -#include -#include -#include - -#include "windef.h" -#include "winbase.h" -#include "winnls.h" -#include "winerror.h" -#include "winternl.h" -#include "wine/unicode.h" - -#include "rpc.h" -#include "rpcndr.h" - -#include "wine/debug.h" - -#include "rpc_binding.h" -#include "rpc_assoc.h" - -WINE_DEFAULT_DEBUG_CHANNEL(rpc); - -LPSTR RPCRT4_strndupA(LPCSTR src, INT slen) -{ - DWORD len; - LPSTR s; - if (!src) return NULL; - if (slen == -1) slen = strlen(src); - len = slen; - s = HeapAlloc(GetProcessHeap(), 0, len+1); - memcpy(s, src, len); - s[len] = 0; - return s; -} - -LPSTR RPCRT4_strdupWtoA(LPCWSTR src) -{ - DWORD len; - LPSTR s; - if (!src) return NULL; - len = WideCharToMultiByte(CP_ACP, 0, src, -1, NULL, 0, NULL, NULL); - s = HeapAlloc(GetProcessHeap(), 0, len); - WideCharToMultiByte(CP_ACP, 0, src, -1, s, len, NULL, NULL); - return s; -} - -LPWSTR RPCRT4_strdupAtoW(LPCSTR src) -{ - DWORD len; - LPWSTR s; - if (!src) return NULL; - len = MultiByteToWideChar(CP_ACP, 0, src, -1, NULL, 0); - s = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR)); - MultiByteToWideChar(CP_ACP, 0, src, -1, s, len); - return s; -} - -static LPWSTR RPCRT4_strndupAtoW(LPCSTR src, INT slen) -{ - DWORD len; - LPWSTR s; - if (!src) return NULL; - len = MultiByteToWideChar(CP_ACP, 0, src, slen, NULL, 0); - s = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR)); - MultiByteToWideChar(CP_ACP, 0, src, slen, s, len); - return s; -} - -LPWSTR RPCRT4_strndupW(LPCWSTR src, INT slen) -{ - DWORD len; - LPWSTR s; - if (!src) return NULL; - if (slen == -1) slen = strlenW(src); - len = slen; - s = HeapAlloc(GetProcessHeap(), 0, (len+1)*sizeof(WCHAR)); - memcpy(s, src, len*sizeof(WCHAR)); - s[len] = 0; - return s; -} - -void RPCRT4_strfree(LPSTR src) -{ - HeapFree(GetProcessHeap(), 0, src); -} - -static RPC_STATUS RPCRT4_AllocBinding(RpcBinding** Binding, BOOL server) -{ - RpcBinding* NewBinding; - - NewBinding = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcBinding)); - NewBinding->refs = 1; - NewBinding->server = server; - - *Binding = NewBinding; - - return RPC_S_OK; -} - -static RPC_STATUS RPCRT4_CreateBindingA(RpcBinding** Binding, BOOL server, LPCSTR Protseq) -{ - RpcBinding* NewBinding; - - RPCRT4_AllocBinding(&NewBinding, server); - NewBinding->Protseq = RPCRT4_strdupA(Protseq); - - TRACE("binding: %p\n", NewBinding); - *Binding = NewBinding; - - return RPC_S_OK; -} - -static RPC_STATUS RPCRT4_CreateBindingW(RpcBinding** Binding, BOOL server, LPCWSTR Protseq) -{ - RpcBinding* NewBinding; - - RPCRT4_AllocBinding(&NewBinding, server); - NewBinding->Protseq = RPCRT4_strdupWtoA(Protseq); - - TRACE("binding: %p\n", NewBinding); - *Binding = NewBinding; - - return RPC_S_OK; -} - -static RPC_STATUS RPCRT4_CompleteBindingA(RpcBinding* Binding, LPCSTR NetworkAddr, - LPCSTR Endpoint, LPCSTR NetworkOptions) -{ - RPC_STATUS status; - - TRACE("(RpcBinding == ^%p, NetworkAddr == %s, EndPoint == %s, NetworkOptions == %s)\n", Binding, - debugstr_a(NetworkAddr), debugstr_a(Endpoint), debugstr_a(NetworkOptions)); - - RPCRT4_strfree(Binding->NetworkAddr); - Binding->NetworkAddr = RPCRT4_strdupA(NetworkAddr); - RPCRT4_strfree(Binding->Endpoint); - if (Endpoint) { - Binding->Endpoint = RPCRT4_strdupA(Endpoint); - } else { - Binding->Endpoint = RPCRT4_strdupA(""); - } - HeapFree(GetProcessHeap(), 0, Binding->NetworkOptions); - Binding->NetworkOptions = RPCRT4_strdupAtoW(NetworkOptions); - if (!Binding->Endpoint) ERR("out of memory?\n"); - - status = RPCRT4_GetAssociation(Binding->Protseq, Binding->NetworkAddr, - Binding->Endpoint, Binding->NetworkOptions, - &Binding->Assoc); - if (status != RPC_S_OK) - return status; - - return RPC_S_OK; -} - -static RPC_STATUS RPCRT4_CompleteBindingW(RpcBinding* Binding, LPCWSTR NetworkAddr, - LPCWSTR Endpoint, LPCWSTR NetworkOptions) -{ - RPC_STATUS status; - - TRACE("(RpcBinding == ^%p, NetworkAddr == %s, EndPoint == %s, NetworkOptions == %s)\n", Binding, - debugstr_w(NetworkAddr), debugstr_w(Endpoint), debugstr_w(NetworkOptions)); - - RPCRT4_strfree(Binding->NetworkAddr); - Binding->NetworkAddr = RPCRT4_strdupWtoA(NetworkAddr); - RPCRT4_strfree(Binding->Endpoint); - if (Endpoint) { - Binding->Endpoint = RPCRT4_strdupWtoA(Endpoint); - } else { - Binding->Endpoint = RPCRT4_strdupA(""); - } - if (!Binding->Endpoint) ERR("out of memory?\n"); - HeapFree(GetProcessHeap(), 0, Binding->NetworkOptions); - Binding->NetworkOptions = RPCRT4_strdupW(NetworkOptions); - - status = RPCRT4_GetAssociation(Binding->Protseq, Binding->NetworkAddr, - Binding->Endpoint, Binding->NetworkOptions, - &Binding->Assoc); - if (status != RPC_S_OK) - return status; - - return RPC_S_OK; -} - -RPC_STATUS RPCRT4_ResolveBinding(RpcBinding* Binding, LPCSTR Endpoint) -{ - RPC_STATUS status; - - TRACE("(RpcBinding == ^%p, EndPoint == \"%s\"\n", Binding, Endpoint); - - RPCRT4_strfree(Binding->Endpoint); - Binding->Endpoint = RPCRT4_strdupA(Endpoint); - - RpcAssoc_Release(Binding->Assoc); - Binding->Assoc = NULL; - status = RPCRT4_GetAssociation(Binding->Protseq, Binding->NetworkAddr, - Binding->Endpoint, Binding->NetworkOptions, - &Binding->Assoc); - if (status != RPC_S_OK) - return status; - - return RPC_S_OK; -} - -RPC_STATUS RPCRT4_SetBindingObject(RpcBinding* Binding, const UUID* ObjectUuid) -{ - TRACE("(*RpcBinding == ^%p, UUID == %s)\n", Binding, debugstr_guid(ObjectUuid)); - if (ObjectUuid) memcpy(&Binding->ObjectUuid, ObjectUuid, sizeof(UUID)); - else UuidCreateNil(&Binding->ObjectUuid); - return RPC_S_OK; -} - -RPC_STATUS RPCRT4_MakeBinding(RpcBinding** Binding, RpcConnection* Connection) -{ - RpcBinding* NewBinding; - TRACE("(RpcBinding == ^%p, Connection == ^%p)\n", Binding, Connection); - - RPCRT4_AllocBinding(&NewBinding, Connection->server); - NewBinding->Protseq = RPCRT4_strdupA(rpcrt4_conn_get_name(Connection)); - NewBinding->NetworkAddr = RPCRT4_strdupA(Connection->NetworkAddr); - NewBinding->Endpoint = RPCRT4_strdupA(Connection->Endpoint); - NewBinding->FromConn = Connection; - - TRACE("binding: %p\n", NewBinding); - *Binding = NewBinding; - - return RPC_S_OK; -} - -RPC_STATUS RPCRT4_ExportBinding(RpcBinding** Binding, RpcBinding* OldBinding) -{ - InterlockedIncrement(&OldBinding->refs); - *Binding = OldBinding; - return RPC_S_OK; -} - -RPC_STATUS RPCRT4_DestroyBinding(RpcBinding* Binding) -{ - if (InterlockedDecrement(&Binding->refs)) - return RPC_S_OK; - - TRACE("binding: %p\n", Binding); - if (Binding->Assoc) RpcAssoc_Release(Binding->Assoc); - RPCRT4_strfree(Binding->Endpoint); - RPCRT4_strfree(Binding->NetworkAddr); - RPCRT4_strfree(Binding->Protseq); - HeapFree(GetProcessHeap(), 0, Binding->NetworkOptions); - if (Binding->AuthInfo) RpcAuthInfo_Release(Binding->AuthInfo); - if (Binding->QOS) RpcQualityOfService_Release(Binding->QOS); - HeapFree(GetProcessHeap(), 0, Binding); - return RPC_S_OK; -} - -RPC_STATUS RPCRT4_OpenBinding(RpcBinding* Binding, RpcConnection** Connection, - const RPC_SYNTAX_IDENTIFIER *TransferSyntax, - const RPC_SYNTAX_IDENTIFIER *InterfaceId) -{ - TRACE("(Binding == ^%p)\n", Binding); - - if (!Binding->server) { - return RpcAssoc_GetClientConnection(Binding->Assoc, InterfaceId, - TransferSyntax, Binding->AuthInfo, Binding->QOS, Connection); - } else { - /* we already have a connection with acceptable binding, so use it */ - if (Binding->FromConn) { - *Connection = Binding->FromConn; - return RPC_S_OK; - } else { - ERR("no connection in binding\n"); - return RPC_S_INTERNAL_ERROR; - } - } -} - -RPC_STATUS RPCRT4_CloseBinding(RpcBinding* Binding, RpcConnection* Connection) -{ - TRACE("(Binding == ^%p)\n", Binding); - if (!Connection) return RPC_S_OK; - if (Binding->server) { - /* don't destroy a connection that is cached in the binding */ - if (Binding->FromConn == Connection) - return RPC_S_OK; - return RPCRT4_DestroyConnection(Connection); - } - else { - RpcAssoc_ReleaseIdleConnection(Binding->Assoc, Connection); - return RPC_S_OK; - } -} - -/* utility functions for string composing and parsing */ -static unsigned RPCRT4_strcopyA(LPSTR data, LPCSTR src) -{ - unsigned len = strlen(src); - memcpy(data, src, len*sizeof(CHAR)); - return len; -} - -static unsigned RPCRT4_strcopyW(LPWSTR data, LPCWSTR src) -{ - unsigned len = strlenW(src); - memcpy(data, src, len*sizeof(WCHAR)); - return len; -} - -static LPSTR RPCRT4_strconcatA(LPSTR dst, LPCSTR src) -{ - DWORD len = strlen(dst), slen = strlen(src); - LPSTR ndst = HeapReAlloc(GetProcessHeap(), 0, dst, (len+slen+2)*sizeof(CHAR)); - if (!ndst) - { - HeapFree(GetProcessHeap(), 0, dst); - return NULL; - } - ndst[len] = ','; - memcpy(ndst+len+1, src, slen+1); - return ndst; -} - -static LPWSTR RPCRT4_strconcatW(LPWSTR dst, LPCWSTR src) -{ - DWORD len = strlenW(dst), slen = strlenW(src); - LPWSTR ndst = HeapReAlloc(GetProcessHeap(), 0, dst, (len+slen+2)*sizeof(WCHAR)); - if (!ndst) - { - HeapFree(GetProcessHeap(), 0, dst); - return NULL; - } - ndst[len] = ','; - memcpy(ndst+len+1, src, (slen+1)*sizeof(WCHAR)); - return ndst; -} - - -/*********************************************************************** - * RpcStringBindingComposeA (RPCRT4.@) - */ -RPC_STATUS WINAPI RpcStringBindingComposeA(RPC_CSTR ObjUuid, RPC_CSTR Protseq, - RPC_CSTR NetworkAddr, RPC_CSTR Endpoint, - RPC_CSTR Options, RPC_CSTR *StringBinding ) -{ - DWORD len = 1; - LPSTR data; - - TRACE( "(%s,%s,%s,%s,%s,%p)\n", - debugstr_a( (char*)ObjUuid ), debugstr_a( (char*)Protseq ), - debugstr_a( (char*)NetworkAddr ), debugstr_a( (char*)Endpoint ), - debugstr_a( (char*)Options ), StringBinding ); - - if (ObjUuid && *ObjUuid) len += strlen((char*)ObjUuid) + 1; - if (Protseq && *Protseq) len += strlen((char*)Protseq) + 1; - if (NetworkAddr && *NetworkAddr) len += strlen((char*)NetworkAddr); - if (Endpoint && *Endpoint) len += strlen((char*)Endpoint) + 2; - if (Options && *Options) len += strlen((char*)Options) + 2; - - data = HeapAlloc(GetProcessHeap(), 0, len); - *StringBinding = (unsigned char*)data; - - if (ObjUuid && *ObjUuid) { - data += RPCRT4_strcopyA(data, (char*)ObjUuid); - *data++ = '@'; - } - if (Protseq && *Protseq) { - data += RPCRT4_strcopyA(data, (char*)Protseq); - *data++ = ':'; - } - if (NetworkAddr && *NetworkAddr) - data += RPCRT4_strcopyA(data, (char*)NetworkAddr); - - if ((Endpoint && *Endpoint) || - (Options && *Options)) { - *data++ = '['; - if (Endpoint && *Endpoint) { - data += RPCRT4_strcopyA(data, (char*)Endpoint); - if (Options && *Options) *data++ = ','; - } - if (Options && *Options) { - data += RPCRT4_strcopyA(data, (char*)Options); - } - *data++ = ']'; - } - *data = 0; - - return RPC_S_OK; -} - -/*********************************************************************** - * RpcStringBindingComposeW (RPCRT4.@) - */ -RPC_STATUS WINAPI RpcStringBindingComposeW( RPC_WSTR ObjUuid, RPC_WSTR Protseq, - RPC_WSTR NetworkAddr, RPC_WSTR Endpoint, - RPC_WSTR Options, RPC_WSTR* StringBinding ) -{ - DWORD len = 1; - RPC_WSTR data; - - TRACE("(%s,%s,%s,%s,%s,%p)\n", - debugstr_w( ObjUuid ), debugstr_w( Protseq ), - debugstr_w( NetworkAddr ), debugstr_w( Endpoint ), - debugstr_w( Options ), StringBinding); - - if (ObjUuid && *ObjUuid) len += strlenW(ObjUuid) + 1; - if (Protseq && *Protseq) len += strlenW(Protseq) + 1; - if (NetworkAddr && *NetworkAddr) len += strlenW(NetworkAddr); - if (Endpoint && *Endpoint) len += strlenW(Endpoint) + 2; - if (Options && *Options) len += strlenW(Options) + 2; - - data = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR)); - *StringBinding = data; - - if (ObjUuid && *ObjUuid) { - data += RPCRT4_strcopyW(data, ObjUuid); - *data++ = '@'; - } - if (Protseq && *Protseq) { - data += RPCRT4_strcopyW(data, Protseq); - *data++ = ':'; - } - if (NetworkAddr && *NetworkAddr) { - data += RPCRT4_strcopyW(data, NetworkAddr); - } - if ((Endpoint && *Endpoint) || - (Options && *Options)) { - *data++ = '['; - if (Endpoint && *Endpoint) { - data += RPCRT4_strcopyW(data, Endpoint); - if (Options && *Options) *data++ = ','; - } - if (Options && *Options) { - data += RPCRT4_strcopyW(data, Options); - } - *data++ = ']'; - } - *data = 0; - - return RPC_S_OK; -} - - -/*********************************************************************** - * RpcStringBindingParseA (RPCRT4.@) - */ -RPC_STATUS WINAPI RpcStringBindingParseA( RPC_CSTR StringBinding, RPC_CSTR *ObjUuid, - RPC_CSTR *Protseq, RPC_CSTR *NetworkAddr, - RPC_CSTR *Endpoint, RPC_CSTR *Options) -{ - CHAR *data, *next; - static const char ep_opt[] = "endpoint="; - - TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_a((char*)StringBinding), - ObjUuid, Protseq, NetworkAddr, Endpoint, Options); - - if (ObjUuid) *ObjUuid = NULL; - if (Protseq) *Protseq = NULL; - if (NetworkAddr) *NetworkAddr = NULL; - if (Endpoint) *Endpoint = NULL; - if (Options) *Options = NULL; - - data = (char*) StringBinding; - - next = strchr(data, '@'); - if (next) { - if (ObjUuid) *ObjUuid = (unsigned char*)RPCRT4_strndupA(data, next - data); - data = next+1; - } - - next = strchr(data, ':'); - if (next) { - if (Protseq) *Protseq = (unsigned char*)RPCRT4_strndupA(data, next - data); - data = next+1; - } - - next = strchr(data, '['); - if (next) { - CHAR *close, *opt; - - if (NetworkAddr) *NetworkAddr = (unsigned char*)RPCRT4_strndupA(data, next - data); - data = next+1; - close = strchr(data, ']'); - if (!close) goto fail; - - /* tokenize options */ - while (data < close) { - next = strchr(data, ','); - if (!next || next > close) next = close; - /* FIXME: this is kind of inefficient */ - opt = RPCRT4_strndupA(data, next - data); - data = next+1; - - /* parse option */ - next = strchr(opt, '='); - if (!next) { - /* not an option, must be an endpoint */ - if (*Endpoint) goto fail; - *Endpoint = (unsigned char*) opt; - } else { - if (strncmp(opt, ep_opt, strlen(ep_opt)) == 0) { - /* endpoint option */ - if (*Endpoint) goto fail; - *Endpoint = (unsigned char*) RPCRT4_strdupA(next+1); - HeapFree(GetProcessHeap(), 0, opt); - } else { - /* network option */ - if (*Options) { - /* FIXME: this is kind of inefficient */ - *Options = (unsigned char*) RPCRT4_strconcatA( (char*)*Options, opt); - HeapFree(GetProcessHeap(), 0, opt); - } else - *Options = (unsigned char*) opt; - } - } - } - - data = close+1; - if (*data) goto fail; - } - else if (NetworkAddr) - *NetworkAddr = (unsigned char*)RPCRT4_strdupA(data); - - 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); - return RPC_S_INVALID_STRING_BINDING; -} - -/*********************************************************************** - * RpcStringBindingParseW (RPCRT4.@) - */ -RPC_STATUS WINAPI RpcStringBindingParseW( RPC_WSTR StringBinding, RPC_WSTR *ObjUuid, - RPC_WSTR *Protseq, RPC_WSTR *NetworkAddr, - RPC_WSTR *Endpoint, RPC_WSTR *Options) -{ - WCHAR *data, *next; - static const WCHAR ep_opt[] = {'e','n','d','p','o','i','n','t','=',0}; - - TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_w(StringBinding), - ObjUuid, Protseq, NetworkAddr, Endpoint, Options); - - if (ObjUuid) *ObjUuid = NULL; - if (Protseq) *Protseq = NULL; - if (NetworkAddr) *NetworkAddr = NULL; - if (Endpoint) *Endpoint = NULL; - if (Options) *Options = NULL; - - data = StringBinding; - - next = strchrW(data, '@'); - if (next) { - if (ObjUuid) *ObjUuid = RPCRT4_strndupW(data, next - data); - data = next+1; - } - - next = strchrW(data, ':'); - if (next) { - if (Protseq) *Protseq = RPCRT4_strndupW(data, next - data); - data = next+1; - } - - next = strchrW(data, '['); - if (next) { - WCHAR *close, *opt; - - if (NetworkAddr) *NetworkAddr = RPCRT4_strndupW(data, next - data); - data = next+1; - close = strchrW(data, ']'); - if (!close) goto fail; - - /* tokenize options */ - while (data < close) { - next = strchrW(data, ','); - if (!next || next > close) next = close; - /* FIXME: this is kind of inefficient */ - opt = RPCRT4_strndupW(data, next - data); - data = next+1; - - /* parse option */ - next = strchrW(opt, '='); - if (!next) { - /* not an option, must be an endpoint */ - if (*Endpoint) goto fail; - *Endpoint = opt; - } else { - if (strncmpW(opt, ep_opt, strlenW(ep_opt)) == 0) { - /* endpoint option */ - if (*Endpoint) goto fail; - *Endpoint = RPCRT4_strdupW(next+1); - HeapFree(GetProcessHeap(), 0, opt); - } else { - /* network option */ - if (*Options) { - /* FIXME: this is kind of inefficient */ - *Options = RPCRT4_strconcatW(*Options, opt); - HeapFree(GetProcessHeap(), 0, opt); - } else - *Options = opt; - } - } - } - - data = close+1; - if (*data) goto fail; - } else if (NetworkAddr) - *NetworkAddr = RPCRT4_strdupW(data); - - return RPC_S_OK; - -fail: - if (ObjUuid) RpcStringFreeW(ObjUuid); - if (Protseq) RpcStringFreeW(Protseq); - if (NetworkAddr) RpcStringFreeW(NetworkAddr); - if (Endpoint) RpcStringFreeW(Endpoint); - if (Options) RpcStringFreeW(Options); - return RPC_S_INVALID_STRING_BINDING; -} - -/*********************************************************************** - * RpcBindingFree (RPCRT4.@) - */ -RPC_STATUS WINAPI RpcBindingFree( RPC_BINDING_HANDLE* Binding ) -{ - RPC_STATUS status; - TRACE("(%p) = %p\n", Binding, *Binding); - status = RPCRT4_DestroyBinding(*Binding); - if (status == RPC_S_OK) *Binding = 0; - return status; -} - -/*********************************************************************** - * RpcBindingVectorFree (RPCRT4.@) - */ -RPC_STATUS WINAPI RpcBindingVectorFree( RPC_BINDING_VECTOR** BindingVector ) -{ - RPC_STATUS status; - unsigned long c; - - TRACE("(%p)\n", BindingVector); - for (c=0; c<(*BindingVector)->Count; c++) { - status = RpcBindingFree(&(*BindingVector)->BindingH[c]); - } - HeapFree(GetProcessHeap(), 0, *BindingVector); - *BindingVector = NULL; - return RPC_S_OK; -} - -/*********************************************************************** - * RpcBindingInqObject (RPCRT4.@) - */ -RPC_STATUS WINAPI RpcBindingInqObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid ) -{ - RpcBinding* bind = (RpcBinding*)Binding; - - TRACE("(%p,%p) = %s\n", Binding, ObjectUuid, debugstr_guid(&bind->ObjectUuid)); - memcpy(ObjectUuid, &bind->ObjectUuid, sizeof(UUID)); - return RPC_S_OK; -} - -/*********************************************************************** - * RpcBindingSetObject (RPCRT4.@) - */ -RPC_STATUS WINAPI RpcBindingSetObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid ) -{ - RpcBinding* bind = (RpcBinding*)Binding; - - TRACE("(%p,%s)\n", Binding, debugstr_guid(ObjectUuid)); - if (bind->server) return RPC_S_WRONG_KIND_OF_BINDING; - return RPCRT4_SetBindingObject(Binding, ObjectUuid); -} - -/*********************************************************************** - * RpcBindingFromStringBindingA (RPCRT4.@) - */ -RPC_STATUS WINAPI RpcBindingFromStringBindingA( RPC_CSTR StringBinding, RPC_BINDING_HANDLE* Binding ) -{ - RPC_STATUS ret; - RpcBinding* bind = NULL; - RPC_CSTR ObjectUuid, Protseq, NetworkAddr, Endpoint, Options; - UUID Uuid; - - TRACE("(%s,%p)\n", debugstr_a((char*)StringBinding), Binding); - - ret = RpcStringBindingParseA(StringBinding, &ObjectUuid, &Protseq, - &NetworkAddr, &Endpoint, &Options); - if (ret != RPC_S_OK) return ret; - - ret = UuidFromStringA(ObjectUuid, &Uuid); - - if (ret == RPC_S_OK) - ret = RPCRT4_CreateBindingA(&bind, FALSE, (char*)Protseq); - if (ret == RPC_S_OK) - ret = RPCRT4_SetBindingObject(bind, &Uuid); - 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); - - if (ret == RPC_S_OK) - *Binding = (RPC_BINDING_HANDLE)bind; - else - RPCRT4_DestroyBinding(bind); - - return ret; -} - -/*********************************************************************** - * RpcBindingFromStringBindingW (RPCRT4.@) - */ -RPC_STATUS WINAPI RpcBindingFromStringBindingW( RPC_WSTR StringBinding, RPC_BINDING_HANDLE* Binding ) -{ - RPC_STATUS ret; - RpcBinding* bind = NULL; - RPC_WSTR ObjectUuid, Protseq, NetworkAddr, Endpoint, Options; - UUID Uuid; - - TRACE("(%s,%p)\n", debugstr_w(StringBinding), Binding); - - ret = RpcStringBindingParseW(StringBinding, &ObjectUuid, &Protseq, - &NetworkAddr, &Endpoint, &Options); - if (ret != RPC_S_OK) return ret; - - ret = UuidFromStringW(ObjectUuid, &Uuid); - - if (ret == RPC_S_OK) - ret = RPCRT4_CreateBindingW(&bind, FALSE, Protseq); - if (ret == RPC_S_OK) - ret = RPCRT4_SetBindingObject(bind, &Uuid); - if (ret == RPC_S_OK) - ret = RPCRT4_CompleteBindingW(bind, NetworkAddr, Endpoint, Options); - - RpcStringFreeW(&Options); - RpcStringFreeW(&Endpoint); - RpcStringFreeW(&NetworkAddr); - RpcStringFreeW(&Protseq); - RpcStringFreeW(&ObjectUuid); - - if (ret == RPC_S_OK) - *Binding = (RPC_BINDING_HANDLE)bind; - else - RPCRT4_DestroyBinding(bind); - - return ret; -} - -/*********************************************************************** - * RpcBindingToStringBindingA (RPCRT4.@) - */ -RPC_STATUS WINAPI RpcBindingToStringBindingA( RPC_BINDING_HANDLE Binding, RPC_CSTR *StringBinding ) -{ - RPC_STATUS ret; - RpcBinding* bind = (RpcBinding*)Binding; - RPC_CSTR ObjectUuid; - - TRACE("(%p,%p)\n", Binding, StringBinding); - - ret = UuidToStringA(&bind->ObjectUuid, &ObjectUuid); - if (ret != RPC_S_OK) return ret; - - ret = RpcStringBindingComposeA(ObjectUuid, (unsigned char*)bind->Protseq, (unsigned char*) bind->NetworkAddr, - (unsigned char*) bind->Endpoint, NULL, StringBinding); - - RpcStringFreeA(&ObjectUuid); - - return ret; -} - -/*********************************************************************** - * RpcBindingToStringBindingW (RPCRT4.@) - */ -RPC_STATUS WINAPI RpcBindingToStringBindingW( RPC_BINDING_HANDLE Binding, RPC_WSTR *StringBinding ) -{ - RPC_STATUS ret; - unsigned char *str = NULL; - TRACE("(%p,%p)\n", Binding, StringBinding); - ret = RpcBindingToStringBindingA(Binding, &str); - *StringBinding = RPCRT4_strdupAtoW((char*)str); - RpcStringFreeA((unsigned char**)&str); - return ret; -} - -/*********************************************************************** - * I_RpcBindingSetAsync (RPCRT4.@) - * NOTES - * Exists in win9x and winNT, but with different number of arguments - * (9x version has 3 arguments, NT has 2). - */ -RPC_STATUS WINAPI I_RpcBindingSetAsync( RPC_BINDING_HANDLE Binding, RPC_BLOCKING_FN BlockingFn) -{ - RpcBinding* bind = (RpcBinding*)Binding; - - TRACE( "(%p,%p): stub\n", Binding, BlockingFn ); - - bind->BlockingFn = BlockingFn; - - return RPC_S_OK; -} - -/*********************************************************************** - * RpcBindingCopy (RPCRT4.@) - */ -RPC_STATUS RPC_ENTRY RpcBindingCopy( - RPC_BINDING_HANDLE SourceBinding, - RPC_BINDING_HANDLE* DestinationBinding) -{ - RpcBinding *DestBinding; - RpcBinding *SrcBinding = (RpcBinding*)SourceBinding; - RPC_STATUS status; - - TRACE("(%p, %p)\n", SourceBinding, DestinationBinding); - - status = RPCRT4_AllocBinding(&DestBinding, SrcBinding->server); - if (status != RPC_S_OK) return status; - - DestBinding->ObjectUuid = SrcBinding->ObjectUuid; - DestBinding->BlockingFn = SrcBinding->BlockingFn; - DestBinding->Protseq = RPCRT4_strndupA(SrcBinding->Protseq, -1); - DestBinding->NetworkAddr = RPCRT4_strndupA(SrcBinding->NetworkAddr, -1); - DestBinding->Endpoint = RPCRT4_strndupA(SrcBinding->Endpoint, -1); - DestBinding->NetworkOptions = RPCRT4_strdupW(SrcBinding->NetworkOptions); - if (SrcBinding->Assoc) SrcBinding->Assoc->refs++; - DestBinding->Assoc = SrcBinding->Assoc; - - if (SrcBinding->AuthInfo) RpcAuthInfo_AddRef(SrcBinding->AuthInfo); - DestBinding->AuthInfo = SrcBinding->AuthInfo; - if (SrcBinding->QOS) RpcQualityOfService_AddRef(SrcBinding->QOS); - DestBinding->QOS = SrcBinding->QOS; - - *DestinationBinding = DestBinding; - return RPC_S_OK; -} - -/*********************************************************************** - * RpcImpersonateClient (RPCRT4.@) - * - * Impersonates the client connected via a binding handle so that security - * checks are done in the context of the client. - * - * PARAMS - * BindingHandle [I] Handle to the binding to the client. - * - * RETURNS - * Success: RPS_S_OK. - * Failure: RPC_STATUS value. - * - * NOTES - * - * If BindingHandle is NULL then the function impersonates the client - * connected to the binding handle of the current thread. - */ -RPC_STATUS WINAPI RpcImpersonateClient(RPC_BINDING_HANDLE BindingHandle) -{ - FIXME("(%p): stub\n", BindingHandle); - ImpersonateSelf(SecurityImpersonation); - return RPC_S_OK; -} - -/*********************************************************************** - * RpcRevertToSelfEx (RPCRT4.@) - * - * Stops impersonating the client connected to the binding handle so that security - * checks are no longer done in the context of the client. - * - * PARAMS - * BindingHandle [I] Handle to the binding to the client. - * - * RETURNS - * Success: RPS_S_OK. - * Failure: RPC_STATUS value. - * - * NOTES - * - * If BindingHandle is NULL then the function stops impersonating the client - * connected to the binding handle of the current thread. - */ -RPC_STATUS WINAPI RpcRevertToSelfEx(RPC_BINDING_HANDLE BindingHandle) -{ - FIXME("(%p): stub\n", BindingHandle); - return RPC_S_OK; -} - -static inline BOOL has_nt_auth_identity(ULONG AuthnLevel) -{ - switch (AuthnLevel) - { - case RPC_C_AUTHN_GSS_NEGOTIATE: - case RPC_C_AUTHN_WINNT: - case RPC_C_AUTHN_GSS_KERBEROS: - return TRUE; - default: - return FALSE; - } -} - -static 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) - return ERROR_OUTOFMEMORY; - - AuthInfo->refs = 1; - AuthInfo->AuthnLevel = AuthnLevel; - AuthInfo->AuthnSvc = AuthnSvc; - AuthInfo->cred = cred; - AuthInfo->exp = exp; - AuthInfo->cbMaxToken = cbMaxToken; - AuthInfo->identity = identity; - - /* duplicate the SEC_WINNT_AUTH_IDENTITY structure, if applicable, to - * enable better matching in RpcAuthInfo_IsEqual */ - if (identity && has_nt_auth_identity(AuthnSvc)) - { - const SEC_WINNT_AUTH_IDENTITY_W *nt_identity = identity; - AuthInfo->nt_identity = HeapAlloc(GetProcessHeap(), 0, sizeof(*AuthInfo->nt_identity)); - if (!AuthInfo->nt_identity) - { - HeapFree(GetProcessHeap(), 0, AuthInfo); - return ERROR_OUTOFMEMORY; - } - - AuthInfo->nt_identity->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; - if (nt_identity->Flags & SEC_WINNT_AUTH_IDENTITY_UNICODE) - AuthInfo->nt_identity->User = RPCRT4_strndupW(nt_identity->User, nt_identity->UserLength); - else - AuthInfo->nt_identity->User = RPCRT4_strndupAtoW((const char *)nt_identity->User, nt_identity->UserLength); - AuthInfo->nt_identity->UserLength = nt_identity->UserLength; - if (nt_identity->Flags & SEC_WINNT_AUTH_IDENTITY_UNICODE) - AuthInfo->nt_identity->Domain = RPCRT4_strndupW(nt_identity->Domain, nt_identity->DomainLength); - else - AuthInfo->nt_identity->Domain = RPCRT4_strndupAtoW((const char *)nt_identity->Domain, nt_identity->DomainLength); - AuthInfo->nt_identity->DomainLength = nt_identity->DomainLength; - if (nt_identity->Flags & SEC_WINNT_AUTH_IDENTITY_UNICODE) - AuthInfo->nt_identity->Password = RPCRT4_strndupW(nt_identity->Password, nt_identity->PasswordLength); - else - AuthInfo->nt_identity->Password = RPCRT4_strndupAtoW((const char *)nt_identity->Password, nt_identity->PasswordLength); - AuthInfo->nt_identity->PasswordLength = nt_identity->PasswordLength; - - if (!AuthInfo->nt_identity->User || - !AuthInfo->nt_identity->Domain || - !AuthInfo->nt_identity->Password) - { - HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->User); - HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->Domain); - HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->Password); - HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity); - HeapFree(GetProcessHeap(), 0, AuthInfo); - return ERROR_OUTOFMEMORY; - } - } - else - AuthInfo->nt_identity = NULL; - *ret = AuthInfo; - return RPC_S_OK; -} - -ULONG RpcAuthInfo_AddRef(RpcAuthInfo *AuthInfo) -{ - return InterlockedIncrement(&AuthInfo->refs); -} - -ULONG RpcAuthInfo_Release(RpcAuthInfo *AuthInfo) -{ - ULONG refs = InterlockedDecrement(&AuthInfo->refs); - - if (!refs) - { - FreeCredentialsHandle(&AuthInfo->cred); - if (AuthInfo->nt_identity) - { - HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->User); - HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->Domain); - HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->Password); - HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity); - } - HeapFree(GetProcessHeap(), 0, AuthInfo); - } - - return refs; -} - -BOOL RpcAuthInfo_IsEqual(const RpcAuthInfo *AuthInfo1, const RpcAuthInfo *AuthInfo2) -{ - if (AuthInfo1 == AuthInfo2) - return TRUE; - - if (!AuthInfo1 || !AuthInfo2) - return FALSE; - - if ((AuthInfo1->AuthnLevel != AuthInfo2->AuthnLevel) || - (AuthInfo1->AuthnSvc != AuthInfo2->AuthnSvc)) - return FALSE; - - if (AuthInfo1->identity == AuthInfo2->identity) - return TRUE; - - if (!AuthInfo1->identity || !AuthInfo2->identity) - return FALSE; - - if (has_nt_auth_identity(AuthInfo1->AuthnSvc)) - { - const SEC_WINNT_AUTH_IDENTITY_W *identity1 = AuthInfo1->nt_identity; - const SEC_WINNT_AUTH_IDENTITY_W *identity2 = AuthInfo2->nt_identity; - /* compare user names */ - if (identity1->UserLength != identity2->UserLength || - memcmp(identity1->User, identity2->User, identity1->UserLength)) - return FALSE; - /* compare domain names */ - if (identity1->DomainLength != identity2->DomainLength || - memcmp(identity1->Domain, identity2->Domain, identity1->DomainLength)) - return FALSE; - /* compare passwords */ - if (identity1->PasswordLength != identity2->PasswordLength || - memcmp(identity1->Password, identity2->Password, identity1->PasswordLength)) - return FALSE; - } - else - return FALSE; - - return TRUE; -} - -static RPC_STATUS RpcQualityOfService_Create(const RPC_SECURITY_QOS *qos_src, BOOL unicode, RpcQualityOfService **qos_dst) -{ - RpcQualityOfService *qos = HeapAlloc(GetProcessHeap(), 0, sizeof(*qos)); - - if (!qos) - return RPC_S_OUT_OF_RESOURCES; - - qos->refs = 1; - qos->qos = HeapAlloc(GetProcessHeap(), 0, sizeof(*qos->qos)); - if (!qos->qos) goto error; - qos->qos->Version = qos_src->Version; - qos->qos->Capabilities = qos_src->Capabilities; - qos->qos->IdentityTracking = qos_src->IdentityTracking; - qos->qos->ImpersonationType = qos_src->ImpersonationType; - qos->qos->AdditionalSecurityInfoType = 0; - - if (qos_src->Version >= 2) - { - const RPC_SECURITY_QOS_V2_W *qos_src2 = (const RPC_SECURITY_QOS_V2_W *)qos_src; - qos->qos->AdditionalSecurityInfoType = qos_src2->AdditionalSecurityInfoType; - if (qos_src2->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP) - { - const RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_credentials_src = qos_src2->u.HttpCredentials; - RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_credentials_dst; - - http_credentials_dst = HeapAlloc(GetProcessHeap(), 0, sizeof(*http_credentials_dst)); - qos->qos->u.HttpCredentials = http_credentials_dst; - if (!http_credentials_dst) goto error; - http_credentials_dst->TransportCredentials = NULL; - http_credentials_dst->Flags = http_credentials_src->Flags; - http_credentials_dst->AuthenticationTarget = http_credentials_src->AuthenticationTarget; - http_credentials_dst->NumberOfAuthnSchemes = http_credentials_src->NumberOfAuthnSchemes; - http_credentials_dst->AuthnSchemes = NULL; - http_credentials_dst->ServerCertificateSubject = NULL; - if (http_credentials_src->TransportCredentials) - { - SEC_WINNT_AUTH_IDENTITY_W *cred_dst; - cred_dst = http_credentials_dst->TransportCredentials = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*cred_dst)); - if (!cred_dst) goto error; - cred_dst->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; - if (unicode) - { - const SEC_WINNT_AUTH_IDENTITY_W *cred_src = http_credentials_src->TransportCredentials; - cred_dst->UserLength = cred_src->UserLength; - cred_dst->PasswordLength = cred_src->PasswordLength; - cred_dst->DomainLength = cred_src->DomainLength; - cred_dst->User = RPCRT4_strndupW(cred_src->User, cred_src->UserLength); - cred_dst->Password = RPCRT4_strndupW(cred_src->Password, cred_src->PasswordLength); - cred_dst->Domain = RPCRT4_strndupW(cred_src->Domain, cred_src->DomainLength); - } - else - { - const SEC_WINNT_AUTH_IDENTITY_A *cred_src = (const SEC_WINNT_AUTH_IDENTITY_A *)http_credentials_src->TransportCredentials; - cred_dst->UserLength = MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->User, cred_src->UserLength, NULL, 0); - cred_dst->DomainLength = MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->Domain, cred_src->DomainLength, NULL, 0); - cred_dst->PasswordLength = MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->Password, cred_src->PasswordLength, NULL, 0); - 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; - 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); - } - } - if (http_credentials_src->NumberOfAuthnSchemes) - { - http_credentials_dst->AuthnSchemes = HeapAlloc(GetProcessHeap(), 0, http_credentials_src->NumberOfAuthnSchemes * sizeof(*http_credentials_dst->AuthnSchemes)); - if (!http_credentials_dst->AuthnSchemes) goto error; - memcpy(http_credentials_dst->AuthnSchemes, http_credentials_src->AuthnSchemes, http_credentials_src->NumberOfAuthnSchemes * sizeof(*http_credentials_dst->AuthnSchemes)); - } - if (http_credentials_src->ServerCertificateSubject) - { - if (unicode) - http_credentials_dst->ServerCertificateSubject = - RPCRT4_strndupW(http_credentials_src->ServerCertificateSubject, - strlenW(http_credentials_src->ServerCertificateSubject)); - else - http_credentials_dst->ServerCertificateSubject = - RPCRT4_strdupAtoW((char *)http_credentials_src->ServerCertificateSubject); - if (!http_credentials_dst->ServerCertificateSubject) goto error; - } - } - } - *qos_dst = qos; - return RPC_S_OK; - -error: - if (qos->qos) - { - if (qos->qos->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP && - qos->qos->u.HttpCredentials) - { - if (qos->qos->u.HttpCredentials->TransportCredentials) - { - HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->User); - HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->Domain); - HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->Password); - HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials); - } - HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->AuthnSchemes); - HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->ServerCertificateSubject); - HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials); - } - HeapFree(GetProcessHeap(), 0, qos->qos); - } - HeapFree(GetProcessHeap(), 0, qos); - return RPC_S_OUT_OF_RESOURCES; -} - -ULONG RpcQualityOfService_AddRef(RpcQualityOfService *qos) -{ - return InterlockedIncrement(&qos->refs); -} - -ULONG RpcQualityOfService_Release(RpcQualityOfService *qos) -{ - ULONG refs = InterlockedDecrement(&qos->refs); - - if (!refs) - { - if (qos->qos->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP) - { - if (qos->qos->u.HttpCredentials->TransportCredentials) - { - HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->User); - HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->Domain); - HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->Password); - HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials); - } - HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->AuthnSchemes); - HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->ServerCertificateSubject); - HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials); - } - HeapFree(GetProcessHeap(), 0, qos->qos); - HeapFree(GetProcessHeap(), 0, qos); - } - return refs; -} - -BOOL RpcQualityOfService_IsEqual(const RpcQualityOfService *qos1, const RpcQualityOfService *qos2) -{ - if (qos1 == qos2) - return TRUE; - - if (!qos1 || !qos2) - return FALSE; - - TRACE("qos1 = { %ld %ld %ld %ld }, qos2 = { %ld %ld %ld %ld }\n", - qos1->qos->Capabilities, qos1->qos->IdentityTracking, - qos1->qos->ImpersonationType, qos1->qos->AdditionalSecurityInfoType, - qos2->qos->Capabilities, qos2->qos->IdentityTracking, - qos2->qos->ImpersonationType, qos2->qos->AdditionalSecurityInfoType); - - if ((qos1->qos->Capabilities != qos2->qos->Capabilities) || - (qos1->qos->IdentityTracking != qos2->qos->IdentityTracking) || - (qos1->qos->ImpersonationType != qos2->qos->ImpersonationType) || - (qos1->qos->AdditionalSecurityInfoType != qos2->qos->AdditionalSecurityInfoType)) - return FALSE; - - if (qos1->qos->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP) - { - const RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_credentials1 = qos1->qos->u.HttpCredentials; - const RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_credentials2 = qos2->qos->u.HttpCredentials; - - if (http_credentials1->Flags != http_credentials2->Flags) - return FALSE; - - if (http_credentials1->AuthenticationTarget != http_credentials2->AuthenticationTarget) - return FALSE; - - /* authentication schemes and server certificate subject not currently used */ - - if (http_credentials1->TransportCredentials != http_credentials2->TransportCredentials) - { - const SEC_WINNT_AUTH_IDENTITY_W *identity1 = http_credentials1->TransportCredentials; - const SEC_WINNT_AUTH_IDENTITY_W *identity2 = http_credentials2->TransportCredentials; - - if (!identity1 || !identity2) - return FALSE; - - /* compare user names */ - if (identity1->UserLength != identity2->UserLength || - memcmp(identity1->User, identity2->User, identity1->UserLength)) - return FALSE; - /* compare domain names */ - if (identity1->DomainLength != identity2->DomainLength || - memcmp(identity1->Domain, identity2->Domain, identity1->DomainLength)) - return FALSE; - /* compare passwords */ - if (identity1->PasswordLength != identity2->PasswordLength || - memcmp(identity1->Password, identity2->Password, identity1->PasswordLength)) - return FALSE; - } - } - - return TRUE; -} - -/*********************************************************************** - * RpcRevertToSelf (RPCRT4.@) - */ -RPC_STATUS WINAPI RpcRevertToSelf(void) -{ - FIXME("stub\n"); - RevertToSelf(); - return RPC_S_OK; -} - -/*********************************************************************** - * RpcMgmtSetComTimeout (RPCRT4.@) - */ -RPC_STATUS WINAPI RpcMgmtSetComTimeout(RPC_BINDING_HANDLE BindingHandle, unsigned int Timeout) -{ - FIXME("(%p, %d): stub\n", BindingHandle, Timeout); - return RPC_S_OK; -} - -/*********************************************************************** - * RpcBindingInqAuthInfoExA (RPCRT4.@) - */ -RPCRTAPI RPC_STATUS RPC_ENTRY -RpcBindingInqAuthInfoExA( RPC_BINDING_HANDLE Binding, RPC_CSTR *ServerPrincName, ULONG *AuthnLevel, - 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, - AuthnSvc, AuthIdentity, AuthzSvc, RpcQosVersion, SecurityQOS); - return RPC_S_INVALID_BINDING; -} - -/*********************************************************************** - * RpcBindingInqAuthInfoExW (RPCRT4.@) - */ -RPCRTAPI RPC_STATUS RPC_ENTRY -RpcBindingInqAuthInfoExW( RPC_BINDING_HANDLE Binding, RPC_WSTR *ServerPrincName, ULONG *AuthnLevel, - 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, - AuthnSvc, AuthIdentity, AuthzSvc, RpcQosVersion, SecurityQOS); - return RPC_S_INVALID_BINDING; -} - -/*********************************************************************** - * RpcBindingInqAuthInfoA (RPCRT4.@) - */ -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; -} - -/*********************************************************************** - * RpcBindingInqAuthInfoW (RPCRT4.@) - */ -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; -} - -/*********************************************************************** - * RpcBindingSetAuthInfoExA (RPCRT4.@) - */ -RPCRTAPI RPC_STATUS RPC_ENTRY -RpcBindingSetAuthInfoExA( RPC_BINDING_HANDLE Binding, RPC_CSTR ServerPrincName, - ULONG AuthnLevel, ULONG AuthnSvc, - RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr, - RPC_SECURITY_QOS *SecurityQos ) -{ - RpcBinding* bind = (RpcBinding*)Binding; - SECURITY_STATUS r; - CredHandle cred; - TimeStamp exp; - ULONG package_count; - ULONG i; - PSecPkgInfoA packages; - ULONG cbMaxToken; - - TRACE("%p %s %u %u %p %u %p\n", Binding, debugstr_a((const char*)ServerPrincName), - AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, SecurityQos); - - if (SecurityQos) - { - RPC_STATUS status; - - TRACE("SecurityQos { Version=%ld, Capabilties=0x%lx, IdentityTracking=%ld, ImpersonationLevel=%ld", - SecurityQos->Version, SecurityQos->Capabilities, SecurityQos->IdentityTracking, SecurityQos->ImpersonationType); - if (SecurityQos->Version >= 2) - { - const RPC_SECURITY_QOS_V2_A *SecurityQos2 = (const RPC_SECURITY_QOS_V2_A *)SecurityQos; - TRACE(", AdditionalSecurityInfoType=%ld", SecurityQos2->AdditionalSecurityInfoType); - if (SecurityQos2->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP) - TRACE(", { %p, 0x%lx, %ld, %ld, %p, %s }", - SecurityQos2->u.HttpCredentials->TransportCredentials, - SecurityQos2->u.HttpCredentials->Flags, - SecurityQos2->u.HttpCredentials->AuthenticationTarget, - SecurityQos2->u.HttpCredentials->NumberOfAuthnSchemes, - SecurityQos2->u.HttpCredentials->AuthnSchemes, - SecurityQos2->u.HttpCredentials->ServerCertificateSubject); - } - TRACE("}\n"); - status = RpcQualityOfService_Create(SecurityQos, FALSE, &bind->QOS); - if (status != RPC_S_OK) - return status; - } - else - { - if (bind->QOS) RpcQualityOfService_Release(bind->QOS); - bind->QOS = NULL; - } - - if (AuthnSvc == RPC_C_AUTHN_DEFAULT) - AuthnSvc = RPC_C_AUTHN_WINNT; - - /* FIXME: the mapping should probably be retrieved using SSPI somehow */ - if (AuthnLevel == RPC_C_AUTHN_LEVEL_DEFAULT) - AuthnLevel = RPC_C_AUTHN_LEVEL_NONE; - - if ((AuthnLevel == RPC_C_AUTHN_LEVEL_NONE) || (AuthnSvc == RPC_C_AUTHN_NONE)) - { - if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo); - bind->AuthInfo = NULL; - return RPC_S_OK; - } - - if (AuthnLevel > RPC_C_AUTHN_LEVEL_PKT_PRIVACY) - { - FIXME("unknown AuthnLevel %u\n", AuthnLevel); - return RPC_S_UNKNOWN_AUTHN_LEVEL; - } - - if (AuthzSvr) - { - FIXME("unsupported AuthzSvr %u\n", AuthzSvr); - return RPC_S_UNKNOWN_AUTHZ_SERVICE; - } - - r = EnumerateSecurityPackagesA(&package_count, &packages); - if (r != SEC_E_OK) - { - ERR("EnumerateSecurityPackagesA failed with error 0x%08x\n", r); - return RPC_S_SEC_PKG_ERROR; - } - - for (i = 0; i < package_count; i++) - if (packages[i].wRPCID == AuthnSvc) - break; - - if (i == package_count) - { - FIXME("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); - r = AcquireCredentialsHandleA((SEC_CHAR *)ServerPrincName, packages[i].Name, SECPKG_CRED_OUTBOUND, NULL, - AuthIdentity, NULL, NULL, &cred, &exp); - cbMaxToken = packages[i].cbMaxToken; - FreeContextBuffer(packages); - if (r == ERROR_SUCCESS) - { - if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo); - bind->AuthInfo = NULL; - r = RpcAuthInfo_Create(AuthnLevel, AuthnSvc, cred, exp, cbMaxToken, - AuthIdentity, &bind->AuthInfo); - if (r != RPC_S_OK) - FreeCredentialsHandle(&cred); - return RPC_S_OK; - } - else - { - ERR("AcquireCredentialsHandleA failed with error 0x%08x\n", r); - return RPC_S_SEC_PKG_ERROR; - } -} - -/*********************************************************************** - * RpcBindingSetAuthInfoExW (RPCRT4.@) - */ -RPCRTAPI RPC_STATUS RPC_ENTRY -RpcBindingSetAuthInfoExW( RPC_BINDING_HANDLE Binding, RPC_WSTR ServerPrincName, ULONG AuthnLevel, - ULONG AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr, - RPC_SECURITY_QOS *SecurityQos ) -{ - RpcBinding* bind = (RpcBinding*)Binding; - SECURITY_STATUS r; - CredHandle cred; - TimeStamp exp; - ULONG package_count; - ULONG i; - PSecPkgInfoW packages; - ULONG cbMaxToken; - - TRACE("%p %s %u %u %p %u %p\n", Binding, debugstr_w((const WCHAR*)ServerPrincName), - AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, SecurityQos); - - if (SecurityQos) - { - RPC_STATUS status; - - TRACE("SecurityQos { Version=%ld, Capabilties=0x%lx, IdentityTracking=%ld, ImpersonationLevel=%ld", - SecurityQos->Version, SecurityQos->Capabilities, SecurityQos->IdentityTracking, SecurityQos->ImpersonationType); - if (SecurityQos->Version >= 2) - { - const RPC_SECURITY_QOS_V2_W *SecurityQos2 = (const RPC_SECURITY_QOS_V2_W *)SecurityQos; - TRACE(", AdditionalSecurityInfoType=%ld", SecurityQos2->AdditionalSecurityInfoType); - if (SecurityQos2->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP) - TRACE(", { %p, 0x%lx, %ld, %ld, %p, %s }", - SecurityQos2->u.HttpCredentials->TransportCredentials, - SecurityQos2->u.HttpCredentials->Flags, - SecurityQos2->u.HttpCredentials->AuthenticationTarget, - SecurityQos2->u.HttpCredentials->NumberOfAuthnSchemes, - SecurityQos2->u.HttpCredentials->AuthnSchemes, - debugstr_w(SecurityQos2->u.HttpCredentials->ServerCertificateSubject)); - } - TRACE("}\n"); - status = RpcQualityOfService_Create(SecurityQos, TRUE, &bind->QOS); - if (status != RPC_S_OK) - return status; - } - else - { - if (bind->QOS) RpcQualityOfService_Release(bind->QOS); - bind->QOS = NULL; - } - - if (AuthnSvc == RPC_C_AUTHN_DEFAULT) - AuthnSvc = RPC_C_AUTHN_WINNT; - - /* FIXME: the mapping should probably be retrieved using SSPI somehow */ - if (AuthnLevel == RPC_C_AUTHN_LEVEL_DEFAULT) - AuthnLevel = RPC_C_AUTHN_LEVEL_NONE; - - if ((AuthnLevel == RPC_C_AUTHN_LEVEL_NONE) || (AuthnSvc == RPC_C_AUTHN_NONE)) - { - if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo); - bind->AuthInfo = NULL; - return RPC_S_OK; - } - - if (AuthnLevel > RPC_C_AUTHN_LEVEL_PKT_PRIVACY) - { - FIXME("unknown AuthnLevel %u\n", AuthnLevel); - return RPC_S_UNKNOWN_AUTHN_LEVEL; - } - - if (AuthzSvr) - { - FIXME("unsupported AuthzSvr %u\n", AuthzSvr); - return RPC_S_UNKNOWN_AUTHZ_SERVICE; - } - - r = EnumerateSecurityPackagesW(&package_count, &packages); - if (r != SEC_E_OK) - { - ERR("EnumerateSecurityPackagesA failed with error 0x%08x\n", r); - return RPC_S_SEC_PKG_ERROR; - } - - for (i = 0; i < package_count; i++) - if (packages[i].wRPCID == AuthnSvc) - break; - - if (i == package_count) - { - FIXME("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); - r = AcquireCredentialsHandleW((SEC_WCHAR *)ServerPrincName, packages[i].Name, SECPKG_CRED_OUTBOUND, NULL, - AuthIdentity, NULL, NULL, &cred, &exp); - cbMaxToken = packages[i].cbMaxToken; - FreeContextBuffer(packages); - if (r == ERROR_SUCCESS) - { - if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo); - bind->AuthInfo = NULL; - r = RpcAuthInfo_Create(AuthnLevel, AuthnSvc, cred, exp, cbMaxToken, - AuthIdentity, &bind->AuthInfo); - if (r != RPC_S_OK) - FreeCredentialsHandle(&cred); - return RPC_S_OK; - } - else - { - ERR("AcquireCredentialsHandleA failed with error 0x%08x\n", r); - return RPC_S_SEC_PKG_ERROR; - } -} - -/*********************************************************************** - * RpcBindingSetAuthInfoA (RPCRT4.@) - */ -RPCRTAPI RPC_STATUS RPC_ENTRY -RpcBindingSetAuthInfoA( RPC_BINDING_HANDLE Binding, RPC_CSTR ServerPrincName, ULONG AuthnLevel, - ULONG AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr ) -{ - TRACE("%p %s %u %u %p %u\n", Binding, debugstr_a((const char*)ServerPrincName), - AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr); - return RpcBindingSetAuthInfoExA(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, NULL); -} - -/*********************************************************************** - * RpcBindingSetAuthInfoW (RPCRT4.@) - */ -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), - AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr); - return RpcBindingSetAuthInfoExW(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, NULL); -} - -/*********************************************************************** - * RpcBindingSetOption (RPCRT4.@) - */ -RPC_STATUS WINAPI RpcBindingSetOption(RPC_BINDING_HANDLE BindingHandle, ULONG Option, ULONG OptionValue) -{ - FIXME("(%p, %d, %d): stub\n", BindingHandle, Option, OptionValue); - return RPC_S_OK; -} +/* + * RPC binding API + * + * Copyright 2001 Ove Kåven, TransGaming Technologies + * Copyright 2003 Mike Hearn + * Copyright 2004 Filip Navara + * Copyright 2006 CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include +#include +#include + +#include "windef.h" +#include "winbase.h" +#include "winnls.h" +#include "winerror.h" +#include "winternl.h" +#include "wine/unicode.h" + +#include "rpc.h" +#include "rpcndr.h" + +#include "wine/debug.h" + +#include "rpc_binding.h" +#include "rpc_assoc.h" + +WINE_DEFAULT_DEBUG_CHANNEL(rpc); + +LPSTR RPCRT4_strndupA(LPCSTR src, INT slen) +{ + DWORD len; + LPSTR s; + if (!src) return NULL; + if (slen == -1) slen = strlen(src); + len = slen; + s = HeapAlloc(GetProcessHeap(), 0, len+1); + memcpy(s, src, len); + s[len] = 0; + return s; +} + +LPSTR RPCRT4_strdupWtoA(LPCWSTR src) +{ + DWORD len; + LPSTR s; + if (!src) return NULL; + len = WideCharToMultiByte(CP_ACP, 0, src, -1, NULL, 0, NULL, NULL); + s = HeapAlloc(GetProcessHeap(), 0, len); + WideCharToMultiByte(CP_ACP, 0, src, -1, s, len, NULL, NULL); + return s; +} + +LPWSTR RPCRT4_strdupAtoW(LPCSTR src) +{ + DWORD len; + LPWSTR s; + if (!src) return NULL; + len = MultiByteToWideChar(CP_ACP, 0, src, -1, NULL, 0); + s = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, src, -1, s, len); + return s; +} + +static LPWSTR RPCRT4_strndupAtoW(LPCSTR src, INT slen) +{ + DWORD len; + LPWSTR s; + if (!src) return NULL; + len = MultiByteToWideChar(CP_ACP, 0, src, slen, NULL, 0); + s = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, src, slen, s, len); + return s; +} + +LPWSTR RPCRT4_strndupW(LPCWSTR src, INT slen) +{ + DWORD len; + LPWSTR s; + if (!src) return NULL; + if (slen == -1) slen = strlenW(src); + len = slen; + s = HeapAlloc(GetProcessHeap(), 0, (len+1)*sizeof(WCHAR)); + memcpy(s, src, len*sizeof(WCHAR)); + s[len] = 0; + return s; +} + +void RPCRT4_strfree(LPSTR src) +{ + HeapFree(GetProcessHeap(), 0, src); +} + +static RPC_STATUS RPCRT4_AllocBinding(RpcBinding** Binding, BOOL server) +{ + RpcBinding* NewBinding; + + NewBinding = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcBinding)); + NewBinding->refs = 1; + NewBinding->server = server; + + *Binding = NewBinding; + + return RPC_S_OK; +} + +static RPC_STATUS RPCRT4_CreateBindingA(RpcBinding** Binding, BOOL server, LPCSTR Protseq) +{ + RpcBinding* NewBinding; + + RPCRT4_AllocBinding(&NewBinding, server); + NewBinding->Protseq = RPCRT4_strdupA(Protseq); + + TRACE("binding: %p\n", NewBinding); + *Binding = NewBinding; + + return RPC_S_OK; +} + +static RPC_STATUS RPCRT4_CreateBindingW(RpcBinding** Binding, BOOL server, LPCWSTR Protseq) +{ + RpcBinding* NewBinding; + + RPCRT4_AllocBinding(&NewBinding, server); + NewBinding->Protseq = RPCRT4_strdupWtoA(Protseq); + + TRACE("binding: %p\n", NewBinding); + *Binding = NewBinding; + + return RPC_S_OK; +} + +static RPC_STATUS RPCRT4_CompleteBindingA(RpcBinding* Binding, LPCSTR NetworkAddr, + LPCSTR Endpoint, LPCSTR NetworkOptions) +{ + RPC_STATUS status; + + TRACE("(RpcBinding == ^%p, NetworkAddr == %s, EndPoint == %s, NetworkOptions == %s)\n", Binding, + debugstr_a(NetworkAddr), debugstr_a(Endpoint), debugstr_a(NetworkOptions)); + + RPCRT4_strfree(Binding->NetworkAddr); + Binding->NetworkAddr = RPCRT4_strdupA(NetworkAddr); + RPCRT4_strfree(Binding->Endpoint); + if (Endpoint) { + Binding->Endpoint = RPCRT4_strdupA(Endpoint); + } else { + Binding->Endpoint = RPCRT4_strdupA(""); + } + HeapFree(GetProcessHeap(), 0, Binding->NetworkOptions); + Binding->NetworkOptions = RPCRT4_strdupAtoW(NetworkOptions); + if (!Binding->Endpoint) ERR("out of memory?\n"); + + status = RPCRT4_GetAssociation(Binding->Protseq, Binding->NetworkAddr, + Binding->Endpoint, Binding->NetworkOptions, + &Binding->Assoc); + if (status != RPC_S_OK) + return status; + + return RPC_S_OK; +} + +static RPC_STATUS RPCRT4_CompleteBindingW(RpcBinding* Binding, LPCWSTR NetworkAddr, + LPCWSTR Endpoint, LPCWSTR NetworkOptions) +{ + RPC_STATUS status; + + TRACE("(RpcBinding == ^%p, NetworkAddr == %s, EndPoint == %s, NetworkOptions == %s)\n", Binding, + debugstr_w(NetworkAddr), debugstr_w(Endpoint), debugstr_w(NetworkOptions)); + + RPCRT4_strfree(Binding->NetworkAddr); + Binding->NetworkAddr = RPCRT4_strdupWtoA(NetworkAddr); + RPCRT4_strfree(Binding->Endpoint); + if (Endpoint) { + Binding->Endpoint = RPCRT4_strdupWtoA(Endpoint); + } else { + Binding->Endpoint = RPCRT4_strdupA(""); + } + if (!Binding->Endpoint) ERR("out of memory?\n"); + HeapFree(GetProcessHeap(), 0, Binding->NetworkOptions); + Binding->NetworkOptions = RPCRT4_strdupW(NetworkOptions); + + status = RPCRT4_GetAssociation(Binding->Protseq, Binding->NetworkAddr, + Binding->Endpoint, Binding->NetworkOptions, + &Binding->Assoc); + if (status != RPC_S_OK) + return status; + + return RPC_S_OK; +} + +RPC_STATUS RPCRT4_ResolveBinding(RpcBinding* Binding, LPCSTR Endpoint) +{ + RPC_STATUS status; + + TRACE("(RpcBinding == ^%p, EndPoint == \"%s\"\n", Binding, Endpoint); + + RPCRT4_strfree(Binding->Endpoint); + Binding->Endpoint = RPCRT4_strdupA(Endpoint); + + RpcAssoc_Release(Binding->Assoc); + Binding->Assoc = NULL; + status = RPCRT4_GetAssociation(Binding->Protseq, Binding->NetworkAddr, + Binding->Endpoint, Binding->NetworkOptions, + &Binding->Assoc); + if (status != RPC_S_OK) + return status; + + return RPC_S_OK; +} + +RPC_STATUS RPCRT4_SetBindingObject(RpcBinding* Binding, const UUID* ObjectUuid) +{ + TRACE("(*RpcBinding == ^%p, UUID == %s)\n", Binding, debugstr_guid(ObjectUuid)); + if (ObjectUuid) memcpy(&Binding->ObjectUuid, ObjectUuid, sizeof(UUID)); + else UuidCreateNil(&Binding->ObjectUuid); + return RPC_S_OK; +} + +RPC_STATUS RPCRT4_MakeBinding(RpcBinding** Binding, RpcConnection* Connection) +{ + RpcBinding* NewBinding; + TRACE("(RpcBinding == ^%p, Connection == ^%p)\n", Binding, Connection); + + RPCRT4_AllocBinding(&NewBinding, Connection->server); + NewBinding->Protseq = RPCRT4_strdupA(rpcrt4_conn_get_name(Connection)); + NewBinding->NetworkAddr = RPCRT4_strdupA(Connection->NetworkAddr); + NewBinding->Endpoint = RPCRT4_strdupA(Connection->Endpoint); + NewBinding->FromConn = Connection; + + TRACE("binding: %p\n", NewBinding); + *Binding = NewBinding; + + return RPC_S_OK; +} + +RPC_STATUS RPCRT4_ExportBinding(RpcBinding** Binding, RpcBinding* OldBinding) +{ + InterlockedIncrement(&OldBinding->refs); + *Binding = OldBinding; + return RPC_S_OK; +} + +RPC_STATUS RPCRT4_DestroyBinding(RpcBinding* Binding) +{ + if (InterlockedDecrement(&Binding->refs)) + return RPC_S_OK; + + TRACE("binding: %p\n", Binding); + if (Binding->Assoc) RpcAssoc_Release(Binding->Assoc); + RPCRT4_strfree(Binding->Endpoint); + RPCRT4_strfree(Binding->NetworkAddr); + RPCRT4_strfree(Binding->Protseq); + HeapFree(GetProcessHeap(), 0, Binding->NetworkOptions); + if (Binding->AuthInfo) RpcAuthInfo_Release(Binding->AuthInfo); + if (Binding->QOS) RpcQualityOfService_Release(Binding->QOS); + HeapFree(GetProcessHeap(), 0, Binding); + return RPC_S_OK; +} + +RPC_STATUS RPCRT4_OpenBinding(RpcBinding* Binding, RpcConnection** Connection, + const RPC_SYNTAX_IDENTIFIER *TransferSyntax, + const RPC_SYNTAX_IDENTIFIER *InterfaceId) +{ + TRACE("(Binding == ^%p)\n", Binding); + + if (!Binding->server) { + return RpcAssoc_GetClientConnection(Binding->Assoc, InterfaceId, + TransferSyntax, Binding->AuthInfo, Binding->QOS, Connection); + } else { + /* we already have a connection with acceptable binding, so use it */ + if (Binding->FromConn) { + *Connection = Binding->FromConn; + return RPC_S_OK; + } else { + ERR("no connection in binding\n"); + return RPC_S_INTERNAL_ERROR; + } + } +} + +RPC_STATUS RPCRT4_CloseBinding(RpcBinding* Binding, RpcConnection* Connection) +{ + TRACE("(Binding == ^%p)\n", Binding); + if (!Connection) return RPC_S_OK; + if (Binding->server) { + /* don't destroy a connection that is cached in the binding */ + if (Binding->FromConn == Connection) + return RPC_S_OK; + return RPCRT4_DestroyConnection(Connection); + } + else { + RpcAssoc_ReleaseIdleConnection(Binding->Assoc, Connection); + return RPC_S_OK; + } +} + +/* utility functions for string composing and parsing */ +static unsigned RPCRT4_strcopyA(LPSTR data, LPCSTR src) +{ + unsigned len = strlen(src); + memcpy(data, src, len*sizeof(CHAR)); + return len; +} + +static unsigned RPCRT4_strcopyW(LPWSTR data, LPCWSTR src) +{ + unsigned len = strlenW(src); + memcpy(data, src, len*sizeof(WCHAR)); + return len; +} + +static LPSTR RPCRT4_strconcatA(LPSTR dst, LPCSTR src) +{ + DWORD len = strlen(dst), slen = strlen(src); + LPSTR ndst = HeapReAlloc(GetProcessHeap(), 0, dst, (len+slen+2)*sizeof(CHAR)); + if (!ndst) + { + HeapFree(GetProcessHeap(), 0, dst); + return NULL; + } + ndst[len] = ','; + memcpy(ndst+len+1, src, slen+1); + return ndst; +} + +static LPWSTR RPCRT4_strconcatW(LPWSTR dst, LPCWSTR src) +{ + DWORD len = strlenW(dst), slen = strlenW(src); + LPWSTR ndst = HeapReAlloc(GetProcessHeap(), 0, dst, (len+slen+2)*sizeof(WCHAR)); + if (!ndst) + { + HeapFree(GetProcessHeap(), 0, dst); + return NULL; + } + ndst[len] = ','; + memcpy(ndst+len+1, src, (slen+1)*sizeof(WCHAR)); + return ndst; +} + + +/*********************************************************************** + * RpcStringBindingComposeA (RPCRT4.@) + */ +RPC_STATUS WINAPI RpcStringBindingComposeA(RPC_CSTR ObjUuid, RPC_CSTR Protseq, + RPC_CSTR NetworkAddr, RPC_CSTR Endpoint, + RPC_CSTR Options, RPC_CSTR *StringBinding ) +{ + DWORD len = 1; + LPSTR data; + + TRACE( "(%s,%s,%s,%s,%s,%p)\n", + debugstr_a( (char*)ObjUuid ), debugstr_a( (char*)Protseq ), + debugstr_a( (char*)NetworkAddr ), debugstr_a( (char*)Endpoint ), + debugstr_a( (char*)Options ), StringBinding ); + + if (ObjUuid && *ObjUuid) len += strlen((char*)ObjUuid) + 1; + if (Protseq && *Protseq) len += strlen((char*)Protseq) + 1; + if (NetworkAddr && *NetworkAddr) len += strlen((char*)NetworkAddr); + if (Endpoint && *Endpoint) len += strlen((char*)Endpoint) + 2; + if (Options && *Options) len += strlen((char*)Options) + 2; + + data = HeapAlloc(GetProcessHeap(), 0, len); + *StringBinding = (unsigned char*)data; + + if (ObjUuid && *ObjUuid) { + data += RPCRT4_strcopyA(data, (char*)ObjUuid); + *data++ = '@'; + } + if (Protseq && *Protseq) { + data += RPCRT4_strcopyA(data, (char*)Protseq); + *data++ = ':'; + } + if (NetworkAddr && *NetworkAddr) + data += RPCRT4_strcopyA(data, (char*)NetworkAddr); + + if ((Endpoint && *Endpoint) || + (Options && *Options)) { + *data++ = '['; + if (Endpoint && *Endpoint) { + data += RPCRT4_strcopyA(data, (char*)Endpoint); + if (Options && *Options) *data++ = ','; + } + if (Options && *Options) { + data += RPCRT4_strcopyA(data, (char*)Options); + } + *data++ = ']'; + } + *data = 0; + + return RPC_S_OK; +} + +/*********************************************************************** + * RpcStringBindingComposeW (RPCRT4.@) + */ +RPC_STATUS WINAPI RpcStringBindingComposeW( RPC_WSTR ObjUuid, RPC_WSTR Protseq, + RPC_WSTR NetworkAddr, RPC_WSTR Endpoint, + RPC_WSTR Options, RPC_WSTR* StringBinding ) +{ + DWORD len = 1; + RPC_WSTR data; + + TRACE("(%s,%s,%s,%s,%s,%p)\n", + debugstr_w( ObjUuid ), debugstr_w( Protseq ), + debugstr_w( NetworkAddr ), debugstr_w( Endpoint ), + debugstr_w( Options ), StringBinding); + + if (ObjUuid && *ObjUuid) len += strlenW(ObjUuid) + 1; + if (Protseq && *Protseq) len += strlenW(Protseq) + 1; + if (NetworkAddr && *NetworkAddr) len += strlenW(NetworkAddr); + if (Endpoint && *Endpoint) len += strlenW(Endpoint) + 2; + if (Options && *Options) len += strlenW(Options) + 2; + + data = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR)); + *StringBinding = data; + + if (ObjUuid && *ObjUuid) { + data += RPCRT4_strcopyW(data, ObjUuid); + *data++ = '@'; + } + if (Protseq && *Protseq) { + data += RPCRT4_strcopyW(data, Protseq); + *data++ = ':'; + } + if (NetworkAddr && *NetworkAddr) { + data += RPCRT4_strcopyW(data, NetworkAddr); + } + if ((Endpoint && *Endpoint) || + (Options && *Options)) { + *data++ = '['; + if (Endpoint && *Endpoint) { + data += RPCRT4_strcopyW(data, Endpoint); + if (Options && *Options) *data++ = ','; + } + if (Options && *Options) { + data += RPCRT4_strcopyW(data, Options); + } + *data++ = ']'; + } + *data = 0; + + return RPC_S_OK; +} + + +/*********************************************************************** + * RpcStringBindingParseA (RPCRT4.@) + */ +RPC_STATUS WINAPI RpcStringBindingParseA( RPC_CSTR StringBinding, RPC_CSTR *ObjUuid, + RPC_CSTR *Protseq, RPC_CSTR *NetworkAddr, + RPC_CSTR *Endpoint, RPC_CSTR *Options) +{ + CHAR *data, *next; + static const char ep_opt[] = "endpoint="; + + TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_a((char*)StringBinding), + ObjUuid, Protseq, NetworkAddr, Endpoint, Options); + + if (ObjUuid) *ObjUuid = NULL; + if (Protseq) *Protseq = NULL; + if (NetworkAddr) *NetworkAddr = NULL; + if (Endpoint) *Endpoint = NULL; + if (Options) *Options = NULL; + + data = (char*) StringBinding; + + next = strchr(data, '@'); + if (next) { + if (ObjUuid) *ObjUuid = (unsigned char*)RPCRT4_strndupA(data, next - data); + data = next+1; + } + + next = strchr(data, ':'); + if (next) { + if (Protseq) *Protseq = (unsigned char*)RPCRT4_strndupA(data, next - data); + data = next+1; + } + + next = strchr(data, '['); + if (next) { + CHAR *close, *opt; + + if (NetworkAddr) *NetworkAddr = (unsigned char*)RPCRT4_strndupA(data, next - data); + data = next+1; + close = strchr(data, ']'); + if (!close) goto fail; + + /* tokenize options */ + while (data < close) { + next = strchr(data, ','); + if (!next || next > close) next = close; + /* FIXME: this is kind of inefficient */ + opt = RPCRT4_strndupA(data, next - data); + data = next+1; + + /* parse option */ + next = strchr(opt, '='); + if (!next) { + /* not an option, must be an endpoint */ + if (*Endpoint) goto fail; + *Endpoint = (unsigned char*) opt; + } else { + if (strncmp(opt, ep_opt, strlen(ep_opt)) == 0) { + /* endpoint option */ + if (*Endpoint) goto fail; + *Endpoint = (unsigned char*) RPCRT4_strdupA(next+1); + HeapFree(GetProcessHeap(), 0, opt); + } else { + /* network option */ + if (*Options) { + /* FIXME: this is kind of inefficient */ + *Options = (unsigned char*) RPCRT4_strconcatA( (char*)*Options, opt); + HeapFree(GetProcessHeap(), 0, opt); + } else + *Options = (unsigned char*) opt; + } + } + } + + data = close+1; + if (*data) goto fail; + } + else if (NetworkAddr) + *NetworkAddr = (unsigned char*)RPCRT4_strdupA(data); + + 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); + return RPC_S_INVALID_STRING_BINDING; +} + +/*********************************************************************** + * RpcStringBindingParseW (RPCRT4.@) + */ +RPC_STATUS WINAPI RpcStringBindingParseW( RPC_WSTR StringBinding, RPC_WSTR *ObjUuid, + RPC_WSTR *Protseq, RPC_WSTR *NetworkAddr, + RPC_WSTR *Endpoint, RPC_WSTR *Options) +{ + WCHAR *data, *next; + static const WCHAR ep_opt[] = {'e','n','d','p','o','i','n','t','=',0}; + + TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_w(StringBinding), + ObjUuid, Protseq, NetworkAddr, Endpoint, Options); + + if (ObjUuid) *ObjUuid = NULL; + if (Protseq) *Protseq = NULL; + if (NetworkAddr) *NetworkAddr = NULL; + if (Endpoint) *Endpoint = NULL; + if (Options) *Options = NULL; + + data = StringBinding; + + next = strchrW(data, '@'); + if (next) { + if (ObjUuid) *ObjUuid = RPCRT4_strndupW(data, next - data); + data = next+1; + } + + next = strchrW(data, ':'); + if (next) { + if (Protseq) *Protseq = RPCRT4_strndupW(data, next - data); + data = next+1; + } + + next = strchrW(data, '['); + if (next) { + WCHAR *close, *opt; + + if (NetworkAddr) *NetworkAddr = RPCRT4_strndupW(data, next - data); + data = next+1; + close = strchrW(data, ']'); + if (!close) goto fail; + + /* tokenize options */ + while (data < close) { + next = strchrW(data, ','); + if (!next || next > close) next = close; + /* FIXME: this is kind of inefficient */ + opt = RPCRT4_strndupW(data, next - data); + data = next+1; + + /* parse option */ + next = strchrW(opt, '='); + if (!next) { + /* not an option, must be an endpoint */ + if (*Endpoint) goto fail; + *Endpoint = opt; + } else { + if (strncmpW(opt, ep_opt, strlenW(ep_opt)) == 0) { + /* endpoint option */ + if (*Endpoint) goto fail; + *Endpoint = RPCRT4_strdupW(next+1); + HeapFree(GetProcessHeap(), 0, opt); + } else { + /* network option */ + if (*Options) { + /* FIXME: this is kind of inefficient */ + *Options = RPCRT4_strconcatW(*Options, opt); + HeapFree(GetProcessHeap(), 0, opt); + } else + *Options = opt; + } + } + } + + data = close+1; + if (*data) goto fail; + } else if (NetworkAddr) + *NetworkAddr = RPCRT4_strdupW(data); + + return RPC_S_OK; + +fail: + if (ObjUuid) RpcStringFreeW(ObjUuid); + if (Protseq) RpcStringFreeW(Protseq); + if (NetworkAddr) RpcStringFreeW(NetworkAddr); + if (Endpoint) RpcStringFreeW(Endpoint); + if (Options) RpcStringFreeW(Options); + return RPC_S_INVALID_STRING_BINDING; +} + +/*********************************************************************** + * RpcBindingFree (RPCRT4.@) + */ +RPC_STATUS WINAPI RpcBindingFree( RPC_BINDING_HANDLE* Binding ) +{ + RPC_STATUS status; + TRACE("(%p) = %p\n", Binding, *Binding); + status = RPCRT4_DestroyBinding(*Binding); + if (status == RPC_S_OK) *Binding = 0; + return status; +} + +/*********************************************************************** + * RpcBindingVectorFree (RPCRT4.@) + */ +RPC_STATUS WINAPI RpcBindingVectorFree( RPC_BINDING_VECTOR** BindingVector ) +{ + RPC_STATUS status; + unsigned long c; + + TRACE("(%p)\n", BindingVector); + for (c=0; c<(*BindingVector)->Count; c++) { + status = RpcBindingFree(&(*BindingVector)->BindingH[c]); + } + HeapFree(GetProcessHeap(), 0, *BindingVector); + *BindingVector = NULL; + return RPC_S_OK; +} + +/*********************************************************************** + * RpcBindingInqObject (RPCRT4.@) + */ +RPC_STATUS WINAPI RpcBindingInqObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid ) +{ + RpcBinding* bind = (RpcBinding*)Binding; + + TRACE("(%p,%p) = %s\n", Binding, ObjectUuid, debugstr_guid(&bind->ObjectUuid)); + memcpy(ObjectUuid, &bind->ObjectUuid, sizeof(UUID)); + return RPC_S_OK; +} + +/*********************************************************************** + * RpcBindingSetObject (RPCRT4.@) + */ +RPC_STATUS WINAPI RpcBindingSetObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid ) +{ + RpcBinding* bind = (RpcBinding*)Binding; + + TRACE("(%p,%s)\n", Binding, debugstr_guid(ObjectUuid)); + if (bind->server) return RPC_S_WRONG_KIND_OF_BINDING; + return RPCRT4_SetBindingObject(Binding, ObjectUuid); +} + +/*********************************************************************** + * RpcBindingFromStringBindingA (RPCRT4.@) + */ +RPC_STATUS WINAPI RpcBindingFromStringBindingA( RPC_CSTR StringBinding, RPC_BINDING_HANDLE* Binding ) +{ + RPC_STATUS ret; + RpcBinding* bind = NULL; + RPC_CSTR ObjectUuid, Protseq, NetworkAddr, Endpoint, Options; + UUID Uuid; + + TRACE("(%s,%p)\n", debugstr_a((char*)StringBinding), Binding); + + ret = RpcStringBindingParseA(StringBinding, &ObjectUuid, &Protseq, + &NetworkAddr, &Endpoint, &Options); + if (ret != RPC_S_OK) return ret; + + ret = UuidFromStringA(ObjectUuid, &Uuid); + + if (ret == RPC_S_OK) + ret = RPCRT4_CreateBindingA(&bind, FALSE, (char*)Protseq); + if (ret == RPC_S_OK) + ret = RPCRT4_SetBindingObject(bind, &Uuid); + 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); + + if (ret == RPC_S_OK) + *Binding = (RPC_BINDING_HANDLE)bind; + else + RPCRT4_DestroyBinding(bind); + + return ret; +} + +/*********************************************************************** + * RpcBindingFromStringBindingW (RPCRT4.@) + */ +RPC_STATUS WINAPI RpcBindingFromStringBindingW( RPC_WSTR StringBinding, RPC_BINDING_HANDLE* Binding ) +{ + RPC_STATUS ret; + RpcBinding* bind = NULL; + RPC_WSTR ObjectUuid, Protseq, NetworkAddr, Endpoint, Options; + UUID Uuid; + + TRACE("(%s,%p)\n", debugstr_w(StringBinding), Binding); + + ret = RpcStringBindingParseW(StringBinding, &ObjectUuid, &Protseq, + &NetworkAddr, &Endpoint, &Options); + if (ret != RPC_S_OK) return ret; + + ret = UuidFromStringW(ObjectUuid, &Uuid); + + if (ret == RPC_S_OK) + ret = RPCRT4_CreateBindingW(&bind, FALSE, Protseq); + if (ret == RPC_S_OK) + ret = RPCRT4_SetBindingObject(bind, &Uuid); + if (ret == RPC_S_OK) + ret = RPCRT4_CompleteBindingW(bind, NetworkAddr, Endpoint, Options); + + RpcStringFreeW(&Options); + RpcStringFreeW(&Endpoint); + RpcStringFreeW(&NetworkAddr); + RpcStringFreeW(&Protseq); + RpcStringFreeW(&ObjectUuid); + + if (ret == RPC_S_OK) + *Binding = (RPC_BINDING_HANDLE)bind; + else + RPCRT4_DestroyBinding(bind); + + return ret; +} + +/*********************************************************************** + * RpcBindingToStringBindingA (RPCRT4.@) + */ +RPC_STATUS WINAPI RpcBindingToStringBindingA( RPC_BINDING_HANDLE Binding, RPC_CSTR *StringBinding ) +{ + RPC_STATUS ret; + RpcBinding* bind = (RpcBinding*)Binding; + RPC_CSTR ObjectUuid; + + TRACE("(%p,%p)\n", Binding, StringBinding); + + ret = UuidToStringA(&bind->ObjectUuid, &ObjectUuid); + if (ret != RPC_S_OK) return ret; + + ret = RpcStringBindingComposeA(ObjectUuid, (unsigned char*)bind->Protseq, (unsigned char*) bind->NetworkAddr, + (unsigned char*) bind->Endpoint, NULL, StringBinding); + + RpcStringFreeA(&ObjectUuid); + + return ret; +} + +/*********************************************************************** + * RpcBindingToStringBindingW (RPCRT4.@) + */ +RPC_STATUS WINAPI RpcBindingToStringBindingW( RPC_BINDING_HANDLE Binding, RPC_WSTR *StringBinding ) +{ + RPC_STATUS ret; + unsigned char *str = NULL; + TRACE("(%p,%p)\n", Binding, StringBinding); + ret = RpcBindingToStringBindingA(Binding, &str); + *StringBinding = RPCRT4_strdupAtoW((char*)str); + RpcStringFreeA((unsigned char**)&str); + return ret; +} + +/*********************************************************************** + * I_RpcBindingSetAsync (RPCRT4.@) + * NOTES + * Exists in win9x and winNT, but with different number of arguments + * (9x version has 3 arguments, NT has 2). + */ +RPC_STATUS WINAPI I_RpcBindingSetAsync( RPC_BINDING_HANDLE Binding, RPC_BLOCKING_FN BlockingFn) +{ + RpcBinding* bind = (RpcBinding*)Binding; + + TRACE( "(%p,%p): stub\n", Binding, BlockingFn ); + + bind->BlockingFn = BlockingFn; + + return RPC_S_OK; +} + +/*********************************************************************** + * RpcBindingCopy (RPCRT4.@) + */ +RPC_STATUS RPC_ENTRY RpcBindingCopy( + RPC_BINDING_HANDLE SourceBinding, + RPC_BINDING_HANDLE* DestinationBinding) +{ + RpcBinding *DestBinding; + RpcBinding *SrcBinding = (RpcBinding*)SourceBinding; + RPC_STATUS status; + + TRACE("(%p, %p)\n", SourceBinding, DestinationBinding); + + status = RPCRT4_AllocBinding(&DestBinding, SrcBinding->server); + if (status != RPC_S_OK) return status; + + DestBinding->ObjectUuid = SrcBinding->ObjectUuid; + DestBinding->BlockingFn = SrcBinding->BlockingFn; + DestBinding->Protseq = RPCRT4_strndupA(SrcBinding->Protseq, -1); + DestBinding->NetworkAddr = RPCRT4_strndupA(SrcBinding->NetworkAddr, -1); + DestBinding->Endpoint = RPCRT4_strndupA(SrcBinding->Endpoint, -1); + DestBinding->NetworkOptions = RPCRT4_strdupW(SrcBinding->NetworkOptions); + if (SrcBinding->Assoc) SrcBinding->Assoc->refs++; + DestBinding->Assoc = SrcBinding->Assoc; + + if (SrcBinding->AuthInfo) RpcAuthInfo_AddRef(SrcBinding->AuthInfo); + DestBinding->AuthInfo = SrcBinding->AuthInfo; + if (SrcBinding->QOS) RpcQualityOfService_AddRef(SrcBinding->QOS); + DestBinding->QOS = SrcBinding->QOS; + + *DestinationBinding = DestBinding; + return RPC_S_OK; +} + +/*********************************************************************** + * RpcImpersonateClient (RPCRT4.@) + * + * Impersonates the client connected via a binding handle so that security + * checks are done in the context of the client. + * + * PARAMS + * BindingHandle [I] Handle to the binding to the client. + * + * RETURNS + * Success: RPS_S_OK. + * Failure: RPC_STATUS value. + * + * NOTES + * + * If BindingHandle is NULL then the function impersonates the client + * connected to the binding handle of the current thread. + */ +RPC_STATUS WINAPI RpcImpersonateClient(RPC_BINDING_HANDLE BindingHandle) +{ + FIXME("(%p): stub\n", BindingHandle); + ImpersonateSelf(SecurityImpersonation); + return RPC_S_OK; +} + +/*********************************************************************** + * RpcRevertToSelfEx (RPCRT4.@) + * + * Stops impersonating the client connected to the binding handle so that security + * checks are no longer done in the context of the client. + * + * PARAMS + * BindingHandle [I] Handle to the binding to the client. + * + * RETURNS + * Success: RPS_S_OK. + * Failure: RPC_STATUS value. + * + * NOTES + * + * If BindingHandle is NULL then the function stops impersonating the client + * connected to the binding handle of the current thread. + */ +RPC_STATUS WINAPI RpcRevertToSelfEx(RPC_BINDING_HANDLE BindingHandle) +{ + FIXME("(%p): stub\n", BindingHandle); + return RPC_S_OK; +} + +static inline BOOL has_nt_auth_identity(ULONG AuthnLevel) +{ + switch (AuthnLevel) + { + case RPC_C_AUTHN_GSS_NEGOTIATE: + case RPC_C_AUTHN_WINNT: + case RPC_C_AUTHN_GSS_KERBEROS: + return TRUE; + default: + return FALSE; + } +} + +static 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) + return ERROR_OUTOFMEMORY; + + AuthInfo->refs = 1; + AuthInfo->AuthnLevel = AuthnLevel; + AuthInfo->AuthnSvc = AuthnSvc; + AuthInfo->cred = cred; + AuthInfo->exp = exp; + AuthInfo->cbMaxToken = cbMaxToken; + AuthInfo->identity = identity; + + /* duplicate the SEC_WINNT_AUTH_IDENTITY structure, if applicable, to + * enable better matching in RpcAuthInfo_IsEqual */ + if (identity && has_nt_auth_identity(AuthnSvc)) + { + const SEC_WINNT_AUTH_IDENTITY_W *nt_identity = identity; + AuthInfo->nt_identity = HeapAlloc(GetProcessHeap(), 0, sizeof(*AuthInfo->nt_identity)); + if (!AuthInfo->nt_identity) + { + HeapFree(GetProcessHeap(), 0, AuthInfo); + return ERROR_OUTOFMEMORY; + } + + AuthInfo->nt_identity->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; + if (nt_identity->Flags & SEC_WINNT_AUTH_IDENTITY_UNICODE) + AuthInfo->nt_identity->User = RPCRT4_strndupW(nt_identity->User, nt_identity->UserLength); + else + AuthInfo->nt_identity->User = RPCRT4_strndupAtoW((const char *)nt_identity->User, nt_identity->UserLength); + AuthInfo->nt_identity->UserLength = nt_identity->UserLength; + if (nt_identity->Flags & SEC_WINNT_AUTH_IDENTITY_UNICODE) + AuthInfo->nt_identity->Domain = RPCRT4_strndupW(nt_identity->Domain, nt_identity->DomainLength); + else + AuthInfo->nt_identity->Domain = RPCRT4_strndupAtoW((const char *)nt_identity->Domain, nt_identity->DomainLength); + AuthInfo->nt_identity->DomainLength = nt_identity->DomainLength; + if (nt_identity->Flags & SEC_WINNT_AUTH_IDENTITY_UNICODE) + AuthInfo->nt_identity->Password = RPCRT4_strndupW(nt_identity->Password, nt_identity->PasswordLength); + else + AuthInfo->nt_identity->Password = RPCRT4_strndupAtoW((const char *)nt_identity->Password, nt_identity->PasswordLength); + AuthInfo->nt_identity->PasswordLength = nt_identity->PasswordLength; + + if (!AuthInfo->nt_identity->User || + !AuthInfo->nt_identity->Domain || + !AuthInfo->nt_identity->Password) + { + HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->User); + HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->Domain); + HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->Password); + HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity); + HeapFree(GetProcessHeap(), 0, AuthInfo); + return ERROR_OUTOFMEMORY; + } + } + else + AuthInfo->nt_identity = NULL; + *ret = AuthInfo; + return RPC_S_OK; +} + +ULONG RpcAuthInfo_AddRef(RpcAuthInfo *AuthInfo) +{ + return InterlockedIncrement(&AuthInfo->refs); +} + +ULONG RpcAuthInfo_Release(RpcAuthInfo *AuthInfo) +{ + ULONG refs = InterlockedDecrement(&AuthInfo->refs); + + if (!refs) + { + FreeCredentialsHandle(&AuthInfo->cred); + if (AuthInfo->nt_identity) + { + HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->User); + HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->Domain); + HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->Password); + HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity); + } + HeapFree(GetProcessHeap(), 0, AuthInfo); + } + + return refs; +} + +BOOL RpcAuthInfo_IsEqual(const RpcAuthInfo *AuthInfo1, const RpcAuthInfo *AuthInfo2) +{ + if (AuthInfo1 == AuthInfo2) + return TRUE; + + if (!AuthInfo1 || !AuthInfo2) + return FALSE; + + if ((AuthInfo1->AuthnLevel != AuthInfo2->AuthnLevel) || + (AuthInfo1->AuthnSvc != AuthInfo2->AuthnSvc)) + return FALSE; + + if (AuthInfo1->identity == AuthInfo2->identity) + return TRUE; + + if (!AuthInfo1->identity || !AuthInfo2->identity) + return FALSE; + + if (has_nt_auth_identity(AuthInfo1->AuthnSvc)) + { + const SEC_WINNT_AUTH_IDENTITY_W *identity1 = AuthInfo1->nt_identity; + const SEC_WINNT_AUTH_IDENTITY_W *identity2 = AuthInfo2->nt_identity; + /* compare user names */ + if (identity1->UserLength != identity2->UserLength || + memcmp(identity1->User, identity2->User, identity1->UserLength)) + return FALSE; + /* compare domain names */ + if (identity1->DomainLength != identity2->DomainLength || + memcmp(identity1->Domain, identity2->Domain, identity1->DomainLength)) + return FALSE; + /* compare passwords */ + if (identity1->PasswordLength != identity2->PasswordLength || + memcmp(identity1->Password, identity2->Password, identity1->PasswordLength)) + return FALSE; + } + else + return FALSE; + + return TRUE; +} + +static RPC_STATUS RpcQualityOfService_Create(const RPC_SECURITY_QOS *qos_src, BOOL unicode, RpcQualityOfService **qos_dst) +{ + RpcQualityOfService *qos = HeapAlloc(GetProcessHeap(), 0, sizeof(*qos)); + + if (!qos) + return RPC_S_OUT_OF_RESOURCES; + + qos->refs = 1; + qos->qos = HeapAlloc(GetProcessHeap(), 0, sizeof(*qos->qos)); + if (!qos->qos) goto error; + qos->qos->Version = qos_src->Version; + qos->qos->Capabilities = qos_src->Capabilities; + qos->qos->IdentityTracking = qos_src->IdentityTracking; + qos->qos->ImpersonationType = qos_src->ImpersonationType; + qos->qos->AdditionalSecurityInfoType = 0; + + if (qos_src->Version >= 2) + { + const RPC_SECURITY_QOS_V2_W *qos_src2 = (const RPC_SECURITY_QOS_V2_W *)qos_src; + qos->qos->AdditionalSecurityInfoType = qos_src2->AdditionalSecurityInfoType; + if (qos_src2->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP) + { + const RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_credentials_src = qos_src2->u.HttpCredentials; + RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_credentials_dst; + + http_credentials_dst = HeapAlloc(GetProcessHeap(), 0, sizeof(*http_credentials_dst)); + qos->qos->u.HttpCredentials = http_credentials_dst; + if (!http_credentials_dst) goto error; + http_credentials_dst->TransportCredentials = NULL; + http_credentials_dst->Flags = http_credentials_src->Flags; + http_credentials_dst->AuthenticationTarget = http_credentials_src->AuthenticationTarget; + http_credentials_dst->NumberOfAuthnSchemes = http_credentials_src->NumberOfAuthnSchemes; + http_credentials_dst->AuthnSchemes = NULL; + http_credentials_dst->ServerCertificateSubject = NULL; + if (http_credentials_src->TransportCredentials) + { + SEC_WINNT_AUTH_IDENTITY_W *cred_dst; + cred_dst = http_credentials_dst->TransportCredentials = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*cred_dst)); + if (!cred_dst) goto error; + cred_dst->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; + if (unicode) + { + const SEC_WINNT_AUTH_IDENTITY_W *cred_src = http_credentials_src->TransportCredentials; + cred_dst->UserLength = cred_src->UserLength; + cred_dst->PasswordLength = cred_src->PasswordLength; + cred_dst->DomainLength = cred_src->DomainLength; + cred_dst->User = RPCRT4_strndupW(cred_src->User, cred_src->UserLength); + cred_dst->Password = RPCRT4_strndupW(cred_src->Password, cred_src->PasswordLength); + cred_dst->Domain = RPCRT4_strndupW(cred_src->Domain, cred_src->DomainLength); + } + else + { + const SEC_WINNT_AUTH_IDENTITY_A *cred_src = (const SEC_WINNT_AUTH_IDENTITY_A *)http_credentials_src->TransportCredentials; + cred_dst->UserLength = MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->User, cred_src->UserLength, NULL, 0); + cred_dst->DomainLength = MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->Domain, cred_src->DomainLength, NULL, 0); + cred_dst->PasswordLength = MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->Password, cred_src->PasswordLength, NULL, 0); + 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; + 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); + } + } + if (http_credentials_src->NumberOfAuthnSchemes) + { + http_credentials_dst->AuthnSchemes = HeapAlloc(GetProcessHeap(), 0, http_credentials_src->NumberOfAuthnSchemes * sizeof(*http_credentials_dst->AuthnSchemes)); + if (!http_credentials_dst->AuthnSchemes) goto error; + memcpy(http_credentials_dst->AuthnSchemes, http_credentials_src->AuthnSchemes, http_credentials_src->NumberOfAuthnSchemes * sizeof(*http_credentials_dst->AuthnSchemes)); + } + if (http_credentials_src->ServerCertificateSubject) + { + if (unicode) + http_credentials_dst->ServerCertificateSubject = + RPCRT4_strndupW(http_credentials_src->ServerCertificateSubject, + strlenW(http_credentials_src->ServerCertificateSubject)); + else + http_credentials_dst->ServerCertificateSubject = + RPCRT4_strdupAtoW((char *)http_credentials_src->ServerCertificateSubject); + if (!http_credentials_dst->ServerCertificateSubject) goto error; + } + } + } + *qos_dst = qos; + return RPC_S_OK; + +error: + if (qos->qos) + { + if (qos->qos->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP && + qos->qos->u.HttpCredentials) + { + if (qos->qos->u.HttpCredentials->TransportCredentials) + { + HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->User); + HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->Domain); + HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->Password); + HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials); + } + HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->AuthnSchemes); + HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->ServerCertificateSubject); + HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials); + } + HeapFree(GetProcessHeap(), 0, qos->qos); + } + HeapFree(GetProcessHeap(), 0, qos); + return RPC_S_OUT_OF_RESOURCES; +} + +ULONG RpcQualityOfService_AddRef(RpcQualityOfService *qos) +{ + return InterlockedIncrement(&qos->refs); +} + +ULONG RpcQualityOfService_Release(RpcQualityOfService *qos) +{ + ULONG refs = InterlockedDecrement(&qos->refs); + + if (!refs) + { + if (qos->qos->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP) + { + if (qos->qos->u.HttpCredentials->TransportCredentials) + { + HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->User); + HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->Domain); + HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->Password); + HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials); + } + HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->AuthnSchemes); + HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->ServerCertificateSubject); + HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials); + } + HeapFree(GetProcessHeap(), 0, qos->qos); + HeapFree(GetProcessHeap(), 0, qos); + } + return refs; +} + +BOOL RpcQualityOfService_IsEqual(const RpcQualityOfService *qos1, const RpcQualityOfService *qos2) +{ + if (qos1 == qos2) + return TRUE; + + if (!qos1 || !qos2) + return FALSE; + + TRACE("qos1 = { %ld %ld %ld %ld }, qos2 = { %ld %ld %ld %ld }\n", + qos1->qos->Capabilities, qos1->qos->IdentityTracking, + qos1->qos->ImpersonationType, qos1->qos->AdditionalSecurityInfoType, + qos2->qos->Capabilities, qos2->qos->IdentityTracking, + qos2->qos->ImpersonationType, qos2->qos->AdditionalSecurityInfoType); + + if ((qos1->qos->Capabilities != qos2->qos->Capabilities) || + (qos1->qos->IdentityTracking != qos2->qos->IdentityTracking) || + (qos1->qos->ImpersonationType != qos2->qos->ImpersonationType) || + (qos1->qos->AdditionalSecurityInfoType != qos2->qos->AdditionalSecurityInfoType)) + return FALSE; + + if (qos1->qos->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP) + { + const RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_credentials1 = qos1->qos->u.HttpCredentials; + const RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_credentials2 = qos2->qos->u.HttpCredentials; + + if (http_credentials1->Flags != http_credentials2->Flags) + return FALSE; + + if (http_credentials1->AuthenticationTarget != http_credentials2->AuthenticationTarget) + return FALSE; + + /* authentication schemes and server certificate subject not currently used */ + + if (http_credentials1->TransportCredentials != http_credentials2->TransportCredentials) + { + const SEC_WINNT_AUTH_IDENTITY_W *identity1 = http_credentials1->TransportCredentials; + const SEC_WINNT_AUTH_IDENTITY_W *identity2 = http_credentials2->TransportCredentials; + + if (!identity1 || !identity2) + return FALSE; + + /* compare user names */ + if (identity1->UserLength != identity2->UserLength || + memcmp(identity1->User, identity2->User, identity1->UserLength)) + return FALSE; + /* compare domain names */ + if (identity1->DomainLength != identity2->DomainLength || + memcmp(identity1->Domain, identity2->Domain, identity1->DomainLength)) + return FALSE; + /* compare passwords */ + if (identity1->PasswordLength != identity2->PasswordLength || + memcmp(identity1->Password, identity2->Password, identity1->PasswordLength)) + return FALSE; + } + } + + return TRUE; +} + +/*********************************************************************** + * RpcRevertToSelf (RPCRT4.@) + */ +RPC_STATUS WINAPI RpcRevertToSelf(void) +{ + FIXME("stub\n"); + RevertToSelf(); + return RPC_S_OK; +} + +/*********************************************************************** + * RpcMgmtSetComTimeout (RPCRT4.@) + */ +RPC_STATUS WINAPI RpcMgmtSetComTimeout(RPC_BINDING_HANDLE BindingHandle, unsigned int Timeout) +{ + FIXME("(%p, %d): stub\n", BindingHandle, Timeout); + return RPC_S_OK; +} + +/*********************************************************************** + * RpcBindingInqAuthInfoExA (RPCRT4.@) + */ +RPCRTAPI RPC_STATUS RPC_ENTRY +RpcBindingInqAuthInfoExA( RPC_BINDING_HANDLE Binding, RPC_CSTR *ServerPrincName, ULONG *AuthnLevel, + 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, + AuthnSvc, AuthIdentity, AuthzSvc, RpcQosVersion, SecurityQOS); + return RPC_S_INVALID_BINDING; +} + +/*********************************************************************** + * RpcBindingInqAuthInfoExW (RPCRT4.@) + */ +RPCRTAPI RPC_STATUS RPC_ENTRY +RpcBindingInqAuthInfoExW( RPC_BINDING_HANDLE Binding, RPC_WSTR *ServerPrincName, ULONG *AuthnLevel, + 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, + AuthnSvc, AuthIdentity, AuthzSvc, RpcQosVersion, SecurityQOS); + return RPC_S_INVALID_BINDING; +} + +/*********************************************************************** + * RpcBindingInqAuthInfoA (RPCRT4.@) + */ +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; +} + +/*********************************************************************** + * RpcBindingInqAuthInfoW (RPCRT4.@) + */ +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; +} + +/*********************************************************************** + * RpcBindingSetAuthInfoExA (RPCRT4.@) + */ +RPCRTAPI RPC_STATUS RPC_ENTRY +RpcBindingSetAuthInfoExA( RPC_BINDING_HANDLE Binding, RPC_CSTR ServerPrincName, + ULONG AuthnLevel, ULONG AuthnSvc, + RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr, + RPC_SECURITY_QOS *SecurityQos ) +{ + RpcBinding* bind = (RpcBinding*)Binding; + SECURITY_STATUS r; + CredHandle cred; + TimeStamp exp; + ULONG package_count; + ULONG i; + PSecPkgInfoA packages; + ULONG cbMaxToken; + + TRACE("%p %s %u %u %p %u %p\n", Binding, debugstr_a((const char*)ServerPrincName), + AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, SecurityQos); + + if (SecurityQos) + { + RPC_STATUS status; + + TRACE("SecurityQos { Version=%ld, Capabilties=0x%lx, IdentityTracking=%ld, ImpersonationLevel=%ld", + SecurityQos->Version, SecurityQos->Capabilities, SecurityQos->IdentityTracking, SecurityQos->ImpersonationType); + if (SecurityQos->Version >= 2) + { + const RPC_SECURITY_QOS_V2_A *SecurityQos2 = (const RPC_SECURITY_QOS_V2_A *)SecurityQos; + TRACE(", AdditionalSecurityInfoType=%ld", SecurityQos2->AdditionalSecurityInfoType); + if (SecurityQos2->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP) + TRACE(", { %p, 0x%lx, %ld, %ld, %p, %s }", + SecurityQos2->u.HttpCredentials->TransportCredentials, + SecurityQos2->u.HttpCredentials->Flags, + SecurityQos2->u.HttpCredentials->AuthenticationTarget, + SecurityQos2->u.HttpCredentials->NumberOfAuthnSchemes, + SecurityQos2->u.HttpCredentials->AuthnSchemes, + SecurityQos2->u.HttpCredentials->ServerCertificateSubject); + } + TRACE("}\n"); + status = RpcQualityOfService_Create(SecurityQos, FALSE, &bind->QOS); + if (status != RPC_S_OK) + return status; + } + else + { + if (bind->QOS) RpcQualityOfService_Release(bind->QOS); + bind->QOS = NULL; + } + + if (AuthnSvc == RPC_C_AUTHN_DEFAULT) + AuthnSvc = RPC_C_AUTHN_WINNT; + + /* FIXME: the mapping should probably be retrieved using SSPI somehow */ + if (AuthnLevel == RPC_C_AUTHN_LEVEL_DEFAULT) + AuthnLevel = RPC_C_AUTHN_LEVEL_NONE; + + if ((AuthnLevel == RPC_C_AUTHN_LEVEL_NONE) || (AuthnSvc == RPC_C_AUTHN_NONE)) + { + if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo); + bind->AuthInfo = NULL; + return RPC_S_OK; + } + + if (AuthnLevel > RPC_C_AUTHN_LEVEL_PKT_PRIVACY) + { + FIXME("unknown AuthnLevel %u\n", AuthnLevel); + return RPC_S_UNKNOWN_AUTHN_LEVEL; + } + + if (AuthzSvr) + { + FIXME("unsupported AuthzSvr %u\n", AuthzSvr); + return RPC_S_UNKNOWN_AUTHZ_SERVICE; + } + + r = EnumerateSecurityPackagesA(&package_count, &packages); + if (r != SEC_E_OK) + { + ERR("EnumerateSecurityPackagesA failed with error 0x%08x\n", r); + return RPC_S_SEC_PKG_ERROR; + } + + for (i = 0; i < package_count; i++) + if (packages[i].wRPCID == AuthnSvc) + break; + + if (i == package_count) + { + FIXME("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); + r = AcquireCredentialsHandleA((SEC_CHAR *)ServerPrincName, packages[i].Name, SECPKG_CRED_OUTBOUND, NULL, + AuthIdentity, NULL, NULL, &cred, &exp); + cbMaxToken = packages[i].cbMaxToken; + FreeContextBuffer(packages); + if (r == ERROR_SUCCESS) + { + if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo); + bind->AuthInfo = NULL; + r = RpcAuthInfo_Create(AuthnLevel, AuthnSvc, cred, exp, cbMaxToken, + AuthIdentity, &bind->AuthInfo); + if (r != RPC_S_OK) + FreeCredentialsHandle(&cred); + return RPC_S_OK; + } + else + { + ERR("AcquireCredentialsHandleA failed with error 0x%08x\n", r); + return RPC_S_SEC_PKG_ERROR; + } +} + +/*********************************************************************** + * RpcBindingSetAuthInfoExW (RPCRT4.@) + */ +RPCRTAPI RPC_STATUS RPC_ENTRY +RpcBindingSetAuthInfoExW( RPC_BINDING_HANDLE Binding, RPC_WSTR ServerPrincName, ULONG AuthnLevel, + ULONG AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr, + RPC_SECURITY_QOS *SecurityQos ) +{ + RpcBinding* bind = (RpcBinding*)Binding; + SECURITY_STATUS r; + CredHandle cred; + TimeStamp exp; + ULONG package_count; + ULONG i; + PSecPkgInfoW packages; + ULONG cbMaxToken; + + TRACE("%p %s %u %u %p %u %p\n", Binding, debugstr_w((const WCHAR*)ServerPrincName), + AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, SecurityQos); + + if (SecurityQos) + { + RPC_STATUS status; + + TRACE("SecurityQos { Version=%ld, Capabilties=0x%lx, IdentityTracking=%ld, ImpersonationLevel=%ld", + SecurityQos->Version, SecurityQos->Capabilities, SecurityQos->IdentityTracking, SecurityQos->ImpersonationType); + if (SecurityQos->Version >= 2) + { + const RPC_SECURITY_QOS_V2_W *SecurityQos2 = (const RPC_SECURITY_QOS_V2_W *)SecurityQos; + TRACE(", AdditionalSecurityInfoType=%ld", SecurityQos2->AdditionalSecurityInfoType); + if (SecurityQos2->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP) + TRACE(", { %p, 0x%lx, %ld, %ld, %p, %s }", + SecurityQos2->u.HttpCredentials->TransportCredentials, + SecurityQos2->u.HttpCredentials->Flags, + SecurityQos2->u.HttpCredentials->AuthenticationTarget, + SecurityQos2->u.HttpCredentials->NumberOfAuthnSchemes, + SecurityQos2->u.HttpCredentials->AuthnSchemes, + debugstr_w(SecurityQos2->u.HttpCredentials->ServerCertificateSubject)); + } + TRACE("}\n"); + status = RpcQualityOfService_Create(SecurityQos, TRUE, &bind->QOS); + if (status != RPC_S_OK) + return status; + } + else + { + if (bind->QOS) RpcQualityOfService_Release(bind->QOS); + bind->QOS = NULL; + } + + if (AuthnSvc == RPC_C_AUTHN_DEFAULT) + AuthnSvc = RPC_C_AUTHN_WINNT; + + /* FIXME: the mapping should probably be retrieved using SSPI somehow */ + if (AuthnLevel == RPC_C_AUTHN_LEVEL_DEFAULT) + AuthnLevel = RPC_C_AUTHN_LEVEL_NONE; + + if ((AuthnLevel == RPC_C_AUTHN_LEVEL_NONE) || (AuthnSvc == RPC_C_AUTHN_NONE)) + { + if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo); + bind->AuthInfo = NULL; + return RPC_S_OK; + } + + if (AuthnLevel > RPC_C_AUTHN_LEVEL_PKT_PRIVACY) + { + FIXME("unknown AuthnLevel %u\n", AuthnLevel); + return RPC_S_UNKNOWN_AUTHN_LEVEL; + } + + if (AuthzSvr) + { + FIXME("unsupported AuthzSvr %u\n", AuthzSvr); + return RPC_S_UNKNOWN_AUTHZ_SERVICE; + } + + r = EnumerateSecurityPackagesW(&package_count, &packages); + if (r != SEC_E_OK) + { + ERR("EnumerateSecurityPackagesA failed with error 0x%08x\n", r); + return RPC_S_SEC_PKG_ERROR; + } + + for (i = 0; i < package_count; i++) + if (packages[i].wRPCID == AuthnSvc) + break; + + if (i == package_count) + { + FIXME("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); + r = AcquireCredentialsHandleW((SEC_WCHAR *)ServerPrincName, packages[i].Name, SECPKG_CRED_OUTBOUND, NULL, + AuthIdentity, NULL, NULL, &cred, &exp); + cbMaxToken = packages[i].cbMaxToken; + FreeContextBuffer(packages); + if (r == ERROR_SUCCESS) + { + if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo); + bind->AuthInfo = NULL; + r = RpcAuthInfo_Create(AuthnLevel, AuthnSvc, cred, exp, cbMaxToken, + AuthIdentity, &bind->AuthInfo); + if (r != RPC_S_OK) + FreeCredentialsHandle(&cred); + return RPC_S_OK; + } + else + { + ERR("AcquireCredentialsHandleA failed with error 0x%08x\n", r); + return RPC_S_SEC_PKG_ERROR; + } +} + +/*********************************************************************** + * RpcBindingSetAuthInfoA (RPCRT4.@) + */ +RPCRTAPI RPC_STATUS RPC_ENTRY +RpcBindingSetAuthInfoA( RPC_BINDING_HANDLE Binding, RPC_CSTR ServerPrincName, ULONG AuthnLevel, + ULONG AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr ) +{ + TRACE("%p %s %u %u %p %u\n", Binding, debugstr_a((const char*)ServerPrincName), + AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr); + return RpcBindingSetAuthInfoExA(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, NULL); +} + +/*********************************************************************** + * RpcBindingSetAuthInfoW (RPCRT4.@) + */ +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), + AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr); + return RpcBindingSetAuthInfoExW(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, NULL); +} + +/*********************************************************************** + * RpcBindingSetOption (RPCRT4.@) + */ +RPC_STATUS WINAPI RpcBindingSetOption(RPC_BINDING_HANDLE BindingHandle, ULONG Option, ULONG OptionValue) +{ + FIXME("(%p, %d, %d): stub\n", BindingHandle, Option, OptionValue); + return RPC_S_OK; +} diff --git a/reactos/dll/win32/rpcrt4_new/rpc_binding.h b/reactos/dll/win32/rpcrt4_new/rpc_binding.h index 050c0e62925..ed8d4ea062d 100644 --- a/reactos/dll/win32/rpcrt4_new/rpc_binding.h +++ b/reactos/dll/win32/rpcrt4_new/rpc_binding.h @@ -1,197 +1,197 @@ -/* - * RPC binding API - * - * Copyright 2001 Ove Kåven, TransGaming Technologies - * - * 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 - */ - -#ifndef __WINE_RPC_BINDING_H -#define __WINE_RPC_BINDING_H - -#include "wine/rpcss_shared.h" -#include "rpcndr.h" -#include "security.h" -#include "wine/list.h" - - -typedef struct _RpcAuthInfo -{ - LONG refs; - - ULONG AuthnLevel; - ULONG AuthnSvc; - CredHandle cred; - TimeStamp exp; - ULONG cbMaxToken; - /* the auth identity pointer that the application passed us (freed by application) */ - RPC_AUTH_IDENTITY_HANDLE *identity; - /* our copy of NT auth identity structure, if the authentication service - * takes an NT auth identity */ - SEC_WINNT_AUTH_IDENTITY_W *nt_identity; -} RpcAuthInfo; - -typedef struct _RpcQualityOfService -{ - LONG refs; - - RPC_SECURITY_QOS_V2_W *qos; -} RpcQualityOfService; - -struct connection_ops; - -typedef struct _RpcConnection -{ - BOOL server; - LPSTR NetworkAddr; - LPSTR Endpoint; - LPWSTR NetworkOptions; - const struct connection_ops *ops; - USHORT MaxTransmissionSize; - - /* authentication */ - CtxtHandle ctx; - TimeStamp exp; - ULONG attr; - RpcAuthInfo *AuthInfo; - ULONG encryption_auth_len; - ULONG signature_auth_len; - RpcQualityOfService *QOS; - - /* client-only */ - struct list conn_pool_entry; - ULONG assoc_group_id; /* association group returned during binding */ - - /* server-only */ - /* The active interface bound to server. */ - RPC_SYNTAX_IDENTIFIER ActiveInterface; - USHORT NextCallId; - struct _RpcConnection* Next; - struct _RpcBinding *server_binding; -} RpcConnection; - -struct connection_ops { - const char *name; - unsigned char epm_protocols[2]; /* only floors 3 and 4. see http://www.opengroup.org/onlinepubs/9629399/apdxl.htm */ - RpcConnection *(*alloc)(void); - RPC_STATUS (*open_connection_client)(RpcConnection *conn); - RPC_STATUS (*handoff)(RpcConnection *old_conn, RpcConnection *new_conn); - int (*read)(RpcConnection *conn, void *buffer, unsigned int len); - int (*write)(RpcConnection *conn, const void *buffer, unsigned int len); - int (*close)(RpcConnection *conn); - void (*cancel_call)(RpcConnection *conn); - size_t (*get_top_of_tower)(unsigned char *tower_data, const char *networkaddr, const char *endpoint); - RPC_STATUS (*parse_top_of_tower)(const unsigned char *tower_data, size_t tower_size, char **networkaddr, char **endpoint); -}; - -/* don't know what MS's structure looks like */ -typedef struct _RpcBinding -{ - LONG refs; - struct _RpcBinding* Next; - BOOL server; - UUID ObjectUuid; - LPSTR Protseq; - LPSTR NetworkAddr; - LPSTR Endpoint; - LPWSTR NetworkOptions; - RPC_BLOCKING_FN BlockingFn; - ULONG ServerTid; - RpcConnection* FromConn; - struct _RpcAssoc *Assoc; - - /* authentication */ - RpcAuthInfo *AuthInfo; - 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); - -#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 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_SpawnConnection(RpcConnection** Connection, RpcConnection* OldConnection); - -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); -RPC_STATUS RPCRT4_ExportBinding(RpcBinding** Binding, RpcBinding* OldBinding); -RPC_STATUS RPCRT4_DestroyBinding(RpcBinding* Binding); -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); -BOOL RPCRT4_RPCSSOnDemandCall(PRPCSS_NP_MESSAGE msg, char *vardata_payload, PRPCSS_NP_REPLY reply); -HANDLE RPCRT4_GetMasterMutex(void); -HANDLE RPCRT4_RpcssNPConnect(void); - -static inline const char *rpcrt4_conn_get_name(const RpcConnection *Connection) -{ - return Connection->ops->name; -} - -static inline int rpcrt4_conn_read(RpcConnection *Connection, - void *buffer, unsigned int len) -{ - return Connection->ops->read(Connection, buffer, len); -} - -static inline int rpcrt4_conn_write(RpcConnection *Connection, - const void *buffer, unsigned int len) -{ - return Connection->ops->write(Connection, buffer, len); -} - -static inline int rpcrt4_conn_close(RpcConnection *Connection) -{ - return Connection->ops->close(Connection); -} - -static inline void rpcrt4_conn_cancel_call(RpcConnection *Connection) -{ - Connection->ops->cancel_call(Connection); -} - -static inline RPC_STATUS rpcrt4_conn_handoff(RpcConnection *old_conn, RpcConnection *new_conn) -{ - 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); - -void RPCRT4_SetThreadCurrentConnection(RpcConnection *Connection); -void RPCRT4_SetThreadCurrentCallHandle(RpcBinding *Binding); -RpcBinding *RPCRT4_GetThreadCurrentCallHandle(void); -void RPCRT4_PushThreadContextHandle(NDR_SCONTEXT SContext); -void RPCRT4_RemoveThreadContextHandle(NDR_SCONTEXT SContext); -NDR_SCONTEXT RPCRT4_PopThreadContextHandle(void); - -#endif +/* + * RPC binding API + * + * Copyright 2001 Ove Kåven, TransGaming Technologies + * + * 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 + */ + +#ifndef __WINE_RPC_BINDING_H +#define __WINE_RPC_BINDING_H + +#include "wine/rpcss_shared.h" +#include "rpcndr.h" +#include "security.h" +#include "wine/list.h" + + +typedef struct _RpcAuthInfo +{ + LONG refs; + + ULONG AuthnLevel; + ULONG AuthnSvc; + CredHandle cred; + TimeStamp exp; + ULONG cbMaxToken; + /* the auth identity pointer that the application passed us (freed by application) */ + RPC_AUTH_IDENTITY_HANDLE *identity; + /* our copy of NT auth identity structure, if the authentication service + * takes an NT auth identity */ + SEC_WINNT_AUTH_IDENTITY_W *nt_identity; +} RpcAuthInfo; + +typedef struct _RpcQualityOfService +{ + LONG refs; + + RPC_SECURITY_QOS_V2_W *qos; +} RpcQualityOfService; + +struct connection_ops; + +typedef struct _RpcConnection +{ + BOOL server; + LPSTR NetworkAddr; + LPSTR Endpoint; + LPWSTR NetworkOptions; + const struct connection_ops *ops; + USHORT MaxTransmissionSize; + + /* authentication */ + CtxtHandle ctx; + TimeStamp exp; + ULONG attr; + RpcAuthInfo *AuthInfo; + ULONG encryption_auth_len; + ULONG signature_auth_len; + RpcQualityOfService *QOS; + + /* client-only */ + struct list conn_pool_entry; + ULONG assoc_group_id; /* association group returned during binding */ + + /* server-only */ + /* The active interface bound to server. */ + RPC_SYNTAX_IDENTIFIER ActiveInterface; + USHORT NextCallId; + struct _RpcConnection* Next; + struct _RpcBinding *server_binding; +} RpcConnection; + +struct connection_ops { + const char *name; + unsigned char epm_protocols[2]; /* only floors 3 and 4. see http://www.opengroup.org/onlinepubs/9629399/apdxl.htm */ + RpcConnection *(*alloc)(void); + RPC_STATUS (*open_connection_client)(RpcConnection *conn); + RPC_STATUS (*handoff)(RpcConnection *old_conn, RpcConnection *new_conn); + int (*read)(RpcConnection *conn, void *buffer, unsigned int len); + int (*write)(RpcConnection *conn, const void *buffer, unsigned int len); + int (*close)(RpcConnection *conn); + void (*cancel_call)(RpcConnection *conn); + size_t (*get_top_of_tower)(unsigned char *tower_data, const char *networkaddr, const char *endpoint); + RPC_STATUS (*parse_top_of_tower)(const unsigned char *tower_data, size_t tower_size, char **networkaddr, char **endpoint); +}; + +/* don't know what MS's structure looks like */ +typedef struct _RpcBinding +{ + LONG refs; + struct _RpcBinding* Next; + BOOL server; + UUID ObjectUuid; + LPSTR Protseq; + LPSTR NetworkAddr; + LPSTR Endpoint; + LPWSTR NetworkOptions; + RPC_BLOCKING_FN BlockingFn; + ULONG ServerTid; + RpcConnection* FromConn; + struct _RpcAssoc *Assoc; + + /* authentication */ + RpcAuthInfo *AuthInfo; + 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); + +#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 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_SpawnConnection(RpcConnection** Connection, RpcConnection* OldConnection); + +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); +RPC_STATUS RPCRT4_ExportBinding(RpcBinding** Binding, RpcBinding* OldBinding); +RPC_STATUS RPCRT4_DestroyBinding(RpcBinding* Binding); +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); +BOOL RPCRT4_RPCSSOnDemandCall(PRPCSS_NP_MESSAGE msg, char *vardata_payload, PRPCSS_NP_REPLY reply); +HANDLE RPCRT4_GetMasterMutex(void); +HANDLE RPCRT4_RpcssNPConnect(void); + +static inline const char *rpcrt4_conn_get_name(const RpcConnection *Connection) +{ + return Connection->ops->name; +} + +static inline int rpcrt4_conn_read(RpcConnection *Connection, + void *buffer, unsigned int len) +{ + return Connection->ops->read(Connection, buffer, len); +} + +static inline int rpcrt4_conn_write(RpcConnection *Connection, + const void *buffer, unsigned int len) +{ + return Connection->ops->write(Connection, buffer, len); +} + +static inline int rpcrt4_conn_close(RpcConnection *Connection) +{ + return Connection->ops->close(Connection); +} + +static inline void rpcrt4_conn_cancel_call(RpcConnection *Connection) +{ + Connection->ops->cancel_call(Connection); +} + +static inline RPC_STATUS rpcrt4_conn_handoff(RpcConnection *old_conn, RpcConnection *new_conn) +{ + 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); + +void RPCRT4_SetThreadCurrentConnection(RpcConnection *Connection); +void RPCRT4_SetThreadCurrentCallHandle(RpcBinding *Binding); +RpcBinding *RPCRT4_GetThreadCurrentCallHandle(void); +void RPCRT4_PushThreadContextHandle(NDR_SCONTEXT SContext); +void RPCRT4_RemoveThreadContextHandle(NDR_SCONTEXT SContext); +NDR_SCONTEXT RPCRT4_PopThreadContextHandle(void); + +#endif diff --git a/reactos/dll/win32/rpcrt4_new/rpc_defs.h b/reactos/dll/win32/rpcrt4_new/rpc_defs.h index 12b63eeb1ad..c0c3609f1cc 100644 --- a/reactos/dll/win32/rpcrt4_new/rpc_defs.h +++ b/reactos/dll/win32/rpcrt4_new/rpc_defs.h @@ -1,212 +1,212 @@ -/* - * RPC definitions - * - * Copyright 2001-2002 Ove Kåven, TransGaming Technologies - * Copyright 2004 Filip Navara - * - * 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 - */ - -#ifndef __WINE_RPC_DEFS_H -#define __WINE_RPC_DEFS_H - -/* info from http://www.microsoft.com/msj/0398/dcomtextfigs.htm */ - -typedef struct -{ - unsigned char rpc_ver; /* RPC major version (5) */ - unsigned char rpc_ver_minor; /* RPC minor version (0) */ - unsigned char ptype; /* Packet type (PKT_*) */ - unsigned char flags; - 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. */ -} RpcPktCommonHdr; - -typedef struct -{ - RpcPktCommonHdr common; - unsigned long alloc_hint; /* Data size in bytes excluding header and tail. */ - unsigned short context_id; /* Presentation context identifier */ - unsigned short opnum; -} RpcPktRequestHdr; - -typedef struct -{ - RpcPktCommonHdr common; - unsigned long alloc_hint; /* Data size in bytes excluding header and tail. */ - unsigned short context_id; /* Presentation context identifier */ - unsigned char cancel_count; - unsigned char reserved; -} RpcPktResponseHdr; - -typedef struct -{ - RpcPktCommonHdr common; - unsigned long alloc_hint; /* Data size in bytes excluding header and tail. */ - unsigned short context_id; /* Presentation context identifier */ - unsigned char cancel_count; /* Received cancel count */ - unsigned char reserved; /* Force alignment! */ - unsigned long status; /* Runtime fault code (RPC_STATUS) */ - unsigned long reserved2; -} RpcPktFaultHdr; - -typedef struct -{ - RpcPktCommonHdr common; - unsigned short max_tsize; /* Maximum transmission fragment size */ - unsigned short max_rsize; /* Maximum receive fragment size */ - unsigned long assoc_gid; /* Associated group id */ - unsigned char num_elements; /* Number of elements */ - unsigned char padding[3]; /* Force alignment! */ - unsigned short context_id; /* Presentation context identifier */ - unsigned char num_syntaxes; /* Number of syntaxes */ - RPC_SYNTAX_IDENTIFIER abstract; - RPC_SYNTAX_IDENTIFIER transfer; -} 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 */ -} RpcAddressString; -#include "poppack.h" - -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; - -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 */ - /* - * 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; - */ -} RpcPktBindAckHdr; - -typedef struct -{ - RpcPktCommonHdr common; - unsigned short reject_reason; - unsigned char protocols_count; - struct { - unsigned char rpc_ver; - unsigned char rpc_ver_minor; - } protocols[1]; -} RpcPktBindNAckHdr; - -/* Union representing all possible packet headers */ -typedef union -{ - RpcPktCommonHdr common; - RpcPktRequestHdr request; - RpcPktResponseHdr response; - RpcPktFaultHdr fault; - RpcPktBindHdr bind; - RpcPktBindAckHdr bind_ack; - RpcPktBindNAckHdr bind_nack; -} RpcPktHdr; - -typedef struct -{ - unsigned char auth_type; /* authentication scheme in use */ - 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 */ -} RpcAuthVerifier; - -#define RPC_AUTH_VERIFIER_LEN(common_hdr) \ - ((common_hdr)->auth_len ? (common_hdr)->auth_len + sizeof(RpcAuthVerifier) : 0) - -#define RPC_VER_MAJOR 5 -#define RPC_VER_MINOR 0 - -#define RPC_FLG_FIRST 1 -#define RPC_FLG_LAST 2 -#define RPC_FLG_OBJECT_UUID 0x80 - -#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 - -#define RESULT_ACCEPT 0 -#define RESULT_USER_REJECTION 1 -#define RESULT_PROVIDER_REJECTION 2 - -#define REASON_NONE 0 -#define REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED 1 -#define REASON_TRANSFER_SYNTAXES_NOT_SUPPORTED 2 -#define REASON_LOCAL_LIMIT_EXCEEDED 3 - -#define REJECT_REASON_NOT_SPECIFIED 0 -#define REJECT_TEMPORARY_CONGESTION 1 -#define REJECT_LOCAL_LIMIT_EXCEEDED 2 -#define REJECT_CALLED_PADDR_UNKNOWN 3 /* not used */ -#define REJECT_PROTOCOL_VERSION_NOT_SUPPORTED 4 -#define REJECT_DEFAULT_CONTEXT_NOT_SUPPORTED 5 /* not used */ -#define REJECT_USER_DATA_NOT_READABLE 6 /* not used */ -#define REJECT_NO_PSAP_AVAILABLE 7 /* not used */ -#define REJECT_UNKNOWN_AUTHN_SERVICE 8 -#define REJECT_INVALID_CHECKSUM 9 - -#define NCADG_IP_UDP 0x08 -#define NCACN_IP_TCP 0x07 -#define NCADG_IPX 0x0E -#define NCACN_SPX 0x0C -#define NCACN_NB_NB 0x12 -#define NCACN_NB_IPX 0x0D -#define NCACN_DNET_NSP 0x04 -#define NCACN_HTTP 0x1F - -/* FreeDCE: TWR_C_FLR_PROT_ID_IP */ -#define TWR_IP 0x09 - -#endif /* __WINE_RPC_DEFS_H */ +/* + * RPC definitions + * + * Copyright 2001-2002 Ove Kåven, TransGaming Technologies + * Copyright 2004 Filip Navara + * + * 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 + */ + +#ifndef __WINE_RPC_DEFS_H +#define __WINE_RPC_DEFS_H + +/* info from http://www.microsoft.com/msj/0398/dcomtextfigs.htm */ + +typedef struct +{ + unsigned char rpc_ver; /* RPC major version (5) */ + unsigned char rpc_ver_minor; /* RPC minor version (0) */ + unsigned char ptype; /* Packet type (PKT_*) */ + unsigned char flags; + 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. */ +} RpcPktCommonHdr; + +typedef struct +{ + RpcPktCommonHdr common; + unsigned long alloc_hint; /* Data size in bytes excluding header and tail. */ + unsigned short context_id; /* Presentation context identifier */ + unsigned short opnum; +} RpcPktRequestHdr; + +typedef struct +{ + RpcPktCommonHdr common; + unsigned long alloc_hint; /* Data size in bytes excluding header and tail. */ + unsigned short context_id; /* Presentation context identifier */ + unsigned char cancel_count; + unsigned char reserved; +} RpcPktResponseHdr; + +typedef struct +{ + RpcPktCommonHdr common; + unsigned long alloc_hint; /* Data size in bytes excluding header and tail. */ + unsigned short context_id; /* Presentation context identifier */ + unsigned char cancel_count; /* Received cancel count */ + unsigned char reserved; /* Force alignment! */ + unsigned long status; /* Runtime fault code (RPC_STATUS) */ + unsigned long reserved2; +} RpcPktFaultHdr; + +typedef struct +{ + RpcPktCommonHdr common; + unsigned short max_tsize; /* Maximum transmission fragment size */ + unsigned short max_rsize; /* Maximum receive fragment size */ + unsigned long assoc_gid; /* Associated group id */ + unsigned char num_elements; /* Number of elements */ + unsigned char padding[3]; /* Force alignment! */ + unsigned short context_id; /* Presentation context identifier */ + unsigned char num_syntaxes; /* Number of syntaxes */ + RPC_SYNTAX_IDENTIFIER abstract; + RPC_SYNTAX_IDENTIFIER transfer; +} 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 */ +} RpcAddressString; +#include "poppack.h" + +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; + +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 */ + /* + * 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; + */ +} RpcPktBindAckHdr; + +typedef struct +{ + RpcPktCommonHdr common; + unsigned short reject_reason; + unsigned char protocols_count; + struct { + unsigned char rpc_ver; + unsigned char rpc_ver_minor; + } protocols[1]; +} RpcPktBindNAckHdr; + +/* Union representing all possible packet headers */ +typedef union +{ + RpcPktCommonHdr common; + RpcPktRequestHdr request; + RpcPktResponseHdr response; + RpcPktFaultHdr fault; + RpcPktBindHdr bind; + RpcPktBindAckHdr bind_ack; + RpcPktBindNAckHdr bind_nack; +} RpcPktHdr; + +typedef struct +{ + unsigned char auth_type; /* authentication scheme in use */ + 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 */ +} RpcAuthVerifier; + +#define RPC_AUTH_VERIFIER_LEN(common_hdr) \ + ((common_hdr)->auth_len ? (common_hdr)->auth_len + sizeof(RpcAuthVerifier) : 0) + +#define RPC_VER_MAJOR 5 +#define RPC_VER_MINOR 0 + +#define RPC_FLG_FIRST 1 +#define RPC_FLG_LAST 2 +#define RPC_FLG_OBJECT_UUID 0x80 + +#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 + +#define RESULT_ACCEPT 0 +#define RESULT_USER_REJECTION 1 +#define RESULT_PROVIDER_REJECTION 2 + +#define REASON_NONE 0 +#define REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED 1 +#define REASON_TRANSFER_SYNTAXES_NOT_SUPPORTED 2 +#define REASON_LOCAL_LIMIT_EXCEEDED 3 + +#define REJECT_REASON_NOT_SPECIFIED 0 +#define REJECT_TEMPORARY_CONGESTION 1 +#define REJECT_LOCAL_LIMIT_EXCEEDED 2 +#define REJECT_CALLED_PADDR_UNKNOWN 3 /* not used */ +#define REJECT_PROTOCOL_VERSION_NOT_SUPPORTED 4 +#define REJECT_DEFAULT_CONTEXT_NOT_SUPPORTED 5 /* not used */ +#define REJECT_USER_DATA_NOT_READABLE 6 /* not used */ +#define REJECT_NO_PSAP_AVAILABLE 7 /* not used */ +#define REJECT_UNKNOWN_AUTHN_SERVICE 8 +#define REJECT_INVALID_CHECKSUM 9 + +#define NCADG_IP_UDP 0x08 +#define NCACN_IP_TCP 0x07 +#define NCADG_IPX 0x0E +#define NCACN_SPX 0x0C +#define NCACN_NB_NB 0x12 +#define NCACN_NB_IPX 0x0D +#define NCACN_DNET_NSP 0x04 +#define NCACN_HTTP 0x1F + +/* FreeDCE: TWR_C_FLR_PROT_ID_IP */ +#define TWR_IP 0x09 + +#endif /* __WINE_RPC_DEFS_H */ diff --git a/reactos/dll/win32/rpcrt4_new/rpc_epmap.c b/reactos/dll/win32/rpcrt4_new/rpc_epmap.c index 19dda66c18c..cac3f626c1a 100644 --- a/reactos/dll/win32/rpcrt4_new/rpc_epmap.c +++ b/reactos/dll/win32/rpcrt4_new/rpc_epmap.c @@ -1,384 +1,384 @@ -/* - * RPC endpoint mapper - * - * Copyright 2002 Greg Turner - * Copyright 2001 Ove Kåven, TransGaming Technologies - * - * 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 - * - * TODO: - * - actually do things right - */ - -#include -#include -#include - -#include "windef.h" -#include "winbase.h" -#include "winerror.h" - -#include "rpc.h" - -#include "wine/debug.h" - -#include "rpc_binding.h" -#include "epm_towers.h" - -WINE_DEFAULT_DEBUG_CHANNEL(ole); - -/* The "real" RPC portmapper endpoints that I know of are: - * - * ncadg_ip_udp: 135 - * ncacn_ip_tcp: 135 - * ncacn_np: \\pipe\epmapper (?) - * ncalrpc: epmapper - * - * If the user's machine ran a DCE RPC daemon, it would - * probably be possible to connect to it, but there are many - * reasons not to, like: - * - the user probably does *not* run one, and probably - * shouldn't be forced to run one just for local COM - * - very few Unix systems use DCE RPC... if they run a RPC - * daemon at all, it's usually Sun RPC - * - DCE RPC registrations are persistent and saved on disk, - * while MS-RPC registrations are documented as non-persistent - * and stored only in RAM, and auto-destroyed when the process - * dies (something DCE RPC can't do) - * - * Of course, if the user *did* want to run a DCE RPC daemon anyway, - * there would be interoperability advantages, like the possibility - * of running a fully functional DCOM server using Wine... - */ - -/*********************************************************************** - * RpcEpRegisterA (RPCRT4.@) - */ -RPC_STATUS WINAPI RpcEpRegisterA( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *BindingVector, - UUID_VECTOR *UuidVector, RPC_CSTR Annotation ) -{ - RPCSS_NP_MESSAGE msg; - RPCSS_NP_REPLY reply; - char *vardata_payload, *vp; - PRPC_SERVER_INTERFACE If = (PRPC_SERVER_INTERFACE)IfSpec; - unsigned long c; - RPC_STATUS rslt = RPC_S_OK; - - TRACE("(%p,%p,%p,%s)\n", IfSpec, BindingVector, UuidVector, debugstr_a((char*)Annotation)); - TRACE(" ifid=%s\n", debugstr_guid(&If->InterfaceId.SyntaxGUID)); - for (c=0; cCount; c++) { - RpcBinding* bind = (RpcBinding*)(BindingVector->BindingH[c]); - TRACE(" protseq[%ld]=%s\n", c, debugstr_a(bind->Protseq)); - TRACE(" endpoint[%ld]=%s\n", c, debugstr_a(bind->Endpoint)); - } - if (UuidVector) { - for (c=0; cCount; c++) - TRACE(" obj[%ld]=%s\n", c, debugstr_guid(UuidVector->Uuid[c])); - } - - /* FIXME: Do something with annotation. */ - - /* construct the message to rpcss */ - msg.message_type = RPCSS_NP_MESSAGE_TYPEID_REGISTEREPMSG; - msg.message.registerepmsg.iface = If->InterfaceId; - msg.message.registerepmsg.no_replace = 0; - - msg.message.registerepmsg.object_count = (UuidVector) ? UuidVector->Count : 0; - msg.message.registerepmsg.binding_count = BindingVector->Count; - - /* calculate vardata payload size */ - msg.vardata_payload_size = msg.message.registerepmsg.object_count * sizeof(UUID); - for (c=0; c < msg.message.registerepmsg.binding_count; c++) { - RpcBinding *bind = (RpcBinding *)(BindingVector->BindingH[c]); - msg.vardata_payload_size += strlen(bind->Protseq) + 1; - msg.vardata_payload_size += strlen(bind->Endpoint) + 1; - } - - /* allocate the payload buffer */ - vp = vardata_payload = LocalAlloc(LPTR, msg.vardata_payload_size); - if (!vardata_payload) - return RPC_S_OUT_OF_MEMORY; - - /* populate the payload data */ - for (c=0; c < msg.message.registerepmsg.object_count; c++) { - CopyMemory(vp, UuidVector->Uuid[c], sizeof(UUID)); - vp += sizeof(UUID); - } - - for (c=0; c < msg.message.registerepmsg.binding_count; c++) { - RpcBinding *bind = (RpcBinding*)(BindingVector->BindingH[c]); - unsigned long pslen = strlen(bind->Protseq) + 1, eplen = strlen(bind->Endpoint) + 1; - CopyMemory(vp, bind->Protseq, pslen); - vp += pslen; - CopyMemory(vp, bind->Endpoint, eplen); - vp += eplen; - } - - /* send our request */ - if (!RPCRT4_RPCSSOnDemandCall(&msg, vardata_payload, &reply)) - rslt = RPC_S_OUT_OF_MEMORY; - - /* free the payload buffer */ - LocalFree(vardata_payload); - - return rslt; -} - -/*********************************************************************** - * RpcEpUnregister (RPCRT4.@) - */ -RPC_STATUS WINAPI RpcEpUnregister( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *BindingVector, - UUID_VECTOR *UuidVector ) -{ - RPCSS_NP_MESSAGE msg; - RPCSS_NP_REPLY reply; - char *vardata_payload, *vp; - PRPC_SERVER_INTERFACE If = (PRPC_SERVER_INTERFACE)IfSpec; - unsigned long c; - RPC_STATUS rslt = RPC_S_OK; - - TRACE("(%p,%p,%p)\n", IfSpec, BindingVector, UuidVector); - TRACE(" ifid=%s\n", debugstr_guid(&If->InterfaceId.SyntaxGUID)); - for (c=0; cCount; c++) { - RpcBinding* bind = (RpcBinding*)(BindingVector->BindingH[c]); - TRACE(" protseq[%ld]=%s\n", c, debugstr_a(bind->Protseq)); - TRACE(" endpoint[%ld]=%s\n", c, debugstr_a(bind->Endpoint)); - } - if (UuidVector) { - for (c=0; cCount; c++) - TRACE(" obj[%ld]=%s\n", c, debugstr_guid(UuidVector->Uuid[c])); - } - - /* construct the message to rpcss */ - msg.message_type = RPCSS_NP_MESSAGE_TYPEID_UNREGISTEREPMSG; - msg.message.unregisterepmsg.iface = If->InterfaceId; - - msg.message.unregisterepmsg.object_count = (UuidVector) ? UuidVector->Count : 0; - msg.message.unregisterepmsg.binding_count = BindingVector->Count; - - /* calculate vardata payload size */ - msg.vardata_payload_size = msg.message.unregisterepmsg.object_count * sizeof(UUID); - for (c=0; c < msg.message.unregisterepmsg.binding_count; c++) { - RpcBinding *bind = (RpcBinding *)(BindingVector->BindingH[c]); - msg.vardata_payload_size += strlen(bind->Protseq) + 1; - msg.vardata_payload_size += strlen(bind->Endpoint) + 1; - } - - /* allocate the payload buffer */ - vp = vardata_payload = LocalAlloc(LPTR, msg.vardata_payload_size); - if (!vardata_payload) - return RPC_S_OUT_OF_MEMORY; - - /* populate the payload data */ - for (c=0; c < msg.message.unregisterepmsg.object_count; c++) { - CopyMemory(vp, UuidVector->Uuid[c], sizeof(UUID)); - vp += sizeof(UUID); - } - - for (c=0; c < msg.message.unregisterepmsg.binding_count; c++) { - RpcBinding *bind = (RpcBinding*)(BindingVector->BindingH[c]); - unsigned long pslen = strlen(bind->Protseq) + 1, eplen = strlen(bind->Endpoint) + 1; - CopyMemory(vp, bind->Protseq, pslen); - vp += pslen; - CopyMemory(vp, bind->Endpoint, eplen); - vp += eplen; - } - - /* send our request */ - if (!RPCRT4_RPCSSOnDemandCall(&msg, vardata_payload, &reply)) - rslt = RPC_S_OUT_OF_MEMORY; - - /* free the payload buffer */ - LocalFree(vardata_payload); - - return rslt; -} - -/*********************************************************************** - * RpcEpResolveBinding (RPCRT4.@) - */ -RPC_STATUS WINAPI RpcEpResolveBinding( RPC_BINDING_HANDLE Binding, RPC_IF_HANDLE IfSpec ) -{ - RPCSS_NP_MESSAGE msg; - RPCSS_NP_REPLY reply; - PRPC_CLIENT_INTERFACE If = (PRPC_CLIENT_INTERFACE)IfSpec; - RpcBinding* bind = (RpcBinding*)Binding; - - TRACE("(%p,%p)\n", Binding, IfSpec); - TRACE(" protseq=%s\n", debugstr_a(bind->Protseq)); - TRACE(" obj=%s\n", debugstr_guid(&bind->ObjectUuid)); - TRACE(" ifid=%s\n", debugstr_guid(&If->InterfaceId.SyntaxGUID)); - - /* FIXME: totally untested */ - - /* just return for fully bound handles */ - if (bind->Endpoint && (bind->Endpoint[0] != '\0')) - return RPC_S_OK; - - /* construct the message to rpcss */ - msg.message_type = RPCSS_NP_MESSAGE_TYPEID_RESOLVEEPMSG; - msg.message.resolveepmsg.iface = If->InterfaceId; - msg.message.resolveepmsg.object = bind->ObjectUuid; - - msg.vardata_payload_size = strlen(bind->Protseq) + 1; - - /* send the message */ - if (!RPCRT4_RPCSSOnDemandCall(&msg, bind->Protseq, &reply)) - return RPC_S_OUT_OF_MEMORY; - - /* empty-string result means not registered */ - if (reply.as_string[0] == '\0') - return EPT_S_NOT_REGISTERED; - - /* otherwise we fully bind the handle & return RPC_S_OK */ - return RPCRT4_ResolveBinding(Binding, reply.as_string); -} - -typedef unsigned int unsigned32; -typedef struct twr_t - { - unsigned32 tower_length; - /* [size_is] */ BYTE tower_octet_string[ 1 ]; - } twr_t; - -/*********************************************************************** - * TowerExplode (RPCRT4.@) - */ -RPC_STATUS WINAPI TowerExplode( - const twr_t *tower, PRPC_SYNTAX_IDENTIFIER object, PRPC_SYNTAX_IDENTIFIER syntax, - char **protseq, char **endpoint, char **address) -{ - size_t tower_size; - RPC_STATUS status; - const unsigned char *p; - u_int16 floor_count; - const twr_uuid_floor_t *object_floor; - const twr_uuid_floor_t *syntax_floor; - - if (protseq) - *protseq = NULL; - if (endpoint) - *endpoint = NULL; - if (address) - *address = NULL; - - tower_size = tower->tower_length; - - if (tower_size < sizeof(u_int16)) - return EPT_S_NOT_REGISTERED; - - p = &tower->tower_octet_string[0]; - - floor_count = *(const u_int16 *)p; - p += sizeof(u_int16); - tower_size -= sizeof(u_int16); - TRACE("floor_count: %d\n", floor_count); - /* FIXME: should we do something with the floor count? at the moment we don't */ - - if (tower_size < sizeof(*object_floor) + sizeof(*syntax_floor)) - return EPT_S_NOT_REGISTERED; - - object_floor = (const twr_uuid_floor_t *)p; - p += sizeof(*object_floor); - tower_size -= sizeof(*object_floor); - syntax_floor = (const twr_uuid_floor_t *)p; - p += sizeof(*syntax_floor); - tower_size -= sizeof(*syntax_floor); - - if ((object_floor->count_lhs != sizeof(object_floor->protid) + - sizeof(object_floor->uuid) + sizeof(object_floor->major_version)) || - (object_floor->protid != EPM_PROTOCOL_UUID) || - (object_floor->count_rhs != sizeof(object_floor->minor_version))) - return EPT_S_NOT_REGISTERED; - - if ((syntax_floor->count_lhs != sizeof(syntax_floor->protid) + - sizeof(syntax_floor->uuid) + sizeof(syntax_floor->major_version)) || - (syntax_floor->protid != EPM_PROTOCOL_UUID) || - (syntax_floor->count_rhs != sizeof(syntax_floor->minor_version))) - return EPT_S_NOT_REGISTERED; - - status = RpcTransport_ParseTopOfTower(p, tower_size, protseq, address, endpoint); - if ((status == RPC_S_OK) && syntax && object) - { - syntax->SyntaxGUID = syntax_floor->uuid; - syntax->SyntaxVersion.MajorVersion = syntax_floor->major_version; - syntax->SyntaxVersion.MinorVersion = syntax_floor->minor_version; - object->SyntaxGUID = object_floor->uuid; - object->SyntaxVersion.MajorVersion = object_floor->major_version; - object->SyntaxVersion.MinorVersion = object_floor->minor_version; - } - return status; -} - -/*********************************************************************** - * TowerConstruct (RPCRT4.@) - */ -RPC_STATUS WINAPI TowerConstruct( - const RPC_SYNTAX_IDENTIFIER *object, const RPC_SYNTAX_IDENTIFIER *syntax, - const char *protseq, const char *endpoint, const char *address, - twr_t **tower) -{ - size_t tower_size; - RPC_STATUS status; - unsigned char *p; - twr_uuid_floor_t *object_floor; - twr_uuid_floor_t *syntax_floor; - - *tower = NULL; - - status = RpcTransport_GetTopOfTower(NULL, &tower_size, protseq, address, endpoint); - - if (status != RPC_S_OK) - return status; - - tower_size += sizeof(u_int16) + sizeof(*object_floor) + sizeof(*syntax_floor); - *tower = I_RpcAllocate(FIELD_OFFSET(twr_t, tower_octet_string[tower_size])); - if (!*tower) - return RPC_S_OUT_OF_RESOURCES; - - (*tower)->tower_length = tower_size; - p = &(*tower)->tower_octet_string[0]; - *(u_int16 *)p = 5; /* number of floors */ - p += sizeof(u_int16); - object_floor = (twr_uuid_floor_t *)p; - p += sizeof(*object_floor); - syntax_floor = (twr_uuid_floor_t *)p; - p += sizeof(*syntax_floor); - - object_floor->count_lhs = sizeof(object_floor->protid) + sizeof(object_floor->uuid) + - sizeof(object_floor->major_version); - object_floor->protid = EPM_PROTOCOL_UUID; - object_floor->count_rhs = sizeof(object_floor->minor_version); - object_floor->uuid = object->SyntaxGUID; - object_floor->major_version = object->SyntaxVersion.MajorVersion; - object_floor->minor_version = object->SyntaxVersion.MinorVersion; - - syntax_floor->count_lhs = sizeof(syntax_floor->protid) + sizeof(syntax_floor->uuid) + - sizeof(syntax_floor->major_version); - syntax_floor->protid = EPM_PROTOCOL_UUID; - syntax_floor->count_rhs = sizeof(syntax_floor->minor_version); - syntax_floor->uuid = syntax->SyntaxGUID; - syntax_floor->major_version = syntax->SyntaxVersion.MajorVersion; - syntax_floor->minor_version = syntax->SyntaxVersion.MinorVersion; - - status = RpcTransport_GetTopOfTower(p, &tower_size, protseq, address, endpoint); - if (status != RPC_S_OK) - { - I_RpcFree(*tower); - *tower = NULL; - return status; - } - return RPC_S_OK; -} +/* + * RPC endpoint mapper + * + * Copyright 2002 Greg Turner + * Copyright 2001 Ove Kåven, TransGaming Technologies + * + * 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 + * + * TODO: + * - actually do things right + */ + +#include +#include +#include + +#include "windef.h" +#include "winbase.h" +#include "winerror.h" + +#include "rpc.h" + +#include "wine/debug.h" + +#include "rpc_binding.h" +#include "epm_towers.h" + +WINE_DEFAULT_DEBUG_CHANNEL(ole); + +/* The "real" RPC portmapper endpoints that I know of are: + * + * ncadg_ip_udp: 135 + * ncacn_ip_tcp: 135 + * ncacn_np: \\pipe\epmapper (?) + * ncalrpc: epmapper + * + * If the user's machine ran a DCE RPC daemon, it would + * probably be possible to connect to it, but there are many + * reasons not to, like: + * - the user probably does *not* run one, and probably + * shouldn't be forced to run one just for local COM + * - very few Unix systems use DCE RPC... if they run a RPC + * daemon at all, it's usually Sun RPC + * - DCE RPC registrations are persistent and saved on disk, + * while MS-RPC registrations are documented as non-persistent + * and stored only in RAM, and auto-destroyed when the process + * dies (something DCE RPC can't do) + * + * Of course, if the user *did* want to run a DCE RPC daemon anyway, + * there would be interoperability advantages, like the possibility + * of running a fully functional DCOM server using Wine... + */ + +/*********************************************************************** + * RpcEpRegisterA (RPCRT4.@) + */ +RPC_STATUS WINAPI RpcEpRegisterA( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *BindingVector, + UUID_VECTOR *UuidVector, RPC_CSTR Annotation ) +{ + RPCSS_NP_MESSAGE msg; + RPCSS_NP_REPLY reply; + char *vardata_payload, *vp; + PRPC_SERVER_INTERFACE If = (PRPC_SERVER_INTERFACE)IfSpec; + unsigned long c; + RPC_STATUS rslt = RPC_S_OK; + + TRACE("(%p,%p,%p,%s)\n", IfSpec, BindingVector, UuidVector, debugstr_a((char*)Annotation)); + TRACE(" ifid=%s\n", debugstr_guid(&If->InterfaceId.SyntaxGUID)); + for (c=0; cCount; c++) { + RpcBinding* bind = (RpcBinding*)(BindingVector->BindingH[c]); + TRACE(" protseq[%ld]=%s\n", c, debugstr_a(bind->Protseq)); + TRACE(" endpoint[%ld]=%s\n", c, debugstr_a(bind->Endpoint)); + } + if (UuidVector) { + for (c=0; cCount; c++) + TRACE(" obj[%ld]=%s\n", c, debugstr_guid(UuidVector->Uuid[c])); + } + + /* FIXME: Do something with annotation. */ + + /* construct the message to rpcss */ + msg.message_type = RPCSS_NP_MESSAGE_TYPEID_REGISTEREPMSG; + msg.message.registerepmsg.iface = If->InterfaceId; + msg.message.registerepmsg.no_replace = 0; + + msg.message.registerepmsg.object_count = (UuidVector) ? UuidVector->Count : 0; + msg.message.registerepmsg.binding_count = BindingVector->Count; + + /* calculate vardata payload size */ + msg.vardata_payload_size = msg.message.registerepmsg.object_count * sizeof(UUID); + for (c=0; c < msg.message.registerepmsg.binding_count; c++) { + RpcBinding *bind = (RpcBinding *)(BindingVector->BindingH[c]); + msg.vardata_payload_size += strlen(bind->Protseq) + 1; + msg.vardata_payload_size += strlen(bind->Endpoint) + 1; + } + + /* allocate the payload buffer */ + vp = vardata_payload = LocalAlloc(LPTR, msg.vardata_payload_size); + if (!vardata_payload) + return RPC_S_OUT_OF_MEMORY; + + /* populate the payload data */ + for (c=0; c < msg.message.registerepmsg.object_count; c++) { + CopyMemory(vp, UuidVector->Uuid[c], sizeof(UUID)); + vp += sizeof(UUID); + } + + for (c=0; c < msg.message.registerepmsg.binding_count; c++) { + RpcBinding *bind = (RpcBinding*)(BindingVector->BindingH[c]); + unsigned long pslen = strlen(bind->Protseq) + 1, eplen = strlen(bind->Endpoint) + 1; + CopyMemory(vp, bind->Protseq, pslen); + vp += pslen; + CopyMemory(vp, bind->Endpoint, eplen); + vp += eplen; + } + + /* send our request */ + if (!RPCRT4_RPCSSOnDemandCall(&msg, vardata_payload, &reply)) + rslt = RPC_S_OUT_OF_MEMORY; + + /* free the payload buffer */ + LocalFree(vardata_payload); + + return rslt; +} + +/*********************************************************************** + * RpcEpUnregister (RPCRT4.@) + */ +RPC_STATUS WINAPI RpcEpUnregister( RPC_IF_HANDLE IfSpec, RPC_BINDING_VECTOR *BindingVector, + UUID_VECTOR *UuidVector ) +{ + RPCSS_NP_MESSAGE msg; + RPCSS_NP_REPLY reply; + char *vardata_payload, *vp; + PRPC_SERVER_INTERFACE If = (PRPC_SERVER_INTERFACE)IfSpec; + unsigned long c; + RPC_STATUS rslt = RPC_S_OK; + + TRACE("(%p,%p,%p)\n", IfSpec, BindingVector, UuidVector); + TRACE(" ifid=%s\n", debugstr_guid(&If->InterfaceId.SyntaxGUID)); + for (c=0; cCount; c++) { + RpcBinding* bind = (RpcBinding*)(BindingVector->BindingH[c]); + TRACE(" protseq[%ld]=%s\n", c, debugstr_a(bind->Protseq)); + TRACE(" endpoint[%ld]=%s\n", c, debugstr_a(bind->Endpoint)); + } + if (UuidVector) { + for (c=0; cCount; c++) + TRACE(" obj[%ld]=%s\n", c, debugstr_guid(UuidVector->Uuid[c])); + } + + /* construct the message to rpcss */ + msg.message_type = RPCSS_NP_MESSAGE_TYPEID_UNREGISTEREPMSG; + msg.message.unregisterepmsg.iface = If->InterfaceId; + + msg.message.unregisterepmsg.object_count = (UuidVector) ? UuidVector->Count : 0; + msg.message.unregisterepmsg.binding_count = BindingVector->Count; + + /* calculate vardata payload size */ + msg.vardata_payload_size = msg.message.unregisterepmsg.object_count * sizeof(UUID); + for (c=0; c < msg.message.unregisterepmsg.binding_count; c++) { + RpcBinding *bind = (RpcBinding *)(BindingVector->BindingH[c]); + msg.vardata_payload_size += strlen(bind->Protseq) + 1; + msg.vardata_payload_size += strlen(bind->Endpoint) + 1; + } + + /* allocate the payload buffer */ + vp = vardata_payload = LocalAlloc(LPTR, msg.vardata_payload_size); + if (!vardata_payload) + return RPC_S_OUT_OF_MEMORY; + + /* populate the payload data */ + for (c=0; c < msg.message.unregisterepmsg.object_count; c++) { + CopyMemory(vp, UuidVector->Uuid[c], sizeof(UUID)); + vp += sizeof(UUID); + } + + for (c=0; c < msg.message.unregisterepmsg.binding_count; c++) { + RpcBinding *bind = (RpcBinding*)(BindingVector->BindingH[c]); + unsigned long pslen = strlen(bind->Protseq) + 1, eplen = strlen(bind->Endpoint) + 1; + CopyMemory(vp, bind->Protseq, pslen); + vp += pslen; + CopyMemory(vp, bind->Endpoint, eplen); + vp += eplen; + } + + /* send our request */ + if (!RPCRT4_RPCSSOnDemandCall(&msg, vardata_payload, &reply)) + rslt = RPC_S_OUT_OF_MEMORY; + + /* free the payload buffer */ + LocalFree(vardata_payload); + + return rslt; +} + +/*********************************************************************** + * RpcEpResolveBinding (RPCRT4.@) + */ +RPC_STATUS WINAPI RpcEpResolveBinding( RPC_BINDING_HANDLE Binding, RPC_IF_HANDLE IfSpec ) +{ + RPCSS_NP_MESSAGE msg; + RPCSS_NP_REPLY reply; + PRPC_CLIENT_INTERFACE If = (PRPC_CLIENT_INTERFACE)IfSpec; + RpcBinding* bind = (RpcBinding*)Binding; + + TRACE("(%p,%p)\n", Binding, IfSpec); + TRACE(" protseq=%s\n", debugstr_a(bind->Protseq)); + TRACE(" obj=%s\n", debugstr_guid(&bind->ObjectUuid)); + TRACE(" ifid=%s\n", debugstr_guid(&If->InterfaceId.SyntaxGUID)); + + /* FIXME: totally untested */ + + /* just return for fully bound handles */ + if (bind->Endpoint && (bind->Endpoint[0] != '\0')) + return RPC_S_OK; + + /* construct the message to rpcss */ + msg.message_type = RPCSS_NP_MESSAGE_TYPEID_RESOLVEEPMSG; + msg.message.resolveepmsg.iface = If->InterfaceId; + msg.message.resolveepmsg.object = bind->ObjectUuid; + + msg.vardata_payload_size = strlen(bind->Protseq) + 1; + + /* send the message */ + if (!RPCRT4_RPCSSOnDemandCall(&msg, bind->Protseq, &reply)) + return RPC_S_OUT_OF_MEMORY; + + /* empty-string result means not registered */ + if (reply.as_string[0] == '\0') + return EPT_S_NOT_REGISTERED; + + /* otherwise we fully bind the handle & return RPC_S_OK */ + return RPCRT4_ResolveBinding(Binding, reply.as_string); +} + +typedef unsigned int unsigned32; +typedef struct twr_t + { + unsigned32 tower_length; + /* [size_is] */ BYTE tower_octet_string[ 1 ]; + } twr_t; + +/*********************************************************************** + * TowerExplode (RPCRT4.@) + */ +RPC_STATUS WINAPI TowerExplode( + const twr_t *tower, PRPC_SYNTAX_IDENTIFIER object, PRPC_SYNTAX_IDENTIFIER syntax, + char **protseq, char **endpoint, char **address) +{ + size_t tower_size; + RPC_STATUS status; + const unsigned char *p; + u_int16 floor_count; + const twr_uuid_floor_t *object_floor; + const twr_uuid_floor_t *syntax_floor; + + if (protseq) + *protseq = NULL; + if (endpoint) + *endpoint = NULL; + if (address) + *address = NULL; + + tower_size = tower->tower_length; + + if (tower_size < sizeof(u_int16)) + return EPT_S_NOT_REGISTERED; + + p = &tower->tower_octet_string[0]; + + floor_count = *(const u_int16 *)p; + p += sizeof(u_int16); + tower_size -= sizeof(u_int16); + TRACE("floor_count: %d\n", floor_count); + /* FIXME: should we do something with the floor count? at the moment we don't */ + + if (tower_size < sizeof(*object_floor) + sizeof(*syntax_floor)) + return EPT_S_NOT_REGISTERED; + + object_floor = (const twr_uuid_floor_t *)p; + p += sizeof(*object_floor); + tower_size -= sizeof(*object_floor); + syntax_floor = (const twr_uuid_floor_t *)p; + p += sizeof(*syntax_floor); + tower_size -= sizeof(*syntax_floor); + + if ((object_floor->count_lhs != sizeof(object_floor->protid) + + sizeof(object_floor->uuid) + sizeof(object_floor->major_version)) || + (object_floor->protid != EPM_PROTOCOL_UUID) || + (object_floor->count_rhs != sizeof(object_floor->minor_version))) + return EPT_S_NOT_REGISTERED; + + if ((syntax_floor->count_lhs != sizeof(syntax_floor->protid) + + sizeof(syntax_floor->uuid) + sizeof(syntax_floor->major_version)) || + (syntax_floor->protid != EPM_PROTOCOL_UUID) || + (syntax_floor->count_rhs != sizeof(syntax_floor->minor_version))) + return EPT_S_NOT_REGISTERED; + + status = RpcTransport_ParseTopOfTower(p, tower_size, protseq, address, endpoint); + if ((status == RPC_S_OK) && syntax && object) + { + syntax->SyntaxGUID = syntax_floor->uuid; + syntax->SyntaxVersion.MajorVersion = syntax_floor->major_version; + syntax->SyntaxVersion.MinorVersion = syntax_floor->minor_version; + object->SyntaxGUID = object_floor->uuid; + object->SyntaxVersion.MajorVersion = object_floor->major_version; + object->SyntaxVersion.MinorVersion = object_floor->minor_version; + } + return status; +} + +/*********************************************************************** + * TowerConstruct (RPCRT4.@) + */ +RPC_STATUS WINAPI TowerConstruct( + const RPC_SYNTAX_IDENTIFIER *object, const RPC_SYNTAX_IDENTIFIER *syntax, + const char *protseq, const char *endpoint, const char *address, + twr_t **tower) +{ + size_t tower_size; + RPC_STATUS status; + unsigned char *p; + twr_uuid_floor_t *object_floor; + twr_uuid_floor_t *syntax_floor; + + *tower = NULL; + + status = RpcTransport_GetTopOfTower(NULL, &tower_size, protseq, address, endpoint); + + if (status != RPC_S_OK) + return status; + + tower_size += sizeof(u_int16) + sizeof(*object_floor) + sizeof(*syntax_floor); + *tower = I_RpcAllocate(FIELD_OFFSET(twr_t, tower_octet_string[tower_size])); + if (!*tower) + return RPC_S_OUT_OF_RESOURCES; + + (*tower)->tower_length = tower_size; + p = &(*tower)->tower_octet_string[0]; + *(u_int16 *)p = 5; /* number of floors */ + p += sizeof(u_int16); + object_floor = (twr_uuid_floor_t *)p; + p += sizeof(*object_floor); + syntax_floor = (twr_uuid_floor_t *)p; + p += sizeof(*syntax_floor); + + object_floor->count_lhs = sizeof(object_floor->protid) + sizeof(object_floor->uuid) + + sizeof(object_floor->major_version); + object_floor->protid = EPM_PROTOCOL_UUID; + object_floor->count_rhs = sizeof(object_floor->minor_version); + object_floor->uuid = object->SyntaxGUID; + object_floor->major_version = object->SyntaxVersion.MajorVersion; + object_floor->minor_version = object->SyntaxVersion.MinorVersion; + + syntax_floor->count_lhs = sizeof(syntax_floor->protid) + sizeof(syntax_floor->uuid) + + sizeof(syntax_floor->major_version); + syntax_floor->protid = EPM_PROTOCOL_UUID; + syntax_floor->count_rhs = sizeof(syntax_floor->minor_version); + syntax_floor->uuid = syntax->SyntaxGUID; + syntax_floor->major_version = syntax->SyntaxVersion.MajorVersion; + syntax_floor->minor_version = syntax->SyntaxVersion.MinorVersion; + + status = RpcTransport_GetTopOfTower(p, &tower_size, protseq, address, endpoint); + if (status != RPC_S_OK) + { + I_RpcFree(*tower); + *tower = NULL; + return status; + } + return RPC_S_OK; +} diff --git a/reactos/dll/win32/rpcrt4_new/rpc_message.c b/reactos/dll/win32/rpcrt4_new/rpc_message.c index 8cb0d2c5813..1248e4605fa 100644 --- a/reactos/dll/win32/rpcrt4_new/rpc_message.c +++ b/reactos/dll/win32/rpcrt4_new/rpc_message.c @@ -1,1159 +1,1159 @@ -/* - * RPC messages - * - * Copyright 2001-2002 Ove Kåven, TransGaming Technologies - * Copyright 2004 Filip Navara - * Copyright 2006 CodeWeavers - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include -#include -#include - -#include "windef.h" -#include "winbase.h" -#include "winerror.h" - -#include "rpc.h" -#include "rpcndr.h" -#include "rpcdcep.h" - -#include "wine/debug.h" - -#include "rpc_binding.h" -#include "rpc_defs.h" -#include "rpc_message.h" -#include "ncastatus.h" - -WINE_DEFAULT_DEBUG_CHANNEL(rpc); - -/* note: the DCE/RPC spec says the alignment amount should be 4, but - * MS/RPC servers seem to always use 16 */ -#define AUTH_ALIGNMENT 16 - -/* gets the amount needed to round a value up to the specified alignment */ -#define ROUND_UP_AMOUNT(value, alignment) \ - (((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) -{ - 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 - }; - 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"); - if (Header->common.flags & RPC_FLG_OBJECT_UUID) - ret += sizeof(UUID); - } else { - TRACE("invalid packet type\n"); - } - - return ret; -} - -static int packet_has_body(const RpcPktHdr *Header) -{ - return (Header->common.ptype == PKT_FAULT) || - (Header->common.ptype == PKT_REQUEST) || - (Header->common.ptype == PKT_RESPONSE); -} - -static int packet_has_auth_verifier(const RpcPktHdr *Header) -{ - return !(Header->common.ptype == PKT_BIND_NACK) && - !(Header->common.ptype == PKT_SHUTDOWN); -} - -static VOID RPCRT4_BuildCommonHeader(RpcPktHdr *Header, unsigned char PacketType, - unsigned long DataRepresentation) -{ - Header->common.rpc_ver = RPC_VER_MAJOR; - Header->common.rpc_ver_minor = RPC_VER_MINOR; - Header->common.ptype = PacketType; - Header->common.drep[0] = LOBYTE(LOWORD(DataRepresentation)); - Header->common.drep[1] = HIBYTE(LOWORD(DataRepresentation)); - Header->common.drep[2] = LOBYTE(HIWORD(DataRepresentation)); - Header->common.drep[3] = HIBYTE(HIWORD(DataRepresentation)); - Header->common.auth_len = 0; - Header->common.call_id = 1; - Header->common.flags = 0; - /* Flags and fragment length are computed in RPCRT4_Send. */ -} - -static RpcPktHdr *RPCRT4_BuildRequestHeader(unsigned long DataRepresentation, - unsigned long BufferLength, - unsigned short ProcNum, - UUID *ObjectUuid) -{ - RpcPktHdr *header; - BOOL has_object; - RPC_STATUS status; - - has_object = (ObjectUuid != NULL && !UuidIsNil(ObjectUuid, &status)); - header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, - sizeof(header->request) + (has_object ? sizeof(UUID) : 0)); - if (header == NULL) { - return NULL; - } - - RPCRT4_BuildCommonHeader(header, PKT_REQUEST, DataRepresentation); - header->common.frag_len = sizeof(header->request); - header->request.alloc_hint = BufferLength; - header->request.context_id = 0; - header->request.opnum = ProcNum; - if (has_object) { - header->common.flags |= RPC_FLG_OBJECT_UUID; - header->common.frag_len += sizeof(UUID); - memcpy(&header->request + 1, ObjectUuid, sizeof(UUID)); - } - - return header; -} - -RpcPktHdr *RPCRT4_BuildResponseHeader(unsigned long DataRepresentation, - unsigned long BufferLength) -{ - RpcPktHdr *header; - - header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(header->response)); - if (header == NULL) { - return NULL; - } - - RPCRT4_BuildCommonHeader(header, PKT_RESPONSE, DataRepresentation); - header->common.frag_len = sizeof(header->response); - header->response.alloc_hint = BufferLength; - - return header; -} - -RpcPktHdr *RPCRT4_BuildFaultHeader(unsigned long DataRepresentation, - RPC_STATUS Status) -{ - RpcPktHdr *header; - - header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(header->fault)); - if (header == NULL) { - return NULL; - } - - RPCRT4_BuildCommonHeader(header, PKT_FAULT, DataRepresentation); - header->common.frag_len = sizeof(header->fault); - header->fault.status = Status; - - return header; -} - -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 *header; - - header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(header->bind)); - if (header == NULL) { - return NULL; - } - - RPCRT4_BuildCommonHeader(header, PKT_BIND, DataRepresentation); - header->common.frag_len = sizeof(header->bind); - 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; - memcpy(&header->bind.abstract, AbstractId, sizeof(RPC_SYNTAX_IDENTIFIER)); - memcpy(&header->bind.transfer, TransferId, sizeof(RPC_SYNTAX_IDENTIFIER)); - - return header; -} - -static RpcPktHdr *RPCRT4_BuildAuthHeader(unsigned long DataRepresentation) -{ - RpcPktHdr *header; - - header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, - sizeof(header->common) + 12); - if (header == NULL) - return NULL; - - RPCRT4_BuildCommonHeader(header, PKT_AUTH3, DataRepresentation); - header->common.frag_len = 0x14; - header->common.auth_len = 0; - - return header; -} - -RpcPktHdr *RPCRT4_BuildBindNackHeader(unsigned long DataRepresentation, - unsigned char RpcVersion, - unsigned char RpcVersionMinor) -{ - RpcPktHdr *header; - - header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(header->bind_nack)); - 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->bind_nack.protocols_count = 1; - header->bind_nack.protocols[0].rpc_ver = RpcVersion; - header->bind_nack.protocols[0].rpc_ver_minor = RpcVersionMinor; - - return header; -} - -RpcPktHdr *RPCRT4_BuildBindAckHeader(unsigned long DataRepresentation, - unsigned short MaxTransmissionSize, - unsigned short MaxReceiveSize, - unsigned long AssocGroupId, - LPCSTR ServerAddress, - unsigned long Result, - unsigned long Reason, - const RPC_SYNTAX_IDENTIFIER *TransferId) -{ - RpcPktHdr *header; - unsigned long header_size; - RpcAddressString *server_address; - RpcResults *results; - RPC_SYNTAX_IDENTIFIER *transfer_id; - - header_size = sizeof(header->bind_ack) + - ROUND_UP(FIELD_OFFSET(RpcAddressString, string[strlen(ServerAddress) + 1]), 4) + - sizeof(RpcResults) + - sizeof(RPC_SYNTAX_IDENTIFIER); - - header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, header_size); - if (header == NULL) { - return NULL; - } - - RPCRT4_BuildCommonHeader(header, PKT_BIND_ACK, DataRepresentation); - header->common.frag_len = header_size; - header->bind_ack.max_tsize = MaxTransmissionSize; - header->bind_ack.max_rsize = MaxReceiveSize; - header->bind_ack.assoc_gid = AssocGroupId; - server_address = (RpcAddressString*)(&header->bind_ack + 1); - 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); - memcpy(transfer_id, TransferId, sizeof(RPC_SYNTAX_IDENTIFIER)); - - return header; -} - -VOID RPCRT4_FreeHeader(RpcPktHdr *Header) -{ - HeapFree(GetProcessHeap(), 0, Header); -} - -NCA_STATUS RPC2NCA_STATUS(RPC_STATUS status) -{ - switch (status) - { - case ERROR_INVALID_HANDLE: return NCA_S_FAULT_CONTEXT_MISMATCH; - case ERROR_OUTOFMEMORY: return NCA_S_FAULT_REMOTE_NO_MEMORY; - case RPC_S_NOT_LISTENING: return NCA_S_SERVER_TOO_BUSY; - case RPC_S_UNKNOWN_IF: return NCA_S_UNK_IF; - case RPC_S_SERVER_TOO_BUSY: return NCA_S_SERVER_TOO_BUSY; - case RPC_S_CALL_FAILED: return NCA_S_FAULT_UNSPEC; - case RPC_S_CALL_FAILED_DNE: return NCA_S_MANAGER_NOT_ENTERED; - case RPC_S_PROTOCOL_ERROR: return NCA_S_PROTO_ERROR; - case RPC_S_UNSUPPORTED_TYPE: return NCA_S_UNSUPPORTED_TYPE; - case RPC_S_INVALID_TAG: return NCA_S_FAULT_INVALID_TAG; - case RPC_S_INVALID_BOUND: return NCA_S_FAULT_INVALID_BOUND; - case RPC_S_PROCNUM_OUT_OF_RANGE: return NCA_S_OP_RNG_ERROR; - case RPC_X_SS_HANDLES_MISMATCH: return NCA_S_FAULT_CONTEXT_MISMATCH; - case RPC_S_CALL_CANCELLED: return NCA_S_FAULT_CANCEL; - case RPC_S_COMM_FAILURE: return NCA_S_COMM_FAILURE; - case RPC_X_WRONG_PIPE_ORDER: return NCA_S_FAULT_PIPE_ORDER; - case RPC_X_PIPE_CLOSED: return NCA_S_FAULT_PIPE_CLOSED; - case RPC_X_PIPE_DISCIPLINE_ERROR: return NCA_S_FAULT_PIPE_DISCIPLINE; - case RPC_X_PIPE_EMPTY: return NCA_S_FAULT_PIPE_EMPTY; - case STATUS_FLOAT_DIVIDE_BY_ZERO: return NCA_S_FAULT_FP_DIV_ZERO; - case STATUS_FLOAT_INVALID_OPERATION: return NCA_S_FAULT_FP_ERROR; - case STATUS_FLOAT_OVERFLOW: return NCA_S_FAULT_FP_OVERFLOW; - case STATUS_FLOAT_UNDERFLOW: return NCA_S_FAULT_FP_UNDERFLOW; - case STATUS_INTEGER_DIVIDE_BY_ZERO: return NCA_S_FAULT_INT_DIV_BY_ZERO; - case STATUS_INTEGER_OVERFLOW: return NCA_S_FAULT_INT_OVERFLOW; - default: return status; - } -} - -RPC_STATUS NCA2RPC_STATUS(NCA_STATUS status) -{ - switch (status) - { - case NCA_S_COMM_FAILURE: return RPC_S_COMM_FAILURE; - case NCA_S_OP_RNG_ERROR: return RPC_S_PROCNUM_OUT_OF_RANGE; - case NCA_S_UNK_IF: return RPC_S_UNKNOWN_IF; - case NCA_S_YOU_CRASHED: return RPC_S_CALL_FAILED; - case NCA_S_PROTO_ERROR: return RPC_S_PROTOCOL_ERROR; - case NCA_S_OUT_ARGS_TOO_BIG: return ERROR_NOT_ENOUGH_SERVER_MEMORY; - case NCA_S_SERVER_TOO_BUSY: return RPC_S_SERVER_TOO_BUSY; - case NCA_S_UNSUPPORTED_TYPE: return RPC_S_UNSUPPORTED_TYPE; - case NCA_S_FAULT_INT_DIV_BY_ZERO: return RPC_S_ZERO_DIVIDE; - case NCA_S_FAULT_ADDR_ERROR: return RPC_S_ADDRESS_ERROR; - case NCA_S_FAULT_FP_DIV_ZERO: return RPC_S_FP_DIV_ZERO; - case NCA_S_FAULT_FP_UNDERFLOW: return RPC_S_FP_UNDERFLOW; - case NCA_S_FAULT_FP_OVERFLOW: return RPC_S_FP_OVERFLOW; - case NCA_S_FAULT_INVALID_TAG: return RPC_S_INVALID_TAG; - case NCA_S_FAULT_INVALID_BOUND: return RPC_S_INVALID_BOUND; - case NCA_S_RPC_VERSION_MISMATCH: return RPC_S_PROTOCOL_ERROR; - case NCA_S_UNSPEC_REJECT: return RPC_S_CALL_FAILED_DNE; - case NCA_S_BAD_ACTID: return RPC_S_CALL_FAILED_DNE; - case NCA_S_WHO_ARE_YOU_FAILED: return RPC_S_CALL_FAILED; - case NCA_S_MANAGER_NOT_ENTERED: return RPC_S_CALL_FAILED_DNE; - case NCA_S_FAULT_CANCEL: return RPC_S_CALL_CANCELLED; - case NCA_S_FAULT_ILL_INST: return RPC_S_ADDRESS_ERROR; - case NCA_S_FAULT_FP_ERROR: return RPC_S_FP_OVERFLOW; - case NCA_S_FAULT_INT_OVERFLOW: return RPC_S_ADDRESS_ERROR; - case NCA_S_FAULT_UNSPEC: return RPC_S_CALL_FAILED; - case NCA_S_FAULT_PIPE_EMPTY: return RPC_X_PIPE_EMPTY; - case NCA_S_FAULT_PIPE_CLOSED: return RPC_X_PIPE_CLOSED; - case NCA_S_FAULT_PIPE_ORDER: return RPC_X_WRONG_PIPE_ORDER; - case NCA_S_FAULT_PIPE_DISCIPLINE: return RPC_X_PIPE_DISCIPLINE_ERROR; - case NCA_S_FAULT_PIPE_COMM_ERROR: return RPC_S_COMM_FAILURE; - case NCA_S_FAULT_PIPE_MEMORY: return ERROR_OUTOFMEMORY; - case NCA_S_FAULT_CONTEXT_MISMATCH: return ERROR_INVALID_HANDLE; - case NCA_S_FAULT_REMOTE_NO_MEMORY: return ERROR_NOT_ENOUGH_SERVER_MEMORY; - default: return status; - } -} - -static RPC_STATUS RPCRT4_SecurePacket(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) -{ - SecBufferDesc message; - SecBuffer buffers[4]; - SECURITY_STATUS sec_status; - - message.ulVersion = SECBUFFER_VERSION; - message.cBuffers = sizeof(buffers)/sizeof(buffers[0]); - message.pBuffers = buffers; - - buffers[0].cbBuffer = hdr_size; - buffers[0].BufferType = SECBUFFER_DATA|SECBUFFER_READONLY_WITH_CHECKSUM; - buffers[0].pvBuffer = hdr; - buffers[1].cbBuffer = stub_data_size; - buffers[1].BufferType = SECBUFFER_DATA; - buffers[1].pvBuffer = stub_data; - buffers[2].cbBuffer = sizeof(*auth_hdr); - buffers[2].BufferType = SECBUFFER_DATA|SECBUFFER_READONLY_WITH_CHECKSUM; - buffers[2].pvBuffer = auth_hdr; - buffers[3].cbBuffer = auth_value_size; - buffers[3].BufferType = SECBUFFER_TOKEN; - buffers[3].pvBuffer = auth_value; - - if (dir == SECURE_PACKET_SEND) - { - if ((auth_hdr->auth_level == RPC_C_AUTHN_LEVEL_PKT_PRIVACY) && packet_has_body(hdr)) - { - sec_status = EncryptMessage(&Connection->ctx, 0, &message, 0 /* FIXME */); - if (sec_status != SEC_E_OK) - { - ERR("EncryptMessage failed with 0x%08x\n", sec_status); - return RPC_S_SEC_PKG_ERROR; - } - } - else if (auth_hdr->auth_level != RPC_C_AUTHN_LEVEL_NONE) - { - sec_status = MakeSignature(&Connection->ctx, 0, &message, 0 /* FIXME */); - if (sec_status != SEC_E_OK) - { - ERR("MakeSignature failed with 0x%08x\n", sec_status); - return RPC_S_SEC_PKG_ERROR; - } - } - } - else if (dir == SECURE_PACKET_RECEIVE) - { - if ((auth_hdr->auth_level == RPC_C_AUTHN_LEVEL_PKT_PRIVACY) && packet_has_body(hdr)) - { - sec_status = DecryptMessage(&Connection->ctx, &message, 0 /* FIXME */, 0); - if (sec_status != SEC_E_OK) - { - ERR("DecryptMessage failed with 0x%08x\n", sec_status); - return RPC_S_SEC_PKG_ERROR; - } - } - else if (auth_hdr->auth_level != RPC_C_AUTHN_LEVEL_NONE) - { - sec_status = VerifySignature(&Connection->ctx, &message, 0 /* FIXME */, NULL); - if (sec_status != SEC_E_OK) - { - ERR("VerifySignature failed with 0x%08x\n", sec_status); - return RPC_S_SEC_PKG_ERROR; - } - } - } - - return RPC_S_OK; -} - -/*********************************************************************** - * RPCRT4_SendAuth (internal) - * - * Transmit a packet with authorization data over connection in acceptable fragments. - */ -static RPC_STATUS RPCRT4_SendAuth(RpcConnection *Connection, RpcPktHdr *Header, - void *Buffer, unsigned int BufferLength, - const void *Auth, unsigned int AuthLength) -{ - PUCHAR buffer_pos; - DWORD hdr_size; - LONG count; - unsigned char *pkt; - LONG alen; - RPC_STATUS status; - - RPCRT4_SetThreadCurrentConnection(Connection); - - buffer_pos = Buffer; - /* The packet building functions save the packet header size, so we can use it. */ - hdr_size = Header->common.frag_len; - if (AuthLength) - Header->common.auth_len = AuthLength; - else if (Connection->AuthInfo && packet_has_auth_verifier(Header)) - { - if ((Connection->AuthInfo->AuthnLevel == RPC_C_AUTHN_LEVEL_PKT_PRIVACY) && packet_has_body(Header)) - Header->common.auth_len = Connection->encryption_auth_len; - else - Header->common.auth_len = Connection->signature_auth_len; - } - else - Header->common.auth_len = 0; - Header->common.flags |= RPC_FLG_FIRST; - Header->common.flags &= ~RPC_FLG_LAST; - - alen = RPC_AUTH_VERIFIER_LEN(&Header->common); - - while (!(Header->common.flags & RPC_FLG_LAST)) { - unsigned char auth_pad_len = Header->common.auth_len ? ROUND_UP_AMOUNT(BufferLength, AUTH_ALIGNMENT) : 0; - unsigned int pkt_size = BufferLength + hdr_size + alen + auth_pad_len; - - /* decide if we need to split the packet into fragments */ - if (pkt_size <= Connection->MaxTransmissionSize) { - Header->common.flags |= RPC_FLG_LAST; - Header->common.frag_len = pkt_size; - } else { - auth_pad_len = 0; - /* make sure packet payload will be a multiple of 16 */ - Header->common.frag_len = - ((Connection->MaxTransmissionSize - hdr_size - alen) & ~(AUTH_ALIGNMENT-1)) + - hdr_size + alen; - } - - pkt = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Header->common.frag_len); - - memcpy(pkt, Header, hdr_size); - - /* fragment consisted of header only and is the last one */ - if (hdr_size == Header->common.frag_len) - goto write; - - 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)) - { - RpcAuthVerifier *auth_hdr = (RpcAuthVerifier *)&pkt[Header->common.frag_len - alen]; - - auth_hdr->auth_type = Connection->AuthInfo->AuthnSvc; - auth_hdr->auth_level = Connection->AuthInfo->AuthnLevel; - auth_hdr->auth_pad_length = auth_pad_len; - auth_hdr->auth_reserved = 0; - /* a unique number... */ - auth_hdr->auth_context_id = (unsigned long)Connection; - - if (AuthLength) - memcpy(auth_hdr + 1, Auth, AuthLength); - else - { - status = RPCRT4_SecurePacket(Connection, SECURE_PACKET_SEND, - (RpcPktHdr *)pkt, hdr_size, - pkt + hdr_size, Header->common.frag_len - hdr_size - alen, - auth_hdr, - (unsigned char *)(auth_hdr + 1), Header->common.auth_len); - if (status != RPC_S_OK) - { - HeapFree(GetProcessHeap(), 0, pkt); - RPCRT4_SetThreadCurrentConnection(NULL); - return status; - } - } - } - -write: - count = rpcrt4_conn_write(Connection, pkt, Header->common.frag_len); - HeapFree(GetProcessHeap(), 0, pkt); - if (count<0) { - WARN("rpcrt4_conn_write failed (auth)\n"); - RPCRT4_SetThreadCurrentConnection(NULL); - return RPC_S_CALL_FAILED; - } - - buffer_pos += Header->common.frag_len - hdr_size - alen - auth_pad_len; - BufferLength -= Header->common.frag_len - hdr_size - alen - auth_pad_len; - Header->common.flags &= ~RPC_FLG_FIRST; - } - - RPCRT4_SetThreadCurrentConnection(NULL); - return RPC_S_OK; -} - -/*********************************************************************** - * RPCRT4_ClientAuthorize (internal) - * - * Authorize a client connection. A NULL in param signifies a new connection. - */ -static RPC_STATUS RPCRT4_ClientAuthorize(RpcConnection *conn, SecBuffer *in, - SecBuffer *out) -{ - 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; - - 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; - - out->BufferType = SECBUFFER_TOKEN; - out->cbBuffer = conn->AuthInfo->cbMaxToken; - out->pvBuffer = HeapAlloc(GetProcessHeap(), 0, out->cbBuffer); - if (!out->pvBuffer) return ERROR_OUTOFMEMORY; - - out_desc.ulVersion = 0; - out_desc.cBuffers = 1; - out_desc.pBuffers = out; - - inp_desc.cBuffers = 1; - inp_desc.pBuffers = in; - inp_desc.ulVersion = 0; - - r = InitializeSecurityContextA(&conn->AuthInfo->cred, in ? &conn->ctx : NULL, - NULL, context_req, 0, SECURITY_NETWORK_DREP, - in ? &inp_desc : NULL, 0, &conn->ctx, &out_desc, &conn->attr, - &conn->exp); - if (FAILED(r)) - { - WARN("InitializeSecurityContext failed with error 0x%08x\n", r); - goto failed; - } - - TRACE("r = 0x%08x, attr = 0x%08x\n", r, conn->attr); - continue_needed = ((r == SEC_I_CONTINUE_NEEDED) || - (r == SEC_I_COMPLETE_AND_CONTINUE)); - - if ((r == SEC_I_COMPLETE_NEEDED) || (r == SEC_I_COMPLETE_AND_CONTINUE)) - { - TRACE("complete needed\n"); - r = CompleteAuthToken(&conn->ctx, &out_desc); - if (FAILED(r)) - { - WARN("CompleteAuthToken failed with error 0x%08x\n", r); - goto failed; - } - } - - TRACE("cbBuffer = %ld\n", out->cbBuffer); - - if (!continue_needed) - { - r = QueryContextAttributesA(&conn->ctx, SECPKG_ATTR_SIZES, &secctx_sizes); - if (FAILED(r)) - { - WARN("QueryContextAttributes failed with error 0x%08x\n", r); - goto failed; - } - conn->signature_auth_len = secctx_sizes.cbMaxSignature; - conn->encryption_auth_len = secctx_sizes.cbSecurityTrailer; - } - - return RPC_S_OK; - -failed: - HeapFree(GetProcessHeap(), 0, out->pvBuffer); - out->pvBuffer = NULL; - return ERROR_ACCESS_DENIED; /* FIXME: is this correct? */ -} - -/*********************************************************************** - * RPCRT4_AuthorizeBinding (internal) - */ -static RPC_STATUS RPCRT_AuthorizeConnection(RpcConnection* conn, - BYTE *challenge, ULONG count) -{ - SecBuffer inp, out; - RpcPktHdr *resp_hdr; - RPC_STATUS status; - - TRACE("challenge %s, %d bytes\n", challenge, count); - - inp.BufferType = SECBUFFER_TOKEN; - inp.pvBuffer = challenge; - inp.cbBuffer = count; - - status = RPCRT4_ClientAuthorize(conn, &inp, &out); - if (status) return status; - - resp_hdr = RPCRT4_BuildAuthHeader(NDR_LOCAL_DATA_REPRESENTATION); - if (!resp_hdr) - return E_OUTOFMEMORY; - - status = RPCRT4_SendAuth(conn, resp_hdr, NULL, 0, out.pvBuffer, out.cbBuffer); - - HeapFree(GetProcessHeap(), 0, out.pvBuffer); - RPCRT4_FreeHeader(resp_hdr); - - return status; -} - -/*********************************************************************** - * RPCRT4_Send (internal) - * - * Transmit a packet over connection in acceptable fragments. - */ -RPC_STATUS RPCRT4_Send(RpcConnection *Connection, RpcPktHdr *Header, - void *Buffer, unsigned int BufferLength) -{ - RPC_STATUS r; - SecBuffer out; - - if (!Connection->AuthInfo || SecIsValidHandle(&Connection->ctx)) - { - return RPCRT4_SendAuth(Connection, Header, Buffer, BufferLength, NULL, 0); - } - - /* tack on a negotiate packet */ - RPCRT4_ClientAuthorize(Connection, NULL, &out); - r = RPCRT4_SendAuth(Connection, Header, Buffer, BufferLength, out.pvBuffer, out.cbBuffer); - HeapFree(GetProcessHeap(), 0, out.pvBuffer); - - return r; -} - -/*********************************************************************** - * RPCRT4_Receive (internal) - * - * Receive a packet from connection and merge the fragments. - */ -RPC_STATUS RPCRT4_Receive(RpcConnection *Connection, RpcPktHdr **Header, - PRPC_MESSAGE pMsg) -{ - RPC_STATUS status; - DWORD hdr_length; - LONG dwRead; - unsigned short first_flag; - unsigned long data_length; - unsigned long buffer_length; - unsigned long auth_length; - unsigned char *auth_data = NULL; - RpcPktCommonHdr common_hdr; - - *Header = NULL; - - TRACE("(%p, %p, %p)\n", Connection, Header, pMsg); - - RPCRT4_SetThreadCurrentConnection(Connection); - - /* read packet common header */ - dwRead = rpcrt4_conn_read(Connection, &common_hdr, sizeof(common_hdr)); - if (dwRead != sizeof(common_hdr)) { - WARN("Short read of header, %d bytes\n", dwRead); - status = RPC_S_CALL_FAILED; - goto fail; - } - - /* verify if the header really makes sense */ - if (common_hdr.rpc_ver != RPC_VER_MAJOR || - common_hdr.rpc_ver_minor != RPC_VER_MINOR) { - WARN("unhandled packet version\n"); - status = RPC_S_PROTOCOL_ERROR; - 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); - memcpy(*Header, &common_hdr, sizeof(common_hdr)); - - /* read the rest of packet header */ - dwRead = rpcrt4_conn_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_CALL_FAILED; - goto fail; - } - - /* read packet body */ - switch (common_hdr.ptype) { - case PKT_RESPONSE: - pMsg->BufferLength = (*Header)->response.alloc_hint; - break; - case PKT_REQUEST: - pMsg->BufferLength = (*Header)->request.alloc_hint; - break; - default: - pMsg->BufferLength = common_hdr.frag_len - hdr_length - RPC_AUTH_VERIFIER_LEN(&common_hdr); - } - - TRACE("buffer length = %u\n", pMsg->BufferLength); - - status = I_RpcGetBuffer(pMsg); - if (status != RPC_S_OK) goto fail; - - first_flag = RPC_FLG_FIRST; - auth_length = common_hdr.auth_len; - if (auth_length) { - auth_data = HeapAlloc(GetProcessHeap(), 0, RPC_AUTH_VERIFIER_LEN(&common_hdr)); - if (!auth_data) { - status = RPC_S_OUT_OF_RESOURCES; - goto fail; - } - } - buffer_length = 0; - while (TRUE) - { - unsigned int header_auth_len = RPC_AUTH_VERIFIER_LEN(&(*Header)->common); - - /* verify header fields */ - - if (((*Header)->common.frag_len < hdr_length) || - ((*Header)->common.frag_len - hdr_length < header_auth_len)) { - WARN("frag_len %d too small for hdr_length %d and auth_len %d\n", - (*Header)->common.frag_len, hdr_length, header_auth_len); - status = RPC_S_PROTOCOL_ERROR; - goto fail; - } - - if ((*Header)->common.auth_len != auth_length) { - WARN("auth_len header field changed from %ld to %d\n", - auth_length, (*Header)->common.auth_len); - status = RPC_S_PROTOCOL_ERROR; - goto fail; - } - - if (((*Header)->common.flags & RPC_FLG_FIRST) != first_flag) { - TRACE("invalid packet flags\n"); - status = RPC_S_PROTOCOL_ERROR; - goto fail; - } - - data_length = (*Header)->common.frag_len - hdr_length - header_auth_len; - if (data_length + buffer_length > pMsg->BufferLength) { - TRACE("allocation hint exceeded, new buffer length = %ld\n", - data_length + buffer_length); - pMsg->BufferLength = data_length + buffer_length; - status = I_RpcReAllocateBuffer(pMsg); - if (status != RPC_S_OK) goto fail; - } - - if (data_length == 0) dwRead = 0; else - dwRead = rpcrt4_conn_read(Connection, - (unsigned char *)pMsg->Buffer + buffer_length, data_length); - if (dwRead != data_length) { - WARN("bad data length, %d/%ld\n", dwRead, data_length); - status = RPC_S_CALL_FAILED; - goto fail; - } - - if (header_auth_len) { - if (header_auth_len < sizeof(RpcAuthVerifier)) { - WARN("bad auth verifier length %d\n", header_auth_len); - status = RPC_S_PROTOCOL_ERROR; - goto fail; - } - - /* FIXME: we should accumulate authentication data for the bind, - * bind_ack, alter_context and alter_context_response if necessary. - * however, the details of how this is done is very sketchy in the - * DCE/RPC spec. for all other packet types that have authentication - * verifier data then it is just duplicated in all the fragments */ - dwRead = rpcrt4_conn_read(Connection, auth_data, header_auth_len); - if (dwRead != header_auth_len) { - WARN("bad authentication data length, %d/%d\n", dwRead, - header_auth_len); - status = RPC_S_CALL_FAILED; - goto fail; - } - - /* these packets are handled specially, not by the generic SecurePacket - * function */ - if ((common_hdr.ptype != PKT_BIND) && - (common_hdr.ptype != PKT_BIND_ACK) && - (common_hdr.ptype != PKT_AUTH3)) - { - status = RPCRT4_SecurePacket(Connection, SECURE_PACKET_RECEIVE, - *Header, hdr_length, - (unsigned char *)pMsg->Buffer + buffer_length, data_length, - (RpcAuthVerifier *)auth_data, - (unsigned char *)auth_data + sizeof(RpcAuthVerifier), - header_auth_len - sizeof(RpcAuthVerifier)); - if (status != RPC_S_OK) goto fail; - } - } - - buffer_length += data_length; - if (!((*Header)->common.flags & RPC_FLG_LAST)) { - TRACE("next header\n"); - - /* read the header of next packet */ - dwRead = rpcrt4_conn_read(Connection, *Header, hdr_length); - if (dwRead != hdr_length) { - WARN("invalid packet header size (%d)\n", dwRead); - status = RPC_S_CALL_FAILED; - goto fail; - } - - first_flag = 0; - } else { - break; - } - } - pMsg->BufferLength = buffer_length; - - /* respond to authorization request */ - if (common_hdr.ptype == PKT_BIND_ACK && auth_length > sizeof(RpcAuthVerifier)) - { - status = RPCRT_AuthorizeConnection(Connection, - auth_data + sizeof(RpcAuthVerifier), - auth_length); - if (status) - goto fail; - } - - /* success */ - status = RPC_S_OK; - -fail: - RPCRT4_SetThreadCurrentConnection(NULL); - if (status != RPC_S_OK) { - RPCRT4_FreeHeader(*Header); - *Header = NULL; - } - HeapFree(GetProcessHeap(), 0, auth_data); - return status; -} - -/*********************************************************************** - * I_RpcGetBuffer [RPCRT4.@] - * - * Allocates a buffer for use by I_RpcSend or I_RpcSendReceive and binds to the - * server interface. - * - * PARAMS - * pMsg [I/O] RPC message information. - * - * RETURNS - * Success: RPC_S_OK. - * Failure: RPC_S_INVALID_BINDING if pMsg->Handle is invalid. - * RPC_S_SERVER_UNAVAILABLE if unable to connect to server. - * ERROR_OUTOFMEMORY if buffer allocation failed. - * - * NOTES - * The pMsg->BufferLength field determines the size of the buffer to allocate, - * in bytes. - * - * Use I_RpcFreeBuffer() to unbind from the server and free the message buffer. - * - * SEE ALSO - * I_RpcFreeBuffer(), I_RpcSend(), I_RpcReceive(), I_RpcSendReceive(). - */ -RPC_STATUS WINAPI I_RpcGetBuffer(PRPC_MESSAGE pMsg) -{ - TRACE("(%p): BufferLength=%d\n", pMsg, pMsg->BufferLength); - /* FIXME: pfnAllocate? */ - pMsg->Buffer = HeapAlloc(GetProcessHeap(), 0, pMsg->BufferLength); - - TRACE("Buffer=%p\n", pMsg->Buffer); - /* FIXME: which errors to return? */ - return pMsg->Buffer ? S_OK : E_OUTOFMEMORY; -} - -/*********************************************************************** - * I_RpcReAllocateBuffer (internal) - */ -static RPC_STATUS I_RpcReAllocateBuffer(PRPC_MESSAGE pMsg) -{ - TRACE("(%p): BufferLength=%d\n", pMsg, pMsg->BufferLength); - pMsg->Buffer = HeapReAlloc(GetProcessHeap(), 0, pMsg->Buffer, pMsg->BufferLength); - - TRACE("Buffer=%p\n", pMsg->Buffer); - return pMsg->Buffer ? RPC_S_OK : RPC_S_OUT_OF_RESOURCES; -} - -/*********************************************************************** - * I_RpcFreeBuffer [RPCRT4.@] - * - * Frees a buffer allocated by I_RpcGetBuffer or I_RpcReceive and unbinds from - * the server interface. - * - * PARAMS - * pMsg [I/O] RPC message information. - * - * RETURNS - * RPC_S_OK. - * - * SEE ALSO - * I_RpcGetBuffer(), I_RpcReceive(). - */ -RPC_STATUS WINAPI I_RpcFreeBuffer(PRPC_MESSAGE pMsg) -{ - TRACE("(%p) Buffer=%p\n", pMsg, pMsg->Buffer); - /* FIXME: pfnFree? */ - HeapFree(GetProcessHeap(), 0, pMsg->Buffer); - pMsg->Buffer = NULL; - return S_OK; -} - -/*********************************************************************** - * I_RpcSend [RPCRT4.@] - * - * Sends a message to the server. - * - * PARAMS - * pMsg [I/O] RPC message information. - * - * RETURNS - * Unknown. - * - * NOTES - * The buffer must have been allocated with I_RpcGetBuffer(). - * - * SEE ALSO - * I_RpcGetBuffer(), I_RpcReceive(), I_RpcSendReceive(). - */ -RPC_STATUS WINAPI I_RpcSend(PRPC_MESSAGE pMsg) -{ - RpcBinding* bind = (RpcBinding*)pMsg->Handle; - RpcConnection* conn; - RPC_CLIENT_INTERFACE* cif = NULL; - RPC_STATUS status; - RpcPktHdr *hdr; - - TRACE("(%p)\n", pMsg); - if (!bind || bind->server) return RPC_S_INVALID_BINDING; - - cif = pMsg->RpcInterfaceInformation; - if (!cif) return RPC_S_INTERFACE_NOT_FOUND; /* ? */ - - if (!bind->Endpoint || !bind->Endpoint[0]) - { - TRACE("automatically resolving partially bound binding\n"); - status = RpcEpResolveBinding(bind, cif); - if (status != RPC_S_OK) return status; - } - - status = RPCRT4_OpenBinding(bind, &conn, &cif->TransferSyntax, - &cif->InterfaceId); - if (status != RPC_S_OK) return status; - - hdr = RPCRT4_BuildRequestHeader(pMsg->DataRepresentation, - pMsg->BufferLength, pMsg->ProcNum, - &bind->ObjectUuid); - if (!hdr) - { - RPCRT4_CloseBinding(bind, conn); - return ERROR_OUTOFMEMORY; - } - hdr->common.call_id = conn->NextCallId++; - - status = RPCRT4_Send(conn, hdr, pMsg->Buffer, pMsg->BufferLength); - - RPCRT4_FreeHeader(hdr); - - /* save the connection, so the response can be read from it */ - pMsg->ReservedForRuntime = conn; - return status; -} - -/* is this status something that the server can't recover from? */ -static inline BOOL is_hard_error(RPC_STATUS status) -{ - switch (status) - { - case 0: /* user-defined fault */ - case ERROR_ACCESS_DENIED: - case ERROR_INVALID_PARAMETER: - case RPC_S_PROTOCOL_ERROR: - case RPC_S_CALL_FAILED: - case RPC_S_CALL_FAILED_DNE: - case RPC_S_SEC_PKG_ERROR: - return TRUE; - default: - return FALSE; - } -} - -/*********************************************************************** - * I_RpcReceive [RPCRT4.@] - */ -RPC_STATUS WINAPI I_RpcReceive(PRPC_MESSAGE pMsg) -{ - RpcBinding* bind = (RpcBinding*)pMsg->Handle; - RpcConnection* conn; - RPC_CLIENT_INTERFACE* cif = NULL; - RPC_SERVER_INTERFACE* sif = NULL; - RPC_STATUS status; - RpcPktHdr *hdr = NULL; - - TRACE("(%p)\n", pMsg); - if (!bind) return RPC_S_INVALID_BINDING; - - if (pMsg->ReservedForRuntime) { - conn = pMsg->ReservedForRuntime; - pMsg->ReservedForRuntime = NULL; - } else { - if (bind->server) { - sif = pMsg->RpcInterfaceInformation; - if (!sif) return RPC_S_INTERFACE_NOT_FOUND; /* ? */ - status = RPCRT4_OpenBinding(bind, &conn, &sif->TransferSyntax, - &sif->InterfaceId); - } else { - cif = pMsg->RpcInterfaceInformation; - if (!cif) return RPC_S_INTERFACE_NOT_FOUND; /* ? */ - - if (!bind->Endpoint || !bind->Endpoint[0]) - { - TRACE("automatically resolving partially bound binding\n"); - status = RpcEpResolveBinding(bind, cif); - if (status != RPC_S_OK) return status; - } - - status = RPCRT4_OpenBinding(bind, &conn, &cif->TransferSyntax, - &cif->InterfaceId); - } - if (status != RPC_S_OK) return status; - } - - status = RPCRT4_Receive(conn, &hdr, pMsg); - if (status != RPC_S_OK) { - WARN("receive failed with error %lx\n", status); - goto fail; - } - - switch (hdr->common.ptype) { - case PKT_RESPONSE: - if (bind->server) { - status = RPC_S_PROTOCOL_ERROR; - goto fail; - } - break; - case PKT_REQUEST: - if (!bind->server) { - status = RPC_S_PROTOCOL_ERROR; - goto fail; - } - break; - case PKT_FAULT: - ERR ("we got fault packet with status 0x%lx\n", hdr->fault.status); - status = NCA2RPC_STATUS(hdr->fault.status); - if (is_hard_error(status)) - goto fail; - break; - default: - WARN("bad packet type %d\n", hdr->common.ptype); - status = RPC_S_PROTOCOL_ERROR; - goto fail; - } - - /* success */ - RPCRT4_CloseBinding(bind, conn); - RPCRT4_FreeHeader(hdr); - return status; - -fail: - RPCRT4_FreeHeader(hdr); - RPCRT4_DestroyConnection(conn); - return status; -} - -/*********************************************************************** - * I_RpcSendReceive [RPCRT4.@] - * - * Sends a message to the server and receives the response. - * - * PARAMS - * pMsg [I/O] RPC message information. - * - * RETURNS - * Success: RPC_S_OK. - * Failure: Any error code. - * - * NOTES - * The buffer must have been allocated with I_RpcGetBuffer(). - * - * SEE ALSO - * I_RpcGetBuffer(), I_RpcSend(), I_RpcReceive(). - */ -RPC_STATUS WINAPI I_RpcSendReceive(PRPC_MESSAGE pMsg) -{ - RPC_STATUS status; - RPC_MESSAGE original_message; - - TRACE("(%p)\n", pMsg); - - original_message = *pMsg; - status = I_RpcSend(pMsg); - if (status == RPC_S_OK) - status = I_RpcReceive(pMsg); - /* free the buffer replaced by a new buffer in I_RpcReceive */ - if (status == RPC_S_OK) - I_RpcFreeBuffer(&original_message); - return status; -} +/* + * RPC messages + * + * Copyright 2001-2002 Ove Kåven, TransGaming Technologies + * Copyright 2004 Filip Navara + * Copyright 2006 CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include +#include + +#include "windef.h" +#include "winbase.h" +#include "winerror.h" + +#include "rpc.h" +#include "rpcndr.h" +#include "rpcdcep.h" + +#include "wine/debug.h" + +#include "rpc_binding.h" +#include "rpc_defs.h" +#include "rpc_message.h" +#include "ncastatus.h" + +WINE_DEFAULT_DEBUG_CHANNEL(rpc); + +/* note: the DCE/RPC spec says the alignment amount should be 4, but + * MS/RPC servers seem to always use 16 */ +#define AUTH_ALIGNMENT 16 + +/* gets the amount needed to round a value up to the specified alignment */ +#define ROUND_UP_AMOUNT(value, alignment) \ + (((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) +{ + 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 + }; + 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"); + if (Header->common.flags & RPC_FLG_OBJECT_UUID) + ret += sizeof(UUID); + } else { + TRACE("invalid packet type\n"); + } + + return ret; +} + +static int packet_has_body(const RpcPktHdr *Header) +{ + return (Header->common.ptype == PKT_FAULT) || + (Header->common.ptype == PKT_REQUEST) || + (Header->common.ptype == PKT_RESPONSE); +} + +static int packet_has_auth_verifier(const RpcPktHdr *Header) +{ + return !(Header->common.ptype == PKT_BIND_NACK) && + !(Header->common.ptype == PKT_SHUTDOWN); +} + +static VOID RPCRT4_BuildCommonHeader(RpcPktHdr *Header, unsigned char PacketType, + unsigned long DataRepresentation) +{ + Header->common.rpc_ver = RPC_VER_MAJOR; + Header->common.rpc_ver_minor = RPC_VER_MINOR; + Header->common.ptype = PacketType; + Header->common.drep[0] = LOBYTE(LOWORD(DataRepresentation)); + Header->common.drep[1] = HIBYTE(LOWORD(DataRepresentation)); + Header->common.drep[2] = LOBYTE(HIWORD(DataRepresentation)); + Header->common.drep[3] = HIBYTE(HIWORD(DataRepresentation)); + Header->common.auth_len = 0; + Header->common.call_id = 1; + Header->common.flags = 0; + /* Flags and fragment length are computed in RPCRT4_Send. */ +} + +static RpcPktHdr *RPCRT4_BuildRequestHeader(unsigned long DataRepresentation, + unsigned long BufferLength, + unsigned short ProcNum, + UUID *ObjectUuid) +{ + RpcPktHdr *header; + BOOL has_object; + RPC_STATUS status; + + has_object = (ObjectUuid != NULL && !UuidIsNil(ObjectUuid, &status)); + header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof(header->request) + (has_object ? sizeof(UUID) : 0)); + if (header == NULL) { + return NULL; + } + + RPCRT4_BuildCommonHeader(header, PKT_REQUEST, DataRepresentation); + header->common.frag_len = sizeof(header->request); + header->request.alloc_hint = BufferLength; + header->request.context_id = 0; + header->request.opnum = ProcNum; + if (has_object) { + header->common.flags |= RPC_FLG_OBJECT_UUID; + header->common.frag_len += sizeof(UUID); + memcpy(&header->request + 1, ObjectUuid, sizeof(UUID)); + } + + return header; +} + +RpcPktHdr *RPCRT4_BuildResponseHeader(unsigned long DataRepresentation, + unsigned long BufferLength) +{ + RpcPktHdr *header; + + header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(header->response)); + if (header == NULL) { + return NULL; + } + + RPCRT4_BuildCommonHeader(header, PKT_RESPONSE, DataRepresentation); + header->common.frag_len = sizeof(header->response); + header->response.alloc_hint = BufferLength; + + return header; +} + +RpcPktHdr *RPCRT4_BuildFaultHeader(unsigned long DataRepresentation, + RPC_STATUS Status) +{ + RpcPktHdr *header; + + header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(header->fault)); + if (header == NULL) { + return NULL; + } + + RPCRT4_BuildCommonHeader(header, PKT_FAULT, DataRepresentation); + header->common.frag_len = sizeof(header->fault); + header->fault.status = Status; + + return header; +} + +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 *header; + + header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(header->bind)); + if (header == NULL) { + return NULL; + } + + RPCRT4_BuildCommonHeader(header, PKT_BIND, DataRepresentation); + header->common.frag_len = sizeof(header->bind); + 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; + memcpy(&header->bind.abstract, AbstractId, sizeof(RPC_SYNTAX_IDENTIFIER)); + memcpy(&header->bind.transfer, TransferId, sizeof(RPC_SYNTAX_IDENTIFIER)); + + return header; +} + +static RpcPktHdr *RPCRT4_BuildAuthHeader(unsigned long DataRepresentation) +{ + RpcPktHdr *header; + + header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof(header->common) + 12); + if (header == NULL) + return NULL; + + RPCRT4_BuildCommonHeader(header, PKT_AUTH3, DataRepresentation); + header->common.frag_len = 0x14; + header->common.auth_len = 0; + + return header; +} + +RpcPktHdr *RPCRT4_BuildBindNackHeader(unsigned long DataRepresentation, + unsigned char RpcVersion, + unsigned char RpcVersionMinor) +{ + RpcPktHdr *header; + + header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(header->bind_nack)); + 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->bind_nack.protocols_count = 1; + header->bind_nack.protocols[0].rpc_ver = RpcVersion; + header->bind_nack.protocols[0].rpc_ver_minor = RpcVersionMinor; + + return header; +} + +RpcPktHdr *RPCRT4_BuildBindAckHeader(unsigned long DataRepresentation, + unsigned short MaxTransmissionSize, + unsigned short MaxReceiveSize, + unsigned long AssocGroupId, + LPCSTR ServerAddress, + unsigned long Result, + unsigned long Reason, + const RPC_SYNTAX_IDENTIFIER *TransferId) +{ + RpcPktHdr *header; + unsigned long header_size; + RpcAddressString *server_address; + RpcResults *results; + RPC_SYNTAX_IDENTIFIER *transfer_id; + + header_size = sizeof(header->bind_ack) + + ROUND_UP(FIELD_OFFSET(RpcAddressString, string[strlen(ServerAddress) + 1]), 4) + + sizeof(RpcResults) + + sizeof(RPC_SYNTAX_IDENTIFIER); + + header = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, header_size); + if (header == NULL) { + return NULL; + } + + RPCRT4_BuildCommonHeader(header, PKT_BIND_ACK, DataRepresentation); + header->common.frag_len = header_size; + header->bind_ack.max_tsize = MaxTransmissionSize; + header->bind_ack.max_rsize = MaxReceiveSize; + header->bind_ack.assoc_gid = AssocGroupId; + server_address = (RpcAddressString*)(&header->bind_ack + 1); + 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); + memcpy(transfer_id, TransferId, sizeof(RPC_SYNTAX_IDENTIFIER)); + + return header; +} + +VOID RPCRT4_FreeHeader(RpcPktHdr *Header) +{ + HeapFree(GetProcessHeap(), 0, Header); +} + +NCA_STATUS RPC2NCA_STATUS(RPC_STATUS status) +{ + switch (status) + { + case ERROR_INVALID_HANDLE: return NCA_S_FAULT_CONTEXT_MISMATCH; + case ERROR_OUTOFMEMORY: return NCA_S_FAULT_REMOTE_NO_MEMORY; + case RPC_S_NOT_LISTENING: return NCA_S_SERVER_TOO_BUSY; + case RPC_S_UNKNOWN_IF: return NCA_S_UNK_IF; + case RPC_S_SERVER_TOO_BUSY: return NCA_S_SERVER_TOO_BUSY; + case RPC_S_CALL_FAILED: return NCA_S_FAULT_UNSPEC; + case RPC_S_CALL_FAILED_DNE: return NCA_S_MANAGER_NOT_ENTERED; + case RPC_S_PROTOCOL_ERROR: return NCA_S_PROTO_ERROR; + case RPC_S_UNSUPPORTED_TYPE: return NCA_S_UNSUPPORTED_TYPE; + case RPC_S_INVALID_TAG: return NCA_S_FAULT_INVALID_TAG; + case RPC_S_INVALID_BOUND: return NCA_S_FAULT_INVALID_BOUND; + case RPC_S_PROCNUM_OUT_OF_RANGE: return NCA_S_OP_RNG_ERROR; + case RPC_X_SS_HANDLES_MISMATCH: return NCA_S_FAULT_CONTEXT_MISMATCH; + case RPC_S_CALL_CANCELLED: return NCA_S_FAULT_CANCEL; + case RPC_S_COMM_FAILURE: return NCA_S_COMM_FAILURE; + case RPC_X_WRONG_PIPE_ORDER: return NCA_S_FAULT_PIPE_ORDER; + case RPC_X_PIPE_CLOSED: return NCA_S_FAULT_PIPE_CLOSED; + case RPC_X_PIPE_DISCIPLINE_ERROR: return NCA_S_FAULT_PIPE_DISCIPLINE; + case RPC_X_PIPE_EMPTY: return NCA_S_FAULT_PIPE_EMPTY; + case STATUS_FLOAT_DIVIDE_BY_ZERO: return NCA_S_FAULT_FP_DIV_ZERO; + case STATUS_FLOAT_INVALID_OPERATION: return NCA_S_FAULT_FP_ERROR; + case STATUS_FLOAT_OVERFLOW: return NCA_S_FAULT_FP_OVERFLOW; + case STATUS_FLOAT_UNDERFLOW: return NCA_S_FAULT_FP_UNDERFLOW; + case STATUS_INTEGER_DIVIDE_BY_ZERO: return NCA_S_FAULT_INT_DIV_BY_ZERO; + case STATUS_INTEGER_OVERFLOW: return NCA_S_FAULT_INT_OVERFLOW; + default: return status; + } +} + +RPC_STATUS NCA2RPC_STATUS(NCA_STATUS status) +{ + switch (status) + { + case NCA_S_COMM_FAILURE: return RPC_S_COMM_FAILURE; + case NCA_S_OP_RNG_ERROR: return RPC_S_PROCNUM_OUT_OF_RANGE; + case NCA_S_UNK_IF: return RPC_S_UNKNOWN_IF; + case NCA_S_YOU_CRASHED: return RPC_S_CALL_FAILED; + case NCA_S_PROTO_ERROR: return RPC_S_PROTOCOL_ERROR; + case NCA_S_OUT_ARGS_TOO_BIG: return ERROR_NOT_ENOUGH_SERVER_MEMORY; + case NCA_S_SERVER_TOO_BUSY: return RPC_S_SERVER_TOO_BUSY; + case NCA_S_UNSUPPORTED_TYPE: return RPC_S_UNSUPPORTED_TYPE; + case NCA_S_FAULT_INT_DIV_BY_ZERO: return RPC_S_ZERO_DIVIDE; + case NCA_S_FAULT_ADDR_ERROR: return RPC_S_ADDRESS_ERROR; + case NCA_S_FAULT_FP_DIV_ZERO: return RPC_S_FP_DIV_ZERO; + case NCA_S_FAULT_FP_UNDERFLOW: return RPC_S_FP_UNDERFLOW; + case NCA_S_FAULT_FP_OVERFLOW: return RPC_S_FP_OVERFLOW; + case NCA_S_FAULT_INVALID_TAG: return RPC_S_INVALID_TAG; + case NCA_S_FAULT_INVALID_BOUND: return RPC_S_INVALID_BOUND; + case NCA_S_RPC_VERSION_MISMATCH: return RPC_S_PROTOCOL_ERROR; + case NCA_S_UNSPEC_REJECT: return RPC_S_CALL_FAILED_DNE; + case NCA_S_BAD_ACTID: return RPC_S_CALL_FAILED_DNE; + case NCA_S_WHO_ARE_YOU_FAILED: return RPC_S_CALL_FAILED; + case NCA_S_MANAGER_NOT_ENTERED: return RPC_S_CALL_FAILED_DNE; + case NCA_S_FAULT_CANCEL: return RPC_S_CALL_CANCELLED; + case NCA_S_FAULT_ILL_INST: return RPC_S_ADDRESS_ERROR; + case NCA_S_FAULT_FP_ERROR: return RPC_S_FP_OVERFLOW; + case NCA_S_FAULT_INT_OVERFLOW: return RPC_S_ADDRESS_ERROR; + case NCA_S_FAULT_UNSPEC: return RPC_S_CALL_FAILED; + case NCA_S_FAULT_PIPE_EMPTY: return RPC_X_PIPE_EMPTY; + case NCA_S_FAULT_PIPE_CLOSED: return RPC_X_PIPE_CLOSED; + case NCA_S_FAULT_PIPE_ORDER: return RPC_X_WRONG_PIPE_ORDER; + case NCA_S_FAULT_PIPE_DISCIPLINE: return RPC_X_PIPE_DISCIPLINE_ERROR; + case NCA_S_FAULT_PIPE_COMM_ERROR: return RPC_S_COMM_FAILURE; + case NCA_S_FAULT_PIPE_MEMORY: return ERROR_OUTOFMEMORY; + case NCA_S_FAULT_CONTEXT_MISMATCH: return ERROR_INVALID_HANDLE; + case NCA_S_FAULT_REMOTE_NO_MEMORY: return ERROR_NOT_ENOUGH_SERVER_MEMORY; + default: return status; + } +} + +static RPC_STATUS RPCRT4_SecurePacket(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) +{ + SecBufferDesc message; + SecBuffer buffers[4]; + SECURITY_STATUS sec_status; + + message.ulVersion = SECBUFFER_VERSION; + message.cBuffers = sizeof(buffers)/sizeof(buffers[0]); + message.pBuffers = buffers; + + buffers[0].cbBuffer = hdr_size; + buffers[0].BufferType = SECBUFFER_DATA|SECBUFFER_READONLY_WITH_CHECKSUM; + buffers[0].pvBuffer = hdr; + buffers[1].cbBuffer = stub_data_size; + buffers[1].BufferType = SECBUFFER_DATA; + buffers[1].pvBuffer = stub_data; + buffers[2].cbBuffer = sizeof(*auth_hdr); + buffers[2].BufferType = SECBUFFER_DATA|SECBUFFER_READONLY_WITH_CHECKSUM; + buffers[2].pvBuffer = auth_hdr; + buffers[3].cbBuffer = auth_value_size; + buffers[3].BufferType = SECBUFFER_TOKEN; + buffers[3].pvBuffer = auth_value; + + if (dir == SECURE_PACKET_SEND) + { + if ((auth_hdr->auth_level == RPC_C_AUTHN_LEVEL_PKT_PRIVACY) && packet_has_body(hdr)) + { + sec_status = EncryptMessage(&Connection->ctx, 0, &message, 0 /* FIXME */); + if (sec_status != SEC_E_OK) + { + ERR("EncryptMessage failed with 0x%08x\n", sec_status); + return RPC_S_SEC_PKG_ERROR; + } + } + else if (auth_hdr->auth_level != RPC_C_AUTHN_LEVEL_NONE) + { + sec_status = MakeSignature(&Connection->ctx, 0, &message, 0 /* FIXME */); + if (sec_status != SEC_E_OK) + { + ERR("MakeSignature failed with 0x%08x\n", sec_status); + return RPC_S_SEC_PKG_ERROR; + } + } + } + else if (dir == SECURE_PACKET_RECEIVE) + { + if ((auth_hdr->auth_level == RPC_C_AUTHN_LEVEL_PKT_PRIVACY) && packet_has_body(hdr)) + { + sec_status = DecryptMessage(&Connection->ctx, &message, 0 /* FIXME */, 0); + if (sec_status != SEC_E_OK) + { + ERR("DecryptMessage failed with 0x%08x\n", sec_status); + return RPC_S_SEC_PKG_ERROR; + } + } + else if (auth_hdr->auth_level != RPC_C_AUTHN_LEVEL_NONE) + { + sec_status = VerifySignature(&Connection->ctx, &message, 0 /* FIXME */, NULL); + if (sec_status != SEC_E_OK) + { + ERR("VerifySignature failed with 0x%08x\n", sec_status); + return RPC_S_SEC_PKG_ERROR; + } + } + } + + return RPC_S_OK; +} + +/*********************************************************************** + * RPCRT4_SendAuth (internal) + * + * Transmit a packet with authorization data over connection in acceptable fragments. + */ +static RPC_STATUS RPCRT4_SendAuth(RpcConnection *Connection, RpcPktHdr *Header, + void *Buffer, unsigned int BufferLength, + const void *Auth, unsigned int AuthLength) +{ + PUCHAR buffer_pos; + DWORD hdr_size; + LONG count; + unsigned char *pkt; + LONG alen; + RPC_STATUS status; + + RPCRT4_SetThreadCurrentConnection(Connection); + + buffer_pos = Buffer; + /* The packet building functions save the packet header size, so we can use it. */ + hdr_size = Header->common.frag_len; + if (AuthLength) + Header->common.auth_len = AuthLength; + else if (Connection->AuthInfo && packet_has_auth_verifier(Header)) + { + if ((Connection->AuthInfo->AuthnLevel == RPC_C_AUTHN_LEVEL_PKT_PRIVACY) && packet_has_body(Header)) + Header->common.auth_len = Connection->encryption_auth_len; + else + Header->common.auth_len = Connection->signature_auth_len; + } + else + Header->common.auth_len = 0; + Header->common.flags |= RPC_FLG_FIRST; + Header->common.flags &= ~RPC_FLG_LAST; + + alen = RPC_AUTH_VERIFIER_LEN(&Header->common); + + while (!(Header->common.flags & RPC_FLG_LAST)) { + unsigned char auth_pad_len = Header->common.auth_len ? ROUND_UP_AMOUNT(BufferLength, AUTH_ALIGNMENT) : 0; + unsigned int pkt_size = BufferLength + hdr_size + alen + auth_pad_len; + + /* decide if we need to split the packet into fragments */ + if (pkt_size <= Connection->MaxTransmissionSize) { + Header->common.flags |= RPC_FLG_LAST; + Header->common.frag_len = pkt_size; + } else { + auth_pad_len = 0; + /* make sure packet payload will be a multiple of 16 */ + Header->common.frag_len = + ((Connection->MaxTransmissionSize - hdr_size - alen) & ~(AUTH_ALIGNMENT-1)) + + hdr_size + alen; + } + + pkt = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Header->common.frag_len); + + memcpy(pkt, Header, hdr_size); + + /* fragment consisted of header only and is the last one */ + if (hdr_size == Header->common.frag_len) + goto write; + + 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)) + { + RpcAuthVerifier *auth_hdr = (RpcAuthVerifier *)&pkt[Header->common.frag_len - alen]; + + auth_hdr->auth_type = Connection->AuthInfo->AuthnSvc; + auth_hdr->auth_level = Connection->AuthInfo->AuthnLevel; + auth_hdr->auth_pad_length = auth_pad_len; + auth_hdr->auth_reserved = 0; + /* a unique number... */ + auth_hdr->auth_context_id = (unsigned long)Connection; + + if (AuthLength) + memcpy(auth_hdr + 1, Auth, AuthLength); + else + { + status = RPCRT4_SecurePacket(Connection, SECURE_PACKET_SEND, + (RpcPktHdr *)pkt, hdr_size, + pkt + hdr_size, Header->common.frag_len - hdr_size - alen, + auth_hdr, + (unsigned char *)(auth_hdr + 1), Header->common.auth_len); + if (status != RPC_S_OK) + { + HeapFree(GetProcessHeap(), 0, pkt); + RPCRT4_SetThreadCurrentConnection(NULL); + return status; + } + } + } + +write: + count = rpcrt4_conn_write(Connection, pkt, Header->common.frag_len); + HeapFree(GetProcessHeap(), 0, pkt); + if (count<0) { + WARN("rpcrt4_conn_write failed (auth)\n"); + RPCRT4_SetThreadCurrentConnection(NULL); + return RPC_S_CALL_FAILED; + } + + buffer_pos += Header->common.frag_len - hdr_size - alen - auth_pad_len; + BufferLength -= Header->common.frag_len - hdr_size - alen - auth_pad_len; + Header->common.flags &= ~RPC_FLG_FIRST; + } + + RPCRT4_SetThreadCurrentConnection(NULL); + return RPC_S_OK; +} + +/*********************************************************************** + * RPCRT4_ClientAuthorize (internal) + * + * Authorize a client connection. A NULL in param signifies a new connection. + */ +static RPC_STATUS RPCRT4_ClientAuthorize(RpcConnection *conn, SecBuffer *in, + SecBuffer *out) +{ + 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; + + 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; + + out->BufferType = SECBUFFER_TOKEN; + out->cbBuffer = conn->AuthInfo->cbMaxToken; + out->pvBuffer = HeapAlloc(GetProcessHeap(), 0, out->cbBuffer); + if (!out->pvBuffer) return ERROR_OUTOFMEMORY; + + out_desc.ulVersion = 0; + out_desc.cBuffers = 1; + out_desc.pBuffers = out; + + inp_desc.cBuffers = 1; + inp_desc.pBuffers = in; + inp_desc.ulVersion = 0; + + r = InitializeSecurityContextA(&conn->AuthInfo->cred, in ? &conn->ctx : NULL, + NULL, context_req, 0, SECURITY_NETWORK_DREP, + in ? &inp_desc : NULL, 0, &conn->ctx, &out_desc, &conn->attr, + &conn->exp); + if (FAILED(r)) + { + WARN("InitializeSecurityContext failed with error 0x%08x\n", r); + goto failed; + } + + TRACE("r = 0x%08x, attr = 0x%08x\n", r, conn->attr); + continue_needed = ((r == SEC_I_CONTINUE_NEEDED) || + (r == SEC_I_COMPLETE_AND_CONTINUE)); + + if ((r == SEC_I_COMPLETE_NEEDED) || (r == SEC_I_COMPLETE_AND_CONTINUE)) + { + TRACE("complete needed\n"); + r = CompleteAuthToken(&conn->ctx, &out_desc); + if (FAILED(r)) + { + WARN("CompleteAuthToken failed with error 0x%08x\n", r); + goto failed; + } + } + + TRACE("cbBuffer = %ld\n", out->cbBuffer); + + if (!continue_needed) + { + r = QueryContextAttributesA(&conn->ctx, SECPKG_ATTR_SIZES, &secctx_sizes); + if (FAILED(r)) + { + WARN("QueryContextAttributes failed with error 0x%08x\n", r); + goto failed; + } + conn->signature_auth_len = secctx_sizes.cbMaxSignature; + conn->encryption_auth_len = secctx_sizes.cbSecurityTrailer; + } + + return RPC_S_OK; + +failed: + HeapFree(GetProcessHeap(), 0, out->pvBuffer); + out->pvBuffer = NULL; + return ERROR_ACCESS_DENIED; /* FIXME: is this correct? */ +} + +/*********************************************************************** + * RPCRT4_AuthorizeBinding (internal) + */ +static RPC_STATUS RPCRT_AuthorizeConnection(RpcConnection* conn, + BYTE *challenge, ULONG count) +{ + SecBuffer inp, out; + RpcPktHdr *resp_hdr; + RPC_STATUS status; + + TRACE("challenge %s, %d bytes\n", challenge, count); + + inp.BufferType = SECBUFFER_TOKEN; + inp.pvBuffer = challenge; + inp.cbBuffer = count; + + status = RPCRT4_ClientAuthorize(conn, &inp, &out); + if (status) return status; + + resp_hdr = RPCRT4_BuildAuthHeader(NDR_LOCAL_DATA_REPRESENTATION); + if (!resp_hdr) + return E_OUTOFMEMORY; + + status = RPCRT4_SendAuth(conn, resp_hdr, NULL, 0, out.pvBuffer, out.cbBuffer); + + HeapFree(GetProcessHeap(), 0, out.pvBuffer); + RPCRT4_FreeHeader(resp_hdr); + + return status; +} + +/*********************************************************************** + * RPCRT4_Send (internal) + * + * Transmit a packet over connection in acceptable fragments. + */ +RPC_STATUS RPCRT4_Send(RpcConnection *Connection, RpcPktHdr *Header, + void *Buffer, unsigned int BufferLength) +{ + RPC_STATUS r; + SecBuffer out; + + if (!Connection->AuthInfo || SecIsValidHandle(&Connection->ctx)) + { + return RPCRT4_SendAuth(Connection, Header, Buffer, BufferLength, NULL, 0); + } + + /* tack on a negotiate packet */ + RPCRT4_ClientAuthorize(Connection, NULL, &out); + r = RPCRT4_SendAuth(Connection, Header, Buffer, BufferLength, out.pvBuffer, out.cbBuffer); + HeapFree(GetProcessHeap(), 0, out.pvBuffer); + + return r; +} + +/*********************************************************************** + * RPCRT4_Receive (internal) + * + * Receive a packet from connection and merge the fragments. + */ +RPC_STATUS RPCRT4_Receive(RpcConnection *Connection, RpcPktHdr **Header, + PRPC_MESSAGE pMsg) +{ + RPC_STATUS status; + DWORD hdr_length; + LONG dwRead; + unsigned short first_flag; + unsigned long data_length; + unsigned long buffer_length; + unsigned long auth_length; + unsigned char *auth_data = NULL; + RpcPktCommonHdr common_hdr; + + *Header = NULL; + + TRACE("(%p, %p, %p)\n", Connection, Header, pMsg); + + RPCRT4_SetThreadCurrentConnection(Connection); + + /* read packet common header */ + dwRead = rpcrt4_conn_read(Connection, &common_hdr, sizeof(common_hdr)); + if (dwRead != sizeof(common_hdr)) { + WARN("Short read of header, %d bytes\n", dwRead); + status = RPC_S_CALL_FAILED; + goto fail; + } + + /* verify if the header really makes sense */ + if (common_hdr.rpc_ver != RPC_VER_MAJOR || + common_hdr.rpc_ver_minor != RPC_VER_MINOR) { + WARN("unhandled packet version\n"); + status = RPC_S_PROTOCOL_ERROR; + 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); + memcpy(*Header, &common_hdr, sizeof(common_hdr)); + + /* read the rest of packet header */ + dwRead = rpcrt4_conn_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_CALL_FAILED; + goto fail; + } + + /* read packet body */ + switch (common_hdr.ptype) { + case PKT_RESPONSE: + pMsg->BufferLength = (*Header)->response.alloc_hint; + break; + case PKT_REQUEST: + pMsg->BufferLength = (*Header)->request.alloc_hint; + break; + default: + pMsg->BufferLength = common_hdr.frag_len - hdr_length - RPC_AUTH_VERIFIER_LEN(&common_hdr); + } + + TRACE("buffer length = %u\n", pMsg->BufferLength); + + status = I_RpcGetBuffer(pMsg); + if (status != RPC_S_OK) goto fail; + + first_flag = RPC_FLG_FIRST; + auth_length = common_hdr.auth_len; + if (auth_length) { + auth_data = HeapAlloc(GetProcessHeap(), 0, RPC_AUTH_VERIFIER_LEN(&common_hdr)); + if (!auth_data) { + status = RPC_S_OUT_OF_RESOURCES; + goto fail; + } + } + buffer_length = 0; + while (TRUE) + { + unsigned int header_auth_len = RPC_AUTH_VERIFIER_LEN(&(*Header)->common); + + /* verify header fields */ + + if (((*Header)->common.frag_len < hdr_length) || + ((*Header)->common.frag_len - hdr_length < header_auth_len)) { + WARN("frag_len %d too small for hdr_length %d and auth_len %d\n", + (*Header)->common.frag_len, hdr_length, header_auth_len); + status = RPC_S_PROTOCOL_ERROR; + goto fail; + } + + if ((*Header)->common.auth_len != auth_length) { + WARN("auth_len header field changed from %ld to %d\n", + auth_length, (*Header)->common.auth_len); + status = RPC_S_PROTOCOL_ERROR; + goto fail; + } + + if (((*Header)->common.flags & RPC_FLG_FIRST) != first_flag) { + TRACE("invalid packet flags\n"); + status = RPC_S_PROTOCOL_ERROR; + goto fail; + } + + data_length = (*Header)->common.frag_len - hdr_length - header_auth_len; + if (data_length + buffer_length > pMsg->BufferLength) { + TRACE("allocation hint exceeded, new buffer length = %ld\n", + data_length + buffer_length); + pMsg->BufferLength = data_length + buffer_length; + status = I_RpcReAllocateBuffer(pMsg); + if (status != RPC_S_OK) goto fail; + } + + if (data_length == 0) dwRead = 0; else + dwRead = rpcrt4_conn_read(Connection, + (unsigned char *)pMsg->Buffer + buffer_length, data_length); + if (dwRead != data_length) { + WARN("bad data length, %d/%ld\n", dwRead, data_length); + status = RPC_S_CALL_FAILED; + goto fail; + } + + if (header_auth_len) { + if (header_auth_len < sizeof(RpcAuthVerifier)) { + WARN("bad auth verifier length %d\n", header_auth_len); + status = RPC_S_PROTOCOL_ERROR; + goto fail; + } + + /* FIXME: we should accumulate authentication data for the bind, + * bind_ack, alter_context and alter_context_response if necessary. + * however, the details of how this is done is very sketchy in the + * DCE/RPC spec. for all other packet types that have authentication + * verifier data then it is just duplicated in all the fragments */ + dwRead = rpcrt4_conn_read(Connection, auth_data, header_auth_len); + if (dwRead != header_auth_len) { + WARN("bad authentication data length, %d/%d\n", dwRead, + header_auth_len); + status = RPC_S_CALL_FAILED; + goto fail; + } + + /* these packets are handled specially, not by the generic SecurePacket + * function */ + if ((common_hdr.ptype != PKT_BIND) && + (common_hdr.ptype != PKT_BIND_ACK) && + (common_hdr.ptype != PKT_AUTH3)) + { + status = RPCRT4_SecurePacket(Connection, SECURE_PACKET_RECEIVE, + *Header, hdr_length, + (unsigned char *)pMsg->Buffer + buffer_length, data_length, + (RpcAuthVerifier *)auth_data, + (unsigned char *)auth_data + sizeof(RpcAuthVerifier), + header_auth_len - sizeof(RpcAuthVerifier)); + if (status != RPC_S_OK) goto fail; + } + } + + buffer_length += data_length; + if (!((*Header)->common.flags & RPC_FLG_LAST)) { + TRACE("next header\n"); + + /* read the header of next packet */ + dwRead = rpcrt4_conn_read(Connection, *Header, hdr_length); + if (dwRead != hdr_length) { + WARN("invalid packet header size (%d)\n", dwRead); + status = RPC_S_CALL_FAILED; + goto fail; + } + + first_flag = 0; + } else { + break; + } + } + pMsg->BufferLength = buffer_length; + + /* respond to authorization request */ + if (common_hdr.ptype == PKT_BIND_ACK && auth_length > sizeof(RpcAuthVerifier)) + { + status = RPCRT_AuthorizeConnection(Connection, + auth_data + sizeof(RpcAuthVerifier), + auth_length); + if (status) + goto fail; + } + + /* success */ + status = RPC_S_OK; + +fail: + RPCRT4_SetThreadCurrentConnection(NULL); + if (status != RPC_S_OK) { + RPCRT4_FreeHeader(*Header); + *Header = NULL; + } + HeapFree(GetProcessHeap(), 0, auth_data); + return status; +} + +/*********************************************************************** + * I_RpcGetBuffer [RPCRT4.@] + * + * Allocates a buffer for use by I_RpcSend or I_RpcSendReceive and binds to the + * server interface. + * + * PARAMS + * pMsg [I/O] RPC message information. + * + * RETURNS + * Success: RPC_S_OK. + * Failure: RPC_S_INVALID_BINDING if pMsg->Handle is invalid. + * RPC_S_SERVER_UNAVAILABLE if unable to connect to server. + * ERROR_OUTOFMEMORY if buffer allocation failed. + * + * NOTES + * The pMsg->BufferLength field determines the size of the buffer to allocate, + * in bytes. + * + * Use I_RpcFreeBuffer() to unbind from the server and free the message buffer. + * + * SEE ALSO + * I_RpcFreeBuffer(), I_RpcSend(), I_RpcReceive(), I_RpcSendReceive(). + */ +RPC_STATUS WINAPI I_RpcGetBuffer(PRPC_MESSAGE pMsg) +{ + TRACE("(%p): BufferLength=%d\n", pMsg, pMsg->BufferLength); + /* FIXME: pfnAllocate? */ + pMsg->Buffer = HeapAlloc(GetProcessHeap(), 0, pMsg->BufferLength); + + TRACE("Buffer=%p\n", pMsg->Buffer); + /* FIXME: which errors to return? */ + return pMsg->Buffer ? S_OK : E_OUTOFMEMORY; +} + +/*********************************************************************** + * I_RpcReAllocateBuffer (internal) + */ +static RPC_STATUS I_RpcReAllocateBuffer(PRPC_MESSAGE pMsg) +{ + TRACE("(%p): BufferLength=%d\n", pMsg, pMsg->BufferLength); + pMsg->Buffer = HeapReAlloc(GetProcessHeap(), 0, pMsg->Buffer, pMsg->BufferLength); + + TRACE("Buffer=%p\n", pMsg->Buffer); + return pMsg->Buffer ? RPC_S_OK : RPC_S_OUT_OF_RESOURCES; +} + +/*********************************************************************** + * I_RpcFreeBuffer [RPCRT4.@] + * + * Frees a buffer allocated by I_RpcGetBuffer or I_RpcReceive and unbinds from + * the server interface. + * + * PARAMS + * pMsg [I/O] RPC message information. + * + * RETURNS + * RPC_S_OK. + * + * SEE ALSO + * I_RpcGetBuffer(), I_RpcReceive(). + */ +RPC_STATUS WINAPI I_RpcFreeBuffer(PRPC_MESSAGE pMsg) +{ + TRACE("(%p) Buffer=%p\n", pMsg, pMsg->Buffer); + /* FIXME: pfnFree? */ + HeapFree(GetProcessHeap(), 0, pMsg->Buffer); + pMsg->Buffer = NULL; + return S_OK; +} + +/*********************************************************************** + * I_RpcSend [RPCRT4.@] + * + * Sends a message to the server. + * + * PARAMS + * pMsg [I/O] RPC message information. + * + * RETURNS + * Unknown. + * + * NOTES + * The buffer must have been allocated with I_RpcGetBuffer(). + * + * SEE ALSO + * I_RpcGetBuffer(), I_RpcReceive(), I_RpcSendReceive(). + */ +RPC_STATUS WINAPI I_RpcSend(PRPC_MESSAGE pMsg) +{ + RpcBinding* bind = (RpcBinding*)pMsg->Handle; + RpcConnection* conn; + RPC_CLIENT_INTERFACE* cif = NULL; + RPC_STATUS status; + RpcPktHdr *hdr; + + TRACE("(%p)\n", pMsg); + if (!bind || bind->server) return RPC_S_INVALID_BINDING; + + cif = pMsg->RpcInterfaceInformation; + if (!cif) return RPC_S_INTERFACE_NOT_FOUND; /* ? */ + + if (!bind->Endpoint || !bind->Endpoint[0]) + { + TRACE("automatically resolving partially bound binding\n"); + status = RpcEpResolveBinding(bind, cif); + if (status != RPC_S_OK) return status; + } + + status = RPCRT4_OpenBinding(bind, &conn, &cif->TransferSyntax, + &cif->InterfaceId); + if (status != RPC_S_OK) return status; + + hdr = RPCRT4_BuildRequestHeader(pMsg->DataRepresentation, + pMsg->BufferLength, pMsg->ProcNum, + &bind->ObjectUuid); + if (!hdr) + { + RPCRT4_CloseBinding(bind, conn); + return ERROR_OUTOFMEMORY; + } + hdr->common.call_id = conn->NextCallId++; + + status = RPCRT4_Send(conn, hdr, pMsg->Buffer, pMsg->BufferLength); + + RPCRT4_FreeHeader(hdr); + + /* save the connection, so the response can be read from it */ + pMsg->ReservedForRuntime = conn; + return status; +} + +/* is this status something that the server can't recover from? */ +static inline BOOL is_hard_error(RPC_STATUS status) +{ + switch (status) + { + case 0: /* user-defined fault */ + case ERROR_ACCESS_DENIED: + case ERROR_INVALID_PARAMETER: + case RPC_S_PROTOCOL_ERROR: + case RPC_S_CALL_FAILED: + case RPC_S_CALL_FAILED_DNE: + case RPC_S_SEC_PKG_ERROR: + return TRUE; + default: + return FALSE; + } +} + +/*********************************************************************** + * I_RpcReceive [RPCRT4.@] + */ +RPC_STATUS WINAPI I_RpcReceive(PRPC_MESSAGE pMsg) +{ + RpcBinding* bind = (RpcBinding*)pMsg->Handle; + RpcConnection* conn; + RPC_CLIENT_INTERFACE* cif = NULL; + RPC_SERVER_INTERFACE* sif = NULL; + RPC_STATUS status; + RpcPktHdr *hdr = NULL; + + TRACE("(%p)\n", pMsg); + if (!bind) return RPC_S_INVALID_BINDING; + + if (pMsg->ReservedForRuntime) { + conn = pMsg->ReservedForRuntime; + pMsg->ReservedForRuntime = NULL; + } else { + if (bind->server) { + sif = pMsg->RpcInterfaceInformation; + if (!sif) return RPC_S_INTERFACE_NOT_FOUND; /* ? */ + status = RPCRT4_OpenBinding(bind, &conn, &sif->TransferSyntax, + &sif->InterfaceId); + } else { + cif = pMsg->RpcInterfaceInformation; + if (!cif) return RPC_S_INTERFACE_NOT_FOUND; /* ? */ + + if (!bind->Endpoint || !bind->Endpoint[0]) + { + TRACE("automatically resolving partially bound binding\n"); + status = RpcEpResolveBinding(bind, cif); + if (status != RPC_S_OK) return status; + } + + status = RPCRT4_OpenBinding(bind, &conn, &cif->TransferSyntax, + &cif->InterfaceId); + } + if (status != RPC_S_OK) return status; + } + + status = RPCRT4_Receive(conn, &hdr, pMsg); + if (status != RPC_S_OK) { + WARN("receive failed with error %lx\n", status); + goto fail; + } + + switch (hdr->common.ptype) { + case PKT_RESPONSE: + if (bind->server) { + status = RPC_S_PROTOCOL_ERROR; + goto fail; + } + break; + case PKT_REQUEST: + if (!bind->server) { + status = RPC_S_PROTOCOL_ERROR; + goto fail; + } + break; + case PKT_FAULT: + ERR ("we got fault packet with status 0x%lx\n", hdr->fault.status); + status = NCA2RPC_STATUS(hdr->fault.status); + if (is_hard_error(status)) + goto fail; + break; + default: + WARN("bad packet type %d\n", hdr->common.ptype); + status = RPC_S_PROTOCOL_ERROR; + goto fail; + } + + /* success */ + RPCRT4_CloseBinding(bind, conn); + RPCRT4_FreeHeader(hdr); + return status; + +fail: + RPCRT4_FreeHeader(hdr); + RPCRT4_DestroyConnection(conn); + return status; +} + +/*********************************************************************** + * I_RpcSendReceive [RPCRT4.@] + * + * Sends a message to the server and receives the response. + * + * PARAMS + * pMsg [I/O] RPC message information. + * + * RETURNS + * Success: RPC_S_OK. + * Failure: Any error code. + * + * NOTES + * The buffer must have been allocated with I_RpcGetBuffer(). + * + * SEE ALSO + * I_RpcGetBuffer(), I_RpcSend(), I_RpcReceive(). + */ +RPC_STATUS WINAPI I_RpcSendReceive(PRPC_MESSAGE pMsg) +{ + RPC_STATUS status; + RPC_MESSAGE original_message; + + TRACE("(%p)\n", pMsg); + + original_message = *pMsg; + status = I_RpcSend(pMsg); + if (status == RPC_S_OK) + status = I_RpcReceive(pMsg); + /* free the buffer replaced by a new buffer in I_RpcReceive */ + if (status == RPC_S_OK) + I_RpcFreeBuffer(&original_message); + return status; +} diff --git a/reactos/dll/win32/rpcrt4_new/rpc_message.h b/reactos/dll/win32/rpcrt4_new/rpc_message.h index eab30608b7e..cbf83d30ce0 100644 --- a/reactos/dll/win32/rpcrt4_new/rpc_message.h +++ b/reactos/dll/win32/rpcrt4_new/rpc_message.h @@ -1,40 +1,40 @@ -/* - * RPC message API - * - * Copyright 2004 Filip Navara - * - * 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 - */ - -#ifndef __WINE_RPC_MESSAGE_H -#define __WINE_RPC_MESSAGE_H - -#include "wine/rpcss_shared.h" -#include "rpc_defs.h" - -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); -NCA_STATUS RPC2NCA_STATUS(RPC_STATUS status); -RPC_STATUS NCA2RPC_STATUS(NCA_STATUS status); - -#endif +/* + * RPC message API + * + * Copyright 2004 Filip Navara + * + * 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 + */ + +#ifndef __WINE_RPC_MESSAGE_H +#define __WINE_RPC_MESSAGE_H + +#include "wine/rpcss_shared.h" +#include "rpc_defs.h" + +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); +NCA_STATUS RPC2NCA_STATUS(RPC_STATUS status); +RPC_STATUS NCA2RPC_STATUS(NCA_STATUS status); + +#endif diff --git a/reactos/dll/win32/rpcrt4_new/rpc_misc.h b/reactos/dll/win32/rpcrt4_new/rpc_misc.h deleted file mode 100644 index 6bccfd69618..00000000000 --- a/reactos/dll/win32/rpcrt4_new/rpc_misc.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * RPC definitions - * - * Copyright 2003 Ove Kåven, TransGaming Technologies - * - * 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 - * - */ - -#ifndef __WINE_RPC_MISC_H -#define __WINE_RPC_MISC_H - -/* flags for RPC_MESSAGE.RpcFlags */ -#define WINE_RPCFLAG_EXCEPTION 0x0001 - -#endif /* __WINE_RPC_MISC_H */ diff --git a/reactos/dll/win32/rpcrt4_new/rpc_server.c b/reactos/dll/win32/rpcrt4_new/rpc_server.c index 880d8e5a14b..34c71c78c5c 100644 --- a/reactos/dll/win32/rpcrt4_new/rpc_server.c +++ b/reactos/dll/win32/rpcrt4_new/rpc_server.c @@ -1,1139 +1,1139 @@ -/* - * RPC server API - * - * Copyright 2001 Ove Kåven, TransGaming Technologies - * Copyright 2004 Filip Navara - * - * 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 - * - * TODO: - * - a whole lot - */ - -#include "config.h" -#include "wine/port.h" - -#include -#include -#include -#include - -#include "windef.h" -#include "winbase.h" -#include "winerror.h" - -#include "rpc.h" -#include "rpcndr.h" -#include "excpt.h" - -#include "wine/debug.h" -#include "wine/exception.h" - -#include "rpc_server.h" -#include "rpc_assoc.h" -#include "rpc_message.h" -#include "rpc_defs.h" -#include "ncastatus.h" - -WINE_DEFAULT_DEBUG_CHANNEL(rpc); - -typedef struct _RpcPacket -{ - struct _RpcConnection* conn; - RpcPktHdr* hdr; - RPC_MESSAGE* msg; -} RpcPacket; - -typedef struct _RpcObjTypeMap -{ - /* FIXME: a hash table would be better. */ - struct _RpcObjTypeMap *next; - UUID Object; - UUID Type; -} RpcObjTypeMap; - -static RpcObjTypeMap *RpcObjTypeMaps; - -/* list of type RpcServerProtseq */ -static struct list protseqs = LIST_INIT(protseqs); -static struct list server_interfaces = LIST_INIT(server_interfaces); - -static CRITICAL_SECTION server_cs; -static CRITICAL_SECTION_DEBUG server_cs_debug = -{ - 0, 0, &server_cs, - { &server_cs_debug.ProcessLocksList, &server_cs_debug.ProcessLocksList }, - 0, 0, { (DWORD_PTR)(__FILE__ ": server_cs") } -}; -static CRITICAL_SECTION server_cs = { &server_cs_debug, -1, 0, 0, 0, 0 }; - -static CRITICAL_SECTION listen_cs; -static CRITICAL_SECTION_DEBUG listen_cs_debug = -{ - 0, 0, &listen_cs, - { &listen_cs_debug.ProcessLocksList, &listen_cs_debug.ProcessLocksList }, - 0, 0, { (DWORD_PTR)(__FILE__ ": listen_cs") } -}; -static CRITICAL_SECTION listen_cs = { &listen_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; - -static UUID uuid_nil; - -static inline RpcObjTypeMap *LookupObjTypeMap(UUID *ObjUuid) -{ - RpcObjTypeMap *rslt = RpcObjTypeMaps; - RPC_STATUS dummy; - - while (rslt) { - if (! UuidCompare(ObjUuid, &rslt->Object, &dummy)) break; - rslt = rslt->next; - } - - return rslt; -} - -static inline UUID *LookupObjType(UUID *ObjUuid) -{ - RpcObjTypeMap *map = LookupObjTypeMap(ObjUuid); - if (map) - return &map->Type; - else - return &uuid_nil; -} - -static RpcServerInterface* RPCRT4_find_interface(UUID* object, - const RPC_SYNTAX_IDENTIFIER* if_id, - BOOL check_object) -{ - UUID* MgrType = NULL; - RpcServerInterface* cif; - RPC_STATUS status; - - if (check_object) - MgrType = LookupObjType(object); - EnterCriticalSection(&server_cs); - LIST_FOR_EACH_ENTRY(cif, &server_interfaces, RpcServerInterface, entry) { - if (!memcmp(if_id, &cif->If->InterfaceId, sizeof(RPC_SYNTAX_IDENTIFIER)) && - (check_object == FALSE || UuidEqual(MgrType, &cif->MgrTypeUuid, &status)) && - std_listen) { - InterlockedIncrement(&cif->CurrentCalls); - break; - } - } - LeaveCriticalSection(&server_cs); - if (&cif->entry == &server_interfaces) cif = NULL; - TRACE("returning %p for %s\n", cif, debugstr_guid(object)); - return cif; -} - -static void RPCRT4_release_server_interface(RpcServerInterface *sif) -{ - if (!InterlockedDecrement(&sif->CurrentCalls) && - sif->CallsCompletedEvent) { - /* sif must have been removed from server_interfaces before - * CallsCompletedEvent is set */ - SetEvent(sif->CallsCompletedEvent); - HeapFree(GetProcessHeap(), 0, sif); - } -} - -static WINE_EXCEPTION_FILTER(rpc_filter) -{ - WARN("exception caught with code 0x%08x = %d\n", GetExceptionCode(), GetExceptionCode()); - TRACE("returning failure packet\n"); - /* catch every exception */ - return EXCEPTION_EXECUTE_HANDLER; -} - -static void RPCRT4_process_packet(RpcConnection* conn, RpcPktHdr* hdr, RPC_MESSAGE* msg) -{ - RpcServerInterface* sif; - RPC_DISPATCH_FUNCTION func; - UUID *object_uuid; - RpcPktHdr *response = NULL; - void *buf = msg->Buffer; - RPC_STATUS status; - BOOL exception; - NDR_SCONTEXT context_handle; - - msg->Handle = (RPC_BINDING_HANDLE)conn->server_binding; - - switch (hdr->common.ptype) { - case PKT_BIND: - TRACE("got bind packet\n"); - - /* FIXME: do more checks! */ - if (hdr->bind.max_tsize < RPC_MIN_PACKET_SIZE || - !UuidIsNil(&conn->ActiveInterface.SyntaxGUID, &status) || - 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->bind.assoc_gid, - &conn->server_binding->Assoc) == RPC_S_OK) - sif = RPCRT4_find_interface(NULL, &hdr->bind.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->bind.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->bind.abstract; - conn->MaxTransmissionSize = hdr->bind.max_tsize; - - RPCRT4_release_server_interface(sif); - } - - status = RPCRT4_Send(conn, response, NULL, 0); - RPCRT4_FreeHeader(response); - if (status != RPC_S_OK) - goto fail; - - break; - - case PKT_REQUEST: - TRACE("got request packet\n"); - - /* fail if the connection isn't bound with an interface */ - if (UuidIsNil(&conn->ActiveInterface.SyntaxGUID, &status)) { - /* FIXME: should send BindNack instead */ - response = RPCRT4_BuildFaultHeader(NDR_LOCAL_DATA_REPRESENTATION, - status); - - RPCRT4_Send(conn, response, NULL, 0); - RPCRT4_FreeHeader(response); - break; - } - - if (hdr->common.flags & RPC_FLG_OBJECT_UUID) { - object_uuid = (UUID*)(&hdr->request + 1); - } else { - object_uuid = NULL; - } - - sif = RPCRT4_find_interface(object_uuid, &conn->ActiveInterface, 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, - NCA_S_UNK_IF); - - RPCRT4_Send(conn, response, NULL, 0); - RPCRT4_FreeHeader(response); - break; - } - msg->RpcInterfaceInformation = sif->If; - /* copy the endpoint vector from sif to msg so that midl-generated code will use it */ - msg->ManagerEpv = sif->MgrEpv; - if (object_uuid != NULL) { - RPCRT4_SetBindingObject(msg->Handle, object_uuid); - } - - /* find dispatch function */ - msg->ProcNum = hdr->request.opnum; - if (sif->Flags & RPC_IF_OLE) { - /* native ole32 always gives us a dispatch table with a single entry - * (I assume that's a wrapper for IRpcStubBuffer::Invoke) */ - func = *sif->If->DispatchTable->DispatchTable; - } else { - if (msg->ProcNum >= sif->If->DispatchTable->DispatchTableCount) { - WARN("invalid procnum (%d/%d)\n", msg->ProcNum, sif->If->DispatchTable->DispatchTableCount); - response = RPCRT4_BuildFaultHeader(NDR_LOCAL_DATA_REPRESENTATION, - NCA_S_OP_RNG_ERROR); - - RPCRT4_Send(conn, response, NULL, 0); - RPCRT4_FreeHeader(response); - } - func = sif->If->DispatchTable->DispatchTable[msg->ProcNum]; - } - - /* put in the drep. FIXME: is this more universally applicable? - perhaps we should move this outward... */ - msg->DataRepresentation = - MAKELONG( MAKEWORD(hdr->common.drep[0], hdr->common.drep[1]), - MAKEWORD(hdr->common.drep[2], hdr->common.drep[3])); - - exception = FALSE; - - /* dispatch */ - RPCRT4_SetThreadCurrentCallHandle(msg->Handle); - __TRY { - if (func) func(msg); - } __EXCEPT(rpc_filter) { - exception = TRUE; - if (GetExceptionCode() == STATUS_ACCESS_VIOLATION) - status = ERROR_NOACCESS; - else - status = GetExceptionCode(); - response = RPCRT4_BuildFaultHeader(msg->DataRepresentation, - RPC2NCA_STATUS(status)); - } __ENDTRY - RPCRT4_SetThreadCurrentCallHandle(NULL); - - /* release any unmarshalled context handles */ - while ((context_handle = RPCRT4_PopThreadContextHandle()) != NULL) - RpcServerAssoc_ReleaseContextHandle(conn->server_binding->Assoc, context_handle, TRUE); - - if (!exception) - response = RPCRT4_BuildResponseHeader(msg->DataRepresentation, - msg->BufferLength); - - /* send response packet */ - if (response) { - status = RPCRT4_Send(conn, response, exception ? NULL : msg->Buffer, - exception ? 0 : msg->BufferLength); - RPCRT4_FreeHeader(response); - } else - ERR("out of memory\n"); - - msg->RpcInterfaceInformation = NULL; - RPCRT4_release_server_interface(sif); - - break; - - default: - FIXME("unhandled packet type %u\n", hdr->common.ptype); - break; - } - -fail: - /* clean up */ - if (msg->Buffer == buf) msg->Buffer = NULL; - TRACE("freeing Buffer=%p\n", buf); - HeapFree(GetProcessHeap(), 0, buf); - msg->Handle = 0; - I_RpcFreeBuffer(msg); - msg->Buffer = NULL; - RPCRT4_FreeHeader(hdr); - HeapFree(GetProcessHeap(), 0, msg); -} - -static DWORD CALLBACK RPCRT4_worker_thread(LPVOID the_arg) -{ - RpcPacket *pkt = the_arg; - RPCRT4_process_packet(pkt->conn, pkt->hdr, pkt->msg); - HeapFree(GetProcessHeap(), 0, pkt); - return 0; -} - -static DWORD CALLBACK RPCRT4_io_thread(LPVOID the_arg) -{ - RpcConnection* conn = (RpcConnection*)the_arg; - RpcPktHdr *hdr; - RPC_MESSAGE *msg; - RPC_STATUS status; - RpcPacket *packet; - - TRACE("(%p)\n", conn); - - for (;;) { - msg = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RPC_MESSAGE)); - - status = RPCRT4_Receive(conn, &hdr, msg); - if (status != RPC_S_OK) { - WARN("receive failed with error %lx\n", status); - HeapFree(GetProcessHeap(), 0, msg); - break; - } - -#if 0 - RPCRT4_process_packet(conn, hdr, msg); -#else - packet = HeapAlloc(GetProcessHeap(), 0, sizeof(RpcPacket)); - packet->conn = conn; - packet->hdr = hdr; - packet->msg = msg; - QueueUserWorkItem(RPCRT4_worker_thread, packet, WT_EXECUTELONGFUNCTION); -#endif - msg = NULL; - } - RPCRT4_DestroyConnection(conn); - return 0; -} - -void RPCRT4_new_client(RpcConnection* conn) -{ - HANDLE thread = CreateThread(NULL, 0, RPCRT4_io_thread, conn, 0, NULL); - if (!thread) { - DWORD err = GetLastError(); - ERR("failed to create thread, error=%08x\n", err); - RPCRT4_DestroyConnection(conn); - } - /* we could set conn->thread, but then we'd have to make the io_thread wait - * for that, otherwise the thread might finish, destroy the connection, and - * free the memory we'd write to before we did, causing crashes and stuff - - * so let's implement that later, when we really need conn->thread */ - - CloseHandle( thread ); -} - -static DWORD CALLBACK RPCRT4_server_thread(LPVOID the_arg) -{ - int res; - unsigned int count; - void *objs = NULL; - RpcServerProtseq* cps = the_arg; - RpcConnection* conn; - BOOL set_ready_event = FALSE; - - TRACE("(the_arg == ^%p)\n", the_arg); - - for (;;) { - objs = cps->ops->get_wait_array(cps, objs, &count); - - if (set_ready_event) - { - /* signal to function that changed state that we are now sync'ed */ - SetEvent(cps->server_ready_event); - set_ready_event = FALSE; - } - - /* start waiting */ - res = cps->ops->wait_for_new_connection(cps, count, objs); - if (res == -1) - break; - else if (res == 0) - { - if (!std_listen) - { - SetEvent(cps->server_ready_event); - break; - } - set_ready_event = TRUE; - } - } - cps->ops->free_wait_array(cps, objs); - EnterCriticalSection(&cps->cs); - /* close connections */ - conn = cps->conn; - while (conn) { - RPCRT4_CloseConnection(conn); - conn = conn->Next; - } - LeaveCriticalSection(&cps->cs); - return 0; -} - -/* tells the server thread that the state has changed and waits for it to - * make the changes */ -static void RPCRT4_sync_with_server_thread(RpcServerProtseq *ps) -{ - /* make sure we are the only thread sync'ing the server state, otherwise - * there is a race with the server thread setting an older state and setting - * the server_ready_event when the new state hasn't yet been applied */ - WaitForSingleObject(ps->mgr_mutex, INFINITE); - - ps->ops->signal_state_changed(ps); - - /* wait for server thread to make the requested changes before returning */ - WaitForSingleObject(ps->server_ready_event, INFINITE); - - ReleaseMutex(ps->mgr_mutex); -} - -static RPC_STATUS RPCRT4_start_listen_protseq(RpcServerProtseq *ps, BOOL auto_listen) -{ - RPC_STATUS status = RPC_S_OK; - HANDLE server_thread; - - EnterCriticalSection(&listen_cs); - if (ps->is_listening) goto done; - - if (!ps->mgr_mutex) ps->mgr_mutex = CreateMutexW(NULL, FALSE, NULL); - if (!ps->server_ready_event) ps->server_ready_event = CreateEventW(NULL, FALSE, FALSE, NULL); - server_thread = CreateThread(NULL, 0, RPCRT4_server_thread, ps, 0, NULL); - if (!server_thread) - { - status = RPC_S_OUT_OF_RESOURCES; - goto done; - } - ps->is_listening = TRUE; - CloseHandle(server_thread); - -done: - LeaveCriticalSection(&listen_cs); - return status; -} - -static RPC_STATUS RPCRT4_start_listen(BOOL auto_listen) -{ - RPC_STATUS status = RPC_S_ALREADY_LISTENING; - RpcServerProtseq *cps; - - TRACE("\n"); - - EnterCriticalSection(&listen_cs); - if (auto_listen || (manual_listen_count++ == 0)) - { - status = RPC_S_OK; - if (++listen_count == 1) - std_listen = TRUE; - } - LeaveCriticalSection(&listen_cs); - - if (std_listen) - { - EnterCriticalSection(&server_cs); - LIST_FOR_EACH_ENTRY(cps, &protseqs, RpcServerProtseq, entry) - { - status = RPCRT4_start_listen_protseq(cps, TRUE); - if (status != RPC_S_OK) - break; - - /* make sure server is actually listening on the interface before - * returning */ - RPCRT4_sync_with_server_thread(cps); - } - LeaveCriticalSection(&server_cs); - } - - return status; -} - -static void RPCRT4_stop_listen(BOOL auto_listen) -{ - EnterCriticalSection(&listen_cs); - if (auto_listen || (--manual_listen_count == 0)) - { - if (listen_count != 0 && --listen_count == 0) { - RpcServerProtseq *cps; - - std_listen = FALSE; - LeaveCriticalSection(&listen_cs); - - LIST_FOR_EACH_ENTRY(cps, &protseqs, RpcServerProtseq, entry) - RPCRT4_sync_with_server_thread(cps); - - return; - } - assert(listen_count >= 0); - } - LeaveCriticalSection(&listen_cs); -} - -static RPC_STATUS RPCRT4_use_protseq(RpcServerProtseq* ps, LPSTR endpoint) -{ - RPC_STATUS status; - - status = ps->ops->open_endpoint(ps, endpoint); - if (status != RPC_S_OK) - return status; - - if (std_listen) - { - status = RPCRT4_start_listen_protseq(ps, FALSE); - if (status == RPC_S_OK) - RPCRT4_sync_with_server_thread(ps); - } - - return status; -} - -/*********************************************************************** - * RpcServerInqBindings (RPCRT4.@) - */ -RPC_STATUS WINAPI RpcServerInqBindings( RPC_BINDING_VECTOR** BindingVector ) -{ - RPC_STATUS status; - DWORD count; - RpcServerProtseq* ps; - RpcConnection* conn; - - if (BindingVector) - TRACE("(*BindingVector == ^%p)\n", *BindingVector); - else - ERR("(BindingVector == NULL!!?)\n"); - - EnterCriticalSection(&server_cs); - /* count connections */ - count = 0; - LIST_FOR_EACH_ENTRY(ps, &protseqs, RpcServerProtseq, entry) { - EnterCriticalSection(&ps->cs); - conn = ps->conn; - while (conn) { - count++; - conn = conn->Next; - } - LeaveCriticalSection(&ps->cs); - } - if (count) { - /* export bindings */ - *BindingVector = HeapAlloc(GetProcessHeap(), 0, - sizeof(RPC_BINDING_VECTOR) + - sizeof(RPC_BINDING_HANDLE)*(count-1)); - (*BindingVector)->Count = count; - count = 0; - LIST_FOR_EACH_ENTRY(ps, &protseqs, RpcServerProtseq, entry) { - EnterCriticalSection(&ps->cs); - conn = ps->conn; - while (conn) { - RPCRT4_MakeBinding((RpcBinding**)&(*BindingVector)->BindingH[count], - conn); - count++; - conn = conn->Next; - } - LeaveCriticalSection(&ps->cs); - } - status = RPC_S_OK; - } else { - *BindingVector = NULL; - status = RPC_S_NO_BINDINGS; - } - LeaveCriticalSection(&server_cs); - return status; -} - -/*********************************************************************** - * RpcServerUseProtseqEpA (RPCRT4.@) - */ -RPC_STATUS WINAPI RpcServerUseProtseqEpA( RPC_CSTR Protseq, UINT MaxCalls, RPC_CSTR Endpoint, LPVOID SecurityDescriptor ) -{ - RPC_POLICY policy; - - TRACE( "(%s,%u,%s,%p)\n", Protseq, MaxCalls, Endpoint, SecurityDescriptor ); - - /* This should provide the default behaviour */ - policy.Length = sizeof( policy ); - policy.EndpointFlags = 0; - policy.NICFlags = 0; - - return RpcServerUseProtseqEpExA( Protseq, MaxCalls, Endpoint, SecurityDescriptor, &policy ); -} - -/*********************************************************************** - * RpcServerUseProtseqEpW (RPCRT4.@) - */ -RPC_STATUS WINAPI RpcServerUseProtseqEpW( RPC_WSTR Protseq, UINT MaxCalls, RPC_WSTR Endpoint, LPVOID SecurityDescriptor ) -{ - RPC_POLICY policy; - - TRACE( "(%s,%u,%s,%p)\n", debugstr_w( Protseq ), MaxCalls, debugstr_w( Endpoint ), SecurityDescriptor ); - - /* This should provide the default behaviour */ - policy.Length = sizeof( policy ); - policy.EndpointFlags = 0; - policy.NICFlags = 0; - - return RpcServerUseProtseqEpExW( Protseq, MaxCalls, Endpoint, SecurityDescriptor, &policy ); -} - -/*********************************************************************** - * alloc_serverprotoseq (internal) - * - * Must be called with server_cs held. - */ -static RPC_STATUS alloc_serverprotoseq(UINT MaxCalls, char *Protseq, RpcServerProtseq **ps) -{ - const struct protseq_ops *ops = rpcrt4_get_protseq_ops(Protseq); - - if (!ops) - { - FIXME("protseq %s not supported\n", debugstr_a(Protseq)); - return RPC_S_PROTSEQ_NOT_SUPPORTED; - } - - *ps = ops->alloc(); - if (!*ps) - return RPC_S_OUT_OF_RESOURCES; - (*ps)->MaxCalls = MaxCalls; - (*ps)->Protseq = Protseq; - (*ps)->ops = ops; - (*ps)->MaxCalls = 0; - (*ps)->conn = NULL; - InitializeCriticalSection(&(*ps)->cs); - (*ps)->is_listening = FALSE; - (*ps)->mgr_mutex = NULL; - (*ps)->server_ready_event = NULL; - - list_add_head(&protseqs, &(*ps)->entry); - - TRACE("new protseq %p created for %s\n", *ps, Protseq); - - return RPC_S_OK; -} - -/* 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) -{ - RPC_STATUS status; - RpcServerProtseq *cps; - - EnterCriticalSection(&server_cs); - - LIST_FOR_EACH_ENTRY(cps, &protseqs, RpcServerProtseq, entry) - if (!strcmp(cps->Protseq, Protseq)) - { - TRACE("found existing protseq object for %s\n", Protseq); - *ps = cps; - LeaveCriticalSection(&server_cs); - return S_OK; - } - - status = alloc_serverprotoseq(MaxCalls, Protseq, ps); - - LeaveCriticalSection(&server_cs); - - return status; -} - -/*********************************************************************** - * RpcServerUseProtseqEpExA (RPCRT4.@) - */ -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,%lu,%lu})\n", debugstr_a(szps), MaxCalls, - debugstr_a(szep), SecurityDescriptor, - lpPolicy->Length, lpPolicy->EndpointFlags, lpPolicy->NICFlags ); - - status = RPCRT4_get_or_create_serverprotseq(MaxCalls, RPCRT4_strdupA(szps), &ps); - if (status != RPC_S_OK) - return status; - - return RPCRT4_use_protseq(ps, szep); -} - -/*********************************************************************** - * RpcServerUseProtseqEpExW (RPCRT4.@) - */ -RPC_STATUS WINAPI RpcServerUseProtseqEpExW( RPC_WSTR Protseq, UINT MaxCalls, RPC_WSTR Endpoint, LPVOID SecurityDescriptor, - PRPC_POLICY lpPolicy ) -{ - RpcServerProtseq* ps; - RPC_STATUS status; - LPSTR EndpointA; - - TRACE("(%s,%u,%s,%p,{%u,%lu,%lu})\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); - if (status != RPC_S_OK) - return status; - - EndpointA = RPCRT4_strdupWtoA(Endpoint); - status = RPCRT4_use_protseq(ps, EndpointA); - RPCRT4_strfree(EndpointA); - return status; -} - -/*********************************************************************** - * RpcServerUseProtseqA (RPCRT4.@) - */ -RPC_STATUS WINAPI RpcServerUseProtseqA(RPC_CSTR Protseq, unsigned int MaxCalls, void *SecurityDescriptor) -{ - TRACE("(Protseq == %s, MaxCalls == %d, SecurityDescriptor == ^%p)\n", debugstr_a((char*)Protseq), MaxCalls, SecurityDescriptor); - return RpcServerUseProtseqEpA(Protseq, MaxCalls, NULL, SecurityDescriptor); -} - -/*********************************************************************** - * RpcServerUseProtseqW (RPCRT4.@) - */ -RPC_STATUS WINAPI RpcServerUseProtseqW(RPC_WSTR Protseq, unsigned int MaxCalls, void *SecurityDescriptor) -{ - TRACE("Protseq == %s, MaxCalls == %d, SecurityDescriptor == ^%p)\n", debugstr_w(Protseq), MaxCalls, SecurityDescriptor); - return RpcServerUseProtseqEpW(Protseq, MaxCalls, NULL, SecurityDescriptor); -} - -/*********************************************************************** - * RpcServerRegisterIf (RPCRT4.@) - */ -RPC_STATUS WINAPI RpcServerRegisterIf( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, RPC_MGR_EPV* MgrEpv ) -{ - TRACE("(%p,%s,%p)\n", IfSpec, debugstr_guid(MgrTypeUuid), MgrEpv); - return RpcServerRegisterIf2( IfSpec, MgrTypeUuid, MgrEpv, 0, RPC_C_LISTEN_MAX_CALLS_DEFAULT, (UINT)-1, NULL ); -} - -/*********************************************************************** - * RpcServerRegisterIfEx (RPCRT4.@) - */ -RPC_STATUS WINAPI RpcServerRegisterIfEx( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, RPC_MGR_EPV* MgrEpv, - UINT Flags, UINT MaxCalls, RPC_IF_CALLBACK_FN* IfCallbackFn ) -{ - TRACE("(%p,%s,%p,%u,%u,%p)\n", IfSpec, debugstr_guid(MgrTypeUuid), MgrEpv, Flags, MaxCalls, IfCallbackFn); - return RpcServerRegisterIf2( IfSpec, MgrTypeUuid, MgrEpv, Flags, MaxCalls, (UINT)-1, IfCallbackFn ); -} - -/*********************************************************************** - * RpcServerRegisterIf2 (RPCRT4.@) - */ -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; - RpcServerInterface* sif; - unsigned int i; - - TRACE("(%p,%s,%p,%u,%u,%u,%p)\n", IfSpec, debugstr_guid(MgrTypeUuid), MgrEpv, Flags, MaxCalls, - MaxRpcSize, IfCallbackFn); - TRACE(" interface id: %s %d.%d\n", debugstr_guid(&If->InterfaceId.SyntaxGUID), - If->InterfaceId.SyntaxVersion.MajorVersion, - If->InterfaceId.SyntaxVersion.MinorVersion); - TRACE(" transfer syntax: %s %d.%d\n", debugstr_guid(&If->TransferSyntax.SyntaxGUID), - If->TransferSyntax.SyntaxVersion.MajorVersion, - If->TransferSyntax.SyntaxVersion.MinorVersion); - TRACE(" dispatch table: %p\n", If->DispatchTable); - if (If->DispatchTable) { - TRACE(" dispatch table count: %d\n", If->DispatchTable->DispatchTableCount); - for (i=0; iDispatchTable->DispatchTableCount; i++) { - TRACE(" entry %d: %p\n", i, If->DispatchTable->DispatchTable[i]); - } - TRACE(" reserved: %ld\n", If->DispatchTable->Reserved); - } - TRACE(" protseq endpoint count: %d\n", If->RpcProtseqEndpointCount); - TRACE(" default manager epv: %p\n", If->DefaultManagerEpv); - TRACE(" interpreter info: %p\n", If->InterpreterInfo); - - sif = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcServerInterface)); - sif->If = If; - if (MgrTypeUuid) { - memcpy(&sif->MgrTypeUuid, MgrTypeUuid, sizeof(UUID)); - sif->MgrEpv = MgrEpv; - } else { - memset(&sif->MgrTypeUuid, 0, sizeof(UUID)); - sif->MgrEpv = If->DefaultManagerEpv; - } - sif->Flags = Flags; - sif->MaxCalls = MaxCalls; - sif->MaxRpcSize = MaxRpcSize; - sif->IfCallbackFn = IfCallbackFn; - - EnterCriticalSection(&server_cs); - list_add_head(&server_interfaces, &sif->entry); - LeaveCriticalSection(&server_cs); - - if (sif->Flags & RPC_IF_AUTOLISTEN) - RPCRT4_start_listen(TRUE); - - return RPC_S_OK; -} - -/*********************************************************************** - * RpcServerUnregisterIf (RPCRT4.@) - */ -RPC_STATUS WINAPI RpcServerUnregisterIf( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, UINT WaitForCallsToComplete ) -{ - PRPC_SERVER_INTERFACE If = (PRPC_SERVER_INTERFACE)IfSpec; - HANDLE event = NULL; - BOOL found = FALSE; - BOOL completed = TRUE; - RpcServerInterface *cif; - RPC_STATUS status; - - TRACE("(IfSpec == (RPC_IF_HANDLE)^%p (%s), MgrTypeUuid == %s, WaitForCallsToComplete == %u)\n", - IfSpec, debugstr_guid(&If->InterfaceId.SyntaxGUID), debugstr_guid(MgrTypeUuid), WaitForCallsToComplete); - - EnterCriticalSection(&server_cs); - LIST_FOR_EACH_ENTRY(cif, &server_interfaces, RpcServerInterface, entry) { - if ((!IfSpec || !memcmp(&If->InterfaceId, &cif->If->InterfaceId, sizeof(RPC_SYNTAX_IDENTIFIER))) && - UuidEqual(MgrTypeUuid, &cif->MgrTypeUuid, &status)) { - list_remove(&cif->entry); - if (cif->CurrentCalls) { - completed = FALSE; - if (WaitForCallsToComplete) - cif->CallsCompletedEvent = event = CreateEventW(NULL, FALSE, FALSE, NULL); - } - found = TRUE; - break; - } - } - LeaveCriticalSection(&server_cs); - - if (!found) { - ERR("not found for object %s\n", debugstr_guid(MgrTypeUuid)); - return RPC_S_UNKNOWN_IF; - } - - if (completed) - HeapFree(GetProcessHeap(), 0, cif); - else if (event) { - /* sif will be freed when the last call is completed, so be careful not to - * touch that memory here as that could happen before we get here */ - WaitForSingleObject(event, INFINITE); - CloseHandle(event); - } - - return RPC_S_OK; -} - -/*********************************************************************** - * RpcServerUnregisterIfEx (RPCRT4.@) - */ -RPC_STATUS WINAPI RpcServerUnregisterIfEx( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, int RundownContextHandles ) -{ - FIXME("(IfSpec == (RPC_IF_HANDLE)^%p, MgrTypeUuid == %s, RundownContextHandles == %d): stub\n", - IfSpec, debugstr_guid(MgrTypeUuid), RundownContextHandles); - - return RPC_S_OK; -} - -/*********************************************************************** - * RpcObjectSetType (RPCRT4.@) - * - * PARAMS - * ObjUuid [I] "Object" UUID - * TypeUuid [I] "Type" UUID - * - * RETURNS - * RPC_S_OK The call succeeded - * 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 - * 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 - * interface by registering different end-point vectors for the different - * types. There's no need to call this if a server only supports the nil - * type, as is typical. - */ -RPC_STATUS WINAPI RpcObjectSetType( UUID* ObjUuid, UUID* TypeUuid ) -{ - RpcObjTypeMap *map = RpcObjTypeMaps, *prev = NULL; - RPC_STATUS dummy; - - TRACE("(ObjUUID == %s, TypeUuid == %s).\n", debugstr_guid(ObjUuid), debugstr_guid(TypeUuid)); - if ((! ObjUuid) || UuidIsNil(ObjUuid, &dummy)) { - /* nil uuid cannot be remapped */ - return RPC_S_INVALID_OBJECT; - } - - /* find the mapping for this object if there is one ... */ - while (map) { - if (! UuidCompare(ObjUuid, &map->Object, &dummy)) break; - prev = map; - map = map->next; - } - if ((! TypeUuid) || UuidIsNil(TypeUuid, &dummy)) { - /* ... and drop it from the list */ - if (map) { - if (prev) - prev->next = map->next; - else - RpcObjTypeMaps = map->next; - HeapFree(GetProcessHeap(), 0, map); - } - } else { - /* ... , fail if we found it ... */ - if (map) - return RPC_S_ALREADY_REGISTERED; - /* ... otherwise create a new one and add it in. */ - map = HeapAlloc(GetProcessHeap(), 0, sizeof(RpcObjTypeMap)); - memcpy(&map->Object, ObjUuid, sizeof(UUID)); - memcpy(&map->Type, TypeUuid, sizeof(UUID)); - map->next = NULL; - if (prev) - prev->next = map; /* prev is the last map in the linklist */ - else - RpcObjTypeMaps = map; - } - - return RPC_S_OK; -} - -/*********************************************************************** - * 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 */ -} - -/*********************************************************************** - * RpcServerRegisterAuthInfoW (RPCRT4.@) - */ -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 */ -} - -/*********************************************************************** - * RpcServerListen (RPCRT4.@) - */ -RPC_STATUS WINAPI RpcServerListen( UINT MinimumCallThreads, UINT MaxCalls, UINT DontWait ) -{ - RPC_STATUS status = RPC_S_OK; - - TRACE("(%u,%u,%u)\n", MinimumCallThreads, MaxCalls, DontWait); - - if (list_empty(&protseqs)) - return RPC_S_NO_PROTSEQS_REGISTERED; - - status = RPCRT4_start_listen(FALSE); - - if (DontWait || (status != RPC_S_OK)) return status; - - return RpcMgmtWaitServerListen(); -} - -/*********************************************************************** - * RpcMgmtServerWaitListen (RPCRT4.@) - */ -RPC_STATUS WINAPI RpcMgmtWaitServerListen( void ) -{ - TRACE("()\n"); - - EnterCriticalSection(&listen_cs); - - if (!std_listen) { - LeaveCriticalSection(&listen_cs); - return RPC_S_NOT_LISTENING; - } - - LeaveCriticalSection(&listen_cs); - - FIXME("not waiting for server calls to finish\n"); - - return RPC_S_OK; -} - -/*********************************************************************** - * RpcMgmtStopServerListening (RPCRT4.@) - */ -RPC_STATUS WINAPI RpcMgmtStopServerListening ( RPC_BINDING_HANDLE Binding ) -{ - TRACE("(Binding == (RPC_BINDING_HANDLE)^%p)\n", Binding); - - if (Binding) { - FIXME("client-side invocation not implemented.\n"); - return RPC_S_WRONG_KIND_OF_BINDING; - } - - RPCRT4_stop_listen(FALSE); - - return RPC_S_OK; -} - -/*********************************************************************** - * RpcMgmtEnableIdleCleanup (RPCRT4.@) - */ -RPC_STATUS WINAPI RpcMgmtEnableIdleCleanup(void) -{ - FIXME("(): stub\n"); - return RPC_S_OK; -} - -/*********************************************************************** - * I_RpcServerStartListening (RPCRT4.@) - */ -RPC_STATUS WINAPI I_RpcServerStartListening( HWND hWnd ) -{ - FIXME( "(%p): stub\n", hWnd ); - - return RPC_S_OK; -} - -/*********************************************************************** - * I_RpcServerStopListening (RPCRT4.@) - */ -RPC_STATUS WINAPI I_RpcServerStopListening( void ) -{ - FIXME( "(): stub\n" ); - - return RPC_S_OK; -} - -/*********************************************************************** - * I_RpcWindowProc (RPCRT4.@) - */ -UINT WINAPI I_RpcWindowProc( void *hWnd, UINT Message, UINT wParam, ULONG lParam ) -{ - FIXME( "(%p,%08x,%08x,%08x): stub\n", hWnd, Message, wParam, lParam ); - - return 0; -} - -/*********************************************************************** - * RpcMgmtInqIfIds (RPCRT4.@) - */ -RPC_STATUS WINAPI RpcMgmtInqIfIds(RPC_BINDING_HANDLE Binding, RPC_IF_ID_VECTOR **IfIdVector) -{ - FIXME("(%p,%p): stub\n", Binding, IfIdVector); - return RPC_S_INVALID_BINDING; -} - -/*********************************************************************** - * RpcMgmtEpEltInqBegin (RPCRT4.@) - */ -RPC_STATUS WINAPI RpcMgmtEpEltInqBegin(RPC_BINDING_HANDLE Binding, ULONG InquiryType, - RPC_IF_ID *IfId, ULONG VersOption, UUID *ObjectUuid, RPC_EP_INQ_HANDLE* InquiryContext) -{ - FIXME("(%p,%u,%p,%u,%p,%p): stub\n", - Binding, InquiryType, IfId, VersOption, ObjectUuid, InquiryContext); - return RPC_S_INVALID_BINDING; -} - -/*********************************************************************** - * RpcMgmtIsServerListening (RPCRT4.@) - */ -RPC_STATUS WINAPI RpcMgmtIsServerListening(RPC_BINDING_HANDLE Binding) -{ - FIXME("(%p): stub\n", Binding); - return RPC_S_INVALID_BINDING; -} - -/*********************************************************************** - * RpcMgmtSetServerStackSize (RPCRT4.@) - */ -RPC_STATUS WINAPI RpcMgmtSetServerStackSize(ULONG ThreadStackSize) -{ - FIXME("(0x%x): stub\n", ThreadStackSize); - return RPC_S_OK; -} - -/*********************************************************************** - * I_RpcGetCurrentCallHandle (RPCRT4.@) - */ -RPC_BINDING_HANDLE WINAPI I_RpcGetCurrentCallHandle(void) -{ - TRACE("\n"); - return RPCRT4_GetThreadCurrentCallHandle(); -} +/* + * RPC server API + * + * Copyright 2001 Ove Kåven, TransGaming Technologies + * Copyright 2004 Filip Navara + * + * 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 + * + * TODO: + * - a whole lot + */ + +#include "config.h" +#include "wine/port.h" + +#include +#include +#include +#include + +#include "windef.h" +#include "winbase.h" +#include "winerror.h" + +#include "rpc.h" +#include "rpcndr.h" +#include "excpt.h" + +#include "wine/debug.h" +#include "wine/exception.h" + +#include "rpc_server.h" +#include "rpc_assoc.h" +#include "rpc_message.h" +#include "rpc_defs.h" +#include "ncastatus.h" + +WINE_DEFAULT_DEBUG_CHANNEL(rpc); + +typedef struct _RpcPacket +{ + struct _RpcConnection* conn; + RpcPktHdr* hdr; + RPC_MESSAGE* msg; +} RpcPacket; + +typedef struct _RpcObjTypeMap +{ + /* FIXME: a hash table would be better. */ + struct _RpcObjTypeMap *next; + UUID Object; + UUID Type; +} RpcObjTypeMap; + +static RpcObjTypeMap *RpcObjTypeMaps; + +/* list of type RpcServerProtseq */ +static struct list protseqs = LIST_INIT(protseqs); +static struct list server_interfaces = LIST_INIT(server_interfaces); + +static CRITICAL_SECTION server_cs; +static CRITICAL_SECTION_DEBUG server_cs_debug = +{ + 0, 0, &server_cs, + { &server_cs_debug.ProcessLocksList, &server_cs_debug.ProcessLocksList }, + 0, 0, { (DWORD_PTR)(__FILE__ ": server_cs") } +}; +static CRITICAL_SECTION server_cs = { &server_cs_debug, -1, 0, 0, 0, 0 }; + +static CRITICAL_SECTION listen_cs; +static CRITICAL_SECTION_DEBUG listen_cs_debug = +{ + 0, 0, &listen_cs, + { &listen_cs_debug.ProcessLocksList, &listen_cs_debug.ProcessLocksList }, + 0, 0, { (DWORD_PTR)(__FILE__ ": listen_cs") } +}; +static CRITICAL_SECTION listen_cs = { &listen_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; + +static UUID uuid_nil; + +static inline RpcObjTypeMap *LookupObjTypeMap(UUID *ObjUuid) +{ + RpcObjTypeMap *rslt = RpcObjTypeMaps; + RPC_STATUS dummy; + + while (rslt) { + if (! UuidCompare(ObjUuid, &rslt->Object, &dummy)) break; + rslt = rslt->next; + } + + return rslt; +} + +static inline UUID *LookupObjType(UUID *ObjUuid) +{ + RpcObjTypeMap *map = LookupObjTypeMap(ObjUuid); + if (map) + return &map->Type; + else + return &uuid_nil; +} + +static RpcServerInterface* RPCRT4_find_interface(UUID* object, + const RPC_SYNTAX_IDENTIFIER* if_id, + BOOL check_object) +{ + UUID* MgrType = NULL; + RpcServerInterface* cif; + RPC_STATUS status; + + if (check_object) + MgrType = LookupObjType(object); + EnterCriticalSection(&server_cs); + LIST_FOR_EACH_ENTRY(cif, &server_interfaces, RpcServerInterface, entry) { + if (!memcmp(if_id, &cif->If->InterfaceId, sizeof(RPC_SYNTAX_IDENTIFIER)) && + (check_object == FALSE || UuidEqual(MgrType, &cif->MgrTypeUuid, &status)) && + std_listen) { + InterlockedIncrement(&cif->CurrentCalls); + break; + } + } + LeaveCriticalSection(&server_cs); + if (&cif->entry == &server_interfaces) cif = NULL; + TRACE("returning %p for %s\n", cif, debugstr_guid(object)); + return cif; +} + +static void RPCRT4_release_server_interface(RpcServerInterface *sif) +{ + if (!InterlockedDecrement(&sif->CurrentCalls) && + sif->CallsCompletedEvent) { + /* sif must have been removed from server_interfaces before + * CallsCompletedEvent is set */ + SetEvent(sif->CallsCompletedEvent); + HeapFree(GetProcessHeap(), 0, sif); + } +} + +static WINE_EXCEPTION_FILTER(rpc_filter) +{ + WARN("exception caught with code 0x%08x = %d\n", GetExceptionCode(), GetExceptionCode()); + TRACE("returning failure packet\n"); + /* catch every exception */ + return EXCEPTION_EXECUTE_HANDLER; +} + +static void RPCRT4_process_packet(RpcConnection* conn, RpcPktHdr* hdr, RPC_MESSAGE* msg) +{ + RpcServerInterface* sif; + RPC_DISPATCH_FUNCTION func; + UUID *object_uuid; + RpcPktHdr *response = NULL; + void *buf = msg->Buffer; + RPC_STATUS status; + BOOL exception; + NDR_SCONTEXT context_handle; + + msg->Handle = (RPC_BINDING_HANDLE)conn->server_binding; + + switch (hdr->common.ptype) { + case PKT_BIND: + TRACE("got bind packet\n"); + + /* FIXME: do more checks! */ + if (hdr->bind.max_tsize < RPC_MIN_PACKET_SIZE || + !UuidIsNil(&conn->ActiveInterface.SyntaxGUID, &status) || + 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->bind.assoc_gid, + &conn->server_binding->Assoc) == RPC_S_OK) + sif = RPCRT4_find_interface(NULL, &hdr->bind.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->bind.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->bind.abstract; + conn->MaxTransmissionSize = hdr->bind.max_tsize; + + RPCRT4_release_server_interface(sif); + } + + status = RPCRT4_Send(conn, response, NULL, 0); + RPCRT4_FreeHeader(response); + if (status != RPC_S_OK) + goto fail; + + break; + + case PKT_REQUEST: + TRACE("got request packet\n"); + + /* fail if the connection isn't bound with an interface */ + if (UuidIsNil(&conn->ActiveInterface.SyntaxGUID, &status)) { + /* FIXME: should send BindNack instead */ + response = RPCRT4_BuildFaultHeader(NDR_LOCAL_DATA_REPRESENTATION, + status); + + RPCRT4_Send(conn, response, NULL, 0); + RPCRT4_FreeHeader(response); + break; + } + + if (hdr->common.flags & RPC_FLG_OBJECT_UUID) { + object_uuid = (UUID*)(&hdr->request + 1); + } else { + object_uuid = NULL; + } + + sif = RPCRT4_find_interface(object_uuid, &conn->ActiveInterface, 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, + NCA_S_UNK_IF); + + RPCRT4_Send(conn, response, NULL, 0); + RPCRT4_FreeHeader(response); + break; + } + msg->RpcInterfaceInformation = sif->If; + /* copy the endpoint vector from sif to msg so that midl-generated code will use it */ + msg->ManagerEpv = sif->MgrEpv; + if (object_uuid != NULL) { + RPCRT4_SetBindingObject(msg->Handle, object_uuid); + } + + /* find dispatch function */ + msg->ProcNum = hdr->request.opnum; + if (sif->Flags & RPC_IF_OLE) { + /* native ole32 always gives us a dispatch table with a single entry + * (I assume that's a wrapper for IRpcStubBuffer::Invoke) */ + func = *sif->If->DispatchTable->DispatchTable; + } else { + if (msg->ProcNum >= sif->If->DispatchTable->DispatchTableCount) { + WARN("invalid procnum (%d/%d)\n", msg->ProcNum, sif->If->DispatchTable->DispatchTableCount); + response = RPCRT4_BuildFaultHeader(NDR_LOCAL_DATA_REPRESENTATION, + NCA_S_OP_RNG_ERROR); + + RPCRT4_Send(conn, response, NULL, 0); + RPCRT4_FreeHeader(response); + } + func = sif->If->DispatchTable->DispatchTable[msg->ProcNum]; + } + + /* put in the drep. FIXME: is this more universally applicable? + perhaps we should move this outward... */ + msg->DataRepresentation = + MAKELONG( MAKEWORD(hdr->common.drep[0], hdr->common.drep[1]), + MAKEWORD(hdr->common.drep[2], hdr->common.drep[3])); + + exception = FALSE; + + /* dispatch */ + RPCRT4_SetThreadCurrentCallHandle(msg->Handle); + __TRY { + if (func) func(msg); + } __EXCEPT(rpc_filter) { + exception = TRUE; + if (GetExceptionCode() == STATUS_ACCESS_VIOLATION) + status = ERROR_NOACCESS; + else + status = GetExceptionCode(); + response = RPCRT4_BuildFaultHeader(msg->DataRepresentation, + RPC2NCA_STATUS(status)); + } __ENDTRY + RPCRT4_SetThreadCurrentCallHandle(NULL); + + /* release any unmarshalled context handles */ + while ((context_handle = RPCRT4_PopThreadContextHandle()) != NULL) + RpcServerAssoc_ReleaseContextHandle(conn->server_binding->Assoc, context_handle, TRUE); + + if (!exception) + response = RPCRT4_BuildResponseHeader(msg->DataRepresentation, + msg->BufferLength); + + /* send response packet */ + if (response) { + status = RPCRT4_Send(conn, response, exception ? NULL : msg->Buffer, + exception ? 0 : msg->BufferLength); + RPCRT4_FreeHeader(response); + } else + ERR("out of memory\n"); + + msg->RpcInterfaceInformation = NULL; + RPCRT4_release_server_interface(sif); + + break; + + default: + FIXME("unhandled packet type %u\n", hdr->common.ptype); + break; + } + +fail: + /* clean up */ + if (msg->Buffer == buf) msg->Buffer = NULL; + TRACE("freeing Buffer=%p\n", buf); + HeapFree(GetProcessHeap(), 0, buf); + msg->Handle = 0; + I_RpcFreeBuffer(msg); + msg->Buffer = NULL; + RPCRT4_FreeHeader(hdr); + HeapFree(GetProcessHeap(), 0, msg); +} + +static DWORD CALLBACK RPCRT4_worker_thread(LPVOID the_arg) +{ + RpcPacket *pkt = the_arg; + RPCRT4_process_packet(pkt->conn, pkt->hdr, pkt->msg); + HeapFree(GetProcessHeap(), 0, pkt); + return 0; +} + +static DWORD CALLBACK RPCRT4_io_thread(LPVOID the_arg) +{ + RpcConnection* conn = (RpcConnection*)the_arg; + RpcPktHdr *hdr; + RPC_MESSAGE *msg; + RPC_STATUS status; + RpcPacket *packet; + + TRACE("(%p)\n", conn); + + for (;;) { + msg = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RPC_MESSAGE)); + + status = RPCRT4_Receive(conn, &hdr, msg); + if (status != RPC_S_OK) { + WARN("receive failed with error %lx\n", status); + HeapFree(GetProcessHeap(), 0, msg); + break; + } + +#if 0 + RPCRT4_process_packet(conn, hdr, msg); +#else + packet = HeapAlloc(GetProcessHeap(), 0, sizeof(RpcPacket)); + packet->conn = conn; + packet->hdr = hdr; + packet->msg = msg; + QueueUserWorkItem(RPCRT4_worker_thread, packet, WT_EXECUTELONGFUNCTION); +#endif + msg = NULL; + } + RPCRT4_DestroyConnection(conn); + return 0; +} + +void RPCRT4_new_client(RpcConnection* conn) +{ + HANDLE thread = CreateThread(NULL, 0, RPCRT4_io_thread, conn, 0, NULL); + if (!thread) { + DWORD err = GetLastError(); + ERR("failed to create thread, error=%08x\n", err); + RPCRT4_DestroyConnection(conn); + } + /* we could set conn->thread, but then we'd have to make the io_thread wait + * for that, otherwise the thread might finish, destroy the connection, and + * free the memory we'd write to before we did, causing crashes and stuff - + * so let's implement that later, when we really need conn->thread */ + + CloseHandle( thread ); +} + +static DWORD CALLBACK RPCRT4_server_thread(LPVOID the_arg) +{ + int res; + unsigned int count; + void *objs = NULL; + RpcServerProtseq* cps = the_arg; + RpcConnection* conn; + BOOL set_ready_event = FALSE; + + TRACE("(the_arg == ^%p)\n", the_arg); + + for (;;) { + objs = cps->ops->get_wait_array(cps, objs, &count); + + if (set_ready_event) + { + /* signal to function that changed state that we are now sync'ed */ + SetEvent(cps->server_ready_event); + set_ready_event = FALSE; + } + + /* start waiting */ + res = cps->ops->wait_for_new_connection(cps, count, objs); + if (res == -1) + break; + else if (res == 0) + { + if (!std_listen) + { + SetEvent(cps->server_ready_event); + break; + } + set_ready_event = TRUE; + } + } + cps->ops->free_wait_array(cps, objs); + EnterCriticalSection(&cps->cs); + /* close connections */ + conn = cps->conn; + while (conn) { + RPCRT4_CloseConnection(conn); + conn = conn->Next; + } + LeaveCriticalSection(&cps->cs); + return 0; +} + +/* tells the server thread that the state has changed and waits for it to + * make the changes */ +static void RPCRT4_sync_with_server_thread(RpcServerProtseq *ps) +{ + /* make sure we are the only thread sync'ing the server state, otherwise + * there is a race with the server thread setting an older state and setting + * the server_ready_event when the new state hasn't yet been applied */ + WaitForSingleObject(ps->mgr_mutex, INFINITE); + + ps->ops->signal_state_changed(ps); + + /* wait for server thread to make the requested changes before returning */ + WaitForSingleObject(ps->server_ready_event, INFINITE); + + ReleaseMutex(ps->mgr_mutex); +} + +static RPC_STATUS RPCRT4_start_listen_protseq(RpcServerProtseq *ps, BOOL auto_listen) +{ + RPC_STATUS status = RPC_S_OK; + HANDLE server_thread; + + EnterCriticalSection(&listen_cs); + if (ps->is_listening) goto done; + + if (!ps->mgr_mutex) ps->mgr_mutex = CreateMutexW(NULL, FALSE, NULL); + if (!ps->server_ready_event) ps->server_ready_event = CreateEventW(NULL, FALSE, FALSE, NULL); + server_thread = CreateThread(NULL, 0, RPCRT4_server_thread, ps, 0, NULL); + if (!server_thread) + { + status = RPC_S_OUT_OF_RESOURCES; + goto done; + } + ps->is_listening = TRUE; + CloseHandle(server_thread); + +done: + LeaveCriticalSection(&listen_cs); + return status; +} + +static RPC_STATUS RPCRT4_start_listen(BOOL auto_listen) +{ + RPC_STATUS status = RPC_S_ALREADY_LISTENING; + RpcServerProtseq *cps; + + TRACE("\n"); + + EnterCriticalSection(&listen_cs); + if (auto_listen || (manual_listen_count++ == 0)) + { + status = RPC_S_OK; + if (++listen_count == 1) + std_listen = TRUE; + } + LeaveCriticalSection(&listen_cs); + + if (std_listen) + { + EnterCriticalSection(&server_cs); + LIST_FOR_EACH_ENTRY(cps, &protseqs, RpcServerProtseq, entry) + { + status = RPCRT4_start_listen_protseq(cps, TRUE); + if (status != RPC_S_OK) + break; + + /* make sure server is actually listening on the interface before + * returning */ + RPCRT4_sync_with_server_thread(cps); + } + LeaveCriticalSection(&server_cs); + } + + return status; +} + +static void RPCRT4_stop_listen(BOOL auto_listen) +{ + EnterCriticalSection(&listen_cs); + if (auto_listen || (--manual_listen_count == 0)) + { + if (listen_count != 0 && --listen_count == 0) { + RpcServerProtseq *cps; + + std_listen = FALSE; + LeaveCriticalSection(&listen_cs); + + LIST_FOR_EACH_ENTRY(cps, &protseqs, RpcServerProtseq, entry) + RPCRT4_sync_with_server_thread(cps); + + return; + } + assert(listen_count >= 0); + } + LeaveCriticalSection(&listen_cs); +} + +static RPC_STATUS RPCRT4_use_protseq(RpcServerProtseq* ps, LPSTR endpoint) +{ + RPC_STATUS status; + + status = ps->ops->open_endpoint(ps, endpoint); + if (status != RPC_S_OK) + return status; + + if (std_listen) + { + status = RPCRT4_start_listen_protseq(ps, FALSE); + if (status == RPC_S_OK) + RPCRT4_sync_with_server_thread(ps); + } + + return status; +} + +/*********************************************************************** + * RpcServerInqBindings (RPCRT4.@) + */ +RPC_STATUS WINAPI RpcServerInqBindings( RPC_BINDING_VECTOR** BindingVector ) +{ + RPC_STATUS status; + DWORD count; + RpcServerProtseq* ps; + RpcConnection* conn; + + if (BindingVector) + TRACE("(*BindingVector == ^%p)\n", *BindingVector); + else + ERR("(BindingVector == NULL!!?)\n"); + + EnterCriticalSection(&server_cs); + /* count connections */ + count = 0; + LIST_FOR_EACH_ENTRY(ps, &protseqs, RpcServerProtseq, entry) { + EnterCriticalSection(&ps->cs); + conn = ps->conn; + while (conn) { + count++; + conn = conn->Next; + } + LeaveCriticalSection(&ps->cs); + } + if (count) { + /* export bindings */ + *BindingVector = HeapAlloc(GetProcessHeap(), 0, + sizeof(RPC_BINDING_VECTOR) + + sizeof(RPC_BINDING_HANDLE)*(count-1)); + (*BindingVector)->Count = count; + count = 0; + LIST_FOR_EACH_ENTRY(ps, &protseqs, RpcServerProtseq, entry) { + EnterCriticalSection(&ps->cs); + conn = ps->conn; + while (conn) { + RPCRT4_MakeBinding((RpcBinding**)&(*BindingVector)->BindingH[count], + conn); + count++; + conn = conn->Next; + } + LeaveCriticalSection(&ps->cs); + } + status = RPC_S_OK; + } else { + *BindingVector = NULL; + status = RPC_S_NO_BINDINGS; + } + LeaveCriticalSection(&server_cs); + return status; +} + +/*********************************************************************** + * RpcServerUseProtseqEpA (RPCRT4.@) + */ +RPC_STATUS WINAPI RpcServerUseProtseqEpA( RPC_CSTR Protseq, UINT MaxCalls, RPC_CSTR Endpoint, LPVOID SecurityDescriptor ) +{ + RPC_POLICY policy; + + TRACE( "(%s,%u,%s,%p)\n", Protseq, MaxCalls, Endpoint, SecurityDescriptor ); + + /* This should provide the default behaviour */ + policy.Length = sizeof( policy ); + policy.EndpointFlags = 0; + policy.NICFlags = 0; + + return RpcServerUseProtseqEpExA( Protseq, MaxCalls, Endpoint, SecurityDescriptor, &policy ); +} + +/*********************************************************************** + * RpcServerUseProtseqEpW (RPCRT4.@) + */ +RPC_STATUS WINAPI RpcServerUseProtseqEpW( RPC_WSTR Protseq, UINT MaxCalls, RPC_WSTR Endpoint, LPVOID SecurityDescriptor ) +{ + RPC_POLICY policy; + + TRACE( "(%s,%u,%s,%p)\n", debugstr_w( Protseq ), MaxCalls, debugstr_w( Endpoint ), SecurityDescriptor ); + + /* This should provide the default behaviour */ + policy.Length = sizeof( policy ); + policy.EndpointFlags = 0; + policy.NICFlags = 0; + + return RpcServerUseProtseqEpExW( Protseq, MaxCalls, Endpoint, SecurityDescriptor, &policy ); +} + +/*********************************************************************** + * alloc_serverprotoseq (internal) + * + * Must be called with server_cs held. + */ +static RPC_STATUS alloc_serverprotoseq(UINT MaxCalls, char *Protseq, RpcServerProtseq **ps) +{ + const struct protseq_ops *ops = rpcrt4_get_protseq_ops(Protseq); + + if (!ops) + { + FIXME("protseq %s not supported\n", debugstr_a(Protseq)); + return RPC_S_PROTSEQ_NOT_SUPPORTED; + } + + *ps = ops->alloc(); + if (!*ps) + return RPC_S_OUT_OF_RESOURCES; + (*ps)->MaxCalls = MaxCalls; + (*ps)->Protseq = Protseq; + (*ps)->ops = ops; + (*ps)->MaxCalls = 0; + (*ps)->conn = NULL; + InitializeCriticalSection(&(*ps)->cs); + (*ps)->is_listening = FALSE; + (*ps)->mgr_mutex = NULL; + (*ps)->server_ready_event = NULL; + + list_add_head(&protseqs, &(*ps)->entry); + + TRACE("new protseq %p created for %s\n", *ps, Protseq); + + return RPC_S_OK; +} + +/* 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) +{ + RPC_STATUS status; + RpcServerProtseq *cps; + + EnterCriticalSection(&server_cs); + + LIST_FOR_EACH_ENTRY(cps, &protseqs, RpcServerProtseq, entry) + if (!strcmp(cps->Protseq, Protseq)) + { + TRACE("found existing protseq object for %s\n", Protseq); + *ps = cps; + LeaveCriticalSection(&server_cs); + return S_OK; + } + + status = alloc_serverprotoseq(MaxCalls, Protseq, ps); + + LeaveCriticalSection(&server_cs); + + return status; +} + +/*********************************************************************** + * RpcServerUseProtseqEpExA (RPCRT4.@) + */ +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,%lu,%lu})\n", debugstr_a(szps), MaxCalls, + debugstr_a(szep), SecurityDescriptor, + lpPolicy->Length, lpPolicy->EndpointFlags, lpPolicy->NICFlags ); + + status = RPCRT4_get_or_create_serverprotseq(MaxCalls, RPCRT4_strdupA(szps), &ps); + if (status != RPC_S_OK) + return status; + + return RPCRT4_use_protseq(ps, szep); +} + +/*********************************************************************** + * RpcServerUseProtseqEpExW (RPCRT4.@) + */ +RPC_STATUS WINAPI RpcServerUseProtseqEpExW( RPC_WSTR Protseq, UINT MaxCalls, RPC_WSTR Endpoint, LPVOID SecurityDescriptor, + PRPC_POLICY lpPolicy ) +{ + RpcServerProtseq* ps; + RPC_STATUS status; + LPSTR EndpointA; + + TRACE("(%s,%u,%s,%p,{%u,%lu,%lu})\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); + if (status != RPC_S_OK) + return status; + + EndpointA = RPCRT4_strdupWtoA(Endpoint); + status = RPCRT4_use_protseq(ps, EndpointA); + RPCRT4_strfree(EndpointA); + return status; +} + +/*********************************************************************** + * RpcServerUseProtseqA (RPCRT4.@) + */ +RPC_STATUS WINAPI RpcServerUseProtseqA(RPC_CSTR Protseq, unsigned int MaxCalls, void *SecurityDescriptor) +{ + TRACE("(Protseq == %s, MaxCalls == %d, SecurityDescriptor == ^%p)\n", debugstr_a((char*)Protseq), MaxCalls, SecurityDescriptor); + return RpcServerUseProtseqEpA(Protseq, MaxCalls, NULL, SecurityDescriptor); +} + +/*********************************************************************** + * RpcServerUseProtseqW (RPCRT4.@) + */ +RPC_STATUS WINAPI RpcServerUseProtseqW(RPC_WSTR Protseq, unsigned int MaxCalls, void *SecurityDescriptor) +{ + TRACE("Protseq == %s, MaxCalls == %d, SecurityDescriptor == ^%p)\n", debugstr_w(Protseq), MaxCalls, SecurityDescriptor); + return RpcServerUseProtseqEpW(Protseq, MaxCalls, NULL, SecurityDescriptor); +} + +/*********************************************************************** + * RpcServerRegisterIf (RPCRT4.@) + */ +RPC_STATUS WINAPI RpcServerRegisterIf( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, RPC_MGR_EPV* MgrEpv ) +{ + TRACE("(%p,%s,%p)\n", IfSpec, debugstr_guid(MgrTypeUuid), MgrEpv); + return RpcServerRegisterIf2( IfSpec, MgrTypeUuid, MgrEpv, 0, RPC_C_LISTEN_MAX_CALLS_DEFAULT, (UINT)-1, NULL ); +} + +/*********************************************************************** + * RpcServerRegisterIfEx (RPCRT4.@) + */ +RPC_STATUS WINAPI RpcServerRegisterIfEx( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, RPC_MGR_EPV* MgrEpv, + UINT Flags, UINT MaxCalls, RPC_IF_CALLBACK_FN* IfCallbackFn ) +{ + TRACE("(%p,%s,%p,%u,%u,%p)\n", IfSpec, debugstr_guid(MgrTypeUuid), MgrEpv, Flags, MaxCalls, IfCallbackFn); + return RpcServerRegisterIf2( IfSpec, MgrTypeUuid, MgrEpv, Flags, MaxCalls, (UINT)-1, IfCallbackFn ); +} + +/*********************************************************************** + * RpcServerRegisterIf2 (RPCRT4.@) + */ +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; + RpcServerInterface* sif; + unsigned int i; + + TRACE("(%p,%s,%p,%u,%u,%u,%p)\n", IfSpec, debugstr_guid(MgrTypeUuid), MgrEpv, Flags, MaxCalls, + MaxRpcSize, IfCallbackFn); + TRACE(" interface id: %s %d.%d\n", debugstr_guid(&If->InterfaceId.SyntaxGUID), + If->InterfaceId.SyntaxVersion.MajorVersion, + If->InterfaceId.SyntaxVersion.MinorVersion); + TRACE(" transfer syntax: %s %d.%d\n", debugstr_guid(&If->TransferSyntax.SyntaxGUID), + If->TransferSyntax.SyntaxVersion.MajorVersion, + If->TransferSyntax.SyntaxVersion.MinorVersion); + TRACE(" dispatch table: %p\n", If->DispatchTable); + if (If->DispatchTable) { + TRACE(" dispatch table count: %d\n", If->DispatchTable->DispatchTableCount); + for (i=0; iDispatchTable->DispatchTableCount; i++) { + TRACE(" entry %d: %p\n", i, If->DispatchTable->DispatchTable[i]); + } + TRACE(" reserved: %ld\n", If->DispatchTable->Reserved); + } + TRACE(" protseq endpoint count: %d\n", If->RpcProtseqEndpointCount); + TRACE(" default manager epv: %p\n", If->DefaultManagerEpv); + TRACE(" interpreter info: %p\n", If->InterpreterInfo); + + sif = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcServerInterface)); + sif->If = If; + if (MgrTypeUuid) { + memcpy(&sif->MgrTypeUuid, MgrTypeUuid, sizeof(UUID)); + sif->MgrEpv = MgrEpv; + } else { + memset(&sif->MgrTypeUuid, 0, sizeof(UUID)); + sif->MgrEpv = If->DefaultManagerEpv; + } + sif->Flags = Flags; + sif->MaxCalls = MaxCalls; + sif->MaxRpcSize = MaxRpcSize; + sif->IfCallbackFn = IfCallbackFn; + + EnterCriticalSection(&server_cs); + list_add_head(&server_interfaces, &sif->entry); + LeaveCriticalSection(&server_cs); + + if (sif->Flags & RPC_IF_AUTOLISTEN) + RPCRT4_start_listen(TRUE); + + return RPC_S_OK; +} + +/*********************************************************************** + * RpcServerUnregisterIf (RPCRT4.@) + */ +RPC_STATUS WINAPI RpcServerUnregisterIf( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, UINT WaitForCallsToComplete ) +{ + PRPC_SERVER_INTERFACE If = (PRPC_SERVER_INTERFACE)IfSpec; + HANDLE event = NULL; + BOOL found = FALSE; + BOOL completed = TRUE; + RpcServerInterface *cif; + RPC_STATUS status; + + TRACE("(IfSpec == (RPC_IF_HANDLE)^%p (%s), MgrTypeUuid == %s, WaitForCallsToComplete == %u)\n", + IfSpec, debugstr_guid(&If->InterfaceId.SyntaxGUID), debugstr_guid(MgrTypeUuid), WaitForCallsToComplete); + + EnterCriticalSection(&server_cs); + LIST_FOR_EACH_ENTRY(cif, &server_interfaces, RpcServerInterface, entry) { + if ((!IfSpec || !memcmp(&If->InterfaceId, &cif->If->InterfaceId, sizeof(RPC_SYNTAX_IDENTIFIER))) && + UuidEqual(MgrTypeUuid, &cif->MgrTypeUuid, &status)) { + list_remove(&cif->entry); + if (cif->CurrentCalls) { + completed = FALSE; + if (WaitForCallsToComplete) + cif->CallsCompletedEvent = event = CreateEventW(NULL, FALSE, FALSE, NULL); + } + found = TRUE; + break; + } + } + LeaveCriticalSection(&server_cs); + + if (!found) { + ERR("not found for object %s\n", debugstr_guid(MgrTypeUuid)); + return RPC_S_UNKNOWN_IF; + } + + if (completed) + HeapFree(GetProcessHeap(), 0, cif); + else if (event) { + /* sif will be freed when the last call is completed, so be careful not to + * touch that memory here as that could happen before we get here */ + WaitForSingleObject(event, INFINITE); + CloseHandle(event); + } + + return RPC_S_OK; +} + +/*********************************************************************** + * RpcServerUnregisterIfEx (RPCRT4.@) + */ +RPC_STATUS WINAPI RpcServerUnregisterIfEx( RPC_IF_HANDLE IfSpec, UUID* MgrTypeUuid, int RundownContextHandles ) +{ + FIXME("(IfSpec == (RPC_IF_HANDLE)^%p, MgrTypeUuid == %s, RundownContextHandles == %d): stub\n", + IfSpec, debugstr_guid(MgrTypeUuid), RundownContextHandles); + + return RPC_S_OK; +} + +/*********************************************************************** + * RpcObjectSetType (RPCRT4.@) + * + * PARAMS + * ObjUuid [I] "Object" UUID + * TypeUuid [I] "Type" UUID + * + * RETURNS + * RPC_S_OK The call succeeded + * 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 + * 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 + * interface by registering different end-point vectors for the different + * types. There's no need to call this if a server only supports the nil + * type, as is typical. + */ +RPC_STATUS WINAPI RpcObjectSetType( UUID* ObjUuid, UUID* TypeUuid ) +{ + RpcObjTypeMap *map = RpcObjTypeMaps, *prev = NULL; + RPC_STATUS dummy; + + TRACE("(ObjUUID == %s, TypeUuid == %s).\n", debugstr_guid(ObjUuid), debugstr_guid(TypeUuid)); + if ((! ObjUuid) || UuidIsNil(ObjUuid, &dummy)) { + /* nil uuid cannot be remapped */ + return RPC_S_INVALID_OBJECT; + } + + /* find the mapping for this object if there is one ... */ + while (map) { + if (! UuidCompare(ObjUuid, &map->Object, &dummy)) break; + prev = map; + map = map->next; + } + if ((! TypeUuid) || UuidIsNil(TypeUuid, &dummy)) { + /* ... and drop it from the list */ + if (map) { + if (prev) + prev->next = map->next; + else + RpcObjTypeMaps = map->next; + HeapFree(GetProcessHeap(), 0, map); + } + } else { + /* ... , fail if we found it ... */ + if (map) + return RPC_S_ALREADY_REGISTERED; + /* ... otherwise create a new one and add it in. */ + map = HeapAlloc(GetProcessHeap(), 0, sizeof(RpcObjTypeMap)); + memcpy(&map->Object, ObjUuid, sizeof(UUID)); + memcpy(&map->Type, TypeUuid, sizeof(UUID)); + map->next = NULL; + if (prev) + prev->next = map; /* prev is the last map in the linklist */ + else + RpcObjTypeMaps = map; + } + + return RPC_S_OK; +} + +/*********************************************************************** + * 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 */ +} + +/*********************************************************************** + * RpcServerRegisterAuthInfoW (RPCRT4.@) + */ +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 */ +} + +/*********************************************************************** + * RpcServerListen (RPCRT4.@) + */ +RPC_STATUS WINAPI RpcServerListen( UINT MinimumCallThreads, UINT MaxCalls, UINT DontWait ) +{ + RPC_STATUS status = RPC_S_OK; + + TRACE("(%u,%u,%u)\n", MinimumCallThreads, MaxCalls, DontWait); + + if (list_empty(&protseqs)) + return RPC_S_NO_PROTSEQS_REGISTERED; + + status = RPCRT4_start_listen(FALSE); + + if (DontWait || (status != RPC_S_OK)) return status; + + return RpcMgmtWaitServerListen(); +} + +/*********************************************************************** + * RpcMgmtServerWaitListen (RPCRT4.@) + */ +RPC_STATUS WINAPI RpcMgmtWaitServerListen( void ) +{ + TRACE("()\n"); + + EnterCriticalSection(&listen_cs); + + if (!std_listen) { + LeaveCriticalSection(&listen_cs); + return RPC_S_NOT_LISTENING; + } + + LeaveCriticalSection(&listen_cs); + + FIXME("not waiting for server calls to finish\n"); + + return RPC_S_OK; +} + +/*********************************************************************** + * RpcMgmtStopServerListening (RPCRT4.@) + */ +RPC_STATUS WINAPI RpcMgmtStopServerListening ( RPC_BINDING_HANDLE Binding ) +{ + TRACE("(Binding == (RPC_BINDING_HANDLE)^%p)\n", Binding); + + if (Binding) { + FIXME("client-side invocation not implemented.\n"); + return RPC_S_WRONG_KIND_OF_BINDING; + } + + RPCRT4_stop_listen(FALSE); + + return RPC_S_OK; +} + +/*********************************************************************** + * RpcMgmtEnableIdleCleanup (RPCRT4.@) + */ +RPC_STATUS WINAPI RpcMgmtEnableIdleCleanup(void) +{ + FIXME("(): stub\n"); + return RPC_S_OK; +} + +/*********************************************************************** + * I_RpcServerStartListening (RPCRT4.@) + */ +RPC_STATUS WINAPI I_RpcServerStartListening( HWND hWnd ) +{ + FIXME( "(%p): stub\n", hWnd ); + + return RPC_S_OK; +} + +/*********************************************************************** + * I_RpcServerStopListening (RPCRT4.@) + */ +RPC_STATUS WINAPI I_RpcServerStopListening( void ) +{ + FIXME( "(): stub\n" ); + + return RPC_S_OK; +} + +/*********************************************************************** + * I_RpcWindowProc (RPCRT4.@) + */ +UINT WINAPI I_RpcWindowProc( void *hWnd, UINT Message, UINT wParam, ULONG lParam ) +{ + FIXME( "(%p,%08x,%08x,%08x): stub\n", hWnd, Message, wParam, lParam ); + + return 0; +} + +/*********************************************************************** + * RpcMgmtInqIfIds (RPCRT4.@) + */ +RPC_STATUS WINAPI RpcMgmtInqIfIds(RPC_BINDING_HANDLE Binding, RPC_IF_ID_VECTOR **IfIdVector) +{ + FIXME("(%p,%p): stub\n", Binding, IfIdVector); + return RPC_S_INVALID_BINDING; +} + +/*********************************************************************** + * RpcMgmtEpEltInqBegin (RPCRT4.@) + */ +RPC_STATUS WINAPI RpcMgmtEpEltInqBegin(RPC_BINDING_HANDLE Binding, ULONG InquiryType, + RPC_IF_ID *IfId, ULONG VersOption, UUID *ObjectUuid, RPC_EP_INQ_HANDLE* InquiryContext) +{ + FIXME("(%p,%u,%p,%u,%p,%p): stub\n", + Binding, InquiryType, IfId, VersOption, ObjectUuid, InquiryContext); + return RPC_S_INVALID_BINDING; +} + +/*********************************************************************** + * RpcMgmtIsServerListening (RPCRT4.@) + */ +RPC_STATUS WINAPI RpcMgmtIsServerListening(RPC_BINDING_HANDLE Binding) +{ + FIXME("(%p): stub\n", Binding); + return RPC_S_INVALID_BINDING; +} + +/*********************************************************************** + * RpcMgmtSetServerStackSize (RPCRT4.@) + */ +RPC_STATUS WINAPI RpcMgmtSetServerStackSize(ULONG ThreadStackSize) +{ + FIXME("(0x%x): stub\n", ThreadStackSize); + return RPC_S_OK; +} + +/*********************************************************************** + * I_RpcGetCurrentCallHandle (RPCRT4.@) + */ +RPC_BINDING_HANDLE WINAPI I_RpcGetCurrentCallHandle(void) +{ + TRACE("\n"); + return RPCRT4_GetThreadCurrentCallHandle(); +} diff --git a/reactos/dll/win32/rpcrt4_new/rpc_server.h b/reactos/dll/win32/rpcrt4_new/rpc_server.h index 822e954a880..eb32be6afc9 100644 --- a/reactos/dll/win32/rpcrt4_new/rpc_server.h +++ b/reactos/dll/win32/rpcrt4_new/rpc_server.h @@ -1,81 +1,81 @@ -/* - * RPC server API - * - * Copyright 2001 Ove Kåven, TransGaming Technologies - * - * 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 - */ - -#ifndef __WINE_RPC_SERVER_H -#define __WINE_RPC_SERVER_H - -#include "rpc_binding.h" -#include "wine/list.h" - -struct protseq_ops; - -typedef struct _RpcServerProtseq -{ - const struct protseq_ops *ops; /* RO */ - struct list entry; /* CS ::server_cs */ - LPSTR Protseq; /* RO */ - UINT MaxCalls; /* RO */ - /* list of listening connections */ - RpcConnection* conn; /* CS cs */ - CRITICAL_SECTION cs; - - /* is the server currently listening? */ - BOOL is_listening; /* CS ::listen_cs */ - /* mutex for ensuring only one thread can change state at a time */ - HANDLE mgr_mutex; - /* set when server thread has finished opening connections */ - HANDLE server_ready_event; -} RpcServerProtseq; - -struct protseq_ops -{ - const char *name; - RpcServerProtseq *(*alloc)(void); - void (*signal_state_changed)(RpcServerProtseq *protseq); - /* previous array is passed in to allow reuse of memory */ - void *(*get_wait_array)(RpcServerProtseq *protseq, void *prev_array, unsigned int *count); - void (*free_wait_array)(RpcServerProtseq *protseq, void *array); - /* returns -1 for failure, 0 for server state changed and 1 to indicate a - * 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); -}; - -typedef struct _RpcServerInterface -{ - struct list entry; - RPC_SERVER_INTERFACE* If; - UUID MgrTypeUuid; - RPC_MGR_EPV* MgrEpv; - UINT Flags; - UINT MaxCalls; - UINT MaxRpcSize; - RPC_IF_CALLBACK_FN* IfCallbackFn; - LONG CurrentCalls; /* number of calls currently executing */ - /* set when unregistering interface to let the caller of - * RpcServerUnregisterIf* know that all calls have finished */ - HANDLE CallsCompletedEvent; -} RpcServerInterface; - -void RPCRT4_new_client(RpcConnection* conn); -const struct protseq_ops *rpcrt4_get_protseq_ops(const char *protseq); - -#endif /* __WINE_RPC_SERVER_H */ +/* + * RPC server API + * + * Copyright 2001 Ove Kåven, TransGaming Technologies + * + * 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 + */ + +#ifndef __WINE_RPC_SERVER_H +#define __WINE_RPC_SERVER_H + +#include "rpc_binding.h" +#include "wine/list.h" + +struct protseq_ops; + +typedef struct _RpcServerProtseq +{ + const struct protseq_ops *ops; /* RO */ + struct list entry; /* CS ::server_cs */ + LPSTR Protseq; /* RO */ + UINT MaxCalls; /* RO */ + /* list of listening connections */ + RpcConnection* conn; /* CS cs */ + CRITICAL_SECTION cs; + + /* is the server currently listening? */ + BOOL is_listening; /* CS ::listen_cs */ + /* mutex for ensuring only one thread can change state at a time */ + HANDLE mgr_mutex; + /* set when server thread has finished opening connections */ + HANDLE server_ready_event; +} RpcServerProtseq; + +struct protseq_ops +{ + const char *name; + RpcServerProtseq *(*alloc)(void); + void (*signal_state_changed)(RpcServerProtseq *protseq); + /* previous array is passed in to allow reuse of memory */ + void *(*get_wait_array)(RpcServerProtseq *protseq, void *prev_array, unsigned int *count); + void (*free_wait_array)(RpcServerProtseq *protseq, void *array); + /* returns -1 for failure, 0 for server state changed and 1 to indicate a + * 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); +}; + +typedef struct _RpcServerInterface +{ + struct list entry; + RPC_SERVER_INTERFACE* If; + UUID MgrTypeUuid; + RPC_MGR_EPV* MgrEpv; + UINT Flags; + UINT MaxCalls; + UINT MaxRpcSize; + RPC_IF_CALLBACK_FN* IfCallbackFn; + LONG CurrentCalls; /* number of calls currently executing */ + /* set when unregistering interface to let the caller of + * RpcServerUnregisterIf* know that all calls have finished */ + HANDLE CallsCompletedEvent; +} RpcServerInterface; + +void RPCRT4_new_client(RpcConnection* conn); +const struct protseq_ops *rpcrt4_get_protseq_ops(const char *protseq); + +#endif /* __WINE_RPC_SERVER_H */ diff --git a/reactos/dll/win32/rpcrt4_new/rpc_transport.c b/reactos/dll/win32/rpcrt4_new/rpc_transport.c index 5bc26ffd297..65dc7997260 100644 --- a/reactos/dll/win32/rpcrt4_new/rpc_transport.c +++ b/reactos/dll/win32/rpcrt4_new/rpc_transport.c @@ -951,8 +951,8 @@ static RPC_STATUS rpcrt4_conn_tcp_handoff(RpcConnection *old_conn, RpcConnection return RPC_S_OUT_OF_RESOURCES; } /* reset to blocking behaviour */ - blocking = 0; - ret = ioctlsocket(ret, FIONBIO, &blocking); + blocking = 0; + ret = ioctlsocket(ret, FIONBIO, &blocking); client->sock = ret; TRACE("Accepted a new TCP connection\n"); return RPC_S_OK; @@ -1203,8 +1203,8 @@ static RpcServerProtseq *rpcrt4_protseq_sock_alloc(void) if (!socketpair(PF_UNIX, SOCK_DGRAM, 0, fds)) { blocking = 1; - ioctlsocket(fds[0], FIONBIO, &blocking); - ioctlsocket(fds[1], FIONBIO, &blocking); + ioctlsocket(fds[0], FIONBIO, &blocking); + ioctlsocket(fds[1], FIONBIO, &blocking); ps->mgr_event_rcv = fds[0]; ps->mgr_event_snd = fds[1]; } diff --git a/reactos/dll/win32/rpcrt4_new/rpcrt4.rbuild b/reactos/dll/win32/rpcrt4_new/rpcrt4.rbuild index 2da95d825fc..fa6f46b15eb 100644 --- a/reactos/dll/win32/rpcrt4_new/rpcrt4.rbuild +++ b/reactos/dll/win32/rpcrt4_new/rpcrt4.rbuild @@ -1,43 +1,43 @@ - - - - . - include/reactos/wine - - - 0x600 - 0x501 - 0x501 - - - - - wine - uuid - ntdll - kernel32 - advapi32 - secur32 - iphlpapi - ws2_32 - cproxy.c - cpsf.c - cstub.c - ndr_contexthandle.c - ndr_clientserver.c - ndr_fullpointer.c - ndr_marshall.c - ndr_ole.c - ndr_stubless.c - rpc_assoc.c - rpc_binding.c - rpc_epmap.c - rpc_message.c - rpc_server.c - rpc_transport.c - rpcrt4_main.c - rpcss_np_client.c - unix_func.c - rpcrt4.rc - rpcrt4.spec - + + + + . + include/reactos/wine + + + 0x600 + 0x501 + 0x501 + + + + + wine + uuid + ntdll + kernel32 + advapi32 + secur32 + iphlpapi + ws2_32 + cproxy.c + cpsf.c + cstub.c + ndr_contexthandle.c + ndr_clientserver.c + ndr_fullpointer.c + ndr_marshall.c + ndr_ole.c + ndr_stubless.c + rpc_assoc.c + rpc_binding.c + rpc_epmap.c + rpc_message.c + rpc_server.c + rpc_transport.c + rpcrt4_main.c + rpcss_np_client.c + unix_func.c + rpcrt4.rc + rpcrt4.spec + diff --git a/reactos/dll/win32/rpcrt4_new/rpcrt4.spec b/reactos/dll/win32/rpcrt4_new/rpcrt4.spec index 1e9cbe3446d..93f6d318e46 100644 --- a/reactos/dll/win32/rpcrt4_new/rpcrt4.spec +++ b/reactos/dll/win32/rpcrt4_new/rpcrt4.spec @@ -1,565 +1,565 @@ -@ stdcall CreateProxyFromTypeInfo(ptr ptr ptr ptr ptr) -@ stub CreateStubFromTypeInfo -@ stdcall CStdStubBuffer_AddRef(ptr) -@ stdcall CStdStubBuffer_Connect(ptr ptr) -@ stdcall CStdStubBuffer_CountRefs(ptr) -@ stdcall CStdStubBuffer_DebugServerQueryInterface(ptr ptr) -@ stdcall CStdStubBuffer_DebugServerRelease(ptr ptr) -@ stdcall CStdStubBuffer_Disconnect(ptr) -@ stdcall CStdStubBuffer_Invoke(ptr ptr ptr) -@ stdcall CStdStubBuffer_IsIIDSupported(ptr ptr) -@ stdcall CStdStubBuffer_QueryInterface(ptr ptr ptr) -@ stub CreateServerInterfaceFromStub # wxp -@ stdcall DceErrorInqTextA (long ptr) -@ stdcall DceErrorInqTextW (long ptr) -@ stdcall -private DllRegisterServer() -@ stub GlobalMutexClearExternal -@ stub GlobalMutexRequestExternal -@ stdcall IUnknown_AddRef_Proxy(ptr) -@ stdcall IUnknown_QueryInterface_Proxy(ptr ptr ptr) -@ stdcall IUnknown_Release_Proxy(ptr) -@ stub I_RpcAbortAsyncCall -@ stdcall I_RpcAllocate(long) -@ stub I_RpcAsyncAbortCall -@ stub I_RpcAsyncSendReceive # NT4 -@ stub I_RpcAsyncSetHandle -@ stub I_RpcBCacheAllocate -@ stub I_RpcBCacheFree -@ stub I_RpcBindingCopy -@ stub I_RpcBindingInqConnId -@ stub I_RpcBindingInqDynamicEndPoint -@ stub I_RpcBindingInqDynamicEndPointA -@ stub I_RpcBindingInqDynamicEndPointW -@ stub I_RpcBindingInqLocalClientPID # wxp -@ stub I_RpcBindingInqSecurityContext -@ stub I_RpcBindingInqTransportType -@ stub I_RpcBindingInqWireIdForSnego -@ stub I_RpcBindingIsClientLocal -# 9x version of I_RpcBindingSetAsync has 3 arguments, not 2 -@ stdcall I_RpcBindingSetAsync(ptr ptr) -@ stub I_RpcBindingToStaticStringBindingW -@ stub I_RpcClearMutex -@ stub I_RpcConnectionInqSockBuffSize2 -@ stub I_RpcConnectionInqSockBuffSize -@ stub I_RpcConnectionSetSockBuffSize -@ stub I_RpcDeleteMutex -@ stub I_RpcEnableWmiTrace # wxp -@ stub I_RpcExceptionFilter # wxp -@ stdcall I_RpcFree(ptr) -@ stdcall I_RpcFreeBuffer(ptr) -@ stub I_RpcFreePipeBuffer -@ stub I_RpcGetAssociationContext -@ stdcall I_RpcGetBuffer(ptr) -@ stub I_RpcGetBufferWithObject -@ stdcall I_RpcGetCurrentCallHandle() -@ stub I_RpcGetExtendedError -@ stub I_RpcGetServerContextList -@ stub I_RpcGetThreadEvent # win9x -@ stub I_RpcGetThreadWindowHandle # win9x -@ stub I_RpcIfInqTransferSyntaxes -@ stub I_RpcLaunchDatagramReceiveThread # win9x -@ stub I_RpcLogEvent -@ stdcall I_RpcMapWin32Status(long) -@ stub I_RpcMonitorAssociation -@ stub I_RpcNegotiateTransferSyntax # wxp -@ stub I_RpcNsBindingSetEntryName -@ stub I_RpcNsBindingSetEntryNameA -@ stub I_RpcNsBindingSetEntryNameW -@ stub I_RpcNsInterfaceExported -@ stub I_RpcNsInterfaceUnexported -@ stub I_RpcParseSecurity -@ stub I_RpcPauseExecution -@ stub I_RpcProxyNewConnection # wxp -@ stub I_RpcReallocPipeBuffer -@ stdcall I_RpcReceive(ptr) -@ stub I_RpcRequestMutex -@ stdcall I_RpcSend(ptr) -@ stdcall I_RpcSendReceive(ptr) -@ stub I_RpcServerAllocateIpPort -@ stub I_RpcServerInqAddressChangeFn -@ stub I_RpcServerInqLocalConnAddress # wxp -@ stub I_RpcServerInqTransportType -@ stub I_RpcServerRegisterForwardFunction -@ stub I_RpcServerSetAddressChangeFn -@ stdcall I_RpcServerStartListening(ptr) # win9x -@ stdcall I_RpcServerStopListening() # win9x -@ stub I_RpcServerUnregisterEndpointA # win9x -@ stub I_RpcServerUnregisterEndpointW # win9x -@ stub I_RpcServerUseProtseq2A -@ stub I_RpcServerUseProtseq2W -@ stub I_RpcServerUseProtseqEp2A -@ stub I_RpcServerUseProtseqEp2W -@ stub I_RpcSetAssociationContext # win9x -@ stub I_RpcSetAsyncHandle -@ stub I_RpcSetServerContextList -@ stub I_RpcSetThreadParams # win9x -@ stub I_RpcSetWMsgEndpoint # NT4 -@ stub I_RpcSsDontSerializeContext -@ stub I_RpcStopMonitorAssociation -@ stub I_RpcSystemFunction001 # wxp (oh, brother!) -@ stub I_RpcTransCancelMigration # win9x -@ stub I_RpcTransClientMaxFrag # win9x -@ stub I_RpcTransClientReallocBuffer # win9x -@ stub I_RpcTransConnectionAllocatePacket -@ stub I_RpcTransConnectionFreePacket -@ stub I_RpcTransConnectionReallocPacket -@ stub I_RpcTransDatagramAllocate2 -@ stub I_RpcTransDatagramAllocate -@ stub I_RpcTransDatagramFree -@ stub I_RpcTransGetAddressList -@ stub I_RpcTransGetThreadEvent -@ stub I_RpcTransIoCancelled -@ stub I_RpcTransMaybeMakeReceiveAny # win9x -@ stub I_RpcTransMaybeMakeReceiveDirect # win9x -@ stub I_RpcTransPingServer # win9x -@ stub I_RpcTransServerFindConnection # win9x -@ stub I_RpcTransServerFreeBuffer # win9x -@ stub I_RpcTransServerMaxFrag # win9x -@ stub I_RpcTransServerNewConnection -@ stub I_RpcTransServerProtectThread # win9x -@ stub I_RpcTransServerReallocBuffer # win9x -@ stub I_RpcTransServerReceiveDirectReady # win9x -@ stub I_RpcTransServerUnprotectThread # win9x -@ stub I_RpcTurnOnEEInfoPropagation # wxp -@ stdcall I_RpcWindowProc(ptr long long long) # win9x -@ stub I_RpcltDebugSetPDUFilter -@ stub I_UuidCreate -@ stub MIDL_wchar_strcpy -@ stub MIDL_wchar_strlen -@ stub MesBufferHandleReset -@ stub MesDecodeBufferHandleCreate -@ stub MesDecodeIncrementalHandleCreate -@ stub MesEncodeDynBufferHandleCreate -@ stub MesEncodeFixedBufferHandleCreate -@ stub MesEncodeIncrementalHandleCreate -@ stub MesHandleFree -@ stub MesIncrementalHandleReset -@ stub MesInqProcEncodingId -@ stub MqGetContext # win9x -@ stub MqRegisterQueue # win9x -@ stdcall NDRCContextBinding(ptr) -@ stdcall NDRCContextMarshall(ptr ptr) -@ stdcall NDRCContextUnmarshall(ptr ptr ptr long) -@ stdcall NDRSContextMarshall2(ptr ptr ptr ptr ptr long) -@ stdcall NDRSContextMarshall(ptr ptr ptr) -@ stdcall NDRSContextMarshallEx(ptr ptr ptr ptr) -@ stdcall NDRSContextUnmarshall2(ptr ptr ptr ptr long) -@ stdcall NDRSContextUnmarshall(ptr ptr) -@ stdcall NDRSContextUnmarshallEx(ptr ptr ptr) -@ stub NDRcopy -@ stdcall NdrAllocate(ptr long) -@ stub NdrAsyncClientCall -@ stub NdrAsyncServerCall -@ stdcall NdrByteCountPointerBufferSize(ptr ptr ptr) -@ stdcall NdrByteCountPointerFree(ptr ptr ptr) -@ stdcall NdrByteCountPointerMarshall(ptr ptr ptr) -@ stdcall NdrByteCountPointerUnmarshall(ptr ptr ptr long) -@ stdcall NdrCStdStubBuffer2_Release(ptr ptr) -@ stdcall NdrCStdStubBuffer_Release(ptr ptr) -@ stdcall NdrClearOutParameters(ptr ptr ptr) -@ varargs NdrClientCall2(ptr ptr) -@ varargs NdrClientCall(ptr ptr) NdrClientCall2 -@ stdcall NdrClientContextMarshall(ptr ptr long) -@ stdcall NdrClientContextUnmarshall(ptr ptr ptr) -@ stub NdrClientInitialize -@ stdcall NdrClientInitializeNew(ptr ptr ptr long) -@ stdcall NdrComplexArrayBufferSize(ptr ptr ptr) -@ stdcall NdrComplexArrayFree(ptr ptr ptr) -@ stdcall NdrComplexArrayMarshall(ptr ptr ptr) -@ stdcall NdrComplexArrayMemorySize(ptr ptr) -@ stdcall NdrComplexArrayUnmarshall(ptr ptr ptr long) -@ stdcall NdrComplexStructBufferSize(ptr ptr ptr) -@ stdcall NdrComplexStructFree(ptr ptr ptr) -@ stdcall NdrComplexStructMarshall(ptr ptr ptr) -@ stdcall NdrComplexStructMemorySize(ptr ptr) -@ stdcall NdrComplexStructUnmarshall(ptr ptr ptr long) -@ stdcall NdrConformantArrayBufferSize(ptr ptr ptr) -@ stdcall NdrConformantArrayFree(ptr ptr ptr) -@ stdcall NdrConformantArrayMarshall(ptr ptr ptr) -@ stdcall NdrConformantArrayMemorySize(ptr ptr) -@ stdcall NdrConformantArrayUnmarshall(ptr ptr ptr long) -@ stdcall NdrConformantStringBufferSize(ptr ptr ptr) -@ stdcall NdrConformantStringMarshall(ptr ptr ptr) -@ stdcall NdrConformantStringMemorySize(ptr ptr) -@ stdcall NdrConformantStringUnmarshall(ptr ptr ptr long) -@ stdcall NdrConformantStructBufferSize(ptr ptr ptr) -@ stdcall NdrConformantStructFree(ptr ptr ptr) -@ stdcall NdrConformantStructMarshall(ptr ptr ptr) -@ stdcall NdrConformantStructMemorySize(ptr ptr) -@ stdcall NdrConformantStructUnmarshall(ptr ptr ptr long) -@ stdcall NdrConformantVaryingArrayBufferSize(ptr ptr ptr) -@ stdcall NdrConformantVaryingArrayFree(ptr ptr ptr) -@ stdcall NdrConformantVaryingArrayMarshall(ptr ptr ptr) -@ stdcall NdrConformantVaryingArrayMemorySize(ptr ptr) -@ stdcall NdrConformantVaryingArrayUnmarshall(ptr ptr ptr long) -@ stdcall NdrConformantVaryingStructBufferSize(ptr ptr ptr) -@ stdcall NdrConformantVaryingStructFree(ptr ptr ptr) -@ stdcall NdrConformantVaryingStructMarshall(ptr ptr ptr) -@ stdcall NdrConformantVaryingStructMemorySize(ptr ptr) -@ stdcall NdrConformantVaryingStructUnmarshall(ptr ptr ptr long) -@ stdcall NdrContextHandleInitialize(ptr ptr) -@ stdcall NdrContextHandleSize(ptr ptr ptr) -@ stdcall NdrConvert2(ptr ptr long) -@ stdcall NdrConvert(ptr ptr) -@ stub NdrCorrelationFree -@ stub NdrCorrelationInitialize -@ stub NdrCorrelationPass -@ stub NdrDcomAsyncClientCall -@ stub NdrDcomAsyncStubCall -@ stdcall NdrDllCanUnloadNow(ptr) -@ stdcall NdrDllGetClassObject(ptr ptr ptr ptr ptr ptr) -@ stdcall NdrDllRegisterProxy(long ptr ptr) -@ stdcall NdrDllUnregisterProxy(long ptr ptr) -@ stdcall NdrEncapsulatedUnionBufferSize(ptr ptr ptr) -@ stdcall NdrEncapsulatedUnionFree(ptr ptr ptr) -@ stdcall NdrEncapsulatedUnionMarshall(ptr ptr ptr) -@ stdcall NdrEncapsulatedUnionMemorySize(ptr ptr) -@ stdcall NdrEncapsulatedUnionUnmarshall(ptr ptr ptr long) -@ stdcall NdrFixedArrayBufferSize(ptr ptr ptr) -@ stdcall NdrFixedArrayFree(ptr ptr ptr) -@ stdcall NdrFixedArrayMarshall(ptr ptr ptr) -@ stdcall NdrFixedArrayMemorySize(ptr ptr) -@ stdcall NdrFixedArrayUnmarshall(ptr ptr ptr long) -@ stdcall NdrFreeBuffer(ptr) -@ stdcall NdrFullPointerFree(ptr ptr) -@ stdcall NdrFullPointerInsertRefId(ptr long ptr) -@ stdcall NdrFullPointerQueryPointer(ptr ptr long ptr) -@ stdcall NdrFullPointerQueryRefId(ptr long long ptr) -@ stdcall NdrFullPointerXlatFree(ptr) -@ stdcall NdrFullPointerXlatInit(long long) -@ stdcall NdrGetBuffer(ptr long ptr) -@ stub NdrGetDcomProtocolVersion -@ stub NdrGetPartialBuffer -@ stub NdrGetPipeBuffer -@ stub NdrGetSimpleTypeBufferAlignment # wxp -@ stub NdrGetSimpleTypeBufferSize # wxp -@ stub NdrGetSimpleTypeMemorySize # wxp -@ stub NdrGetTypeFlags # wxp -@ stub NdrGetUserMarshallInfo -@ stub NdrHardStructBufferSize #(ptr ptr ptr) -@ stub NdrHardStructFree #(ptr ptr ptr) -@ stub NdrHardStructMarshall #(ptr ptr ptr) -@ stub NdrHardStructMemorySize #(ptr ptr) -@ stub NdrHardStructUnmarshall #(ptr ptr ptr long) -@ stdcall NdrInterfacePointerBufferSize(ptr ptr ptr) -@ stdcall NdrInterfacePointerFree(ptr ptr ptr) -@ stdcall NdrInterfacePointerMarshall(ptr ptr ptr) -@ stdcall NdrInterfacePointerMemorySize(ptr ptr) -@ stdcall NdrInterfacePointerUnmarshall(ptr ptr ptr long) -@ stub NdrIsAppDoneWithPipes -@ stdcall NdrMapCommAndFaultStatus(ptr ptr ptr long) -@ stub NdrMarkNextActivePipe -@ stub NdrMesProcEncodeDecode2 -@ stub NdrMesProcEncodeDecode -@ stub NdrMesSimpleTypeAlignSize -@ stub NdrMesSimpleTypeDecode -@ stub NdrMesSimpleTypeEncode -@ stub NdrMesTypeAlignSize2 -@ stub NdrMesTypeAlignSize -@ stub NdrMesTypeDecode2 -@ stub NdrMesTypeDecode -@ stub NdrMesTypeEncode2 -@ stub NdrMesTypeEncode -@ stub NdrMesTypeFree2 -@ stdcall NdrNonConformantStringBufferSize(ptr ptr ptr) -@ stdcall NdrNonConformantStringMarshall(ptr ptr ptr) -@ stdcall NdrNonConformantStringMemorySize(ptr ptr) -@ stdcall NdrNonConformantStringUnmarshall(ptr ptr ptr long) -@ stdcall NdrNonEncapsulatedUnionBufferSize(ptr ptr ptr) -@ stdcall NdrNonEncapsulatedUnionFree(ptr ptr ptr) -@ stdcall NdrNonEncapsulatedUnionMarshall(ptr ptr ptr) -@ stdcall NdrNonEncapsulatedUnionMemorySize(ptr ptr) -@ stdcall NdrNonEncapsulatedUnionUnmarshall(ptr ptr ptr long) -@ stub NdrNsGetBuffer -@ stub NdrNsSendReceive -@ stdcall NdrOleAllocate(long) -@ stdcall NdrOleFree(ptr) -@ stub NdrOutInit # wxp -@ stub NdrPartialIgnoreClientBufferSize # wxp -@ stub NdrPartialIgnoreClientMarshall # wxp -@ stub NdrPartialIgnoreServerInitialize # wxp -@ stub NdrPartialIgnoreServerUnmarshall # wxp -@ stub NdrPipePull -@ stub NdrPipePush -@ stub NdrPipeSendReceive -@ stub NdrPipesDone -@ stub NdrPipesInitialize -@ stdcall NdrPointerBufferSize(ptr ptr ptr) -@ stdcall NdrPointerFree(ptr ptr ptr) -@ stdcall NdrPointerMarshall(ptr ptr ptr) -@ stdcall NdrPointerMemorySize(ptr ptr) -@ stdcall NdrPointerUnmarshall(ptr ptr ptr long) -@ stdcall NdrProxyErrorHandler(long) -@ stdcall NdrProxyFreeBuffer(ptr ptr) -@ stdcall NdrProxyGetBuffer(ptr ptr) -@ stdcall NdrProxyInitialize(ptr ptr ptr ptr long) -@ stdcall NdrProxySendReceive(ptr ptr) -@ stdcall NdrRangeUnmarshall(ptr ptr ptr long) -@ stub NdrRpcSmClientAllocate -@ stub NdrRpcSmClientFree -@ stub NdrRpcSmSetClientToOsf -@ stub NdrRpcSsDefaultAllocate -@ stub NdrRpcSsDefaultFree -@ stub NdrRpcSsDisableAllocate -@ stub NdrRpcSsEnableAllocate -@ stdcall NdrSendReceive(ptr ptr) -@ stdcall NdrServerCall2(ptr) -@ stub NdrServerCall -@ stdcall NdrServerContextMarshall(ptr ptr long) -@ stdcall NdrServerContextNewMarshall(ptr ptr ptr ptr) # wxp -@ stdcall NdrServerContextNewUnmarshall(ptr ptr) # wxp -@ stdcall NdrServerContextUnmarshall(ptr) -@ stub NdrServerInitialize -@ stub NdrServerInitializeMarshall -@ stdcall NdrServerInitializeNew(ptr ptr ptr) -@ stub NdrServerInitializePartial # wxp -@ stub NdrServerInitializeUnmarshall -@ stub NdrServerMarshall -@ stub NdrServerUnmarshall -@ stdcall NdrSimpleStructBufferSize(ptr ptr ptr) -@ stdcall NdrSimpleStructFree(ptr ptr ptr) -@ stdcall NdrSimpleStructMarshall(ptr ptr ptr) -@ stdcall NdrSimpleStructMemorySize(ptr ptr) -@ stdcall NdrSimpleStructUnmarshall(ptr ptr ptr long) -@ stdcall NdrSimpleTypeMarshall(ptr ptr long) -@ stdcall NdrSimpleTypeUnmarshall(ptr ptr long) -@ stdcall NdrStubCall2(ptr ptr ptr ptr) -@ stub NdrStubCall -@ stdcall NdrStubForwardingFunction(ptr ptr ptr ptr) -@ stdcall NdrStubGetBuffer(ptr ptr ptr) -@ stdcall NdrStubInitialize(ptr ptr ptr ptr) -@ stub NdrStubInitializeMarshall -@ stub NdrTypeFlags # wxp -@ stub NdrTypeFree # wxp -@ stub NdrTypeMarshall # wxp -@ stub NdrTypeSize # wxp -@ stub NdrTypeUnmarshall # wxp -@ stub NdrUnmarshallBasetypeInline # wxp -@ stdcall NdrUserMarshalBufferSize(ptr ptr ptr) -@ stdcall NdrUserMarshalFree(ptr ptr ptr) -@ stdcall NdrUserMarshalMarshall(ptr ptr ptr) -@ stdcall NdrUserMarshalMemorySize(ptr ptr) -@ stub NdrUserMarshalSimpleTypeConvert -@ stdcall NdrUserMarshalUnmarshall(ptr ptr ptr long) -@ stdcall NdrVaryingArrayBufferSize(ptr ptr ptr) -@ stdcall NdrVaryingArrayFree(ptr ptr ptr) -@ stdcall NdrVaryingArrayMarshall(ptr ptr ptr) -@ stdcall NdrVaryingArrayMemorySize(ptr ptr) -@ stdcall NdrVaryingArrayUnmarshall(ptr ptr ptr long) -@ stdcall NdrXmitOrRepAsBufferSize(ptr ptr ptr) -@ stdcall NdrXmitOrRepAsFree(ptr ptr ptr) -@ stdcall NdrXmitOrRepAsMarshall(ptr ptr ptr) -@ stdcall NdrXmitOrRepAsMemorySize(ptr ptr) -@ stdcall NdrXmitOrRepAsUnmarshall(ptr ptr ptr long) -@ stub NdrpCreateProxy # wxp -@ stub NdrpCreateStub # wxp -@ stub NdrpGetProcFormatString # wxp -@ stub NdrpGetTypeFormatString # wxp -@ stub NdrpGetTypeGenCookie # wxp -@ stub NdrpMemoryIncrement # wxp -@ stub NdrpReleaseTypeFormatString # wxp -@ stub NdrpReleaseTypeGenCookie # wxp -@ stub NdrpSetRpcSsDefaults -@ stub NdrpVarVtOfTypeDesc # wxp -@ stub PerformRpcInitialization -@ stub RpcAbortAsyncCall -@ stub RpcAsyncAbortCall -@ stub RpcAsyncCancelCall -@ stub RpcAsyncCompleteCall -@ stub RpcAsyncGetCallStatus -@ stub RpcAsyncInitializeHandle -@ stub RpcAsyncRegisterInfo -@ stdcall RpcBindingCopy(ptr ptr) -@ stdcall RpcBindingFree(ptr) -@ stdcall RpcBindingFromStringBindingA(str ptr) -@ stdcall RpcBindingFromStringBindingW(wstr ptr) -@ stub RpcBindingInqAuthClientA -@ stub RpcBindingInqAuthClientExA -@ stub RpcBindingInqAuthClientExW -@ stub RpcBindingInqAuthClientW -@ 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) -@ stdcall RpcBindingInqAuthInfoW(ptr ptr ptr ptr ptr ptr) -@ stdcall RpcBindingInqObject(ptr ptr) -@ stub RpcBindingInqOption -@ stub RpcBindingReset -@ stub RpcBindingServerFromClient -@ stdcall RpcBindingSetAuthInfoA(ptr str long long ptr long) -@ stdcall RpcBindingSetAuthInfoExA(ptr str long long ptr long ptr) -@ stdcall RpcBindingSetAuthInfoExW(ptr wstr long long ptr long ptr) -@ stdcall RpcBindingSetAuthInfoW(ptr wstr long long ptr long) -@ stdcall RpcBindingSetObject(ptr ptr) -@ stdcall RpcBindingSetOption(ptr long long) -@ stdcall RpcBindingToStringBindingA(ptr ptr) -@ stdcall RpcBindingToStringBindingW(ptr ptr) -@ stdcall RpcBindingVectorFree(ptr) -@ stub RpcCancelAsyncCall -@ stdcall RpcCancelThread(ptr) -@ stub RpcCancelThreadEx -@ stub RpcCertGeneratePrincipalNameA -@ stub RpcCertGeneratePrincipalNameW -@ stub RpcCompleteAsyncCall -@ stdcall RpcEpRegisterA(ptr ptr ptr str) -@ stub RpcEpRegisterNoReplaceA -@ stub RpcEpRegisterNoReplaceW -@ stub RpcEpRegisterW -@ stdcall RpcEpResolveBinding(ptr ptr) -@ stdcall RpcEpUnregister(ptr ptr ptr) -@ stub RpcErrorAddRecord # wxp -@ stub RpcErrorClearInformation # wxp -@ stub RpcErrorEndEnumeration # wxp -@ stub RpcErrorGetNextRecord # wxp -@ stub RpcErrorLoadErrorInfo # wxp -@ stub RpcErrorNumberOfRecords # wxp -@ stub RpcErrorResetEnumeration # wxp -@ stub RpcErrorSaveErrorInfo # wxp -@ stdcall RpcErrorStartEnumeration(ptr) -@ stub RpcFreeAuthorizationContext # wxp -@ stub RpcGetAsyncCallStatus -@ stub RpcIfIdVectorFree -@ stub RpcIfInqId -@ stdcall RpcImpersonateClient(ptr) -@ stub RpcInitializeAsyncHandle -@ stub RpcMgmtBindingInqParameter # win9x -@ stub RpcMgmtBindingSetParameter # win9x -@ stdcall RpcMgmtEnableIdleCleanup() -@ stdcall RpcMgmtEpEltInqBegin(ptr long ptr long ptr ptr) -@ stub RpcMgmtEpEltInqDone -@ stub RpcMgmtEpEltInqNextA -@ stub RpcMgmtEpEltInqNextW -@ stub RpcMgmtEpUnregister -@ stub RpcMgmtInqComTimeout -@ stub RpcMgmtInqDefaultProtectLevel -@ stdcall RpcMgmtInqIfIds(ptr ptr) -@ stub RpcMgmtInqParameter # win9x -@ stub RpcMgmtInqServerPrincNameA -@ stub RpcMgmtInqServerPrincNameW -@ stub RpcMgmtInqStats -@ stdcall RpcMgmtIsServerListening(ptr) -@ stub RpcMgmtSetAuthorizationFn -@ stdcall RpcMgmtSetCancelTimeout(long) -@ stdcall RpcMgmtSetComTimeout(ptr long) -@ stub RpcMgmtSetParameter # win9x -@ stdcall RpcMgmtSetServerStackSize(long) -@ stub RpcMgmtStatsVectorFree -@ stdcall RpcMgmtStopServerListening(ptr) -@ stdcall RpcMgmtWaitServerListen() -@ stub RpcNetworkInqProtseqsA -@ stub RpcNetworkInqProtseqsW -@ stdcall RpcNetworkIsProtseqValidA(ptr) -@ stdcall RpcNetworkIsProtseqValidW(ptr) -@ stub RpcNsBindingInqEntryNameA -@ stub RpcNsBindingInqEntryNameW -@ stub RpcObjectInqType -@ stub RpcObjectSetInqFn -@ stdcall RpcObjectSetType(ptr ptr) -@ stub RpcProtseqVectorFreeA -@ stub RpcProtseqVectorFreeW -@ stdcall RpcRaiseException(long) -@ stub RpcRegisterAsyncInfo -@ stdcall RpcRevertToSelf() -@ stdcall RpcRevertToSelfEx(ptr) -@ stdcall RpcServerInqBindings(ptr) -@ stub RpcServerInqCallAttributesA # wxp -@ stub RpcServerInqCallAttributesW # wxp -@ stub RpcServerInqDefaultPrincNameA -@ stub RpcServerInqDefaultPrincNameW -@ stub RpcServerInqIf -@ stdcall RpcServerListen(long long long) -@ stdcall RpcServerRegisterAuthInfoA(str long ptr ptr) -@ stdcall RpcServerRegisterAuthInfoW(wstr long ptr ptr) -@ stdcall RpcServerRegisterIf2(ptr ptr ptr long long long ptr) -@ stdcall RpcServerRegisterIf(ptr ptr ptr) -@ stdcall RpcServerRegisterIfEx(ptr ptr ptr long long ptr) -@ stub RpcServerTestCancel -@ stdcall RpcServerUnregisterIf(ptr ptr long) -@ stdcall RpcServerUnregisterIfEx(ptr ptr long) -@ stub RpcServerUseAllProtseqs -@ stub RpcServerUseAllProtseqsEx -@ stub RpcServerUseAllProtseqsIf -@ stub RpcServerUseAllProtseqsIfEx -@ stdcall RpcServerUseProtseqA(str long ptr) -@ stdcall RpcServerUseProtseqEpA(str long str ptr) -@ stdcall RpcServerUseProtseqEpExA(str long str ptr ptr) -@ stdcall RpcServerUseProtseqEpExW(wstr long wstr ptr ptr) -@ stdcall RpcServerUseProtseqEpW(wstr long wstr ptr) -@ stub RpcServerUseProtseqExA -@ stub RpcServerUseProtseqExW -@ stub RpcServerUseProtseqIfA -@ stub RpcServerUseProtseqIfExA -@ stub RpcServerUseProtseqIfExW -@ stub RpcServerUseProtseqIfW -@ stdcall RpcServerUseProtseqW(wstr long ptr) -@ stub RpcServerYield -@ stub RpcSmAllocate -@ stub RpcSmClientFree -@ stdcall RpcSmDestroyClientContext(ptr) -@ stub RpcSmDisableAllocate -@ stub RpcSmEnableAllocate -@ stub RpcSmFree -@ stub RpcSmGetThreadHandle -@ stub RpcSmSetClientAllocFree -@ stub RpcSmSetThreadHandle -@ stub RpcSmSwapClientAllocFree -@ stub RpcSsAllocate -@ stub RpcSsContextLockExclusive # wxp -@ stub RpcSsContextLockShared # wxp -@ stdcall RpcSsDestroyClientContext(ptr) -@ stub RpcSsDisableAllocate -@ stub RpcSsDontSerializeContext -@ stub RpcSsEnableAllocate -@ stub RpcSsFree -@ stub RpcSsGetContextBinding -@ stub RpcSsGetThreadHandle -@ stub RpcSsSetClientAllocFree -@ stub RpcSsSetThreadHandle -@ stub RpcSsSwapClientAllocFree -@ stdcall RpcStringBindingComposeA(str str str str str ptr) -@ stdcall RpcStringBindingComposeW(wstr wstr wstr wstr wstr ptr) -@ stdcall RpcStringBindingParseA(str ptr ptr ptr ptr ptr) -@ stdcall RpcStringBindingParseW(wstr ptr ptr ptr ptr ptr) -@ stdcall RpcStringFreeA(ptr) -@ stdcall RpcStringFreeW(ptr) -@ stub RpcTestCancel -@ stub RpcUserFree # wxp -@ stub SimpleTypeAlignment # wxp -@ stub SimpleTypeBufferSize # wxp -@ stub SimpleTypeMemorySize # wxp -@ stub StartServiceIfNecessary # win9x -@ stdcall TowerConstruct(ptr ptr ptr ptr ptr ptr) -@ stdcall TowerExplode(ptr ptr ptr ptr ptr ptr) -@ stdcall UuidCompare(ptr ptr ptr) -@ stdcall UuidCreate(ptr) -@ stdcall UuidCreateNil(ptr) -@ stdcall UuidCreateSequential(ptr) # win 2000 -@ stdcall UuidEqual(ptr ptr ptr) -@ stdcall UuidFromStringA(str ptr) -@ stdcall UuidFromStringW(wstr ptr) -@ stdcall UuidHash(ptr ptr) -@ stdcall UuidIsNil(ptr ptr) -@ stdcall UuidToStringA(ptr ptr) -@ stdcall UuidToStringW(ptr ptr) -@ stub char_array_from_ndr -@ stub char_from_ndr -@ stub data_from_ndr -@ stub data_into_ndr -@ stub data_size_ndr -@ stub double_array_from_ndr -@ stub double_from_ndr -@ stub enum_from_ndr -@ stub float_array_from_ndr -@ stub float_from_ndr -@ stub long_array_from_ndr -@ stub long_from_ndr -@ stub long_from_ndr_temp -@ stub pfnFreeRoutines # wxp -@ stub pfnMarshallRouteines # wxp -@ stub pfnSizeRoutines # wxp -@ stub pfnUnmarshallRouteines # wxp -@ stub short_array_from_ndr -@ stub short_from_ndr -@ stub short_from_ndr_temp -@ stub tree_into_ndr -@ stub tree_peek_ndr -@ stub tree_size_ndr +@ stdcall CreateProxyFromTypeInfo(ptr ptr ptr ptr ptr) +@ stub CreateStubFromTypeInfo +@ stdcall CStdStubBuffer_AddRef(ptr) +@ stdcall CStdStubBuffer_Connect(ptr ptr) +@ stdcall CStdStubBuffer_CountRefs(ptr) +@ stdcall CStdStubBuffer_DebugServerQueryInterface(ptr ptr) +@ stdcall CStdStubBuffer_DebugServerRelease(ptr ptr) +@ stdcall CStdStubBuffer_Disconnect(ptr) +@ stdcall CStdStubBuffer_Invoke(ptr ptr ptr) +@ stdcall CStdStubBuffer_IsIIDSupported(ptr ptr) +@ stdcall CStdStubBuffer_QueryInterface(ptr ptr ptr) +@ stub CreateServerInterfaceFromStub # wxp +@ stdcall DceErrorInqTextA (long ptr) +@ stdcall DceErrorInqTextW (long ptr) +@ stdcall -private DllRegisterServer() +@ stub GlobalMutexClearExternal +@ stub GlobalMutexRequestExternal +@ stdcall IUnknown_AddRef_Proxy(ptr) +@ stdcall IUnknown_QueryInterface_Proxy(ptr ptr ptr) +@ stdcall IUnknown_Release_Proxy(ptr) +@ stub I_RpcAbortAsyncCall +@ stdcall I_RpcAllocate(long) +@ stub I_RpcAsyncAbortCall +@ stub I_RpcAsyncSendReceive # NT4 +@ stub I_RpcAsyncSetHandle +@ stub I_RpcBCacheAllocate +@ stub I_RpcBCacheFree +@ stub I_RpcBindingCopy +@ stub I_RpcBindingInqConnId +@ stub I_RpcBindingInqDynamicEndPoint +@ stub I_RpcBindingInqDynamicEndPointA +@ stub I_RpcBindingInqDynamicEndPointW +@ stub I_RpcBindingInqLocalClientPID # wxp +@ stub I_RpcBindingInqSecurityContext +@ stub I_RpcBindingInqTransportType +@ stub I_RpcBindingInqWireIdForSnego +@ stub I_RpcBindingIsClientLocal +# 9x version of I_RpcBindingSetAsync has 3 arguments, not 2 +@ stdcall I_RpcBindingSetAsync(ptr ptr) +@ stub I_RpcBindingToStaticStringBindingW +@ stub I_RpcClearMutex +@ stub I_RpcConnectionInqSockBuffSize2 +@ stub I_RpcConnectionInqSockBuffSize +@ stub I_RpcConnectionSetSockBuffSize +@ stub I_RpcDeleteMutex +@ stub I_RpcEnableWmiTrace # wxp +@ stub I_RpcExceptionFilter # wxp +@ stdcall I_RpcFree(ptr) +@ stdcall I_RpcFreeBuffer(ptr) +@ stub I_RpcFreePipeBuffer +@ stub I_RpcGetAssociationContext +@ stdcall I_RpcGetBuffer(ptr) +@ stub I_RpcGetBufferWithObject +@ stdcall I_RpcGetCurrentCallHandle() +@ stub I_RpcGetExtendedError +@ stub I_RpcGetServerContextList +@ stub I_RpcGetThreadEvent # win9x +@ stub I_RpcGetThreadWindowHandle # win9x +@ stub I_RpcIfInqTransferSyntaxes +@ stub I_RpcLaunchDatagramReceiveThread # win9x +@ stub I_RpcLogEvent +@ stdcall I_RpcMapWin32Status(long) +@ stub I_RpcMonitorAssociation +@ stub I_RpcNegotiateTransferSyntax # wxp +@ stub I_RpcNsBindingSetEntryName +@ stub I_RpcNsBindingSetEntryNameA +@ stub I_RpcNsBindingSetEntryNameW +@ stub I_RpcNsInterfaceExported +@ stub I_RpcNsInterfaceUnexported +@ stub I_RpcParseSecurity +@ stub I_RpcPauseExecution +@ stub I_RpcProxyNewConnection # wxp +@ stub I_RpcReallocPipeBuffer +@ stdcall I_RpcReceive(ptr) +@ stub I_RpcRequestMutex +@ stdcall I_RpcSend(ptr) +@ stdcall I_RpcSendReceive(ptr) +@ stub I_RpcServerAllocateIpPort +@ stub I_RpcServerInqAddressChangeFn +@ stub I_RpcServerInqLocalConnAddress # wxp +@ stub I_RpcServerInqTransportType +@ stub I_RpcServerRegisterForwardFunction +@ stub I_RpcServerSetAddressChangeFn +@ stdcall I_RpcServerStartListening(ptr) # win9x +@ stdcall I_RpcServerStopListening() # win9x +@ stub I_RpcServerUnregisterEndpointA # win9x +@ stub I_RpcServerUnregisterEndpointW # win9x +@ stub I_RpcServerUseProtseq2A +@ stub I_RpcServerUseProtseq2W +@ stub I_RpcServerUseProtseqEp2A +@ stub I_RpcServerUseProtseqEp2W +@ stub I_RpcSetAssociationContext # win9x +@ stub I_RpcSetAsyncHandle +@ stub I_RpcSetServerContextList +@ stub I_RpcSetThreadParams # win9x +@ stub I_RpcSetWMsgEndpoint # NT4 +@ stub I_RpcSsDontSerializeContext +@ stub I_RpcStopMonitorAssociation +@ stub I_RpcSystemFunction001 # wxp (oh, brother!) +@ stub I_RpcTransCancelMigration # win9x +@ stub I_RpcTransClientMaxFrag # win9x +@ stub I_RpcTransClientReallocBuffer # win9x +@ stub I_RpcTransConnectionAllocatePacket +@ stub I_RpcTransConnectionFreePacket +@ stub I_RpcTransConnectionReallocPacket +@ stub I_RpcTransDatagramAllocate2 +@ stub I_RpcTransDatagramAllocate +@ stub I_RpcTransDatagramFree +@ stub I_RpcTransGetAddressList +@ stub I_RpcTransGetThreadEvent +@ stub I_RpcTransIoCancelled +@ stub I_RpcTransMaybeMakeReceiveAny # win9x +@ stub I_RpcTransMaybeMakeReceiveDirect # win9x +@ stub I_RpcTransPingServer # win9x +@ stub I_RpcTransServerFindConnection # win9x +@ stub I_RpcTransServerFreeBuffer # win9x +@ stub I_RpcTransServerMaxFrag # win9x +@ stub I_RpcTransServerNewConnection +@ stub I_RpcTransServerProtectThread # win9x +@ stub I_RpcTransServerReallocBuffer # win9x +@ stub I_RpcTransServerReceiveDirectReady # win9x +@ stub I_RpcTransServerUnprotectThread # win9x +@ stub I_RpcTurnOnEEInfoPropagation # wxp +@ stdcall I_RpcWindowProc(ptr long long long) # win9x +@ stub I_RpcltDebugSetPDUFilter +@ stub I_UuidCreate +@ stub MIDL_wchar_strcpy +@ stub MIDL_wchar_strlen +@ stub MesBufferHandleReset +@ stub MesDecodeBufferHandleCreate +@ stub MesDecodeIncrementalHandleCreate +@ stub MesEncodeDynBufferHandleCreate +@ stub MesEncodeFixedBufferHandleCreate +@ stub MesEncodeIncrementalHandleCreate +@ stub MesHandleFree +@ stub MesIncrementalHandleReset +@ stub MesInqProcEncodingId +@ stub MqGetContext # win9x +@ stub MqRegisterQueue # win9x +@ stdcall NDRCContextBinding(ptr) +@ stdcall NDRCContextMarshall(ptr ptr) +@ stdcall NDRCContextUnmarshall(ptr ptr ptr long) +@ stdcall NDRSContextMarshall2(ptr ptr ptr ptr ptr long) +@ stdcall NDRSContextMarshall(ptr ptr ptr) +@ stdcall NDRSContextMarshallEx(ptr ptr ptr ptr) +@ stdcall NDRSContextUnmarshall2(ptr ptr ptr ptr long) +@ stdcall NDRSContextUnmarshall(ptr ptr) +@ stdcall NDRSContextUnmarshallEx(ptr ptr ptr) +@ stub NDRcopy +@ stdcall NdrAllocate(ptr long) +@ stub NdrAsyncClientCall +@ stub NdrAsyncServerCall +@ stdcall NdrByteCountPointerBufferSize(ptr ptr ptr) +@ stdcall NdrByteCountPointerFree(ptr ptr ptr) +@ stdcall NdrByteCountPointerMarshall(ptr ptr ptr) +@ stdcall NdrByteCountPointerUnmarshall(ptr ptr ptr long) +@ stdcall NdrCStdStubBuffer2_Release(ptr ptr) +@ stdcall NdrCStdStubBuffer_Release(ptr ptr) +@ stdcall NdrClearOutParameters(ptr ptr ptr) +@ varargs NdrClientCall2(ptr ptr) +@ varargs NdrClientCall(ptr ptr) NdrClientCall2 +@ stdcall NdrClientContextMarshall(ptr ptr long) +@ stdcall NdrClientContextUnmarshall(ptr ptr ptr) +@ stub NdrClientInitialize +@ stdcall NdrClientInitializeNew(ptr ptr ptr long) +@ stdcall NdrComplexArrayBufferSize(ptr ptr ptr) +@ stdcall NdrComplexArrayFree(ptr ptr ptr) +@ stdcall NdrComplexArrayMarshall(ptr ptr ptr) +@ stdcall NdrComplexArrayMemorySize(ptr ptr) +@ stdcall NdrComplexArrayUnmarshall(ptr ptr ptr long) +@ stdcall NdrComplexStructBufferSize(ptr ptr ptr) +@ stdcall NdrComplexStructFree(ptr ptr ptr) +@ stdcall NdrComplexStructMarshall(ptr ptr ptr) +@ stdcall NdrComplexStructMemorySize(ptr ptr) +@ stdcall NdrComplexStructUnmarshall(ptr ptr ptr long) +@ stdcall NdrConformantArrayBufferSize(ptr ptr ptr) +@ stdcall NdrConformantArrayFree(ptr ptr ptr) +@ stdcall NdrConformantArrayMarshall(ptr ptr ptr) +@ stdcall NdrConformantArrayMemorySize(ptr ptr) +@ stdcall NdrConformantArrayUnmarshall(ptr ptr ptr long) +@ stdcall NdrConformantStringBufferSize(ptr ptr ptr) +@ stdcall NdrConformantStringMarshall(ptr ptr ptr) +@ stdcall NdrConformantStringMemorySize(ptr ptr) +@ stdcall NdrConformantStringUnmarshall(ptr ptr ptr long) +@ stdcall NdrConformantStructBufferSize(ptr ptr ptr) +@ stdcall NdrConformantStructFree(ptr ptr ptr) +@ stdcall NdrConformantStructMarshall(ptr ptr ptr) +@ stdcall NdrConformantStructMemorySize(ptr ptr) +@ stdcall NdrConformantStructUnmarshall(ptr ptr ptr long) +@ stdcall NdrConformantVaryingArrayBufferSize(ptr ptr ptr) +@ stdcall NdrConformantVaryingArrayFree(ptr ptr ptr) +@ stdcall NdrConformantVaryingArrayMarshall(ptr ptr ptr) +@ stdcall NdrConformantVaryingArrayMemorySize(ptr ptr) +@ stdcall NdrConformantVaryingArrayUnmarshall(ptr ptr ptr long) +@ stdcall NdrConformantVaryingStructBufferSize(ptr ptr ptr) +@ stdcall NdrConformantVaryingStructFree(ptr ptr ptr) +@ stdcall NdrConformantVaryingStructMarshall(ptr ptr ptr) +@ stdcall NdrConformantVaryingStructMemorySize(ptr ptr) +@ stdcall NdrConformantVaryingStructUnmarshall(ptr ptr ptr long) +@ stdcall NdrContextHandleInitialize(ptr ptr) +@ stdcall NdrContextHandleSize(ptr ptr ptr) +@ stdcall NdrConvert2(ptr ptr long) +@ stdcall NdrConvert(ptr ptr) +@ stub NdrCorrelationFree +@ stub NdrCorrelationInitialize +@ stub NdrCorrelationPass +@ stub NdrDcomAsyncClientCall +@ stub NdrDcomAsyncStubCall +@ stdcall NdrDllCanUnloadNow(ptr) +@ stdcall NdrDllGetClassObject(ptr ptr ptr ptr ptr ptr) +@ stdcall NdrDllRegisterProxy(long ptr ptr) +@ stdcall NdrDllUnregisterProxy(long ptr ptr) +@ stdcall NdrEncapsulatedUnionBufferSize(ptr ptr ptr) +@ stdcall NdrEncapsulatedUnionFree(ptr ptr ptr) +@ stdcall NdrEncapsulatedUnionMarshall(ptr ptr ptr) +@ stdcall NdrEncapsulatedUnionMemorySize(ptr ptr) +@ stdcall NdrEncapsulatedUnionUnmarshall(ptr ptr ptr long) +@ stdcall NdrFixedArrayBufferSize(ptr ptr ptr) +@ stdcall NdrFixedArrayFree(ptr ptr ptr) +@ stdcall NdrFixedArrayMarshall(ptr ptr ptr) +@ stdcall NdrFixedArrayMemorySize(ptr ptr) +@ stdcall NdrFixedArrayUnmarshall(ptr ptr ptr long) +@ stdcall NdrFreeBuffer(ptr) +@ stdcall NdrFullPointerFree(ptr ptr) +@ stdcall NdrFullPointerInsertRefId(ptr long ptr) +@ stdcall NdrFullPointerQueryPointer(ptr ptr long ptr) +@ stdcall NdrFullPointerQueryRefId(ptr long long ptr) +@ stdcall NdrFullPointerXlatFree(ptr) +@ stdcall NdrFullPointerXlatInit(long long) +@ stdcall NdrGetBuffer(ptr long ptr) +@ stub NdrGetDcomProtocolVersion +@ stub NdrGetPartialBuffer +@ stub NdrGetPipeBuffer +@ stub NdrGetSimpleTypeBufferAlignment # wxp +@ stub NdrGetSimpleTypeBufferSize # wxp +@ stub NdrGetSimpleTypeMemorySize # wxp +@ stub NdrGetTypeFlags # wxp +@ stub NdrGetUserMarshallInfo +@ stub NdrHardStructBufferSize #(ptr ptr ptr) +@ stub NdrHardStructFree #(ptr ptr ptr) +@ stub NdrHardStructMarshall #(ptr ptr ptr) +@ stub NdrHardStructMemorySize #(ptr ptr) +@ stub NdrHardStructUnmarshall #(ptr ptr ptr long) +@ stdcall NdrInterfacePointerBufferSize(ptr ptr ptr) +@ stdcall NdrInterfacePointerFree(ptr ptr ptr) +@ stdcall NdrInterfacePointerMarshall(ptr ptr ptr) +@ stdcall NdrInterfacePointerMemorySize(ptr ptr) +@ stdcall NdrInterfacePointerUnmarshall(ptr ptr ptr long) +@ stub NdrIsAppDoneWithPipes +@ stdcall NdrMapCommAndFaultStatus(ptr ptr ptr long) +@ stub NdrMarkNextActivePipe +@ stub NdrMesProcEncodeDecode2 +@ stub NdrMesProcEncodeDecode +@ stub NdrMesSimpleTypeAlignSize +@ stub NdrMesSimpleTypeDecode +@ stub NdrMesSimpleTypeEncode +@ stub NdrMesTypeAlignSize2 +@ stub NdrMesTypeAlignSize +@ stub NdrMesTypeDecode2 +@ stub NdrMesTypeDecode +@ stub NdrMesTypeEncode2 +@ stub NdrMesTypeEncode +@ stub NdrMesTypeFree2 +@ stdcall NdrNonConformantStringBufferSize(ptr ptr ptr) +@ stdcall NdrNonConformantStringMarshall(ptr ptr ptr) +@ stdcall NdrNonConformantStringMemorySize(ptr ptr) +@ stdcall NdrNonConformantStringUnmarshall(ptr ptr ptr long) +@ stdcall NdrNonEncapsulatedUnionBufferSize(ptr ptr ptr) +@ stdcall NdrNonEncapsulatedUnionFree(ptr ptr ptr) +@ stdcall NdrNonEncapsulatedUnionMarshall(ptr ptr ptr) +@ stdcall NdrNonEncapsulatedUnionMemorySize(ptr ptr) +@ stdcall NdrNonEncapsulatedUnionUnmarshall(ptr ptr ptr long) +@ stub NdrNsGetBuffer +@ stub NdrNsSendReceive +@ stdcall NdrOleAllocate(long) +@ stdcall NdrOleFree(ptr) +@ stub NdrOutInit # wxp +@ stub NdrPartialIgnoreClientBufferSize # wxp +@ stub NdrPartialIgnoreClientMarshall # wxp +@ stub NdrPartialIgnoreServerInitialize # wxp +@ stub NdrPartialIgnoreServerUnmarshall # wxp +@ stub NdrPipePull +@ stub NdrPipePush +@ stub NdrPipeSendReceive +@ stub NdrPipesDone +@ stub NdrPipesInitialize +@ stdcall NdrPointerBufferSize(ptr ptr ptr) +@ stdcall NdrPointerFree(ptr ptr ptr) +@ stdcall NdrPointerMarshall(ptr ptr ptr) +@ stdcall NdrPointerMemorySize(ptr ptr) +@ stdcall NdrPointerUnmarshall(ptr ptr ptr long) +@ stdcall NdrProxyErrorHandler(long) +@ stdcall NdrProxyFreeBuffer(ptr ptr) +@ stdcall NdrProxyGetBuffer(ptr ptr) +@ stdcall NdrProxyInitialize(ptr ptr ptr ptr long) +@ stdcall NdrProxySendReceive(ptr ptr) +@ stdcall NdrRangeUnmarshall(ptr ptr ptr long) +@ stub NdrRpcSmClientAllocate +@ stub NdrRpcSmClientFree +@ stub NdrRpcSmSetClientToOsf +@ stub NdrRpcSsDefaultAllocate +@ stub NdrRpcSsDefaultFree +@ stub NdrRpcSsDisableAllocate +@ stub NdrRpcSsEnableAllocate +@ stdcall NdrSendReceive(ptr ptr) +@ stdcall NdrServerCall2(ptr) +@ stub NdrServerCall +@ stdcall NdrServerContextMarshall(ptr ptr long) +@ stdcall NdrServerContextNewMarshall(ptr ptr ptr ptr) # wxp +@ stdcall NdrServerContextNewUnmarshall(ptr ptr) # wxp +@ stdcall NdrServerContextUnmarshall(ptr) +@ stub NdrServerInitialize +@ stub NdrServerInitializeMarshall +@ stdcall NdrServerInitializeNew(ptr ptr ptr) +@ stub NdrServerInitializePartial # wxp +@ stub NdrServerInitializeUnmarshall +@ stub NdrServerMarshall +@ stub NdrServerUnmarshall +@ stdcall NdrSimpleStructBufferSize(ptr ptr ptr) +@ stdcall NdrSimpleStructFree(ptr ptr ptr) +@ stdcall NdrSimpleStructMarshall(ptr ptr ptr) +@ stdcall NdrSimpleStructMemorySize(ptr ptr) +@ stdcall NdrSimpleStructUnmarshall(ptr ptr ptr long) +@ stdcall NdrSimpleTypeMarshall(ptr ptr long) +@ stdcall NdrSimpleTypeUnmarshall(ptr ptr long) +@ stdcall NdrStubCall2(ptr ptr ptr ptr) +@ stub NdrStubCall +@ stdcall NdrStubForwardingFunction(ptr ptr ptr ptr) +@ stdcall NdrStubGetBuffer(ptr ptr ptr) +@ stdcall NdrStubInitialize(ptr ptr ptr ptr) +@ stub NdrStubInitializeMarshall +@ stub NdrTypeFlags # wxp +@ stub NdrTypeFree # wxp +@ stub NdrTypeMarshall # wxp +@ stub NdrTypeSize # wxp +@ stub NdrTypeUnmarshall # wxp +@ stub NdrUnmarshallBasetypeInline # wxp +@ stdcall NdrUserMarshalBufferSize(ptr ptr ptr) +@ stdcall NdrUserMarshalFree(ptr ptr ptr) +@ stdcall NdrUserMarshalMarshall(ptr ptr ptr) +@ stdcall NdrUserMarshalMemorySize(ptr ptr) +@ stub NdrUserMarshalSimpleTypeConvert +@ stdcall NdrUserMarshalUnmarshall(ptr ptr ptr long) +@ stdcall NdrVaryingArrayBufferSize(ptr ptr ptr) +@ stdcall NdrVaryingArrayFree(ptr ptr ptr) +@ stdcall NdrVaryingArrayMarshall(ptr ptr ptr) +@ stdcall NdrVaryingArrayMemorySize(ptr ptr) +@ stdcall NdrVaryingArrayUnmarshall(ptr ptr ptr long) +@ stdcall NdrXmitOrRepAsBufferSize(ptr ptr ptr) +@ stdcall NdrXmitOrRepAsFree(ptr ptr ptr) +@ stdcall NdrXmitOrRepAsMarshall(ptr ptr ptr) +@ stdcall NdrXmitOrRepAsMemorySize(ptr ptr) +@ stdcall NdrXmitOrRepAsUnmarshall(ptr ptr ptr long) +@ stub NdrpCreateProxy # wxp +@ stub NdrpCreateStub # wxp +@ stub NdrpGetProcFormatString # wxp +@ stub NdrpGetTypeFormatString # wxp +@ stub NdrpGetTypeGenCookie # wxp +@ stub NdrpMemoryIncrement # wxp +@ stub NdrpReleaseTypeFormatString # wxp +@ stub NdrpReleaseTypeGenCookie # wxp +@ stub NdrpSetRpcSsDefaults +@ stub NdrpVarVtOfTypeDesc # wxp +@ stub PerformRpcInitialization +@ stub RpcAbortAsyncCall +@ stub RpcAsyncAbortCall +@ stub RpcAsyncCancelCall +@ stub RpcAsyncCompleteCall +@ stub RpcAsyncGetCallStatus +@ stub RpcAsyncInitializeHandle +@ stub RpcAsyncRegisterInfo +@ stdcall RpcBindingCopy(ptr ptr) +@ stdcall RpcBindingFree(ptr) +@ stdcall RpcBindingFromStringBindingA(str ptr) +@ stdcall RpcBindingFromStringBindingW(wstr ptr) +@ stub RpcBindingInqAuthClientA +@ stub RpcBindingInqAuthClientExA +@ stub RpcBindingInqAuthClientExW +@ stub RpcBindingInqAuthClientW +@ 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) +@ stdcall RpcBindingInqAuthInfoW(ptr ptr ptr ptr ptr ptr) +@ stdcall RpcBindingInqObject(ptr ptr) +@ stub RpcBindingInqOption +@ stub RpcBindingReset +@ stub RpcBindingServerFromClient +@ stdcall RpcBindingSetAuthInfoA(ptr str long long ptr long) +@ stdcall RpcBindingSetAuthInfoExA(ptr str long long ptr long ptr) +@ stdcall RpcBindingSetAuthInfoExW(ptr wstr long long ptr long ptr) +@ stdcall RpcBindingSetAuthInfoW(ptr wstr long long ptr long) +@ stdcall RpcBindingSetObject(ptr ptr) +@ stdcall RpcBindingSetOption(ptr long long) +@ stdcall RpcBindingToStringBindingA(ptr ptr) +@ stdcall RpcBindingToStringBindingW(ptr ptr) +@ stdcall RpcBindingVectorFree(ptr) +@ stub RpcCancelAsyncCall +@ stdcall RpcCancelThread(ptr) +@ stub RpcCancelThreadEx +@ stub RpcCertGeneratePrincipalNameA +@ stub RpcCertGeneratePrincipalNameW +@ stub RpcCompleteAsyncCall +@ stdcall RpcEpRegisterA(ptr ptr ptr str) +@ stub RpcEpRegisterNoReplaceA +@ stub RpcEpRegisterNoReplaceW +@ stub RpcEpRegisterW +@ stdcall RpcEpResolveBinding(ptr ptr) +@ stdcall RpcEpUnregister(ptr ptr ptr) +@ stub RpcErrorAddRecord # wxp +@ stub RpcErrorClearInformation # wxp +@ stub RpcErrorEndEnumeration # wxp +@ stub RpcErrorGetNextRecord # wxp +@ stub RpcErrorLoadErrorInfo # wxp +@ stub RpcErrorNumberOfRecords # wxp +@ stub RpcErrorResetEnumeration # wxp +@ stub RpcErrorSaveErrorInfo # wxp +@ stdcall RpcErrorStartEnumeration(ptr) +@ stub RpcFreeAuthorizationContext # wxp +@ stub RpcGetAsyncCallStatus +@ stub RpcIfIdVectorFree +@ stub RpcIfInqId +@ stdcall RpcImpersonateClient(ptr) +@ stub RpcInitializeAsyncHandle +@ stub RpcMgmtBindingInqParameter # win9x +@ stub RpcMgmtBindingSetParameter # win9x +@ stdcall RpcMgmtEnableIdleCleanup() +@ stdcall RpcMgmtEpEltInqBegin(ptr long ptr long ptr ptr) +@ stub RpcMgmtEpEltInqDone +@ stub RpcMgmtEpEltInqNextA +@ stub RpcMgmtEpEltInqNextW +@ stub RpcMgmtEpUnregister +@ stub RpcMgmtInqComTimeout +@ stub RpcMgmtInqDefaultProtectLevel +@ stdcall RpcMgmtInqIfIds(ptr ptr) +@ stub RpcMgmtInqParameter # win9x +@ stub RpcMgmtInqServerPrincNameA +@ stub RpcMgmtInqServerPrincNameW +@ stub RpcMgmtInqStats +@ stdcall RpcMgmtIsServerListening(ptr) +@ stub RpcMgmtSetAuthorizationFn +@ stdcall RpcMgmtSetCancelTimeout(long) +@ stdcall RpcMgmtSetComTimeout(ptr long) +@ stub RpcMgmtSetParameter # win9x +@ stdcall RpcMgmtSetServerStackSize(long) +@ stub RpcMgmtStatsVectorFree +@ stdcall RpcMgmtStopServerListening(ptr) +@ stdcall RpcMgmtWaitServerListen() +@ stub RpcNetworkInqProtseqsA +@ stub RpcNetworkInqProtseqsW +@ stdcall RpcNetworkIsProtseqValidA(ptr) +@ stdcall RpcNetworkIsProtseqValidW(ptr) +@ stub RpcNsBindingInqEntryNameA +@ stub RpcNsBindingInqEntryNameW +@ stub RpcObjectInqType +@ stub RpcObjectSetInqFn +@ stdcall RpcObjectSetType(ptr ptr) +@ stub RpcProtseqVectorFreeA +@ stub RpcProtseqVectorFreeW +@ stdcall RpcRaiseException(long) +@ stub RpcRegisterAsyncInfo +@ stdcall RpcRevertToSelf() +@ stdcall RpcRevertToSelfEx(ptr) +@ stdcall RpcServerInqBindings(ptr) +@ stub RpcServerInqCallAttributesA # wxp +@ stub RpcServerInqCallAttributesW # wxp +@ stub RpcServerInqDefaultPrincNameA +@ stub RpcServerInqDefaultPrincNameW +@ stub RpcServerInqIf +@ stdcall RpcServerListen(long long long) +@ stdcall RpcServerRegisterAuthInfoA(str long ptr ptr) +@ stdcall RpcServerRegisterAuthInfoW(wstr long ptr ptr) +@ stdcall RpcServerRegisterIf2(ptr ptr ptr long long long ptr) +@ stdcall RpcServerRegisterIf(ptr ptr ptr) +@ stdcall RpcServerRegisterIfEx(ptr ptr ptr long long ptr) +@ stub RpcServerTestCancel +@ stdcall RpcServerUnregisterIf(ptr ptr long) +@ stdcall RpcServerUnregisterIfEx(ptr ptr long) +@ stub RpcServerUseAllProtseqs +@ stub RpcServerUseAllProtseqsEx +@ stub RpcServerUseAllProtseqsIf +@ stub RpcServerUseAllProtseqsIfEx +@ stdcall RpcServerUseProtseqA(str long ptr) +@ stdcall RpcServerUseProtseqEpA(str long str ptr) +@ stdcall RpcServerUseProtseqEpExA(str long str ptr ptr) +@ stdcall RpcServerUseProtseqEpExW(wstr long wstr ptr ptr) +@ stdcall RpcServerUseProtseqEpW(wstr long wstr ptr) +@ stub RpcServerUseProtseqExA +@ stub RpcServerUseProtseqExW +@ stub RpcServerUseProtseqIfA +@ stub RpcServerUseProtseqIfExA +@ stub RpcServerUseProtseqIfExW +@ stub RpcServerUseProtseqIfW +@ stdcall RpcServerUseProtseqW(wstr long ptr) +@ stub RpcServerYield +@ stub RpcSmAllocate +@ stub RpcSmClientFree +@ stdcall RpcSmDestroyClientContext(ptr) +@ stub RpcSmDisableAllocate +@ stub RpcSmEnableAllocate +@ stub RpcSmFree +@ stub RpcSmGetThreadHandle +@ stub RpcSmSetClientAllocFree +@ stub RpcSmSetThreadHandle +@ stub RpcSmSwapClientAllocFree +@ stub RpcSsAllocate +@ stub RpcSsContextLockExclusive # wxp +@ stub RpcSsContextLockShared # wxp +@ stdcall RpcSsDestroyClientContext(ptr) +@ stub RpcSsDisableAllocate +@ stub RpcSsDontSerializeContext +@ stub RpcSsEnableAllocate +@ stub RpcSsFree +@ stub RpcSsGetContextBinding +@ stub RpcSsGetThreadHandle +@ stub RpcSsSetClientAllocFree +@ stub RpcSsSetThreadHandle +@ stub RpcSsSwapClientAllocFree +@ stdcall RpcStringBindingComposeA(str str str str str ptr) +@ stdcall RpcStringBindingComposeW(wstr wstr wstr wstr wstr ptr) +@ stdcall RpcStringBindingParseA(str ptr ptr ptr ptr ptr) +@ stdcall RpcStringBindingParseW(wstr ptr ptr ptr ptr ptr) +@ stdcall RpcStringFreeA(ptr) +@ stdcall RpcStringFreeW(ptr) +@ stub RpcTestCancel +@ stub RpcUserFree # wxp +@ stub SimpleTypeAlignment # wxp +@ stub SimpleTypeBufferSize # wxp +@ stub SimpleTypeMemorySize # wxp +@ stub StartServiceIfNecessary # win9x +@ stdcall TowerConstruct(ptr ptr ptr ptr ptr ptr) +@ stdcall TowerExplode(ptr ptr ptr ptr ptr ptr) +@ stdcall UuidCompare(ptr ptr ptr) +@ stdcall UuidCreate(ptr) +@ stdcall UuidCreateNil(ptr) +@ stdcall UuidCreateSequential(ptr) # win 2000 +@ stdcall UuidEqual(ptr ptr ptr) +@ stdcall UuidFromStringA(str ptr) +@ stdcall UuidFromStringW(wstr ptr) +@ stdcall UuidHash(ptr ptr) +@ stdcall UuidIsNil(ptr ptr) +@ stdcall UuidToStringA(ptr ptr) +@ stdcall UuidToStringW(ptr ptr) +@ stub char_array_from_ndr +@ stub char_from_ndr +@ stub data_from_ndr +@ stub data_into_ndr +@ stub data_size_ndr +@ stub double_array_from_ndr +@ stub double_from_ndr +@ stub enum_from_ndr +@ stub float_array_from_ndr +@ stub float_from_ndr +@ stub long_array_from_ndr +@ stub long_from_ndr +@ stub long_from_ndr_temp +@ stub pfnFreeRoutines # wxp +@ stub pfnMarshallRouteines # wxp +@ stub pfnSizeRoutines # wxp +@ stub pfnUnmarshallRouteines # wxp +@ stub short_array_from_ndr +@ stub short_from_ndr +@ stub short_from_ndr_temp +@ stub tree_into_ndr +@ stub tree_peek_ndr +@ stub tree_size_ndr diff --git a/reactos/dll/win32/rpcrt4_new/rpcrt4_main.c b/reactos/dll/win32/rpcrt4_new/rpcrt4_main.c index 8ce6db906e9..e48cf586988 100644 --- a/reactos/dll/win32/rpcrt4_new/rpcrt4_main.c +++ b/reactos/dll/win32/rpcrt4_new/rpcrt4_main.c @@ -1,1025 +1,1025 @@ -/* - * RPCRT4 - * - * Copyright 2000 Huw D M Davies for CodeWeavers - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - * - * WINE RPC TODO's (and a few TODONT's) - * - * - Ove's decreasingly incomplete widl is an IDL compiler for wine. For widl - * to be wine's only IDL compiler, a fair bit of work remains to be done. - * until then we have used some midl-generated stuff. (What?) - * widl currently doesn't generate stub/proxy files required by wine's (O)RPC - * capabilities -- nor does it make those lovely format strings :( - * The MS MIDL compiler does some really esoteric stuff. Of course Ove has - * started with the less esoteric stuff. There are also lots of nice - * comments in there if you want to flex your bison and help build this monster. - * - * - RPC has a quite featureful error handling mechanism; basically none of this is - * implemented right now. We also have deficiencies on the compiler side, where - * wine's __TRY / __EXCEPT / __FINALLY macros are not even used for RpcTryExcept & co, - * due to syntactic differences! (we can fix it with widl by using __TRY) - * - * - There are several different memory allocation schemes for MSRPC. - * I don't even understand what they all are yet, much less have them - * properly implemented. Surely we are supposed to be doing something with - * the user-provided allocation/deallocation functions, but so far, - * I don't think we are doing this... - * - * - MSRPC provides impersonation capabilities which currently are not possible - * to implement in wine. At the very least we should implement the authorization - * API's & gracefully ignore the irrelevant stuff (to an extent we already do). - * - * - Some transports are not yet implemented. The existing transport implementations - * are incomplete and may be bug-infested. - * - * - The various transports that we do support ought to be supported in a more - * object-oriented manner, as in DCE's RPC implementation, instead of cluttering - * up the code with conditionals like we do now. - * - * - Data marshalling: So far, only the beginnings of a full implementation - * exist in wine. NDR protocol itself is documented, but the MS API's to - * convert data-types in memory into NDR are not. This is challenging work, - * and has supposedly been "at the top of Greg's queue" for several months now. - * - * - ORPC is RPC for OLE; once we have a working RPC framework, we can - * use it to implement out-of-process OLE client/server communications. - * ATM there is maybe a disconnect between the marshalling in the OLE DLLs - * and the marshalling going on here [TODO: well, is there or not?] - * - * - In-source API Documentation, at least for those functions which we have - * implemented, but preferably for everything we can document, would be nice, - * since some of this stuff is quite obscure. - * - * - Name services... [TODO: what about them] - * - * - Protocol Towers: Totally unimplemented.... I think. - * - * - Context Handle Rundown: whatever that is. - * - * - Nested RPC's: Totally unimplemented. - * - * - Statistics: we are supposed to be keeping various counters. we aren't. - * - * - Async RPC: Unimplemented. - * - * - XML/http RPC: Somewhere there's an XML fiend that wants to do this! Betcha - * we could use these as a transport for RPC's across computers without a - * permissions and/or licensing crisis. - * - * - The NT "ports" API, aka LPC. Greg claims this is on his radar. Might (or - * might not) enable users to get some kind of meaningful result out of - * NT-based native rpcrt4's. Commonly-used transport for self-to-self RPC's. - * - * - ...? More stuff I haven't thought of. If you think of more RPC todo's - * drop me an e-mail or send a patch to the - * wine-patches mailing list. - */ - -#include "config.h" - -#include -#include -#include -#include - -#include "windef.h" -#include "winerror.h" -#include "winbase.h" -#include "winuser.h" -#include "winnt.h" -#include "winternl.h" -#include "iptypes.h" -#include "iphlpapi.h" -#include "wine/unicode.h" -#include "rpc.h" - -#include "ole2.h" -#include "rpcndr.h" -#include "rpcproxy.h" - -#include "rpc_binding.h" -#include "rpcss_np_client.h" - -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(rpc); - -static UUID uuid_nil; -static HANDLE master_mutex; - -HANDLE RPCRT4_GetMasterMutex(void) -{ - return master_mutex; -} - -static CRITICAL_SECTION uuid_cs; -static CRITICAL_SECTION_DEBUG critsect_debug = -{ - 0, 0, &uuid_cs, - { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList }, - 0, 0, { (DWORD_PTR)(__FILE__ ": uuid_cs") } -}; -static CRITICAL_SECTION uuid_cs = { &critsect_debug, -1, 0, 0, 0, 0 }; - -static CRITICAL_SECTION threaddata_cs; -static CRITICAL_SECTION_DEBUG threaddata_cs_debug = -{ - 0, 0, &threaddata_cs, - { &threaddata_cs_debug.ProcessLocksList, &threaddata_cs_debug.ProcessLocksList }, - 0, 0, { (DWORD_PTR)(__FILE__ ": threaddata_cs") } -}; -static CRITICAL_SECTION threaddata_cs = { &threaddata_cs_debug, -1, 0, 0, 0, 0 }; - -struct list threaddata_list = LIST_INIT(threaddata_list); - -struct context_handle_list -{ - struct context_handle_list *next; - NDR_SCONTEXT context_handle; -}; - -struct threaddata -{ - struct list entry; - CRITICAL_SECTION cs; - DWORD thread_id; - RpcConnection *connection; - RpcBinding *server_binding; - struct context_handle_list *context_handle_list; -}; - -/*********************************************************************** - * DllMain - * - * PARAMS - * hinstDLL [I] handle to the DLL's instance - * fdwReason [I] - * lpvReserved [I] reserved, must be NULL - * - * RETURNS - * Success: TRUE - * Failure: FALSE - */ - -BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) -{ - struct threaddata *tdata; - - switch (fdwReason) { - case DLL_PROCESS_ATTACH: - master_mutex = CreateMutexA( NULL, FALSE, RPCSS_MASTER_MUTEX_NAME); - if (!master_mutex) - ERR("Failed to create master mutex\n"); - break; - - case DLL_THREAD_DETACH: - tdata = NtCurrentTeb()->ReservedForNtRpc; - if (tdata) - { - EnterCriticalSection(&threaddata_cs); - list_remove(&tdata->entry); - LeaveCriticalSection(&threaddata_cs); - - DeleteCriticalSection(&tdata->cs); - if (tdata->connection) - ERR("tdata->connection should be NULL but is still set to %p\n", tdata->connection); - if (tdata->server_binding) - ERR("tdata->server_binding should be NULL but is still set to %p\n", tdata->server_binding); - HeapFree(GetProcessHeap(), 0, tdata); - } - break; - - case DLL_PROCESS_DETACH: - CloseHandle(master_mutex); - master_mutex = NULL; - break; - } - - return TRUE; -} - -/************************************************************************* - * RpcStringFreeA [RPCRT4.@] - * - * Frees a character string allocated by the RPC run-time library. - * - * RETURNS - * - * S_OK if successful. - */ -RPC_STATUS WINAPI RpcStringFreeA(RPC_CSTR* String) -{ - HeapFree( GetProcessHeap(), 0, *String); - - return RPC_S_OK; -} - -/************************************************************************* - * RpcStringFreeW [RPCRT4.@] - * - * Frees a character string allocated by the RPC run-time library. - * - * RETURNS - * - * S_OK if successful. - */ -RPC_STATUS WINAPI RpcStringFreeW(RPC_WSTR* String) -{ - HeapFree( GetProcessHeap(), 0, *String); - - return RPC_S_OK; -} - -/************************************************************************* - * RpcRaiseException [RPCRT4.@] - * - * Raises an exception. - */ -void DECLSPEC_NORETURN WINAPI RpcRaiseException(RPC_STATUS exception) -{ - /* shouldn't return */ - RaiseException(exception, 0, 0, NULL); - ERR("handler continued execution\n"); - ExitProcess(1); -} - -/************************************************************************* - * UuidCompare [RPCRT4.@] - * - * PARAMS - * UUID *Uuid1 [I] Uuid to compare - * UUID *Uuid2 [I] Uuid to compare - * RPC_STATUS *Status [O] returns RPC_S_OK - * - * RETURNS - * -1 if Uuid1 is less than Uuid2 - * 0 if Uuid1 and Uuid2 are equal - * 1 if Uuid1 is greater than Uuid2 - */ -int WINAPI UuidCompare(UUID *Uuid1, UUID *Uuid2, RPC_STATUS *Status) -{ - int i; - - TRACE("(%s,%s)\n", debugstr_guid(Uuid1), debugstr_guid(Uuid2)); - - *Status = RPC_S_OK; - - if (!Uuid1) Uuid1 = &uuid_nil; - if (!Uuid2) Uuid2 = &uuid_nil; - - if (Uuid1 == Uuid2) return 0; - - if (Uuid1->Data1 != Uuid2->Data1) - return Uuid1->Data1 < Uuid2->Data1 ? -1 : 1; - - if (Uuid1->Data2 != Uuid2->Data2) - return Uuid1->Data2 < Uuid2->Data2 ? -1 : 1; - - if (Uuid1->Data3 != Uuid2->Data3) - return Uuid1->Data3 < Uuid2->Data3 ? -1 : 1; - - for (i = 0; i < 8; i++) { - if (Uuid1->Data4[i] < Uuid2->Data4[i]) - return -1; - if (Uuid1->Data4[i] > Uuid2->Data4[i]) - return 1; - } - - return 0; -} - -/************************************************************************* - * UuidEqual [RPCRT4.@] - * - * PARAMS - * UUID *Uuid1 [I] Uuid to compare - * UUID *Uuid2 [I] Uuid to compare - * RPC_STATUS *Status [O] returns RPC_S_OK - * - * RETURNS - * TRUE/FALSE - */ -int WINAPI UuidEqual(UUID *Uuid1, UUID *Uuid2, RPC_STATUS *Status) -{ - TRACE("(%s,%s)\n", debugstr_guid(Uuid1), debugstr_guid(Uuid2)); - return !UuidCompare(Uuid1, Uuid2, Status); -} - -/************************************************************************* - * UuidIsNil [RPCRT4.@] - * - * PARAMS - * UUID *Uuid [I] Uuid to compare - * RPC_STATUS *Status [O] retuns RPC_S_OK - * - * RETURNS - * TRUE/FALSE - */ -int WINAPI UuidIsNil(UUID *Uuid, RPC_STATUS *Status) -{ - TRACE("(%s)\n", debugstr_guid(Uuid)); - if (!Uuid) return TRUE; - return !UuidCompare(Uuid, &uuid_nil, Status); -} - - /************************************************************************* - * UuidCreateNil [RPCRT4.@] - * - * PARAMS - * UUID *Uuid [O] returns a nil UUID - * - * RETURNS - * RPC_S_OK - */ -RPC_STATUS WINAPI UuidCreateNil(UUID *Uuid) -{ - *Uuid = uuid_nil; - return RPC_S_OK; -} - -/* Number of 100ns ticks per clock tick. To be safe, assume that the clock - resolution is at least 1000 * 100 * (1/1000000) = 1/10 of a second */ -#define TICKS_PER_CLOCK_TICK 1000 -#define SECSPERDAY 86400 -#define TICKSPERSEC 10000000 -/* UUID system time starts at October 15, 1582 */ -#define SECS_15_OCT_1582_TO_1601 ((17 + 30 + 31 + 365 * 18 + 5) * SECSPERDAY) -#define TICKS_15_OCT_1582_TO_1601 ((ULONGLONG)SECS_15_OCT_1582_TO_1601 * TICKSPERSEC) - -static void RPC_UuidGetSystemTime(ULONGLONG *time) -{ - FILETIME ft; - - GetSystemTimeAsFileTime(&ft); - - *time = ((ULONGLONG)ft.dwHighDateTime << 32) | ft.dwLowDateTime; - *time += TICKS_15_OCT_1582_TO_1601; -} - -/* Assume that a hardware address is at least 6 bytes long */ -#define ADDRESS_BYTES_NEEDED 6 - -static RPC_STATUS RPC_UuidGetNodeAddress(BYTE *address) -{ - int i; - DWORD status = RPC_S_OK; - - ULONG buflen = sizeof(IP_ADAPTER_INFO); - PIP_ADAPTER_INFO adapter = HeapAlloc(GetProcessHeap(), 0, buflen); - - if (GetAdaptersInfo(adapter, &buflen) == ERROR_BUFFER_OVERFLOW) { - HeapFree(GetProcessHeap(), 0, adapter); - adapter = HeapAlloc(GetProcessHeap(), 0, buflen); - } - - if (GetAdaptersInfo(adapter, &buflen) == NO_ERROR) { - for (i = 0; i < ADDRESS_BYTES_NEEDED; i++) { - address[i] = adapter->Address[i]; - } - } - /* We can't get a hardware address, just use random numbers. - Set the multicast bit to prevent conflicts with real cards. */ - else { - for (i = 0; i < ADDRESS_BYTES_NEEDED; i++) { - address[i] = rand() & 0xff; - } - - address[0] |= 0x01; - status = RPC_S_UUID_LOCAL_ONLY; - } - - HeapFree(GetProcessHeap(), 0, adapter); - return status; -} - -/************************************************************************* - * UuidCreate [RPCRT4.@] - * - * Creates a 128bit UUID. - * - * RETURNS - * - * RPC_S_OK if successful. - * 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 - * backwards and swapped network cards). The RFC - * suggests using NVRAM for storing persistent - * values. - */ -RPC_STATUS WINAPI UuidCreate(UUID *Uuid) -{ - static int initialised, count; - - ULONGLONG time; - static ULONGLONG timelast; - static WORD sequence; - - static DWORD status; - static BYTE address[MAX_ADAPTER_ADDRESS_LENGTH]; - - EnterCriticalSection(&uuid_cs); - - if (!initialised) { - RPC_UuidGetSystemTime(&timelast); - count = TICKS_PER_CLOCK_TICK; - - sequence = ((rand() & 0xff) << 8) + (rand() & 0xff); - sequence &= 0x1fff; - - status = RPC_UuidGetNodeAddress(address); - initialised = 1; - } - - /* Generate time element of the UUID. Account for going faster - than our clock as well as the clock going backwards. */ - while (1) { - RPC_UuidGetSystemTime(&time); - if (time > timelast) { - count = 0; - break; - } - if (time < timelast) { - sequence = (sequence + 1) & 0x1fff; - count = 0; - break; - } - if (count < TICKS_PER_CLOCK_TICK) { - count++; - break; - } - } - - timelast = time; - time += count; - - /* Pack the information into the UUID structure. */ - - Uuid->Data1 = (unsigned long)(time & 0xffffffff); - Uuid->Data2 = (unsigned short)((time >> 32) & 0xffff); - Uuid->Data3 = (unsigned short)((time >> 48) & 0x0fff); - - /* This is a version 1 UUID */ - Uuid->Data3 |= (1 << 12); - - Uuid->Data4[0] = sequence & 0xff; - Uuid->Data4[1] = (sequence & 0x3f00) >> 8; - Uuid->Data4[1] |= 0x80; - - Uuid->Data4[2] = address[0]; - Uuid->Data4[3] = address[1]; - Uuid->Data4[4] = address[2]; - Uuid->Data4[5] = address[3]; - Uuid->Data4[6] = address[4]; - Uuid->Data4[7] = address[5]; - - LeaveCriticalSection(&uuid_cs); - - TRACE("%s\n", debugstr_guid(Uuid)); - - return 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.@] - * - * Generates a hash value for a given UUID - * - * Code based on FreeDCE implementation - * - */ -unsigned short WINAPI UuidHash(UUID *uuid, RPC_STATUS *Status) -{ - BYTE *data = (BYTE*)uuid; - short c0 = 0, c1 = 0, x, y; - unsigned int i; - - if (!uuid) data = (BYTE*)(uuid = &uuid_nil); - - TRACE("(%s)\n", debugstr_guid(uuid)); - - for (i=0; iData1, Uuid->Data2, Uuid->Data3, - Uuid->Data4[0], Uuid->Data4[1], Uuid->Data4[2], - Uuid->Data4[3], Uuid->Data4[4], Uuid->Data4[5], - Uuid->Data4[6], Uuid->Data4[7] ); - - return RPC_S_OK; -} - -/************************************************************************* - * UuidToStringW [RPCRT4.@] - * - * Converts a UUID to a string. - * - * S_OK if successful. - * S_OUT_OF_MEMORY if unsuccessful. - */ -RPC_STATUS WINAPI UuidToStringW(UUID *Uuid, RPC_WSTR* StringUuid) -{ - char buf[37]; - - if (!Uuid) Uuid = &uuid_nil; - - sprintf(buf, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", - Uuid->Data1, Uuid->Data2, Uuid->Data3, - Uuid->Data4[0], Uuid->Data4[1], Uuid->Data4[2], - Uuid->Data4[3], Uuid->Data4[4], Uuid->Data4[5], - Uuid->Data4[6], Uuid->Data4[7] ); - - *StringUuid = RPCRT4_strdupAtoW(buf); - - if(!(*StringUuid)) - return RPC_S_OUT_OF_MEMORY; - - return RPC_S_OK; -} - -static const BYTE hex2bin[] = -{ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x00 */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x10 */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x20 */ - 0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0, /* 0x30 */ - 0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0, /* 0x40 */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x50 */ - 0,10,11,12,13,14,15 /* 0x60 */ -}; - -/*********************************************************************** - * UuidFromStringA (RPCRT4.@) - */ -RPC_STATUS WINAPI UuidFromStringA(RPC_CSTR s, UUID *uuid) -{ - int i; - - if (!s) return UuidCreateNil( uuid ); - - if (strlen((char*)s) != 36) return RPC_S_INVALID_STRING_UUID; - - if ((s[8]!='-') || (s[13]!='-') || (s[18]!='-') || (s[23]!='-')) - return RPC_S_INVALID_STRING_UUID; - - for (i=0; i<36; i++) - { - if ((i == 8)||(i == 13)||(i == 18)||(i == 23)) continue; - if (s[i] > 'f' || (!hex2bin[s[i]] && s[i] != '0')) return RPC_S_INVALID_STRING_UUID; - } - - /* in form XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX */ - - uuid->Data1 = (hex2bin[s[0]] << 28 | hex2bin[s[1]] << 24 | hex2bin[s[2]] << 20 | hex2bin[s[3]] << 16 | - hex2bin[s[4]] << 12 | hex2bin[s[5]] << 8 | hex2bin[s[6]] << 4 | hex2bin[s[7]]); - uuid->Data2 = hex2bin[s[9]] << 12 | hex2bin[s[10]] << 8 | hex2bin[s[11]] << 4 | hex2bin[s[12]]; - uuid->Data3 = hex2bin[s[14]] << 12 | hex2bin[s[15]] << 8 | hex2bin[s[16]] << 4 | hex2bin[s[17]]; - - /* these are just sequential bytes */ - uuid->Data4[0] = hex2bin[s[19]] << 4 | hex2bin[s[20]]; - uuid->Data4[1] = hex2bin[s[21]] << 4 | hex2bin[s[22]]; - uuid->Data4[2] = hex2bin[s[24]] << 4 | hex2bin[s[25]]; - uuid->Data4[3] = hex2bin[s[26]] << 4 | hex2bin[s[27]]; - uuid->Data4[4] = hex2bin[s[28]] << 4 | hex2bin[s[29]]; - uuid->Data4[5] = hex2bin[s[30]] << 4 | hex2bin[s[31]]; - uuid->Data4[6] = hex2bin[s[32]] << 4 | hex2bin[s[33]]; - uuid->Data4[7] = hex2bin[s[34]] << 4 | hex2bin[s[35]]; - return RPC_S_OK; -} - - -/*********************************************************************** - * UuidFromStringW (RPCRT4.@) - */ -RPC_STATUS WINAPI UuidFromStringW(RPC_WSTR s, UUID *uuid) -{ - int i; - - if (!s) return UuidCreateNil( uuid ); - - if (strlenW(s) != 36) return RPC_S_INVALID_STRING_UUID; - - if ((s[8]!='-') || (s[13]!='-') || (s[18]!='-') || (s[23]!='-')) - return RPC_S_INVALID_STRING_UUID; - - for (i=0; i<36; i++) - { - if ((i == 8)||(i == 13)||(i == 18)||(i == 23)) continue; - if (s[i] > 'f' || (!hex2bin[s[i]] && s[i] != '0')) return RPC_S_INVALID_STRING_UUID; - } - - /* in form XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX */ - - uuid->Data1 = (hex2bin[s[0]] << 28 | hex2bin[s[1]] << 24 | hex2bin[s[2]] << 20 | hex2bin[s[3]] << 16 | - hex2bin[s[4]] << 12 | hex2bin[s[5]] << 8 | hex2bin[s[6]] << 4 | hex2bin[s[7]]); - uuid->Data2 = hex2bin[s[9]] << 12 | hex2bin[s[10]] << 8 | hex2bin[s[11]] << 4 | hex2bin[s[12]]; - uuid->Data3 = hex2bin[s[14]] << 12 | hex2bin[s[15]] << 8 | hex2bin[s[16]] << 4 | hex2bin[s[17]]; - - /* these are just sequential bytes */ - uuid->Data4[0] = hex2bin[s[19]] << 4 | hex2bin[s[20]]; - uuid->Data4[1] = hex2bin[s[21]] << 4 | hex2bin[s[22]]; - uuid->Data4[2] = hex2bin[s[24]] << 4 | hex2bin[s[25]]; - uuid->Data4[3] = hex2bin[s[26]] << 4 | hex2bin[s[27]]; - uuid->Data4[4] = hex2bin[s[28]] << 4 | hex2bin[s[29]]; - uuid->Data4[5] = hex2bin[s[30]] << 4 | hex2bin[s[31]]; - uuid->Data4[6] = hex2bin[s[32]] << 4 | hex2bin[s[33]]; - uuid->Data4[7] = hex2bin[s[34]] << 4 | hex2bin[s[35]]; - return RPC_S_OK; -} - -/*********************************************************************** - * DllRegisterServer (RPCRT4.@) - */ - -HRESULT WINAPI DllRegisterServer( void ) -{ - FIXME( "(): stub\n" ); - return S_OK; -} - -static BOOL RPCRT4_StartRPCSS(void) -{ - PROCESS_INFORMATION pi; - STARTUPINFOA si; - static char cmd[6]; - BOOL rslt; - - ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); - ZeroMemory(&si, sizeof(STARTUPINFOA)); - si.cb = sizeof(STARTUPINFOA); - - /* apparently it's not OK to use a constant string below */ - CopyMemory(cmd, "rpcss", 6); - - /* FIXME: will this do the right thing when run as a test? */ - rslt = CreateProcessA( - 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 */ - ); - - if (rslt) { - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); - } - - return rslt; -} - -/*********************************************************************** - * RPCRT4_RPCSSOnDemandCall (internal) - * - * Attempts to send a message to the RPCSS process - * on the local machine, invoking it if necessary. - * For remote RPCSS calls, use.... your imagination. - * - * PARAMS - * msg [I] pointer to the RPCSS message - * vardata_payload [I] pointer vardata portion of the RPCSS message - * reply [O] pointer to reply structure - * - * RETURNS - * TRUE if successful - * FALSE otherwise - */ -BOOL RPCRT4_RPCSSOnDemandCall(PRPCSS_NP_MESSAGE msg, char *vardata_payload, PRPCSS_NP_REPLY reply) -{ - HANDLE client_handle; - BOOL ret; - int i, j = 0; - - TRACE("(msg == %p, vardata_payload == %p, reply == %p)\n", msg, vardata_payload, reply); - - client_handle = RPCRT4_RpcssNPConnect(); - - while (INVALID_HANDLE_VALUE == client_handle) { - /* start the RPCSS process */ - if (!RPCRT4_StartRPCSS()) { - ERR("Unable to start RPCSS process.\n"); - return FALSE; - } - /* wait for a connection (w/ periodic polling) */ - for (i = 0; i < 60; i++) { - Sleep(200); - client_handle = RPCRT4_RpcssNPConnect(); - if (INVALID_HANDLE_VALUE != client_handle) break; - } - /* we are only willing to try twice */ - if (j++ >= 1) break; - } - - if (INVALID_HANDLE_VALUE == client_handle) { - /* no dice! */ - ERR("Unable to connect to RPCSS process!\n"); - SetLastError(RPC_E_SERVER_DIED_DNE); - return FALSE; - } - - /* great, we're connected. now send the message */ - ret = TRUE; - if (!RPCRT4_SendReceiveNPMsg(client_handle, msg, vardata_payload, reply)) { - ERR("Something is amiss: RPC_SendReceive failed.\n"); - ret = FALSE; - } - CloseHandle(client_handle); - - return ret; -} - -#define MAX_RPC_ERROR_TEXT 256 - -/****************************************************************************** - * DceErrorInqTextW (rpcrt4.@) - * - * Notes - * 1. On passing a NULL pointer the code does bomb out. - * 2. The size of the required buffer is not defined in the documentation. - * It appears to be 256. - * 3. The function is defined to return RPC_S_INVALID_ARG but I don't know - * of any value for which it does. - * 4. The MSDN documentation currently declares that the second argument is - * unsigned char *, even for the W version. I don't believe it. - */ -RPC_STATUS RPC_ENTRY DceErrorInqTextW (RPC_STATUS e, RPC_WSTR buffer) -{ - DWORD count; - count = FormatMessageW (FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, e, 0, buffer, MAX_RPC_ERROR_TEXT, NULL); - if (!count) - { - count = FormatMessageW (FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, RPC_S_NOT_RPC_ERROR, 0, buffer, MAX_RPC_ERROR_TEXT, NULL); - if (!count) - { - ERR ("Failed to translate error\n"); - return RPC_S_INVALID_ARG; - } - } - return RPC_S_OK; -} - -/****************************************************************************** - * DceErrorInqTextA (rpcrt4.@) - */ -RPC_STATUS RPC_ENTRY DceErrorInqTextA (RPC_STATUS e, RPC_CSTR buffer) -{ - RPC_STATUS status; - WCHAR bufferW [MAX_RPC_ERROR_TEXT]; - if ((status = DceErrorInqTextW (e, bufferW)) == RPC_S_OK) - { - if (!WideCharToMultiByte(CP_ACP, 0, bufferW, -1, (LPSTR)buffer, MAX_RPC_ERROR_TEXT, - NULL, NULL)) - { - ERR ("Failed to translate error\n"); - status = RPC_S_INVALID_ARG; - } - } - return status; -} - -/****************************************************************************** - * I_RpcAllocate (rpcrt4.@) - */ -void * WINAPI I_RpcAllocate(unsigned int Size) -{ - return HeapAlloc(GetProcessHeap(), 0, Size); -} - -/****************************************************************************** - * I_RpcFree (rpcrt4.@) - */ -void WINAPI I_RpcFree(void *Object) -{ - HeapFree(GetProcessHeap(), 0, Object); -} - -/****************************************************************************** - * I_RpcMapWin32Status (rpcrt4.@) - */ -LONG WINAPI I_RpcMapWin32Status(RPC_STATUS status) -{ - FIXME("(%ld): stub\n", status); - return 0; -} - -/****************************************************************************** - * RpcErrorStartEnumeration (rpcrt4.@) - */ -RPC_STATUS RPC_ENTRY RpcErrorStartEnumeration(RPC_ERROR_ENUM_HANDLE* EnumHandle) -{ - FIXME("(%p): stub\n", EnumHandle); - return RPC_S_ENTRY_NOT_FOUND; -} - -/****************************************************************************** - * RpcMgmtSetCancelTimeout (rpcrt4.@) - */ -RPC_STATUS RPC_ENTRY RpcMgmtSetCancelTimeout(LONG Timeout) -{ - FIXME("(%d): stub\n", Timeout); - return RPC_S_OK; -} - -static struct threaddata *get_or_create_threaddata(void) -{ - struct threaddata *tdata = NtCurrentTeb()->ReservedForNtRpc; - if (!tdata) - { - tdata = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*tdata)); - if (!tdata) return NULL; - - InitializeCriticalSection(&tdata->cs); - tdata->thread_id = GetCurrentThreadId(); - - EnterCriticalSection(&threaddata_cs); - list_add_tail(&threaddata_list, &tdata->entry); - LeaveCriticalSection(&threaddata_cs); - - NtCurrentTeb()->ReservedForNtRpc = tdata; - return tdata; - } - return tdata; -} - -void RPCRT4_SetThreadCurrentConnection(RpcConnection *Connection) -{ - struct threaddata *tdata = get_or_create_threaddata(); - if (!tdata) return; - - EnterCriticalSection(&tdata->cs); - tdata->connection = Connection; - LeaveCriticalSection(&tdata->cs); -} - -void RPCRT4_SetThreadCurrentCallHandle(RpcBinding *Binding) -{ - struct threaddata *tdata = get_or_create_threaddata(); - if (!tdata) return; - - tdata->server_binding = Binding; -} - -RpcBinding *RPCRT4_GetThreadCurrentCallHandle(void) -{ - struct threaddata *tdata = get_or_create_threaddata(); - if (!tdata) return NULL; - - return tdata->server_binding; -} - -void RPCRT4_PushThreadContextHandle(NDR_SCONTEXT SContext) -{ - struct threaddata *tdata = get_or_create_threaddata(); - struct context_handle_list *context_handle_list; - - if (!tdata) return; - - context_handle_list = HeapAlloc(GetProcessHeap(), 0, sizeof(*context_handle_list)); - if (!context_handle_list) return; - - context_handle_list->context_handle = SContext; - context_handle_list->next = tdata->context_handle_list; - tdata->context_handle_list = context_handle_list; -} - -void RPCRT4_RemoveThreadContextHandle(NDR_SCONTEXT SContext) -{ - struct threaddata *tdata = get_or_create_threaddata(); - struct context_handle_list *current, *prev; - - if (!tdata) return; - - for (current = tdata->context_handle_list, prev = NULL; current; prev = current, current = current->next) - { - if (current->context_handle == SContext) - { - if (prev) - prev->next = current->next; - else - tdata->context_handle_list = current->next; - HeapFree(GetProcessHeap(), 0, current); - return; - } - } -} - -NDR_SCONTEXT RPCRT4_PopThreadContextHandle(void) -{ - struct threaddata *tdata = get_or_create_threaddata(); - struct context_handle_list *context_handle_list; - NDR_SCONTEXT context_handle; - - if (!tdata) return NULL; - - context_handle_list = tdata->context_handle_list; - if (!context_handle_list) return NULL; - tdata->context_handle_list = context_handle_list->next; - - context_handle = context_handle_list->context_handle; - HeapFree(GetProcessHeap(), 0, context_handle_list); - return context_handle; -} - -/****************************************************************************** - * RpcCancelThread (rpcrt4.@) - */ -RPC_STATUS RPC_ENTRY RpcCancelThread(void* ThreadHandle) -{ - DWORD target_tid; - struct threaddata *tdata; - - TRACE("(%p)\n", ThreadHandle); - - target_tid = GetThreadId(ThreadHandle); - if (!target_tid) - return RPC_S_INVALID_ARG; - - EnterCriticalSection(&threaddata_cs); - LIST_FOR_EACH_ENTRY(tdata, &threaddata_list, struct threaddata, entry) - if (tdata->thread_id == target_tid) - { - EnterCriticalSection(&tdata->cs); - if (tdata->connection) rpcrt4_conn_cancel_call(tdata->connection); - LeaveCriticalSection(&tdata->cs); - break; - } - LeaveCriticalSection(&threaddata_cs); - - return RPC_S_OK; -} +/* + * RPCRT4 + * + * Copyright 2000 Huw D M Davies for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + * + * WINE RPC TODO's (and a few TODONT's) + * + * - Ove's decreasingly incomplete widl is an IDL compiler for wine. For widl + * to be wine's only IDL compiler, a fair bit of work remains to be done. + * until then we have used some midl-generated stuff. (What?) + * widl currently doesn't generate stub/proxy files required by wine's (O)RPC + * capabilities -- nor does it make those lovely format strings :( + * The MS MIDL compiler does some really esoteric stuff. Of course Ove has + * started with the less esoteric stuff. There are also lots of nice + * comments in there if you want to flex your bison and help build this monster. + * + * - RPC has a quite featureful error handling mechanism; basically none of this is + * implemented right now. We also have deficiencies on the compiler side, where + * wine's __TRY / __EXCEPT / __FINALLY macros are not even used for RpcTryExcept & co, + * due to syntactic differences! (we can fix it with widl by using __TRY) + * + * - There are several different memory allocation schemes for MSRPC. + * I don't even understand what they all are yet, much less have them + * properly implemented. Surely we are supposed to be doing something with + * the user-provided allocation/deallocation functions, but so far, + * I don't think we are doing this... + * + * - MSRPC provides impersonation capabilities which currently are not possible + * to implement in wine. At the very least we should implement the authorization + * API's & gracefully ignore the irrelevant stuff (to an extent we already do). + * + * - Some transports are not yet implemented. The existing transport implementations + * are incomplete and may be bug-infested. + * + * - The various transports that we do support ought to be supported in a more + * object-oriented manner, as in DCE's RPC implementation, instead of cluttering + * up the code with conditionals like we do now. + * + * - Data marshalling: So far, only the beginnings of a full implementation + * exist in wine. NDR protocol itself is documented, but the MS API's to + * convert data-types in memory into NDR are not. This is challenging work, + * and has supposedly been "at the top of Greg's queue" for several months now. + * + * - ORPC is RPC for OLE; once we have a working RPC framework, we can + * use it to implement out-of-process OLE client/server communications. + * ATM there is maybe a disconnect between the marshalling in the OLE DLLs + * and the marshalling going on here [TODO: well, is there or not?] + * + * - In-source API Documentation, at least for those functions which we have + * implemented, but preferably for everything we can document, would be nice, + * since some of this stuff is quite obscure. + * + * - Name services... [TODO: what about them] + * + * - Protocol Towers: Totally unimplemented.... I think. + * + * - Context Handle Rundown: whatever that is. + * + * - Nested RPC's: Totally unimplemented. + * + * - Statistics: we are supposed to be keeping various counters. we aren't. + * + * - Async RPC: Unimplemented. + * + * - XML/http RPC: Somewhere there's an XML fiend that wants to do this! Betcha + * we could use these as a transport for RPC's across computers without a + * permissions and/or licensing crisis. + * + * - The NT "ports" API, aka LPC. Greg claims this is on his radar. Might (or + * might not) enable users to get some kind of meaningful result out of + * NT-based native rpcrt4's. Commonly-used transport for self-to-self RPC's. + * + * - ...? More stuff I haven't thought of. If you think of more RPC todo's + * drop me an e-mail or send a patch to the + * wine-patches mailing list. + */ + +#include "config.h" + +#include +#include +#include +#include + +#include "windef.h" +#include "winerror.h" +#include "winbase.h" +#include "winuser.h" +#include "winnt.h" +#include "winternl.h" +#include "iptypes.h" +#include "iphlpapi.h" +#include "wine/unicode.h" +#include "rpc.h" + +#include "ole2.h" +#include "rpcndr.h" +#include "rpcproxy.h" + +#include "rpc_binding.h" +#include "rpcss_np_client.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(rpc); + +static UUID uuid_nil; +static HANDLE master_mutex; + +HANDLE RPCRT4_GetMasterMutex(void) +{ + return master_mutex; +} + +static CRITICAL_SECTION uuid_cs; +static CRITICAL_SECTION_DEBUG critsect_debug = +{ + 0, 0, &uuid_cs, + { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList }, + 0, 0, { (DWORD_PTR)(__FILE__ ": uuid_cs") } +}; +static CRITICAL_SECTION uuid_cs = { &critsect_debug, -1, 0, 0, 0, 0 }; + +static CRITICAL_SECTION threaddata_cs; +static CRITICAL_SECTION_DEBUG threaddata_cs_debug = +{ + 0, 0, &threaddata_cs, + { &threaddata_cs_debug.ProcessLocksList, &threaddata_cs_debug.ProcessLocksList }, + 0, 0, { (DWORD_PTR)(__FILE__ ": threaddata_cs") } +}; +static CRITICAL_SECTION threaddata_cs = { &threaddata_cs_debug, -1, 0, 0, 0, 0 }; + +struct list threaddata_list = LIST_INIT(threaddata_list); + +struct context_handle_list +{ + struct context_handle_list *next; + NDR_SCONTEXT context_handle; +}; + +struct threaddata +{ + struct list entry; + CRITICAL_SECTION cs; + DWORD thread_id; + RpcConnection *connection; + RpcBinding *server_binding; + struct context_handle_list *context_handle_list; +}; + +/*********************************************************************** + * DllMain + * + * PARAMS + * hinstDLL [I] handle to the DLL's instance + * fdwReason [I] + * lpvReserved [I] reserved, must be NULL + * + * RETURNS + * Success: TRUE + * Failure: FALSE + */ + +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + struct threaddata *tdata; + + switch (fdwReason) { + case DLL_PROCESS_ATTACH: + master_mutex = CreateMutexA( NULL, FALSE, RPCSS_MASTER_MUTEX_NAME); + if (!master_mutex) + ERR("Failed to create master mutex\n"); + break; + + case DLL_THREAD_DETACH: + tdata = NtCurrentTeb()->ReservedForNtRpc; + if (tdata) + { + EnterCriticalSection(&threaddata_cs); + list_remove(&tdata->entry); + LeaveCriticalSection(&threaddata_cs); + + DeleteCriticalSection(&tdata->cs); + if (tdata->connection) + ERR("tdata->connection should be NULL but is still set to %p\n", tdata->connection); + if (tdata->server_binding) + ERR("tdata->server_binding should be NULL but is still set to %p\n", tdata->server_binding); + HeapFree(GetProcessHeap(), 0, tdata); + } + break; + + case DLL_PROCESS_DETACH: + CloseHandle(master_mutex); + master_mutex = NULL; + break; + } + + return TRUE; +} + +/************************************************************************* + * RpcStringFreeA [RPCRT4.@] + * + * Frees a character string allocated by the RPC run-time library. + * + * RETURNS + * + * S_OK if successful. + */ +RPC_STATUS WINAPI RpcStringFreeA(RPC_CSTR* String) +{ + HeapFree( GetProcessHeap(), 0, *String); + + return RPC_S_OK; +} + +/************************************************************************* + * RpcStringFreeW [RPCRT4.@] + * + * Frees a character string allocated by the RPC run-time library. + * + * RETURNS + * + * S_OK if successful. + */ +RPC_STATUS WINAPI RpcStringFreeW(RPC_WSTR* String) +{ + HeapFree( GetProcessHeap(), 0, *String); + + return RPC_S_OK; +} + +/************************************************************************* + * RpcRaiseException [RPCRT4.@] + * + * Raises an exception. + */ +void DECLSPEC_NORETURN WINAPI RpcRaiseException(RPC_STATUS exception) +{ + /* shouldn't return */ + RaiseException(exception, 0, 0, NULL); + ERR("handler continued execution\n"); + ExitProcess(1); +} + +/************************************************************************* + * UuidCompare [RPCRT4.@] + * + * PARAMS + * UUID *Uuid1 [I] Uuid to compare + * UUID *Uuid2 [I] Uuid to compare + * RPC_STATUS *Status [O] returns RPC_S_OK + * + * RETURNS + * -1 if Uuid1 is less than Uuid2 + * 0 if Uuid1 and Uuid2 are equal + * 1 if Uuid1 is greater than Uuid2 + */ +int WINAPI UuidCompare(UUID *Uuid1, UUID *Uuid2, RPC_STATUS *Status) +{ + int i; + + TRACE("(%s,%s)\n", debugstr_guid(Uuid1), debugstr_guid(Uuid2)); + + *Status = RPC_S_OK; + + if (!Uuid1) Uuid1 = &uuid_nil; + if (!Uuid2) Uuid2 = &uuid_nil; + + if (Uuid1 == Uuid2) return 0; + + if (Uuid1->Data1 != Uuid2->Data1) + return Uuid1->Data1 < Uuid2->Data1 ? -1 : 1; + + if (Uuid1->Data2 != Uuid2->Data2) + return Uuid1->Data2 < Uuid2->Data2 ? -1 : 1; + + if (Uuid1->Data3 != Uuid2->Data3) + return Uuid1->Data3 < Uuid2->Data3 ? -1 : 1; + + for (i = 0; i < 8; i++) { + if (Uuid1->Data4[i] < Uuid2->Data4[i]) + return -1; + if (Uuid1->Data4[i] > Uuid2->Data4[i]) + return 1; + } + + return 0; +} + +/************************************************************************* + * UuidEqual [RPCRT4.@] + * + * PARAMS + * UUID *Uuid1 [I] Uuid to compare + * UUID *Uuid2 [I] Uuid to compare + * RPC_STATUS *Status [O] returns RPC_S_OK + * + * RETURNS + * TRUE/FALSE + */ +int WINAPI UuidEqual(UUID *Uuid1, UUID *Uuid2, RPC_STATUS *Status) +{ + TRACE("(%s,%s)\n", debugstr_guid(Uuid1), debugstr_guid(Uuid2)); + return !UuidCompare(Uuid1, Uuid2, Status); +} + +/************************************************************************* + * UuidIsNil [RPCRT4.@] + * + * PARAMS + * UUID *Uuid [I] Uuid to compare + * RPC_STATUS *Status [O] retuns RPC_S_OK + * + * RETURNS + * TRUE/FALSE + */ +int WINAPI UuidIsNil(UUID *Uuid, RPC_STATUS *Status) +{ + TRACE("(%s)\n", debugstr_guid(Uuid)); + if (!Uuid) return TRUE; + return !UuidCompare(Uuid, &uuid_nil, Status); +} + + /************************************************************************* + * UuidCreateNil [RPCRT4.@] + * + * PARAMS + * UUID *Uuid [O] returns a nil UUID + * + * RETURNS + * RPC_S_OK + */ +RPC_STATUS WINAPI UuidCreateNil(UUID *Uuid) +{ + *Uuid = uuid_nil; + return RPC_S_OK; +} + +/* Number of 100ns ticks per clock tick. To be safe, assume that the clock + resolution is at least 1000 * 100 * (1/1000000) = 1/10 of a second */ +#define TICKS_PER_CLOCK_TICK 1000 +#define SECSPERDAY 86400 +#define TICKSPERSEC 10000000 +/* UUID system time starts at October 15, 1582 */ +#define SECS_15_OCT_1582_TO_1601 ((17 + 30 + 31 + 365 * 18 + 5) * SECSPERDAY) +#define TICKS_15_OCT_1582_TO_1601 ((ULONGLONG)SECS_15_OCT_1582_TO_1601 * TICKSPERSEC) + +static void RPC_UuidGetSystemTime(ULONGLONG *time) +{ + FILETIME ft; + + GetSystemTimeAsFileTime(&ft); + + *time = ((ULONGLONG)ft.dwHighDateTime << 32) | ft.dwLowDateTime; + *time += TICKS_15_OCT_1582_TO_1601; +} + +/* Assume that a hardware address is at least 6 bytes long */ +#define ADDRESS_BYTES_NEEDED 6 + +static RPC_STATUS RPC_UuidGetNodeAddress(BYTE *address) +{ + int i; + DWORD status = RPC_S_OK; + + ULONG buflen = sizeof(IP_ADAPTER_INFO); + PIP_ADAPTER_INFO adapter = HeapAlloc(GetProcessHeap(), 0, buflen); + + if (GetAdaptersInfo(adapter, &buflen) == ERROR_BUFFER_OVERFLOW) { + HeapFree(GetProcessHeap(), 0, adapter); + adapter = HeapAlloc(GetProcessHeap(), 0, buflen); + } + + if (GetAdaptersInfo(adapter, &buflen) == NO_ERROR) { + for (i = 0; i < ADDRESS_BYTES_NEEDED; i++) { + address[i] = adapter->Address[i]; + } + } + /* We can't get a hardware address, just use random numbers. + Set the multicast bit to prevent conflicts with real cards. */ + else { + for (i = 0; i < ADDRESS_BYTES_NEEDED; i++) { + address[i] = rand() & 0xff; + } + + address[0] |= 0x01; + status = RPC_S_UUID_LOCAL_ONLY; + } + + HeapFree(GetProcessHeap(), 0, adapter); + return status; +} + +/************************************************************************* + * UuidCreate [RPCRT4.@] + * + * Creates a 128bit UUID. + * + * RETURNS + * + * RPC_S_OK if successful. + * 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 + * backwards and swapped network cards). The RFC + * suggests using NVRAM for storing persistent + * values. + */ +RPC_STATUS WINAPI UuidCreate(UUID *Uuid) +{ + static int initialised, count; + + ULONGLONG time; + static ULONGLONG timelast; + static WORD sequence; + + static DWORD status; + static BYTE address[MAX_ADAPTER_ADDRESS_LENGTH]; + + EnterCriticalSection(&uuid_cs); + + if (!initialised) { + RPC_UuidGetSystemTime(&timelast); + count = TICKS_PER_CLOCK_TICK; + + sequence = ((rand() & 0xff) << 8) + (rand() & 0xff); + sequence &= 0x1fff; + + status = RPC_UuidGetNodeAddress(address); + initialised = 1; + } + + /* Generate time element of the UUID. Account for going faster + than our clock as well as the clock going backwards. */ + while (1) { + RPC_UuidGetSystemTime(&time); + if (time > timelast) { + count = 0; + break; + } + if (time < timelast) { + sequence = (sequence + 1) & 0x1fff; + count = 0; + break; + } + if (count < TICKS_PER_CLOCK_TICK) { + count++; + break; + } + } + + timelast = time; + time += count; + + /* Pack the information into the UUID structure. */ + + Uuid->Data1 = (unsigned long)(time & 0xffffffff); + Uuid->Data2 = (unsigned short)((time >> 32) & 0xffff); + Uuid->Data3 = (unsigned short)((time >> 48) & 0x0fff); + + /* This is a version 1 UUID */ + Uuid->Data3 |= (1 << 12); + + Uuid->Data4[0] = sequence & 0xff; + Uuid->Data4[1] = (sequence & 0x3f00) >> 8; + Uuid->Data4[1] |= 0x80; + + Uuid->Data4[2] = address[0]; + Uuid->Data4[3] = address[1]; + Uuid->Data4[4] = address[2]; + Uuid->Data4[5] = address[3]; + Uuid->Data4[6] = address[4]; + Uuid->Data4[7] = address[5]; + + LeaveCriticalSection(&uuid_cs); + + TRACE("%s\n", debugstr_guid(Uuid)); + + return 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.@] + * + * Generates a hash value for a given UUID + * + * Code based on FreeDCE implementation + * + */ +unsigned short WINAPI UuidHash(UUID *uuid, RPC_STATUS *Status) +{ + BYTE *data = (BYTE*)uuid; + short c0 = 0, c1 = 0, x, y; + unsigned int i; + + if (!uuid) data = (BYTE*)(uuid = &uuid_nil); + + TRACE("(%s)\n", debugstr_guid(uuid)); + + for (i=0; iData1, Uuid->Data2, Uuid->Data3, + Uuid->Data4[0], Uuid->Data4[1], Uuid->Data4[2], + Uuid->Data4[3], Uuid->Data4[4], Uuid->Data4[5], + Uuid->Data4[6], Uuid->Data4[7] ); + + return RPC_S_OK; +} + +/************************************************************************* + * UuidToStringW [RPCRT4.@] + * + * Converts a UUID to a string. + * + * S_OK if successful. + * S_OUT_OF_MEMORY if unsuccessful. + */ +RPC_STATUS WINAPI UuidToStringW(UUID *Uuid, RPC_WSTR* StringUuid) +{ + char buf[37]; + + if (!Uuid) Uuid = &uuid_nil; + + sprintf(buf, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", + Uuid->Data1, Uuid->Data2, Uuid->Data3, + Uuid->Data4[0], Uuid->Data4[1], Uuid->Data4[2], + Uuid->Data4[3], Uuid->Data4[4], Uuid->Data4[5], + Uuid->Data4[6], Uuid->Data4[7] ); + + *StringUuid = RPCRT4_strdupAtoW(buf); + + if(!(*StringUuid)) + return RPC_S_OUT_OF_MEMORY; + + return RPC_S_OK; +} + +static const BYTE hex2bin[] = +{ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x00 */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x10 */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x20 */ + 0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0, /* 0x30 */ + 0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0, /* 0x40 */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x50 */ + 0,10,11,12,13,14,15 /* 0x60 */ +}; + +/*********************************************************************** + * UuidFromStringA (RPCRT4.@) + */ +RPC_STATUS WINAPI UuidFromStringA(RPC_CSTR s, UUID *uuid) +{ + int i; + + if (!s) return UuidCreateNil( uuid ); + + if (strlen((char*)s) != 36) return RPC_S_INVALID_STRING_UUID; + + if ((s[8]!='-') || (s[13]!='-') || (s[18]!='-') || (s[23]!='-')) + return RPC_S_INVALID_STRING_UUID; + + for (i=0; i<36; i++) + { + if ((i == 8)||(i == 13)||(i == 18)||(i == 23)) continue; + if (s[i] > 'f' || (!hex2bin[s[i]] && s[i] != '0')) return RPC_S_INVALID_STRING_UUID; + } + + /* in form XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX */ + + uuid->Data1 = (hex2bin[s[0]] << 28 | hex2bin[s[1]] << 24 | hex2bin[s[2]] << 20 | hex2bin[s[3]] << 16 | + hex2bin[s[4]] << 12 | hex2bin[s[5]] << 8 | hex2bin[s[6]] << 4 | hex2bin[s[7]]); + uuid->Data2 = hex2bin[s[9]] << 12 | hex2bin[s[10]] << 8 | hex2bin[s[11]] << 4 | hex2bin[s[12]]; + uuid->Data3 = hex2bin[s[14]] << 12 | hex2bin[s[15]] << 8 | hex2bin[s[16]] << 4 | hex2bin[s[17]]; + + /* these are just sequential bytes */ + uuid->Data4[0] = hex2bin[s[19]] << 4 | hex2bin[s[20]]; + uuid->Data4[1] = hex2bin[s[21]] << 4 | hex2bin[s[22]]; + uuid->Data4[2] = hex2bin[s[24]] << 4 | hex2bin[s[25]]; + uuid->Data4[3] = hex2bin[s[26]] << 4 | hex2bin[s[27]]; + uuid->Data4[4] = hex2bin[s[28]] << 4 | hex2bin[s[29]]; + uuid->Data4[5] = hex2bin[s[30]] << 4 | hex2bin[s[31]]; + uuid->Data4[6] = hex2bin[s[32]] << 4 | hex2bin[s[33]]; + uuid->Data4[7] = hex2bin[s[34]] << 4 | hex2bin[s[35]]; + return RPC_S_OK; +} + + +/*********************************************************************** + * UuidFromStringW (RPCRT4.@) + */ +RPC_STATUS WINAPI UuidFromStringW(RPC_WSTR s, UUID *uuid) +{ + int i; + + if (!s) return UuidCreateNil( uuid ); + + if (strlenW(s) != 36) return RPC_S_INVALID_STRING_UUID; + + if ((s[8]!='-') || (s[13]!='-') || (s[18]!='-') || (s[23]!='-')) + return RPC_S_INVALID_STRING_UUID; + + for (i=0; i<36; i++) + { + if ((i == 8)||(i == 13)||(i == 18)||(i == 23)) continue; + if (s[i] > 'f' || (!hex2bin[s[i]] && s[i] != '0')) return RPC_S_INVALID_STRING_UUID; + } + + /* in form XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX */ + + uuid->Data1 = (hex2bin[s[0]] << 28 | hex2bin[s[1]] << 24 | hex2bin[s[2]] << 20 | hex2bin[s[3]] << 16 | + hex2bin[s[4]] << 12 | hex2bin[s[5]] << 8 | hex2bin[s[6]] << 4 | hex2bin[s[7]]); + uuid->Data2 = hex2bin[s[9]] << 12 | hex2bin[s[10]] << 8 | hex2bin[s[11]] << 4 | hex2bin[s[12]]; + uuid->Data3 = hex2bin[s[14]] << 12 | hex2bin[s[15]] << 8 | hex2bin[s[16]] << 4 | hex2bin[s[17]]; + + /* these are just sequential bytes */ + uuid->Data4[0] = hex2bin[s[19]] << 4 | hex2bin[s[20]]; + uuid->Data4[1] = hex2bin[s[21]] << 4 | hex2bin[s[22]]; + uuid->Data4[2] = hex2bin[s[24]] << 4 | hex2bin[s[25]]; + uuid->Data4[3] = hex2bin[s[26]] << 4 | hex2bin[s[27]]; + uuid->Data4[4] = hex2bin[s[28]] << 4 | hex2bin[s[29]]; + uuid->Data4[5] = hex2bin[s[30]] << 4 | hex2bin[s[31]]; + uuid->Data4[6] = hex2bin[s[32]] << 4 | hex2bin[s[33]]; + uuid->Data4[7] = hex2bin[s[34]] << 4 | hex2bin[s[35]]; + return RPC_S_OK; +} + +/*********************************************************************** + * DllRegisterServer (RPCRT4.@) + */ + +HRESULT WINAPI DllRegisterServer( void ) +{ + FIXME( "(): stub\n" ); + return S_OK; +} + +static BOOL RPCRT4_StartRPCSS(void) +{ + PROCESS_INFORMATION pi; + STARTUPINFOA si; + static char cmd[6]; + BOOL rslt; + + ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); + ZeroMemory(&si, sizeof(STARTUPINFOA)); + si.cb = sizeof(STARTUPINFOA); + + /* apparently it's not OK to use a constant string below */ + CopyMemory(cmd, "rpcss", 6); + + /* FIXME: will this do the right thing when run as a test? */ + rslt = CreateProcessA( + 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 */ + ); + + if (rslt) { + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + } + + return rslt; +} + +/*********************************************************************** + * RPCRT4_RPCSSOnDemandCall (internal) + * + * Attempts to send a message to the RPCSS process + * on the local machine, invoking it if necessary. + * For remote RPCSS calls, use.... your imagination. + * + * PARAMS + * msg [I] pointer to the RPCSS message + * vardata_payload [I] pointer vardata portion of the RPCSS message + * reply [O] pointer to reply structure + * + * RETURNS + * TRUE if successful + * FALSE otherwise + */ +BOOL RPCRT4_RPCSSOnDemandCall(PRPCSS_NP_MESSAGE msg, char *vardata_payload, PRPCSS_NP_REPLY reply) +{ + HANDLE client_handle; + BOOL ret; + int i, j = 0; + + TRACE("(msg == %p, vardata_payload == %p, reply == %p)\n", msg, vardata_payload, reply); + + client_handle = RPCRT4_RpcssNPConnect(); + + while (INVALID_HANDLE_VALUE == client_handle) { + /* start the RPCSS process */ + if (!RPCRT4_StartRPCSS()) { + ERR("Unable to start RPCSS process.\n"); + return FALSE; + } + /* wait for a connection (w/ periodic polling) */ + for (i = 0; i < 60; i++) { + Sleep(200); + client_handle = RPCRT4_RpcssNPConnect(); + if (INVALID_HANDLE_VALUE != client_handle) break; + } + /* we are only willing to try twice */ + if (j++ >= 1) break; + } + + if (INVALID_HANDLE_VALUE == client_handle) { + /* no dice! */ + ERR("Unable to connect to RPCSS process!\n"); + SetLastError(RPC_E_SERVER_DIED_DNE); + return FALSE; + } + + /* great, we're connected. now send the message */ + ret = TRUE; + if (!RPCRT4_SendReceiveNPMsg(client_handle, msg, vardata_payload, reply)) { + ERR("Something is amiss: RPC_SendReceive failed.\n"); + ret = FALSE; + } + CloseHandle(client_handle); + + return ret; +} + +#define MAX_RPC_ERROR_TEXT 256 + +/****************************************************************************** + * DceErrorInqTextW (rpcrt4.@) + * + * Notes + * 1. On passing a NULL pointer the code does bomb out. + * 2. The size of the required buffer is not defined in the documentation. + * It appears to be 256. + * 3. The function is defined to return RPC_S_INVALID_ARG but I don't know + * of any value for which it does. + * 4. The MSDN documentation currently declares that the second argument is + * unsigned char *, even for the W version. I don't believe it. + */ +RPC_STATUS RPC_ENTRY DceErrorInqTextW (RPC_STATUS e, RPC_WSTR buffer) +{ + DWORD count; + count = FormatMessageW (FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, e, 0, buffer, MAX_RPC_ERROR_TEXT, NULL); + if (!count) + { + count = FormatMessageW (FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, RPC_S_NOT_RPC_ERROR, 0, buffer, MAX_RPC_ERROR_TEXT, NULL); + if (!count) + { + ERR ("Failed to translate error\n"); + return RPC_S_INVALID_ARG; + } + } + return RPC_S_OK; +} + +/****************************************************************************** + * DceErrorInqTextA (rpcrt4.@) + */ +RPC_STATUS RPC_ENTRY DceErrorInqTextA (RPC_STATUS e, RPC_CSTR buffer) +{ + RPC_STATUS status; + WCHAR bufferW [MAX_RPC_ERROR_TEXT]; + if ((status = DceErrorInqTextW (e, bufferW)) == RPC_S_OK) + { + if (!WideCharToMultiByte(CP_ACP, 0, bufferW, -1, (LPSTR)buffer, MAX_RPC_ERROR_TEXT, + NULL, NULL)) + { + ERR ("Failed to translate error\n"); + status = RPC_S_INVALID_ARG; + } + } + return status; +} + +/****************************************************************************** + * I_RpcAllocate (rpcrt4.@) + */ +void * WINAPI I_RpcAllocate(unsigned int Size) +{ + return HeapAlloc(GetProcessHeap(), 0, Size); +} + +/****************************************************************************** + * I_RpcFree (rpcrt4.@) + */ +void WINAPI I_RpcFree(void *Object) +{ + HeapFree(GetProcessHeap(), 0, Object); +} + +/****************************************************************************** + * I_RpcMapWin32Status (rpcrt4.@) + */ +LONG WINAPI I_RpcMapWin32Status(RPC_STATUS status) +{ + FIXME("(%ld): stub\n", status); + return 0; +} + +/****************************************************************************** + * RpcErrorStartEnumeration (rpcrt4.@) + */ +RPC_STATUS RPC_ENTRY RpcErrorStartEnumeration(RPC_ERROR_ENUM_HANDLE* EnumHandle) +{ + FIXME("(%p): stub\n", EnumHandle); + return RPC_S_ENTRY_NOT_FOUND; +} + +/****************************************************************************** + * RpcMgmtSetCancelTimeout (rpcrt4.@) + */ +RPC_STATUS RPC_ENTRY RpcMgmtSetCancelTimeout(LONG Timeout) +{ + FIXME("(%d): stub\n", Timeout); + return RPC_S_OK; +} + +static struct threaddata *get_or_create_threaddata(void) +{ + struct threaddata *tdata = NtCurrentTeb()->ReservedForNtRpc; + if (!tdata) + { + tdata = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*tdata)); + if (!tdata) return NULL; + + InitializeCriticalSection(&tdata->cs); + tdata->thread_id = GetCurrentThreadId(); + + EnterCriticalSection(&threaddata_cs); + list_add_tail(&threaddata_list, &tdata->entry); + LeaveCriticalSection(&threaddata_cs); + + NtCurrentTeb()->ReservedForNtRpc = tdata; + return tdata; + } + return tdata; +} + +void RPCRT4_SetThreadCurrentConnection(RpcConnection *Connection) +{ + struct threaddata *tdata = get_or_create_threaddata(); + if (!tdata) return; + + EnterCriticalSection(&tdata->cs); + tdata->connection = Connection; + LeaveCriticalSection(&tdata->cs); +} + +void RPCRT4_SetThreadCurrentCallHandle(RpcBinding *Binding) +{ + struct threaddata *tdata = get_or_create_threaddata(); + if (!tdata) return; + + tdata->server_binding = Binding; +} + +RpcBinding *RPCRT4_GetThreadCurrentCallHandle(void) +{ + struct threaddata *tdata = get_or_create_threaddata(); + if (!tdata) return NULL; + + return tdata->server_binding; +} + +void RPCRT4_PushThreadContextHandle(NDR_SCONTEXT SContext) +{ + struct threaddata *tdata = get_or_create_threaddata(); + struct context_handle_list *context_handle_list; + + if (!tdata) return; + + context_handle_list = HeapAlloc(GetProcessHeap(), 0, sizeof(*context_handle_list)); + if (!context_handle_list) return; + + context_handle_list->context_handle = SContext; + context_handle_list->next = tdata->context_handle_list; + tdata->context_handle_list = context_handle_list; +} + +void RPCRT4_RemoveThreadContextHandle(NDR_SCONTEXT SContext) +{ + struct threaddata *tdata = get_or_create_threaddata(); + struct context_handle_list *current, *prev; + + if (!tdata) return; + + for (current = tdata->context_handle_list, prev = NULL; current; prev = current, current = current->next) + { + if (current->context_handle == SContext) + { + if (prev) + prev->next = current->next; + else + tdata->context_handle_list = current->next; + HeapFree(GetProcessHeap(), 0, current); + return; + } + } +} + +NDR_SCONTEXT RPCRT4_PopThreadContextHandle(void) +{ + struct threaddata *tdata = get_or_create_threaddata(); + struct context_handle_list *context_handle_list; + NDR_SCONTEXT context_handle; + + if (!tdata) return NULL; + + context_handle_list = tdata->context_handle_list; + if (!context_handle_list) return NULL; + tdata->context_handle_list = context_handle_list->next; + + context_handle = context_handle_list->context_handle; + HeapFree(GetProcessHeap(), 0, context_handle_list); + return context_handle; +} + +/****************************************************************************** + * RpcCancelThread (rpcrt4.@) + */ +RPC_STATUS RPC_ENTRY RpcCancelThread(void* ThreadHandle) +{ + DWORD target_tid; + struct threaddata *tdata; + + TRACE("(%p)\n", ThreadHandle); + + target_tid = GetThreadId(ThreadHandle); + if (!target_tid) + return RPC_S_INVALID_ARG; + + EnterCriticalSection(&threaddata_cs); + LIST_FOR_EACH_ENTRY(tdata, &threaddata_list, struct threaddata, entry) + if (tdata->thread_id == target_tid) + { + EnterCriticalSection(&tdata->cs); + if (tdata->connection) rpcrt4_conn_cancel_call(tdata->connection); + LeaveCriticalSection(&tdata->cs); + break; + } + LeaveCriticalSection(&threaddata_cs); + + return RPC_S_OK; +} diff --git a/reactos/dll/win32/rpcrt4_new/rpcrt4_ros.diff b/reactos/dll/win32/rpcrt4_new/rpcrt4_ros.diff index 595706b0b60..54d83860622 100644 --- a/reactos/dll/win32/rpcrt4_new/rpcrt4_ros.diff +++ b/reactos/dll/win32/rpcrt4_new/rpcrt4_ros.diff @@ -1,101 +1,115 @@ -Index: rpc_transport.c -=================================================================== ---- rpc_transport.c (revision 27793) -+++ rpc_transport.c (working copy) -@@ -56,9 +56,6 @@ +--- H:\Working Copies\wine\dlls\rpcrt4\rpc_transport.c Sun Jan 06 19:27:38 2008 ++++ H:\Working Copies\ReactOS\trunk\reactos\dll\win32\rpcrt4\rpc_transport.c Sun Jan 06 19:28:07 2008 +@@ -56,6 +56,9 @@ #include #endif --#include --#include -- ++#include ++#include ++ #include "windef.h" #include "winbase.h" #include "winnls.h" -@@ -76,8 +73,6 @@ +@@ -73,6 +76,8 @@ #include "rpc_server.h" #include "epm_towers.h" --#include "unix_func.h" -- ++#include "unix_func.h" ++ #ifndef SOL_TCP # define SOL_TCP IPPROTO_TCP #endif -@@ -781,7 +776,7 @@ +@@ -128,7 +133,7 @@ + RpcConnection_np *npc = (RpcConnection_np *) Connection; + TRACE("listening on %s\n", pname); + +- npc->pipe = CreateNamedPipeA(pname, PIPE_ACCESS_DUPLEX, ++ npc->pipe = CreateNamedPipeA(pname, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, + PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, + PIPE_UNLIMITED_INSTANCES, + RPC_MAX_PACKET_SIZE, RPC_MAX_PACKET_SIZE, 5000, NULL); +@@ -715,12 +720,14 @@ + if (tcpc == NULL) + return NULL; + tcpc->sock = -1; ++#ifndef __REACTOS__ + if (socketpair(PF_UNIX, SOCK_STREAM, 0, tcpc->cancel_fds) < 0) + { + ERR("socketpair() failed: %s\n", strerror(errno)); + HeapFree(GetProcessHeap(), 0, tcpc); + return NULL; + } ++#endif + return &tcpc->common; + } + +@@ -785,8 +792,7 @@ /* RPC depends on having minimal latency so disable the Nagle algorithm */ val = 1; -- setsockopt(sock, SOL_TCP, TCP_NODELAY, (char *)&val, sizeof(val)); -+ setsockopt(sock, SOL_TCP, TCP_NODELAY, &val, sizeof(val)); +- setsockopt(sock, SOL_TCP, TCP_NODELAY, &val, sizeof(val)); +- fcntl(sock, F_SETFL, O_NONBLOCK); /* make socket nonblocking */ ++ setsockopt(sock, SOL_TCP, TCP_NODELAY, (char *)&val, sizeof(val)); tcpc->sock = sock; -@@ -804,7 +799,6 @@ +@@ -808,6 +814,7 @@ + struct addrinfo *ai; struct addrinfo *ai_cur; struct addrinfo hints; ++ u_long blocking; RpcConnection *first_connection = NULL; -- u_long blocking; TRACE("(%p, %s)\n", protseq, endpoint); - -@@ -855,7 +849,7 @@ +@@ -859,7 +866,7 @@ { WARN("bind failed: %s\n", strerror(errno)); close(sock); -- if (errno == WSAEADDRINUSE) -+ if (errno == EADDRINUSE) +- if (errno == EADDRINUSE) ++ if (errno == WSAEADDRINUSE) status = RPC_S_DUPLICATE_ENDPOINT; else status = RPC_S_CANT_CREATE_ENDPOINT; -@@ -884,8 +878,7 @@ +@@ -888,7 +895,8 @@ * race-condition (poll() says it is readable, connection drops, * and accept() blocks until the next connection comes...) */ -- blocking = 1; -- ret = ioctlsocket(sock, FIONBIO, &blocking); -+ ret = fcntl(sock, F_SETFL, O_NONBLOCK); +- ret = fcntl(sock, F_SETFL, O_NONBLOCK); ++ blocking = 1; ++ ret = ioctlsocket(sock, FIONBIO, &blocking); if (ret < 0) { WARN("couldn't make socket non-blocking, error %d\n", ret); -@@ -928,7 +921,6 @@ +@@ -931,6 +939,7 @@ int ret; struct sockaddr_in address; socklen_t addrsize; -- u_long blocking; ++ u_long blocking; RpcConnection_tcp *server = (RpcConnection_tcp*) old_conn; RpcConnection_tcp *client = (RpcConnection_tcp*) new_conn; -@@ -940,8 +932,7 @@ +@@ -942,7 +951,8 @@ return RPC_S_OUT_OF_RESOURCES; } /* reset to blocking behaviour */ -- blocking = 0; -- ret = ioctlsocket(ret, FIONBIO, &blocking); -+ fcntl(ret, F_SETFL, 0); +- fcntl(ret, F_SETFL, 0); ++ blocking = 0; ++ ret = ioctlsocket(ret, FIONBIO, &blocking); client->sock = ret; TRACE("Accepted a new TCP connection\n"); return RPC_S_OK; -@@ -1125,12 +1116,10 @@ +@@ -1189,10 +1199,12 @@ if (ps) { int fds[2]; -- u_long blocking; ++ u_long blocking; if (!socketpair(PF_UNIX, SOCK_DGRAM, 0, fds)) { -- blocking = 1; -- ioctlsocket(fds[0], FIONBIO, &blocking); -- ioctlsocket(fds[1], FIONBIO, &blocking); -+ fcntl(fds[0], F_SETFL, O_NONBLOCK); -+ fcntl(fds[1], F_SETFL, O_NONBLOCK); +- fcntl(fds[0], F_SETFL, O_NONBLOCK); +- fcntl(fds[1], F_SETFL, O_NONBLOCK); ++ blocking = 1; ++ ioctlsocket(fds[0], FIONBIO, &blocking); ++ ioctlsocket(fds[1], FIONBIO, &blocking); ps->mgr_event_rcv = fds[0]; ps->mgr_event_snd = fds[1]; } -@@ -1211,7 +1200,7 @@ - - if (!poll_info) - return -1; -- -+ - ret = poll(poll_info, count, -1); - if (ret < 0) - { diff --git a/reactos/dll/win32/rpcrt4_new/rpcss_np_client.c b/reactos/dll/win32/rpcrt4_new/rpcss_np_client.c index f18fd56e03d..016f77f5f15 100644 --- a/reactos/dll/win32/rpcrt4_new/rpcss_np_client.c +++ b/reactos/dll/win32/rpcrt4_new/rpcss_np_client.c @@ -1,152 +1,152 @@ -/* - * RPCSS named pipe client implementation - * - * Copyright (C) 2002 Greg Turner - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include -#include - -#include "windef.h" -#include "winbase.h" -#include "wine/rpcss_shared.h" -#include "wine/debug.h" - -#include "rpc_binding.h" - -WINE_DEFAULT_DEBUG_CHANNEL(ole); - -HANDLE RPCRT4_RpcssNPConnect(void) -{ - HANDLE the_pipe; - DWORD dwmode, wait_result; - HANDLE master_mutex = RPCRT4_GetMasterMutex(); - - TRACE("\n"); - - while (TRUE) { - - wait_result = WaitForSingleObject(master_mutex, MASTER_MUTEX_TIMEOUT); - switch (wait_result) { - case WAIT_ABANDONED: - case WAIT_OBJECT_0: - break; - case WAIT_FAILED: - case WAIT_TIMEOUT: - default: - ERR("This should never happen: couldn't enter mutex.\n"); - return NULL; - } - - /* try to open the client side of the named pipe. */ - the_pipe = CreateFileA( - NAME_RPCSS_NAMED_PIPE, /* pipe name */ - GENERIC_READ | GENERIC_WRITE, /* r/w access */ - 0, /* no sharing */ - NULL, /* no security attributes */ - OPEN_EXISTING, /* open an existing pipe */ - 0, /* default attributes */ - NULL /* no template file */ - ); - - if (the_pipe != INVALID_HANDLE_VALUE) - break; - - if (GetLastError() != ERROR_PIPE_BUSY) { - WARN("Unable to open named pipe %s (assuming unavailable).\n", - debugstr_a(NAME_RPCSS_NAMED_PIPE)); - break; - } - - WARN("Named pipe busy (will wait)\n"); - - if (!ReleaseMutex(master_mutex)) - ERR("Failed to release master mutex. Expect deadlock.\n"); - - /* wait for the named pipe. We are only willing to wait for 5 seconds. - It should be available /very/ soon. */ - if (! WaitNamedPipeA(NAME_RPCSS_NAMED_PIPE, MASTER_MUTEX_WAITNAMEDPIPE_TIMEOUT)) - { - ERR("Named pipe unavailable after waiting. Something is probably wrong.\n"); - break; - } - - } - - if (the_pipe != INVALID_HANDLE_VALUE) { - dwmode = PIPE_READMODE_MESSAGE; - /* SetNamedPipeHandleState not implemented ATM, but still seems to work somehow. */ - if (! SetNamedPipeHandleState(the_pipe, &dwmode, NULL, NULL)) - WARN("Failed to set pipe handle state\n"); - } - - if (!ReleaseMutex(master_mutex)) - ERR("Uh oh, failed to leave the RPC Master Mutex!\n"); - - return the_pipe; -} - -BOOL RPCRT4_SendReceiveNPMsg(HANDLE np, PRPCSS_NP_MESSAGE msg, char *vardata, PRPCSS_NP_REPLY reply) -{ - DWORD count; - UINT32 payload_offset; - RPCSS_NP_MESSAGE vardata_payload_msg; - - TRACE("(np == %p, msg == %p, vardata == %p, reply == %p)\n", - np, msg, vardata, reply); - - if (! WriteFile(np, msg, sizeof(RPCSS_NP_MESSAGE), &count, NULL)) { - ERR("write failed.\n"); - return FALSE; - } - - if (count != sizeof(RPCSS_NP_MESSAGE)) { - ERR("write count mismatch.\n"); - return FALSE; - } - - /* process the vardata payload if necessary */ - vardata_payload_msg.message_type = RPCSS_NP_MESSAGE_TYPEID_VARDATAPAYLOADMSG; - vardata_payload_msg.vardata_payload_size = 0; /* meaningless */ - for ( payload_offset = 0; payload_offset < msg->vardata_payload_size; - payload_offset += VARDATA_PAYLOAD_BYTES ) { - TRACE("sending vardata payload. vd=%p, po=%d, ps=%d\n", vardata, - payload_offset, msg->vardata_payload_size); - ZeroMemory(vardata_payload_msg.message.vardatapayloadmsg.payload, VARDATA_PAYLOAD_BYTES); - CopyMemory(vardata_payload_msg.message.vardatapayloadmsg.payload, - vardata, - min( VARDATA_PAYLOAD_BYTES, msg->vardata_payload_size - payload_offset )); - vardata += VARDATA_PAYLOAD_BYTES; - if (! WriteFile(np, &vardata_payload_msg, sizeof(RPCSS_NP_MESSAGE), &count, NULL)) { - ERR("vardata write failed at %u bytes.\n", payload_offset); - return FALSE; - } - } - - if (! ReadFile(np, reply, sizeof(RPCSS_NP_REPLY), &count, NULL)) { - ERR("read failed.\n"); - return FALSE; - } - - if (count != sizeof(RPCSS_NP_REPLY)) { - ERR("read count mismatch. got %d.\n", count); - return FALSE; - } - - /* message execution was successful */ - return TRUE; -} +/* + * RPCSS named pipe client implementation + * + * Copyright (C) 2002 Greg Turner + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include + +#include "windef.h" +#include "winbase.h" +#include "wine/rpcss_shared.h" +#include "wine/debug.h" + +#include "rpc_binding.h" + +WINE_DEFAULT_DEBUG_CHANNEL(ole); + +HANDLE RPCRT4_RpcssNPConnect(void) +{ + HANDLE the_pipe; + DWORD dwmode, wait_result; + HANDLE master_mutex = RPCRT4_GetMasterMutex(); + + TRACE("\n"); + + while (TRUE) { + + wait_result = WaitForSingleObject(master_mutex, MASTER_MUTEX_TIMEOUT); + switch (wait_result) { + case WAIT_ABANDONED: + case WAIT_OBJECT_0: + break; + case WAIT_FAILED: + case WAIT_TIMEOUT: + default: + ERR("This should never happen: couldn't enter mutex.\n"); + return NULL; + } + + /* try to open the client side of the named pipe. */ + the_pipe = CreateFileA( + NAME_RPCSS_NAMED_PIPE, /* pipe name */ + GENERIC_READ | GENERIC_WRITE, /* r/w access */ + 0, /* no sharing */ + NULL, /* no security attributes */ + OPEN_EXISTING, /* open an existing pipe */ + 0, /* default attributes */ + NULL /* no template file */ + ); + + if (the_pipe != INVALID_HANDLE_VALUE) + break; + + if (GetLastError() != ERROR_PIPE_BUSY) { + WARN("Unable to open named pipe %s (assuming unavailable).\n", + debugstr_a(NAME_RPCSS_NAMED_PIPE)); + break; + } + + WARN("Named pipe busy (will wait)\n"); + + if (!ReleaseMutex(master_mutex)) + ERR("Failed to release master mutex. Expect deadlock.\n"); + + /* wait for the named pipe. We are only willing to wait for 5 seconds. + It should be available /very/ soon. */ + if (! WaitNamedPipeA(NAME_RPCSS_NAMED_PIPE, MASTER_MUTEX_WAITNAMEDPIPE_TIMEOUT)) + { + ERR("Named pipe unavailable after waiting. Something is probably wrong.\n"); + break; + } + + } + + if (the_pipe != INVALID_HANDLE_VALUE) { + dwmode = PIPE_READMODE_MESSAGE; + /* SetNamedPipeHandleState not implemented ATM, but still seems to work somehow. */ + if (! SetNamedPipeHandleState(the_pipe, &dwmode, NULL, NULL)) + WARN("Failed to set pipe handle state\n"); + } + + if (!ReleaseMutex(master_mutex)) + ERR("Uh oh, failed to leave the RPC Master Mutex!\n"); + + return the_pipe; +} + +BOOL RPCRT4_SendReceiveNPMsg(HANDLE np, PRPCSS_NP_MESSAGE msg, char *vardata, PRPCSS_NP_REPLY reply) +{ + DWORD count; + UINT32 payload_offset; + RPCSS_NP_MESSAGE vardata_payload_msg; + + TRACE("(np == %p, msg == %p, vardata == %p, reply == %p)\n", + np, msg, vardata, reply); + + if (! WriteFile(np, msg, sizeof(RPCSS_NP_MESSAGE), &count, NULL)) { + ERR("write failed.\n"); + return FALSE; + } + + if (count != sizeof(RPCSS_NP_MESSAGE)) { + ERR("write count mismatch.\n"); + return FALSE; + } + + /* process the vardata payload if necessary */ + vardata_payload_msg.message_type = RPCSS_NP_MESSAGE_TYPEID_VARDATAPAYLOADMSG; + vardata_payload_msg.vardata_payload_size = 0; /* meaningless */ + for ( payload_offset = 0; payload_offset < msg->vardata_payload_size; + payload_offset += VARDATA_PAYLOAD_BYTES ) { + TRACE("sending vardata payload. vd=%p, po=%d, ps=%d\n", vardata, + payload_offset, msg->vardata_payload_size); + ZeroMemory(vardata_payload_msg.message.vardatapayloadmsg.payload, VARDATA_PAYLOAD_BYTES); + CopyMemory(vardata_payload_msg.message.vardatapayloadmsg.payload, + vardata, + min( VARDATA_PAYLOAD_BYTES, msg->vardata_payload_size - payload_offset )); + vardata += VARDATA_PAYLOAD_BYTES; + if (! WriteFile(np, &vardata_payload_msg, sizeof(RPCSS_NP_MESSAGE), &count, NULL)) { + ERR("vardata write failed at %u bytes.\n", payload_offset); + return FALSE; + } + } + + if (! ReadFile(np, reply, sizeof(RPCSS_NP_REPLY), &count, NULL)) { + ERR("read failed.\n"); + return FALSE; + } + + if (count != sizeof(RPCSS_NP_REPLY)) { + ERR("read count mismatch. got %d.\n", count); + return FALSE; + } + + /* message execution was successful */ + return TRUE; +} diff --git a/reactos/dll/win32/rpcrt4_new/rpcss_np_client.h b/reactos/dll/win32/rpcrt4_new/rpcss_np_client.h index 5b21cfe2869..db65d432bca 100644 --- a/reactos/dll/win32/rpcrt4_new/rpcss_np_client.h +++ b/reactos/dll/win32/rpcrt4_new/rpcss_np_client.h @@ -1,26 +1,26 @@ -/* - * Copyright (C) 2002 Greg Turner - * - * 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 - */ - -#ifndef __WINE_RPCSS_NP_CLIENT_H -#define __WINE_RPCSS_NP_CLIENT_H - -/* rpcss_np_client.c */ -HANDLE RPC_RpcssNPConnect(void); -BOOL RPCRT4_SendReceiveNPMsg(HANDLE, PRPCSS_NP_MESSAGE, char *, PRPCSS_NP_REPLY); - -#endif /* __RPCSS_NP_CLINET_H */ +/* + * Copyright (C) 2002 Greg Turner + * + * 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 + */ + +#ifndef __WINE_RPCSS_NP_CLIENT_H +#define __WINE_RPCSS_NP_CLIENT_H + +/* rpcss_np_client.c */ +HANDLE RPC_RpcssNPConnect(void); +BOOL RPCRT4_SendReceiveNPMsg(HANDLE, PRPCSS_NP_MESSAGE, char *, PRPCSS_NP_REPLY); + +#endif /* __RPCSS_NP_CLINET_H */ diff --git a/reactos/dll/win32/rpcrt4_new/unix_func.c b/reactos/dll/win32/rpcrt4_new/unix_func.c index 7ccc7429a72..9e29098756e 100644 --- a/reactos/dll/win32/rpcrt4_new/unix_func.c +++ b/reactos/dll/win32/rpcrt4_new/unix_func.c @@ -1,169 +1,169 @@ -#include -#include -#include -#include -#include "unix_func.h" - - -int -poll(struct pollfd *fds, - unsigned long nfds, - int timo) -{ - TIMEVAL timeout, *toptr; - FD_SET ifds, ofds, efds, *ip, *op; - int i, rc, n = -1; - - ip = op = NULL; - - FD_ZERO(&ifds); - FD_ZERO(&ofds); - FD_ZERO(&efds); - - for (i = 0; i < nfds; ++i) - { - fds[i].revents = 0; - - if (fds[i].fd < 0) - continue; - - if (fds[i].fd > n) - n = fds[i].fd; - - if (fds[i].events & (POLLIN|POLLPRI)) - { - ip = &ifds; - FD_SET(fds[i].fd, ip); - } - - if (fds[i].events & POLLOUT) - { - op = &ofds; - FD_SET(fds[i].fd, op); - } - - FD_SET(fds[i].fd, &efds); - } - - if (timo < 0) - toptr = 0; - else - { - toptr = &timeout; - timeout.tv_sec = timo / 1000; - timeout.tv_usec = (timo - timeout.tv_sec * 1000) * 1000; - } - - rc = select(++n, ip, op, &efds, toptr); - - if (rc <= 0) - return rc; - - for (i = 0, n = 0; i < nfds; ++i) - { - if (fds[i].fd < 0) continue; - - if (fds[i].events & (POLLIN|POLLPRI) && FD_ISSET(i, &ifds)) - fds[i].revents |= POLLIN; - - if (fds[i].events & POLLOUT && FD_ISSET(i, &ofds)) - fds[i].revents |= POLLOUT; - - if (FD_ISSET(i, &efds)) - fds[i].revents |= POLLHUP; - } - - return rc; -} - - -int socketpair(int af, - int type, - int protocol, - SOCKET socks[2]) -{ - struct sockaddr_in addr; - SOCKET listener; - int e; - int addrlen = sizeof(addr); - DWORD flags = 0; //(make_overlapped ? WSA_FLAG_OVERLAPPED : 0); - - if (socks == 0) - { - WSASetLastError(WSAEINVAL); - return SOCKET_ERROR; - } - - socks[0] = socks[1] = INVALID_SOCKET; - if ((listener = socket(af, type, 0)) == INVALID_SOCKET) - return SOCKET_ERROR; - - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = htonl(0x7f000001); - addr.sin_port = 0; - - e = bind(listener, (const struct sockaddr*) &addr, sizeof(addr)); - if (e == SOCKET_ERROR) - { - e = WSAGetLastError(); - closesocket(listener); - WSASetLastError(e); - return SOCKET_ERROR; - } - e = getsockname(listener, (struct sockaddr*) &addr, &addrlen); - if (e == SOCKET_ERROR) - { - e = WSAGetLastError(); - closesocket(listener); - WSASetLastError(e); - return SOCKET_ERROR; - } - - do - { - if (listen(listener, 1) == SOCKET_ERROR) - break; - if ((socks[0] = WSASocket(af, type, 0, NULL, 0, flags)) == INVALID_SOCKET) - break; - if (connect(socks[0], (const struct sockaddr*) &addr, sizeof(addr)) == SOCKET_ERROR) - break; - if ((socks[1] = accept(listener, NULL, NULL)) == INVALID_SOCKET) - break; - - closesocket(listener); - return 0; - - } while (0); - - e = WSAGetLastError(); - closesocket(listener); - closesocket(socks[0]); - closesocket(socks[1]); - WSASetLastError(e); - return SOCKET_ERROR; -} - - -const char * -inet_ntop (int af, - const void *src, - char *dst, - size_t cnt) -{ - struct in_addr in; - char *text_addr; - - if (af == AF_INET) - { - memcpy(&in.s_addr, src, sizeof(in.s_addr)); - text_addr = inet_ntoa(in); - if (text_addr && dst) - { - strncpy(dst, text_addr, cnt); - return dst; - } - } - - return 0; -} +#include +#include +#include +#include +#include "unix_func.h" + + +int +poll(struct pollfd *fds, + unsigned long nfds, + int timo) +{ + TIMEVAL timeout, *toptr; + FD_SET ifds, ofds, efds, *ip, *op; + int i, rc, n = -1; + + ip = op = NULL; + + FD_ZERO(&ifds); + FD_ZERO(&ofds); + FD_ZERO(&efds); + + for (i = 0; i < nfds; ++i) + { + fds[i].revents = 0; + + if (fds[i].fd < 0) + continue; + + if (fds[i].fd > n) + n = fds[i].fd; + + if (fds[i].events & (POLLIN|POLLPRI)) + { + ip = &ifds; + FD_SET(fds[i].fd, ip); + } + + if (fds[i].events & POLLOUT) + { + op = &ofds; + FD_SET(fds[i].fd, op); + } + + FD_SET(fds[i].fd, &efds); + } + + if (timo < 0) + toptr = 0; + else + { + toptr = &timeout; + timeout.tv_sec = timo / 1000; + timeout.tv_usec = (timo - timeout.tv_sec * 1000) * 1000; + } + + rc = select(++n, ip, op, &efds, toptr); + + if (rc <= 0) + return rc; + + for (i = 0, n = 0; i < nfds; ++i) + { + if (fds[i].fd < 0) continue; + + if (fds[i].events & (POLLIN|POLLPRI) && FD_ISSET(i, &ifds)) + fds[i].revents |= POLLIN; + + if (fds[i].events & POLLOUT && FD_ISSET(i, &ofds)) + fds[i].revents |= POLLOUT; + + if (FD_ISSET(i, &efds)) + fds[i].revents |= POLLHUP; + } + + return rc; +} + + +int socketpair(int af, + int type, + int protocol, + SOCKET socks[2]) +{ + struct sockaddr_in addr; + SOCKET listener; + int e; + int addrlen = sizeof(addr); + DWORD flags = 0; //(make_overlapped ? WSA_FLAG_OVERLAPPED : 0); + + if (socks == 0) + { + WSASetLastError(WSAEINVAL); + return SOCKET_ERROR; + } + + socks[0] = socks[1] = INVALID_SOCKET; + if ((listener = socket(af, type, 0)) == INVALID_SOCKET) + return SOCKET_ERROR; + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htonl(0x7f000001); + addr.sin_port = 0; + + e = bind(listener, (const struct sockaddr*) &addr, sizeof(addr)); + if (e == SOCKET_ERROR) + { + e = WSAGetLastError(); + closesocket(listener); + WSASetLastError(e); + return SOCKET_ERROR; + } + e = getsockname(listener, (struct sockaddr*) &addr, &addrlen); + if (e == SOCKET_ERROR) + { + e = WSAGetLastError(); + closesocket(listener); + WSASetLastError(e); + return SOCKET_ERROR; + } + + do + { + if (listen(listener, 1) == SOCKET_ERROR) + break; + if ((socks[0] = WSASocket(af, type, 0, NULL, 0, flags)) == INVALID_SOCKET) + break; + if (connect(socks[0], (const struct sockaddr*) &addr, sizeof(addr)) == SOCKET_ERROR) + break; + if ((socks[1] = accept(listener, NULL, NULL)) == INVALID_SOCKET) + break; + + closesocket(listener); + return 0; + + } while (0); + + e = WSAGetLastError(); + closesocket(listener); + closesocket(socks[0]); + closesocket(socks[1]); + WSASetLastError(e); + return SOCKET_ERROR; +} + + +const char * +inet_ntop (int af, + const void *src, + char *dst, + size_t cnt) +{ + struct in_addr in; + char *text_addr; + + if (af == AF_INET) + { + memcpy(&in.s_addr, src, sizeof(in.s_addr)); + text_addr = inet_ntoa(in); + if (text_addr && dst) + { + strncpy(dst, text_addr, cnt); + return dst; + } + } + + return 0; +} diff --git a/reactos/dll/win32/rpcrt4_new/unix_func.h b/reactos/dll/win32/rpcrt4_new/unix_func.h index 49d4b2b79d0..b4c04976458 100644 --- a/reactos/dll/win32/rpcrt4_new/unix_func.h +++ b/reactos/dll/win32/rpcrt4_new/unix_func.h @@ -1,19 +1,19 @@ - -#define POLLIN 001 -#define POLLPRI 002 -#define POLLOUT 004 -#define POLLNORM POLLIN -#define POLLERR 010 -#define POLLHUP 020 -#define POLLNVAL 040 - -struct pollfd -{ - int fd; /* file descriptor */ - short events; /* requested events */ - short revents; /* returned events */ -}; - -int poll(struct pollfd *fds, unsigned long nfds, int timo); -int socketpair (int af, int type, int protocol, SOCKET socket[2]); -const char * inet_ntop (int af, const void *src, char *dst, size_t cnt); + +#define POLLIN 001 +#define POLLPRI 002 +#define POLLOUT 004 +#define POLLNORM POLLIN +#define POLLERR 010 +#define POLLHUP 020 +#define POLLNVAL 040 + +struct pollfd +{ + int fd; /* file descriptor */ + short events; /* requested events */ + short revents; /* returned events */ +}; + +int poll(struct pollfd *fds, unsigned long nfds, int timo); +int socketpair (int af, int type, int protocol, SOCKET socket[2]); +const char * inet_ntop (int af, const void *src, char *dst, size_t cnt);