Message du 08/07/03 12:45
De : Mike Hearn A : wine-devel@winehq.com Copie à : Objet : MS OLE questions Hi all,
Hi,
Thirdly, why does MSOLE use hidden windows for communication? I've come across lots of gnashing of teeth in OLE/DCOM forums about this, people wondering why their app (and sometimes the whole system!) deadlocks if they don't service the message queue in threads that use OLE. Windows has had other forms of IPC for years, I can't see the logic behind using the limited and broken message passing scheme for it.
IFAIK, this is how apartments are implemented and this comes from Windows 3.1.
Christian.
IFAIK, this is how apartments are implemented and this comes from Windows 3.1.
That's what I was thinking, but I found an article from 1994 claiming that ole would be shortly moving to the DCE RPC protocol instead of using window messages (and so they did).
I guess they didn't purge window messages entirely.
That's what I was thinking, but I found an article from 1994 claiming that ole would be shortly moving to the DCE RPC protocol instead of using window messages (and so they did).
I guess they didn't purge window messages entirely.
Actually, it looks like they didn't: http://www.microsoft.com/msj/0596/activex0596.aspx
so it seems window messages are still used for RPC when no networking is involved.
That's what I was thinking, but I found an article from 1994 claiming that ole would be shortly moving to the DCE RPC protocol instead of using window messages (and so they did).
I guess they didn't purge window messages entirely.
Actually, it looks like they didn't: http://www.microsoft.com/msj/0596/activex0596.aspx
so it seems window messages are still used for RPC when no networking is involved.
This looks like the part that should be most interesting to us... (below) I didn't see anything to indicate that RPC uses messages (If i'm reading your comments correctly, it sounds like you think it does?). However, in order to avoid the blocking RPC system call, the thread enters a message loop and makes the RPC system call on another worker thread (when a call is made within the channel implementation). If this pool of threads and worker-made-call functionality is not currently implemented in the standard IRpcChannelBuffer implementation in WINELIB, then we probably need to implement it somehow.
As shown in Figure 4, the Apartment model uses additional threads to achieve the reentrancy requirements for OLE. In the Apartment model, when the client thread makes a method call on an object in a different thread, process, or host, the client is actually making a method call on a proxy. The proxy marshals the appropriate parameters into the request PDU and dispatches the call to the object by calling the channel's SendReceive method, which does not return until the response PDU is received from the object. For those of you new to standard marshaling, a channel is just a COM-based wrapper around the RPC run-time layer. Once inside the implementation of the channel, the client thread does not call the low-level RPC run-time routine directly. Instead, the client thread spawns a worker thread to perform the blocking call and then waits in a modal message loop so external method requests can be serviced as well. (An application can install a message filter inside this modal loop to allow or disallow incoming method requests and non-OLE window messages. See CoRegisterMessageFilter for details.) This modal loop continues until the worker thread notifies the client thread that the response PDU was returned by the RPC run time. When the modal loop exits, the channel's SendReceive method returns the response PDU to the proxy for unmarshaling to the client. Because all of this happens behind the channel's IRpcChannelBuffer interface, the client and proxy are blissfully unaware that anything other than a blocking call took place. To avoid excessive thread creation, COM maintains a pool of worker threads that perform blocking RPC calls. The number of threads in the pool grows and shrinks based on the number of outstanding calls.
Kelly
This looks like the part that should be most interesting to us... (below) I didn't see anything to indicate that RPC uses messages (If i'm reading your comments correctly, it sounds like you think it does?).
Under the Apartment model, each thread that calls CoInitialize or OleInitialize is an OLE Apartment (a place where objects reside). Both API calls result in a call to CreateWindowEx. This creates an invisible HWND that receives a private window message for each incoming method request. The OLE-supplied WndProc for this window looks up the stub—based on the contents of the request—and calls the stub's Invoke routine. The first time an interface pointer on an object is marshaled, its owning apartment is established based on the thread executing the call to CoMarshalInterface.
(For objects created via CoCreateInstance, this is determined by the thread that made the initial call to CoRegisterClassObject.) From that point forward, all proxies to the object route their request PDUs to the message queue of the object's apartment. These messages are normally serviced in the main message pump of the server application, but some technique for allowing incoming calls to be serviced is needed to avoid deadlock if the server application is also a client and is making a synchronous method call.
So, the article seems to imply that messages are used, and they definately play a role - I can see WM_USER messages being sent between the OLEChannelWnd and OleMainThreadWnd, wp=thread id of sender, lp=opaque value (pointer??)
One puzzling thing is this:
004d:trace:msg:PostMessageW hwnd 0x10024 msg 400 ("SunAwtComponent") wp 4d lp 56e60510
SunAwtComponent? That doesn't look right.
Java registers its own window message somewhere up at the start of the app, msg id 0x0c003 or something like that, 400 otoh is WM_USER, so I don't know why Wine matches against SunAwtComponent here. OTOH it does it again here:
004d:trace:msg:PostMessageW hwnd 0x10024 msg 400 (WM_NCHITTEST) wp 4d lp 56e60510
*shrug*
After sending this message it sits in a loop frobbing the message queue with GetQueueStatus, normally followed by a MsgWaitForMultipleObjects() call, then an IsWindow (are you alive rpc server?), allocates some memory in a loop then does some RtlUnwind()s, and some GetProcAddress()s. Then it begins again.
I can't quite see the boundaries of the RPC call, it appears to be made asynchronously, then MSRPC polls a wait object for a bit? The MainWnd picks this message up just fine, does some stuff and returns from the window proc.
tir, 08.07.2003 kl. 13.57 skrev Kelly Leahy:
That's what I was thinking, but I found an article from 1994 claiming that ole would be shortly moving to the DCE RPC protocol instead of using window messages (and so they did).
I guess they didn't purge window messages entirely.
Actually, it looks like they didn't: http://www.microsoft.com/msj/0596/activex0596.aspx
so it seems window messages are still used for RPC when no networking is involved.
This looks like the part that should be most interesting to us... (below) I didn't see anything to indicate that RPC uses messages (If i'm reading your comments correctly, it sounds like you think it does?). However, in order to avoid the blocking RPC system call, the thread enters a message loop and makes the RPC system call on another worker thread (when a call is made within the channel implementation). If this pool of threads and worker-made-call functionality is not currently implemented in the standard IRpcChannelBuffer implementation in WINELIB, then we probably need to implement it somehow.
I've implemented this, I just haven't submitted my work in this area because there's a lot of other ugliness around my interthread work which I *still* haven't got around to clean up (perhaps I better do it soon). Should I maybe send it in as-is anyway if I still can't get around to it?
I've implemented this, I just haven't submitted my work in this area because there's a lot of other ugliness around my interthread work which I *still* haven't got around to clean up (perhaps I better do it soon). Should I maybe send it in as-is anyway if I still can't get around to it?
Yeah, please. At this point I am basically running out of time for this app before I leave/they run out of patience. As such, I don't care how messy the patch is, or how many other apps it breaks, I'd like to take a look at it.
I'm still not sure it'll work - I tried a simple inter-process app demo from 1994 today, and it wouldn't work with wines built in ole.
But, it's either that or wrestle with binary only OLE, and so far every time I've done that, Microsoft won :(
tir, 08.07.2003 kl. 21.45 skrev Mike Hearn:
I've implemented this, I just haven't submitted my work in this area because there's a lot of other ugliness around my interthread work which I *still* haven't got around to clean up (perhaps I better do it soon). Should I maybe send it in as-is anyway if I still can't get around to it?
Yeah, please. At this point I am basically running out of time for this app before I leave/they run out of patience. As such, I don't care how messy the patch is, or how many other apps it breaks, I'd like to take a look at it.
Well, here's the relevant pieces of the unmerged bits of the raw patch against ReWind I'm currently working on. Since some Wine stuff is not in ReWind, it doesn't apply to Wine, and ignores necessary changes to some stuff which is there - particularly Marcus's typelib marshaller is ignored here, since I've used my own original one (which is added to this patch for completeness), although Marcus's one would probably not be too hard to adapt. Anyway, getting this work merged may be a fair bit of work, and I've been intending to get it all in eventually, but I guess I have not been that quick about it...
I might get around to do some cleanups and merges soon, but now you have it in case I don't.
Oh my god... a 200k patch ??
===== Sylvain Petreolle (spetreolle_at_users_dot_sourceforge_dot_net) ICQ #170597259
alias upsf='false ; while [ $? -ne 0 ] ; do cvs update -APd ; done 2>&1 |tee cvslog'
"What if tomorrow the War could be over ?" Morpheus, in "Reloaded".
___________________________________________________________ Do You Yahoo!? -- Une adresse @yahoo.fr gratuite et en français ! Yahoo! Mail : http://fr.mail.yahoo.com
Most of it is generated by MIDL.
Given how flakey wines built in OLE is with this sort of thing currently (my little test case app crashes unless you use exactly ole32,oleaut32,rpcrt4=n shell32=b) I'll stick with trying to debug native ole for a bit longer.
Ove, can you remember what that book was called, the one that talked about what OLE does at thread shutdown?
thanks -mike
On Wed, 2003-07-09 at 18:57, Sylvain Petreolle wrote:
Oh my god... a 200k patch ??
===== Sylvain Petreolle (spetreolle_at_users_dot_sourceforge_dot_net) ICQ #170597259
alias upsf='false ; while [ $? -ne 0 ] ; do cvs update -APd ; done 2>&1 |tee cvslog'
"What if tomorrow the War could be over ?" Morpheus, in "Reloaded".
Do You Yahoo!? -- Une adresse @yahoo.fr gratuite et en français ! Yahoo! Mail : http://fr.mail.yahoo.com
tor, 10.07.2003 kl. 12.44 skrev Mike Hearn:
Most of it is generated by MIDL.
Yes. I still haven't made widl generate this stuff itself (but then again, midl is known to reliably generate MS-compatible code, which it would be hard to trust widl to do 100% even after implementing it).
Ove, can you remember what that book was called, the one that talked about what OLE does at thread shutdown?
Not sure. I have "Essential COM" by Don Box, which goes in pretty good depth about what happens behind the scenes, though unfortunately not every possible detail is covered. It's also possible that I read it is one of his articles available on MSDN (you had a link to one of them, but there are others), but still, the book is a very, very informative read.
Before I start, sorry for the long email, but if I'm going to make our app work within the 3 weeks I have left, I'm going to have to learn about COM pretty quickly :/
Reading through the patch, I have a few questions.
Firstly, how much of the code in this patch is already duplicated in the WineHQ tree? I see a oleproxy.c file, from Marcus (C) 2002, which you removed from the build, but your patch is in parts (C) 2001. Does that mean that the patch removes code that actually it shouldn't when applied to WineHQ?
I don't understand this code:
+static void RpcChannel_push_request(RpcRequest *req) +{ + req->next = NULL; + req->ret = RPC_S_CALL_IN_PROGRESS; /* ? */ + EnterCriticalSection(&creq_cs); + if (creq_tail) creq_tail->next = req; + else { + creq_head = req; + creq_tail = req; + } + LeaveCriticalSection(&creq_cs); +}
If this is a double-ended queue, like it looks, then shouldn't the middle line read:
if (creq_tail) { creq_tail->next = req; creq_tail = req; } else .....
I can't see where creq_tail is moved otherwise. If you push two requests one after the other, it looks like the previous req would "fall off" the queue.
I don't understand why StubMan_Invoke only appears able to marshal IRemUnknown - I've been reading chapter 5 of "Essential COM" as well as MSDN and it would seem it should be able to marshal any interface? Is that just time pressures?
I don't understand what COM_CreateIIf does. Creates an imported interface?
In CoMarshalInterThreadInterfaceInStream(), there is this code:
+#ifdef FAKE_INTERTHREAD + hr = IStream_Write(*ppStm, &pUnk, sizeof(pUnk), NULL); + if (SUCCEEDED(hr)) IUnknown_AddRef(pUnk); + TRACE("<= %p\n", pUnk); +#else + hr = CoMarshalInterface(*ppStm, riid, pUnk, MSHCTX_INPROC, 0, MSHLFLAGS_NORMAL); +#endif
Was that just for development, or are there still times when fake interthread marshalling is needed?
In the builtin Proxy/Stub section, for IClassFactory, there is this code:
+#if 0 +/* we need to create an IDL compiler for Wine that can generate + * most of these automatically */
Followed by a section of unused code. Was this written before you decided to use MIDL? Is this code in the auto-generated dcom marshalling code? (I didn't read all of the auto-genned stuf)
In your typelib marshaller, there is this code:
+ case VT_VOID: /* <= InstallShield hack */ + { + LPVOID pv = *(LPVOID*)args; + const IID *piid; + if (pType->vt == VT_DISPATCH) piid = &IID_IDispatch; else + if (pType->vt == VT_UNKNOWN) piid = &IID_IUnknown; else + { + pv = (LPVOID)args; + piid = is_iid; + } + TRACE(" marshaling INTERFACE %p %s\n", pv, debugstr_guid(piid)); + hr = CoMarshalInterface(pStm, piid, pv, CLSCTX_LOCAL_SERVER, NULL, MSHLFLAGS_NORMAL); + } + break;
but in Marcus', it is just this:
case VT_VOID: if (debugout) MESSAGE("<void>"); return S_OK;
What is supposed to happen when marshalling a void param like this?
+static HRESULT WINAPI PSOAStub_Invoke(LPRPCSTUBBUFFER iface, + PRPCOLEMESSAGE pMsg, + LPRPCCHANNELBUFFER pChannel)
This function looks a lot like WineHQs ITypeInfo::Invoke. Is there any relation?
+static LPVOID OA_BuildProxyVtbl(LPTYPEINFO pInfo, int *pfs, int rec)
Likewise, this function would seem to be similar but not the same as some code in WineHQ (they both give warnings if you don't have stdole32.tlb). Same? Different?
Thanks for any insight you can give to me on these questions. Finally, I am wondering whether anything would break if I simply merged in (to my local tree) the duplicated code. As I mentioned previously, time is a big problem here, and I can't use Microsofts own implementation for whatever reason. I don't care about cleanliness.
thanks -mike
man, 14.07.2003 kl. 17.55 skrev Mike Hearn:
Firstly, how much of the code in this patch is already duplicated in the WineHQ tree? I see a oleproxy.c file, from Marcus (C) 2002, which you removed from the build, but your patch is in parts (C) 2001. Does that mean that the patch removes code that actually it shouldn't when applied to WineHQ?
oleproxy.c and related files are both LGPL and obsolete (their functionality is supposed to handled by rpcrt4 and IDL tools), therefore I don't plan to touch it in my implementation. I use my own code instead, which happened to use a different file name. Whenever my patches are merged into WineHQ, the ole32/oleproxy.c and friends is likely to be either removed or replaced with chunks from my proxy.c (I'm not sure which). But as I explained in the mail, I assume the case will be different in oleaut32/, where the existing LGPL-ed stuff isn't all that obsolete (yet? its functionality should probably also really be in rpcrt4 but there's no reason to move it there at this time), so files there will probably just be adapted for the RPC transport, not replaced with my X11-licensed code like in my patch.
I don't understand this code:
+static void RpcChannel_push_request(RpcRequest *req) +{
- req->next = NULL;
- req->ret = RPC_S_CALL_IN_PROGRESS; /* ? */
- EnterCriticalSection(&creq_cs);
- if (creq_tail) creq_tail->next = req;
- else {
- creq_head = req;
- creq_tail = req;
- }
- LeaveCriticalSection(&creq_cs);
+}
If this is a double-ended queue, like it looks, then shouldn't the middle line read:
if (creq_tail) { creq_tail->next = req; creq_tail = req; } else .....
Hmm, maybe you're right. I copied it from dlls/rpcrt4/rpc_server.c where there's a RPCRT4_push_packet with the same bug, then. Still my fault as that was written by me too...
I don't understand why StubMan_Invoke only appears able to marshal IRemUnknown - I've been reading chapter 5 of "Essential COM" as well as MSDN and it would seem it should be able to marshal any interface? Is that just time pressures?
StubMan is what manages the object's lifetime (reference counts), it is the server-side thing that only handles IUnknown (or IRemUnknown in my implementation, which is technically wrong, as IRemUnknown should be handled by the apartment, not the stub manager). For other interfaces, the respective interface stub's Invoke is called instead; StubMan_Invoke don't have to know about them. You can see the logic of finding out which Invoke to invoke in COM_RpcDispatch. The StubMan's own Invoke is only used for IRemUnknown.
I don't understand what COM_CreateIIf does. Creates an imported interface?
Yes, kind of. Basically instantiate (and keep track of) an interface proxy, so that it's possible to use the requested interface from the apartment that imported the object. The interface proxy (created by COM_CreateIIf and returned to the app when it wants the object) will marshal calls to its methods and transmit them through rpcrt4 (wrapped by IRpcChannelBuffer), which will hand it over to COM_RpcDispatch, which will send the request to the exporting apartment and have its interface stub (created by COM_CreateXIf) unmarshal the data, call the function (in its own apartment), marshal the result (all done by calling its Invoke method), the result again goes through rpcrt4, and the interface proxy can then unmarshal the result and return to its caller. The book should have more detailed information about this process, but that's what this implements.
In CoMarshalInterThreadInterfaceInStream(), there is this code:
+#ifdef FAKE_INTERTHREAD
- hr = IStream_Write(*ppStm, &pUnk, sizeof(pUnk), NULL);
- if (SUCCEEDED(hr)) IUnknown_AddRef(pUnk);
- TRACE("<= %p\n", pUnk);
+#else
- hr = CoMarshalInterface(*ppStm, riid, pUnk, MSHCTX_INPROC, 0, MSHLFLAGS_NORMAL);
+#endif
Was that just for development, or are there still times when fake interthread marshalling is needed?
No, there aren't times anymore. That was used when we had interprocess marshalling but not interthread.
In the builtin Proxy/Stub section, for IClassFactory, there is this code:
+#if 0 +/* we need to create an IDL compiler for Wine that can generate
- most of these automatically */
Followed by a section of unused code. Was this written before you decided to use MIDL?
Not before I "decided", but before I had written all the rpcrt4 code needed for using MIDL-generated code.
Is this code in the auto-generated dcom marshalling code? (I didn't read all of the auto-genned stuf)
It should be in unknwn_p.c
In your typelib marshaller, there is this code:
- case VT_VOID: /* <= InstallShield hack */
- {
LPVOID pv = *(LPVOID*)args;
const IID *piid;
if (pType->vt == VT_DISPATCH) piid = &IID_IDispatch; else
if (pType->vt == VT_UNKNOWN) piid = &IID_IUnknown; else
{
pv = (LPVOID)args;
piid = is_iid;
}
TRACE(" marshaling INTERFACE %p %s\n", pv, debugstr_guid(piid));
hr = CoMarshalInterface(pStm, piid, pv, CLSCTX_LOCAL_SERVER, NULL, MSHLFLAGS_NORMAL);
- }
- break;
but in Marcus', it is just this:
case VT_VOID:
if (debugout) MESSAGE("<void>"); return S_OK;
He might be handling it at a higher level, then, as he do have some "thisisiid" stuff.
What is supposed to happen when marshalling a void param like this?
It's not legal for an app to do it. However, because MIDL-based marshallers weren't working before this patch, we had to force installshield to use the typelib marshaller (even though it didn't want to), and then hack our typelib marshallers to handle what installshield wanted to do. Treating VT_VOID as an interface (like VT_UNKNOWN) was enough to make installshield work without using its MIDL-based marshallers. The "force" is the "if (1 ||" at line 525 in typelib.c, the "1 || " can be removed after my patch is applied, and then the above VT_VOID hacks could be removed too, since then the MIDL-based marshallers would be used instead of the typelib marshaller to handle the interfaces that has VT_VOIDs in them.
+static HRESULT WINAPI PSOAStub_Invoke(LPRPCSTUBBUFFER iface,
PRPCOLEMESSAGE pMsg,
LPRPCCHANNELBUFFER pChannel)
This function looks a lot like WineHQs ITypeInfo::Invoke. Is there any relation?
ITypeInfo::Invoke converts a list of variants to suitable raw function arguments and then calls the method with it. My PSOAStub_Invoke has already unmarshalled the data into suitable raw function arguments so it doesn't need this conversion, can just call the method directly. But it would probably be *possible* to implement PSOAStub_Invoke in terms of ITypeInfo::Invoke, by unmarshalling into a variant list instead of raw function arguments.
Or did you mean to compare it to TMStubImpl_Invoke?
+static LPVOID OA_BuildProxyVtbl(LPTYPEINFO pInfo, int *pfs, int rec)
Likewise, this function would seem to be similar but not the same as some code in WineHQ (they both give warnings if you don't have stdole32.tlb). Same? Different?
You mean PSFacBuf_CreateProxy? Yes, basically accomplishes largely the same thing. As mentioned, Marcus's oleaut32 code doesn't really have to be removed and replaced, just adapted. I just don't use it, because of the LGPL-ness of patches to it and such.
Thanks for any insight you can give to me on these questions. Finally, I am wondering whether anything would break if I simply merged in (to my local tree) the duplicated code.
I don't know, I haven't tried to apply it to a current Wine tree. Might depend on how you handle the merging (for example, whether you'll just use Marcus's tmarshal code and change it to work with rpc, and if so, whether you do the changes needed to do that correctly.)
As I mentioned previously, time is a big problem here, and I can't use Microsofts own implementation for whatever reason. I don't care about cleanliness.
Well, good luck.
Another question (sorry ;) - is it possible to only merge the parts that touch ole32.dll, and continue to use native oleaut32 and rpcrt4?
ie, basically - how many crosscalls are there between wine code in ole32, oleaut32, rpcrt4 - do your patches that add inter-thread marshalling depend explicitly on your typelib marshaller?
thanks -mike
tir, 15.07.2003 kl. 12.38 skrev Mike Hearn:
Another question (sorry ;) - is it possible to only merge the parts that touch ole32.dll, and continue to use native oleaut32 and rpcrt4?
I'm not sure. I'd expect native rpcrt4 (at least the NT/2000 versions of it) to do some stuff that Wine doesn't support, like NT LPC ports (which is a kernel feature exported by ntdll, and as far as I know this is not implemented in wine). Perhaps the win95/98 version of rpcrt4 has a small chance of working.
ie, basically - how many crosscalls are there between wine code in ole32, oleaut32, rpcrt4 - do your patches that add inter-thread marshalling depend explicitly on your typelib marshaller?
oleaut32 and ole32 has in theory completely independent marshallers, you can use any combination as long as they use compatible transports, in this case that both use rpcrt4's dcom stuff. So you can use Marcus's oleaut32 code (as long as you adapt it for RPC), it doesn't matter for ole32. Though you probably can't use native oleaut32 with builtin rpcrt4, because like I mentioned earlier, the core of the typelib marshaller should have been in rpcrt4, and that's where native oleaut32 expects it to be. And as you may have noticed, native ole32 uses a lot of undocumented rpcrt4 features that I haven't figured out the exact behaviour of.
So I guess it looks a bit grim for running any of them native, but I suppose you could experiment.
OK, so I applied (as opposed to merged) the ole32.dll parts of the patch, but I can't figure out why it won't compile.
It seems that I'm missing a #define somewhere that is needed for the basic types to be defined, example errors are:
In file included from ../../include/rpcproxy.h:31, from dcom_p.c:20: ../../include/winnt.h:296: parse error before "BOOLEAN" cc1: warnings being treated as errors ../../include/winnt.h:296: warning: type defaults to `int' in declaration of `BOOLEAN' ../../include/winnt.h:296: warning: type defaults to `int' in declaration of `PBOOLEAN' ../../include/winnt.h:296: warning: data definition has no type or storage class ../../include/winnt.h:355: parse error before "LCID" ../../include/winnt.h:355: warning: type defaults to `int' in declaration of `LCID'
I've tried doing a, for instance, #define __WINE__ but no cigar.
The first line it chokes on, is:
typedef BYTE BOOLEAN, *PBOOLEAN;
I can't see where BYTE is declared actually, but it compiled before.
I vaguely recall a mention of some define to import the wine types that you weren't sure was needed any more, but I don't recall its name :(
Has anybody got any ideas?
On Tue, 2003-07-15 at 13:34, Ove Kaaven wrote:
tir, 15.07.2003 kl. 12.38 skrev Mike Hearn:
Another question (sorry ;) - is it possible to only merge the parts that touch ole32.dll, and continue to use native oleaut32 and rpcrt4?
I'm not sure. I'd expect native rpcrt4 (at least the NT/2000 versions of it) to do some stuff that Wine doesn't support, like NT LPC ports (which is a kernel feature exported by ntdll, and as far as I know this is not implemented in wine). Perhaps the win95/98 version of rpcrt4 has a small chance of working.
ie, basically - how many crosscalls are there between wine code in ole32, oleaut32, rpcrt4 - do your patches that add inter-thread marshalling depend explicitly on your typelib marshaller?
oleaut32 and ole32 has in theory completely independent marshallers, you can use any combination as long as they use compatible transports, in this case that both use rpcrt4's dcom stuff. So you can use Marcus's oleaut32 code (as long as you adapt it for RPC), it doesn't matter for ole32. Though you probably can't use native oleaut32 with builtin rpcrt4, because like I mentioned earlier, the core of the typelib marshaller should have been in rpcrt4, and that's where native oleaut32 expects it to be. And as you may have noticed, native ole32 uses a lot of undocumented rpcrt4 features that I haven't figured out the exact behaviour of.
So I guess it looks a bit grim for running any of them native, but I suppose you could experiment.
tir, 15.07.2003 kl. 17.49 skrev Mike Hearn:
I vaguely recall a mention of some define to import the wine types that you weren't sure was needed any more, but I don't recall its name :(
You may be referring to the #undef __WINE__ that is in my *_p.c files. I think Wine renamed it to __WINESRC__, you could try changing it to that. If that's not it I don't know, you'll have to investigate on your own.
On Tuesday 15 July 2003 07:34 am, Ove Kaaven wrote:
tir, 15.07.2003 kl. 12.38 skrev Mike Hearn:
Another question (sorry ;) - is it possible to only merge the parts that touch ole32.dll, and continue to use native oleaut32 and rpcrt4?
I'm not sure. I'd expect native rpcrt4 (at least the NT/2000 versions of it) to do some stuff that Wine doesn't support, like NT LPC ports (which is a kernel feature exported by ntdll, and as far as I know this is not implemented in wine). Perhaps the win95/98 version of rpcrt4 has a small chance of working.
Native W98SE rpcrt4 & ole* dll's work reasonably well, or used to. They are often very ornery until you drag in a crapload of native supporting dll's. Ove is precisely correct about what will happen with NT/2000/XP rpcrt4. They barf calling the LPC Ports API's. This is why I have placed those API's on my todo list (more like totrytodo list ;) ).
ie, basically - how many crosscalls are there between wine code in ole32, oleaut32, rpcrt4 - do your patches that add inter-thread marshalling depend explicitly on your typelib marshaller?
oleaut32 and ole32 has in theory completely independent marshallers, you can use any combination as long as they use compatible transports, in this case that both use rpcrt4's dcom stuff. So you can use Marcus's oleaut32 code (as long as you adapt it for RPC), it doesn't matter for ole32. Though you probably can't use native oleaut32 with builtin rpcrt4, because like I mentioned earlier, the core of the typelib marshaller should have been in rpcrt4, and that's where native oleaut32 expects it to be. And as you may have noticed, native ole32 uses a lot of undocumented rpcrt4 features that I haven't figured out the exact behaviour of.
Sounds right to me.
On Wednesday 09 July 2003 12:57 pm, Sylvain Petreolle wrote:
Oh my god... a 200k patch ??
Hey, Ove never promised a rose garden, in fact quite the opposite. Yet it was requested by Mike, warts and all:
MH wrote:
"As such, I don't care how messy the patch is, or how many other apps it breaks, I'd like to take a look at it."
As such, giving Ove a hard time for the ungainly patch seems a bit unfair, although I presume this is only a jest.
Kind of reminds me of several months ago when Ove pointed out his original rpcrt4 patches to me....
*evil laughter*
stay tuned for cab patches... looks like you guys have been hard at work while I've been galavanting about the country :)
IFAIK, this is how apartments are implemented and this comes from
Windows 3.1.
That's what I was thinking, but I found an article from 1994 claiming that ole would be shortly moving to the DCE RPC protocol instead of using window messages (and so they did).
I guess they didn't purge window messages entirely.
I think MS was under the impression (not sure if it's correct or not) that RPC is much slower than window messages. I'm pretty sure this is true, but it may not be if there are optimizations in RPC to handle non-cross process calls using some faster form of in-process communication. It may just be slower for initialization (CreateInstance) and finalization (Release()) of proxies and thus objects.
Kelly
tir, 08.07.2003 kl. 13.32 skrev Mike Hearn:
IFAIK, this is how apartments are implemented and this comes from Windows 3.1.
That's what I was thinking, but I found an article from 1994 claiming that ole would be shortly moving to the DCE RPC protocol instead of using window messages (and so they did).
I guess they didn't purge window messages entirely.
DCE RPC is in its heart an interprocess protocol, not an interthread protocol. This distinction does not necessarily matter, though, it can be used as both if done "right". RPC needs a transport layer, however, and which transport is used for communication depends on the context. Thread pools servicing network sockets is used for inter-machine (and perhaps inter-process) communication. For inter-process communication, NT LPC (something like that, don't remember anymore) is used. For inter-thread communication (including dispatching inter-machine requests to a particular thread), the most reliable system communication path with thread affinity is used: window messages.
Yes, Windows's implementation of DCE RPC implements window messages as a transport protocol. So they probably *did* move fully to DCE RPC, they just moved the old cruft in there too...