VirtualBox

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

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

Main: Fixed build after r27415.

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