- new rpcrt4 from Wine-0_9_41 which is a big move from our current implementation, thus I've added it as a separate module for now until we have it working.

- includes an additional file, unix_func.c, which implements 3 unix API's which aren't available in Windows (poll, socketpair, inet_ntop)
- It builds, but it's completely untested.

svn path=/trunk/; revision=27793
This commit is contained in:
Ged Murphy 2007-07-23 22:26:34 +00:00
parent 64d9543194
commit b4fe4fe1f5
30 changed files with 18333 additions and 0 deletions

View file

@ -0,0 +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 <stdarg.h>
#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; i<count; i++) {
struct StublessThunk *thunk = &This->thunks[i];
if (vtbl->Vtbl[i] == (LPVOID)-1) {
PFORMAT_STRING fs = stubless->ProcFormatString + stubless->FormatStringOffset[i];
unsigned bytes = *(const WORD*)(fs+8) - STACK_ADJUST;
TRACE("method %ld: stacksize=%d\n", i, bytes);
FILL_STUBLESS(thunk, i, bytes)
This->PVtbl[i] = thunk;
}
else {
memset(thunk, 0, sizeof(struct StublessThunk));
This->PVtbl[i] = vtbl->Vtbl[i];
}
}
}
else
This->PVtbl = vtbl->Vtbl;
This->lpVtbl = &StdProxy_Vtbl;
/* 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;
}

View file

@ -0,0 +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 <stdarg.h>
#include <stdio.h>
#include <string.h>
#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;
}

View file

@ -0,0 +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 */

View file

@ -0,0 +1,587 @@
/*
* 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 <stdarg.h>
#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 (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
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;
IUnknownVtbl vtbl;
} ref_counted_vtbl;
static struct
{
ref_counted_vtbl *table;
DWORD size;
} 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, 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*)((void **)vtbl + num);
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(num_methods > current_vtbl.size)
{
DWORD size;
if(current_vtbl.table && current_vtbl.table->ref == 0)
{
TRACE("freeing old table\n");
HeapFree(GetProcessHeap(), 0, current_vtbl.table);
}
size = sizeof(DWORD) + num_methods * sizeof(void*) + (num_methods - 3) * sizeof(vtbl_method_t);
current_vtbl.table = HeapAlloc(GetProcessHeap(), 0, size);
fill_table(&current_vtbl.table->vtbl, num_methods);
current_vtbl.table->ref = 0;
current_vtbl.size = num_methods;
}
LeaveCriticalSection(&delegating_vtbl_section);
}
static IUnknownVtbl *get_delegating_vtbl(void)
{
IUnknownVtbl *ret;
EnterCriticalSection(&delegating_vtbl_section);
current_vtbl.table->ref++;
ret = &current_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");
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;
}
/***********************************************************************
* 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->BufferStart = pStubMsg->RpcMsg->Buffer;
pStubMsg->BufferEnd = pStubMsg->BufferStart + pStubMsg->BufferLength;
pStubMsg->Buffer = pStubMsg->BufferStart;
}

View file

@ -0,0 +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 <pshpack1.h>
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 <poppack.h>

View file

@ -0,0 +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

View file

@ -0,0 +1,207 @@
/*
* 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 <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#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);
assert( pRpcMessage && pStubMsg && pStubDesc );
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);
assert( pRpcMsg && pStubMsg && pStubDesc );
/* not everyone allocates stack space for w2kReserved */
memset(pStubMsg, 0, FIELD_OFFSET(MIDL_STUB_MESSAGE,pCSInfo));
pStubMsg->ReuseBuffer = TRUE;
pStubMsg->IsClient = FALSE;
pStubMsg->StubDesc = pStubDesc;
pStubMsg->pfnAllocate = pStubDesc->pfnAllocate;
pStubMsg->pfnFree = pStubDesc->pfnFree;
pStubMsg->RpcMsg = pRpcMsg;
pStubMsg->Buffer = pStubMsg->BufferStart = pRpcMsg->Buffer;
pStubMsg->BufferLength = pRpcMsg->BufferLength;
pStubMsg->BufferEnd = pStubMsg->Buffer + pStubMsg->BufferLength;
/* FIXME: determine the proper return value */
return NULL;
}
/***********************************************************************
* NdrGetBuffer [RPCRT4.@]
*/
unsigned char *WINAPI NdrGetBuffer(PMIDL_STUB_MESSAGE stubmsg, ULONG buflen, RPC_BINDING_HANDLE handle)
{
TRACE("(stubmsg == ^%p, buflen == %u, handle == %p): wild guess.\n", stubmsg, buflen, handle);
assert( stubmsg && stubmsg->RpcMsg );
/* I guess this is our chance to put the binding handle into the RPC_MESSAGE */
stubmsg->RpcMsg->Handle = handle;
stubmsg->RpcMsg->BufferLength = buflen;
if (I_RpcGetBuffer(stubmsg->RpcMsg) != S_OK)
return NULL;
stubmsg->Buffer = stubmsg->BufferStart = stubmsg->RpcMsg->Buffer;
stubmsg->BufferLength = stubmsg->RpcMsg->BufferLength;
stubmsg->BufferEnd = stubmsg->Buffer + stubmsg->BufferLength;
return (stubmsg->Buffer = (unsigned char *)stubmsg->RpcMsg->Buffer);
}
/***********************************************************************
* NdrFreeBuffer [RPCRT4.@]
*/
void WINAPI NdrFreeBuffer(PMIDL_STUB_MESSAGE pStubMsg)
{
TRACE("(pStubMsg == ^%p): wild guess.\n", pStubMsg);
I_RpcFreeBuffer(pStubMsg->RpcMsg);
pStubMsg->BufferLength = 0;
pStubMsg->Buffer = pStubMsg->BufferEnd = (unsigned char *)(pStubMsg->RpcMsg->Buffer = NULL);
}
/************************************************************************
* 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;
}

View file

@ -0,0 +1,233 @@
/*
* 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 <stdarg.h>
#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)
{
TRACE("(%p)\n", pXlatTables);
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;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +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 <stdarg.h>
#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 */

View file

@ -0,0 +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 <stdarg.h>
#include <stdio.h>
#include <string.h>
#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;
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 > (char *)This->pMsg->BufferEnd)
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 = (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;
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,201 @@
/*
* 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 "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;
typedef struct _RpcAssoc
{
struct list entry; /* entry in the global list of associations */
LONG refs;
LPSTR Protseq;
LPSTR NetworkAddr;
LPSTR Endpoint;
LPWSTR NetworkOptions;
/* id of this association group */
ULONG assoc_group_id;
CRITICAL_SECTION cs;
struct list connection_pool;
} RpcAssoc;
struct connection_ops;
typedef struct _RpcConnection
{
struct _RpcConnection* Next;
BOOL server;
LPSTR NetworkAddr;
LPSTR Endpoint;
LPWSTR NetworkOptions;
const struct connection_ops *ops;
USHORT MaxTransmissionSize;
/* The active interface bound to server. */
RPC_SYNTAX_IDENTIFIER ActiveInterface;
USHORT NextCallId;
/* 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 */
} 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);
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;
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_GetAssociation(LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint, LPCWSTR NetworkOptions, RpcAssoc **assoc);
RPC_STATUS RpcAssoc_GetClientConnection(RpcAssoc *assoc, const RPC_SYNTAX_IDENTIFIER *InterfaceId, const RPC_SYNTAX_IDENTIFIER *TransferSyntax, RpcAuthInfo *AuthInfo, RpcQualityOfService *QOS, RpcConnection **Connection);
void RpcAssoc_ReleaseIdleConnection(RpcAssoc *assoc, RpcConnection *Connection);
ULONG RpcAssoc_Release(RpcAssoc *assoc);
RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server, LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint, LPCWSTR NetworkOptions, RpcAuthInfo* AuthInfo, RpcQualityOfService *QOS);
RPC_STATUS RPCRT4_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, PRPC_SYNTAX_IDENTIFIER TransferSyntax, PRPC_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(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 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);
#endif

View file

@ -0,0 +1,196 @@
/*
* 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 NO_REASON 0
#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 */

View file

@ -0,0 +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 <stdarg.h>
#include <stdio.h>
#include <string.h>
#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; c<BindingVector->Count; 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; c<UuidVector->Count; 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; c<BindingVector->Count; 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; c<UuidVector->Count; 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;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +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, 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

View file

@ -0,0 +1,28 @@
/*
* 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 */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +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 */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,41 @@
<module name="rpcrt4" type="win32dll" baseaddress="${BASEADDRESS_RPCRT4}" installbase="system32" installname="rpcrt4.dll" allowwarnings="true">
<autoregister infsection="OleControlDlls" type="DllRegisterServer" />
<importlibrary definition="rpcrt4.spec.def" />
<include base="rpcrt4">.</include>
<include base="ReactOS">include/reactos/wine</include>
<define name="__REACTOS__" />
<define name="__USE_W32API" />
<define name="_WIN32_IE">0x600</define>
<define name="_WIN32_WINNT">0x501</define>
<define name="WINVER">0x501</define>
<define name="_STDDEF_H" />
<define name="_RPCRT4_" />
<define name="COM_NO_WINDOWS_H" />
<define name="MSWMSG" />
<library>wine</library>
<library>uuid</library>
<library>ntdll</library>
<library>kernel32</library>
<library>advapi32</library>
<library>secur32</library>
<library>iphlpapi</library>
<library>ws2_32</library>
<file>cproxy.c</file>
<file>cpsf.c</file>
<file>cstub.c</file>
<file>ndr_clientserver.c</file>
<file>ndr_fullpointer.c</file>
<file>ndr_marshall.c</file>
<file>ndr_ole.c</file>
<file>ndr_stubless.c</file>
<file>rpc_binding.c</file>
<file>rpc_epmap.c</file>
<file>rpc_message.c</file>
<file>rpc_server.c</file>
<file>rpc_transport.c</file>
<file>rpcrt4_main.c</file>
<file>rpcss_np_client.c</file>
<file>unix_func.c</file>
<file>rpcrt4.rc</file>
<file>rpcrt4.spec</file>
</module>

View file

@ -0,0 +1,7 @@
#include <windows.h>
#define REACTOS_VERSION_DLL
#define REACTOS_STR_FILE_DESCRIPTION "ReactOS RPC server API\0"
#define REACTOS_STR_INTERNAL_NAME "rpcrt4\0"
#define REACTOS_STR_ORIGINAL_FILENAME "rpcrt4.dll\0"
#include <reactos/version.rc>

View file

@ -0,0 +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
@ stub 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)
@ stub NdrRangeUnmarshall
@ 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
@ stub RpcCancelThread
@ 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
@ stub RpcErrorStartEnumeration # wxp
@ 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
@ stub RpcMgmtSetCancelTimeout
@ 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
@ stub RpcSmDestroyClientContext
@ stub RpcSmDisableAllocate
@ stub RpcSmEnableAllocate
@ stub RpcSmFree
@ stub RpcSmGetThreadHandle
@ stub RpcSmSetClientAllocFree
@ stub RpcSmSetThreadHandle
@ stub RpcSmSwapClientAllocFree
@ stub RpcSsAllocate
@ stub RpcSsContextLockExclusive # wxp
@ stub RpcSsContextLockShared # wxp
@ stub RpcSsDestroyClientContext
@ 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

View file

@ -0,0 +1,830 @@
/*
* 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 <gmturner007@ameritech.net> or send a patch to the
* wine-patches mailing list.
*/
#include "config.h"
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "windef.h"
#include "winerror.h"
#include "winbase.h"
#include "winuser.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 };
/***********************************************************************
* 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)
{
switch (fdwReason) {
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hinstDLL);
master_mutex = CreateMutexA( NULL, FALSE, RPCSS_MASTER_MUTEX_NAME);
if (!master_mutex)
ERR("Failed to create master mutex\n");
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 WINAPI RpcRaiseException(RPC_STATUS exception)
{
/* FIXME: translate exception? */
RaiseException(exception, 0, 0, NULL);
}
/*************************************************************************
* 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; i<sizeof(UUID); i++) {
c0 += data[i];
c1 += c0;
}
x = -c1 % 255;
if (x < 0) x += 255;
y = (c1 - c0) % 255;
if (y < 0) y += 255;
*Status = RPC_S_OK;
return y*256 + x;
}
/*************************************************************************
* UuidToStringA [RPCRT4.@]
*
* Converts a UUID to a string.
*
* UUID format is 8 hex digits, followed by a hyphen then three groups of
* 4 hex digits each followed by a hyphen and then 12 hex digits
*
* RETURNS
*
* S_OK if successful.
* S_OUT_OF_MEMORY if unsuccessful.
*/
RPC_STATUS WINAPI UuidToStringA(UUID *Uuid, RPC_CSTR* StringUuid)
{
*StringUuid = HeapAlloc( GetProcessHeap(), 0, sizeof(char) * 37);
if(!(*StringUuid))
return RPC_S_OUT_OF_MEMORY;
if (!Uuid) Uuid = &uuid_nil;
sprintf( (char*)*StringUuid, "%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] );
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.@)
*/
DWORD WINAPI I_RpcMapWin32Status(RPC_STATUS status)
{
FIXME("(%ld): stub\n", status);
return 0;
}

View file

@ -0,0 +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 <assert.h>
#include <stdarg.h>
#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;
}

View file

@ -0,0 +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 */

View file

@ -0,0 +1,169 @@
#include <string.h>
#include <winsock2.h>
#include <windows.h>
#include <io.h>
#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;
}

View file

@ -0,0 +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);