Implemented Local Server COM.
Implemented the Typelib based Marshaler.
This commit is contained in:
parent
395e8bafc4
commit
0749fc2034
|
@ -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 \
|
||||||
|
|
|
@ -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
|
||||||
*
|
*
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -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 */
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,6 @@
|
||||||
|
#ifndef TMARSHAL_H
|
||||||
|
#define TMARSHAL_H
|
||||||
|
HRESULT WINAPI
|
||||||
|
TypeLibFac_DllGetClassObject(REFCLSID rclsid, REFIID iid,LPVOID *ppv);
|
||||||
|
|
||||||
|
#endif
|
|
@ -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;
|
||||||
|
|
|
@ -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--------------------------------------------*/
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue