Hi, This patch fixes some small installation problems with DreamWeaver 4. Both patch and new files are attached. The implementation is as good that it now installs DreamWeaver 4, which is the exit criteria for releasing the patch ;) No single line of code was taken from WineX CVS, just the idea of using named pipes and several hints regarding problems and other unsupported features. New debug channel 'olerelay' to watch the interprocess calls. (5 weeks of spare evenings and weekends well spent I think.) Ciao, Marcus Changelog: Implemented Local Server COM. Implemented the Typelib based Marshaler.
Index: dlls/ole32/Makefile.in =================================================================== RCS file: /home/wine/wine/dlls/ole32/Makefile.in,v retrieving revision 1.16 diff -u -r1.16 Makefile.in --- dlls/ole32/Makefile.in 2000/12/06 01:50:48 1.16 +++ dlls/ole32/Makefile.in 2002/02/03 19:33:32 @@ -22,6 +22,7 @@ hglobalstream.c \ ifs.c \ itemmoniker.c \ + marshal.c \ memlockbytes.c \ moniker.c \ ole2.c \ @@ -30,6 +31,8 @@ ole2nls.c \ ole32_main.c \ oleobj.c \ + oleproxy.c \ + rpc.c \ stg_bigblockfile.c \ stg_stream.c \ storage.c \ Index: dlls/ole32/compobj.c =================================================================== RCS file: /home/wine/wine/dlls/ole32/compobj.c,v retrieving revision 1.53 diff -u -r1.53 compobj.c --- dlls/ole32/compobj.c 2002/02/02 18:42:14 1.53 +++ dlls/ole32/compobj.c 2002/02/03 19:33:55 @@ -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 @@ DWORD runContext; DWORD connectFlags; DWORD dwCookie; + HANDLE hThread; /* only for localserver */ struct tagRegisteredClass* nextClass; } RegisteredClass; @@ -559,7 +562,7 @@ * 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 @@ 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 @@ 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 @@ * 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 @@ 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 @@ 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 @@ 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) || @@ -1854,18 +1960,6 @@ 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 Index: dlls/ole32/compobj_private.h =================================================================== RCS file: /home/wine/wine/dlls/ole32/compobj_private.h,v retrieving revision 1.2 diff -u -r1.2 compobj_private.h --- dlls/ole32/compobj_private.h 2001/07/20 18:00:01 1.2 +++ dlls/ole32/compobj_private.h 2002/02/03 19:33:55 @@ -5,6 +5,87 @@ #include "wtypes.h" +WINE_UNUSED HRESULT WINE_StringFromCLSID(const CLSID *id,LPSTR idstr); +HRESULT create_marshalled_proxy(REFCLSID rclsid, REFIID iid, LPVOID *ppv); + +static HRESULT WINE_UNUSED +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; + +static BOOL WINE_UNUSED +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 */ +static BOOL WINE_UNUSED +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(); + +HRESULT WINE_UNUSED +PIPE_GetNewPipeBuf(wine_marshal_id *mid, IRpcChannelBuffer **pipebuf); + /* This function initialize the Running Object Table */ HRESULT WINAPI RunningObjectTableImpl_Initialize(); Index: dlls/ole32/ole32.spec =================================================================== RCS file: /home/wine/wine/dlls/ole32/ole32.spec,v retrieving revision 1.29 diff -u -r1.29 ole32.spec --- dlls/ole32/ole32.spec 2001/07/14 00:47:52 1.29 +++ dlls/ole32/ole32.spec 2002/02/03 19:34:00 @@ -30,7 +30,7 @@ 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 @@ 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 @@ 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 Index: dlls/oleaut32/Makefile.in =================================================================== RCS file: /home/wine/wine/dlls/oleaut32/Makefile.in,v retrieving revision 1.25 diff -u -r1.25 Makefile.in --- dlls/oleaut32/Makefile.in 2001/10/23 19:59:24 1.25 +++ dlls/oleaut32/Makefile.in 2002/02/03 19:34:01 @@ -21,6 +21,7 @@ propertyframe.c \ safearray.c \ stubs.c \ + tmarshal.c \ typelib.c \ variant.c Index: dlls/oleaut32/oleaut.c =================================================================== RCS file: /home/wine/wine/dlls/oleaut32/oleaut.c,v retrieving revision 1.21 diff -u -r1.21 oleaut.c --- dlls/oleaut32/oleaut.c 2001/10/02 18:28:31 1.21 +++ dlls/oleaut32/oleaut.c 2002/02/03 19:34:06 @@ -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); @@ -161,6 +164,11 @@ IClassFactory_AddRef((IClassFactory*)*ppv); 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; Index: dlls/oleaut32/oleaut32.spec =================================================================== RCS file: /home/wine/wine/dlls/oleaut32/oleaut32.spec,v retrieving revision 1.34 diff -u -r1.34 oleaut32.spec --- dlls/oleaut32/oleaut32.spec 2002/01/29 02:44:44 1.34 +++ dlls/oleaut32/oleaut32.spec 2002/02/03 19:34:08 @@ -10,7 +10,7 @@ import kernel32.dll import ntdll.dll -debug_channels (ole typelib) +debug_channels (ole typelib olerelay) 1 stdcall DllGetClassObject(ptr ptr ptr) OLEAUT32_DllGetClassObject 2 stdcall SysAllocString(wstr) SysAllocString Index: dlls/oleaut32/typelib.c =================================================================== RCS file: /home/wine/wine/dlls/oleaut32/typelib.c,v retrieving revision 1.61 diff -u -r1.61 typelib.c --- dlls/oleaut32/typelib.c 2002/01/29 17:05:11 1.61 +++ dlls/oleaut32/typelib.c 2002/02/03 19:34:32 @@ -3915,7 +3934,8 @@ * 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)) { @@ -3949,6 +3969,26 @@ 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; Index: dlls/oleaut32/typelib.h =================================================================== RCS file: /home/wine/wine/dlls/oleaut32/typelib.h,v retrieving revision 1.7 diff -u -r1.7 typelib.h --- dlls/oleaut32/typelib.h 2002/01/29 03:12:22 1.7 +++ dlls/oleaut32/typelib.h 2002/02/03 19:34:37 @@ -542,6 +542,8 @@ WORD typeofarray */ +extern DWORD _invoke(LPVOID func,CALLCONV callconv, int nrargs, DWORD *args); + #include "poppack.h" /*---------------------------END--------------------------------------------*/ Index: dlls/oleaut32/variant.c =================================================================== RCS file: /home/wine/wine/dlls/oleaut32/variant.c,v retrieving revision 1.31 diff -u -r1.31 variant.c --- dlls/oleaut32/variant.c 2002/01/29 02:44:44 1.31 +++ dlls/oleaut32/variant.c 2002/02/03 19:34:47 @@ -1392,6 +1396,10 @@ 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;
Attachment:
newfiles.tgz
Description: Binary data