VirtualBox

source: vbox/trunk/include/VBox/com/ptr.h@ 8155

Last change on this file since 8155 was 8155, checked in by vboxsync, 17 years ago

The Big Sun Rebranding Header Change

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette