VirtualBox

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

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

Automated rebranding to Oracle copyright/license strings via filemuncher

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