Implemented Local Server COM.

Implemented the Typelib based Marshaler.
This commit is contained in:
Marcus Meissner 2002-02-05 18:11:17 +00:00 committed by Alexandre Julliard
parent 395e8bafc4
commit 0749fc2034
15 changed files with 3285 additions and 58 deletions

View File

@ -22,6 +22,7 @@ C_SRCS = \
hglobalstream.c \ hglobalstream.c \
ifs.c \ ifs.c \
itemmoniker.c \ itemmoniker.c \
marshal.c \
memlockbytes.c \ memlockbytes.c \
moniker.c \ moniker.c \
ole2.c \ ole2.c \
@ -30,6 +31,8 @@ C_SRCS = \
ole2nls.c \ ole2nls.c \
ole32_main.c \ ole32_main.c \
oleobj.c \ oleobj.c \
oleproxy.c \
rpc.c \
stg_bigblockfile.c \ stg_bigblockfile.c \
stg_stream.c \ stg_stream.c \
storage.c \ storage.c \

View File

@ -5,6 +5,7 @@
* Copyright 1998 Justin Bradford * Copyright 1998 Justin Bradford
* Copyright 1999 Francis Beaudet * Copyright 1999 Francis Beaudet
* Copyright 1999 Sylvain St-Germain * Copyright 1999 Sylvain St-Germain
* Copyright 2002 Marcus Meissner
*/ */
#include "config.h" #include "config.h"
@ -29,6 +30,7 @@
#include "wine/obj_misc.h" #include "wine/obj_misc.h"
#include "wine/obj_marshal.h" #include "wine/obj_marshal.h"
#include "wine/obj_storage.h" #include "wine/obj_storage.h"
#include "wine/obj_channel.h"
#include "wine/winbase16.h" #include "wine/winbase16.h"
#include "compobj_private.h" #include "compobj_private.h"
#include "ifs.h" #include "ifs.h"
@ -138,6 +140,7 @@ typedef struct tagRegisteredClass
DWORD runContext; DWORD runContext;
DWORD connectFlags; DWORD connectFlags;
DWORD dwCookie; DWORD dwCookie;
HANDLE hThread; /* only for localserver */
struct tagRegisteredClass* nextClass; struct tagRegisteredClass* nextClass;
} RegisteredClass; } RegisteredClass;
@ -559,7 +562,7 @@ HRESULT WINAPI CLSIDFromString(
* RETURNS * RETURNS
* the string representation and HRESULT * the string representation and HRESULT
*/ */
static HRESULT WINE_StringFromCLSID( HRESULT WINE_StringFromCLSID(
const CLSID *id, /* [in] GUID to be converted */ const CLSID *id, /* [in] GUID to be converted */
LPSTR idstr /* [out] pointer to buffer to contain converted guid */ LPSTR idstr /* [out] pointer to buffer to contain converted guid */
) { ) {
@ -1060,6 +1063,83 @@ end:
return hr; return hr;
} }
static DWORD WINAPI
_LocalServerThread(LPVOID param) {
HANDLE hPipe;
char pipefn[200];
RegisteredClass *newClass = (RegisteredClass*)param;
HRESULT hres;
IStream *pStm;
STATSTG ststg;
unsigned char *buffer;
int buflen;
IClassFactory *classfac;
LARGE_INTEGER seekto;
ULARGE_INTEGER newpos;
ULONG res;
TRACE("Starting threader for %s.\n",debugstr_guid(&newClass->classIdentifier));
strcpy(pipefn,PIPEPREF);
WINE_StringFromCLSID(&newClass->classIdentifier,pipefn+strlen(PIPEPREF));
hres = IUnknown_QueryInterface(newClass->classObject,&IID_IClassFactory,(LPVOID*)&classfac);
if (hres) return hres;
hres = CreateStreamOnHGlobal(0,TRUE,&pStm);
if (hres) {
FIXME("Failed to create stream on hglobal.\n");
return hres;
}
hres = CoMarshalInterface(pStm,&IID_IClassFactory,(LPVOID)classfac,0,NULL,0);
if (hres) {
FIXME("CoMarshalInterface failed, %lx!\n",hres);
return hres;
}
hres = IStream_Stat(pStm,&ststg,0);
if (hres) return hres;
buflen = ststg.cbSize.s.LowPart;
buffer = HeapAlloc(GetProcessHeap(),0,buflen);
seekto.s.LowPart = 0;
seekto.s.HighPart = 0;
hres = IStream_Seek(pStm,seekto,SEEK_SET,&newpos);
if (hres) {
FIXME("IStream_Seek failed, %lx\n",hres);
return hres;
}
hres = IStream_Read(pStm,buffer,buflen,&res);
if (hres) {
FIXME("Stream Read failed, %lx\n",hres);
return hres;
}
IStream_Release(pStm);
while (1) {
hPipe = CreateNamedPipeA(
pipefn,
PIPE_ACCESS_DUPLEX,
PIPE_TYPE_BYTE|PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES,
4096,
4096,
NMPWAIT_USE_DEFAULT_WAIT,
NULL
);
if (hPipe == INVALID_HANDLE_VALUE) {
FIXME("pipe creation failed for %s, le is %lx\n",pipefn,GetLastError());
return 1;
}
if (!ConnectNamedPipe(hPipe,NULL)) {
ERR("Failure during ConnectNamedPipe %lx, ABORT!\n",GetLastError());
CloseHandle(hPipe);
continue;
}
WriteFile(hPipe,buffer,buflen,&res,NULL);
CloseHandle(hPipe);
}
return 0;
}
/****************************************************************************** /******************************************************************************
* CoRegisterClassObject [OLE32.36] * CoRegisterClassObject [OLE32.36]
* *
@ -1078,24 +1158,13 @@ HRESULT WINAPI CoRegisterClassObject(
RegisteredClass* newClass; RegisteredClass* newClass;
LPUNKNOWN foundObject; LPUNKNOWN foundObject;
HRESULT hr; HRESULT hr;
char buf[80];
WINE_StringFromCLSID(rclsid,buf);
TRACE("(%s,%p,0x%08lx,0x%08lx,%p)\n", TRACE("(%s,%p,0x%08lx,0x%08lx,%p)\n",
buf,pUnk,dwClsContext,flags,lpdwRegister); debugstr_guid(rclsid),pUnk,dwClsContext,flags,lpdwRegister);
/*
* Perform a sanity check on the parameters
*/
if ( (lpdwRegister==0) || (pUnk==0) ) if ( (lpdwRegister==0) || (pUnk==0) )
{
return E_INVALIDARG; return E_INVALIDARG;
}
/*
* Initialize the cookie (out parameter)
*/
*lpdwRegister = 0; *lpdwRegister = 0;
/* /*
@ -1103,35 +1172,24 @@ HRESULT WINAPI CoRegisterClassObject(
* If it is, this should cause an error. * If it is, this should cause an error.
*/ */
hr = COM_GetRegisteredClassObject(rclsid, dwClsContext, &foundObject); hr = COM_GetRegisteredClassObject(rclsid, dwClsContext, &foundObject);
if (hr == S_OK) {
if (hr == S_OK)
{
/*
* The COM_GetRegisteredClassObject increased the reference count on the
* object so it has to be released.
*/
IUnknown_Release(foundObject); IUnknown_Release(foundObject);
return CO_E_OBJISREG; return CO_E_OBJISREG;
} }
/*
* If it is not registered, we must create a new entry for this class and
* append it to the registered class list.
* We use the address of the chain node as the cookie since we are sure it's
* unique.
*/
newClass = HeapAlloc(GetProcessHeap(), 0, sizeof(RegisteredClass)); newClass = HeapAlloc(GetProcessHeap(), 0, sizeof(RegisteredClass));
if ( newClass == NULL ) if ( newClass == NULL )
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
EnterCriticalSection( &csRegisteredClassList ); EnterCriticalSection( &csRegisteredClassList );
/*
* Initialize the node.
*/
newClass->classIdentifier = *rclsid; newClass->classIdentifier = *rclsid;
newClass->runContext = dwClsContext; newClass->runContext = dwClsContext;
newClass->connectFlags = flags; newClass->connectFlags = flags;
/*
* Use the address of the chain node as the cookie since we are sure it's
* unique.
*/
newClass->dwCookie = (DWORD)newClass; newClass->dwCookie = (DWORD)newClass;
newClass->nextClass = firstRegisteredClass; newClass->nextClass = firstRegisteredClass;
@ -1143,17 +1201,16 @@ HRESULT WINAPI CoRegisterClassObject(
IUnknown_AddRef(newClass->classObject); IUnknown_AddRef(newClass->classObject);
firstRegisteredClass = newClass; firstRegisteredClass = newClass;
LeaveCriticalSection( &csRegisteredClassList ); LeaveCriticalSection( &csRegisteredClassList );
/*
* Assign the out parameter (cookie)
*/
*lpdwRegister = newClass->dwCookie; *lpdwRegister = newClass->dwCookie;
/* if (dwClsContext & CLSCTX_LOCAL_SERVER) {
* We're successful Yippee! DWORD tid;
*/
STUBMGR_Start();
newClass->hThread=CreateThread(NULL,0,_LocalServerThread,newClass,0,&tid);
}
return S_OK; return S_OK;
} }
@ -1222,6 +1279,42 @@ end:
return hr; return hr;
} }
static HRESULT WINAPI Remote_CoGetClassObject(
REFCLSID rclsid, DWORD dwClsContext, COSERVERINFO *pServerInfo,
REFIID iid, LPVOID *ppv
) {
HKEY key;
char buf[200];
HRESULT hres = E_UNEXPECTED;
char xclsid[80];
WCHAR dllName[MAX_PATH+1];
DWORD dllNameLen = sizeof(dllName);
STARTUPINFOW sinfo;
PROCESS_INFORMATION pinfo;
WINE_StringFromCLSID((LPCLSID)rclsid,xclsid);
sprintf(buf,"CLSID\\%s\\LocalServer32",xclsid);
hres = RegOpenKeyExA(HKEY_CLASSES_ROOT, buf, 0, KEY_READ, &key);
if (hres != ERROR_SUCCESS)
return REGDB_E_CLASSNOTREG;
memset(dllName,0,sizeof(dllName));
hres= RegQueryValueExW(key,NULL,NULL,NULL,(LPBYTE)dllName,&dllNameLen);
if (hres)
return REGDB_E_CLASSNOTREG; /* FIXME: check retval */
RegCloseKey(key);
TRACE("found LocalServer32 exe %s\n", debugstr_w(dllName));
memset(&sinfo,0,sizeof(sinfo));
sinfo.cb = sizeof(sinfo);
if (!CreateProcessW(NULL,dllName,NULL,NULL,FALSE,0,NULL,NULL,&sinfo,&pinfo))
return E_FAIL;
return create_marshalled_proxy(rclsid,iid,ppv);
}
/*********************************************************************** /***********************************************************************
* CoGetClassObject [COMPOBJ.7] * CoGetClassObject [COMPOBJ.7]
* CoGetClassObject [OLE32.16] * CoGetClassObject [OLE32.16]
@ -1280,9 +1373,22 @@ HRESULT WINAPI CoGetClassObject(
return hres; return hres;
} }
/* Then try for in-process */ if (((CLSCTX_LOCAL_SERVER) & dwClsContext)
if ((CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER) & dwClsContext) && !((CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER) & dwClsContext))
{ return Remote_CoGetClassObject(rclsid,dwClsContext,pServerInfo,iid,ppv);
/* remote servers not supported yet */
if ( ((CLSCTX_REMOTE_SERVER) & dwClsContext)
&& !((CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER) & dwClsContext)
){
FIXME("CLSCTX_REMOTE_SERVER not supported!\n");
return E_NOINTERFACE;
}
if ((CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER) & dwClsContext) {
HKEY key;
char buf[200];
memset(ProviderName,0,sizeof(ProviderName)); memset(ProviderName,0,sizeof(ProviderName));
sprintf(buf,"CLSID\\%s\\InprocServer32",xclsid); sprintf(buf,"CLSID\\%s\\InprocServer32",xclsid);
if (((hres = RegOpenKeyExA(HKEY_CLASSES_ROOT, buf, 0, KEY_READ, &key)) != ERROR_SUCCESS) || if (((hres = RegOpenKeyExA(HKEY_CLASSES_ROOT, buf, 0, KEY_READ, &key)) != ERROR_SUCCESS) ||
@ -1855,18 +1961,6 @@ HRESULT WINAPI CoCreateFreeThreadedMarshaler (LPUNKNOWN punkOuter, LPUNKNOWN* pp
return S_OK; return S_OK;
} }
/***********************************************************************
* DllGetClassObject [OLE32.63]
*/
HRESULT WINAPI OLE32_DllGetClassObject(REFCLSID rclsid, REFIID iid,LPVOID *ppv)
{
FIXME("\n\tCLSID:\t%s,\n\tIID:\t%s\n",debugstr_guid(rclsid),debugstr_guid(iid));
*ppv = NULL;
return CLASS_E_CLASSNOTAVAILABLE;
}
/*** /***
* COM_RevokeAllClasses * COM_RevokeAllClasses
* *

View File

@ -5,6 +5,86 @@
#include "wtypes.h" #include "wtypes.h"
extern HRESULT WINE_StringFromCLSID(const CLSID *id,LPSTR idstr);
extern HRESULT create_marshalled_proxy(REFCLSID rclsid, REFIID iid, LPVOID *ppv);
inline static HRESULT
get_facbuf_for_iid(REFIID riid,IPSFactoryBuffer **facbuf) {
HRESULT hres;
CLSID pxclsid;
if ((hres = CoGetPSClsid(riid,&pxclsid)))
return hres;
return CoGetClassObject(&pxclsid,CLSCTX_INPROC_SERVER,NULL,&IID_IPSFactoryBuffer,(LPVOID*)facbuf);
}
#define PIPEPREF "\\\\.\\pipe\\"
#define OLESTUBMGR PIPEPREF"WINE_OLE_StubMgr"
/* Standard Marshaling definitions */
typedef struct _wine_marshal_id {
DWORD processid;
DWORD objectid; /* unique value corresp. IUnknown of object */
IID iid;
} wine_marshal_id;
inline static BOOL
MARSHAL_Compare_Mids(wine_marshal_id *mid1,wine_marshal_id *mid2) {
return
(mid1->processid == mid2->processid) &&
(mid1->objectid == mid2->objectid) &&
IsEqualIID(&(mid1->iid),&(mid2->iid))
;
}
/* compare without interface compare */
inline static BOOL
MARSHAL_Compare_Mids_NoInterface(wine_marshal_id *mid1, wine_marshal_id *mid2) {
return
(mid1->processid == mid2->processid) &&
(mid1->objectid == mid2->objectid)
;
}
HRESULT MARSHAL_Find_Stub_Buffer(wine_marshal_id *mid,IRpcStubBuffer **stub);
HRESULT MARSHAL_Find_Stub_Server(wine_marshal_id *mid,LPUNKNOWN *punk);
HRESULT MARSHAL_Register_Stub(wine_marshal_id *mid,LPUNKNOWN punk, IRpcStubBuffer *stub);
HRESULT MARSHAL_GetStandardMarshalCF(LPVOID *ppv);
typedef struct _wine_marshal_data {
DWORD dwDestContext;
DWORD mshlflags;
} wine_marshal_data;
#define REQTYPE_REQUEST 0
typedef struct _wine_rpc_request_header {
DWORD reqid;
wine_marshal_id mid;
DWORD iMethod;
DWORD cbBuffer;
} wine_rpc_request_header;
#define REQTYPE_RESPONSE 1
typedef struct _wine_rpc_response_header {
DWORD reqid;
DWORD cbBuffer;
DWORD retval;
} wine_rpc_response_header;
#define REQSTATE_START 0
#define REQSTATE_REQ_QUEUED 1
#define REQSTATE_REQ_WAITING_FOR_REPLY 2
#define REQSTATE_REQ_GOT 3
#define REQSTATE_INVOKING 4
#define REQSTATE_RESP_QUEUED 5
#define REQSTATE_RESP_GOT 6
#define REQSTATE_DONE 6
void STUBMGR_Start();
extern HRESULT PIPE_GetNewPipeBuf(wine_marshal_id *mid, IRpcChannelBuffer **pipebuf);
/* This function initialize the Running Object Table */ /* This function initialize the Running Object Table */
HRESULT WINAPI RunningObjectTableImpl_Initialize(); HRESULT WINAPI RunningObjectTableImpl_Initialize();

615
dlls/ole32/marshal.c Normal file
View File

@ -0,0 +1,615 @@
/*
* Marshaling library
*
* Copyright 2002 Marcus Meissner
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "windef.h"
#include "objbase.h"
#include "ole2.h"
#include "ole2ver.h"
#include "rpc.h"
#include "winerror.h"
#include "winreg.h"
#include "wownt32.h"
#include "wtypes.h"
#include "wine/unicode.h"
#include "wine/obj_base.h"
#include "wine/obj_clientserver.h"
#include "wine/obj_misc.h"
#include "wine/obj_marshal.h"
#include "wine/obj_storage.h"
#include "wine/obj_channel.h"
#include "wine/winbase16.h"
#include "compobj_private.h"
#include "ifs.h"
#include "debugtools.h"
DEFAULT_DEBUG_CHANNEL(ole);
/* Marshaling just passes a unique identifier to the remote client,
* that makes it possible to find the passed interface again.
*
* So basically we need a set of values that make it unique.
*
* Process Identifier, Object IUnknown ptr, IID
*
* Note that the IUnknown_QI(ob,xiid,&ppv) always returns the SAME ppv value!
*/
typedef struct _mid2unknown {
wine_marshal_id mid;
LPUNKNOWN pUnk;
} mid2unknown;
typedef struct _mid2stub {
wine_marshal_id mid;
IRpcStubBuffer *stub;
LPUNKNOWN pUnkServer;
} mid2stub;
static mid2stub *stubs = NULL;
static int nrofstubs = 0;
static mid2unknown *proxies = NULL;
static int nrofproxies = 0;
HRESULT
MARSHAL_Find_Stub_Server(wine_marshal_id *mid,LPUNKNOWN *punk) {
int i;
for (i=0;i<nrofstubs;i++) {
if (MARSHAL_Compare_Mids_NoInterface(mid,&(stubs[i].mid))) {
*punk = stubs[i].pUnkServer;
IUnknown_AddRef((*punk));
return S_OK;
}
}
return E_FAIL;
}
HRESULT
MARSHAL_Find_Stub_Buffer(wine_marshal_id *mid,IRpcStubBuffer **stub) {
int i;
for (i=0;i<nrofstubs;i++) {
if (MARSHAL_Compare_Mids(mid,&(stubs[i].mid))) {
*stub = stubs[i].stub;
IUnknown_AddRef((*stub));
return S_OK;
}
}
return E_FAIL;
}
HRESULT
MARSHAL_Find_Stub(wine_marshal_id *mid,LPUNKNOWN *pUnk) {
int i;
for (i=0;i<nrofstubs;i++) {
if (MARSHAL_Compare_Mids(mid,&(stubs[i].mid))) {
*pUnk = stubs[i].pUnkServer;
IUnknown_AddRef((*pUnk));
return S_OK;
}
}
return E_FAIL;
}
HRESULT
MARSHAL_Register_Stub(wine_marshal_id *mid,LPUNKNOWN pUnk,IRpcStubBuffer *stub) {
LPUNKNOWN xPunk;
if (!MARSHAL_Find_Stub(mid,&xPunk)) {
FIXME("Already have entry for (%lx/%s)!\n",mid->objectid,debugstr_guid(&(mid->iid)));
return S_OK;
}
if (nrofstubs)
stubs=HeapReAlloc(GetProcessHeap(),0,stubs,sizeof(stubs[0])*(nrofstubs+1));
else
stubs=HeapAlloc(GetProcessHeap(),0,sizeof(stubs[0]));
if (!stubs) return E_OUTOFMEMORY;
stubs[nrofstubs].stub = stub;
stubs[nrofstubs].pUnkServer = pUnk;
memcpy(&(stubs[nrofstubs].mid),mid,sizeof(*mid));
nrofstubs++;
return S_OK;
}
HRESULT
MARSHAL_Find_Proxy(wine_marshal_id *mid,LPUNKNOWN *punk) {
int i;
for (i=0;i<nrofproxies;i++)
if (MARSHAL_Compare_Mids(mid,&(proxies[i].mid))) {
*punk = proxies[i].pUnk;
IUnknown_AddRef((*punk));
return S_OK;
}
return E_FAIL;
}
HRESULT
MARSHAL_Find_Proxy_Object(wine_marshal_id *mid,LPUNKNOWN *punk) {
int i;
for (i=0;i<nrofproxies;i++)
if (MARSHAL_Compare_Mids_NoInterface(mid,&(proxies[i].mid))) {
*punk = proxies[i].pUnk;
IUnknown_AddRef((*punk));
return S_OK;
}
return E_FAIL;
}
HRESULT
MARSHAL_Register_Proxy(wine_marshal_id *mid,LPUNKNOWN punk) {
int i;
for (i=0;i<nrofproxies;i++) {
if (MARSHAL_Compare_Mids(mid,&(proxies[i].mid))) {
ERR("Already have mid?\n");
return E_FAIL;
}
}
if (nrofproxies)
proxies = HeapReAlloc(GetProcessHeap(),0,proxies,sizeof(proxies[0])*(nrofproxies+1));
else
proxies = HeapAlloc(GetProcessHeap(),0,sizeof(proxies[0]));
memcpy(&(proxies[nrofproxies].mid),mid,sizeof(*mid));
proxies[nrofproxies].pUnk = punk;
nrofproxies++;
IUnknown_AddRef(punk);
return S_OK;
}
/********************** StdMarshal implementation ****************************/
typedef struct _StdMarshalImpl {
ICOM_VTABLE(IMarshal) *lpvtbl;
DWORD ref;
IID iid;
DWORD dwDestContext;
LPVOID pvDestContext;
DWORD mshlflags;
} StdMarshalImpl;
HRESULT WINAPI
StdMarshalImpl_QueryInterface(LPMARSHAL iface,REFIID riid,LPVOID *ppv) {
*ppv = NULL;
if (IsEqualIID(&IID_IUnknown,riid) || IsEqualIID(&IID_IMarshal,riid)) {
*ppv = iface;
IUnknown_AddRef(iface);
return S_OK;
}
FIXME("No interface for %s.\n",debugstr_guid(riid));
return E_NOINTERFACE;
}
ULONG WINAPI
StdMarshalImpl_AddRef(LPMARSHAL iface) {
ICOM_THIS(StdMarshalImpl,iface);
This->ref++;
return This->ref;
}
ULONG WINAPI
StdMarshalImpl_Release(LPMARSHAL iface) {
ICOM_THIS(StdMarshalImpl,iface);
This->ref--;
if (This->ref)
return This->ref;
HeapFree(GetProcessHeap(),0,This);
return 0;
}
HRESULT WINAPI
StdMarshalImpl_GetUnmarshalClass(
LPMARSHAL iface, REFIID riid, void* pv, DWORD dwDestContext,
void* pvDestContext, DWORD mshlflags, CLSID* pCid
) {
memcpy(pCid,&CLSID_DfMarshal,sizeof(CLSID_DfMarshal));
return S_OK;
}
HRESULT WINAPI
StdMarshalImpl_GetMarshalSizeMax(
LPMARSHAL iface, REFIID riid, void* pv, DWORD dwDestContext,
void* pvDestContext, DWORD mshlflags, DWORD* pSize
) {
*pSize = sizeof(wine_marshal_id)+sizeof(wine_marshal_data);
return S_OK;
}
HRESULT WINAPI
StdMarshalImpl_MarshalInterface(
LPMARSHAL iface, IStream *pStm,REFIID riid, void* pv, DWORD dwDestContext,
void* pvDestContext, DWORD mshlflags
) {
wine_marshal_id mid;
wine_marshal_data md;
IUnknown *pUnk;
ULONG res;
HRESULT hres;
IRpcStubBuffer *stub;
IPSFactoryBuffer *psfacbuf;
TRACE("(...,%s,...)\n",debugstr_guid(riid));
IUnknown_QueryInterface((LPUNKNOWN)pv,&IID_IUnknown,(LPVOID*)&pUnk);
mid.processid = GetCurrentProcessId();
mid.objectid = (DWORD)pUnk; /* FIXME */
IUnknown_Release(pUnk);
memcpy(&mid.iid,riid,sizeof(mid.iid));
md.dwDestContext = dwDestContext;
md.mshlflags = mshlflags;
hres = IStream_Write(pStm,&mid,sizeof(mid),&res);
if (hres) return hres;
hres = IStream_Write(pStm,&md,sizeof(md),&res);
if (hres) return hres;
if (SUCCEEDED(MARSHAL_Find_Stub(&mid,&pUnk))) {
IUnknown_Release(pUnk);
return S_OK;
}
hres = get_facbuf_for_iid(riid,&psfacbuf);
if (hres) return hres;
hres = IPSFactoryBuffer_CreateStub(psfacbuf,riid,pv,&stub);
IPSFactoryBuffer_Release(psfacbuf);
if (hres) {
FIXME("Failed to create a stub for %s\n",debugstr_guid(riid));
return hres;
}
IUnknown_QueryInterface((LPUNKNOWN)pv,riid,(LPVOID*)&pUnk);
MARSHAL_Register_Stub(&mid,pUnk,stub);
IUnknown_Release(pUnk);
return S_OK;
}
HRESULT WINAPI
StdMarshalImpl_UnmarshalInterface(
LPMARSHAL iface, IStream *pStm, REFIID riid, void **ppv
) {
wine_marshal_id mid;
wine_marshal_data md;
ULONG res;
HRESULT hres;
IPSFactoryBuffer *psfacbuf;
IRpcProxyBuffer *rpcproxy;
IRpcChannelBuffer *chanbuf;
TRACE("(...,%s,....)\n",debugstr_guid(riid));
hres = IStream_Read(pStm,&mid,sizeof(mid),&res);
if (hres) return hres;
hres = IStream_Read(pStm,&md,sizeof(md),&res);
if (hres) return hres;
if (SUCCEEDED(MARSHAL_Find_Stub(&mid,(LPUNKNOWN*)ppv))) {
FIXME("Calling back to ourselves for %s!\n",debugstr_guid(riid));
return S_OK;
}
hres = get_facbuf_for_iid(riid,&psfacbuf);
if (hres) return hres;
hres = IPSFactoryBuffer_CreateProxy(psfacbuf,NULL,riid,&rpcproxy,ppv);
if (hres) {
FIXME("Failed to create a proxy for %s\n",debugstr_guid(riid));
return hres;
}
hres = PIPE_GetNewPipeBuf(&mid,&chanbuf);
if (hres)
FIXME("Failed to get an rpc channel buffer for %s\n",debugstr_guid(riid));
IRpcProxyBuffer_Connect(rpcproxy,chanbuf);
IRpcProxyBuffer_Release(rpcproxy); /* no need */
IPSFactoryBuffer_Release(psfacbuf);
return S_OK;
}
HRESULT WINAPI
StdMarshalImpl_ReleaseMarshalData(LPMARSHAL iface, IStream *pStm) {
FIXME("(), stub!\n");
return S_OK;
}
HRESULT WINAPI
StdMarshalImpl_DisconnectObject(LPMARSHAL iface, DWORD dwReserved) {
FIXME("(), stub!\n");
return S_OK;
}
ICOM_VTABLE(IMarshal) stdmvtbl = {
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
StdMarshalImpl_QueryInterface,
StdMarshalImpl_AddRef,
StdMarshalImpl_Release,
StdMarshalImpl_GetUnmarshalClass,
StdMarshalImpl_GetMarshalSizeMax,
StdMarshalImpl_MarshalInterface,
StdMarshalImpl_UnmarshalInterface,
StdMarshalImpl_ReleaseMarshalData,
StdMarshalImpl_DisconnectObject
};
/***********************************************************************
* CoGetStandardMarshal [OLE32.23]
*
* When the COM library in the client process receives a marshaled
* interface pointer, it looks for a CLSID to be used in creating a proxy
* for the purposes of unmarshaling the packet. If the packet does not
* contain a CLSID for the proxy, COM calls CoGetStandardMarshal, passing a
* NULL pUnk value.
* This function creates a standard proxy in the client process and returns
* a pointer to that proxy's implementation of IMarshal.
* COM uses this pointer to call CoUnmarshalInterface to retrieve the pointer
* to the requested interface.
*/
HRESULT WINAPI
CoGetStandardMarshal(
REFIID riid,IUnknown *pUnk,DWORD dwDestContext,LPVOID pvDestContext,
DWORD mshlflags, LPMARSHAL *pMarshal
) {
StdMarshalImpl *dm;
if (pUnk == NULL) {
FIXME("(%s,NULL,%lx,%p,%lx,%p), unimplemented yet.\n",
debugstr_guid(riid),dwDestContext,pvDestContext,mshlflags,pMarshal
);
return E_FAIL;
}
TRACE("(%s,%p,%lx,%p,%lx,%p)\n",
debugstr_guid(riid),pUnk,dwDestContext,pvDestContext,mshlflags,pMarshal
);
dm = (StdMarshalImpl*) *pMarshal = HeapAlloc(GetProcessHeap(),0,sizeof(StdMarshalImpl));
if (!dm) return E_FAIL;
dm->lpvtbl = &stdmvtbl;
dm->ref = 1;
memcpy(&dm->iid,riid,sizeof(dm->iid));
dm->dwDestContext = dwDestContext;
dm->pvDestContext = pvDestContext;
dm->mshlflags = mshlflags;
return S_OK;
}
/* Helper function for getting Marshaler */
static HRESULT WINAPI
_GetMarshaller(REFIID riid, IUnknown *pUnk,DWORD dwDestContext,
void *pvDestContext, DWORD mshlFlags, LPMARSHAL *pMarshal
) {
HRESULT hres;
if (!pUnk)
return E_POINTER;
hres = IUnknown_QueryInterface(pUnk,&IID_IMarshal,(LPVOID*)pMarshal);
if (hres)
hres = CoGetStandardMarshal(riid,pUnk,dwDestContext,pvDestContext,mshlFlags,pMarshal);
return hres;
}
/***********************************************************************
* CoGetMarshalSizeMax [OLE32.21]
*/
HRESULT WINAPI
CoGetMarshalSizeMax(ULONG *pulSize, REFIID riid, IUnknown *pUnk,
DWORD dwDestContext, void *pvDestContext, DWORD mshlFlags
) {
HRESULT hres;
LPMARSHAL pMarshal;
hres = _GetMarshaller(riid,pUnk,dwDestContext,pvDestContext,mshlFlags,&pMarshal);
if (hres)
return hres;
hres = IMarshal_GetMarshalSizeMax(pMarshal,riid,pUnk,dwDestContext,pvDestContext,mshlFlags,pulSize);
*pulSize += sizeof(wine_marshal_id)+sizeof(wine_marshal_data)+sizeof(CLSID);
IMarshal_Release(pMarshal);
return hres;
}
/***********************************************************************
* CoMarshalInterface [OLE32.34]
*/
HRESULT WINAPI
CoMarshalInterface( IStream *pStm, REFIID riid, IUnknown *pUnk,
DWORD dwDestContext, void *pvDestContext, DWORD mshlflags
) {
HRESULT hres;
LPMARSHAL pMarshal;
CLSID xclsid;
ULONG writeres;
wine_marshal_id mid;
wine_marshal_data md;
ULONG res;
IUnknown *pUnknown;
TRACE("(%p, %s, %p, %lx, %p, %lx)\n",
pStm,debugstr_guid(riid),pUnk,dwDestContext,pvDestContext,mshlflags
);
STUBMGR_Start(); /* Just to be sure we have one running. */
mid.processid = GetCurrentProcessId();
IUnknown_QueryInterface(pUnk,&IID_IUnknown,(LPVOID*)&pUnknown);
mid.objectid = (DWORD)pUnknown;
IUnknown_Release(pUnknown);
memcpy(&mid.iid,riid,sizeof(mid.iid));
md.dwDestContext = dwDestContext;
md.mshlflags = mshlflags;
hres = IStream_Write(pStm,&mid,sizeof(mid),&res);
if (hres) return hres;
hres = IStream_Write(pStm,&md,sizeof(md),&res);
if (hres) return hres;
hres = _GetMarshaller(riid,pUnk,dwDestContext,pvDestContext,mshlflags,&pMarshal);
if (hres) {
FIXME("Failed to get marshaller, %lx?\n",hres);
return hres;
}
hres = IMarshal_GetUnmarshalClass(pMarshal,riid,pUnk,dwDestContext,pvDestContext,mshlflags,&xclsid);
if (hres) {
FIXME("IMarshal:GetUnmarshalClass failed, %lx\n",hres);
goto release_marshal;
}
hres = IStream_Write(pStm,&xclsid,sizeof(xclsid),&writeres);
if (hres) {
FIXME("Stream write failed, %lx\n",hres);
goto release_marshal;
}
hres = IMarshal_MarshalInterface(pMarshal,pStm,riid,pUnk,dwDestContext,pvDestContext,mshlflags);
if (hres) {
FIXME("Failed to Marshal the interface, %lx?\n",hres);
goto release_marshal;
}
release_marshal:
IMarshal_Release(pMarshal);
return hres;
}
/***********************************************************************
* CoUnmarshalInterface [OLE32.50]
*/
HRESULT WINAPI
CoUnmarshalInterface(IStream *pStm, REFIID riid, LPVOID *ppv) {
HRESULT hres;
wine_marshal_id mid;
wine_marshal_data md;
ULONG res;
LPMARSHAL pMarshal;
LPUNKNOWN pUnk;
CLSID xclsid;
TRACE("(%p,%s,%p)\n",pStm,debugstr_guid(riid),ppv);
hres = IStream_Read(pStm,&mid,sizeof(mid),&res);
if (hres) {
FIXME("Stream read 1 failed, %lx, (%ld of %d)\n",hres,res,sizeof(mid));
return hres;
}
hres = IStream_Read(pStm,&md,sizeof(md),&res);
if (hres) {
FIXME("Stream read 2 failed, %lx, (%ld of %d)\n",hres,res,sizeof(md));
return hres;
}
hres = IStream_Read(pStm,&xclsid,sizeof(xclsid),&res);
if (hres) {
FIXME("Stream read 3 failed, %lx, (%ld of %d)\n",hres,res,sizeof(xclsid));
return hres;
}
hres=CoCreateInstance(&xclsid,NULL,CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER | CLSCTX_LOCAL_SERVER,&IID_IMarshal,(void**)&pUnk);
if (hres) {
FIXME("Failed to create instance of unmarshaller %s.\n",debugstr_guid(&xclsid));
return hres;
}
hres = _GetMarshaller(riid,pUnk,md.dwDestContext,NULL,md.mshlflags,&pMarshal);
if (hres) {
FIXME("Failed to get unmarshaller, %lx?\n",hres);
return hres;
}
hres = IMarshal_UnmarshalInterface(pMarshal,pStm,riid,ppv);
if (hres) {
FIXME("Failed to Unmarshal the interface, %lx?\n",hres);
goto release_marshal;
}
release_marshal:
IMarshal_Release(pMarshal);
return hres;
}
/***********************************************************************
* CoMarshalInterThreadInterfaceInStream [OLE32.33]
*
* Marshal interfaces across threads. We don't have a thread distinction,
* meaning most interfaces just work across different threads, the RPC
* handles it.
*/
HRESULT WINAPI
CoMarshalInterThreadInterfaceInStream(
REFIID riid, LPUNKNOWN pUnk, LPSTREAM * ppStm
) {
ULONG res;
ULARGE_INTEGER xpos;
LARGE_INTEGER seekto;
HRESULT hres;
TRACE("(,%s,)\n",debugstr_guid(riid));
hres = CreateStreamOnHGlobal(0, TRUE, ppStm);
if (hres) return hres;
/* CoMarshalInterface(...); */
hres = IStream_Write(*ppStm,&pUnk,sizeof(LPUNKNOWN),&res);
if (hres) return hres;
memset(&seekto,0,sizeof(seekto));
IStream_Seek(*ppStm,seekto,SEEK_SET,&xpos);
return S_OK;
}
/***********************************************************************
* CoGetInterfaceAndReleaseStream [OLE32.19]
*/
HRESULT WINAPI
CoGetInterfaceAndReleaseStream(LPSTREAM pStm,REFIID riid, LPVOID *ppv) {
ULONG res;
HRESULT hres;
LPUNKNOWN pUnk;
TRACE("(,%s,)\n",debugstr_guid(riid));
/* CoUnmarshalInterface(...); */
hres = IStream_Read(pStm,&pUnk,sizeof(LPUNKNOWN),&res);
if (hres) return hres;
IStream_Release(pStm);
return IUnknown_QueryInterface(pUnk,riid,ppv);
}
static WINAPI HRESULT
SMCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid, LPVOID *ppv) {
*ppv = NULL;
if (IsEqualIID(riid,&IID_IUnknown) || IsEqualIID(riid,&IID_IClassFactory)) {
*ppv = (LPVOID)iface;
return S_OK;
}
return E_NOINTERFACE;
}
static WINAPI ULONG SMCF_AddRef(LPCLASSFACTORY iface) { return 2; }
static WINAPI ULONG SMCF_Release(LPCLASSFACTORY iface) { return 1; }
static WINAPI HRESULT
SMCF_CreateInstance(
LPCLASSFACTORY iface, LPUNKNOWN pUnk, REFIID riid, LPVOID *ppv
) {
if (IsEqualIID(riid,&IID_IMarshal)) {
StdMarshalImpl *dm;
dm=(StdMarshalImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(StdMarshalImpl));
if (!dm)
return E_FAIL;
dm->lpvtbl = &stdmvtbl;
dm->ref = 1;
*ppv = (LPVOID)dm;
return S_OK;
}
FIXME("(%s), not supported.\n",debugstr_guid(riid));
return E_NOINTERFACE;
}
static WINAPI HRESULT
SMCF_LockServer(LPCLASSFACTORY iface, BOOL fLock) {
FIXME("(%d), stub!\n",fLock);
return S_OK;
}
static ICOM_VTABLE(IClassFactory) dfmarshalcfvtbl = {
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
SMCF_QueryInterface,
SMCF_AddRef,
SMCF_Release,
SMCF_CreateInstance,
SMCF_LockServer
};
static ICOM_VTABLE(IClassFactory) *pdfmarshalcfvtbl = &dfmarshalcfvtbl;
HRESULT
MARSHAL_GetStandardMarshalCF(LPVOID *ppv) {
*ppv = &pdfmarshalcfvtbl;
return S_OK;
}

View File

@ -30,7 +30,7 @@ debug_channels (accel ole relay storage)
16 stdcall CoGetClassObject(ptr long ptr ptr ptr) CoGetClassObject 16 stdcall CoGetClassObject(ptr long ptr ptr ptr) CoGetClassObject
17 stub CoGetCurrentLogicalThreadId 17 stub CoGetCurrentLogicalThreadId
18 stdcall CoGetCurrentProcess() CoGetCurrentProcess 18 stdcall CoGetCurrentProcess() CoGetCurrentProcess
19 stub CoGetInterfaceAndReleaseStream # stdcall (ptr ptr ptr) return 0,ERR_NOTIMPLEMENTED 19 stdcall CoGetInterfaceAndReleaseStream(ptr ptr ptr) CoGetInterfaceAndReleaseStream
20 stdcall CoGetMalloc(long ptr) CoGetMalloc 20 stdcall CoGetMalloc(long ptr) CoGetMalloc
21 stub CoGetMarshalSizeMax # stdcall (ptr ptr ptr long ptr long) return 0,ERR_NOTIMPLEMENTED 21 stub CoGetMarshalSizeMax # stdcall (ptr ptr ptr long ptr long) return 0,ERR_NOTIMPLEMENTED
22 stdcall CoGetPSClsid(ptr ptr) CoGetPSClsid 22 stdcall CoGetPSClsid(ptr ptr) CoGetPSClsid
@ -44,8 +44,8 @@ debug_channels (accel ole relay storage)
30 stdcall CoLoadLibrary(wstr long) CoLoadLibrary 30 stdcall CoLoadLibrary(wstr long) CoLoadLibrary
31 stdcall CoLockObjectExternal(ptr long long) CoLockObjectExternal 31 stdcall CoLockObjectExternal(ptr long long) CoLockObjectExternal
32 stub CoMarshalHresult # stdcall (ptr ptr) return 0,ERR_NOTIMPLEMENTED 32 stub CoMarshalHresult # stdcall (ptr ptr) return 0,ERR_NOTIMPLEMENTED
33 stub CoMarshalInterThreadInterfaceInStream # stdcall (ptr ptr ptr) return 0,ERR_NOTIMPLEMENTED 33 stdcall CoMarshalInterThreadInterfaceInStream(ptr ptr ptr) CoMarshalInterThreadInterfaceInStream
34 stub CoMarshalInterface # stdcall (ptr ptr ptr long ptr long) return 0,ERR_NOTIMPLEMENTED 34 stdcall CoMarshalInterface(ptr ptr ptr long ptr long) CoMarshalInterface
35 stub CoQueryReleaseObject 35 stub CoQueryReleaseObject
36 stdcall CoRegisterClassObject(ptr ptr long long ptr) CoRegisterClassObject 36 stdcall CoRegisterClassObject(ptr ptr long long ptr) CoRegisterClassObject
37 stub CoRegisterMallocSpy # stdcall (ptr) return 0,ERR_NOTIMPLEMENTED 37 stub CoRegisterMallocSpy # stdcall (ptr) return 0,ERR_NOTIMPLEMENTED
@ -61,7 +61,7 @@ debug_channels (accel ole relay storage)
47 stdcall CoUninitialize() CoUninitialize 47 stdcall CoUninitialize() CoUninitialize
48 stub CoUnloadingWOW 48 stub CoUnloadingWOW
49 stub CoUnmarshalHresult # stdcall (ptr ptr) return 0,ERR_NOTIMPLEMENTED 49 stub CoUnmarshalHresult # stdcall (ptr ptr) return 0,ERR_NOTIMPLEMENTED
50 stub CoUnmarshalInterface # stdcall (ptr ptr ptr) return 0,ERR_NOTIMPLEMENTED 50 stdcall CoUnmarshalInterface(ptr ptr ptr) CoUnmarshalInterface
51 stdcall CreateAntiMoniker(ptr) CreateAntiMoniker 51 stdcall CreateAntiMoniker(ptr) CreateAntiMoniker
52 stdcall CreateBindCtx(long ptr) CreateBindCtx 52 stdcall CreateBindCtx(long ptr) CreateBindCtx
53 stdcall CreateDataAdviseHolder(ptr) CreateDataAdviseHolder 53 stdcall CreateDataAdviseHolder(ptr) CreateDataAdviseHolder

496
dlls/ole32/oleproxy.c Normal file
View File

@ -0,0 +1,496 @@
/*
* OLE32 proxy/stub handler
*
* Copyright 2002 Marcus Meissner
*/
/* Documentation on MSDN:
*
* (COM Proxy)
* http://msdn.microsoft.com/library/en-us/com/comext_1q0p.asp
*
* (COM Stub)
* http://msdn.microsoft.com/library/en-us/com/comext_1lia.asp
*
* (Marshal)
* http://msdn.microsoft.com/library/en-us/com/comext_1gfn.asp
*
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "windef.h"
#include "objbase.h"
#include "ole2.h"
#include "rpc.h"
#include "winerror.h"
#include "winreg.h"
#include "wtypes.h"
#include "wine/obj_base.h"
#include "wine/obj_marshal.h"
#include "wine/obj_channel.h"
#include "compobj_private.h"
#include "debugtools.h"
DEFAULT_DEBUG_CHANNEL(ole);
/* From: http://msdn.microsoft.com/library/en-us/com/cmi_m_4lda.asp
*
* The first time a client requests a pointer to an interface on a
* particular object, COM loads an IClassFactory stub in the server
* process and uses it to marshal the first pointer back to the
* client. In the client process, COM loads the generic proxy for the
* class factory object and calls its implementation of IMarshal to
* unmarshal that first pointer. COM then creates the first interface
* proxy and hands it a pointer to the RPC channel. Finally, COM returns
* the IClassFactory pointer to the client, which uses it to call
* IClassFactory::CreateInstance, passing it a reference to the interface.
*
* Back in the server process, COM now creates a new instance of the
* object, along with a stub for the requested interface. This stub marshals
* the interface pointer back to the client process, where another object
* proxy is created, this time for the object itself. Also created is a
* proxy for the requested interface, a pointer to which is returned to
* the client. With subsequent calls to other interfaces on the object,
* COM will load the appropriate interface stubs and proxies as needed.
*/
typedef struct _CFStub {
ICOM_VTABLE(IRpcStubBuffer) *lpvtbl;
DWORD ref;
LPUNKNOWN pUnkServer;
} CFStub;
static HRESULT WINAPI
CFStub_QueryInterface(LPRPCSTUBBUFFER iface, REFIID riid, LPVOID *ppv) {
if (IsEqualIID(&IID_IUnknown,riid)||IsEqualIID(&IID_IRpcStubBuffer,riid)) {
*ppv = (LPVOID)iface;
IUnknown_AddRef(iface);
return S_OK;
}
FIXME("(%s), interface not supported.\n",debugstr_guid(riid));
return E_NOINTERFACE;
}
static ULONG WINAPI
CFStub_AddRef(LPRPCSTUBBUFFER iface) {
ICOM_THIS(CFStub,iface);
This->ref++;
return This->ref;
}
static ULONG WINAPI
CFStub_Release(LPRPCSTUBBUFFER iface) {
ICOM_THIS(CFStub,iface);
This->ref--;
if (This->ref)
return This->ref;
HeapFree(GetProcessHeap(),0,This);
return 0;
}
static HRESULT WINAPI
CFStub_Connect(LPRPCSTUBBUFFER iface, IUnknown *pUnkServer) {
ICOM_THIS(CFStub,iface);
This->pUnkServer = pUnkServer;
IUnknown_AddRef(pUnkServer);
return S_OK;
}
static void WINAPI
CFStub_Disconnect(LPRPCSTUBBUFFER iface) {
ICOM_THIS(CFStub,iface);
IUnknown_Release(This->pUnkServer);
This->pUnkServer = NULL;
}
static HRESULT WINAPI
CFStub_Invoke(
LPRPCSTUBBUFFER iface,RPCOLEMESSAGE* msg,IRpcChannelBuffer* chanbuf
) {
ICOM_THIS(CFStub,iface);
HRESULT hres;
if (msg->iMethod == 3) { /* CreateInstance */
IID iid;
IClassFactory *classfac;
IUnknown *ppv;
IStream *pStm;
STATSTG ststg;
ULARGE_INTEGER newpos;
LARGE_INTEGER seekto;
ULONG res;
if (msg->cbBuffer < sizeof(IID)) {
FIXME("Not enough bytes in buffer (%ld instead of %d)?\n",msg->cbBuffer,sizeof(IID));
return E_FAIL;
}
memcpy(&iid,msg->Buffer,sizeof(iid));
TRACE("->CreateInstance(%s)\n",debugstr_guid(&iid));
hres = IUnknown_QueryInterface(This->pUnkServer,&IID_IClassFactory,(LPVOID*)&classfac);
if (hres) {
FIXME("Ole server does not provide a IClassFactory?\n");
return hres;
}
hres = IClassFactory_CreateInstance(classfac,NULL,&iid,(LPVOID*)&ppv);
IClassFactory_Release(classfac);
if (hres) {
msg->cbBuffer = 0;
FIXME("Failed to create an instance of %s\n",debugstr_guid(&iid));
return hres;
}
hres = CreateStreamOnHGlobal(0,TRUE,&pStm);
if (hres) {
FIXME("Failed to create stream on hglobal\n");
return hres;
}
hres = CoMarshalInterface(pStm,&iid,ppv,0,NULL,0);
if (hres) {
FIXME("CoMarshalInterface failed, %lx!\n",hres);
msg->cbBuffer = 0;
return hres;
}
hres = IStream_Stat(pStm,&ststg,0);
if (hres) {
FIXME("Stat failed.\n");
return hres;
}
msg->cbBuffer = ststg.cbSize.s.LowPart;
msg->Buffer = HeapReAlloc(GetProcessHeap(),0,msg->Buffer,ststg.cbSize.s.LowPart);
seekto.s.LowPart = 0;seekto.s.HighPart = 0;
hres = IStream_Seek(pStm,seekto,SEEK_SET,&newpos);
if (hres) {
FIXME("IStream_Seek failed, %lx\n",hres);
return hres;
}
hres = IStream_Read(pStm,msg->Buffer,msg->cbBuffer,&res);
if (hres) {
FIXME("Stream Read failed, %lx\n",hres);
return hres;
}
IStream_Release(pStm);
return S_OK;
}
FIXME("(%p,%p), stub!\n",msg,chanbuf);
FIXME("iMethod is %ld\n",msg->iMethod);
FIXME("cbBuffer is %ld\n",msg->cbBuffer);
return E_FAIL;
}
static LPRPCSTUBBUFFER WINAPI
CFStub_IsIIDSupported(LPRPCSTUBBUFFER iface,REFIID riid) {
FIXME("(%s), stub!\n",debugstr_guid(riid));
return NULL;
}
static ULONG WINAPI
CFStub_CountRefs(LPRPCSTUBBUFFER iface) {
FIXME("(), stub!\n");
return 1;
}
static HRESULT WINAPI
CFStub_DebugServerQueryInterface(LPRPCSTUBBUFFER iface,void** ppv) {
FIXME("(%p), stub!\n",ppv);
return E_FAIL;
}
static void WINAPI
CFStub_DebugServerRelease(LPRPCSTUBBUFFER iface,void *pv) {
FIXME("(%p), stub!\n",pv);
}
static ICOM_VTABLE(IRpcStubBuffer) cfstubvt = {
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
CFStub_QueryInterface,
CFStub_AddRef,
CFStub_Release,
CFStub_Connect,
CFStub_Disconnect,
CFStub_Invoke,
CFStub_IsIIDSupported,
CFStub_CountRefs,
CFStub_DebugServerQueryInterface,
CFStub_DebugServerRelease
};
static HRESULT
CFStub_Construct(LPRPCSTUBBUFFER *ppv) {
CFStub *cfstub;
cfstub = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(CFStub));
if (!cfstub)
return E_OUTOFMEMORY;
*ppv = (LPRPCSTUBBUFFER)cfstub;
cfstub->lpvtbl = &cfstubvt;
cfstub->ref = 1;
return S_OK;
}
/* Since we create proxy buffers and classfactory in a pair, there is
* no need for 2 seperate structs. Just put them in one, but remember
* the refcount.
*/
typedef struct _CFProxy {
ICOM_VTABLE(IClassFactory) *lpvtbl_cf;
ICOM_VTABLE(IRpcProxyBuffer) *lpvtbl_proxy;
DWORD ref;
IRpcChannelBuffer *chanbuf;
} CFProxy;
static HRESULT WINAPI IRpcProxyBufferImpl_QueryInterface(LPRPCPROXYBUFFER iface,REFIID riid,LPVOID *ppv) {
*ppv = NULL;
if (IsEqualIID(riid,&IID_IRpcProxyBuffer)||IsEqualIID(riid,&IID_IUnknown)) {
IRpcProxyBuffer_AddRef(iface);
*ppv = (LPVOID)iface;
return S_OK;
}
FIXME("(%s), no interface.\n",debugstr_guid(riid));
return E_NOINTERFACE;
}
static ULONG WINAPI IRpcProxyBufferImpl_AddRef(LPRPCPROXYBUFFER iface) {
ICOM_THIS_MULTI(CFProxy,lpvtbl_proxy,iface);
return ++(This->ref);
}
static ULONG WINAPI IRpcProxyBufferImpl_Release(LPRPCPROXYBUFFER iface) {
ICOM_THIS_MULTI(CFProxy,lpvtbl_proxy,iface);
if (!--(This->ref)) {
IRpcChannelBuffer_Release(This->chanbuf);This->chanbuf = NULL;
HeapFree(GetProcessHeap(),0,This);
return 0;
}
return This->ref;
}
static HRESULT WINAPI IRpcProxyBufferImpl_Connect(LPRPCPROXYBUFFER iface,IRpcChannelBuffer* pRpcChannelBuffer) {
ICOM_THIS_MULTI(CFProxy,lpvtbl_proxy,iface);
This->chanbuf = pRpcChannelBuffer;
IRpcChannelBuffer_AddRef(This->chanbuf);
return S_OK;
}
static void WINAPI IRpcProxyBufferImpl_Disconnect(LPRPCPROXYBUFFER iface) {
ICOM_THIS_MULTI(CFProxy,lpvtbl_proxy,iface);
if (This->chanbuf) {
IRpcChannelBuffer_Release(This->chanbuf);
This->chanbuf = NULL;
}
}
static HRESULT WINAPI
CFProxy_QueryInterface(LPCLASSFACTORY iface,REFIID riid, LPVOID *ppv) {
*ppv = NULL;
if (IsEqualIID(&IID_IClassFactory,riid) || IsEqualIID(&IID_IUnknown,riid)) {
*ppv = (LPVOID)iface;
IClassFactory_AddRef(iface);
return S_OK;
}
if (IsEqualIID(riid,&IID_IMarshal)) /* just to avoid debugoutput */
return E_NOINTERFACE;
FIXME("Unhandled interface: %s\n",debugstr_guid(riid));
return E_NOINTERFACE;
}
static ULONG WINAPI CFProxy_AddRef(LPCLASSFACTORY iface) {
ICOM_THIS_MULTI(CFProxy,lpvtbl_cf,iface);
This->ref++;
return This->ref;
}
static ULONG WINAPI CFProxy_Release(LPCLASSFACTORY iface) {
ICOM_THIS_MULTI(CFProxy,lpvtbl_cf,iface);
This->ref--;
if (This->ref)
return This->ref;
HeapFree(GetProcessHeap(),0,This);
return 0;
}
static HRESULT WINAPI CFProxy_CreateInstance(
LPCLASSFACTORY iface,
LPUNKNOWN pUnkOuter,/* [in] */
REFIID riid, /* [in] */
LPVOID *ppv /* [out] */
) {
ICOM_THIS_MULTI(CFProxy,lpvtbl_cf,iface);
HRESULT hres;
LPSTREAM pStream;
HGLOBAL hGlobal;
ULONG srstatus;
RPCOLEMESSAGE msg;
TRACE("(%p,%s,%p)\n",pUnkOuter,debugstr_guid(riid),ppv);
/* Send CreateInstance to the remote classfactory.
*
* Data: Only the 'IID'.
*/
msg.iMethod = 3;
msg.cbBuffer = sizeof(*riid);
msg.Buffer = NULL;
hres = IRpcChannelBuffer_GetBuffer(This->chanbuf,&msg,&IID_IClassFactory);
if (hres) {
FIXME("IRpcChannelBuffer_GetBuffer failed with %lx?\n",hres);
return hres;
}
memcpy(msg.Buffer,riid,sizeof(*riid));
hres = IRpcChannelBuffer_SendReceive(This->chanbuf,&msg,&srstatus);
if (hres) {
FIXME("IRpcChannelBuffer_SendReceive failed with %lx?\n",hres);
return hres;
}
if (!msg.cbBuffer) /* interface not found on remote */
return srstatus;
/* We got back: [Marshaled Interface data] */
TRACE("got %ld bytes data.\n",msg.cbBuffer);
hGlobal = GlobalAlloc(GMEM_MOVEABLE|GMEM_NODISCARD|GMEM_SHARE,msg.cbBuffer);
memcpy(GlobalLock(hGlobal),msg.Buffer,msg.cbBuffer);
hres = CreateStreamOnHGlobal(hGlobal,TRUE,&pStream);
if (hres) {
FIXME("CreateStreamOnHGlobal failed with %lx\n",hres);
return hres;
}
hres = CoUnmarshalInterface(
pStream,
riid,
ppv
);
IStream_Release(pStream); /* Does GlobalFree hGlobal too. */
if (hres) {
FIXME("CoMarshalInterface failed, %lx\n",hres);
return hres;
}
return S_OK;
}
static HRESULT WINAPI CFProxy_LockServer(LPCLASSFACTORY iface,BOOL fLock) {
/*ICOM_THIS_MULTI(CFProxy,lpvtbl_cf,iface);*/
FIXME("(%d), stub!\n",fLock);
/* basically: write BOOL, read empty */
return S_OK;
}
static ICOM_VTABLE(IRpcProxyBuffer) pspbvtbl = {
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
IRpcProxyBufferImpl_QueryInterface,
IRpcProxyBufferImpl_AddRef,
IRpcProxyBufferImpl_Release,
IRpcProxyBufferImpl_Connect,
IRpcProxyBufferImpl_Disconnect
};
static ICOM_VTABLE(IClassFactory) cfproxyvt = {
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
CFProxy_QueryInterface,
CFProxy_AddRef,
CFProxy_Release,
CFProxy_CreateInstance,
CFProxy_LockServer
};
static HRESULT
CFProxy_Construct(LPVOID *ppv,LPVOID *ppProxy) {
CFProxy *cf;
cf = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(CFProxy));
if (!cf)
return E_OUTOFMEMORY;
cf->lpvtbl_cf = &cfproxyvt;
cf->lpvtbl_proxy = &pspbvtbl;
cf->ref = 2; /* we return 2 references to the object! */
*ppv = &(cf->lpvtbl_cf);
*ppProxy = &(cf->lpvtbl_proxy);
return S_OK;
}
/********************* OLE Proxy/Stub Factory ********************************/
static HRESULT WINAPI
PSFacBuf_QueryInterface(LPPSFACTORYBUFFER iface, REFIID iid, LPVOID *ppv) {
if (IsEqualIID(iid,&IID_IPSFactoryBuffer)||IsEqualIID(iid,&IID_IUnknown)) {
*ppv = (LPVOID)iface;
/* No ref counting, static class */
return S_OK;
}
FIXME("(%s) unknown IID?\n",debugstr_guid(iid));
return E_NOINTERFACE;
}
static ULONG WINAPI PSFacBuf_AddRef(LPPSFACTORYBUFFER iface) { return 2; }
static ULONG WINAPI PSFacBuf_Release(LPPSFACTORYBUFFER iface) { return 1; }
static HRESULT WINAPI
PSFacBuf_CreateProxy(
LPPSFACTORYBUFFER iface, IUnknown* pUnkOuter, REFIID riid,
IRpcProxyBuffer **ppProxy, LPVOID *ppv
) {
if (IsEqualIID(&IID_IClassFactory,riid))
return CFProxy_Construct(ppv,(LPVOID*)ppProxy);
FIXME("proxying not implemented for (%s) yet!\n",debugstr_guid(riid));
return E_FAIL;
}
static HRESULT WINAPI
PSFacBuf_CreateStub(
LPPSFACTORYBUFFER iface, REFIID riid,IUnknown *pUnkServer,
IRpcStubBuffer** ppStub
) {
HRESULT hres;
TRACE("(%s,%p,%p)\n",debugstr_guid(riid),pUnkServer,ppStub);
if (IsEqualIID(&IID_IClassFactory,riid)) {
hres = CFStub_Construct(ppStub);
if (!hres)
IRpcStubBuffer_Connect((*ppStub),pUnkServer);
return hres;
}
FIXME("stubbing not implemented for (%s) yet!\n",debugstr_guid(riid));
return E_FAIL;
}
static ICOM_VTABLE(IPSFactoryBuffer) psfacbufvtbl = {
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
PSFacBuf_QueryInterface,
PSFacBuf_AddRef,
PSFacBuf_Release,
PSFacBuf_CreateProxy,
PSFacBuf_CreateStub
};
/* This is the whole PSFactoryBuffer object, just the vtableptr */
static ICOM_VTABLE(IPSFactoryBuffer) *lppsfac = &psfacbufvtbl;
/***********************************************************************
* DllGetClassObject [OLE32.63]
*/
HRESULT WINAPI OLE32_DllGetClassObject(REFCLSID rclsid, REFIID iid,LPVOID *ppv)
{
*ppv = NULL;
if (IsEqualIID(rclsid,&CLSID_PSFactoryBuffer)) {
*ppv = &lppsfac;
/* If we create a ps factory, we might need a stub manager later
* anyway
*/
STUBMGR_Start();
return S_OK;
}
if (IsEqualIID(rclsid,&CLSID_DfMarshal)&&IsEqualIID(iid,&IID_IClassFactory))
return MARSHAL_GetStandardMarshalCF(ppv);
FIXME("\n\tCLSID:\t%s,\n\tIID:\t%s\n",debugstr_guid(rclsid),debugstr_guid(iid));
return CLASS_E_CLASSNOTAVAILABLE;
}

693
dlls/ole32/rpc.c Normal file
View File

@ -0,0 +1,693 @@
/*
* (Local) RPC Stuff
*
* Copyright 2002 Marcus Meissner
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "windef.h"
#include "objbase.h"
#include "ole2.h"
#include "ole2ver.h"
#include "rpc.h"
#include "winerror.h"
#include "winreg.h"
#include "wownt32.h"
#include "wtypes.h"
#include "wine/unicode.h"
#include "wine/obj_base.h"
#include "wine/obj_clientserver.h"
#include "wine/obj_misc.h"
#include "wine/obj_marshal.h"
#include "wine/obj_storage.h"
#include "wine/obj_channel.h"
#include "wine/winbase16.h"
#include "compobj_private.h"
#include "ifs.h"
#include "compobj_private.h"
#include "debugtools.h"
DEFAULT_DEBUG_CHANNEL(ole);
typedef struct _wine_rpc_request {
int state;
HANDLE hPipe; /* temp copy of handle */
wine_rpc_request_header reqh;
wine_rpc_response_header resph;
LPBYTE Buffer;
} wine_rpc_request;
static wine_rpc_request **reqs = NULL;
static int nrofreqs = 0;
/* This pipe is _thread_ based */
typedef struct _wine_pipe {
wine_marshal_id mid; /* target mid */
DWORD tid; /* thread in which we execute */
HANDLE hPipe;
int pending;
HANDLE hThread;
CRITICAL_SECTION crit;
} wine_pipe;
static wine_pipe *pipes = NULL;
static int nrofpipes = 0;
typedef struct _PipeBuf {
ICOM_VTABLE(IRpcChannelBuffer) *lpVtbl;
DWORD ref;
wine_marshal_id mid;
wine_pipe *pipe;
} PipeBuf;
static int nrofreaders = 0;
static HRESULT WINAPI
_xread(HANDLE hf, LPVOID ptr, DWORD size) {
DWORD res;
if (!ReadFile(hf,ptr,size,&res,NULL)) {
FIXME("Failed to read from %x, le is %lx\n",hf,GetLastError());
return E_FAIL;
}
if (res!=size) {
FIXME("Read only %ld of %ld bytes.\n",res,size);
return E_FAIL;
}
return S_OK;
}
static void
drs(LPCSTR where) {
int i, states[10];
return ;
memset(states,0,sizeof(states));
for (i=nrofreqs;i--;)
states[reqs[i]->state]++;
FIXME("%lx/%s/%d: rq %d, w %d, rg %d, rsq %d, rsg %d, d %d\n",
GetCurrentProcessId(),
where,
nrofreaders,
states[REQSTATE_REQ_QUEUED],
states[REQSTATE_REQ_WAITING_FOR_REPLY],
states[REQSTATE_REQ_GOT],
states[REQSTATE_RESP_QUEUED],
states[REQSTATE_RESP_GOT],
states[REQSTATE_DONE]
);
}
static HRESULT WINAPI
_xwrite(HANDLE hf, LPVOID ptr, DWORD size) {
DWORD res;
if (!WriteFile(hf,ptr,size,&res,NULL)) {
FIXME("Failed to write to %x, le is %lx\n",hf,GetLastError());
return E_FAIL;
}
if (res!=size) {
FIXME("Wrote only %ld of %ld bytes.\n",res,size);
return E_FAIL;
}
return S_OK;
}
static DWORD WINAPI _StubReaderThread(LPVOID);
static HRESULT
PIPE_RegisterPipe(wine_marshal_id *mid, HANDLE hPipe, BOOL startreader) {
int i;
char pipefn[100];
for (i=0;i<nrofpipes;i++)
if (pipes[i].mid.processid==mid->processid)
return S_OK;
if (pipes)
pipes=(wine_pipe*)HeapReAlloc(GetProcessHeap(),0,pipes,sizeof(pipes[0])*(nrofpipes+1));
else
pipes=(wine_pipe*)HeapAlloc(GetProcessHeap(),0,sizeof(pipes[0]));
if (!pipes) return E_OUTOFMEMORY;
sprintf(pipefn,OLESTUBMGR"_%08lx",mid->processid);
memcpy(&(pipes[nrofpipes].mid),mid,sizeof(*mid));
pipes[nrofpipes].hPipe = hPipe;
InitializeCriticalSection(&(pipes[nrofpipes].crit));
nrofpipes++;
if (startreader) {
pipes[nrofpipes-1].hThread = CreateThread(NULL,0,_StubReaderThread,(LPVOID)pipes+(nrofpipes-1),0,&(pipes[nrofpipes-1].tid));
} else {
pipes[nrofpipes-1].tid = GetCurrentThreadId();
}
return S_OK;
}
static HANDLE
PIPE_FindByMID(wine_marshal_id *mid) {
int i;
for (i=0;i<nrofpipes;i++)
if ((pipes[i].mid.processid==mid->processid) &&
(GetCurrentThreadId()==pipes[i].tid)
)
return pipes[i].hPipe;
return INVALID_HANDLE_VALUE;
}
static wine_pipe*
PIPE_GetFromMID(wine_marshal_id *mid) {
int i;
for (i=0;i<nrofpipes;i++) {
if ((pipes[i].mid.processid==mid->processid) &&
(GetCurrentThreadId()==pipes[i].tid)
)
return pipes+i;
}
return NULL;
}
static HRESULT
RPC_GetRequest(wine_rpc_request **req) {
static int reqid = 0xdeadbeef;
int i;
for (i=0;i<nrofreqs;i++) { /* try to reuse */
if (reqs[i]->state == REQSTATE_DONE) {
reqs[i]->reqh.reqid = reqid++;
reqs[i]->resph.reqid = reqs[i]->reqh.reqid;
reqs[i]->hPipe = INVALID_HANDLE_VALUE;
*req = reqs[i];
reqs[i]->state = REQSTATE_START;
return S_OK;
}
}
/* create new */
if (reqs)
reqs = (wine_rpc_request**)HeapReAlloc(
GetProcessHeap(),
HEAP_ZERO_MEMORY,
reqs,
sizeof(wine_rpc_request*)*(nrofreqs+1)
);
else
reqs = (wine_rpc_request**)HeapAlloc(
GetProcessHeap(),
HEAP_ZERO_MEMORY,
sizeof(wine_rpc_request*)
);
if (!reqs)
return E_OUTOFMEMORY;
reqs[nrofreqs] = (wine_rpc_request*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(wine_rpc_request));
reqs[nrofreqs]->reqh.reqid = reqid++;
reqs[nrofreqs]->resph.reqid = reqs[nrofreqs]->reqh.reqid;
reqs[nrofreqs]->hPipe = INVALID_HANDLE_VALUE;
*req = reqs[nrofreqs];
reqs[nrofreqs]->state = REQSTATE_START;
nrofreqs++;
return S_OK;
}
static void
RPC_FreeRequest(wine_rpc_request *req) {
req->state = REQSTATE_DONE; /* Just reuse slot. */
return;
}
static HRESULT WINAPI
PipeBuf_QueryInterface(
LPRPCCHANNELBUFFER iface,REFIID riid,LPVOID *ppv
) {
*ppv = NULL;
if (IsEqualIID(riid,&IID_IRpcChannelBuffer) || IsEqualIID(riid,&IID_IUnknown)) {
*ppv = (LPVOID)iface;
IUnknown_AddRef(iface);
return S_OK;
}
return E_NOINTERFACE;
}
static ULONG WINAPI
PipeBuf_AddRef(LPRPCCHANNELBUFFER iface) {
ICOM_THIS(PipeBuf,iface);
This->ref++;
return This->ref;
}
static ULONG WINAPI
PipeBuf_Release(LPRPCCHANNELBUFFER iface) {
ICOM_THIS(PipeBuf,iface);
This->ref--;
if (This->ref)
return This->ref;
ERR("Free all stuff.\n");
HeapFree(GetProcessHeap(),0,This);
return 0;
}
static HRESULT WINAPI
PipeBuf_GetBuffer(
LPRPCCHANNELBUFFER iface,RPCOLEMESSAGE* msg,REFIID riid
) {
/*ICOM_THIS(PipeBuf,iface);*/
TRACE("(%p,%s), slightly wrong.\n",msg,debugstr_guid(riid));
/* probably reuses IID in real. */
if (msg->cbBuffer && (msg->Buffer == NULL))
msg->Buffer = HeapAlloc(GetProcessHeap(),0,msg->cbBuffer);
return S_OK;
}
static HRESULT
_invoke_onereq(wine_rpc_request *req) {
IRpcStubBuffer *stub;
RPCOLEMESSAGE msg;
HRESULT hres;
DWORD reqtype;
hres = MARSHAL_Find_Stub_Buffer(&(req->reqh.mid),&stub);
if (hres) {
ERR("Stub not found?\n");
return hres;
}
msg.Buffer = req->Buffer;
msg.iMethod = req->reqh.iMethod;
msg.cbBuffer = req->reqh.cbBuffer;
req->state = REQSTATE_INVOKING;
req->resph.retval = IRpcStubBuffer_Invoke(stub,&msg,NULL);
req->Buffer = msg.Buffer;
req->resph.cbBuffer = msg.cbBuffer;
reqtype = REQTYPE_RESPONSE;
hres = _xwrite(req->hPipe,&reqtype,sizeof(reqtype));
if (hres) return hres;
hres = _xwrite(req->hPipe,&(req->resph),sizeof(req->resph));
if (hres) return hres;
hres = _xwrite(req->hPipe,req->Buffer,req->resph.cbBuffer);
if (hres) return hres;
req->state = REQSTATE_DONE;
drs("invoke");
return S_OK;
}
static HRESULT _read_one(wine_pipe *xpipe);
static HRESULT
RPC_QueueRequestAndWait(wine_rpc_request *req) {
int i;
wine_rpc_request *xreq;
HRESULT hres;
DWORD reqtype;
wine_pipe *xpipe = PIPE_GetFromMID(&(req->reqh.mid));
if (!xpipe) {
FIXME("no pipe found.\n");
return E_POINTER;
}
if (GetCurrentProcessId() == req->reqh.mid.processid) {
ERR("In current process?\n");
return E_FAIL;
}
req->hPipe = xpipe->hPipe;
req->state = REQSTATE_REQ_WAITING_FOR_REPLY;
reqtype = REQTYPE_REQUEST;
hres = _xwrite(req->hPipe,&reqtype,sizeof(reqtype));
if (hres) return hres;
hres = _xwrite(req->hPipe,&(req->reqh),sizeof(req->reqh));
if (hres) return hres;
hres = _xwrite(req->hPipe,req->Buffer,req->reqh.cbBuffer);
if (hres) return hres;
while (1) {
/*WaitForSingleObject(hRpcChanged,INFINITE);*/
hres = _read_one(xpipe);
if (hres) break;
for (i=0;i<nrofreqs;i++) {
xreq = reqs[i];
if ((xreq->state==REQSTATE_REQ_GOT) && (xreq->hPipe==req->hPipe)) {
_invoke_onereq(xreq);
}
}
if (req->state == REQSTATE_RESP_GOT)
return S_OK;
}
return hres;
}
static HRESULT WINAPI
PipeBuf_SendReceive(
LPRPCCHANNELBUFFER iface,RPCOLEMESSAGE* msg,ULONG *status
) {
ICOM_THIS(PipeBuf,iface);
wine_rpc_request *req;
HRESULT hres;
TRACE("()\n");
if (This->mid.processid == GetCurrentProcessId()) {
ERR("Need to call directly!\n");
return E_FAIL;
}
hres = RPC_GetRequest(&req);
if (hres) return hres;
req->reqh.iMethod = msg->iMethod;
req->reqh.cbBuffer = msg->cbBuffer;
memcpy(&(req->reqh.mid),&(This->mid),sizeof(This->mid));
req->Buffer = msg->Buffer;
hres = RPC_QueueRequestAndWait(req);
if (hres) {
RPC_FreeRequest(req);
return hres;
}
msg->cbBuffer = req->resph.cbBuffer;
msg->Buffer = req->Buffer;
*status = req->resph.retval;
RPC_FreeRequest(req);
return S_OK;
}
static HRESULT WINAPI
PipeBuf_FreeBuffer(LPRPCCHANNELBUFFER iface,RPCOLEMESSAGE* msg) {
FIXME("(%p), stub!\n",msg);
return E_FAIL;
}
static HRESULT WINAPI
PipeBuf_GetDestCtx(
LPRPCCHANNELBUFFER iface,DWORD* pdwDestContext,void** ppvDestContext
) {
FIXME("(%p,%p), stub!\n",pdwDestContext,ppvDestContext);
return E_FAIL;
}
static HRESULT WINAPI
PipeBuf_IsConnected(LPRPCCHANNELBUFFER iface) {
FIXME("(), stub!\n");
return S_OK;
}
static ICOM_VTABLE(IRpcChannelBuffer) pipebufvt = {
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
PipeBuf_QueryInterface,
PipeBuf_AddRef,
PipeBuf_Release,
PipeBuf_GetBuffer,
PipeBuf_SendReceive,
PipeBuf_FreeBuffer,
PipeBuf_GetDestCtx,
PipeBuf_IsConnected
};
HRESULT
PIPE_GetNewPipeBuf(wine_marshal_id *mid, IRpcChannelBuffer **pipebuf) {
wine_marshal_id ourid;
DWORD res;
HANDLE hPipe;
HRESULT hres;
PipeBuf *pbuf;
hPipe = PIPE_FindByMID(mid);
if (hPipe == INVALID_HANDLE_VALUE) {
char pipefn[200];
sprintf(pipefn,OLESTUBMGR"_%08lx",mid->processid);
hPipe = CreateFileA(
pipefn,
GENERIC_READ|GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
0,
-1
);
if (hPipe == INVALID_HANDLE_VALUE) {
FIXME("Could not open named pipe %s, le is %lx\n",pipefn,GetLastError());
return E_FAIL;
}
hres = PIPE_RegisterPipe(mid, hPipe, FALSE);
if (hres) return hres;
memset(&ourid,0,sizeof(ourid));
ourid.processid = GetCurrentProcessId();
if (!WriteFile(hPipe,&ourid,sizeof(ourid),&res,NULL)||(res!=sizeof(ourid))) {
ERR("Failed writing startup mid!\n");
return E_FAIL;
}
}
pbuf = (PipeBuf*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(PipeBuf));
pbuf->lpVtbl = &pipebufvt;
pbuf->ref = 1;
memcpy(&(pbuf->mid),mid,sizeof(*mid));
*pipebuf = (IRpcChannelBuffer*)pbuf;
return S_OK;
}
static HRESULT
create_server(REFCLSID rclsid) {
HKEY key;
char buf[200];
HRESULT hres = E_UNEXPECTED;
char xclsid[80];
WCHAR dllName[MAX_PATH+1];
DWORD dllNameLen = sizeof(dllName);
STARTUPINFOW sinfo;
PROCESS_INFORMATION pinfo;
WINE_StringFromCLSID((LPCLSID)rclsid,xclsid);
sprintf(buf,"CLSID\\%s\\LocalServer32",xclsid);
hres = RegOpenKeyExA(HKEY_CLASSES_ROOT, buf, 0, KEY_READ, &key);
if (hres != ERROR_SUCCESS)
return REGDB_E_CLASSNOTREG;
memset(dllName,0,sizeof(dllName));
hres= RegQueryValueExW(key,NULL,NULL,NULL,(LPBYTE)dllName,&dllNameLen);
if (hres)
return REGDB_E_CLASSNOTREG; /* FIXME: check retval */
RegCloseKey(key);
memset(&sinfo,0,sizeof(sinfo));
sinfo.cb = sizeof(sinfo);
if (!CreateProcessW(NULL,dllName,NULL,NULL,FALSE,0,NULL,NULL,&sinfo,&pinfo))
return E_FAIL;
return S_OK;
}
/* http://msdn.microsoft.com/library/en-us/dnmsj99/html/com0199.asp, Figure 4 */
HRESULT create_marshalled_proxy(REFCLSID rclsid, REFIID iid, LPVOID *ppv) {
HRESULT hres;
HANDLE hPipe;
char pipefn[200];
DWORD res,bufferlen;
char marshalbuffer[200];
IStream *pStm;
LARGE_INTEGER seekto;
ULARGE_INTEGER newpos;
int tries = 0;
#define MAXTRIES 10000
strcpy(pipefn,PIPEPREF);
WINE_StringFromCLSID(rclsid,pipefn+strlen(PIPEPREF));
while (tries++<MAXTRIES) {
hPipe = CreateFileA(
pipefn,
GENERIC_READ|GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
0,
-1
);
if (hPipe == INVALID_HANDLE_VALUE) {
if (tries == 1) {
if ((hres = create_server(rclsid)))
return hres;
Sleep(1000);
} else {
WARN("Could not open named pipe to broker %s, le is %lx\n",pipefn,GetLastError());
Sleep(1000);
}
continue;
}
bufferlen = 0;
if (!ReadFile(hPipe,marshalbuffer,sizeof(marshalbuffer),&bufferlen,NULL)) {
FIXME("Failed to read marshal id from classfactory of %s.\n",debugstr_guid(rclsid));
Sleep(1000);
continue;
}
CloseHandle(hPipe);
break;
}
if (tries>=MAXTRIES)
return E_NOINTERFACE;
hres = CreateStreamOnHGlobal(0,TRUE,&pStm);
if (hres) return hres;
hres = IStream_Write(pStm,marshalbuffer,bufferlen,&res);
if (hres) goto out;
seekto.s.LowPart = 0;seekto.s.HighPart = 0;
hres = IStream_Seek(pStm,seekto,SEEK_SET,&newpos);
hres = CoUnmarshalInterface(pStm,&IID_IClassFactory,ppv);
out:
IStream_Release(pStm);
return hres;
}
static void WINAPI
PIPE_StartRequestThread(HANDLE xhPipe) {
wine_marshal_id remoteid;
HRESULT hres;
hres = _xread(xhPipe,&remoteid,sizeof(remoteid));
if (hres) {
ERR("Failed to read remote mid!\n");
return;
}
PIPE_RegisterPipe(&remoteid,xhPipe, TRUE);
}
static HRESULT
_read_one(wine_pipe *xpipe) {
DWORD reqtype;
HRESULT hres = S_OK;
HANDLE xhPipe = xpipe->hPipe;
/*FIXME("%lx %d reading reqtype\n",GetCurrentProcessId(),xhPipe);*/
hres = _xread(xhPipe,&reqtype,sizeof(reqtype));
if (hres) goto end;
EnterCriticalSection(&(xpipe->crit));
/*FIXME("%lx got reqtype %ld\n",GetCurrentProcessId(),reqtype);*/
if (reqtype == REQTYPE_REQUEST) {
wine_rpc_request *xreq;
RPC_GetRequest(&xreq);
xreq->hPipe = xhPipe;
hres = _xread(xhPipe,&(xreq->reqh),sizeof(xreq->reqh));
if (hres) goto end;
xreq->resph.reqid = xreq->reqh.reqid;
xreq->Buffer = HeapAlloc(GetProcessHeap(),0, xreq->reqh.cbBuffer);
hres = _xread(xhPipe,xreq->Buffer,xreq->reqh.cbBuffer);
if (hres) goto end;
xreq->state = REQSTATE_REQ_GOT;
goto end;
}
if (reqtype == REQTYPE_RESPONSE) {
wine_rpc_response_header resph;
int i;
hres = _xread(xhPipe,&resph,sizeof(resph));
if (hres) goto end;
for (i=nrofreqs;i--;) {
wine_rpc_request *xreq = reqs[i];
if (xreq->state != REQSTATE_REQ_WAITING_FOR_REPLY)
continue;
if (xreq->reqh.reqid == resph.reqid) {
memcpy(&(xreq->resph),&resph,sizeof(resph));
xreq->Buffer = HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,xreq->Buffer,xreq->resph.cbBuffer);
hres = _xread(xhPipe,xreq->Buffer,xreq->resph.cbBuffer);
if (hres) goto end;
xreq->state = REQSTATE_RESP_GOT;
/*PulseEvent(hRpcChanged);*/
goto end;
}
}
ERR("Did not find request for id %lx\n",resph.reqid);
hres = S_OK;
goto end;
}
ERR("Unknown reqtype %ld\n",reqtype);
hres = E_FAIL;
end:
LeaveCriticalSection(&(xpipe->crit));
return hres;
}
static DWORD WINAPI
_StubReaderThread(LPVOID param) {
wine_pipe *xpipe = (wine_pipe*)param;
HANDLE xhPipe = xpipe->hPipe;
HRESULT hres;
TRACE("STUB reader thread %lx\n",GetCurrentProcessId());
while (1) {
int i;
hres = _read_one(xpipe);
if (hres) break;
for (i=nrofreqs;i--;) {
wine_rpc_request *xreq = reqs[i];
if ((xreq->state == REQSTATE_REQ_GOT) && (xreq->hPipe == xhPipe)) {
_invoke_onereq(xreq);
}
}
}
FIXME("Failed with hres %lx\n",hres);
CloseHandle(xhPipe);
return 0;
}
static DWORD WINAPI
_StubMgrThread(LPVOID param) {
char pipefn[200];
HANDLE listenPipe;
sprintf(pipefn,OLESTUBMGR"_%08lx",GetCurrentProcessId());
TRACE("Stub Manager Thread starting on (%s)\n",pipefn);
listenPipe = CreateNamedPipeA(
pipefn,
PIPE_ACCESS_DUPLEX,
PIPE_TYPE_BYTE|PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES,
4096,
4096,
NMPWAIT_USE_DEFAULT_WAIT,
NULL
);
if (listenPipe == INVALID_HANDLE_VALUE) {
FIXME("pipe creation failed for %s, le is %lx\n",pipefn,GetLastError());
return 1; /* permanent failure, so quit stubmgr thread */
}
while (1) {
if (!ConnectNamedPipe(listenPipe,NULL)) {
ERR("Failure during ConnectNamedPipe %lx!\n",GetLastError());
CloseHandle(listenPipe);
continue;
}
PIPE_StartRequestThread(listenPipe);
listenPipe = CreateNamedPipeA(
pipefn,
PIPE_ACCESS_DUPLEX,
PIPE_TYPE_BYTE|PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES,
4096,
4096,
NMPWAIT_USE_DEFAULT_WAIT,
NULL
);
if (listenPipe == INVALID_HANDLE_VALUE) {
FIXME("pipe creation failed for %s, le is %lx\n",pipefn,GetLastError());
return 1; /* permanent failure, so quit stubmgr thread */
}
}
return 0;
}
void
STUBMGR_Start() {
static BOOL stubMgrRunning = FALSE;
DWORD tid;
if (!stubMgrRunning) {
stubMgrRunning = TRUE;
CreateThread(NULL,0,_StubMgrThread,NULL,0,&tid);
Sleep(2000); /* actually we just try opening the pipe until it succeeds */
}
}

View File

@ -21,6 +21,7 @@ C_SRCS = \
propertyframe.c \ propertyframe.c \
safearray.c \ safearray.c \
stubs.c \ stubs.c \
tmarshal.c \
typelib.c \ typelib.c \
variant.c variant.c

View File

@ -14,6 +14,9 @@
#include "olectl.h" #include "olectl.h"
#include "wine/obj_oleaut.h" #include "wine/obj_oleaut.h"
#include "wine/obj_olefont.h" #include "wine/obj_olefont.h"
#include "tmarshal.h"
#include "debugtools.h" #include "debugtools.h"
DEFAULT_DEBUG_CHANNEL(ole); DEFAULT_DEBUG_CHANNEL(ole);
@ -162,6 +165,11 @@ HRESULT WINAPI OLEAUT32_DllGetClassObject(REFCLSID rclsid, REFIID iid,LPVOID *pp
return S_OK; return S_OK;
} }
} }
if (IsEqualGUID(rclsid,&CLSID_PSOAInterface)) {
if (S_OK==TypeLibFac_DllGetClassObject(rclsid,iid,ppv))
return S_OK;
/*FALLTHROUGH*/
}
FIXME("\n\tCLSID:\t%s,\n\tIID:\t%s\n",debugstr_guid(rclsid),debugstr_guid(iid)); FIXME("\n\tCLSID:\t%s,\n\tIID:\t%s\n",debugstr_guid(rclsid),debugstr_guid(iid));
return CLASS_E_CLASSNOTAVAILABLE; return CLASS_E_CLASSNOTAVAILABLE;
} }

View File

@ -10,7 +10,7 @@ import advapi32.dll
import kernel32.dll import kernel32.dll
import ntdll.dll import ntdll.dll
debug_channels (ole typelib) debug_channels (ole olerelay typelib)
1 stdcall DllGetClassObject(ptr ptr ptr) OLEAUT32_DllGetClassObject 1 stdcall DllGetClassObject(ptr ptr ptr) OLEAUT32_DllGetClassObject
2 stdcall SysAllocString(wstr) SysAllocString 2 stdcall SysAllocString(wstr) SysAllocString

1204
dlls/oleaut32/tmarshal.c Normal file

File diff suppressed because it is too large Load Diff

6
dlls/oleaut32/tmarshal.h Normal file
View File

@ -0,0 +1,6 @@
#ifndef TMARSHAL_H
#define TMARSHAL_H
HRESULT WINAPI
TypeLibFac_DllGetClassObject(REFCLSID rclsid, REFIID iid,LPVOID *ppv);
#endif

View File

@ -3917,7 +3917,8 @@ static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
* Invokes a method, or accesses a property of an object, that implements the * Invokes a method, or accesses a property of an object, that implements the
* interface described by the type description. * interface described by the type description.
*/ */
static DWORD _invoke(LPVOID func,CALLCONV callconv, int nrargs, DWORD *args) { DWORD
_invoke(LPVOID func,CALLCONV callconv, int nrargs, DWORD *args) {
DWORD res; DWORD res;
if (TRACE_ON(ole)) { if (TRACE_ON(ole)) {
@ -3951,6 +3952,26 @@ static DWORD _invoke(LPVOID func,CALLCONV callconv, int nrargs, DWORD *args) {
res = xfunc(args[0],args[1],args[2]); res = xfunc(args[0],args[1],args[2]);
break; break;
} }
case 4: {
DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD) = func;
res = xfunc(args[0],args[1],args[2],args[3]);
break;
}
case 5: {
DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD,DWORD) = func;
res = xfunc(args[0],args[1],args[2],args[3],args[4]);
break;
}
case 6: {
DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD,DWORD,DWORD) = func;
res = xfunc(args[0],args[1],args[2],args[3],args[4],args[5]);
break;
}
case 7: {
DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD) = func;
res = xfunc(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
break;
}
default: default:
FIXME("unsupported number of arguments %d in stdcall\n",nrargs); FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
res = -1; res = -1;

View File

@ -542,6 +542,8 @@ WORD offset from start of block to SAFEARRAY
WORD typeofarray WORD typeofarray
*/ */
extern DWORD _invoke(LPVOID func,CALLCONV callconv, int nrargs, DWORD *args);
#include "poppack.h" #include "poppack.h"
/*---------------------------END--------------------------------------------*/ /*---------------------------END--------------------------------------------*/

View File

@ -1396,6 +1396,10 @@ static HRESULT Coerce( VARIANTARG* pd, LCID lcid, ULONG dwFlags, VARIANTARG* ps,
case( VT_BOOL ): case( VT_BOOL ):
switch( vtFrom ) switch( vtFrom )
{ {
case( VT_EMPTY ):
res = S_OK;
V_UNION(pd,boolVal) = VARIANT_FALSE;
break;
case( VT_I1 ): case( VT_I1 ):
res = VarBoolFromI1( V_UNION(ps,cVal), &V_UNION(pd,boolVal) ); res = VarBoolFromI1( V_UNION(ps,cVal), &V_UNION(pd,boolVal) );
break; break;