VirtualBox

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

Last change on this file since 13287 was 9332, checked in by vboxsync, 16 years ago

Must make sure UINT32_C() and friends are defined when stdint.h might be included by someone other than iprt/types.h.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.7 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/* 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 */
72template <class C>
73class ComStrongRef
74{
75protected:
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 */
84template <class C>
85class ComWeakRef
86{
87protected:
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 */
106template <class I1, class I2>
107inline 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> */
123template <class I1>
124inline 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> */
136template <class I2>
137inline 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 */
149template<>
150inline 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 */
158template <class C, template <class> class RefOps = ComStrongRef>
159class ComPtrBase : protected RefOps <C>
160{
161public:
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
177protected:
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
197public:
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 * Derefereces 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
266private:
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 */
298template <class I, template <class> class RefOps = ComStrongRef>
299class ComPtr : public ComPtrBase <I, RefOps>
300{
301 typedef ComPtrBase <I, RefOps> Base;
302
303public:
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 * Createas 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 * Createas 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 * Createas 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 */
432template <template <class> class RefOps>
433class ComPtr <IUnknown, RefOps> : public ComPtrBase <IUnknown, RefOps>
434{
435 typedef ComPtrBase <IUnknown, RefOps> Base;
436
437public:
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 */
478template <class C, template <class> class RefOps = ComStrongRef>
479class ComObjPtr : public ComPtrBase <C, RefOps>
480{
481 typedef ComPtrBase <C, RefOps> Base;
482
483public:
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 repository browser.

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