Commit 0749fc20 authored by Marcus Meissner's avatar Marcus Meissner Committed by Alexandre Julliard

Implemented Local Server COM.

Implemented the Typelib based Marshaler.
parent 395e8baf
......@@ -22,6 +22,7 @@ C_SRCS = \
hglobalstream.c \
ifs.c \
itemmoniker.c \
marshal.c \
memlockbytes.c \
moniker.c \
ole2.c \
......@@ -30,6 +31,8 @@ C_SRCS = \
ole2nls.c \
ole32_main.c \
oleobj.c \
oleproxy.c \
rpc.c \
stg_bigblockfile.c \
stg_stream.c \
storage.c \
......
......@@ -5,6 +5,7 @@
* Copyright 1998 Justin Bradford
* Copyright 1999 Francis Beaudet
* Copyright 1999 Sylvain St-Germain
* Copyright 2002 Marcus Meissner
*/
#include "config.h"
......@@ -29,6 +30,7 @@
#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"
......@@ -138,6 +140,7 @@ typedef struct tagRegisteredClass
DWORD runContext;
DWORD connectFlags;
DWORD dwCookie;
HANDLE hThread; /* only for localserver */
struct tagRegisteredClass* nextClass;
} RegisteredClass;
......@@ -559,7 +562,7 @@ HRESULT WINAPI CLSIDFromString(
* RETURNS
* the string representation and HRESULT
*/
static HRESULT WINE_StringFromCLSID(
HRESULT WINE_StringFromCLSID(
const CLSID *id, /* [in] GUID to be converted */
LPSTR idstr /* [out] pointer to buffer to contain converted guid */
) {
......@@ -1060,6 +1063,83 @@ end:
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]
*
......@@ -1078,24 +1158,13 @@ HRESULT WINAPI CoRegisterClassObject(
RegisteredClass* newClass;
LPUNKNOWN foundObject;
HRESULT hr;
char buf[80];
WINE_StringFromCLSID(rclsid,buf);
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) )
{
return E_INVALIDARG;
}
/*
* Initialize the cookie (out parameter)
*/
*lpdwRegister = 0;
/*
......@@ -1103,35 +1172,24 @@ HRESULT WINAPI CoRegisterClassObject(
* If it is, this should cause an error.
*/
hr = COM_GetRegisteredClassObject(rclsid, dwClsContext, &foundObject);
if (hr == S_OK)
{
/*
* The COM_GetRegisteredClassObject increased the reference count on the
* object so it has to be released.
*/
if (hr == S_OK) {
IUnknown_Release(foundObject);
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));
if ( newClass == NULL )
return E_OUTOFMEMORY;
EnterCriticalSection( &csRegisteredClassList );
/*
* Initialize the node.
*/
newClass->classIdentifier = *rclsid;
newClass->runContext = dwClsContext;
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->nextClass = firstRegisteredClass;
......@@ -1143,17 +1201,16 @@ HRESULT WINAPI CoRegisterClassObject(
IUnknown_AddRef(newClass->classObject);
firstRegisteredClass = newClass;
LeaveCriticalSection( &csRegisteredClassList );
/*
* Assign the out parameter (cookie)
*/
*lpdwRegister = newClass->dwCookie;
/*
* We're successful Yippee!
*/
if (dwClsContext & CLSCTX_LOCAL_SERVER) {
DWORD tid;
STUBMGR_Start();
newClass->hThread=CreateThread(NULL,0,_LocalServerThread,newClass,0,&tid);
}
return S_OK;
}
......@@ -1222,6 +1279,42 @@ end:
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 [OLE32.16]
......@@ -1280,9 +1373,22 @@ HRESULT WINAPI CoGetClassObject(
return hres;
}
/* Then try for in-process */
if ((CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER) & dwClsContext)
{
if (((CLSCTX_LOCAL_SERVER) & 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));
sprintf(buf,"CLSID\\%s\\InprocServer32",xclsid);
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;
}
/***********************************************************************
* 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
*
......
......@@ -5,6 +5,86 @@
#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 */
HRESULT WINAPI RunningObjectTableImpl_Initialize();
......
......@@ -30,7 +30,7 @@ debug_channels (accel ole relay storage)
16 stdcall CoGetClassObject(ptr long ptr ptr ptr) CoGetClassObject
17 stub CoGetCurrentLogicalThreadId
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
21 stub CoGetMarshalSizeMax # stdcall (ptr ptr ptr long ptr long) return 0,ERR_NOTIMPLEMENTED
22 stdcall CoGetPSClsid(ptr ptr) CoGetPSClsid
......@@ -44,8 +44,8 @@ debug_channels (accel ole relay storage)
30 stdcall CoLoadLibrary(wstr long) CoLoadLibrary
31 stdcall CoLockObjectExternal(ptr long long) CoLockObjectExternal
32 stub CoMarshalHresult # stdcall (ptr ptr) return 0,ERR_NOTIMPLEMENTED
33 stub CoMarshalInterThreadInterfaceInStream # stdcall (ptr ptr ptr) return 0,ERR_NOTIMPLEMENTED
34 stub CoMarshalInterface # stdcall (ptr ptr ptr long ptr long) return 0,ERR_NOTIMPLEMENTED
33 stdcall CoMarshalInterThreadInterfaceInStream(ptr ptr ptr) CoMarshalInterThreadInterfaceInStream
34 stdcall CoMarshalInterface(ptr ptr ptr long ptr long) CoMarshalInterface
35 stub CoQueryReleaseObject
36 stdcall CoRegisterClassObject(ptr ptr long long ptr) CoRegisterClassObject
37 stub CoRegisterMallocSpy # stdcall (ptr) return 0,ERR_NOTIMPLEMENTED
......@@ -61,7 +61,7 @@ debug_channels (accel ole relay storage)
47 stdcall CoUninitialize() CoUninitialize
48 stub CoUnloadingWOW
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
52 stdcall CreateBindCtx(long ptr) CreateBindCtx
53 stdcall CreateDataAdviseHolder(ptr) CreateDataAdviseHolder
......
......@@ -21,6 +21,7 @@ C_SRCS = \
propertyframe.c \
safearray.c \
stubs.c \
tmarshal.c \
typelib.c \
variant.c
......
......@@ -14,6 +14,9 @@
#include "olectl.h"
#include "wine/obj_oleaut.h"
#include "wine/obj_olefont.h"
#include "tmarshal.h"
#include "debugtools.h"
DEFAULT_DEBUG_CHANNEL(ole);
......@@ -162,6 +165,11 @@ HRESULT WINAPI OLEAUT32_DllGetClassObject(REFCLSID rclsid, REFIID iid,LPVOID *pp
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));
return CLASS_E_CLASSNOTAVAILABLE;
}
......
......@@ -10,7 +10,7 @@ import advapi32.dll
import kernel32.dll
import ntdll.dll
debug_channels (ole typelib)
debug_channels (ole olerelay typelib)
1 stdcall DllGetClassObject(ptr ptr ptr) OLEAUT32_DllGetClassObject
2 stdcall SysAllocString(wstr) SysAllocString
......
#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
* 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;
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]);
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:
FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
res = -1;
......
......@@ -542,6 +542,8 @@ WORD offset from start of block to SAFEARRAY
WORD typeofarray
*/
extern DWORD _invoke(LPVOID func,CALLCONV callconv, int nrargs, DWORD *args);
#include "poppack.h"
/*---------------------------END--------------------------------------------*/
......
......@@ -1396,6 +1396,10 @@ static HRESULT Coerce( VARIANTARG* pd, LCID lcid, ULONG dwFlags, VARIANTARG* ps,
case( VT_BOOL ):
switch( vtFrom )
{
case( VT_EMPTY ):
res = S_OK;
V_UNION(pd,boolVal) = VARIANT_FALSE;
break;
case( VT_I1 ):
res = VarBoolFromI1( V_UNION(ps,cVal), &V_UNION(pd,boolVal) );
break;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment