VirtualBox

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

Last change on this file since 22708 was 22708, checked in by vboxsync, 15 years ago

Main: comptr+webservice logging

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