VirtualBox

root/trunk/include/VBox/com/ptr.h

Revision 13856, 14.7 kB (checked in by vboxsync, 2 months ago)

Main: typos

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /** @file
2  * MS COM / XPCOM Abstraction Layer:
3  * Smart COM pointer classes declaration
4  */
5
6 /*
7  * Copyright (C) 2006-2007 Sun Microsystems, Inc.
8  *
9  * This file is part of VirtualBox Open Source Edition (OSE), as
10  * available from http://www.virtualbox.org. This file is free software;
11  * you can redistribute it and/or modify it under the terms of the GNU
12  * General Public License (GPL) as published by the Free Software
13  * Foundation, in version 2 as it comes in the "COPYING" file of the
14  * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15  * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16  *
17  * The contents of this file may alternatively be used under the terms
18  * of the Common Development and Distribution License Version 1.0
19  * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20  * VirtualBox OSE distribution, in which case the provisions of the
21  * CDDL are applicable instead of those of the GPL.
22  *
23  * You may elect to license modified versions of this file under the
24  * terms and conditions of either the GPL or the CDDL or both.
25  *
26  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
27  * Clara, CA 95054 USA or visit http://www.sun.com if you need
28  * additional information or have any questions.
29  */
30
31 #ifndef ___VBox_com_ptr_h
32 #define ___VBox_com_ptr_h
33
34 /* Make sure all the stdint.h macros are included - must come first! */
35 #ifndef __STDC_LIMIT_MACROS
36 # define __STDC_LIMIT_MACROS
37 #endif
38 #ifndef __STDC_CONSTANT_MACROS
39 # define __STDC_CONSTANT_MACROS
40 #endif
41
42 #if !defined (VBOX_WITH_XPCOM)
43
44 #include <atlbase.h>
45
46 #ifndef _ATL_IIDOF
47 # define _ATL_IIDOF(c) __uuidof(c)
48 #endif
49
50 #else /* !defined (VBOX_WITH_XPCOM) */
51
52 #include <nsXPCOM.h>
53 #include <nsIComponentManager.h>
54 #include <nsCOMPtr.h>
55 #include <ipcIService.h>
56 #include <nsIServiceManagerUtils.h>
57 #include <ipcCID.h>
58 #include <ipcIDConnectService.h>
59
60 // official XPCOM headers don't define it yet
61 #define IPC_DCONNECTSERVICE_CONTRACTID \
62     "@mozilla.org/ipc/dconnect-service;1"
63
64 #endif /* !defined (VBOX_WITH_XPCOM) */
65
66 #include <VBox/com/defs.h>
67 #include <VBox/com/assert.h>
68
69 /**
70  *  Strong referencing operators. Used as a second argument to ComPtr<>/ComObjPtr<>.
71  */
72 template <class C>
73 class ComStrongRef
74 {
75 protected:
76
77     static void addref (C *p) { p->AddRef(); }
78     static void release (C *p) { p->Release(); }
79 };
80
81 /**
82  *  Weak referencing operators. Used as a second argument to ComPtr<>/ComObjPtr<>.
83  */
84 template <class C>
85 class ComWeakRef
86 {
87 protected:
88
89     static void addref (C *p) {}
90     static void release (C *p) {}
91 };
92
93 /**
94  *  Returns @c true if two interface pointers are equal.
95  *
96  *  According to the COM Identity Rule, interface pointers are considered to be
97  *  equal if and only if IUnknown pointers queried on these interfaces pointers
98  *  are equal (e.g. have the same binary value). Equal interface pointers
99  *  represent the same object even if they are pointers to different interfaces.
100  *
101  *  @param I1   Class of the first interface pointer (must be derived from
102  *              IUnknown).
103  *  @param I2   Class of the second interface pointer (must be derived from
104  *              IUnknown).
105  */
106 template <class I1, class I2>
107 inline bool ComPtrEquals (I1 *aThis, I2 *aThat)
108 {
109     IUnknown *thatUnk = NULL, *thisUnk = NULL;
110     if (aThat)
111         aThat->QueryInterface (COM_IIDOF (IUnknown), (void **) &thatUnk);
112     if (aThis)
113         aThis->QueryInterface (COM_IIDOF (IUnknown), (void **) &thisUnk);
114     bool equal = thisUnk == thatUnk;
115     if (thisUnk)
116         thisUnk->Release();
117     if (thatUnk)
118         thatUnk->Release();
119     return equal;
120 }
121
122 /* specialization for <Any, IUnknown> */
123 template <class I1>
124 inline bool ComPtrEquals (I1 *aThis, IUnknown *aThat)
125 {
126     IUnknown *thisUnk = NULL;
127     if (aThis)
128         aThis->QueryInterface (COM_IIDOF (IUnknown), (void **) &thisUnk);
129     bool equal = thisUnk == aThat;
130     if (thisUnk)
131         thisUnk->Release();
132     return equal;
133 }
134
135 /** Specialization for <IUnknown, Any> */
136 template <class I2>
137 inline bool ComPtrEquals (IUnknown *aThis, I2 *aThat)
138 {
139     IUnknown *thatUnk = NULL;
140     if (aThat)
141         aThat->QueryInterface (COM_IIDOF (IUnknown), (void **) &thatUnk);
142     bool equal = aThis == thatUnk;
143     if (thatUnk)
144         thatUnk->Release();
145     return equal;
146 }
147
148 /* specialization for IUnknown */
149 template<>
150 inline bool ComPtrEquals <IUnknown, IUnknown> (IUnknown *aThis, IUnknown *aThat)
151 {
152     return aThis == aThat;
153 }
154
155 /**
156  *  Base template for smart COM pointers. Not intended to be used directly.
157  */
158 template <class C, template <class> class RefOps = ComStrongRef>
159 class ComPtrBase : protected RefOps <C>
160 {
161 public:
162
163     /* special template to disable AddRef()/Release() */
164     template <class I>
165     class NoAddRefRelease : public I
166     {
167         private:
168 #if !defined (VBOX_WITH_XPCOM)
169             STDMETHOD_(ULONG, AddRef)() = 0;
170             STDMETHOD_(ULONG, Release)() = 0;
171 #else /* !defined (VBOX_WITH_XPCOM) */
172             NS_IMETHOD_(nsrefcnt) AddRef(void) = 0;
173             NS_IMETHOD_(nsrefcnt) Release(void) = 0;
174 #endif /* !defined (VBOX_WITH_XPCOM) */
175     };
176
177 protected:
178
179     ComPtrBase () : p (NULL) {}
180     ComPtrBase (const ComPtrBase &that) : p (that.p) { addref(); }
181     ComPtrBase (C *that_p) : p (that_p) { addref(); }
182
183     ~ComPtrBase() { release(); }
184
185     ComPtrBase &operator= (const ComPtrBase &that)
186     {
187         safe_assign (that.p);
188         return *this;
189     }
190
191     ComPtrBase &operator= (C *that_p)
192     {
193         safe_assign (that_p);
194         return *this;
195     }
196
197 public:
198
199     void setNull()
200     {
201         release();
202         p = NULL;
203     }
204
205     bool isNull() const
206     {
207         return (p == NULL);
208     }
209
210     bool operator! () const { return isNull(); }
211
212     bool operator< (C* that_p) const { return p < that_p; }
213     bool operator== (C* that_p) const { return p == that_p; }
214
215     template <class I>
216     bool equalsTo (I *aThat) const
217     {
218         return ComPtrEquals (p, aThat);
219     }
220
221     template <class OC>
222     bool equalsTo (const ComPtrBase <OC> &oc) const
223     {
224         return equalsTo ((OC *) oc);
225     }
226
227     /** Intended to pass instances as in parameters to interface methods */
228     operator C* () const { return p; }
229
230     /**
231      *  Dereferences the instance (redirects the -> operator to the managed
232      *  pointer).
233      */
234     NoAddRefRelease <C> *operator-> () const
235     {
236         AssertMsg (p, ("Managed pointer must not be null\n"));
237         return (NoAddRefRelease <C> *) p;
238     }
239
240     template <class I>
241     HRESULT queryInterfaceTo (I **pp) const
242     {
243         if (pp)
244         {
245             if (p)
246             {
247                 return p->QueryInterface (COM_IIDOF (I), (void **) pp);
248             }
249             else
250             {
251                 *pp = NULL;
252                 return S_OK;
253             }
254         }
255
256         return E_INVALIDARG;
257     }
258
259     /** Intended to pass instances as out parameters to interface methods */
260     C **asOutParam()
261     {
262         setNull();
263         return &p;
264     }
265
266 private:
267
268     void addref()
269     {
270         if (p)
271             RefOps <C>::addref (p);
272     }
273
274     void release()
275     {
276         if (p)
277             RefOps <C>::release (p);
278     }
279
280     void safe_assign (C *that_p)
281     {
282         /* be aware of self-assignment */
283         if (that_p)
284             RefOps <C>::addref (that_p);
285         release();
286         p = that_p;
287     }
288
289     C *p;
290 };
291
292 /**
293  *  Smart COM pointer wrapper that automatically manages refcounting of
294  *  interface pointers.
295  *
296  *  @param I    COM interface class
297  */
298 template <class I, template <class> class RefOps = ComStrongRef>
299 class ComPtr : public ComPtrBase <I, RefOps>
300 {
301     typedef ComPtrBase <I, RefOps> Base;
302
303 public:
304
305     ComPtr () : Base() {}
306     ComPtr (const ComPtr &that) : Base (that) {}
307     ComPtr &operator= (const ComPtr &that)
308     {
309         Base::operator= (that);
310         return *this;
311     }
312
313     template <class OI>
314     ComPtr (OI *that_p) : Base () { operator= (that_p); }
315
316     /* specialization for I */
317     ComPtr (I *that_p) : Base (that_p) {}
318
319     template <class OC>
320     ComPtr (const ComPtr <OC, RefOps> &oc) : Base () { operator= ((OC *) oc); }
321
322     template <class OI>
323     ComPtr &operator= (OI *that_p)
324     {
325         if (that_p)
326             that_p->QueryInterface (COM_IIDOF (I), (void **) Base::asOutParam());
327         else
328             Base::setNull();
329         return *this;
330     }
331
332     /* specialization for I */
333     ComPtr &operator=(I *that_p)
334     {
335         Base::operator= (that_p);
336         return *this;
337     }
338
339     template <class OC>
340     ComPtr &operator= (const ComPtr <OC, RefOps> &oc)
341     {
342         return operator= ((OC *) oc);
343     }
344
345     /**
346      *  Creates an in-process object of the given class ID and starts to
347      *  manage a reference to the created object in case of success.
348      */
349     HRESULT createInprocObject (const CLSID &clsid)
350     {
351         HRESULT rc;
352         I *obj = NULL;
353 #if !defined (VBOX_WITH_XPCOM)
354         rc = CoCreateInstance (clsid, NULL, CLSCTX_INPROC_SERVER, _ATL_IIDOF (I),
355                                (void **) &obj);
356 #else /* !defined (VBOX_WITH_XPCOM) */
357         nsCOMPtr <nsIComponentManager> manager;
358         rc = NS_GetComponentManager (getter_AddRefs (manager));
359         if (SUCCEEDED (rc))
360             rc = manager->CreateInstance (clsid, nsnull, NS_GET_IID (I),
361                                           (void **) &obj);
362 #endif /* !defined (VBOX_WITH_XPCOM) */
363         *this = obj;
364         if (SUCCEEDED (rc))
365             obj->Release();
366         return rc;
367     }
368
369     /**
370      *  Creates a local (out-of-process) object of the given class ID and starts
371      *  to manage a reference to the created object in case of success.
372      *
373      *  Note: In XPCOM, the out-of-process functionality is currently emulated
374      *  through in-process wrapper objects (that start a dedicated process and
375      *  redirect all object requests to that process). For this reason, this
376      *  method is fully equivalent to #createInprocObject() for now.
377      */
378     HRESULT createLocalObject (const CLSID &clsid)
379     {
380 #if !defined (VBOX_WITH_XPCOM)
381         HRESULT rc;
382         I *obj = NULL;
383         rc = CoCreateInstance (clsid, NULL, CLSCTX_LOCAL_SERVER, _ATL_IIDOF (I),
384                                (void **) &obj);
385         *this = obj;
386         if (SUCCEEDED (rc))
387             obj->Release();
388         return rc;
389 #else /* !defined (VBOX_WITH_XPCOM) */
390         return createInprocObject (clsid);
391 #endif /* !defined (VBOX_WITH_XPCOM) */
392     }
393
394 #ifdef VBOX_WITH_XPCOM
395     /**
396      *  Creates an object of the given class ID on the specified server and
397      *  starts to manage a reference to the created object in case of success.
398      *
399      *  @param serverName   Name of the server to create an object within.
400      */
401     HRESULT createObjectOnServer (const CLSID &clsid, const char *serverName)
402     {
403         HRESULT rc;
404         I *obj = NULL;
405         nsCOMPtr <ipcIService> ipcServ = do_GetService (IPC_SERVICE_CONTRACTID, &rc);
406         if (SUCCEEDED (rc))
407         {
408             PRUint32 serverID = 0;
409             rc = ipcServ->ResolveClientName (serverName, &serverID);
410             if (SUCCEEDED (rc))
411             {
412                 nsCOMPtr <ipcIDConnectService> dconServ =
413                     do_GetService (IPC_DCONNECTSERVICE_CONTRACTID, &rc);
414                 if (SUCCEEDED (rc))
415                     rc = dconServ->CreateInstance (serverID, clsid, NS_GET_IID (I),
416                                                    (void **) &obj);
417             }
418         }
419         *this = obj;
420         if (SUCCEEDED (rc))
421             obj->Release();
422         return rc;
423     }
424 #endif
425 };
426
427 /**
428  *  Specialization of ComPtr<> for IUnknown to guarantee identity
429  *  by always doing QueryInterface() when constructing or assigning from
430  *  another interface pointer disregarding its type.
431  */
432 template <template <class> class RefOps>
433 class ComPtr <IUnknown, RefOps> : public ComPtrBase <IUnknown, RefOps>
434 {
435     typedef ComPtrBase <IUnknown, RefOps> Base;
436
437 public:
438
439     ComPtr () : Base() {}
440     ComPtr (const ComPtr &that) : Base (that) {}
441     ComPtr &operator= (const ComPtr &that)
442     {
443         Base::operator= (that);
444         return *this;
445     }
446
447     template <class OI>
448     ComPtr (OI *that_p) : Base () { operator= (that_p); }
449
450     template <class OC>
451     ComPtr (const ComPtr <OC, RefOps> &oc) : Base () { operator= ((OC *) oc); }
452
453     template <class OI>
454     ComPtr &operator= (OI *that_p)
455     {
456         if (that_p)
457             that_p->QueryInterface (COM_IIDOF (IUnknown), (void **) Base::asOutParam());
458         else
459             Base::setNull();
460         return *this;
461     }
462
463     template <class OC>
464     ComPtr &operator= (const ComPtr <OC, RefOps> &oc)
465     {
466         return operator= ((OC *) oc);
467     }
468 };
469
470 /**
471  *  Smart COM pointer wrapper that automatically manages refcounting of
472  *  pointers to interface implementation classes created on the component's
473  *  (i.e. the server's) side. Differs from ComPtr by providing additional
474  *  platform independent operations for creating new class instances.
475  *
476  *  @param C    class that implements some COM interface
477  */
478 template <class C, template <class> class RefOps = ComStrongRef>
479 class ComObjPtr : public ComPtrBase <C, RefOps>
480 {
481     typedef ComPtrBase <C, RefOps> Base;
482
483 public:
484
485     ComObjPtr () : Base() {}
486     ComObjPtr (const ComObjPtr &that) : Base (that) {}
487     ComObjPtr (C *that_p) : Base (that_p) {}
488
489     ComObjPtr &operator= (const ComObjPtr &that)
490     {
491         Base::operator= (that);
492         return *this;
493     }
494
495     ComObjPtr &operator= (C *that_p)
496     {
497         Base::operator= (that_p);
498         return *this;
499     }
500
501     /**
502      *  Creates a new server-side object of the given component class and
503      *  immediately starts to manage a pointer to the created object (the
504      *  previous pointer, if any, is of course released when appropriate).
505      *
506      *  @note This method should be used with care on weakly referenced
507      *  smart pointers because it leaves the newly created object completely
508      *  unreferenced (i.e., with reference count equal to zero),
509      *
510      *  @note Win32: when VBOX_COM_OUTOFPROC_MODULE is defined, the created
511      *  object doesn't increase the lock count of the server module, as it
512      *  does otherwise.
513      */
514     HRESULT createObject()
515     {
516         HRESULT rc;
517 #if !defined (VBOX_WITH_XPCOM)
518 #   ifdef VBOX_COM_OUTOFPROC_MODULE
519         CComObjectNoLock <C> *obj = new CComObjectNoLock <C>();
520         if (obj)
521         {
522             obj->InternalFinalConstructAddRef();
523             rc = obj->FinalConstruct();
524             obj->InternalFinalConstructRelease();
525         }
526         else
527             rc = E_OUTOFMEMORY;
528 #   else
529         CComObject <C> *obj = NULL;
530         rc = CComObject <C>::CreateInstance (&obj);
531 #   endif
532 #else /* !defined (VBOX_WITH_XPCOM) */
533         CComObject <C> *obj = new CComObject <C>();
534         if (obj)
535             rc = obj->FinalConstruct();
536         else
537             rc = E_OUTOFMEMORY;
538 #endif /* !defined (VBOX_WITH_XPCOM) */
539         *this = obj;
540         return rc;
541     }
542 };
543
544 #endif
Note: See TracBrowser for help on using the browser.

© 2008 Sun Microsystems, Inc.
ContactPrivacy policy