It makes no sense to have a left pointing arrow as the desktop icon.
[wine/testsucceed.git] / documentation / ole.sgml
blob12fe7d1683da8ba7b16dc5150a9ebf79471dfb21
1 <chapter id="ole">
2 <title>COM in Wine</title>
4 <sect1 id="com-writing">
5 <title>Writing COM Components for Wine</title>
7 <para>
8 This section describes how to create your own natively
9 compiled COM components.
10 </para>
12 <sect2>
13 <title>Macros to define a COM interface</title>
15 <para>
16 The goal of the following set of definitions is to provide a
17 way to use the same header file definitions to provide both
18 a C interface and a C++ object oriented interface to COM
19 interfaces. The type of interface is selected automatically
20 depending on the language but it is always possible to get
21 the C interface in C++ by defining CINTERFACE.
22 </para>
23 <para>
24 It is based on the following assumptions:
25 </para>
26 <itemizedlist>
27 <listitem>
28 <para>
29 all COM interfaces derive from IUnknown, this should not
30 be a problem.
31 </para>
32 </listitem>
33 <listitem>
34 <para>
35 the header file only defines the interface, the actual
36 fields are defined separately in the C file implementing
37 the interface.
38 </para>
39 </listitem>
40 </itemizedlist>
41 <para>
42 The natural approach to this problem would be to make sure
43 we get a C++ class and virtual methods in C++ and a
44 structure with a table of pointer to functions in C.
45 Unfortunately the layout of the virtual table is compiler
46 specific, the layout of g++ virtual tables is not the same
47 as that of an egcs virtual table which is not the same as
48 that generated by Visual C++. There are work arounds to make
49 the virtual tables compatible via padding but unfortunately
50 the one which is imposed to the Wine emulator by the Windows
51 binaries, i.e. the Visual C++ one, is the most compact of
52 all.
53 </para>
54 <para>
55 So the solution I finally adopted does not use virtual
56 tables. Instead I use in-line non virtual methods that
57 dereference the method pointer themselves and perform the
58 call.
59 </para>
60 <para>
61 Let's take Direct3D as an example:
62 </para>
63 <programlisting>#define ICOM_INTERFACE IDirect3D
64 #define IDirect3D_METHODS \
65 ICOM_METHOD1(HRESULT,Initialize, REFIID,) \
66 ICOM_METHOD2(HRESULT,EnumDevices, LPD3DENUMDEVICESCALLBACK,, LPVOID,) \
67 ICOM_METHOD2(HRESULT,CreateLight, LPDIRECT3DLIGHT*,, IUnknown*,) \
68 ICOM_METHOD2(HRESULT,CreateMaterial,LPDIRECT3DMATERIAL*,, IUnknown*,) \
69 ICOM_METHOD2(HRESULT,CreateViewport,LPDIRECT3DVIEWPORT*,, IUnknown*,) \
70 ICOM_METHOD2(HRESULT,FindDevice, LPD3DFINDDEVICESEARCH,, LPD3DFINDDEVICERESULT,)
71 #define IDirect3D_IMETHODS \
72 IUnknown_IMETHODS \
73 IDirect3D_METHODS
74 ICOM_DEFINE(IDirect3D,IUnknown)
75 #undef ICOM_INTERFACE
77 #ifdef ICOM_CINTERFACE
78 // *** IUnknown methods *** //
79 #define IDirect3D_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b)
80 #define IDirect3D_AddRef(p) ICOM_CALL (AddRef,p)
81 #define IDirect3D_Release(p) ICOM_CALL (Release,p)
82 // *** IDirect3D methods *** //
83 #define IDirect3D_Initialize(p,a) ICOM_CALL1(Initialize,p,a)
84 #define IDirect3D_EnumDevices(p,a,b) ICOM_CALL2(EnumDevice,p,a,b)
85 #define IDirect3D_CreateLight(p,a,b) ICOM_CALL2(CreateLight,p,a,b)
86 #define IDirect3D_CreateMaterial(p,a,b) ICOM_CALL2(CreateMaterial,p,a,b)
87 #define IDirect3D_CreateViewport(p,a,b) ICOM_CALL2(CreateViewport,p,a,b)
88 #define IDirect3D_FindDevice(p,a,b) ICOM_CALL2(FindDevice,p,a,b)
89 #endif</programlisting>
90 <para>
91 Comments:
92 </para>
93 <para>
94 The ICOM_INTERFACE macro is used in the ICOM_METHOD macros
95 to define the type of the 'this' pointer. Defining this
96 macro here saves us the trouble of having to repeat the
97 interface name everywhere. Note however that because of the
98 way macros work, a macro like ICOM_METHOD1 cannot use
99 'ICOM_INTERFACE##_VTABLE' because this would give
100 'ICOM_INTERFACE_VTABLE' and not 'IDirect3D_VTABLE'.
101 </para>
102 <para>
103 ICOM_METHODS defines the methods specific to this
104 interface. It is then aggregated with the inherited methods
105 to form ICOM_IMETHODS.
106 </para>
107 <para>
108 ICOM_IMETHODS defines the list of methods that are
109 inheritable from this interface. It must be written manually
110 (rather than using a macro to generate the equivalent code)
111 to avoid macro recursion (which compilers don't like).
112 </para>
113 <para>
114 The ICOM_DEFINE finally declares all the structures
115 necessary for the interface. We have to explicitly use the
116 interface name for macro expansion reasons again. Inherited
117 methods are inherited in C by using the IDirect3D_METHODS
118 macro and the parent's Xxx_IMETHODS macro. In C++ we need
119 only use the IDirect3D_METHODS since method inheritance is
120 taken care of by the language.
121 </para>
122 <para>
123 In C++ the ICOM_METHOD macros generate a function prototype
124 and a call to a function pointer method. This means using
125 once 't1 p1, t2 p2, ...' and once 'p1, p2' without the
126 types. The only way I found to handle this is to have one
127 ICOM_METHOD macro per number of parameters and to have it
128 take only the type information (with const if necessary) as
129 parameters. The 'undef ICOM_INTERFACE' is here to remind
130 you that using ICOM_INTERFACE in the following macros will
131 not work. This time it's because the ICOM_CALL macro
132 expansion is done only once the 'IDirect3D_Xxx' macro is
133 expanded. And by that time ICOM_INTERFACE will be long gone
134 anyway.
135 </para>
136 <para>
137 You may have noticed the double commas after each parameter
138 type. This allows you to put the name of that parameter
139 which I think is good for documentation. It is not required
140 and since I did not know what to put there for this example
141 (I could only find doc about IDirect3D2), I left them blank.
142 </para>
143 <para>
144 Finally the set of 'IDirect3D_Xxx' macros is a standard set
145 of macros defined to ease access to the interface methods in
146 C. Unfortunately I don't see any way to avoid having to
147 duplicate the inherited method definitions there. This time
148 I could have used a trick to use only one macro whatever the
149 number of parameters but I preferred to have it work the same
150 way as above.
151 </para>
152 <para>
153 You probably have noticed that we don't define the fields we
154 need to actually implement this interface: reference count,
155 pointer to other resources and miscellaneous fields. That's
156 because these interfaces are just that: interfaces. They may
157 be implemented more than once, in different contexts and
158 sometimes not even in Wine. Thus it would not make sense to
159 impose that the interface contains some specific fields.
160 </para>
161 </sect2>
163 <sect2>
164 <title>Bindings in C</title>
166 <para>
167 In C this gives:
168 </para>
169 <programlisting>typedef struct IDirect3DVtbl IDirect3DVtbl;
170 struct IDirect3D {
171 IDirect3DVtbl* lpVtbl;
173 struct IDirect3DVtbl {
174 HRESULT (*fnQueryInterface)(IDirect3D* me, REFIID riid, LPVOID* ppvObj);
175 ULONG (*fnAddRef)(IDirect3D* me);
176 ULONG (*fnRelease)(IDirect3D* me);
177 HRESULT (*fnInitialize)(IDirect3D* me, REFIID a);
178 HRESULT (*fnEnumDevices)(IDirect3D* me, LPD3DENUMDEVICESCALLBACK a, LPVOID b);
179 HRESULT (*fnCreateLight)(IDirect3D* me, LPDIRECT3DLIGHT* a, IUnknown* b);
180 HRESULT (*fnCreateMaterial)(IDirect3D* me, LPDIRECT3DMATERIAL* a, IUnknown* b);
181 HRESULT (*fnCreateViewport)(IDirect3D* me, LPDIRECT3DVIEWPORT* a, IUnknown* b);
182 HRESULT (*fnFindDevice)(IDirect3D* me, LPD3DFINDDEVICESEARCH a, LPD3DFINDDEVICERESULT b);
185 #ifdef ICOM_CINTERFACE
186 // *** IUnknown methods *** //
187 #define IDirect3D_QueryInterface(p,a,b) (p)->lpVtbl->fnQueryInterface(p,a,b)
188 #define IDirect3D_AddRef(p) (p)->lpVtbl->fnAddRef(p)
189 #define IDirect3D_Release(p) (p)->lpVtbl->fnRelease(p)
190 // *** IDirect3D methods *** //
191 #define IDirect3D_Initialize(p,a) (p)->lpVtbl->fnInitialize(p,a)
192 #define IDirect3D_EnumDevices(p,a,b) (p)->lpVtbl->fnEnumDevice(p,a,b)
193 #define IDirect3D_CreateLight(p,a,b) (p)->lpVtbl->fnCreateLight(p,a,b)
194 #define IDirect3D_CreateMaterial(p,a,b) (p)->lpVtbl->fnCreateMaterial(p,a,b)
195 #define IDirect3D_CreateViewport(p,a,b) (p)->lpVtbl->fnCreateViewport(p,a,b)
196 #define IDirect3D_FindDevice(p,a,b) (p)->lpVtbl->fnFindDevice(p,a,b)
197 #endif</programlisting>
198 <para>
199 Comments:
200 </para>
201 <para>
202 IDirect3D only contains a pointer to the IDirect3D
203 virtual/jump table. This is the only thing the user needs to
204 know to use the interface. Of course the structure we will
205 define to implement this interface will have more fields but
206 the first one will match this pointer.
207 </para>
208 <para>
209 The code generated by ICOM_DEFINE defines both the structure
210 representing the interface and the structure for the jump
211 table. ICOM_DEFINE uses the parent's Xxx_IMETHODS macro to
212 automatically repeat the prototypes of all the inherited
213 methods and then uses IDirect3D_METHODS to define the
214 IDirect3D methods.
215 </para>
216 <para>
217 Each method is declared as a pointer to function field in
218 the jump table. The implementation will fill this jump table
219 with appropriate values, probably using a static variable,
220 and initialize the lpVtbl field to point to this variable.
221 </para>
222 <para>
223 The IDirect3D_Xxx macros then just dereference the lpVtbl
224 pointer and use the function pointer corresponding to the
225 macro name. This emulates the behavior of a virtual table
226 and should be just as fast.
227 </para>
228 <para>
229 This C code should be quite compatible with the Windows
230 headers both for code that uses COM interfaces and for code
231 implementing a COM interface.
232 </para>
233 </sect2>
235 <sect2>
236 <title>Bindings in C++</title>
237 <para>
238 And in C++ (with gcc's g++):
239 </para>
240 <programlisting>typedef struct IDirect3D: public IUnknown {
241 private: HRESULT (*fnInitialize)(IDirect3D* me, REFIID a);
242 public: inline HRESULT Initialize(REFIID a) { return ((IDirect3D*)t.lpVtbl)->fnInitialize(this,a); };
243 private: HRESULT (*fnEnumDevices)(IDirect3D* me, LPD3DENUMDEVICESCALLBACK a, LPVOID b);
244 public: inline HRESULT EnumDevices(LPD3DENUMDEVICESCALLBACK a, LPVOID b)
245 { return ((IDirect3D*)t.lpVtbl)->fnEnumDevices(this,a,b); };
246 private: HRESULT (*fnCreateLight)(IDirect3D* me, LPDIRECT3DLIGHT* a, IUnknown* b);
247 public: inline HRESULT CreateLight(LPDIRECT3DLIGHT* a, IUnknown* b)
248 { return ((IDirect3D*)t.lpVtbl)->fnCreateLight(this,a,b); };
249 private: HRESULT (*fnCreateMaterial)(IDirect3D* me, LPDIRECT3DMATERIAL* a, IUnknown* b);
250 public: inline HRESULT CreateMaterial(LPDIRECT3DMATERIAL* a, IUnknown* b)
251 { return ((IDirect3D*)t.lpVtbl)->fnCreateMaterial(this,a,b); };
252 private: HRESULT (*fnCreateViewport)(IDirect3D* me, LPDIRECT3DVIEWPORT* a, IUnknown* b);
253 public: inline HRESULT CreateViewport(LPDIRECT3DVIEWPORT* a, IUnknown* b)
254 { return ((IDirect3D*)t.lpVtbl)->fnCreateViewport(this,a,b); };
255 private: HRESULT (*fnFindDevice)(IDirect3D* me, LPD3DFINDDEVICESEARCH a, LPD3DFINDDEVICERESULT b);
256 public: inline HRESULT FindDevice(LPD3DFINDDEVICESEARCH a, LPD3DFINDDEVICERESULT b)
257 { return ((IDirect3D*)t.lpVtbl)->fnFindDevice(this,a,b); };
258 };</programlisting>
259 <para>
260 Comments:
261 </para>
262 <para>
263 In C++ IDirect3D does double duty as both the virtual/jump
264 table and as the interface definition. The reason for this
265 is to avoid having to duplicate the method definitions: once
266 to have the function pointers in the jump table and once to
267 have the methods in the interface class. Here one macro can
268 generate both. This means though that the first pointer,
269 t.lpVtbl defined in IUnknown, must be interpreted as the
270 jump table pointer if we interpret the structure as the
271 interface class, and as the function pointer to the
272 QueryInterface method, t.fnQueryInterface, if we interpret
273 the structure as the jump table. Fortunately this gymnastic
274 is entirely taken care of in the header of IUnknown.
275 </para>
276 <para>
277 Of course in C++ we use inheritance so that we don't have to
278 duplicate the method definitions.
279 </para>
280 <para>
281 Since IDirect3D does double duty, each ICOM_METHOD macro
282 defines both a function pointer and a non-virtual inline
283 method which dereferences it and calls it. This way this
284 method behaves just like a virtual method but does not
285 create a true C++ virtual table which would break the
286 structure layout. If you look at the implementation of these
287 methods you'll notice that they would not work for void
288 functions. We have to return something and fortunately this
289 seems to be what all the COM methods do (otherwise we would
290 need another set of macros).
291 </para>
292 <para>
293 Note how the ICOM_METHOD generates both function prototypes
294 mixing types and formal parameter names and the method
295 invocation using only the formal parameter name. This is the
296 reason why we need different macros to handle different
297 numbers of parameters.
298 </para>
299 <para>
300 Finally there is no IDirect3D_Xxx macro. These are not
301 needed in C++ unless the CINTERFACE macro is defined in
302 which case we would not be here.
303 </para>
304 <para>
305 This C++ code works well for code that just uses COM
306 interfaces. But it will not work with C++ code implement a
307 COM interface. That's because such code assumes the
308 interface methods are declared as virtual C++ methods which
309 is not the case here.
310 </para>
311 </sect2>
313 <sect2>
314 <title>Implementing a COM interface.</title>
316 <para>
317 This continues the above example. This example assumes that
318 the implementation is in C.
319 </para>
320 <programlisting>typedef struct _IDirect3D {
321 void* lpVtbl;
322 // ...
323 } _IDirect3D;
325 static ICOM_VTABLE(IDirect3D) d3dvt;
327 // implement the IDirect3D methods here
329 int IDirect3D_fnQueryInterface(IDirect3D* me)
331 ICOM_THIS(IDirect3D,me);
332 // ...
335 // ...
337 static ICOM_VTABLE(IDirect3D) d3dvt = {
338 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
339 IDirect3D_fnQueryInterface,
340 IDirect3D_fnAdd,
341 IDirect3D_fnAdd2,
342 IDirect3D_fnInitialize,
343 IDirect3D_fnSetWidth
344 };</programlisting>
345 <para>
346 Comments:
347 </para>
348 <para>
349 We first define what the interface really contains. This is
350 the _IDirect3D structure. The first field must of course be
351 the virtual table pointer. Everything else is free.
352 </para>
353 <para>
354 Then we predeclare our static virtual table variable, we
355 will need its address in some methods to initialize the
356 virtual table pointer of the returned interface objects.
357 </para>
358 <para>
359 Then we implement the interface methods. To match what has
360 been declared in the header file they must take a pointer to
361 an IDirect3D structure and we must cast it to an _IDirect3D
362 so that we can manipulate the fields. This is performed by
363 the ICOM_THIS macro.
364 </para>
365 <para>
366 Finally we initialize the virtual table.
367 </para>
368 </sect2>
369 </sect1>
371 <sect1 id="dcom-1">
372 <title>A brief introduction to DCOM in Wine</title>
374 <para>
375 This section explains the basic principles behind DCOM remoting as used by InstallShield and others.
376 </para>
378 <sect2>
379 <title>Basics</title>
381 <para>
382 The basic idea behind DCOM is to take a COM object and make it location
383 transparent. That means you can use it from other threads, processes and
384 machines without having to worry about the fact that you can't just
385 dereference the interface vtable pointer to call methods on it.
386 </para>
388 <para>
389 You might be wondering about putting threads next to processes and
390 machines in that last paragraph. You can access thread safe objects from
391 multiple threads without DCOM normally, right? Why would you need RPC
392 magic to do that?
393 </para>
395 <para>
396 The answer is of course that COM doesn't assume that objects actually
397 are thread-safe. Most real-world objects aren't, in fact, for various
398 reasons. What these reasons are isn't too important here, though; it's
399 just important to realize that the problem of thread-unsafe objects is
400 what COM tries hard to solve with its apartment model. There are also
401 ways to tell COM that your object is truly thread-safe (namely the
402 free-threaded marshaller). In general, no object is truly thread-safe if
403 it could potentially use another not so thread-safe object, though, so
404 the free-threaded marshaller is less used than you'd think.
405 </para>
407 <para>
408 For now, suffice it to say that COM lets you "marshal" interfaces into
409 other "apartments". An apartment (you may see it referred to as a
410 context in modern versions of COM) can be thought of as a location, and
411 contains objects.
412 </para>
414 <para>
415 Every thread in a program that uses COM exists in an apartment. If a
416 thread wishes to use an object from another apartment, marshalling and
417 the whole DCOM infrastructure gets involved to make that happen behind
418 the scenes.
419 </para>
421 <para>
422 So. Each COM object resides in an apartment, and each apartment
423 resides in a process, and each process resides in a machine, and each
424 machine resides in a network. Allowing those objects to be used
425 from <emphasis>any</emphasis> of these different places is what DCOM
426 is all about.
427 </para>
429 <para>
430 The process of marshalling refers to taking a function call in an
431 apartment and actually performing it in another apartment. Let's say you
432 have two machines, A and B, and on machine B there is an object sitting
433 in a DLL on the hard disk. You want to create an instance of that object
434 (activate it) and use it as if you had compiled it into your own
435 program. This is hard, because the remote object is expecting to be
436 called by code in its own address space - it may do things like accept
437 pointers to linked lists and even return other objects.
438 </para>
440 <para>
441 Very basic marshalling is easy enough to understand. You take a method
442 on a remote interface (that is a COM interface that is
443 implemented on the remote computer), copy each of its
444 parameters into a buffer, and
445 send it to the remote computer. On the other end, the remote server
446 reads each parameter from the buffer, calls the method, writes the
447 result into another buffer and sends it back.
448 </para>
450 <para>
451 The tricky part is exactly how to encode those parameters in the buffer,
452 and how to convert standard stdcall/cdecl method calls to network
453 packets and back again. This is the job of the RPCRT4.DLL file - or the
454 Remote Procedure Call Runtime.
455 </para>
457 <para>
458 The backbone of DCOM is this RPC runtime, which is an implementation
459 of <ulink
460 url="http://www.opengroup.org/onlinepubs/009629399/toc.htm">DCE
461 RPC</ulink>. DCE RPC is not naturally object oriented, so this
462 protocol is extended with some new constructs and by assigning new
463 meanings to some of the packet fields, to produce ORPC or Object
464 RPC. You might see it called MS-RPC as well.
465 </para>
467 <para>
468 RPC packets contain a buffer containing marshalled data in NDR format.
469 NDR is short for "Network Data Representation" and is similar
470 to the XDR
471 format used in SunRPC (the closest native equivalent on Linux to DCE
472 RPC). NDR/XDR are all based on the idea of graph serialization and were
473 worked out during the 80s, meaning they are very powerful and can do
474 things like marshal doubly linked lists and other rather tricky
475 structures.
476 </para>
478 <para>
479 In Wine, our DCOM implementation is <emphasis>not</emphasis>
480 currently based on the
481 RPC runtime, as while few programs use DCOM even fewer use
482 RPC directly so it was developed some time after
483 OLE32/OLEAUT32 were. Eventually this will have to be fixed,
484 otherwise our DCOM will never be compatible with
485 Microsoft's. Bear this in mind as you read through the code
486 however.
487 </para>
488 </sect2>
490 <sect2>
491 <title>Proxies and Stubs</title>
493 <para>
494 Manually marshalling and unmarshalling each method call using the NDR
495 APIs (NdrConformantArrayMarshall etc) is very tedious work, so the
496 Platform SDK ships with a tool called "midl" which is an IDL compiler.
497 IDL or the "Interface Definition Language" is a tool designed
498 specifically for describing interfaces in a reasonably language neutral
499 fashion, though in reality it bears a close resemblence to C++.
500 </para>
502 <para>
503 By describing the functions you want to expose via RPC in IDL therefore,
504 it becomes possible to pass this file to MIDL which spits out a huge
505 amount of C source code. That code defines functions which have the same
506 prototype as the functions described in your IDL but which internally
507 take each argument, marshal it using Ndr, send the packet, and unmarshal
508 the return.
509 </para>
511 <para>
512 Because this code proxies the code from the client to the server, the
513 functions are called proxies. Easy, right?
514 </para>
516 <para>
517 Of course, in the RPC server process at the other end, you need some way
518 to unmarshal the RPCs, so you have functions also generated by MIDL
519 which are the inverse of the proxies; they accept an NDR buffer, extract
520 the parameters, call the real function and then marshal the result back.
521 They are called stubs, and stand in for the real calling code in the
522 client process.
523 </para>
525 <para>
526 The sort of marshalling/unmarshalling code that MIDL spits out can be
527 seen in dlls/oleaut32/oaidl_p.c - it's not exactly what it would look
528 like as that file contains DCOM proxies/stubs which are different, but
529 you get the idea. Proxy functions take the arguments and feed them to
530 the NDR marshallers (or picklers), invoke an NdrProxySendReceive and
531 then convert the out parameters and return code. There's a ton of goop
532 in there for dealing with buffer allocation, exceptions and so on - it's
533 really ugly code. But, this is the basic concept behind DCE RPC.
534 </para>
535 </sect2>
537 <sect2>
538 <title>Interface Marshalling</title>
540 <para>
541 Standard NDR only knows about C style function calls - they
542 can accept and even return structures, but it has no concept
543 of COM interfaces. Confusingly DCE RPC <emphasis>does</emphasis> have a
544 concept of RPC interfaces which are just convenient ways to
545 bundle function calls together into namespaces, but let's
546 ignore that for now as it just muddies the water. The
547 primary extension made by Microsoft to NDR then was the
548 ability to take a COM interface pointer and marshal that
549 into the NDR stream.
550 </para>
552 <para>
553 The basic theory of proxies and stubs and IDL is still here, but it's
554 been modified slightly. Whereas before you could define a bunch of
555 functions in IDL, now a new "object" keyword has appeared. This tells
556 MIDL that you're describing a COM interface, and as a result the
557 proxies/stubs it generates are also COM objects.
558 </para>
560 <para>
561 That's a very important distinction. When you make a call to a remote
562 COM object you do it via a proxy object that COM has constructed on the
563 fly. Likewise, a stub object on the remote end unpacks the RPC packet
564 and makes the call.
565 </para>
567 <para>
568 Because this is object-oriented RPC, there are a few complications: for
569 instance, a call that goes via the same proxies/stubs may end up at a
570 different object instance, so the RPC runtime keeps track of "this" and
571 "that" in the RPC packets.
572 </para>
574 <para>
575 This leads naturally onto the question of how we got those proxy/stub
576 objects in the first place, and where they came from. You can use the
577 CoCreateInstanceEx API to activate COM objects on a remote machine, this
578 works like CoCreateInstance API. Behind the scenes, a lot of stuff is
579 involved to do this (like IRemoteActivation, IOXIDResolver and so on)
580 but let's gloss over that for now.
581 </para>
583 <para>
584 When DCOM creates an object on a remote machine, the DCOM runtime on
585 that machine activates the object in the usual way (by looking it up in
586 the registry etc) and then marshals the requested interface back to the
587 client. Marshalling an interface takes a pointer, and produces a buffer
588 containing all the information DCOM needs to construct a proxy object in
589 the client, a stub object in the server and link the two together.
590 </para>
592 <para>
593 The structure of a marshalled interface pointer is somewhat complex.
594 Let's ignore that too. The important thing is how COM proxies/stubs are
595 loaded.
596 </para>
597 </sect2>
599 <sect2>
600 <title>COM Proxy/Stub System</title>
602 <para>
603 COM proxies are objects that implement both the interfaces needing to be
604 proxied and also IRpcProxyBuffer. Likewise, COM stubs implement
605 IRpcStubBuffer and understand how to invoke the methods of the requested
606 interface.
607 </para>
609 <para>
610 You may be wondering what the word "buffer" is doing in those interface
611 names. I'm not sure either, except that a running theme in DCOM is that
612 interfaces which have nothing to do with buffers have the word Buffer
613 appended to them, seemingly at random. Ignore it and <emphasis>don't let it
614 confuse you</emphasis> :) This stuff is convoluted enough ...
615 </para>
617 <para>
618 The IRpc[Proxy/Stub]Buffer interfaces are used to control the proxy/stub
619 objects and are one of the many semi-public interfaces used in DCOM.
620 </para>
622 <para>
623 DCOM is theoretically an internet RFC
624 <ulink url="http://www.grimes.demon.co.uk/DCOM/DCOMSpec.htm">[2]</ulink> and is
625 specced out, but in reality the only implementation of it apart from
626 ours is Microsoft's, and as a result there are lots of interfaces
627 which <emphasis>can</emphasis> be used if you want to customize or
628 control DCOM but in practice are badly documented or not documented at
629 all, or exist mostly as interfaces between MIDL generated code and COM
630 itself. Don't pay too much attention to the MSDN definitions of these
631 interfaces and APIs.
632 </para>
634 <para>
635 COM proxies and stubs are like any other normal COM object - they are
636 registered in the registry, they can be loaded with CoCreateInstance and
637 so on. They have to be in process (in DLLs) however. They aren't
638 activated directly by COM however, instead the process goes something
639 like this:
641 <itemizedlist>
642 <listitem> <para> COM receives a marshalled interface packet, and retrieves the IID of
643 the marshalled interface from it </para> </listitem>
646 <listitem> <para> COM looks in
647 HKEY_CLASSES_ROOT/Interface/{whatever-iid}/ProxyStubClsId32
648 to retrieve the CLSID of another COM object, which
649 implements IPSFactoryBuffer. </para> </listitem>
651 <listitem> <para> IPSFactoryBuffer has only two methods, CreateProxy and CreateStub. COM
652 calls whichever is appropriate: CreateStub for the server, CreateProxy
653 for the client. MIDL will normally provide an implementation of this
654 object for you in the code it generates. </para></listitem>
655 </itemizedlist>
657 </para>
659 <para>
660 Once CreateProxy has been called, the resultant object is QueryInterfaced to
661 IRpcProxyBuffer, which only has 1 method, IRpcProxyBuffer::Connect.
662 This method only takes one parameter, the IRpcChannelBuffer object which
663 encapsulates the "RPC Channel" between the client and server.
664 </para>
666 <para>
667 On the server side, a similar process is performed - the PSFactoryBuffer
668 is created, CreateStub is called, result is QId to IRpcStubBuffer, and
669 IRpcStubBuffer::Connect is used to link it to the RPC channel.
670 </para>
672 </sect2>
674 <sect2>
675 <title>RPC Channels</title>
677 <para>
678 Remember the RPC runtime? Well, that's not just responsible for
679 marshalling stuff, it also controls the connection and protocols between
680 the client and server. We can ignore the details of this for now,
681 suffice it to say that an RPC Channel is a COM object that implements
682 IRpcChannelBuffer, and it's basically an abstraction of different RPC
683 methods. For instance, in the case of inter-thread marshalling (not
684 covered here) the RPC connection code isn't used, only the NDR
685 marshallers are, so IRpcChannelBuffer in that case isn't actually
686 implemented by RPCRT4 but rather just by the COM/OLE DLLS.
687 </para>
689 <para>
690 On this topic, Ove Kaaven says: It depends on the Windows version, I
691 think. Windows 95 and Windows NT 4 certainly had very different models
692 when I looked. I'm pretty sure the Windows 98 version of RPCRT4 was
693 able to dispatch messages directly to individual apartments. I'd be
694 surprised if some similar functionality was not added to Windows
695 2000. After all, if an object on machine A wanted to use an object on
696 machine B in an apartment C, wouldn't it be most efficient if the RPC
697 system knew about apartments and could dispatch the message directly
698 to it? And if RPC does know how to efficiently dispatch to apartments,
699 why should COM duplicate this functionality? There were, however, no
700 unified way to tell RPC about them across Windows versions, so in that
701 old patch of mine, I let the COM/OLE dlls do the apartment dispatch,
702 but even then, the RPC runtime was always involved. After all, it
703 could be quite tricky to tell whether the call is merely interthread,
704 without involving the RPC runtime...
705 </para>
707 <para>
708 RPC channels are constructed on the fly by DCOM as part of the
709 marshalling process. So, when you make a call on a COM proxy, it goes
710 like this:
711 </para>
713 <para>
714 Your code -&gt; COM proxy object -&gt; RPC Channel -&gt; COM stub object -&gt; Their code
715 </para>
717 </sect2>
719 <sect2>
720 <title>How this actually works in Wine</title>
722 <para>
723 Right now, Wine does not use the NDR marshallers or RPC to implement its
724 DCOM. When you marshal an interface in Wine, in the server process a
725 _StubMgrThread thread is started. I haven't gone into the stub manager
726 here. The important thing is that eventually a _StubReaderThread is
727 started which accepts marshalled DCOM RPCs, and then passes them to
728 IRpcStubBuffer::Invoke on the correct stub object which in turn
729 demarshals the packet and performs the call. The threads started by our
730 implementation of DCOM are never terminated, they just hang around until
731 the process dies.
732 </para>
734 <para>
735 Remember that I said our DCOM doesn't use RPC? Well, you might be
736 thinking "but we use IRpcStubBuffer like we're supposed to ... isn't
737 that provided by MIDL which generates code that uses the NDR APIs?". If
738 so pat yourself on the back, you're still with me. Go get a cup of
739 coffee.
740 </para>
742 </sect2>
744 <sect2>
745 <title>Typelib Marshaller</title>
747 <para>
748 In fact, the reason for the PSFactoryBuffer layer of indirection is
749 because not all interfaces are marshalled using MIDL generated code.
750 Why not? Well, to understand <emphasis>that</emphasis>
751 you have to see that one of the
752 driving forces behind OLE and by extension DCOM was the development of
753 Visual Basic. Microsoft wanted VB developers to be first class citizens
754 in the COM world, but things like writing IDL and compiling them with a
755 C compiler into DLLs wasn't easy enough.
756 </para>
758 <para>
759 So, type libraries were invented. Actually they were invented as part of
760 a parallel line of COM development known as "OLE Automation", but let's
761 not get into that here. Type libraries are basically binary IDL files,
762 except that despite there being two type library formats neither of them
763 can fully express everything expressable in IDL. Anyway, with a type
764 library (which can be embedded as a resource into a DLL) you have
765 another option beyond compiling MIDL output - you can set the
766 ProxyStubClsId32 registry entry for your interfaces to the CLSID of the
767 "type library marshaller" or "universal marshaller". Both terms are
768 used, but in the Wine source it's called the typelib marshaller.
769 </para>
771 <para>
772 The type library marshaller constructs proxy and stub objects on the
773 fly. It does so by having generic marshalling glue which reads the
774 information from the type libraries, and takes the parameters directly
775 off the stack. The CreateProxy method actually builds a vtable out of
776 blocks of assembly stitched together which pass control to _xCall, which
777 then does the marshalling. You can see all this magic in
778 dlls/oleaut32/tmarshal.c
779 </para>
781 <para>
782 In the case of InstallShield, it actually comes with typelibs for all
783 the interfaces it needs to marshal (fixme: is this right?), but they
784 actually use a mix of MIDL and typelib marshalling. In order to cover up
785 for the fact that we don't really use RPC they're all forced to go via
786 the typelib marshaller - that's what the 1 || hack is for and what the
787 "Registering non-automation type library!" warning is about (I think).
788 </para>
789 </sect2>
791 <sect2>
792 <title>Apartments</title>
794 <para>
795 Before a thread can use COM it must enter an apartment. Apartments are
796 an abstraction of a COM objects thread safety level. There are many types
797 of apartment but the only two we care about right now are single threaded
798 apartments (STAs) and the multi-threaded apartment (MTA).
799 </para>
801 <para>
802 Any given process may contain at most one MTA and potentially many STAs.
803 This is because all objects in MTAs never care where they are invoked from
804 and hence can all be treated the same. Since objects in STAs do care, they
805 cannot be treated the same.
806 </para>
808 <para>
809 You enter an apartment by calling <function>CoInitializeEx()</function> and
810 passing the desired thread model in as a parameter. The default if you use
811 the deprecated <function>CoInitialize()</function> is a STA, and this is the
812 most common type of apartment used in COM.
813 </para>
815 <para>
816 An object in the multi-threaded apartment may be accessed concurrently by
817 multiple threads: eg, it's supposed to be entirely thread safe. It must also
818 not care about thread-affinity, the object should react the same way no matter
819 which thread is calling it.
820 </para>
822 <para>
823 An object inside a STA does not have to be thread safe, and all calls upon it
824 should come from the same thread - the thread that entered the apartment in
825 the first place.
826 </para>
828 <para>
829 The apartment system was originally designed to deal with the disparity between
830 the Windows NT/C++ world in which threading was given a strong emphasis, and the
831 Visual Basic world in which threading was barely supported and even if it had
832 been fully supported most developers would not have used it. Visual Basic code
833 is not truly multi-threaded, instead if you start a new thread you get an entirely
834 new VM, with separate sets of global variables. Changes made in one thread do
835 <emphasis>not</emphasis> reflect in another, which pretty much violates the
836 expected semantics of multi-threading entirely but this is Visual Basic, so what
837 did you expect? If you access a VB object concurrently from multiple threads,
838 behind the scenes each VM runs in a STA and the calls are marshaled between the
839 threads using DCOM.
840 </para>
842 <para>
843 In the Windows 2000 release of COM, several new types of apartment were added, the
844 most important of which are RTAs (the rental threaded apartment) in which concurrent
845 access are serialised by COM using an apartment-wide lock but thread affinity is
846 not guaranteed.
847 </para>
848 </sect2>
850 <sect2>
851 <title>Structure of a marshaled interface pointer</title>
853 <para>
854 When an interface is marshaled using <function>CoMarshalInterface()</function>,
855 the result is a serialized OBJREF structure. An OBJREF actually contains a union,
856 but we'll be assuming the variant that embeds a STDOBJREF here which is what's
857 used by the system provided standard marshaling. A STDOBJREF (standard object
858 reference) consists of the magic signature 'MEOW', then some flags, then the IID
859 of the marshaled interface. Quite what MEOW stands for is a mystery, but it's
860 definitely not "Microsoft Extended Object Wire". Next comes the STDOBJREF flags,
861 identified by their SORF_ prefix. Most of these are reserved, and their purpose
862 (if any) is unknown, but a few are defined.
863 </para>
865 <para>
866 After the SORF flags comes a count of the references represented by this marshaled
867 interface. Typically this will be 5 in the case of a normal marshal, but may be 0
868 for table-strong and table-weak marshals (the difference between these is explained below).
869 The reasoning is this: In the general case, we want to know exactly when an object
870 is unmarshaled and released, so we can accurately control the lifetime of the stub
871 object. This is what happens when cPublicRefs is zero. However, in many cases, we
872 only want to unmarshal an object once. Therefore, if we strengthen the rules to say
873 when marshaling that we will only unmarshal once, then we no longer have to know when
874 it is unmarshaled. Therefore, we can give out an arbitrary number of references when
875 marshaling and basically say "don't call me, except when you die."
876 </para>
878 <para>
879 The most interesting part of a STDOBJREF is the OXID, OID, IPID triple. This triple
880 identifies any given marshaled interface pointer in the network. OXIDs are apartment
881 identifiers, and are supposed to be unique network-wide. How this is guaranteed is
882 currently unknown: the original algorithm Windows used was something like the current
883 UNIX time and a local counter.
884 </para>
886 <para>
887 OXIDs are generated and registered with the OXID resolver by performing local RPCs
888 to the RPC subsystem (rpcss.exe). In a fully security-patched Windows system they
889 appear to be randomly generated. This registration is done using the
890 <function>ILocalOxidResolver</function> interface, however the exact structure of
891 this interface is currently unknown.
892 </para>
894 <para>
895 OIDs are object identifiers, and identify a stub manager. The stub manager manages
896 interface stubs. For each exported COM object there are multiple interfaces and
897 therefore multiple interface stubs (<function>IRpcStubBuffer</function> implementations).
898 OIDs are apartment scoped. Each ifstub is identified by an IPID, which identifies
899 a marshaled interface pointer. IPIDs are apartment scoped.
900 </para>
902 <para>
903 Unmarshaling one of these streams therefore means setting up a connection to the
904 object exporter (the apartment holding the marshaled interface pointer) and being
905 able to send RPCs to the right ifstub. Each apartment has its own RPC endpoint and
906 calls can be routed to the correct interface pointer by embedding the IPID into the
907 call using RpcBindingSetObject. IRemUnknown, discussed below, uses a reserved IPID.
908 Please note that this is true only in the current implementation. The native version
909 generates an IPID as per any other object and simply notifies the SCM of this IPID.
910 </para>
912 <para>
913 Both standard and handler marshaled OBJREFs contains an OXID resolver endpoint which
914 is an RPC string binding in a DUALSTRINGARRAY. This is necessary because an OXID
915 alone is not enough to contact the host, as it doesn't contain any network address
916 data. Instead, the combination of the remote OXID resolver RPC endpoint and the OXID
917 itself are passed to the local OXID resolver. It then returns the apartment string binding.
918 </para>
920 <para>
921 This step is an optimisation: technically the OBJREF itself could contain the string
922 binding of the apartment endpoint and the OXID resolver could be bypassed, but by using
923 this DCOM can optimise out a server round-trip by having the local OXID resolver cache
924 the query results. The OXID resolver is a service in the RPC subsystem (rpcss.exe) which
925 implements a raw (non object-oriented) RPC interface called <function>IOXIDResolver</function>.
926 Despite the identical naming convention this is not a COM interface.
927 </para>
929 <para>
930 Unmarshaling an interface pointer stream therefore consists of
931 reading the OXID, OID and IPID from the STDOBJREF, then reading
932 one or more RPC string bindings for the remote OXID resolver.
933 Then <function>RpcBindingFromStringBinding</function> is used
934 to convert this remote string binding into an RPC binding handle
935 which can be passed to the local
936 <function>IOXIDResolver::ResolveOxid</function> implementation
937 along with the OXID. The local OXID resolver consults its list
938 of same-machine OXIDs, then its cache of remote OXIDs, and if
939 not found does an RPC to the remote OXID resolver using the
940 binding handle passed in earlier. The result of the query is
941 stored for future reference in the cache, and finally the
942 unmarshaling application gets back the apartment string binding,
943 the IPID of that apartments <function>IRemUnknown</function>
944 implementation, and a security hint (let's ignore this for now).
945 </para>
947 <para>
948 Once the remote apartments string binding has been located the
949 unmarshalling process constructs an RPC Channel Buffer
950 implementation with the connection handle and the IPID of the
951 needed interface, loads and constructs the
952 <function>IRpcProxyBuffer</function> implementation for that
953 IID and connects it to the channel. Finally the proxy is passed
954 back to the application.
955 </para>
956 </sect2>
958 <sect2>
959 <title>Handling IUnknown</title>
961 <para>
962 There are some subtleties here with respect to IUnknown. IUnknown
963 itself is never marshaled directly: instead a version of it
964 optimised for network usage is used. IRemUnknown is similar in
965 concept to IUnknown except that it allows you to add and release
966 arbitrary numbers of references at once, and it also allows you to
967 query for multiple interfaces at once.
968 </para>
970 <para>
971 IRemUnknown is used for lifecycle management, and for marshaling
972 new interfaces on an object back to the client. Its definition can
973 be seen in dcom.idl - basically the IRemUnknown::RemQueryInterface
974 method takes an IPID and a list of IIDs, then returns STDOBJREFs
975 of each new marshaled interface pointer.
976 </para>
978 <para>
979 There is one IRemUnknown implementation per apartment, not per
980 stub manager as you might expect. This is OK because IPIDs are
981 apartment not object scoped (In fact, according to the DCOM draft
982 spec, they are machine-scoped, but this implies apartment-scoped).
983 </para>
984 </sect2>
986 <sect2>
987 <title>Table marshaling</title>
989 <para>
990 Normally once you have unmarshaled a marshaled interface pointer
991 that stream is dead, you can't unmarshal it again. Sometimes this
992 isn't what you want. In this case, table marshaling can be used.
993 There are two types: strong and weak. In table-strong marshaling,
994 selected by a specific flag to <function>CoMarshalInterface()</function>,
995 a stream can be unmarshaled as many times as you like. Even if
996 all the proxies are released, the marshaled object reference is
997 still valid. Effectively the stream itself holds a ref on the object.
998 To release the object entirely so its server can shut down, you
999 must use <function>CoReleaseMarshalData()</function> on the stream.
1000 </para>
1002 <para>
1003 In table-weak marshaling the stream can be unmarshaled many times,
1004 however the stream does not hold a ref. If you unmarshal the
1005 stream twice, once those two proxies have been released remote
1006 object will also be released. Attempting to unmarshal the stream
1007 at this point will yield <function>CO_E_DISCONNECTED</function>.
1008 </para>
1009 </sect2>
1011 <sect2>
1012 <title>RPC dispatch</title>
1014 <para>
1015 Exactly how RPC dispatch occurs depends on whether the exported
1016 object is in a STA or the MTA. If it's in the MTA then all is
1017 simple: the RPC dispatch thread can temporarily enter the MTA,
1018 perform the remote call, and then leave it again. If it's in a
1019 STA things get more complex, because of the requirement that only
1020 one thread can ever access the object.
1021 </para>
1023 <para>
1024 Instead, when entering a STA a hidden window is created implicitly
1025 by COM, and the user must manually pump the message loop in order
1026 to service incoming RPCs. The RPC dispatch thread performs the
1027 context switch into the STA by sending a message to the apartments
1028 window, which then proceeds to invoke the remote call in the right
1029 thread.
1030 </para>
1032 <para>
1033 RPC dispatch threads are pooled by the RPC runtime. When an incoming
1034 RPC needs to be serviced, a thread is pulled from the pool and
1035 invokes the call. The main RPC thread then goes back to listening
1036 for new calls. It's quite likely for objects in the MTA to therefore
1037 be servicing more than one call at once.
1038 </para>
1039 </sect2>
1041 <sect2>
1042 <title>Message filtering and re-entrancy</title>
1044 <para>
1045 When an outgoing call is made from a STA, it's possible that the
1046 remote server will re-enter the client, for instance to perform a
1047 callback. Because of this potential re-entrancy, when waiting for
1048 the reply to an RPC made inside a STA, COM will pump the message loop.
1049 That's because while this thread is blocked, the incoming callback
1050 will be dispatched by a thread from the RPC dispatch pool, so it
1051 must be processing messages.
1052 </para>
1054 <para>
1055 While COM is pumping the message loop, all incoming messages from
1056 the operating system are filtered through one or more message filters.
1057 These filters are themselves COM objects which can choose to discard,
1058 hold or forward window messages. The default message filter drops all
1059 input messages and forwards the rest. This is so that if the user
1060 chooses a menu option which triggers an RPC, they then cannot choose
1061 that menu option *again* and restart the function from the beginning.
1062 That type of unexpected re-entrancy is extremely difficult to debug,
1063 so it's disallowed.
1064 </para>
1066 <para>
1067 Unfortunately other window messages are allowed through, meaning that
1068 it's possible your UI will be required to repaint itself during an
1069 outgoing RPC. This makes programming with STAs more complex than it
1070 may appear, as you must be prepared to run all kinds of code any time
1071 an outgoing call is made. In turn this breaks the idea that COM
1072 should abstract object location from the programmer, because an
1073 object that was originally free-threaded and is then run from a STA
1074 could trigger new and untested codepaths in a program.
1075 </para>
1076 </sect2>
1078 <sect2>
1079 <title>Wrapup</title>
1081 <para>
1082 Theres are still a lot of topics that have not been covered:
1083 </para>
1085 <itemizedlist>
1086 <listitem><para> Format strings/MOPs</para></listitem>
1088 <listitem><para> IRemoteActivation</para></listitem>
1090 <listitem><para> Complex/simple pings, distributed garbage collection</para></listitem>
1092 <listitem><para> Marshalling IDispatch</para></listitem>
1094 <listitem><para> ICallFrame</para></listitem>
1096 <listitem><para> Interface pointer swizzling</para></listitem>
1098 <listitem><para> Runtime class object registration (CoRegisterClassObject), ROT</para></listitem>
1100 <listitem><para> Exactly how InstallShield uses DCOM</para></listitem>
1101 </itemizedlist>
1103 </sect2>
1105 <sect2>
1106 <title>Further Reading</title>
1108 <para>
1109 Most of these documents assume you have knowledge only contained in
1110 other documents. You may have to reread them a few times for it all to
1111 make sense. Don't feel you need to read these to understand DCOM, you
1112 don't, you only need to look at them if you're planning to help
1113 implement it.
1114 </para>
1116 <itemizedlist>
1117 <listitem><para>
1118 <ulink url="http://www-csag.ucsd.edu/individual/achien/cs491-f97/projects/dcom-writeup.ps">
1119 http://www-csag.ucsd.edu/individual/achien/cs491-f97/projects/dcom-writeup.ps</ulink>
1121 </para></listitem>
1123 <listitem><para>
1124 <ulink url="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/com/htm/cmi_n2p_459u.asp">
1125 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/com/htm/cmi_n2p_459u.asp</ulink>
1127 </para></listitem>
1130 <listitem><para>
1131 <ulink url="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/com/htm/cmi_q2z_5ygi.asp">
1132 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/com/htm/cmi_q2z_5ygi.asp</ulink>
1133 </para></listitem>
1136 <listitem><para>
1137 <ulink url="http://www.microsoft.com/msj/0398/dcom.aspx">
1138 http://www.microsoft.com/msj/0398/dcom.aspx</ulink>
1139 </para></listitem>
1141 <listitem><para>
1142 <ulink url="http://www.microsoft.com/ntserver/techresources/appserv/COM/DCOM/4_ConnectionMgmt.asp">
1143 http://www.microsoft.com/ntserver/techresources/appserv/COM/DCOM/4_ConnectionMgmt.asp</ulink>
1144 </para></listitem>
1147 <listitem><para><ulink url="http://www.idevresource.com/com/library/articles/comonlinux.asp">
1148 http://www.idevresource.com/com/library/articles/comonlinux.asp</ulink>
1150 (unfortunately part 2 of this article does not seem to exist anymore, if it was ever written)</para></listitem>
1151 </itemizedlist>
1152 </sect2>
1153 </sect1>
1154 </chapter>
1156 <!-- Keep this comment at the end of the file
1157 Local variables:
1158 mode: sgml
1159 sgml-parent-document:("wine-devel.sgml" "set" "book" "part" "chapter" "")
1160 End: