Hello,
After last weeks discussion on the "unhandled interface" message in CFProxy_QueryInterface I was getting, we concluded (if I'm correct) that this is part of the "IRemUnknown" handling that is not (yet) implemented correctly in the wine CVS tree.
I'm trying to figure out exactly where in the (OLE) code, this should be handled. If someone could point me in the right direction I would appreciate it very much.
I think it would also be helpfull if there was some "fixme" logging so other people can also see if they hit upon the same problem (since it took a while to finally figure out the problem). --- Jeroen
Jeroen Janssen wrote:
Hello,
After last weeks discussion on the "unhandled interface" message in CFProxy_QueryInterface I was getting, we concluded (if I'm correct) that this is part of the "IRemUnknown" handling that is not (yet) implemented correctly in the wine CVS tree.
I can't work out how IUnknown marshalling is getting delegated to the IClassFactory marshaller, but IUnknown marshalling should be a special case in StdMarshalImpl_UnmarshalInterface.
I'm trying to figure out exactly where in the (OLE) code, this should be handled. If someone could point me in the right direction I would appreciate it very much.
Does this patch help?
I think it would also be helpfull if there was some "fixme" logging so other people can also see if they hit upon the same problem (since it took a while to finally figure out the problem).
I suppose I could put a fixme in the above mentioned function that will alert you to this specific problem, but there are so many problems with the current code that putting in fixme's for all of them would take ages and I'd much rather prefer to be fixing them. If you'd like a list things not implemented in our current COM implementation then please let me know and I'll send one to you.
Rob
Index: wine/dlls/ole32/oleproxy.c =================================================================== RCS file: /home/wine/wine/dlls/ole32/oleproxy.c,v retrieving revision 1.17 diff -u -r1.17 oleproxy.c --- wine/dlls/ole32/oleproxy.c 22 Jul 2004 23:44:54 -0000 1.17 +++ wine/dlls/ole32/oleproxy.c 26 Jul 2004 10:53:20 -0000 @@ -139,7 +139,73 @@ ICOM_THIS(CFStub,iface); HRESULT hres;
- if (msg->iMethod == 3) { /* CreateInstance */ + if (msg->iMethod == 0) { /* QueryInterface */ + 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_QueryInterface(classfac,&iid,(LPVOID*)&ppv); + IClassFactory_Release(classfac); + if (hres) { + msg->cbBuffer = 0; + FIXME("Failed to QueryInterface %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.u.LowPart; + + if (msg->Buffer) + msg->Buffer = HeapReAlloc(GetProcessHeap(),0,msg->Buffer,ststg.cbSize.u.LowPart); + else + msg->Buffer = HeapAlloc(GetProcessHeap(),0,ststg.cbSize.u.LowPart); + + seekto.u.LowPart = 0;seekto.u.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; + } + else if (msg->iMethod == 3) { /* CreateInstance */ IID iid; IClassFactory *classfac; IUnknown *ppv; @@ -315,6 +381,12 @@
static HRESULT WINAPI CFProxy_QueryInterface(LPCLASSFACTORY iface,REFIID riid, LPVOID *ppv) { + ICOM_THIS_MULTI(CFProxy,lpvtbl_cf,iface); + HRESULT hres; + LPSTREAM pStream; + HGLOBAL hGlobal; + ULONG srstatus; + RPCOLEMESSAGE msg; *ppv = NULL; if (IsEqualIID(&IID_IClassFactory,riid) || IsEqualIID(&IID_IUnknown,riid)) { *ppv = (LPVOID)iface; @@ -323,8 +395,49 @@ } if (IsEqualIID(riid,&IID_IMarshal)) /* just to avoid debug output */ return E_NOINTERFACE; - FIXME("Unhandled interface: %s\n",debugstr_guid(riid)); - return E_NOINTERFACE; + + /* Send QueryInterface to the remote classfactory. + * + * Data: Only the 'IID'. + */ + msg.iMethod = 0; + 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: [Marshalled 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 ULONG WINAPI CFProxy_AddRef(LPCLASSFACTORY iface) {
After last weeks discussion on the "unhandled interface" message in CFProxy_QueryInterface I was getting, we concluded (if I'm correct) that this is part of the "IRemUnknown" handling that is not (yet) implemented correctly in the wine CVS tree.
I can't work out how IUnknown marshalling is getting delegated to the IClassFactory marshaller, but IUnknown marshalling should be a special case in StdMarshalImpl_UnmarshalInterface.
I'm trying to figure out exactly where in the (OLE) code, this should be handled. If someone could point me in the right direction I would appreciate it very much.
Does this patch help?
No, with this patch it does not work yet.
I will try to have a more detailed look at the path itself tonight and hopefully understand more about how it should work.
In the mean time, I have attached a small zipfile with the server & client logging from the lab7 test program I send you and Mike (running on CVS as of today + your patch).
If you want an "easy" testcase to see for yourself if the patch works, you can use the original test programs I send you(that zipfile contained both src and executables that you can run with wine).
On a side note I noticed there are no 'unittest' in the ole32 directory. This sounds like something that could be usefull to have in there (although I'm not sure what the best way is to put it in the wine tree). Note though that I didn't write the original testprogram, so we probably would need to write some from scratch to be sure.
I think it would also be helpfull if there was some "fixme" logging so other people can also see if they hit upon the same problem (since it took a while to finally figure out the problem).
I suppose I could put a fixme in the above mentioned function that will alert you to this specific problem, but there are so many problems with the current code that putting in fixme's for all of them would take ages and I'd much rather prefer to be fixing them.
I agree that fixing things is the preferred way to go, however whenever someone 'hits' a problem (like this one), it would be helpfull to point slightly in the right direction on where to look for the problem/a solution.
A 'fixme' in the logging might also make it easier to trigger other people (than the original developer) to try and help & fix, because it's easier to see that something is not implemented (correctly) yet.
If I run a program and I don't see 'fixme' logging for items that are (known to be) broken/missing, it's harder for me to see/understand and have a look at it, so I can help with it.
On the other hand, I do understand that people want to focus on the 'important' things, instead of having to walk through all the (wine) code and put a fixme/todo statement where needed.
If you'd like a list things not implemented in our current COM
implementation then please let
me know and I'll send one to you.
That would be nice to have indeed (I don't know if other people on this list are interested in it too). --- Jeroen
man, 26.07.2004 kl. 13.03 skrev Robert Shearman:
I can't work out how IUnknown marshalling is getting delegated to the IClassFactory marshaller,
It shouldn't, as far as I know. Or, what exactly are you asking?