summaryrefslogtreecommitdiff
path: root/include/VBox/com
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@baserock.org>2012-10-26 16:25:44 +0000
committer <>2012-11-12 12:15:52 +0000
commit58ed4748338f9466599adfc8a9171280ed99e23f (patch)
tree02027d99ded4fb56a64aa9489ac2eb487e7858ab /include/VBox/com
downloadVirtualBox-58ed4748338f9466599adfc8a9171280ed99e23f.tar.gz
Imported from /home/lorry/working-area/delta_VirtualBox/VirtualBox-4.2.4.tar.bz2.VirtualBox-4.2.4
Diffstat (limited to 'include/VBox/com')
-rw-r--r--include/VBox/com/AutoLock.h638
-rw-r--r--include/VBox/com/ErrorInfo.h495
-rw-r--r--include/VBox/com/EventQueue.h140
-rw-r--r--include/VBox/com/Guid.h353
-rw-r--r--include/VBox/com/Makefile.kup0
-rw-r--r--include/VBox/com/MultiResult.h262
-rw-r--r--include/VBox/com/VirtualBox.h55
-rw-r--r--include/VBox/com/array.h1702
-rw-r--r--include/VBox/com/assert.h108
-rw-r--r--include/VBox/com/com.h111
-rw-r--r--include/VBox/com/defs.h549
-rw-r--r--include/VBox/com/errorprint.h261
-rw-r--r--include/VBox/com/list.h197
-rw-r--r--include/VBox/com/listeners.h171
-rw-r--r--include/VBox/com/mtlist.h197
-rw-r--r--include/VBox/com/ptr.h493
-rw-r--r--include/VBox/com/string.h810
17 files changed, 6542 insertions, 0 deletions
diff --git a/include/VBox/com/AutoLock.h b/include/VBox/com/AutoLock.h
new file mode 100644
index 00000000..9c700dd9
--- /dev/null
+++ b/include/VBox/com/AutoLock.h
@@ -0,0 +1,638 @@
+/** @file
+ *
+ * Automatic locks, implementation
+ */
+
+/*
+ * Copyright (C) 2006-2012 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ____H_AUTOLOCK
+#define ____H_AUTOLOCK
+
+#include <iprt/types.h>
+
+// macros for automatic lock validation; these will amount to nothing
+// unless lock validation is enabled for the runtime
+#if defined(RT_LOCK_STRICT)
+# define VBOX_WITH_MAIN_LOCK_VALIDATION
+# define COMMA_LOCKVAL_SRC_POS , RT_SRC_POS
+# define LOCKVAL_SRC_POS_DECL RT_SRC_POS_DECL
+# define COMMA_LOCKVAL_SRC_POS_DECL , RT_SRC_POS_DECL
+# define LOCKVAL_SRC_POS_ARGS RT_SRC_POS_ARGS
+# define COMMA_LOCKVAL_SRC_POS_ARGS , RT_SRC_POS_ARGS
+#else
+# define COMMA_LOCKVAL_SRC_POS
+# define LOCKVAL_SRC_POS_DECL
+# define COMMA_LOCKVAL_SRC_POS_DECL
+# define LOCKVAL_SRC_POS_ARGS
+# define COMMA_LOCKVAL_SRC_POS_ARGS
+#endif
+
+namespace util
+{
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Order classes for lock validation
+//
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * IPRT now has a sophisticated system of run-time locking classes to validate
+ * locking order. Since the Main code is handled by simpler minds, we want
+ * compile-time constants for simplicity, and we'll look up the run-time classes
+ * in AutoLock.cpp transparently. These are passed to the constructors of the
+ * LockHandle classes.
+ */
+enum VBoxLockingClass
+{
+ LOCKCLASS_NONE = 0,
+ LOCKCLASS_WEBSERVICE = 1, // highest order: webservice locks
+ LOCKCLASS_VIRTUALBOXOBJECT = 2, // highest order within Main itself: VirtualBox object lock
+ LOCKCLASS_HOSTOBJECT = 3, // Host object lock
+ LOCKCLASS_LISTOFMACHINES = 4, // list of machines in VirtualBox object
+ LOCKCLASS_MACHINEOBJECT = 5, // Machine object lock
+ LOCKCLASS_SNAPSHOTOBJECT = 6, // snapshot object locks
+ // (the snapshots tree, including the child pointers in Snapshot,
+ // is protected by the normal Machine object lock)
+ LOCKCLASS_MEDIUMQUERY = 7, // lock used to protect Machine::queryInfo
+ LOCKCLASS_LISTOFMEDIA = 8, // list of media (hard disks, DVDs, floppies) in VirtualBox object
+ LOCKCLASS_LISTOFOTHEROBJECTS = 9, // any other list of objects
+ LOCKCLASS_OTHEROBJECT = 10, // any regular object member variable lock
+ LOCKCLASS_PROGRESSLIST = 11, // list of progress objects in VirtualBox; no other object lock
+ // may be held after this!
+ LOCKCLASS_OBJECTSTATE = 12 // object state lock (handled by AutoCaller classes)
+};
+
+void InitAutoLockSystem();
+
+/**
+ * Check whether the current thread holds any locks in the given class
+ *
+ * @return true if any such locks are held, false otherwise. If the lock
+ * validator is not compiled in, always returns false.
+ * @param lockClass Which lock class to check.
+ */
+bool AutoLockHoldsLocksInClass(VBoxLockingClass lockClass);
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// LockHandle and friends
+//
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Abstract base class for semaphore handles (RWLockHandle and WriteLockHandle).
+ * Don't use this directly, but this implements lock validation for them.
+ */
+class LockHandle
+{
+public:
+ LockHandle()
+ {}
+
+ virtual ~LockHandle()
+ {}
+
+ /**
+ * Returns @c true if the current thread holds a write lock on this
+ * read/write semaphore. Intended for debugging only.
+ */
+ virtual bool isWriteLockOnCurrentThread() const = 0;
+
+ /**
+ * Returns the current write lock level of this semaphore. The lock level
+ * determines the number of nested #lock() calls on the given semaphore
+ * handle.
+ *
+ * Note that this call is valid only when the current thread owns a write
+ * lock on the given semaphore handle and will assert otherwise.
+ */
+ virtual uint32_t writeLockLevel() const = 0;
+
+ virtual void lockWrite(LOCKVAL_SRC_POS_DECL) = 0;
+ virtual void unlockWrite() = 0;
+ virtual void lockRead(LOCKVAL_SRC_POS_DECL) = 0;
+ virtual void unlockRead() = 0;
+
+#ifdef VBOX_WITH_MAIN_LOCK_VALIDATION
+ virtual const char* describe() const = 0;
+#endif
+
+private:
+ // prohibit copy + assignment
+ LockHandle(const LockHandle&);
+ LockHandle& operator=(const LockHandle&);
+};
+
+/**
+ * Full-featured read/write semaphore handle implementation.
+ *
+ * This is an auxiliary base class for classes that need full-featured
+ * read/write locking as described in the AutoWriteLock class documentation.
+ * Instances of classes inherited from this class can be passed as arguments to
+ * the AutoWriteLock and AutoReadLock constructors.
+ */
+class RWLockHandle : public LockHandle
+{
+public:
+ RWLockHandle(VBoxLockingClass lockClass);
+ virtual ~RWLockHandle();
+
+ virtual bool isWriteLockOnCurrentThread() const;
+
+ virtual void lockWrite(LOCKVAL_SRC_POS_DECL);
+ virtual void unlockWrite();
+ virtual void lockRead(LOCKVAL_SRC_POS_DECL);
+ virtual void unlockRead();
+
+ virtual uint32_t writeLockLevel() const;
+
+#ifdef VBOX_WITH_MAIN_LOCK_VALIDATION
+ virtual const char* describe() const;
+#endif
+
+private:
+ struct Data;
+ Data *m;
+};
+
+/**
+ * Write-only semaphore handle implementation.
+ *
+ * This is an auxiliary base class for classes that need write-only (exclusive)
+ * locking and do not need read (shared) locking. This implementation uses a
+ * cheap and fast critical section for both lockWrite() and lockRead() methods
+ * which makes a lockRead() call fully equivalent to the lockWrite() call and
+ * therefore makes it pointless to use instahces of this class with
+ * AutoReadLock instances -- shared locking will not be possible anyway and
+ * any call to lock() will block if there are lock owners on other threads.
+ *
+ * Use with care only when absolutely sure that shared locks are not necessary.
+ */
+class WriteLockHandle : public LockHandle
+{
+public:
+ WriteLockHandle(VBoxLockingClass lockClass);
+ virtual ~WriteLockHandle();
+ virtual bool isWriteLockOnCurrentThread() const;
+
+ virtual void lockWrite(LOCKVAL_SRC_POS_DECL);
+ virtual void unlockWrite();
+ virtual void lockRead(LOCKVAL_SRC_POS_DECL);
+ virtual void unlockRead();
+ virtual uint32_t writeLockLevel() const;
+
+#ifdef VBOX_WITH_MAIN_LOCK_VALIDATION
+ virtual const char* describe() const;
+#endif
+
+private:
+ struct Data;
+ Data *m;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Lockable
+//
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Lockable interface.
+ *
+ * This is an abstract base for classes that need read/write locking. Unlike
+ * RWLockHandle and other classes that makes the read/write semaphore a part of
+ * class data, this class allows subclasses to decide which semaphore handle to
+ * use.
+ */
+class Lockable
+{
+public:
+
+ /**
+ * Returns a pointer to a LockHandle used by AutoWriteLock/AutoReadLock
+ * for locking. Subclasses are allowed to return @c NULL -- in this case,
+ * the AutoWriteLock/AutoReadLock object constructed using an instance of
+ * such subclass will simply turn into no-op.
+ */
+ virtual LockHandle *lockHandle() const = 0;
+
+ /**
+ * Equivalent to <tt>#lockHandle()->isWriteLockOnCurrentThread()</tt>.
+ * Returns @c false if lockHandle() returns @c NULL.
+ */
+ bool isWriteLockOnCurrentThread()
+ {
+ LockHandle *h = lockHandle();
+ return h ? h->isWriteLockOnCurrentThread() : false;
+ }
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// AutoLockBase
+//
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Abstract base class for all autolocks.
+ *
+ * This cannot be used directly. Use AutoReadLock or AutoWriteLock or AutoMultiWriteLock2/3
+ * which directly and indirectly derive from this.
+ *
+ * In the implementation, the instance data contains a list of lock handles.
+ * The class provides some utility functions to help locking and unlocking
+ * them.
+ */
+
+class AutoLockBase
+{
+protected:
+ AutoLockBase(uint32_t cHandles
+ COMMA_LOCKVAL_SRC_POS_DECL);
+ AutoLockBase(uint32_t cHandles,
+ LockHandle *pHandle
+ COMMA_LOCKVAL_SRC_POS_DECL);
+ virtual ~AutoLockBase();
+
+ struct Data;
+ Data *m;
+
+ virtual void callLockImpl(LockHandle &l) = 0;
+ virtual void callUnlockImpl(LockHandle &l) = 0;
+
+ void callLockOnAllHandles();
+ void callUnlockOnAllHandles();
+
+ void cleanup();
+
+public:
+ void acquire();
+ void release();
+
+private:
+ // prohibit copy + assignment
+ AutoLockBase(const AutoLockBase&);
+ AutoLockBase& operator=(const AutoLockBase&);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// AutoReadLock
+//
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Automatic read lock. Use this with a RWLockHandle to request a read/write
+ * semaphore in read mode. You can also use this with a WriteLockHandle but
+ * that makes little sense since they treat read mode like write mode.
+ *
+ * If constructed with a RWLockHandle or an instance of Lockable (which in
+ * practice means any VirtualBoxBase derivative), it autoamtically requests
+ * the lock in read mode and releases the read lock in the destructor.
+ */
+class AutoReadLock : public AutoLockBase
+{
+public:
+
+ /**
+ * Constructs a null instance that does not manage any read/write
+ * semaphore.
+ *
+ * Note that all method calls on a null instance are no-ops. This allows to
+ * have the code where lock protection can be selected (or omitted) at
+ * runtime.
+ */
+ AutoReadLock(LOCKVAL_SRC_POS_DECL)
+ : AutoLockBase(1,
+ NULL
+ COMMA_LOCKVAL_SRC_POS_ARGS)
+ { }
+
+ /**
+ * Constructs a new instance that will start managing the given read/write
+ * semaphore by requesting a read lock.
+ */
+ AutoReadLock(LockHandle *aHandle
+ COMMA_LOCKVAL_SRC_POS_DECL)
+ : AutoLockBase(1,
+ aHandle
+ COMMA_LOCKVAL_SRC_POS_ARGS)
+ {
+ acquire();
+ }
+
+ /**
+ * Constructs a new instance that will start managing the given read/write
+ * semaphore by requesting a read lock.
+ */
+ AutoReadLock(LockHandle &aHandle
+ COMMA_LOCKVAL_SRC_POS_DECL)
+ : AutoLockBase(1,
+ &aHandle
+ COMMA_LOCKVAL_SRC_POS_ARGS)
+ {
+ acquire();
+ }
+
+ /**
+ * Constructs a new instance that will start managing the given read/write
+ * semaphore by requesting a read lock.
+ */
+ AutoReadLock(const Lockable &aLockable
+ COMMA_LOCKVAL_SRC_POS_DECL)
+ : AutoLockBase(1,
+ aLockable.lockHandle()
+ COMMA_LOCKVAL_SRC_POS_ARGS)
+ {
+ acquire();
+ }
+
+ /**
+ * Constructs a new instance that will start managing the given read/write
+ * semaphore by requesting a read lock.
+ */
+ AutoReadLock(const Lockable *aLockable
+ COMMA_LOCKVAL_SRC_POS_DECL)
+ : AutoLockBase(1,
+ aLockable ? aLockable->lockHandle() : NULL
+ COMMA_LOCKVAL_SRC_POS_ARGS)
+ {
+ acquire();
+ }
+
+ virtual ~AutoReadLock();
+
+ virtual void callLockImpl(LockHandle &l);
+ virtual void callUnlockImpl(LockHandle &l);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// AutoWriteLockBase
+//
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Base class for all auto write locks.
+ *
+ * This cannot be used directly. Use AutoWriteLock or AutoMultiWriteLock2/3
+ * which derive from this.
+ *
+ * It has some utility methods for subclasses.
+ */
+class AutoWriteLockBase : public AutoLockBase
+{
+protected:
+ AutoWriteLockBase(uint32_t cHandles
+ COMMA_LOCKVAL_SRC_POS_DECL)
+ : AutoLockBase(cHandles
+ COMMA_LOCKVAL_SRC_POS_ARGS)
+ { }
+
+ AutoWriteLockBase(uint32_t cHandles,
+ LockHandle *pHandle
+ COMMA_LOCKVAL_SRC_POS_DECL)
+ : AutoLockBase(cHandles,
+ pHandle
+ COMMA_LOCKVAL_SRC_POS_ARGS)
+ { }
+
+ virtual ~AutoWriteLockBase()
+ { }
+
+ virtual void callLockImpl(LockHandle &l);
+ virtual void callUnlockImpl(LockHandle &l);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// AutoWriteLock
+//
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Automatic write lock. Use this with a RWLockHandle to request a read/write
+ * semaphore in write mode. There can only ever be one writer of a read/write
+ * semaphore: while the lock is held in write mode, no other writer or reader
+ * can request the semaphore and will block.
+ *
+ * If constructed with a RWLockHandle or an instance of Lockable (which in
+ * practice means any VirtualBoxBase derivative), it autoamtically requests
+ * the lock in write mode and releases the write lock in the destructor.
+ *
+ * When used with a WriteLockHandle, it requests the semaphore contained therein
+ * exclusively.
+ */
+class AutoWriteLock : public AutoWriteLockBase
+{
+public:
+
+ /**
+ * Constructs a null instance that does not manage any read/write
+ * semaphore.
+ *
+ * Note that all method calls on a null instance are no-ops. This allows to
+ * have the code where lock protection can be selected (or omitted) at
+ * runtime.
+ */
+ AutoWriteLock(LOCKVAL_SRC_POS_DECL)
+ : AutoWriteLockBase(1,
+ NULL
+ COMMA_LOCKVAL_SRC_POS_ARGS)
+ { }
+
+ /**
+ * Constructs a new instance that will start managing the given read/write
+ * semaphore by requesting a write lock.
+ */
+ AutoWriteLock(LockHandle *aHandle
+ COMMA_LOCKVAL_SRC_POS_DECL)
+ : AutoWriteLockBase(1,
+ aHandle
+ COMMA_LOCKVAL_SRC_POS_ARGS)
+ {
+ acquire();
+ }
+
+ /**
+ * Constructs a new instance that will start managing the given read/write
+ * semaphore by requesting a write lock.
+ */
+ AutoWriteLock(LockHandle &aHandle
+ COMMA_LOCKVAL_SRC_POS_DECL)
+ : AutoWriteLockBase(1,
+ &aHandle
+ COMMA_LOCKVAL_SRC_POS_ARGS)
+ {
+ acquire();
+ }
+
+ /**
+ * Constructs a new instance that will start managing the given read/write
+ * semaphore by requesting a write lock.
+ */
+ AutoWriteLock(const Lockable &aLockable
+ COMMA_LOCKVAL_SRC_POS_DECL)
+ : AutoWriteLockBase(1,
+ aLockable.lockHandle()
+ COMMA_LOCKVAL_SRC_POS_ARGS)
+ {
+ acquire();
+ }
+
+ /**
+ * Constructs a new instance that will start managing the given read/write
+ * semaphore by requesting a write lock.
+ */
+ AutoWriteLock(const Lockable *aLockable
+ COMMA_LOCKVAL_SRC_POS_DECL)
+ : AutoWriteLockBase(1,
+ aLockable ? aLockable->lockHandle() : NULL
+ COMMA_LOCKVAL_SRC_POS_ARGS)
+ {
+ acquire();
+ }
+
+ /**
+ * Constructs a new instance that will start managing the given read/write
+ * semaphore by requesting a write lock.
+ */
+ AutoWriteLock(uint32_t cHandles,
+ LockHandle** pHandles
+ COMMA_LOCKVAL_SRC_POS_DECL);
+
+ /**
+ * Release all write locks acquired by this instance through the #lock()
+ * call and destroys the instance.
+ *
+ * Note that if there there are nested #lock() calls without the
+ * corresponding number of #unlock() calls when the destructor is called, it
+ * will assert. This is because having an unbalanced number of nested locks
+ * is a program logic error which must be fixed.
+ */
+ virtual ~AutoWriteLock()
+ {
+ cleanup();
+ }
+
+ void attach(LockHandle *aHandle);
+
+ /** @see attach (LockHandle *) */
+ void attach(LockHandle &aHandle)
+ {
+ attach(&aHandle);
+ }
+
+ /** @see attach (LockHandle *) */
+ void attach(const Lockable &aLockable)
+ {
+ attach(aLockable.lockHandle());
+ }
+
+ /** @see attach (LockHandle *) */
+ void attach(const Lockable *aLockable)
+ {
+ attach(aLockable ? aLockable->lockHandle() : NULL);
+ }
+
+ bool isWriteLockOnCurrentThread() const;
+ uint32_t writeLockLevel() const;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// AutoMultiWriteLock*
+//
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * A multi-write-lock containing two other write locks.
+ *
+ */
+class AutoMultiWriteLock2 : public AutoWriteLockBase
+{
+public:
+ AutoMultiWriteLock2(Lockable *pl1,
+ Lockable *pl2
+ COMMA_LOCKVAL_SRC_POS_DECL);
+ AutoMultiWriteLock2(LockHandle *pl1,
+ LockHandle *pl2
+ COMMA_LOCKVAL_SRC_POS_DECL);
+
+ virtual ~AutoMultiWriteLock2()
+ {
+ cleanup();
+ }
+};
+
+/**
+ * A multi-write-lock containing three other write locks.
+ *
+ */
+class AutoMultiWriteLock3 : public AutoWriteLockBase
+{
+public:
+ AutoMultiWriteLock3(Lockable *pl1,
+ Lockable *pl2,
+ Lockable *pl3
+ COMMA_LOCKVAL_SRC_POS_DECL);
+ AutoMultiWriteLock3(LockHandle *pl1,
+ LockHandle *pl2,
+ LockHandle *pl3
+ COMMA_LOCKVAL_SRC_POS_DECL);
+
+ virtual ~AutoMultiWriteLock3()
+ {
+ cleanup();
+ }
+};
+
+/**
+ * A multi-write-lock containing four other write locks.
+ *
+ */
+class AutoMultiWriteLock4 : public AutoWriteLockBase
+{
+public:
+ AutoMultiWriteLock4(Lockable *pl1,
+ Lockable *pl2,
+ Lockable *pl3,
+ Lockable *pl4
+ COMMA_LOCKVAL_SRC_POS_DECL);
+ AutoMultiWriteLock4(LockHandle *pl1,
+ LockHandle *pl2,
+ LockHandle *pl3,
+ LockHandle *pl4
+ COMMA_LOCKVAL_SRC_POS_DECL);
+
+ virtual ~AutoMultiWriteLock4()
+ {
+ cleanup();
+ }
+};
+
+} /* namespace util */
+
+#endif // ____H_AUTOLOCK
+
+/* vi: set tabstop=4 shiftwidth=4 expandtab: */
diff --git a/include/VBox/com/ErrorInfo.h b/include/VBox/com/ErrorInfo.h
new file mode 100644
index 00000000..1037b253
--- /dev/null
+++ b/include/VBox/com/ErrorInfo.h
@@ -0,0 +1,495 @@
+/** @file
+ * MS COM / XPCOM Abstraction Layer:
+ * ErrorInfo class declaration
+ */
+
+/*
+ * Copyright (C) 2006-2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_com_ErrorInfo_h
+#define ___VBox_com_ErrorInfo_h
+
+#include "VBox/com/ptr.h"
+#include "VBox/com/string.h"
+#include "VBox/com/Guid.h"
+#include "VBox/com/assert.h"
+
+struct IProgress;
+struct IVirtualBoxErrorInfo;
+
+namespace com
+{
+
+/**
+ * General discussion:
+ *
+ * In COM all errors are stored on a per thread basis. In general this means
+ * only _one_ active error is possible per thread. A new error will overwrite
+ * the previous one. To prevent this use MultiResult or ErrorInfoKeeper (see
+ * below). The implementations in MSCOM/XPCOM differ slightly, but the details
+ * are handled by this glue code.
+ *
+ * We have different classes which are involved in the error management. I try
+ * to describe them separately to make clear what they are there for.
+ *
+ * ErrorInfo:
+ *
+ * This class is able to retrieve the per thread error and store it into its
+ * member variables. This class can also handle non-VirtualBox errors (like
+ * standard COM errors).
+ *
+ * ProgressErrorInfo:
+ *
+ * This is just a simple wrapper class to get the ErrorInfo stored within an
+ * IProgress object. That is the error which was stored when the progress
+ * object was in use and not an error produced by IProgress itself.
+ *
+ * IVirtualBoxErrorInfo:
+ *
+ * The VirtualBox interface class for accessing error information from Main
+ * clients. This class is also used for storing the error information in the
+ * thread context.
+ *
+ * ErrorInfoKeeper:
+ *
+ * A helper class which stores the current per thread info internally. After
+ * calling methods which may produce other errors it is possible to restore
+ * the previous error and therefore restore the situation before calling the
+ * other methods.
+ *
+ * MultiResult:
+ *
+ * Creating an instance of MultiResult turns error chain saving on. All errors
+ * which follow will be saved in a chain for later access.
+ *
+ * COMErrorInfo (Qt/Gui only):
+ *
+ * The Qt GUI does some additional work for saving errors. Because we create
+ * wrappers for _every_ COM call, it is possible to automatically save the
+ * error info after the execution. This allow some additional info like saving
+ * the callee. Please note that this error info is saved on the client side
+ * and therefore locally to the object instance. See COMBaseWithEI,
+ * COMErrorInfo and the generated COMWrappers.cpp in the GUI.
+ *
+ * Errors itself are set in VirtualBoxBase::setErrorInternal. First a
+ * IVirtualBoxErrorInfo object is created and the given error is saved within.
+ * If MultiResult is active the current per thread error is fetched and
+ * attached to the new created IVirtualBoxErrorInfo object. Next this object is
+ * set as the new per thread error.
+ *
+ * Some general hints:
+ *
+ * - Always use setError, especially when you are working in an asynchronous thread
+ * to indicate an error. Otherwise the error information itself will not make
+ * it into the client.
+ *
+ */
+
+/**
+ * The ErrorInfo class provides a convenient way to retrieve error
+ * information set by the most recent interface method, that was invoked on
+ * the current thread and returned an unsuccessful result code.
+ *
+ * Once the instance of this class is created, the error information for
+ * the current thread is cleared.
+ *
+ * There is no sense to use instances of this class after the last
+ * invoked interface method returns a success.
+ *
+ * The class usage pattern is as follows:
+ * <code>
+ * IFoo *foo;
+ * ...
+ * HRESULT rc = foo->SomeMethod();
+ * if (FAILED(rc)) {
+ * ErrorInfo info(foo);
+ * if (info.isFullAvailable()) {
+ * printf("error message = %ls\n", info.getText().raw());
+ * }
+ * }
+ * </code>
+ *
+ * This class fetches error information using the IErrorInfo interface on
+ * Win32 (MS COM) or the nsIException interface on other platforms (XPCOM),
+ * or the extended IVirtualBoxErrorInfo interface when when it is available
+ * (i.e. a given IErrorInfo or nsIException instance implements it).
+ * Currently, IVirtualBoxErrorInfo is only available for VirtualBox components.
+ *
+ * ErrorInfo::isFullAvailable() and ErrorInfo::isBasicAvailable() determine
+ * what level of error information is available. If #isBasicAvailable()
+ * returns true, it means that only IErrorInfo or nsIException is available as
+ * the source of information (depending on the platform), but not
+ * IVirtualBoxErrorInfo. If #isFullAvailable() returns true, it means that all
+ * three interfaces are available. If both methods return false, no error info
+ * is available at all.
+ *
+ * Here is a table of correspondence between this class methods and
+ * and IErrorInfo/nsIException/IVirtualBoxErrorInfo attributes/methods:
+ *
+ * ErrorInfo IErrorInfo nsIException IVirtualBoxErrorInfo
+ * --------------------------------------------------------------------
+ * getResultCode -- result resultCode
+ * getIID GetGUID -- interfaceID
+ * getComponent GetSource -- component
+ * getText GetDescription message text
+ *
+ * '--' means that this interface does not provide the corresponding portion
+ * of information, therefore it is useless to query it if only
+ * #isBasicAvailable() returns true. As it can be seen, the amount of
+ * information provided at the basic level, depends on the platform
+ * (MS COM or XPCOM).
+ */
+class ErrorInfo
+{
+public:
+
+ /**
+ * Constructs a new, "interfaceless" ErrorInfo instance that takes
+ * the error information possibly set on the current thread by an
+ * interface method of some COM component or by the COM subsystem.
+ *
+ * This constructor is useful, for example, after an unsuccessful attempt
+ * to instantiate (create) a component, so there is no any valid interface
+ * pointer available.
+ */
+ explicit ErrorInfo()
+ : mIsBasicAvailable(false),
+ mIsFullAvailable(false),
+ mResultCode(S_OK),
+ m_pNext(NULL)
+ {
+ init();
+ }
+
+ ErrorInfo(IUnknown *pObj, const GUID &aIID)
+ : mIsBasicAvailable(false),
+ mIsFullAvailable(false),
+ mResultCode(S_OK),
+ m_pNext(NULL)
+ {
+ init(pObj, aIID);
+ }
+
+ /** Specialization for the IVirtualBoxErrorInfo smart pointer */
+ ErrorInfo (const ComPtr <IVirtualBoxErrorInfo> &aPtr)
+ : mIsBasicAvailable (false), mIsFullAvailable (false)
+ , mResultCode (S_OK)
+ { init (aPtr); }
+
+ /**
+ * Constructs a new ErrorInfo instance from the IVirtualBoxErrorInfo
+ * interface pointer. If this pointer is not NULL, both #isFullAvailable()
+ * and #isBasicAvailable() will return |true|.
+ *
+ * @param aInfo pointer to the IVirtualBoxErrorInfo interface that
+ * holds error info to be fetched by this instance
+ */
+ ErrorInfo (IVirtualBoxErrorInfo *aInfo)
+ : mIsBasicAvailable (false), mIsFullAvailable (false)
+ , mResultCode (S_OK)
+ { init (aInfo); }
+
+ ErrorInfo(const ErrorInfo &x)
+ {
+ copyFrom(x);
+ }
+
+ virtual ~ErrorInfo()
+ {
+ cleanup();
+ }
+
+ ErrorInfo& operator=(const ErrorInfo& x)
+ {
+ cleanup();
+ copyFrom(x);
+ return *this;
+ }
+
+ /**
+ * Returns whether basic error info is actually available for the current
+ * thread. If the instance was created from an interface pointer that
+ * supports basic error info and successfully provided it, or if it is an
+ * "interfaceless" instance and there is some error info for the current
+ * thread, the returned value will be true.
+ *
+ * See the class description for details about the basic error info level.
+ *
+ * The appropriate methods of this class provide meaningful info only when
+ * this method returns true (otherwise they simply return NULL-like values).
+ */
+ bool isBasicAvailable() const
+ {
+ return mIsBasicAvailable;
+ }
+
+ /**
+ * Returns whether full error info is actually available for the current
+ * thread. If the instance was created from an interface pointer that
+ * supports full error info and successfully provided it, or if it is an
+ * "interfaceless" instance and there is some error info for the current
+ * thread, the returned value will be true.
+ *
+ * See the class description for details about the full error info level.
+ *
+ * The appropriate methods of this class provide meaningful info only when
+ * this method returns true (otherwise they simply return NULL-like values).
+ */
+ bool isFullAvailable() const
+ {
+ return mIsFullAvailable;
+ }
+
+ /**
+ * Returns the COM result code of the failed operation.
+ */
+ HRESULT getResultCode() const
+ {
+ return mResultCode;
+ }
+
+ /**
+ * Returns the IID of the interface that defined the error.
+ */
+ const Guid& getInterfaceID() const
+ {
+ return mInterfaceID;
+ }
+
+ /**
+ * Returns the name of the component that generated the error.
+ */
+ const Bstr& getComponent() const
+ {
+ return mComponent;
+ }
+
+ /**
+ * Returns the textual description of the error.
+ */
+ const Bstr& getText() const
+ {
+ return mText;
+ }
+
+ /**
+ * Returns the next error information object or @c NULL if there is none.
+ */
+ const ErrorInfo* getNext() const
+ {
+ return m_pNext;
+ }
+
+ /**
+ * Returns the name of the interface that defined the error
+ */
+ const Bstr& getInterfaceName() const
+ {
+ return mInterfaceName;
+ }
+
+ /**
+ * Returns the IID of the interface that returned the error.
+ *
+ * This method returns a non-null IID only if the instance was created
+ * using #template <class I> ErrorInfo(I *i) or
+ * template <class I> ErrorInfo(const ComPtr<I> &i) constructor.
+ */
+ const Guid& getCalleeIID() const
+ {
+ return mCalleeIID;
+ }
+
+ /**
+ * Returns the name of the interface that returned the error
+ *
+ * This method returns a non-null name only if the instance was created
+ * using #template <class I> ErrorInfo(I *i) or
+ * template <class I> ErrorInfo(const ComPtr<I> &i) constructor.
+ */
+ const Bstr& getCalleeName() const
+ {
+ return mCalleeName;
+ }
+
+ /**
+ * Resets all collected error information. #isBasicAvailable() and
+ * #isFullAvailable will return @c true after this method is called.
+ */
+ void setNull()
+ {
+ cleanup();
+ }
+
+protected:
+
+ ErrorInfo(bool /* aDummy */)
+ : mIsBasicAvailable(false),
+ mIsFullAvailable(false),
+ mResultCode(S_OK),
+ m_pNext(NULL)
+ { }
+
+ void copyFrom(const ErrorInfo &x);
+ void cleanup();
+
+ void init(bool aKeepObj = false);
+ void init(IUnknown *aUnk, const GUID &aIID, bool aKeepObj = false);
+ void init(IVirtualBoxErrorInfo *aInfo);
+
+ bool mIsBasicAvailable : 1;
+ bool mIsFullAvailable : 1;
+
+ HRESULT mResultCode;
+ Guid mInterfaceID;
+ Bstr mComponent;
+ Bstr mText;
+
+ ErrorInfo *m_pNext;
+
+ Bstr mInterfaceName;
+ Guid mCalleeIID;
+ Bstr mCalleeName;
+
+ ComPtr<IUnknown> mErrorInfo;
+};
+
+/**
+ * A convenience subclass of ErrorInfo that, given an IProgress interface
+ * pointer, reads its errorInfo attribute and uses the returned
+ * IVirtualBoxErrorInfo instance to construct itself.
+ */
+class ProgressErrorInfo : public ErrorInfo
+{
+public:
+
+ /**
+ * Constructs a new instance by fetching error information from the
+ * IProgress interface pointer. If the progress object is not NULL,
+ * its completed attribute is true, resultCode represents a failure,
+ * and the errorInfo attribute returns a valid IVirtualBoxErrorInfo pointer,
+ * both #isFullAvailable() and #isBasicAvailable() will return true.
+ *
+ * @param progress the progress object representing a failed operation
+ */
+ ProgressErrorInfo(IProgress *progress);
+};
+
+/**
+ * A convenience subclass of ErrorInfo that allows to preserve the current
+ * error info. Instances of this class fetch an error info object set on the
+ * current thread and keep a reference to it, which allows to restore it
+ * later using the #restore() method. This is useful to preserve error
+ * information returned by some method for the duration of making another COM
+ * call that may set its own error info and overwrite the existing
+ * one. Preserving and restoring error information makes sense when some
+ * method wants to return error information set by other call as its own
+ * error information while it still needs to make another call before return.
+ *
+ * Instead of calling #restore() explicitly you may let the object destructor
+ * do it for you, if you correctly limit the object's lifetime.
+ *
+ * The usage pattern is:
+ * <code>
+ * rc = foo->method();
+ * if (FAILED(rc))
+ * {
+ * ErrorInfoKeeper eik;
+ * ...
+ * // bar may return error info as well
+ * bar->method();
+ * ...
+ * // no need to call #restore() explicitly here because the eik's
+ * // destructor will restore error info fetched after the failed
+ * // call to foo before returning to the caller
+ * return rc;
+ * }
+ * </code>
+ */
+class ErrorInfoKeeper : public ErrorInfo
+{
+public:
+
+ /**
+ * Constructs a new instance that will fetch the current error info if
+ * @a aIsNull is @c false (by default) or remain uninitialized (null)
+ * otherwise.
+ *
+ * @param aIsNull @c true to prevent fetching error info and leave
+ * the instance uninitialized.
+ */
+ ErrorInfoKeeper(bool aIsNull = false)
+ : ErrorInfo(false), mForgot(aIsNull)
+ {
+ if (!aIsNull)
+ init(true /* aKeepObj */);
+ }
+
+ /**
+ * Destroys this instance and automatically calls #restore() which will
+ * either restore error info fetched by the constructor or do nothing
+ * if #forget() was called before destruction.
+ */
+ ~ErrorInfoKeeper() { if (!mForgot) restore(); }
+
+ /**
+ * Tries to (re-)fetch error info set on the current thread. On success,
+ * the previous error information, if any, will be overwritten with the
+ * new error information. On failure, or if there is no error information
+ * available, this instance will be reset to null.
+ */
+ void fetch()
+ {
+ setNull();
+ mForgot = false;
+ init(true /* aKeepObj */);
+ }
+
+ /**
+ * Restores error info fetched by the constructor and forgets it
+ * afterwards. Does nothing if the error info was forgotten by #forget().
+ *
+ * @return COM result of the restore operation.
+ */
+ HRESULT restore();
+
+ /**
+ * Forgets error info fetched by the constructor to prevent it from
+ * being restored by #restore() or by the destructor.
+ */
+ void forget() { mForgot = true; }
+
+ /**
+ * Forgets error info fetched by the constructor to prevent it from
+ * being restored by #restore() or by the destructor, and returns the
+ * stored error info object to the caller.
+ */
+ ComPtr<IUnknown> takeError() { mForgot = true; return mErrorInfo; }
+
+private:
+
+ bool mForgot : 1;
+};
+
+} /* namespace com */
+
+#endif
+
diff --git a/include/VBox/com/EventQueue.h b/include/VBox/com/EventQueue.h
new file mode 100644
index 00000000..14f4fc84
--- /dev/null
+++ b/include/VBox/com/EventQueue.h
@@ -0,0 +1,140 @@
+/** @file
+ * MS COM / XPCOM Abstraction Layer:
+ * Event and EventQueue class declaration
+ */
+
+/*
+ * Copyright (C) 2006-2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_com_EventQueue_h
+#define ___VBox_com_EventQueue_h
+
+#ifndef VBOX_WITH_XPCOM
+# include <Windows.h>
+#else // VBOX_WITH_XPCOM
+# include <nsEventQueueUtils.h>
+#endif // VBOX_WITH_XPCOM
+
+#include <VBox/com/defs.h>
+#include <VBox/com/assert.h>
+
+namespace com
+{
+
+class EventQueue;
+
+/**
+ * Base class for all events. Intended to be subclassed to introduce new
+ * events and handlers for them.
+ *
+ * Subclasses usually reimplement virtual #handler() (that does nothing by
+ * default) and add new data members describing the event.
+ */
+class Event
+{
+public:
+
+ Event() {}
+ virtual ~Event() {};
+
+protected:
+
+ /**
+ * Event handler. Called in the context of the event queue's thread.
+ * Always reimplemented by subclasses
+ *
+ * @return reserved, should be NULL.
+ */
+ virtual void *handler() { return NULL; }
+
+ friend class EventQueue;
+};
+
+/**
+ * Simple event queue.
+ *
+ * When using XPCOM, this will map onto the default XPCOM queue for the thread.
+ * So, if a queue is created on the main thread, it automatically processes
+ * XPCOM/IPC events while waiting.
+ *
+ * When using Windows, Darwin and OS/2, this will map onto the native thread
+ * queue/runloop. So, windows messages and what not will be processed while
+ * waiting for events.
+ *
+ * @note It is intentional that there is no way to retrieve arbitrary
+ * events and controlling their processing. There is no use case which
+ * warrants introducing the complexity of platform independent events.
+ */
+class EventQueue
+{
+public:
+
+ EventQueue();
+ ~EventQueue();
+
+ BOOL postEvent(Event *event);
+ int processEventQueue(RTMSINTERVAL cMsTimeout);
+ int interruptEventQueueProcessing();
+ int getSelectFD();
+ static int init();
+ static int uninit();
+ static EventQueue *getMainEventQueue();
+
+#ifdef VBOX_WITH_XPCOM
+ already_AddRefed<nsIEventQueue> getIEventQueue()
+ {
+ return mEventQ.get();
+ }
+#else
+ static int dispatchMessageOnWindows(MSG const *pMsg, int rc);
+#endif
+
+private:
+ static EventQueue *sMainQueue;
+
+#ifndef VBOX_WITH_XPCOM
+
+ /** The thread which the queue belongs to. */
+ DWORD mThreadId;
+ /** Duplicated thread handle for MsgWaitForMultipleObjects. */
+ HANDLE mhThread;
+
+#else // VBOX_WITH_XPCOM
+
+ /** Whether it was created (and thus needs destroying) or if a queue already
+ * associated with the thread was used. */
+ bool mEQCreated;
+
+ /** Whether event processing should be interrupted. */
+ bool mInterrupted;
+
+ nsCOMPtr <nsIEventQueue> mEventQ;
+ nsCOMPtr <nsIEventQueueService> mEventQService;
+
+ static void *PR_CALLBACK plEventHandler(PLEvent *self);
+ static void PR_CALLBACK plEventDestructor(PLEvent *self);
+
+#endif // VBOX_WITH_XPCOM
+};
+
+} /* namespace com */
+
+#endif
diff --git a/include/VBox/com/Guid.h b/include/VBox/com/Guid.h
new file mode 100644
index 00000000..c55d69dc
--- /dev/null
+++ b/include/VBox/com/Guid.h
@@ -0,0 +1,353 @@
+/* $Id: Guid.h $ */
+/** @file
+ * MS COM / XPCOM Abstraction Layer - Guid class declaration.
+ */
+
+/*
+ * Copyright (C) 2006-2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_com_Guid_h
+#define ___VBox_com_Guid_h
+
+/* Make sure all the stdint.h macros are included - must come first! */
+#ifndef __STDC_LIMIT_MACROS
+# define __STDC_LIMIT_MACROS
+#endif
+#ifndef __STDC_CONSTANT_MACROS
+# define __STDC_CONSTANT_MACROS
+#endif
+
+#if defined(VBOX_WITH_XPCOM)
+# include <nsMemory.h>
+#endif
+
+#include "VBox/com/string.h"
+
+#include <iprt/uuid.h>
+#include <iprt/err.h>
+
+namespace com
+{
+
+/**
+ * Helper class that represents the UUID type and hides platform-specific
+ * implementation details.
+ */
+class Guid
+{
+public:
+
+ Guid()
+ {
+ ::RTUuidClear(&mUuid);
+ refresh();
+ }
+
+ Guid(const Guid &that)
+ {
+ mUuid = that.mUuid;
+ refresh();
+ }
+
+ Guid(const RTUUID &that)
+ {
+ mUuid = that;
+ refresh();
+ }
+
+ Guid(const GUID &that)
+ {
+ AssertCompileSize(GUID, sizeof(RTUUID));
+ ::memcpy(&mUuid, &that, sizeof(GUID));
+ refresh();
+ }
+
+ /**
+ * Construct a GUID from a string.
+ *
+ * Should the string be invalid, the object will be set to the null GUID
+ * (isEmpty() == true).
+ *
+ * @param that The UUID string. We feed this to RTUuidFromStr(),
+ * so check it out for the exact format.
+ */
+ Guid(const char *that)
+ {
+ int rc = ::RTUuidFromStr(&mUuid, that);
+ if (RT_FAILURE(rc))
+ ::RTUuidClear(&mUuid);
+ refresh();
+ }
+
+ /**
+ * Construct a GUID from a BSTR.
+ *
+ * Should the string be empty or invalid, the object will be set to the
+ * null GUID (isEmpty() == true).
+ *
+ * @param that The UUID BSTR. We feed this to RTUuidFromUtf16(),
+ * so check it out for the exact format.
+ */
+ Guid(const Bstr &that)
+ {
+ int rc = !that.isEmpty()
+ ? ::RTUuidFromUtf16(&mUuid, that.raw())
+ : VERR_INVALID_UUID_FORMAT;
+ if (RT_FAILURE(rc))
+ ::RTUuidClear(&mUuid);
+ refresh();
+ }
+
+ Guid& operator=(const Guid &that)
+ {
+ ::memcpy(&mUuid, &that.mUuid, sizeof (RTUUID));
+ refresh();
+ return *this;
+ }
+ Guid& operator=(const GUID &guid)
+ {
+ ::memcpy(&mUuid, &guid, sizeof (GUID));
+ refresh();
+ return *this;
+ }
+ Guid& operator=(const RTUUID &guid)
+ {
+ ::memcpy(&mUuid, &guid, sizeof (RTUUID));
+ refresh();
+ return *this;
+ }
+ Guid& operator=(const char *str)
+ {
+ int rc = ::RTUuidFromStr(&mUuid, str);
+ if (RT_FAILURE(rc))
+ ::RTUuidClear(&mUuid);
+ refresh();
+ return *this;
+ }
+
+ void create()
+ {
+ ::RTUuidCreate(&mUuid);
+ refresh();
+ }
+ void clear()
+ {
+ ::RTUuidClear(&mUuid);
+ refresh();
+ }
+
+ /**
+ * Convert the GUID to a string.
+ *
+ * @returns String object containing the formatted GUID.
+ * @throws std::bad_alloc
+ */
+ Utf8Str toString() const
+ {
+ char buf[RTUUID_STR_LENGTH];
+ ::RTUuidToStr(&mUuid, buf, RTUUID_STR_LENGTH);
+ return Utf8Str(buf);
+ }
+
+ /**
+ * Like toString, but encloses the returned string in curly brackets.
+ *
+ * @returns String object containing the formatted GUID in curly brackets.
+ * @throws std::bad_alloc
+ */
+ Utf8Str toStringCurly() const
+ {
+ char buf[RTUUID_STR_LENGTH + 2] = "{";
+ ::RTUuidToStr(&mUuid, buf + 1, RTUUID_STR_LENGTH);
+ buf[sizeof(buf) - 2] = '}';
+ buf[sizeof(buf) - 1] = '\0';
+ return Utf8Str(buf);
+ }
+
+ /**
+ * Convert the GUID to a string.
+ *
+ * @returns Bstr object containing the formatted GUID.
+ * @throws std::bad_alloc
+ */
+ Bstr toUtf16() const
+ {
+ if (isEmpty())
+ return Bstr();
+
+ RTUTF16 buf[RTUUID_STR_LENGTH];
+ ::RTUuidToUtf16(&mUuid, buf, RTUUID_STR_LENGTH);
+ return Bstr(buf);
+ }
+
+ bool isEmpty() const
+ {
+ return ::RTUuidIsNull(&mUuid);
+ }
+
+ bool isNotEmpty() const
+ {
+ return !::RTUuidIsNull(&mUuid);
+ }
+
+ bool operator==(const Guid &that) const { return ::RTUuidCompare(&mUuid, &that.mUuid) == 0; }
+ bool operator==(const GUID &guid) const { return ::RTUuidCompare(&mUuid, (PRTUUID)&guid) == 0; }
+ bool operator!=(const Guid &that) const { return !operator==(that); }
+ bool operator!=(const GUID &guid) const { return !operator==(guid); }
+ bool operator<( const Guid &that) const { return ::RTUuidCompare(&mUuid, &that.mUuid) < 0; }
+ bool operator<( const GUID &guid) const { return ::RTUuidCompare(&mUuid, (PRTUUID)&guid) < 0; }
+
+ /**
+ * To directly copy the contents to a GUID, or for passing it as an input
+ * parameter of type (const GUID *), the compiler converts. */
+ const GUID &ref() const
+ {
+ return *(const GUID *)&mUuid;
+ }
+
+ /**
+ * To pass instances to printf-like functions.
+ */
+ PCRTUUID raw() const
+ {
+ return (PCRTUUID)&mUuid;
+ }
+
+#if !defined(VBOX_WITH_XPCOM)
+
+ /** To assign instances to OUT_GUID parameters from within the interface
+ * method. */
+ const Guid &cloneTo(GUID *pguid) const
+ {
+ if (pguid)
+ ::memcpy(pguid, &mUuid, sizeof(GUID));
+ return *this;
+ }
+
+ /** To pass instances as OUT_GUID parameters to interface methods. */
+ GUID *asOutParam()
+ {
+ return (GUID *)&mUuid;
+ }
+
+#else
+
+ /** To assign instances to OUT_GUID parameters from within the
+ * interface method */
+ const Guid &cloneTo(nsID **ppGuid) const
+ {
+ if (ppGuid)
+ *ppGuid = (nsID *)nsMemory::Clone(&mUuid, sizeof(nsID));
+ return *this;
+ }
+
+ /**
+ * Internal helper class for asOutParam().
+ *
+ * This takes a GUID refrence in the constructor and copies the mUuid from
+ * the method to that instance in its destructor.
+ */
+ class GuidOutParam
+ {
+ GuidOutParam(Guid &guid)
+ : ptr(0),
+ outer(guid)
+ {
+ outer.clear();
+ }
+
+ nsID *ptr;
+ Guid &outer;
+ GuidOutParam(const GuidOutParam &that); // disabled
+ GuidOutParam &operator=(const GuidOutParam &that); // disabled
+ public:
+ operator nsID**() { return &ptr; }
+ ~GuidOutParam()
+ {
+ if (ptr && outer.isEmpty())
+ {
+ outer = *ptr;
+ outer.refresh();
+ nsMemory::Free(ptr);
+ }
+ }
+ friend class Guid;
+ };
+
+ /** to pass instances as OUT_GUID parameters to interface methods */
+ GuidOutParam asOutParam() { return GuidOutParam(*this); }
+
+#endif
+
+ /* to directly test IN_GUID interface method's parameters */
+ static bool isEmpty(const GUID &guid)
+ {
+ return ::RTUuidIsNull((PRTUUID)&guid);
+ }
+
+ /**
+ * Static immutable empty object. May be used for comparison purposes.
+ */
+ static const Guid Empty;
+
+private:
+ /**
+ * Refresh the debug-only UUID string.
+ *
+ * In debug code, refresh the UUID string representatino for debugging;
+ * must be called every time the internal uuid changes; compiles to nothing
+ * in release code.
+ */
+ inline void refresh()
+ {
+#ifdef DEBUG
+ ::RTUuidToStr(&mUuid, mszUuid, RTUUID_STR_LENGTH);
+ m_pcszUUID = mszUuid;
+#endif
+ }
+
+ /** The UUID. */
+ RTUUID mUuid;
+
+#ifdef DEBUG
+ /** String representation of mUuid for printing in the debugger. */
+ char mszUuid[RTUUID_STR_LENGTH];
+ /** Another string variant for the debugger, points to szUUID. */
+ const char *m_pcszUUID;
+#endif
+};
+
+inline Bstr asGuidStr(const Bstr& str)
+{
+ Guid guid(str);
+ return guid.isEmpty() ? Bstr() : guid.toUtf16();
+}
+
+inline bool isValidGuid(const Bstr& str)
+{
+ Guid guid(str);
+ return !guid.isEmpty();
+}
+
+} /* namespace com */
+
+#endif /* !___VBox_com_Guid_h */
+
diff --git a/include/VBox/com/Makefile.kup b/include/VBox/com/Makefile.kup
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/include/VBox/com/Makefile.kup
diff --git a/include/VBox/com/MultiResult.h b/include/VBox/com/MultiResult.h
new file mode 100644
index 00000000..705e1dbe
--- /dev/null
+++ b/include/VBox/com/MultiResult.h
@@ -0,0 +1,262 @@
+/* $Id: MultiResult.h $ */
+
+/** @file
+ * MS COM / XPCOM Abstraction Layer:
+ * MultiResult class declarations
+ */
+
+/*
+ * Copyright (C) 2008-2012 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_com_MultiResult_h
+#define ___VBox_com_MultiResult_h
+
+#include "VBox/com/defs.h"
+#include "VBox/com/string.h"
+
+#include <stdarg.h>
+
+namespace com
+{
+
+/**
+ * "First worst" result type.
+ *
+ * Variables of this class are used instead of HRESULT variables when it is
+ * desirable to memorize the "first worst" result code instead of the last
+ * assigned one. In other words, an assignment operation to a variable of this
+ * class will succeed only if the result code to assign has worse severity. The
+ * following table demonstrate this (the first column lists the previous result
+ * code stored in the variable, the first row lists the new result code being
+ * assigned, 'A' means the assignment will take place, '> S_OK' means a warning
+ * result code):
+ *
+ * {{{
+ * FAILED > S_OK S_OK
+ * FAILED - - -
+ * > S_OK A - -
+ * S_OK A A -
+ *
+ * }}}
+ *
+ * In practice, you will need to use a FWResult variable when you call some COM
+ * method B after another COM method A fails and want to return the result code
+ * of A even if B also fails, but want to return the failed result code of B if
+ * A issues a warning or succeeds.
+ */
+class FWResult
+{
+
+public:
+
+ /**
+ * Constructs a new variable. Note that by default this constructor sets the
+ * result code to E_FAIL to make sure a failure is returned to the caller if
+ * the variable is never assigned another value (which is considered as the
+ * improper use of this class).
+ */
+ FWResult (HRESULT aRC = E_FAIL) : mRC (aRC) {}
+
+ FWResult &operator= (HRESULT aRC)
+ {
+ if ((FAILED (aRC) && !FAILED (mRC)) ||
+ (mRC == S_OK && aRC != S_OK))
+ mRC = aRC;
+
+ return *this;
+ }
+
+ operator HRESULT() const { return mRC; }
+
+ HRESULT *operator&() { return &mRC; }
+
+private:
+
+ HRESULT mRC;
+};
+
+/**
+ * The MultiResult class is a com::FWResult enhancement that also acts as a
+ * switch to turn on multi-error mode for VirtualBoxBase::setError() and
+ * VirtualBoxBase::setWarning() calls.
+ *
+ * When an instance of this class is created, multi-error mode is turned on
+ * for the current thread and the turn-on counter is increased by one. In
+ * multi-error mode, a call to setError() or setWarning() does not
+ * overwrite the current error or warning info object possibly set on the
+ * current thread by other method calls, but instead it stores this old
+ * object in the IVirtualBoxErrorInfo::next attribute of the new error
+ * object being set.
+ *
+ * This way, error/warning objects are stacked together and form a chain of
+ * errors where the most recent error is the first one retrieved by the
+ * calling party, the preceding error is what the
+ * IVirtualBoxErrorInfo::next attribute of the first error points to, and so
+ * on, up to the first error or warning occurred which is the last in the
+ * chain. See IVirtualBoxErrorInfo documentation for more info.
+ *
+ * When the instance of the MultiResult class goes out of scope and gets
+ * destroyed, it automatically decreases the turn-on counter by one. If
+ * the counter drops to zero, multi-error mode for the current thread is
+ * turned off and the thread switches back to single-error mode where every
+ * next error or warning object overwrites the previous one.
+ *
+ * Note that the caller of a COM method uses a non-S_OK result code to
+ * decide if the method has returned an error (negative codes) or a warning
+ * (positive non-zero codes) and will query extended error info only in
+ * these two cases. However, since multi-error mode implies that the method
+ * doesn't return control return to the caller immediately after the first
+ * error or warning but continues its execution, the functionality provided
+ * by the base com::FWResult class becomes very useful because it allows to
+ * preserve the error or the warning result code even if it is later assigned
+ * a S_OK value multiple times. See com::FWResult for details.
+ *
+ * Here is the typical usage pattern:
+ * <code>
+
+ HRESULT Bar::method()
+ {
+ // assume multi-errors are turned off here...
+
+ if (something)
+ {
+ // Turn on multi-error mode and make sure severity is preserved
+ MultiResult rc = foo->method1();
+
+ // return on fatal error, but continue on warning or on success
+ CheckComRCReturnRC (rc);
+
+ rc = foo->method2();
+ // no matter what result, stack it and continue
+
+ // ...
+
+ // return the last worst result code (it will be preserved even if
+ // foo->method2() returns S_OK.
+ return rc;
+ }
+
+ // multi-errors are turned off here again...
+
+ return S_OK;
+ }
+
+ * </code>
+ *
+ * @note This class is intended to be instantiated on the stack, therefore
+ * You cannot create them using new(). Although it is possible to copy
+ * instances of MultiResult or return them by value, please never do
+ * that as it is breaks the class semantics (and will assert);
+ */
+class MultiResult : public FWResult
+{
+public:
+
+ /**
+ * @copydoc FWResult::FWResult().
+ */
+ MultiResult (HRESULT aRC = E_FAIL) : FWResult (aRC) { incCounter(); }
+
+ MultiResult (const MultiResult &aThat) : FWResult (aThat)
+ {
+ /* We need this copy constructor only for GCC that wants to have
+ * it in case of expressions like |MultiResult rc = E_FAIL;|. But
+ * we assert since the optimizer should actually avoid the
+ * temporary and call the other constructor directly instead. */
+ AssertFailed();
+ }
+
+ ~MultiResult() { decCounter(); }
+
+ MultiResult &operator= (HRESULT aRC)
+ {
+ FWResult::operator= (aRC);
+ return *this;
+ }
+
+ MultiResult &operator= (const MultiResult & /* aThat */)
+ {
+ /* We need this copy constructor only for GCC that wants to have
+ * it in case of expressions like |MultiResult rc = E_FAIL;|. But
+ * we assert since the optimizer should actually avoid the
+ * temporary and call the other constructor directly instead. */
+ AssertFailed();
+ return *this;
+ }
+
+ /**
+ * Returns true if multi-mode is enabled for the current thread (i.e. at
+ * least one MultiResult instance exists on the stack somewhere).
+ * @return
+ */
+ static bool isMultiEnabled();
+
+private:
+
+ DECLARE_CLS_NEW_DELETE_NOOP(MultiResult)
+
+ static void incCounter();
+ static void decCounter();
+
+ static RTTLS sCounter;
+
+ friend class MultiResultRef;
+};
+
+/**
+ * The MultiResultRef class is equivalent to MultiResult except that it takes
+ * a reference to the existing HRESULT variable instead of maintaining its own
+ * one.
+ */
+class MultiResultRef
+{
+public:
+
+ MultiResultRef (HRESULT &aRC) : mRC (aRC) { MultiResult::incCounter(); }
+
+ ~MultiResultRef() { MultiResult::decCounter(); }
+
+ MultiResultRef &operator= (HRESULT aRC)
+ {
+ /* Copied from FWResult */
+ if ((FAILED (aRC) && !FAILED (mRC)) ||
+ (mRC == S_OK && aRC != S_OK))
+ mRC = aRC;
+
+ return *this;
+ }
+
+ operator HRESULT() const { return mRC; }
+
+ HRESULT *operator&() { return &mRC; }
+
+private:
+
+ DECLARE_CLS_NEW_DELETE_NOOP (MultiResultRef)
+
+ HRESULT &mRC;
+};
+
+
+} /* namespace com */
+
+#endif /* ___VBox_com_MultiResult_h */
+
diff --git a/include/VBox/com/VirtualBox.h b/include/VBox/com/VirtualBox.h
new file mode 100644
index 00000000..92fe1e84
--- /dev/null
+++ b/include/VBox/com/VirtualBox.h
@@ -0,0 +1,55 @@
+/** @file
+ * MS COM / XPCOM Abstraction Layer:
+ * VirtualBox COM Library definitions.
+ *
+ * Note: This is the main header file that COM/XPCOM clients
+ * include; however, it is only a wrapper around another
+ * platform-dependent include file that contains the real
+ * COM/XPCOM interface declarations. That other include file
+ * is generated automatically at build time from
+ * /src/VBox/Main/idl/VirtualBox.xidl, which contains all
+ * the VirtualBox interfaces; the include file is called
+ * VirtualBox.h on Windows hosts and VirtualBox_XPCOM.h
+ * on Linux hosts. The build process places it in
+ * out/<platform>/bin/sdk/include, from where it gets
+ * included by the rest of the VirtualBox code.
+ */
+
+/*
+ * Copyright (C) 2006-2007 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_com_VirtualBox_h
+#define ___VBox_com_VirtualBox_h
+
+// generated VirtualBox COM library definition file
+#if !defined (VBOXCOM_NOINCLUDE)
+# if !defined (VBOX_WITH_XPCOM)
+# include <VirtualBox.h>
+# else
+# include <VirtualBox_XPCOM.h>
+# endif
+#endif // !defined (VBOXCOM_NOINCLUDE)
+
+// for convenience
+#include "VBox/com/defs.h"
+#include "VBox/com/ptr.h"
+
+#endif
diff --git a/include/VBox/com/array.h b/include/VBox/com/array.h
new file mode 100644
index 00000000..7f1796d9
--- /dev/null
+++ b/include/VBox/com/array.h
@@ -0,0 +1,1702 @@
+/** @file
+ * MS COM / XPCOM Abstraction Layer:
+ * Safe array helper class declaration
+ */
+
+/*
+ * Copyright (C) 2006-2011 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_com_array_h
+#define ___VBox_com_array_h
+
+/** @defgroup grp_COM_arrays COM/XPCOM Arrays
+ * @{
+ *
+ * The COM/XPCOM array support layer provides a cross-platform way to pass
+ * arrays to and from COM interface methods and consists of the com::SafeArray
+ * template and a set of ComSafeArray* macros part of which is defined in
+ * VBox/com/defs.h.
+ *
+ * This layer works with interface attributes and method parameters that have
+ * the 'safearray="yes"' attribute in the XIDL definition:
+ * @code
+
+ <interface name="ISomething" ...>
+
+ <method name="testArrays">
+ <param name="inArr" type="long" dir="in" safearray="yes"/>
+ <param name="outArr" type="long" dir="out" safearray="yes"/>
+ <param name="retArr" type="long" dir="return" safearray="yes"/>
+ </method>
+
+ </interface>
+
+ * @endcode
+ *
+ * Methods generated from this and similar definitions are implemented in
+ * component classes using the following declarations:
+ * @code
+
+ STDMETHOD(TestArrays)(ComSafeArrayIn(LONG, aIn),
+ ComSafeArrayOut(LONG, aOut),
+ ComSafeArrayOut(LONG, aRet));
+
+ * @endcode
+ *
+ * And the following function bodies:
+ * @code
+
+ STDMETHODIMP Component::TestArrays(ComSafeArrayIn(LONG, aIn),
+ ComSafeArrayOut(LONG, aOut),
+ ComSafeArrayOut(LONG, aRet))
+ {
+ if (ComSafeArrayInIsNull(aIn))
+ return E_INVALIDARG;
+ if (ComSafeArrayOutIsNull(aOut))
+ return E_POINTER;
+ if (ComSafeArrayOutIsNull(aRet))
+ return E_POINTER;
+
+ // Use SafeArray to access the input array parameter
+
+ com::SafeArray<LONG> in(ComSafeArrayInArg(aIn));
+
+ for (size_t i = 0; i < in.size(); ++ i)
+ LogFlow(("*** in[%u]=%d\n", i, in[i]));
+
+ // Use SafeArray to create the return array (the same technique is used
+ // for output array parameters)
+
+ SafeArray<LONG> ret(in.size() * 2);
+ for (size_t i = 0; i < in.size(); ++ i)
+ {
+ ret[i] = in[i];
+ ret[i + in.size()] = in[i] * 10;
+ }
+
+ ret.detachTo(ComSafeArrayOutArg(aRet));
+
+ return S_OK;
+ }
+
+ * @endcode
+ *
+ * Such methods can be called from the client code using the following pattern:
+ * @code
+
+ ComPtr<ISomething> component;
+
+ // ...
+
+ com::SafeArray<LONG> in(3);
+ in[0] = -1;
+ in[1] = -2;
+ in[2] = -3;
+
+ com::SafeArray<LONG> out;
+ com::SafeArray<LONG> ret;
+
+ HRESULT rc = component->TestArrays(ComSafeArrayAsInParam(in),
+ ComSafeArrayAsOutParam(out),
+ ComSafeArrayAsOutParam(ret));
+
+ if (SUCCEEDED(rc))
+ for (size_t i = 0; i < ret.size(); ++ i)
+ printf("*** ret[%u]=%d\n", i, ret[i]);
+
+ * @endcode
+ *
+ * For interoperability with standard C++ containers, there is a template
+ * constructor that takes such a container as argument and performs a deep copy
+ * of its contents. This can be used in method implementations like this:
+ * @code
+
+ STDMETHODIMP Component::COMGETTER(Values)(ComSafeArrayOut(int, aValues))
+ {
+ // ... assume there is a |std::list<int> mValues| data member
+
+ com::SafeArray<int> values(mValues);
+ values.detachTo(ComSafeArrayOutArg(aValues));
+
+ return S_OK;
+ }
+
+ * @endcode
+ *
+ * The current implementation of the SafeArray layer supports all types normally
+ * allowed in XIDL as array element types (including 'wstring' and 'uuid').
+ * However, 'pointer-to-...' types (e.g. 'long *', 'wstring *') are not
+ * supported and therefore cannot be used as element types.
+ *
+ * Note that for GUID arrays you should use SafeGUIDArray and
+ * SafeConstGUIDArray, customized SafeArray<> specializations.
+ *
+ * Also note that in order to pass input BSTR array parameters declared
+ * using the ComSafeArrayIn(IN_BSTR, aParam) macro to the SafeArray<>
+ * constructor using the ComSafeArrayInArg() macro, you should use IN_BSTR
+ * as the SafeArray<> template argument, not just BSTR.
+ *
+ * Arrays of interface pointers are also supported but they require to use a
+ * special SafeArray implementation, com::SafeIfacePointer, which takes the
+ * interface class name as a template argument (e.g. com::SafeIfacePointer
+ * <IUnknown>). This implementation functions identically to com::SafeArray.
+ */
+
+#ifdef VBOX_WITH_XPCOM
+# include <nsMemory.h>
+#endif
+
+#include "VBox/com/defs.h"
+#include "VBox/com/ptr.h"
+#include "VBox/com/assert.h"
+#include "iprt/cpp/list.h"
+
+#ifdef VBOX_WITH_XPCOM
+
+/**
+ * Wraps the given com::SafeArray instance to generate an expression that is
+ * suitable for passing it to functions that take input safearray parameters
+ * declared using the ComSafeArrayIn macro.
+ *
+ * @param aArray com::SafeArray instance to pass as an input parameter.
+ */
+#define ComSafeArrayAsInParam(aArray) \
+ (aArray).size(), (aArray).__asInParam_Arr((aArray).raw())
+
+/**
+ * Wraps the given com::SafeArray instance to generate an expression that is
+ * suitable for passing it to functions that take output safearray parameters
+ * declared using the ComSafeArrayOut macro.
+ *
+ * @param aArray com::SafeArray instance to pass as an output parameter.
+ */
+#define ComSafeArrayAsOutParam(aArray) \
+ (aArray).__asOutParam_Size(), (aArray).__asOutParam_Arr()
+
+#else /* !VBOX_WITH_XPCOM */
+
+#define ComSafeArrayAsInParam(aArray) (aArray).__asInParam()
+
+#define ComSafeArrayAsOutParam(aArray) (aArray).__asOutParam()
+
+#endif /* !VBOX_WITH_XPCOM */
+
+/**
+ *
+ */
+namespace com
+{
+
+#ifdef VBOX_WITH_XPCOM
+
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Provides various helpers for SafeArray.
+ *
+ * @param T Type of array elements.
+ */
+template<typename T>
+struct SafeArrayTraits
+{
+protected:
+
+ /** Initializes memory for aElem. */
+ static void Init(T &aElem) { aElem = 0; }
+
+ /** Initializes memory occupied by aElem. */
+ static void Uninit(T &aElem) { aElem = 0; }
+
+ /** Creates a deep copy of aFrom and stores it in aTo. */
+ static void Copy(const T &aFrom, T &aTo) { aTo = aFrom; }
+
+public:
+
+ /* Magic to workaround strict rules of par. 4.4.4 of the C++ standard (that
+ * in particular forbid casts of 'char **' to 'const char **'). Then initial
+ * reason for this magic is that XPIDL declares input strings
+ * (char/PRUnichar pointers) as const but doesn't do so for pointers to
+ * arrays. */
+ static T *__asInParam_Arr(T *aArr) { return aArr; }
+ static T *__asInParam_Arr(const T *aArr) { return const_cast<T *>(aArr); }
+};
+
+template<typename T>
+struct SafeArrayTraits<T *>
+{
+ // Arbitrary pointers are not supported
+};
+
+template<>
+struct SafeArrayTraits<PRUnichar *>
+{
+protected:
+
+ static void Init(PRUnichar * &aElem) { aElem = NULL; }
+
+ static void Uninit(PRUnichar * &aElem)
+ {
+ if (aElem)
+ {
+ ::SysFreeString(aElem);
+ aElem = NULL;
+ }
+ }
+
+ static void Copy(const PRUnichar * aFrom, PRUnichar * &aTo)
+ {
+ AssertCompile(sizeof(PRUnichar) == sizeof(OLECHAR));
+ aTo = aFrom ? ::SysAllocString((const OLECHAR *)aFrom) : NULL;
+ }
+
+public:
+
+ /* Magic to workaround strict rules of par. 4.4.4 of the C++ standard */
+ static const PRUnichar **__asInParam_Arr(PRUnichar **aArr)
+ {
+ return const_cast<const PRUnichar **>(aArr);
+ }
+ static const PRUnichar **__asInParam_Arr(const PRUnichar **aArr) { return aArr; }
+};
+
+template<>
+struct SafeArrayTraits<const PRUnichar *>
+{
+protected:
+
+ static void Init(const PRUnichar * &aElem) { aElem = NULL; }
+ static void Uninit(const PRUnichar * &aElem)
+ {
+ if (aElem)
+ {
+ ::SysFreeString(const_cast<PRUnichar *>(aElem));
+ aElem = NULL;
+ }
+ }
+
+ static void Copy(const PRUnichar * aFrom, const PRUnichar * &aTo)
+ {
+ AssertCompile(sizeof(PRUnichar) == sizeof(OLECHAR));
+ aTo = aFrom ? ::SysAllocString((const OLECHAR *)aFrom) : NULL;
+ }
+
+public:
+
+ /* Magic to workaround strict rules of par. 4.4.4 of the C++ standard */
+ static const PRUnichar **__asInParam_Arr(const PRUnichar **aArr) { return aArr; }
+};
+
+template<>
+struct SafeArrayTraits<nsID *>
+{
+protected:
+
+ static void Init(nsID * &aElem) { aElem = NULL; }
+
+ static void Uninit(nsID * &aElem)
+ {
+ if (aElem)
+ {
+ ::nsMemory::Free(aElem);
+ aElem = NULL;
+ }
+ }
+
+ static void Copy(const nsID * aFrom, nsID * &aTo)
+ {
+ if (aFrom)
+ {
+ aTo = (nsID *) ::nsMemory::Alloc(sizeof(nsID));
+ if (aTo)
+ *aTo = *aFrom;
+ }
+ else
+ aTo = NULL;
+ }
+
+ /* This specification is also reused for SafeConstGUIDArray, so provide a
+ * no-op Init() and Uninit() which are necessary for SafeArray<> but should
+ * be never called in context of SafeConstGUIDArray. */
+
+ static void Init(const nsID * &aElem) { NOREF(aElem); AssertFailed(); }
+ static void Uninit(const nsID * &aElem) { NOREF(aElem); AssertFailed(); }
+
+public:
+
+ /** Magic to workaround strict rules of par. 4.4.4 of the C++ standard. */
+ static const nsID **__asInParam_Arr(nsID **aArr)
+ {
+ return const_cast<const nsID **>(aArr);
+ }
+ static const nsID **__asInParam_Arr(const nsID **aArr) { return aArr; }
+};
+
+#else /* !VBOX_WITH_XPCOM */
+
+////////////////////////////////////////////////////////////////////////////////
+
+struct SafeArrayTraitsBase
+{
+protected:
+
+ static SAFEARRAY *CreateSafeArray(VARTYPE aVarType, SAFEARRAYBOUND *aBound)
+ { return SafeArrayCreate(aVarType, 1, aBound); }
+};
+
+/**
+ * Provides various helpers for SafeArray.
+ *
+ * @param T Type of array elements.
+ *
+ * Specializations of this template must provide the following methods:
+ *
+ // Returns the VARTYPE of COM SafeArray elements to be used for T
+ static VARTYPE VarType();
+
+ // Returns the number of VarType() elements necessary for aSize
+ // elements of T
+ static ULONG VarCount(size_t aSize);
+
+ // Returns the number of elements of T that fit into the given number of
+ // VarType() elements (opposite to VarCount(size_t aSize)).
+ static size_t Size(ULONG aVarCount);
+
+ // Creates a deep copy of aFrom and stores it in aTo
+ static void Copy(ULONG aFrom, ULONG &aTo);
+ */
+template<typename T>
+struct SafeArrayTraits : public SafeArrayTraitsBase
+{
+protected:
+
+ // Arbitrary types are treated as passed by value and each value is
+ // represented by a number of VT_Ix type elements where VT_Ix has the
+ // biggest possible bitness necessary to represent T w/o a gap. COM enums
+ // fall into this category.
+
+ static VARTYPE VarType()
+ {
+ if (sizeof(T) % 8 == 0) return VT_I8;
+ if (sizeof(T) % 4 == 0) return VT_I4;
+ if (sizeof(T) % 2 == 0) return VT_I2;
+ return VT_I1;
+ }
+
+ static ULONG VarCount(size_t aSize)
+ {
+ if (sizeof(T) % 8 == 0) return (ULONG)((sizeof(T) / 8) * aSize);
+ if (sizeof(T) % 4 == 0) return (ULONG)((sizeof(T) / 4) * aSize);
+ if (sizeof(T) % 2 == 0) return (ULONG)((sizeof(T) / 2) * aSize);
+ return (ULONG)(sizeof(T) * aSize);
+ }
+
+ static size_t Size(ULONG aVarCount)
+ {
+ if (sizeof(T) % 8 == 0) return (size_t)(aVarCount * 8) / sizeof(T);
+ if (sizeof(T) % 4 == 0) return (size_t)(aVarCount * 4) / sizeof(T);
+ if (sizeof(T) % 2 == 0) return (size_t)(aVarCount * 2) / sizeof(T);
+ return (size_t) aVarCount / sizeof(T);
+ }
+
+ static void Copy(T aFrom, T &aTo) { aTo = aFrom; }
+};
+
+template<typename T>
+struct SafeArrayTraits<T *>
+{
+ // Arbitrary pointer types are not supported
+};
+
+/* Although the generic SafeArrayTraits template would work for all integers,
+ * we specialize it for some of them in order to use the correct VT_ type */
+
+template<>
+struct SafeArrayTraits<LONG> : public SafeArrayTraitsBase
+{
+protected:
+
+ static VARTYPE VarType() { return VT_I4; }
+ static ULONG VarCount(size_t aSize) { return (ULONG)aSize; }
+ static size_t Size(ULONG aVarCount) { return (size_t)aVarCount; }
+
+ static void Copy(LONG aFrom, LONG &aTo) { aTo = aFrom; }
+};
+
+template<>
+struct SafeArrayTraits<ULONG> : public SafeArrayTraitsBase
+{
+protected:
+
+ static VARTYPE VarType() { return VT_UI4; }
+ static ULONG VarCount(size_t aSize) { return (ULONG)aSize; }
+ static size_t Size(ULONG aVarCount) { return (size_t)aVarCount; }
+
+ static void Copy(ULONG aFrom, ULONG &aTo) { aTo = aFrom; }
+};
+
+template<>
+struct SafeArrayTraits<LONG64> : public SafeArrayTraitsBase
+{
+protected:
+
+ static VARTYPE VarType() { return VT_I8; }
+ static ULONG VarCount(size_t aSize) { return (ULONG)aSize; }
+ static size_t Size(ULONG aVarCount) { return (size_t)aVarCount; }
+
+ static void Copy(LONG64 aFrom, LONG64 &aTo) { aTo = aFrom; }
+};
+
+template<>
+struct SafeArrayTraits<ULONG64> : public SafeArrayTraitsBase
+{
+protected:
+
+ static VARTYPE VarType() { return VT_UI8; }
+ static ULONG VarCount(size_t aSize) { return (ULONG)aSize; }
+ static size_t Size(ULONG aVarCount) { return (size_t)aVarCount; }
+
+ static void Copy(ULONG64 aFrom, ULONG64 &aTo) { aTo = aFrom; }
+};
+
+template<>
+struct SafeArrayTraits<BSTR> : public SafeArrayTraitsBase
+{
+protected:
+
+ static VARTYPE VarType() { return VT_BSTR; }
+ static ULONG VarCount(size_t aSize) { return (ULONG)aSize; }
+ static size_t Size(ULONG aVarCount) { return (size_t)aVarCount; }
+
+ static void Copy(BSTR aFrom, BSTR &aTo)
+ {
+ aTo = aFrom ? ::SysAllocString((const OLECHAR *)aFrom) : NULL;
+ }
+};
+
+template<>
+struct SafeArrayTraits<GUID> : public SafeArrayTraitsBase
+{
+protected:
+
+ /* Use the 64-bit unsigned integer type for GUID */
+ static VARTYPE VarType() { return VT_UI8; }
+
+ /* GUID is 128 bit, so we need two VT_UI8 */
+ static ULONG VarCount(size_t aSize)
+ {
+ AssertCompileSize(GUID, 16);
+ return (ULONG)(aSize * 2);
+ }
+
+ static size_t Size(ULONG aVarCount) { return (size_t)aVarCount / 2; }
+
+ static void Copy(GUID aFrom, GUID &aTo) { aTo = aFrom; }
+};
+
+/**
+ * Helper for SafeArray::__asOutParam() that automatically updates m.raw after a
+ * non-NULL m.arr assignment.
+ */
+class OutSafeArrayDipper
+{
+ OutSafeArrayDipper(SAFEARRAY **aArr, void **aRaw)
+ : arr(aArr), raw(aRaw) { Assert(*aArr == NULL && *aRaw == NULL); }
+
+ SAFEARRAY **arr;
+ void **raw;
+
+ template<class, class> friend class SafeArray;
+
+public:
+
+ ~OutSafeArrayDipper()
+ {
+ if (*arr != NULL)
+ {
+ HRESULT rc = SafeArrayAccessData(*arr, raw);
+ AssertComRC(rc);
+ }
+ }
+
+ operator SAFEARRAY **() { return arr; }
+};
+
+#endif /* !VBOX_WITH_XPCOM */
+
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * The SafeArray class represents the safe array type used in COM to pass arrays
+ * to/from interface methods.
+ *
+ * This helper class hides all MSCOM/XPCOM specific implementation details and,
+ * together with ComSafeArrayIn, ComSafeArrayOut and ComSafeArrayRet macros,
+ * provides a platform-neutral way to handle safe arrays in the method
+ * implementation.
+ *
+ * When an instance of this class is destroyed, it automatically frees all
+ * resources occupied by individual elements of the array as well as by the
+ * array itself. However, when the value of an element is manually changed
+ * using #operator[] or by accessing array data through the #raw() pointer, it is
+ * the caller's responsibility to free resources occupied by the previous
+ * element's value.
+ *
+ * Also, objects of this class do not support copy and assignment operations and
+ * therefore cannot be returned from functions by value. In other words, this
+ * class is just a temporary storage for handling interface method calls and not
+ * intended to be used to store arrays as data members and such -- you should
+ * use normal list/vector classes for that.
+ *
+ * @note The current implementation supports only one-dimensional arrays.
+ *
+ * @note This class is not thread-safe.
+ */
+template<typename T, class Traits = SafeArrayTraits<T> >
+class SafeArray : public Traits
+{
+public:
+
+ /**
+ * Creates a null array.
+ */
+ SafeArray() {}
+
+ /**
+ * Creates a new array of the given size. All elements of the newly created
+ * array initialized with null values.
+ *
+ * @param aSize Initial number of elements in the array.
+ *
+ * @note If this object remains null after construction it means that there
+ * was not enough memory for creating an array of the requested size.
+ * The constructor will also assert in this case.
+ */
+ SafeArray(size_t aSize) { resize(aSize); }
+
+ /**
+ * Weakly attaches this instance to the existing array passed in a method
+ * parameter declared using the ComSafeArrayIn macro. When using this call,
+ * always wrap the parameter name in the ComSafeArrayInArg macro call like
+ * this:
+ * <pre>
+ * SafeArray safeArray(ComSafeArrayInArg(aArg));
+ * </pre>
+ *
+ * Note that this constructor doesn't take the ownership of the array. In
+ * particular, it means that operations that operate on the ownership (e.g.
+ * #detachTo()) are forbidden and will assert.
+ *
+ * @param aArg Input method parameter to attach to.
+ */
+ SafeArray(ComSafeArrayIn(T, aArg))
+ {
+#ifdef VBOX_WITH_XPCOM
+
+ AssertReturnVoid(aArg != NULL);
+
+ m.size = aArgSize;
+ m.arr = aArg;
+ m.isWeak = true;
+
+#else /* !VBOX_WITH_XPCOM */
+
+ AssertReturnVoid(aArg != NULL);
+ SAFEARRAY *arg = aArg;
+
+ if (arg)
+ {
+ AssertReturnVoid(arg->cDims == 1);
+
+ VARTYPE vt;
+ HRESULT rc = SafeArrayGetVartype(arg, &vt);
+ AssertComRCReturnVoid(rc);
+ AssertMsgReturnVoid(vt == VarType(),
+ ("Expected vartype %d, got %d.\n",
+ VarType(), vt));
+
+ rc = SafeArrayAccessData(arg, (void HUGEP **)&m.raw);
+ AssertComRCReturnVoid(rc);
+ }
+
+ m.arr = arg;
+ m.isWeak = true;
+
+#endif /* !VBOX_WITH_XPCOM */
+ }
+
+ /**
+ * Creates a deep copy of the given standard C++ container that stores
+ * T objects.
+ *
+ * @param aCntr Container object to copy.
+ *
+ * @param C Standard C++ container template class (normally deduced from
+ * @c aCntr).
+ */
+ template<template<typename, typename> class C, class A>
+ SafeArray(const C<T, A> & aCntr)
+ {
+ resize(aCntr.size());
+ AssertReturnVoid(!isNull());
+
+ size_t i = 0;
+ for (typename C<T, A>::const_iterator it = aCntr.begin();
+ it != aCntr.end(); ++ it, ++ i)
+#ifdef VBOX_WITH_XPCOM
+ SafeArray::Copy(*it, m.arr[i]);
+#else
+ Copy(*it, m.raw[i]);
+#endif
+ }
+
+ /**
+ * Creates a deep copy of the given standard C++ map that stores T objects
+ * as values.
+ *
+ * @param aMap Map object to copy.
+ *
+ * @param C Standard C++ map template class (normally deduced from
+ * @c aCntr).
+ * @param L Standard C++ compare class (deduced from @c aCntr).
+ * @param A Standard C++ allocator class (deduced from @c aCntr).
+ * @param K Map key class (deduced from @c aCntr).
+ */
+ template<template<typename, typename, typename, typename>
+ class C, class L, class A, class K>
+ SafeArray(const C<K, T, L, A> & aMap)
+ {
+ typedef C<K, T, L, A> Map;
+
+ resize(aMap.size());
+ AssertReturnVoid(!isNull());
+
+ int i = 0;
+ for (typename Map::const_iterator it = aMap.begin();
+ it != aMap.end(); ++ it, ++ i)
+#ifdef VBOX_WITH_XPCOM
+ Copy(it->second, m.arr[i]);
+#else
+ Copy(it->second, m.raw[i]);
+#endif
+ }
+
+ /**
+ * Destroys this instance after calling #setNull() to release allocated
+ * resources. See #setNull() for more details.
+ */
+ virtual ~SafeArray() { setNull(); }
+
+ /**
+ * Returns @c true if this instance represents a null array.
+ */
+ bool isNull() const { return m.arr == NULL; }
+
+ /**
+ * Returns @c true if this instance does not represents a null array.
+ */
+ bool isNotNull() const { return m.arr != NULL; }
+
+ /**
+ * Resets this instance to null and, if this instance is not a weak one,
+ * releases any resources occupied by the array data.
+ *
+ * @note This method destroys (cleans up) all elements of the array using
+ * the corresponding cleanup routine for the element type before the
+ * array itself is destroyed.
+ */
+ virtual void setNull() { m.uninit(); }
+
+ /**
+ * Returns @c true if this instance is weak. A weak instance doesn't own the
+ * array data and therefore operations manipulating the ownership (e.g.
+ * #detachTo()) are forbidden and will assert.
+ */
+ bool isWeak() const { return m.isWeak; }
+
+ /** Number of elements in the array. */
+ size_t size() const
+ {
+#ifdef VBOX_WITH_XPCOM
+ if (m.arr)
+ return m.size;
+ return 0;
+#else
+ if (m.arr)
+ return Size(m.arr->rgsabound[0].cElements);
+ return 0;
+#endif
+ }
+
+ /**
+ * Appends a copy of the given element at the end of the array.
+ *
+ * The array size is increased by one by this method and the additional
+ * space is allocated as needed.
+ *
+ * This method is handy in cases where you want to assign a copy of the
+ * existing value to the array element, for example:
+ * <tt>Bstr string; array.push_back(string);</tt>. If you create a string
+ * just to put it in the array, you may find #appendedRaw() more useful.
+ *
+ * @param aElement Element to append.
+ *
+ * @return @c true on success and @c false if there is not enough
+ * memory for resizing.
+ */
+ bool push_back(const T &aElement)
+ {
+ if (!ensureCapacity(size() + 1))
+ return false;
+
+#ifdef VBOX_WITH_XPCOM
+ SafeArray::Copy(aElement, m.arr[m.size]);
+ ++ m.size;
+#else
+ Copy(aElement, m.raw[size() - 1]);
+#endif
+ return true;
+ }
+
+ /**
+ * Appends an empty element at the end of the array and returns a raw
+ * pointer to it suitable for assigning a raw value (w/o constructing a
+ * copy).
+ *
+ * The array size is increased by one by this method and the additional
+ * space is allocated as needed.
+ *
+ * Note that in case of raw assignment, value ownership (for types with
+ * dynamically allocated data and for interface pointers) is transferred to
+ * the safe array object.
+ *
+ * This method is handy for operations like
+ * <tt>Bstr("foo").detachTo(array.appendedRaw());</tt>. Don't use it as
+ * an l-value (<tt>array.appendedRaw() = SysAllocString(L"tralala");</tt>)
+ * since this doesn't check for a NULL condition; use #resize() and
+ * #setRawAt() instead. If you need to assign a copy of the existing value
+ * instead of transferring the ownership, look at #push_back().
+ *
+ * @return Raw pointer to the added element or NULL if no memory.
+ */
+ T *appendedRaw()
+ {
+ if (!ensureCapacity(size() + 1))
+ return NULL;
+
+#ifdef VBOX_WITH_XPCOM
+ SafeArray::Init(m.arr[m.size]);
+ ++ m.size;
+ return &m.arr[m.size - 1];
+#else
+ /* nothing to do here, SafeArrayCreate() has performed element
+ * initialization */
+ return &m.raw[size() - 1];
+#endif
+ }
+
+ /**
+ * Resizes the array preserving its contents when possible. If the new size
+ * is larger than the old size, new elements are initialized with null
+ * values. If the new size is less than the old size, the contents of the
+ * array beyond the new size is lost.
+ *
+ * @param aNewSize New number of elements in the array.
+ * @return @c true on success and @c false if there is not enough
+ * memory for resizing.
+ */
+ bool resize(size_t aNewSize)
+ {
+ if (!ensureCapacity(aNewSize))
+ return false;
+
+#ifdef VBOX_WITH_XPCOM
+
+ if (m.size < aNewSize)
+ {
+ /* initialize the new elements */
+ for (size_t i = m.size; i < aNewSize; ++ i)
+ SafeArray::Init(m.arr[i]);
+ }
+
+ m.size = aNewSize;
+#else
+ /* nothing to do here, SafeArrayCreate() has performed element
+ * initialization */
+#endif
+ return true;
+ }
+
+ /**
+ * Reinitializes this instance by preallocating space for the given number
+ * of elements. The previous array contents is lost.
+ *
+ * @param aNewSize New number of elements in the array.
+ * @return @c true on success and @c false if there is not enough
+ * memory for resizing.
+ */
+ bool reset(size_t aNewSize)
+ {
+ m.uninit();
+ return resize(aNewSize);
+ }
+
+ /**
+ * Returns a pointer to the raw array data. Use this raw pointer with care
+ * as no type or bound checking is done for you in this case.
+ *
+ * @note This method returns @c NULL when this instance is null.
+ * @see #operator[]
+ */
+ T *raw()
+ {
+#ifdef VBOX_WITH_XPCOM
+ return m.arr;
+#else
+ return m.raw;
+#endif
+ }
+
+ /**
+ * Const version of #raw().
+ */
+ const T *raw() const
+ {
+#ifdef VBOX_WITH_XPCOM
+ return m.arr;
+#else
+ return m.raw;
+#endif
+ }
+
+ /**
+ * Array access operator that returns an array element by reference. A bit
+ * safer than #raw(): asserts and returns an invalid reference if this
+ * instance is null or if the index is out of bounds.
+ *
+ * @note For weak instances, this call will succeed but the behavior of
+ * changing the contents of an element of the weak array instance is
+ * undefined and may lead to a program crash on some platforms.
+ */
+ T &operator[] (size_t aIdx)
+ {
+ AssertReturn(m.arr != NULL, *((T *)NULL));
+ AssertReturn(aIdx < size(), *((T *)NULL));
+#ifdef VBOX_WITH_XPCOM
+ return m.arr[aIdx];
+#else
+ AssertReturn(m.raw != NULL, *((T *)NULL));
+ return m.raw[aIdx];
+#endif
+ }
+
+ /**
+ * Const version of #operator[] that returns an array element by value.
+ */
+ const T operator[] (size_t aIdx) const
+ {
+ AssertReturn(m.arr != NULL, *((T *)NULL));
+ AssertReturn(aIdx < size(), *((T *)NULL));
+#ifdef VBOX_WITH_XPCOM
+ return m.arr[aIdx];
+#else
+ AssertReturn(m.raw != NULL, *((T *)NULL));
+ return m.raw[aIdx];
+#endif
+ }
+
+ /**
+ * Creates a copy of this array and stores it in a method parameter declared
+ * using the ComSafeArrayOut macro. When using this call, always wrap the
+ * parameter name in the ComSafeArrayOutArg macro call like this:
+ * <pre>
+ * safeArray.cloneTo(ComSafeArrayOutArg(aArg));
+ * </pre>
+ *
+ * @note It is assumed that the ownership of the returned copy is
+ * transferred to the caller of the method and he is responsible to free the
+ * array data when it is no longer needed.
+ *
+ * @param aArg Output method parameter to clone to.
+ */
+ virtual const SafeArray &cloneTo(ComSafeArrayOut(T, aArg)) const
+ {
+ /// @todo Implement me!
+#ifdef VBOX_WITH_XPCOM
+ NOREF(aArgSize);
+ NOREF(aArg);
+#else
+ NOREF(aArg);
+#endif
+ AssertFailedReturn(*this);
+ }
+
+ void cloneTo(SafeArray<T>& aOther) const
+ {
+ aOther.reset(size());
+ aOther.initFrom(*this);
+ }
+
+
+ /**
+ * Transfers the ownership of this array's data to the specified location
+ * declared using the ComSafeArrayOut macro and makes this array a null
+ * array. When using this call, always wrap the parameter name in the
+ * ComSafeArrayOutArg macro call like this:
+ * <pre>
+ * safeArray.detachTo(ComSafeArrayOutArg(aArg));
+ * </pre>
+ *
+ * Detaching the null array is also possible in which case the location will
+ * receive NULL.
+ *
+ * @note Since the ownership of the array data is transferred to the
+ * caller of the method, he is responsible to free the array data when it is
+ * no longer needed.
+ *
+ * @param aArg Location to detach to.
+ */
+ virtual SafeArray &detachTo(ComSafeArrayOut(T, aArg))
+ {
+ AssertReturn(m.isWeak == false, *this);
+
+#ifdef VBOX_WITH_XPCOM
+
+ AssertReturn(aArgSize != NULL, *this);
+ AssertReturn(aArg != NULL, *this);
+
+ *aArgSize = m.size;
+ *aArg = m.arr;
+
+ m.isWeak = false;
+ m.size = 0;
+ m.arr = NULL;
+
+#else /* !VBOX_WITH_XPCOM */
+
+ AssertReturn(aArg != NULL, *this);
+ *aArg = m.arr;
+
+ if (m.raw)
+ {
+ HRESULT rc = SafeArrayUnaccessData(m.arr);
+ AssertComRCReturn(rc, *this);
+ m.raw = NULL;
+ }
+
+ m.isWeak = false;
+ m.arr = NULL;
+
+#endif /* !VBOX_WITH_XPCOM */
+
+ return *this;
+ }
+
+ /**
+ * Returns a copy of this SafeArray as RTCList<T>.
+ */
+ RTCList<T> toList()
+ {
+ RTCList<T> list(size());
+ for (size_t i = 0; i < size(); ++i)
+#ifdef VBOX_WITH_XPCOM
+ list.append(m.arr[i]);
+#else
+ list.append(m.raw[i]);
+#endif
+ return list;
+ }
+
+ inline void initFrom(const com::SafeArray<T> & aRef);
+ inline void initFrom(const T* aPtr, size_t aSize);
+
+ // Public methods for internal purposes only.
+
+#ifdef VBOX_WITH_XPCOM
+
+ /** Internal function. Never call it directly. */
+ PRUint32 *__asOutParam_Size() { setNull(); return &m.size; }
+
+ /** Internal function Never call it directly. */
+ T **__asOutParam_Arr() { Assert(isNull()); return &m.arr; }
+
+#else /* !VBOX_WITH_XPCOM */
+
+ /** Internal function Never call it directly. */
+ SAFEARRAY * __asInParam() { return m.arr; }
+
+ /** Internal function Never call it directly. */
+ OutSafeArrayDipper __asOutParam()
+ { setNull(); return OutSafeArrayDipper(&m.arr, (void **)&m.raw); }
+
+#endif /* !VBOX_WITH_XPCOM */
+
+ static const SafeArray Null;
+
+protected:
+
+ DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP(SafeArray)
+
+ /**
+ * Ensures that the array is big enough to contain aNewSize elements.
+ *
+ * If the new size is greater than the current capacity, a new array is
+ * allocated and elements from the old array are copied over. The size of
+ * the array doesn't change, only the capacity increases (which is always
+ * greater than the size). Note that the additionally allocated elements are
+ * left uninitialized by this method.
+ *
+ * If the new size is less than the current size, the existing array is
+ * truncated to the specified size and the elements outside the new array
+ * boundary are freed.
+ *
+ * If the new size is the same as the current size, nothing happens.
+ *
+ * @param aNewSize New size of the array.
+ *
+ * @return @c true on success and @c false if not enough memory.
+ */
+ bool ensureCapacity(size_t aNewSize)
+ {
+ AssertReturn(!m.isWeak, false);
+
+#ifdef VBOX_WITH_XPCOM
+
+ /* Note: we distinguish between a null array and an empty (zero
+ * elements) array. Therefore we never use zero in malloc (even if
+ * aNewSize is zero) to make sure we get a non-null pointer. */
+
+ if (m.size == aNewSize && m.arr != NULL)
+ return true;
+
+ /* Allocate in 16-byte pieces. */
+ size_t newCapacity = RT_MAX((aNewSize + 15) / 16 * 16, 16);
+
+ if (m.capacity != newCapacity)
+ {
+ T *newArr = (T *)nsMemory::Alloc(RT_MAX(newCapacity, 1) * sizeof(T));
+ AssertReturn(newArr != NULL, false);
+
+ if (m.arr != NULL)
+ {
+ if (m.size > aNewSize)
+ {
+ /* Truncation takes place, uninit exceeding elements and
+ * shrink the size. */
+ for (size_t i = aNewSize; i < m.size; ++ i)
+ SafeArray::Uninit(m.arr[i]);
+
+ m.size = aNewSize;
+ }
+
+ /* Copy the old contents. */
+ memcpy(newArr, m.arr, m.size * sizeof(T));
+ nsMemory::Free((void *)m.arr);
+ }
+
+ m.arr = newArr;
+ }
+ else
+ {
+ if (m.size > aNewSize)
+ {
+ /* Truncation takes place, uninit exceeding elements and
+ * shrink the size. */
+ for (size_t i = aNewSize; i < m.size; ++ i)
+ SafeArray::Uninit(m.arr[i]);
+
+ m.size = aNewSize;
+ }
+ }
+
+ m.capacity = newCapacity;
+
+#else
+
+ SAFEARRAYBOUND bound = { VarCount(aNewSize), 0 };
+ HRESULT rc;
+
+ if (m.arr == NULL)
+ {
+ m.arr = CreateSafeArray(VarType(), &bound);
+ AssertReturn(m.arr != NULL, false);
+ }
+ else
+ {
+ SafeArrayUnaccessData(m.arr);
+
+ rc = SafeArrayRedim(m.arr, &bound);
+ AssertComRCReturn(rc == S_OK, false);
+ }
+
+ rc = SafeArrayAccessData(m.arr, (void HUGEP **)&m.raw);
+ AssertComRCReturn(rc, false);
+
+#endif
+ return true;
+ }
+
+ struct Data
+ {
+ Data()
+ : isWeak(false)
+#ifdef VBOX_WITH_XPCOM
+ , capacity(0), size(0), arr(NULL)
+#else
+ , arr(NULL), raw(NULL)
+#endif
+ {}
+
+ ~Data() { uninit(); }
+
+ void uninit()
+ {
+#ifdef VBOX_WITH_XPCOM
+
+ if (arr)
+ {
+ if (!isWeak)
+ {
+ for (size_t i = 0; i < size; ++ i)
+ SafeArray::Uninit(arr[i]);
+
+ nsMemory::Free((void *)arr);
+ }
+ else
+ isWeak = false;
+
+ arr = NULL;
+ }
+
+ size = capacity = 0;
+
+#else /* !VBOX_WITH_XPCOM */
+
+ if (arr)
+ {
+ if (raw)
+ {
+ SafeArrayUnaccessData(arr);
+ raw = NULL;
+ }
+
+ if (!isWeak)
+ {
+ HRESULT rc = SafeArrayDestroy(arr);
+ AssertComRCReturnVoid(rc);
+ }
+ else
+ isWeak = false;
+
+ arr = NULL;
+ }
+
+#endif /* !VBOX_WITH_XPCOM */
+ }
+
+ bool isWeak : 1;
+
+#ifdef VBOX_WITH_XPCOM
+ PRUint32 capacity;
+ PRUint32 size;
+ T *arr;
+#else
+ SAFEARRAY *arr;
+ T *raw;
+#endif
+ };
+
+ Data m;
+};
+
+/* Few fast specializations for primitive array types */
+template<>
+inline void com::SafeArray<BYTE>::initFrom(const com::SafeArray<BYTE> & aRef)
+{
+ size_t sSize = aRef.size();
+ resize(sSize);
+ ::memcpy(raw(), aRef.raw(), sSize);
+}
+template<>
+inline void com::SafeArray<BYTE>::initFrom(const BYTE* aPtr, size_t aSize)
+{
+ resize(aSize);
+ ::memcpy(raw(), aPtr, aSize);
+}
+
+
+template<>
+inline void com::SafeArray<LONG>::initFrom(const com::SafeArray<LONG> & aRef)
+{
+ size_t sSize = aRef.size();
+ resize(sSize);
+ ::memcpy(raw(), aRef.raw(), sSize * sizeof(LONG));
+}
+template<>
+inline void com::SafeArray<LONG>::initFrom(const LONG* aPtr, size_t aSize)
+{
+ resize(aSize);
+ ::memcpy(raw(), aPtr, aSize * sizeof(LONG));
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+
+#ifdef VBOX_WITH_XPCOM
+
+/**
+ * Version of com::SafeArray for arrays of GUID.
+ *
+ * In MS COM, GUID arrays store GUIDs by value and therefore input arrays are
+ * represented using |GUID *| and out arrays -- using |GUID **|. In XPCOM,
+ * GUID arrays store pointers to nsID so that input arrays are |const nsID **|
+ * and out arrays are |nsID ***|. Due to this difference, it is impossible to
+ * work with arrays of GUID on both platforms by simply using com::SafeArray
+ * <GUID>. This class is intended to provide some level of cross-platform
+ * behavior.
+ *
+ * The basic usage pattern is basically similar to com::SafeArray<> except that
+ * you use ComSafeGUIDArrayIn* and ComSafeGUIDArrayOut* macros instead of
+ * ComSafeArrayIn* and ComSafeArrayOut*. Another important nuance is that the
+ * raw() array type is different (nsID **, or GUID ** on XPCOM and GUID * on MS
+ * COM) so it is recommended to use operator[] instead which always returns a
+ * GUID by value.
+ *
+ * Note that due to const modifiers, you cannot use SafeGUIDArray for input GUID
+ * arrays. Please use SafeConstGUIDArray for this instead.
+ *
+ * Other than mentioned above, the functionality of this class is equivalent to
+ * com::SafeArray<>. See the description of that template and its methods for
+ * more information.
+ *
+ * Output GUID arrays are handled by a separate class, SafeGUIDArrayOut, since
+ * this class cannot handle them because of const modifiers.
+ */
+class SafeGUIDArray : public SafeArray<nsID *>
+{
+public:
+
+ typedef SafeArray<nsID *> Base;
+
+ class nsIDRef
+ {
+ public:
+
+ nsIDRef(nsID * &aVal) : mVal(aVal) {}
+
+ operator const nsID &() const { return mVal ? *mVal : *Empty; }
+ operator nsID() const { return mVal ? *mVal : *Empty; }
+
+ const nsID *operator&() const { return mVal ? mVal : Empty; }
+
+ nsIDRef &operator= (const nsID &aThat)
+ {
+ if (mVal == NULL)
+ Copy(&aThat, mVal);
+ else
+ *mVal = aThat;
+ return *this;
+ }
+
+ private:
+
+ nsID * &mVal;
+
+ static const nsID *Empty;
+
+ friend class SafeGUIDArray;
+ };
+
+ /** See SafeArray<>::SafeArray(). */
+ SafeGUIDArray() {}
+
+ /** See SafeArray<>::SafeArray(size_t). */
+ SafeGUIDArray(size_t aSize) : Base(aSize) {}
+
+ /**
+ * Array access operator that returns an array element by reference. As a
+ * special case, the return value of this operator on XPCOM is an nsID (GUID)
+ * reference, instead of an nsID pointer (the actual SafeArray template
+ * argument), for compatibility with the MS COM version.
+ *
+ * The rest is equivalent to SafeArray<>::operator[].
+ */
+ nsIDRef operator[] (size_t aIdx)
+ {
+ Assert(m.arr != NULL);
+ Assert(aIdx < size());
+ return nsIDRef(m.arr[aIdx]);
+ }
+
+ /**
+ * Const version of #operator[] that returns an array element by value.
+ */
+ const nsID &operator[] (size_t aIdx) const
+ {
+ Assert(m.arr != NULL);
+ Assert(aIdx < size());
+ return m.arr[aIdx] ? *m.arr[aIdx] : *nsIDRef::Empty;
+ }
+};
+
+/**
+ * Version of com::SafeArray for const arrays of GUID.
+ *
+ * This class is used to work with input GUID array parameters in method
+ * implementations. See SafeGUIDArray for more details.
+ */
+class SafeConstGUIDArray : public SafeArray<const nsID *,
+ SafeArrayTraits<nsID *> >
+{
+public:
+
+ typedef SafeArray<const nsID *, SafeArrayTraits<nsID *> > Base;
+
+ /** See SafeArray<>::SafeArray(). */
+ SafeConstGUIDArray() {}
+
+ /* See SafeArray<>::SafeArray(ComSafeArrayIn(T, aArg)). */
+ SafeConstGUIDArray(ComSafeGUIDArrayIn(aArg))
+ : Base(ComSafeGUIDArrayInArg(aArg)) {}
+
+ /**
+ * Array access operator that returns an array element by reference. As a
+ * special case, the return value of this operator on XPCOM is nsID (GUID)
+ * instead of nsID *, for compatibility with the MS COM version.
+ *
+ * The rest is equivalent to SafeArray<>::operator[].
+ */
+ const nsID &operator[] (size_t aIdx) const
+ {
+ AssertReturn(m.arr != NULL, **((const nsID * *)NULL));
+ AssertReturn(aIdx < size(), **((const nsID * *)NULL));
+ return *m.arr[aIdx];
+ }
+
+private:
+
+ /* These are disabled because of const. */
+ bool reset(size_t aNewSize) { NOREF(aNewSize); return false; }
+};
+
+#else /* !VBOX_WITH_XPCOM */
+
+typedef SafeArray<GUID> SafeGUIDArray;
+typedef SafeArray<const GUID, SafeArrayTraits<GUID> > SafeConstGUIDArray;
+
+#endif /* !VBOX_WITH_XPCOM */
+
+////////////////////////////////////////////////////////////////////////////////
+
+#ifdef VBOX_WITH_XPCOM
+
+template<class I>
+struct SafeIfaceArrayTraits
+{
+protected:
+
+ static void Init(I * &aElem) { aElem = NULL; }
+ static void Uninit(I * &aElem)
+ {
+ if (aElem)
+ {
+ aElem->Release();
+ aElem = NULL;
+ }
+ }
+
+ static void Copy(I * aFrom, I * &aTo)
+ {
+ if (aFrom != NULL)
+ {
+ aTo = aFrom;
+ aTo->AddRef();
+ }
+ else
+ aTo = NULL;
+ }
+
+public:
+
+ /* Magic to workaround strict rules of par. 4.4.4 of the C++ standard. */
+ static I **__asInParam_Arr(I **aArr) { return aArr; }
+ static I **__asInParam_Arr(const I **aArr) { return const_cast<I **>(aArr); }
+};
+
+#else /* !VBOX_WITH_XPCOM */
+
+template<class I>
+struct SafeIfaceArrayTraits
+{
+protected:
+
+ static VARTYPE VarType() { return VT_DISPATCH; }
+ static ULONG VarCount(size_t aSize) { return (ULONG)aSize; }
+ static size_t Size(ULONG aVarCount) { return (size_t)aVarCount; }
+
+ static void Copy(I * aFrom, I * &aTo)
+ {
+ if (aFrom != NULL)
+ {
+ aTo = aFrom;
+ aTo->AddRef();
+ }
+ else
+ aTo = NULL;
+ }
+
+ static SAFEARRAY *CreateSafeArray(VARTYPE aVarType, SAFEARRAYBOUND *aBound)
+ {
+ NOREF(aVarType);
+ return SafeArrayCreateEx(VT_DISPATCH, 1, aBound, (PVOID)&_ATL_IIDOF(I));
+ }
+};
+
+#endif /* !VBOX_WITH_XPCOM */
+
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Version of com::SafeArray for arrays of interface pointers.
+ *
+ * Except that it manages arrays of interface pointers, the usage of this class
+ * is identical to com::SafeArray.
+ *
+ * @param I Interface class (no asterisk).
+ */
+template<class I>
+class SafeIfaceArray : public SafeArray<I *, SafeIfaceArrayTraits<I> >
+{
+public:
+
+ typedef SafeArray<I *, SafeIfaceArrayTraits<I> > Base;
+
+ /**
+ * Creates a null array.
+ */
+ SafeIfaceArray() {}
+
+ /**
+ * Creates a new array of the given size. All elements of the newly created
+ * array initialized with null values.
+ *
+ * @param aSize Initial number of elements in the array. Must be greater
+ * than 0.
+ *
+ * @note If this object remains null after construction it means that there
+ * was not enough memory for creating an array of the requested size.
+ * The constructor will also assert in this case.
+ */
+ SafeIfaceArray(size_t aSize) { Base::resize(aSize); }
+
+ /**
+ * Weakly attaches this instance to the existing array passed in a method
+ * parameter declared using the ComSafeArrayIn macro. When using this call,
+ * always wrap the parameter name in the ComSafeArrayOutArg macro call like
+ * this:
+ * <pre>
+ * SafeArray safeArray(ComSafeArrayInArg(aArg));
+ * </pre>
+ *
+ * Note that this constructor doesn't take the ownership of the array. In
+ * particular, this means that operations that operate on the ownership
+ * (e.g. #detachTo()) are forbidden and will assert.
+ *
+ * @param aArg Input method parameter to attach to.
+ */
+ SafeIfaceArray(ComSafeArrayIn(I *, aArg))
+ {
+#ifdef VBOX_WITH_XPCOM
+
+ AssertReturnVoid(aArg != NULL);
+
+ Base::m.size = aArgSize;
+ Base::m.arr = aArg;
+ Base::m.isWeak = true;
+
+#else /* !VBOX_WITH_XPCOM */
+
+ AssertReturnVoid(aArg != NULL);
+ SAFEARRAY *arg = aArg;
+
+ if (arg)
+ {
+ AssertReturnVoid(arg->cDims == 1);
+
+ VARTYPE vt;
+ HRESULT rc = SafeArrayGetVartype(arg, &vt);
+ AssertComRCReturnVoid(rc);
+ AssertMsgReturnVoid(vt == VT_UNKNOWN || vt == VT_DISPATCH,
+ ("Expected vartype VT_UNKNOWN, got %d.\n",
+ VarType(), vt));
+ GUID guid;
+ rc = SafeArrayGetIID(arg, &guid);
+ AssertComRCReturnVoid(rc);
+ AssertMsgReturnVoid(InlineIsEqualGUID(_ATL_IIDOF(I), guid),
+ ("Expected IID {%RTuuid}, got {%RTuuid}.\n",
+ &_ATL_IIDOF(I), &guid));
+
+ rc = SafeArrayAccessData(arg, (void HUGEP **)&m.raw);
+ AssertComRCReturnVoid(rc);
+ }
+
+ m.arr = arg;
+ m.isWeak = true;
+
+#endif /* !VBOX_WITH_XPCOM */
+ }
+
+ /**
+ * Creates a deep copy of the given standard C++ container that stores
+ * interface pointers as objects of the ComPtr<I> class.
+ *
+ * @param aCntr Container object to copy.
+ *
+ * @param C Standard C++ container template class (normally deduced from
+ * @c aCntr).
+ * @param A Standard C++ allocator class (deduced from @c aCntr).
+ * @param OI Argument to the ComPtr template (deduced from @c aCntr).
+ */
+ template<template<typename, typename> class C, class A, class OI>
+ SafeIfaceArray(const C<ComPtr<OI>, A> & aCntr)
+ {
+ typedef C<ComPtr<OI>, A> List;
+
+ Base::resize(aCntr.size());
+ AssertReturnVoid(!Base::isNull());
+
+ int i = 0;
+ for (typename List::const_iterator it = aCntr.begin();
+ it != aCntr.end(); ++ it, ++ i)
+#ifdef VBOX_WITH_XPCOM
+ Copy(*it, Base::m.arr[i]);
+#else
+ Copy(*it, Base::m.raw[i]);
+#endif
+ }
+
+ /**
+ * Creates a deep copy of the given standard C++ container that stores
+ * interface pointers as objects of the ComObjPtr<I> class.
+ *
+ * @param aCntr Container object to copy.
+ *
+ * @param C Standard C++ container template class (normally deduced from
+ * @c aCntr).
+ * @param A Standard C++ allocator class (deduced from @c aCntr).
+ * @param OI Argument to the ComObjPtr template (deduced from @c aCntr).
+ */
+ template<template<typename, typename> class C, class A, class OI>
+ SafeIfaceArray(const C<ComObjPtr<OI>, A> & aCntr)
+ {
+ typedef C<ComObjPtr<OI>, A> List;
+
+ Base::resize(aCntr.size());
+ AssertReturnVoid(!Base::isNull());
+
+ int i = 0;
+ for (typename List::const_iterator it = aCntr.begin();
+ it != aCntr.end(); ++ it, ++ i)
+#ifdef VBOX_WITH_XPCOM
+ SafeIfaceArray::Copy(*it, Base::m.arr[i]);
+#else
+ Copy(*it, Base::m.raw[i]);
+#endif
+ }
+
+ /**
+ * Creates a deep copy of the given standard C++ map whose values are
+ * interface pointers stored as objects of the ComPtr<I> class.
+ *
+ * @param aMap Map object to copy.
+ *
+ * @param C Standard C++ map template class (normally deduced from
+ * @c aCntr).
+ * @param L Standard C++ compare class (deduced from @c aCntr).
+ * @param A Standard C++ allocator class (deduced from @c aCntr).
+ * @param K Map key class (deduced from @c aCntr).
+ * @param OI Argument to the ComPtr template (deduced from @c aCntr).
+ */
+ template<template<typename, typename, typename, typename>
+ class C, class L, class A, class K, class OI>
+ SafeIfaceArray(const C<K, ComPtr<OI>, L, A> & aMap)
+ {
+ typedef C<K, ComPtr<OI>, L, A> Map;
+
+ Base::resize(aMap.size());
+ AssertReturnVoid(!Base::isNull());
+
+ int i = 0;
+ for (typename Map::const_iterator it = aMap.begin();
+ it != aMap.end(); ++ it, ++ i)
+#ifdef VBOX_WITH_XPCOM
+ SafeIfaceArray::Copy(it->second, Base::m.arr[i]);
+#else
+ Copy(it->second, Base::m.raw[i]);
+#endif
+ }
+
+ /**
+ * Creates a deep copy of the given standard C++ map whose values are
+ * interface pointers stored as objects of the ComObjPtr<I> class.
+ *
+ * @param aMap Map object to copy.
+ *
+ * @param C Standard C++ map template class (normally deduced from
+ * @c aCntr).
+ * @param L Standard C++ compare class (deduced from @c aCntr).
+ * @param A Standard C++ allocator class (deduced from @c aCntr).
+ * @param K Map key class (deduced from @c aCntr).
+ * @param OI Argument to the ComObjPtr template (deduced from @c aCntr).
+ */
+ template<template<typename, typename, typename, typename>
+ class C, class L, class A, class K, class OI>
+ SafeIfaceArray(const C<K, ComObjPtr<OI>, L, A> & aMap)
+ {
+ typedef C<K, ComObjPtr<OI>, L, A> Map;
+
+ Base::resize(aMap.size());
+ AssertReturnVoid(!Base::isNull());
+
+ int i = 0;
+ for (typename Map::const_iterator it = aMap.begin();
+ it != aMap.end(); ++ it, ++ i)
+#ifdef VBOX_WITH_XPCOM
+ SafeIfaceArray::Copy(it->second, Base::m.arr[i]);
+#else
+ Copy(it->second, Base::m.raw[i]);
+#endif
+ }
+
+ void setElement(size_t iIdx, I* obj)
+ {
+#ifdef VBOX_WITH_XPCOM
+ SafeIfaceArray::Copy(obj, Base::m.arr[iIdx]);
+#else
+ Copy(obj, Base::m.raw[iIdx]);
+#endif
+ }
+};
+
+} /* namespace com */
+
+/** @} */
+
+#endif /* ___VBox_com_array_h */
diff --git a/include/VBox/com/assert.h b/include/VBox/com/assert.h
new file mode 100644
index 00000000..0a9b1afd
--- /dev/null
+++ b/include/VBox/com/assert.h
@@ -0,0 +1,108 @@
+/** @file
+ * MS COM / XPCOM Abstraction Layer:
+ * Assertion macros for COM/XPCOM
+ */
+
+/*
+ * Copyright (C) 2006-2007 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_com_assert_h
+#define ___VBox_com_assert_h
+
+#include <iprt/assert.h>
+
+/**
+ * Asserts that the COM result code is succeeded in strict builds.
+ * In non-strict builds the result code will be NOREF'ed to kill compiler warnings.
+ *
+ * @param rc COM result code
+ */
+#define AssertComRC(rc) \
+ do { AssertMsg (SUCCEEDED (rc), ("COM RC = %Rhrc (0x%08X)\n", rc, rc)); NOREF (rc); } while (0)
+
+/**
+ * A special version of AssertComRC that returns the given expression
+ * if the result code is failed.
+ *
+ * @param rc COM result code
+ * @param ret the expression to return
+ */
+#define AssertComRCReturn(rc, ret) \
+ AssertMsgReturn (SUCCEEDED (rc), ("COM RC = %Rhrc (0x%08X)\n", rc, rc), ret)
+
+/**
+ * A special version of AssertComRC that returns the given result code
+ * if it is failed.
+ *
+ * @param rc COM result code
+ * @param ret the expression to return
+ */
+#define AssertComRCReturnRC(rc) \
+ AssertMsgReturn (SUCCEEDED (rc), ("COM RC = %Rhrc (0x%08X)\n", rc, rc), rc)
+
+/**
+ * A special version of AssertComRC that returns if the result code is failed.
+ *
+ * @param rc COM result code
+ * @param ret the expression to return
+ */
+#define AssertComRCReturnVoid(rc) \
+ AssertMsgReturnVoid (SUCCEEDED (rc), ("COM RC = %Rhrc (0x%08X)\n", rc, rc))
+
+/**
+ * A special version of AssertComRC that evaluates the given expression and
+ * breaks if the result code is failed.
+ *
+ * @param rc COM result code
+ * @param eval the expression to evaluate
+ */
+#define AssertComRCBreak(rc, eval) \
+ if (!SUCCEEDED (rc)) { AssertComRC (rc); eval; break; } else do {} while (0)
+
+/**
+ * A special version of AssertComRC that evaluates the given expression and
+ * throws it if the result code is failed.
+ *
+ * @param rc COM result code
+ * @param eval the expression to throw
+ */
+#define AssertComRCThrow(rc, eval) \
+ if (!SUCCEEDED (rc)) { AssertComRC (rc); throw (eval); } else do {} while (0)
+
+/**
+ * A special version of AssertComRC that just breaks if the result code is
+ * failed.
+ *
+ * @param rc COM result code
+ */
+#define AssertComRCBreakRC(rc) \
+ if (!SUCCEEDED (rc)) { AssertComRC (rc); break; } else do {} while (0)
+
+/**
+ * A special version of AssertComRC that just throws @a rc if the result code is
+ * failed.
+ *
+ * @param rc COM result code
+ */
+#define AssertComRCThrowRC(rc) \
+ if (!SUCCEEDED (rc)) { AssertComRC (rc); throw rc; } else do {} while (0)
+
+#endif // !___VBox_com_assert_h
diff --git a/include/VBox/com/com.h b/include/VBox/com/com.h
new file mode 100644
index 00000000..524c89c6
--- /dev/null
+++ b/include/VBox/com/com.h
@@ -0,0 +1,111 @@
+/** @file
+ * MS COM / XPCOM Abstraction Layer:
+ * COM initialization / shutdown
+ */
+
+/*
+ * Copyright (C) 2005-2012 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_com_com_h
+#define ___VBox_com_com_h
+
+#include "VBox/com/defs.h"
+
+namespace com
+{
+
+/**
+ * Initializes the COM runtime.
+ * Must be called on the main thread, before any COM activity in any thread, and by any thread
+ * willing to perform COM operations.
+ *
+ * @param fMain if call is performed on the GUI thread
+ * @return COM result code
+ */
+HRESULT Initialize(bool fGui = false);
+
+/**
+ * Shuts down the COM runtime.
+ * Must be called on the main thread before termination.
+ * No COM calls may be made in any thread after this method returns.
+ */
+HRESULT Shutdown();
+
+/**
+ * Resolves a given interface ID to a string containing the interface name.
+ * If, for some reason, the given IID cannot be resolved to a name, a NULL
+ * string is returned. A non-NULL string returned by this function must be
+ * freed using SysFreeString().
+ *
+ * @param aIID ID of the interface to get a name for
+ * @param aName Resolved interface name or @c NULL on error
+ */
+void GetInterfaceNameByIID(const GUID &aIID, BSTR *aName);
+
+/**
+ * Returns the VirtualBox user home directory.
+ *
+ * On failure, this function will return a path that caused a failure (or
+ * NULL if the failure is not path-related).
+ *
+ * On success, this function will try to create the returned directory if it
+ * doesn't exist yet. This may also fail with the corresponding status code.
+ *
+ * If @a aDirLen is smaller than RTPATH_MAX then there is a great chance that
+ * this method will return VERR_BUFFER_OVERFLOW.
+ *
+ * @param aDir Buffer to store the directory string in UTF-8 encoding.
+ * @param aDirLen Length of the supplied buffer including space for the
+ * terminating null character, in bytes.
+ * @param fCreateDir Flag whether to create the returned directory on success if it
+ * doesn't exist.
+ * @return VBox status code.
+ */
+int GetVBoxUserHomeDirectory(char *aDir, size_t aDirLen, bool fCreateDir = true);
+
+/**
+ * Creates a release log file, used both in VBoxSVC and in API clients.
+ *
+ * @param pcszEntity Human readable name of the program.
+ * @param pcszLogFile Name of the release log file.
+ * @param fFlags Logger instance flags.
+ * @param pcszGroupSettings Group logging settings.
+ * @param pcszEnvVarBase Base environment variable name for the logger.
+ * @param fDestFlags Logger destination flags.
+ * @param cMaxEntriesPerGroup Limit for log entries per group. UINT32_MAX for no limit.
+ * @param cHistory Number of old log files to keep.
+ * @param uHistoryFileTime Maximum amount of time to put in a log file.
+ * @param uHistoryFileSize Maximum size of a log file before rotating.
+ * @param pszError In case of creation failure: buffer for error message.
+ * @param cbError Size of error message buffer.
+ * @return VBox status code.
+ */
+int VBoxLogRelCreate(const char *pcszEntity, const char *pcszLogFile,
+ uint32_t fFlags, const char *pcszGroupSettings,
+ const char *pcszEnvVarBase, uint32_t fDestFlags,
+ uint32_t cMaxEntriesPerGroup, uint32_t cHistory,
+ uint32_t uHistoryFileTime, uint64_t uHistoryFileSize,
+ char *pszError, size_t cbError);
+
+} /* namespace com */
+
+#endif
+
diff --git a/include/VBox/com/defs.h b/include/VBox/com/defs.h
new file mode 100644
index 00000000..aa9800dd
--- /dev/null
+++ b/include/VBox/com/defs.h
@@ -0,0 +1,549 @@
+/** @file
+ * MS COM / XPCOM Abstraction Layer:
+ * Common definitions
+ */
+
+/*
+ * Copyright (C) 2006-2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_com_defs_h
+#define ___VBox_com_defs_h
+
+/* Make sure all the stdint.h macros are included - must come first! */
+#ifndef __STDC_LIMIT_MACROS
+# define __STDC_LIMIT_MACROS
+#endif
+#ifndef __STDC_CONSTANT_MACROS
+# define __STDC_CONSTANT_MACROS
+#endif
+
+#if defined (RT_OS_OS2)
+
+# if defined(RT_MAX) && RT_MAX != 22
+# undef RT_MAX
+# define REDEFINE_RT_MAX
+# endif
+# undef RT_MAX
+
+/* Make sure OS/2 Toolkit headers are pulled in to have BOOL/ULONG/etc. typedefs
+ * already defined in order to be able to redefine them using #define. */
+# define INCL_BASE
+# define INCL_PM
+# include <os2.h>
+
+/* OS/2 Toolkit defines TRUE and FALSE */
+# undef FALSE
+# undef TRUE
+
+/* */
+# undef RT_MAX
+# ifdef REDEFINE_RT_MAX
+# define RT_MAX(Value1, Value2) ( (Value1) >= (Value2) ? (Value1) : (Value2) )
+# endif
+
+#endif /* defined (RT_OS_OS2) */
+
+/* Include iprt/types.h (which also includes iprt/types.h) now to make sure iprt
+ * gets to stdint.h first, otherwise a system/xpcom header might beat us and
+ * we'll be without the macros that are optional in C++. */
+#include <iprt/types.h>
+
+#if !defined (VBOX_WITH_XPCOM)
+
+#if defined (RT_OS_WINDOWS)
+
+// Windows COM
+/////////////////////////////////////////////////////////////////////////////
+
+#include <objbase.h>
+#ifndef VBOX_COM_NO_ATL
+# define _ATL_FREE_THREADED
+
+# include <atlbase.h>
+#include <atlcom.h>
+#endif
+
+#define NS_DECL_ISUPPORTS
+#define NS_IMPL_ISUPPORTS1_CI(a, b)
+
+/* these are XPCOM only, one for every interface implemented */
+#define NS_DECL_ISUPPORTS
+
+/** Returns @c true if @a rc represents a warning result code */
+#define SUCCEEDED_WARNING(rc) (SUCCEEDED (rc) && (rc) != S_OK)
+
+/** Tests is a COM result code indicates that the process implementing the
+ * interface is dead.
+ *
+ * COM status codes:
+ * 0x800706ba - RPC_S_SERVER_UNAVAILABLE. Killed before call was made.
+ * 0x800706be - RPC_S_CALL_FAILED. Killed after call was made.
+ * 0x800706bf - RPC_S_CALL_FAILED_DNE. Not observed, but should be matter of timing.
+ */
+#define FAILED_DEAD_INTERFACE(rc) \
+ ( (rc) == HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE) \
+ || (rc) == HRESULT_FROM_WIN32(RPC_S_CALL_FAILED) \
+ || (rc) == HRESULT_FROM_WIN32(RPC_S_CALL_FAILED_DNE) \
+ )
+
+/** Immutable BSTR string */
+typedef const OLECHAR *CBSTR;
+
+/** Input BSTR argument of interface method declaration. */
+#define IN_BSTR BSTR
+
+/** Input GUID argument of interface method declaration. */
+#define IN_GUID GUID
+/** Output GUID argument of interface method declaration. */
+#define OUT_GUID GUID*
+
+/** Makes the name of the getter interface function (n must be capitalized). */
+#define COMGETTER(n) get_##n
+/** Makes the name of the setter interface function (n must be capitalized). */
+#define COMSETTER(n) put_##n
+
+/**
+ * Declares an input safearray parameter in the COM method implementation. Also
+ * used to declare the COM attribute setter parameter. Corresponds to either of
+ * the following XIDL definitions:
+ * <pre>
+ * <param name="arg" ... dir="in" safearray="yes"/>
+ * ...
+ * <attribute name="arg" ... safearray="yes"/>
+ * </pre>
+ *
+ * The method implementation should use the com::SafeArray helper class to work
+ * with parameters declared using this define.
+ *
+ * @param aType Array element type.
+ * @param aArg Parameter/attribute name.
+ */
+#define ComSafeArrayIn(aType, aArg) SAFEARRAY *aArg
+
+/**
+ * Expands to @true if the given input safearray parameter is a "null pointer"
+ * which makes it impossible to use it for reading safearray data.
+ */
+#define ComSafeArrayInIsNull(aArg) ((aArg) == NULL)
+
+/**
+ * Wraps the given parameter name to generate an expression that is suitable for
+ * passing the parameter to functions that take input safearray parameters
+ * declared using the ComSafeArrayIn marco.
+ *
+ * @param aArg Parameter name to wrap. The given parameter must be declared
+ * within the calling function using the ComSafeArrayIn macro.
+ */
+#define ComSafeArrayInArg(aArg) aArg
+
+/**
+ * Declares an output safearray parameter in the COM method implementation. Also
+ * used to declare the COM attribute getter parameter. Corresponds to either of
+ * the following XIDL definitions:
+ * <pre>
+ * <param name="arg" ... dir="out" safearray="yes"/>
+ * <param name="arg" ... dir="return" safearray="yes"/>
+ * ...
+ * <attribute name="arg" ... safearray="yes"/>
+ * </pre>
+ *
+ * The method implementation should use the com::SafeArray helper class to work
+ * with parameters declared using this define.
+ *
+ * @param aType Array element type.
+ * @param aArg Parameter/attribute name.
+ */
+#define ComSafeArrayOut(aType, aArg) SAFEARRAY **aArg
+
+/**
+ * Expands to @true if the given output safearray parameter is a "null pointer"
+ * which makes it impossible to use it for returning a safearray.
+ */
+#define ComSafeArrayOutIsNull(aArg) ((aArg) == NULL)
+
+/**
+ * Wraps the given parameter name to generate an expression that is suitable for
+ * passing the parameter to functions that take output safearray parameters
+ * declared using the ComSafeArrayOut marco.
+ *
+ * @param aArg Parameter name to wrap. The given parameter must be declared
+ * within the calling function using the ComSafeArrayOut macro.
+ */
+#define ComSafeArrayOutArg(aArg) aArg
+
+/**
+ * Version of ComSafeArrayIn for GUID.
+ * @param aArg Parameter name to wrap.
+ */
+#define ComSafeGUIDArrayIn(aArg) SAFEARRAY *aArg
+
+/**
+ * Version of ComSafeArrayInIsNull for GUID.
+ * @param aArg Parameter name to wrap.
+ */
+#define ComSafeGUIDArrayInIsNull(aArg) ComSafeArrayInIsNull (aArg)
+
+/**
+ * Version of ComSafeArrayInArg for GUID.
+ * @param aArg Parameter name to wrap.
+ */
+#define ComSafeGUIDArrayInArg(aArg) ComSafeArrayInArg (aArg)
+
+/**
+ * Version of ComSafeArrayOut for GUID.
+ * @param aArg Parameter name to wrap.
+ */
+#define ComSafeGUIDArrayOut(aArg) SAFEARRAY **aArg
+
+/**
+ * Version of ComSafeArrayOutIsNull for GUID.
+ * @param aArg Parameter name to wrap.
+ */
+#define ComSafeGUIDArrayOutIsNull(aArg) ComSafeArrayOutIsNull (aArg)
+
+/**
+ * Version of ComSafeArrayOutArg for GUID.
+ * @param aArg Parameter name to wrap.
+ */
+#define ComSafeGUIDArrayOutArg(aArg) ComSafeArrayOutArg (aArg)
+
+/**
+ * Returns the const reference to the IID (i.e., |const GUID &|) of the given
+ * interface.
+ *
+ * @param i interface class
+ */
+#define COM_IIDOF(I) _ATL_IIDOF(I)
+
+/**
+ * For using interfaces before including the interface definitions. This will
+ * deal with XPCOM using 'class' and COM using 'struct' when defining
+ * interfaces.
+ *
+ * @param I interface name.
+ */
+#define COM_STRUCT_OR_CLASS(I) struct I
+
+#else /* defined (RT_OS_WINDOWS) */
+
+#error "VBOX_WITH_XPCOM must be defined on a platform other than Windows!"
+
+#endif /* defined (RT_OS_WINDOWS) */
+
+#else /* !defined (VBOX_WITH_XPCOM) */
+
+// XPCOM
+/////////////////////////////////////////////////////////////////////////////
+
+#if defined (RT_OS_DARWIN) || (defined (QT_VERSION) && (QT_VERSION >= 0x040000))
+ /* CFBase.h defines these &
+ * qglobal.h from Qt4 defines these */
+# undef FALSE
+# undef TRUE
+#endif /* RT_OS_DARWIN || QT_VERSION */
+
+#include <nsID.h>
+
+#define ATL_NO_VTABLE
+#define DECLARE_CLASSFACTORY(a)
+#define DECLARE_CLASSFACTORY_SINGLETON(a)
+#define DECLARE_REGISTRY_RESOURCEID(a)
+#define DECLARE_NOT_AGGREGATABLE(a)
+#define DECLARE_PROTECT_FINAL_CONSTRUCT()
+#define BEGIN_COM_MAP(a)
+#define COM_INTERFACE_ENTRY(a)
+#define COM_INTERFACE_ENTRY2(a,b)
+#define END_COM_MAP() NS_DECL_ISUPPORTS
+#define COM_INTERFACE_ENTRY_AGGREGATE(a,b)
+
+#define HRESULT nsresult
+#define SUCCEEDED NS_SUCCEEDED
+#define FAILED NS_FAILED
+
+#define SUCCEEDED_WARNING(rc) (NS_SUCCEEDED (rc) && (rc) != NS_OK)
+
+#define FAILED_DEAD_INTERFACE(rc) ( (rc) == NS_ERROR_ABORT \
+ || (rc) == NS_ERROR_CALL_FAILED \
+ )
+
+#define IUnknown nsISupports
+
+#define BOOL PRBool
+#define BYTE PRUint8
+#define SHORT PRInt16
+#define USHORT PRUint16
+#define LONG PRInt32
+#define ULONG PRUint32
+#define LONG64 PRInt64
+#define ULONG64 PRUint64
+/* XPCOM has only 64bit floats */
+#define FLOAT PRFloat64
+#define DOUBLE PRFloat64
+
+#define FALSE PR_FALSE
+#define TRUE PR_TRUE
+
+#define OLECHAR wchar_t
+
+/* note: typedef to semantically match BSTR on Win32 */
+typedef PRUnichar *BSTR;
+typedef const PRUnichar *CBSTR;
+typedef BSTR *LPBSTR;
+
+/** Input BSTR argument the interface method declaration. */
+#define IN_BSTR CBSTR
+
+/**
+ * Type to define a raw GUID variable (for members use the com::Guid class
+ * instead).
+ */
+#define GUID nsID
+/** Input GUID argument the interface method declaration. */
+#define IN_GUID const nsID &
+/** Output GUID argument the interface method declaration. */
+#define OUT_GUID nsID **
+
+/** Makes the name of the getter interface function (n must be capitalized). */
+#define COMGETTER(n) Get##n
+/** Makes the name of the setter interface function (n must be capitalized). */
+#define COMSETTER(n) Set##n
+
+/* safearray input parameter macros */
+#define ComSafeArrayIn(aType, aArg) PRUint32 aArg##Size, aType *aArg
+#define ComSafeArrayInIsNull(aArg) ((aArg) == NULL)
+#define ComSafeArrayInArg(aArg) aArg##Size, aArg
+
+/* safearray output parameter macros */
+#define ComSafeArrayOut(aType, aArg) PRUint32 *aArg##Size, aType **aArg
+#define ComSafeArrayOutIsNull(aArg) ((aArg) == NULL)
+#define ComSafeArrayOutArg(aArg) aArg##Size, aArg
+
+/* safearray input parameter macros for GUID */
+#define ComSafeGUIDArrayIn(aArg) PRUint32 aArg##Size, const nsID **aArg
+#define ComSafeGUIDArrayInIsNull(aArg) ComSafeArrayInIsNull (aArg)
+#define ComSafeGUIDArrayInArg(aArg) ComSafeArrayInArg (aArg)
+
+/* safearray output parameter macros for GUID */
+#define ComSafeGUIDArrayOut(aArg) PRUint32 *aArg##Size, nsID ***aArg
+#define ComSafeGUIDArrayOutIsNull(aArg) ComSafeArrayOutIsNull (aArg)
+#define ComSafeGUIDArrayOutArg(aArg) ComSafeArrayOutArg (aArg)
+
+/* CLSID and IID for compatibility with Win32 */
+typedef nsCID CLSID;
+typedef nsIID IID;
+
+/* OLE error codes */
+#define S_OK ((nsresult) NS_OK)
+#define E_UNEXPECTED NS_ERROR_UNEXPECTED
+#define E_NOTIMPL NS_ERROR_NOT_IMPLEMENTED
+#define E_OUTOFMEMORY NS_ERROR_OUT_OF_MEMORY
+#define E_INVALIDARG NS_ERROR_INVALID_ARG
+#define E_NOINTERFACE NS_ERROR_NO_INTERFACE
+#define E_POINTER NS_ERROR_NULL_POINTER
+#define E_ABORT NS_ERROR_ABORT
+#define E_FAIL NS_ERROR_FAILURE
+/* Note: a better analog for E_ACCESSDENIED would probably be
+ * NS_ERROR_NOT_AVAILABLE, but we want binary compatibility for now. */
+#define E_ACCESSDENIED ((nsresult) 0x80070005L)
+
+#define STDMETHOD(a) NS_IMETHOD a
+#define STDMETHODIMP NS_IMETHODIMP
+
+#define COM_IIDOF(I) NS_GET_IID(I)
+
+#define COM_STRUCT_OR_CLASS(I) class I
+
+/* A few very simple ATL emulator classes to provide
+ * FinalConstruct()/FinalRelease() functionality on Linux. */
+
+class CComMultiThreadModel
+{
+};
+
+template <class Base> class CComObjectRootEx : public Base
+{
+public:
+ HRESULT FinalConstruct() { return S_OK; }
+ void FinalRelease() {}
+};
+
+template <class Base> class CComObject : public Base
+{
+public:
+ virtual ~CComObject() { this->FinalRelease(); }
+};
+
+/* helper functions */
+extern "C"
+{
+BSTR SysAllocString (const OLECHAR* sz);
+BSTR SysAllocStringByteLen (char *psz, unsigned int len);
+BSTR SysAllocStringLen (const OLECHAR *pch, unsigned int cch);
+void SysFreeString (BSTR bstr);
+int SysReAllocString (BSTR *pbstr, const OLECHAR *psz);
+int SysReAllocStringLen (BSTR *pbstr, const OLECHAR *psz, unsigned int cch);
+unsigned int SysStringByteLen (BSTR bstr);
+unsigned int SysStringLen (BSTR bstr);
+}
+
+/**
+ * 'Constructor' for the component class.
+ * This constructor, as opposed to NS_GENERIC_FACTORY_CONSTRUCTOR,
+ * assumes that the component class is derived from the CComObjectRootEx<>
+ * template, so it calls FinalConstruct() right after object creation
+ * and ensures that FinalRelease() will be called right before destruction.
+ * The result from FinalConstruct() is returned to the caller.
+ */
+#define NS_GENERIC_FACTORY_CONSTRUCTOR_WITH_RC(_InstanceClass) \
+static NS_IMETHODIMP \
+_InstanceClass##Constructor(nsISupports *aOuter, REFNSIID aIID, \
+ void **aResult) \
+{ \
+ nsresult rv; \
+ \
+ *aResult = NULL; \
+ if (NULL != aOuter) { \
+ rv = NS_ERROR_NO_AGGREGATION; \
+ return rv; \
+ } \
+ \
+ CComObject <_InstanceClass> *inst = new CComObject <_InstanceClass>(); \
+ if (NULL == inst) { \
+ rv = NS_ERROR_OUT_OF_MEMORY; \
+ return rv; \
+ } \
+ \
+ NS_ADDREF(inst); /* protect FinalConstruct() */ \
+ rv = inst->FinalConstruct(); \
+ if (NS_SUCCEEDED(rv)) \
+ rv = inst->QueryInterface(aIID, aResult); \
+ NS_RELEASE(inst); \
+ \
+ return rv; \
+}
+
+/**
+ * 'Constructor' that uses an existing getter function that gets a singleton.
+ * The getter function must have the following prototype:
+ * nsresult _GetterProc (_InstanceClass **inst)
+ * This constructor, as opposed to NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR,
+ * lets the getter function return a result code that is passed back to the
+ * caller that tries to instantiate the object.
+ * NOTE: assumes that getter does an AddRef - so additional AddRef is not done.
+ */
+#define NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR_WITH_RC(_InstanceClass, _GetterProc) \
+static NS_IMETHODIMP \
+_InstanceClass##Constructor(nsISupports *aOuter, REFNSIID aIID, \
+ void **aResult) \
+{ \
+ nsresult rv; \
+ \
+ _InstanceClass * inst = NULL; /* initialized to shut up gcc */ \
+ \
+ *aResult = NULL; \
+ if (NULL != aOuter) { \
+ rv = NS_ERROR_NO_AGGREGATION; \
+ return rv; \
+ } \
+ \
+ rv = _GetterProc(&inst); \
+ if (NS_FAILED(rv)) \
+ return rv; \
+ \
+ /* sanity check */ \
+ if (NULL == inst) \
+ return NS_ERROR_OUT_OF_MEMORY; \
+ \
+ /* NS_ADDREF(inst); */ \
+ if (NS_SUCCEEDED(rv)) { \
+ rv = inst->QueryInterface(aIID, aResult); \
+ } \
+ NS_RELEASE(inst); \
+ \
+ return rv; \
+}
+
+#endif /* !defined (VBOX_WITH_XPCOM) */
+
+/**
+ * Declares a wchar_t string literal from the argument.
+ * Necessary to overcome MSC / GCC differences.
+ * @param s expression to stringify
+ */
+#if defined (_MSC_VER)
+# define WSTR_LITERAL(s) L#s
+#elif defined (__GNUC__)
+# define WSTR_LITERAL(s) L""#s
+#else
+# error "Unsupported compiler!"
+#endif
+
+namespace com
+{
+
+// use this macro to implement scriptable interfaces
+#ifdef RT_OS_WINDOWS
+#define VBOX_SCRIPTABLE_IMPL(iface) \
+ public IDispatchImpl<iface, &IID_##iface, &LIBID_VirtualBox, \
+ kTypeLibraryMajorVersion, kTypeLibraryMinorVersion>
+
+#define VBOX_SCRIPTABLE_DISPATCH_IMPL(iface) \
+ STDMETHOD(QueryInterface)(REFIID riid , void **ppObj) \
+ { \
+ if (riid == IID_##iface) \
+ { \
+ *ppObj = (iface*)this; \
+ AddRef(); \
+ return S_OK; \
+ } \
+ if (riid == IID_IUnknown) \
+ { \
+ *ppObj = (IUnknown*)this; \
+ AddRef(); \
+ return S_OK; \
+ } \
+ if (riid == IID_IDispatch) \
+ { \
+ *ppObj = (IDispatch*)this; \
+ AddRef(); \
+ return S_OK; \
+ } \
+ *ppObj = NULL; \
+ return E_NOINTERFACE; \
+ }
+
+
+#define VBOX_DEFAULT_INTERFACE_ENTRIES(iface) \
+ COM_INTERFACE_ENTRY(ISupportErrorInfo) \
+ COM_INTERFACE_ENTRY(iface) \
+ COM_INTERFACE_ENTRY2(IDispatch,iface) \
+ COM_INTERFACE_ENTRY_AGGREGATE(IID_IMarshal, m_pUnkMarshaler.p)
+#else
+#define VBOX_SCRIPTABLE_IMPL(iface) \
+ public iface
+#define VBOX_SCRIPTABLE_DISPATCH_IMPL(iface)
+#define VBOX_DEFAULT_INTERFACE_ENTRIES(iface)
+#endif
+
+
+} /* namespace com */
+
+#endif /* ___VBox_com_defs_h */
diff --git a/include/VBox/com/errorprint.h b/include/VBox/com/errorprint.h
new file mode 100644
index 00000000..2ee11676
--- /dev/null
+++ b/include/VBox/com/errorprint.h
@@ -0,0 +1,261 @@
+/** @file
+ * MS COM / XPCOM Abstraction Layer:
+ * Error printing macros using shared functions defined in shared glue code.
+ * Use these CHECK_* macros for efficient error checking around calling COM methods.
+ */
+
+/*
+ * Copyright (C) 2009 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_com_errorprint_h
+#define ___VBox_com_errorprint_h
+
+#include <VBox/com/ErrorInfo.h>
+
+namespace com
+{
+
+// shared prototypes; these are defined in shared glue code and are
+// compiled only once for all front-ends
+void GluePrintErrorInfo(const com::ErrorInfo &info);
+void GluePrintErrorContext(const char *pcszContext, const char *pcszSourceFile, uint32_t ulLine);
+void GluePrintRCMessage(HRESULT rc);
+void GlueHandleComError(ComPtr<IUnknown> iface,
+ const char *pcszContext,
+ HRESULT rc,
+ const char *pcszSourceFile,
+ uint32_t ulLine);
+void GlueHandleComErrorProgress(ComPtr<IProgress> progress,
+ const char *pcszContext,
+ HRESULT rc,
+ const char *pcszSourceFile,
+ uint32_t ulLine);
+
+/**
+ * Calls the given method of the given interface and then checks if the return
+ * value (COM result code) indicates a failure. If so, prints the failed
+ * function/line/file, the description of the result code and attempts to
+ * query the extended error information on the current thread (using
+ * com::ErrorInfo) if the interface reports that it supports error information.
+ *
+ * Used by command line tools or for debugging and assumes the |HRESULT rc|
+ * variable is accessible for assigning in the current scope.
+ */
+#define CHECK_ERROR(iface, method) \
+ do { \
+ rc = iface->method; \
+ if (FAILED(rc)) \
+ com::GlueHandleComError(iface, #method, rc, __FILE__, __LINE__); \
+ } while (0)
+
+/**
+ * Same as CHECK_ERROR except that it also executes the statement |stmt| on
+ * failure.
+ */
+#define CHECK_ERROR_STMT(iface, method, stmt) \
+ do { \
+ rc = iface->method; \
+ if (FAILED(rc)) \
+ { \
+ com::GlueHandleComError(iface, #method, rc, __FILE__, __LINE__); \
+ stmt; \
+ } \
+ } while (0)
+
+/**
+ * Same as CHECK_ERROR_STMT except that it uses an internal variable |hrcCheck|
+ * for holding the result.
+ */
+#define CHECK_ERROR2_STMT(iface, method, stmt) \
+ do { \
+ HRESULT hrcCheck = iface->method; \
+ if (FAILED(hrcCheck)) \
+ { \
+ com::GlueHandleComError(iface, #method, hrcCheck, __FILE__, __LINE__); \
+ stmt; \
+ } \
+ } while (0)
+
+
+/**
+ * Does the same as CHECK_ERROR(), but executes the |break| statement on
+ * failure.
+ */
+#ifdef __GNUC__
+# define CHECK_ERROR_BREAK(iface, method) \
+ __extension__ \
+ ({ \
+ rc = iface->method; \
+ if (FAILED(rc)) \
+ { \
+ com::GlueHandleComError(iface, #method, rc, __FILE__, __LINE__); \
+ break; \
+ } \
+ })
+#else
+# define CHECK_ERROR_BREAK(iface, method) \
+ if (1) \
+ { \
+ rc = iface->method; \
+ if (FAILED(rc)) \
+ { \
+ com::GlueHandleComError(iface, #method, rc, __FILE__, __LINE__); \
+ break; \
+ } \
+ } \
+ else do {} while (0)
+#endif
+
+/**
+ * Does the same as CHECK_ERROR(), but executes the |return ret| statement on
+ * failure.
+ */
+#define CHECK_ERROR_RET(iface, method, ret) \
+ do { \
+ rc = iface->method; \
+ if (FAILED(rc)) \
+ { \
+ com::GlueHandleComError(iface, #method, rc, __FILE__, __LINE__); \
+ return (ret); \
+ } \
+ } while (0)
+
+/**
+ * Does the same as CHECK_ERROR(), but returns @a ret on failure.
+ *
+ * Unlike CHECK_ERROR and CHECK_ERROR_RET, this macro does not presuppose a
+ * |rc| variable but instead employs a local variable |hrcCheck| in its own
+ * scope. This |hrcCheck| variable can be referenced by the @a rcRet
+ * parameter.
+ *
+ * @param iface The interface pointer (can be a smart pointer object).
+ * @param method The method to invoke together with the parameters.
+ * @param rcRet What to return on failure. Use |hrcCheck| to return
+ * the status code of the method call.
+ */
+#define CHECK_ERROR2_RET(iface, method, rcRet) \
+ do { \
+ HRESULT hrcCheck = iface->method; \
+ if (FAILED(hrcCheck)) \
+ { \
+ com::GlueHandleComError(iface, #method, hrcCheck, __FILE__, __LINE__); \
+ return (rcRet); \
+ } \
+ } while (0)
+
+
+/**
+ * Check the progress object for an error and if there is one print out the
+ * extended error information.
+ */
+#define CHECK_PROGRESS_ERROR(progress, msg) \
+ do { \
+ LONG iRc; \
+ rc = progress->COMGETTER(ResultCode)(&iRc); \
+ if (FAILED(iRc)) \
+ { \
+ rc = iRc; \
+ RTMsgError msg; \
+ com::GlueHandleComErrorProgress(progress, __PRETTY_FUNCTION__, iRc, __FILE__, __LINE__); \
+ } \
+ } while (0)
+
+/**
+ * Does the same as CHECK_PROGRESS_ERROR(), but executes the |break| statement
+ * on failure.
+ */
+#ifdef __GNUC__
+# define CHECK_PROGRESS_ERROR_BREAK(progress, msg) \
+ __extension__ \
+ ({ \
+ LONG iRc; \
+ rc = progress->COMGETTER(ResultCode)(&iRc); \
+ if (FAILED(iRc)) \
+ { \
+ rc = iRc; \
+ RTMsgError msg; \
+ com::GlueHandleComErrorProgress(progress, __PRETTY_FUNCTION__, iRc, __FILE__, __LINE__); \
+ break; \
+ } \
+ })
+#else
+# define CHECK_PROGRESS_ERROR_BREAK(progress, msg) \
+ if (1) \
+ { \
+ LONG iRc; \
+ rc = progress->COMGETTER(ResultCode)(&iRc); \
+ if (FAILED(iRc)) \
+ { \
+ rc = iRc; \
+ RTMsgError msg; \
+ com::GlueHandleComErrorProgress(progress, __PRETTY_FUNCTION__, iRc, __FILE__, __LINE__); \
+ break; \
+ } \
+ } \
+ else do {} while (0)
+#endif
+
+/**
+ * Does the same as CHECK_PROGRESS_ERROR(), but executes the |return ret|
+ * statement on failure.
+ */
+#define CHECK_PROGRESS_ERROR_RET(progress, msg, ret) \
+ do { \
+ LONG iRc; \
+ progress->COMGETTER(ResultCode)(&iRc); \
+ if (FAILED(iRc)) \
+ { \
+ RTMsgError msg; \
+ com::GlueHandleComErrorProgress(progress, __PRETTY_FUNCTION__, iRc, __FILE__, __LINE__); \
+ return (ret); \
+ } \
+ } while (0)
+
+/**
+ * Asserts the given expression is true. When the expression is false, prints
+ * a line containing the failed function/line/file; otherwise does nothing.
+ */
+#define ASSERT(expr) \
+ do { \
+ if (!(expr)) \
+ { \
+ RTPrintf ("[!] ASSERTION FAILED at line %d: %s\n", __LINE__, #expr); \
+ Log (("[!] ASSERTION FAILED at line %d: %s\n", __LINE__, #expr)); \
+ } \
+ } while (0)
+
+#endif
+
+/**
+ * Does the same as ASSERT(), but executes the |return ret| statement if the
+ * expression to assert is false;
+ */
+#define ASSERT_RET(expr, ret) \
+ do { ASSERT(expr); if (!(expr)) return (ret); } while (0)
+
+/**
+ * Does the same as ASSERT(), but executes the |break| statement if the
+ * expression to assert is false;
+ */
+#define ASSERT_BREAK(expr, ret) \
+ if (1) { ASSERT(expr); if (!(expr)) break; } else do {} while (0)
+
+} /* namespace com */
diff --git a/include/VBox/com/list.h b/include/VBox/com/list.h
new file mode 100644
index 00000000..11a137b5
--- /dev/null
+++ b/include/VBox/com/list.h
@@ -0,0 +1,197 @@
+/* $Id: list.h $ */
+/** @file
+ * MS COM / XPCOM Abstraction Layer - List classes declaration.
+ */
+
+/*
+ * Copyright (C) 2011 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_com_list_h
+#define ___VBox_com_list_h
+
+#include <VBox/com/ptr.h>
+#include <VBox/com/string.h>
+#include <iprt/cpp/list.h>
+
+/**
+ * Specialized list class for using with com::ComPtr<C>
+ *
+ * @note: This is necessary cause ComPtr<IFACE> has a size of 8.
+ */
+template <typename C>
+class RTCList< ComPtr<C> >: public RTCListBase< ComPtr<C>, ComPtr<C>*, false>
+{
+ /* Traits */
+ typedef ComPtr<C> T;
+ typedef T *ITYPE;
+ static const bool MT = false;
+ typedef RTCListBase<T, ITYPE, MT> BASE;
+
+public:
+ /**
+ * Creates a new list.
+ *
+ * This preallocates @a cCapacity elements within the list.
+ *
+ * @param cCapacitiy The initial capacity the list has.
+ * @throws std::bad_alloc
+ */
+ RTCList(size_t cCapacity = BASE::DefaultCapacity)
+ : BASE(cCapacity) {}
+
+ /* Define our own new and delete. */
+ RTMEMEF_NEW_AND_DELETE_OPERATORS();
+};
+
+/**
+ * Specialized list class for using with com::ComObjPtr<C>
+ *
+ * @note: This is necessary cause ComObjPtr<IFACE> has a size of 8.
+ */
+template <typename C>
+class RTCList< ComObjPtr<C> >: public RTCListBase< ComObjPtr<C>, ComObjPtr<C>*, false>
+{
+ /* Traits */
+ typedef ComObjPtr<C> T;
+ typedef T *ITYPE;
+ static const bool MT = false;
+ typedef RTCListBase<T, ITYPE, MT> BASE;
+
+public:
+ /**
+ * Creates a new list.
+ *
+ * This preallocates @a cCapacity elements within the list.
+ *
+ * @param cCapacitiy The initial capacity the list has.
+ * @throws std::bad_alloc
+ */
+ RTCList(size_t cCapacity = BASE::DefaultCapacity)
+ : BASE(cCapacity) {}
+
+ /* Define our own new and delete. */
+ RTMEMEF_NEW_AND_DELETE_OPERATORS();
+};
+
+/**
+ * Specialized list class for using with com::Utf8Str.
+ *
+ * The class offers methods for importing com::SafeArray's of com::Bstr's.
+ */
+template <>
+class RTCList<Utf8Str>: public RTCListBase<Utf8Str, Utf8Str*, false>
+{
+ /* Traits */
+ typedef Utf8Str T;
+ typedef T *ITYPE;
+ static const bool MT = false;
+ typedef RTCListBase<T, ITYPE, MT> BASE;
+
+public:
+ /**
+ * Creates a new list.
+ *
+ * This preallocates @a cCapacity elements within the list.
+ *
+ * @param cCapacitiy The initial capacity the list has.
+ * @throws std::bad_alloc
+ */
+ RTCList(size_t cCapacity = BASE::DefaultCapacity)
+ : BASE(cCapacity) {}
+
+ /**
+ * Creates a copy of another list.
+ *
+ * The other list will be fully copied and the capacity will be the same as
+ * the size of the other list. The com::Bstr's are silently converted to
+ * com::Utf8Str's.
+ *
+ * @param other The list to copy.
+ * @throws std::bad_alloc
+ */
+ RTCList(ComSafeArrayIn(IN_BSTR, other))
+ {
+ com::SafeArray<IN_BSTR> sfaOther(ComSafeArrayInArg(other));
+ realloc(sfaOther.size());
+ m_cSize = sfaOther.size();
+ for (size_t i = 0; i < m_cSize; ++i)
+ RTCListHelper<T, ITYPE>::set(m_pArray, i, T(sfaOther[i]));
+ }
+
+ /**
+ * Creates a copy of another list.
+ *
+ * The other list will be fully copied and the capacity will be the same as
+ * the size of the other list. The com::Bstr's are silently converted to
+ * com::Utf8Str's.
+ *
+ * @param other The list to copy.
+ * @throws std::bad_alloc
+ */
+ RTCList(const com::SafeArray<IN_BSTR> &other)
+ : BASE(other.size())
+ {
+ for (size_t i = 0; i < m_cSize; ++i)
+ RTCListHelper<T, ITYPE>::set(m_pArray, i, T(other[i]));
+ }
+
+ /**
+ * Copy the items of the other list into this list. All previous items of
+ * this list are deleted.
+ *
+ * @param other The list to copy.
+ * @return a reference to this list.
+ * @throws std::bad_alloc
+ */
+ RTCListBase<T, ITYPE, MT> &operator=(const com::SafeArray<IN_BSTR> &other)
+ {
+ m_guard.enterWrite();
+ /* Values cleanup */
+ RTCListHelper<T, ITYPE>::eraseRange(m_pArray, 0, m_cSize);
+ /* Copy */
+ if (other.size() != m_cCapacity)
+ realloc_no_elements_clean(other.size());
+ m_cSize = other.size();
+ for (size_t i = 0; i < other.size(); ++i)
+ RTCListHelper<T, ITYPE>::set(m_pArray, i, T(other[i]));
+ m_guard.leaveWrite();
+
+ return *this;
+ }
+
+ /**
+ * Implicit conversion to a RTCString list.
+ *
+ * This allows the usage of the RTCString::join method with this list type.
+ *
+ * @return a converted const reference to this list.
+ */
+ operator const RTCList<RTCString, RTCString*>&()
+ {
+ return *reinterpret_cast<RTCList<RTCString, RTCString*> *>(this);
+ }
+
+ /* Define our own new and delete. */
+ RTMEMEF_NEW_AND_DELETE_OPERATORS();
+};
+
+#endif /* !___VBox_com_list_h */
+
diff --git a/include/VBox/com/listeners.h b/include/VBox/com/listeners.h
new file mode 100644
index 00000000..419b18fa
--- /dev/null
+++ b/include/VBox/com/listeners.h
@@ -0,0 +1,171 @@
+/* $Id: listeners.h $ */
+/** @file
+ * Listeners helpers.
+ */
+
+/*
+ * Copyright (C) 2010-2011 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_com_listeners_h
+#define ___VBox_com_listeners_h
+
+#include <VBox/com/com.h>
+#include <VBox/com/VirtualBox.h>
+
+#ifdef VBOX_WITH_XPCOM
+# define NS_IMPL_QUERY_HEAD_INLINE() \
+NS_IMETHODIMP QueryInterface(REFNSIID aIID, void **aInstancePtr) \
+{ \
+ NS_ASSERTION(aInstancePtr, "QueryInterface requires a non-NULL destination!"); \
+ nsISupports *foundInterface;
+
+# define NS_INTERFACE_MAP_BEGIN_INLINE() NS_IMPL_QUERY_HEAD_INLINE()
+
+# define NS_IMPL_QUERY_INTERFACE1_INLINE(a_i1) \
+ NS_INTERFACE_MAP_BEGIN_INLINE() \
+ NS_INTERFACE_MAP_ENTRY(a_i1) \
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, a_i1) \
+ NS_INTERFACE_MAP_END
+#endif
+
+template <class T, class TParam = void *>
+class ListenerImpl :
+ public CComObjectRootEx<CComMultiThreadModel>,
+ VBOX_SCRIPTABLE_IMPL(IEventListener)
+{
+ T* mListener;
+
+#ifdef RT_OS_WINDOWS
+ /* FTM stuff */
+ CComPtr <IUnknown> m_pUnkMarshaler;
+#else
+ nsAutoRefCnt mRefCnt;
+ NS_DECL_OWNINGTHREAD
+#endif
+
+public:
+ ListenerImpl()
+ {
+ }
+
+ virtual ~ListenerImpl()
+ {
+ }
+
+ HRESULT init(T* aListener, TParam param)
+ {
+ mListener = aListener;
+ return mListener->init(param);
+ }
+
+ HRESULT init(T* aListener)
+ {
+ mListener = aListener;
+ return mListener->init();
+ }
+
+ void uninit()
+ {
+ if (mListener)
+ {
+ mListener->uninit();
+ delete mListener;
+ mListener = 0;
+ }
+ }
+
+ HRESULT FinalConstruct()
+ {
+#ifdef RT_OS_WINDOWS
+ return CoCreateFreeThreadedMarshaler(this, &m_pUnkMarshaler.p);
+#else
+ return S_OK;
+#endif
+ }
+
+ void FinalRelease()
+ {
+ uninit();
+#ifdef RT_OS_WINDOWS
+ m_pUnkMarshaler.Release();
+#endif
+ }
+
+ T* getWrapped()
+ {
+ return mListener;
+ }
+
+ DECLARE_NOT_AGGREGATABLE(ListenerImpl)
+
+ DECLARE_PROTECT_FINAL_CONSTRUCT()
+
+#ifdef RT_OS_WINDOWS
+ BEGIN_COM_MAP(ListenerImpl)
+ COM_INTERFACE_ENTRY(IEventListener)
+ COM_INTERFACE_ENTRY2(IDispatch, IEventListener)
+ COM_INTERFACE_ENTRY_AGGREGATE(IID_IMarshal, m_pUnkMarshaler.p)
+ END_COM_MAP()
+#else
+ NS_IMETHOD_(nsrefcnt) AddRef(void)
+ {
+ NS_PRECONDITION(PRInt32(mRefCnt) >= 0, "illegal refcnt");
+ nsrefcnt count;
+ count = PR_AtomicIncrement((PRInt32*)&mRefCnt);
+ NS_LOG_ADDREF(this, count, "ListenerImpl", sizeof(*this));
+ return count;
+ }
+
+ NS_IMETHOD_(nsrefcnt) Release(void)
+ {
+ nsrefcnt count;
+ NS_PRECONDITION(0 != mRefCnt, "dup release");
+ count = PR_AtomicDecrement((PRInt32 *)&mRefCnt);
+ NS_LOG_RELEASE(this, count, "ListenerImpl");
+ if (0 == count) {
+ mRefCnt = 1; /* stabilize */
+ /* enable this to find non-threadsafe destructors: */
+ /* NS_ASSERT_OWNINGTHREAD(_class); */
+ NS_DELETEXPCOM(this);
+ return 0;
+ }
+ return count;
+ }
+
+ NS_IMPL_QUERY_INTERFACE1_INLINE(IEventListener)
+#endif
+
+
+ STDMETHOD(HandleEvent)(IEvent * aEvent)
+ {
+ VBoxEventType_T aType = VBoxEventType_Invalid;
+ aEvent->COMGETTER(Type)(&aType);
+ return mListener->HandleEvent(aType, aEvent);
+ }
+};
+
+#ifdef VBOX_WITH_XPCOM
+# define VBOX_LISTENER_DECLARE(klazz) NS_DECL_CLASSINFO(klazz)
+#else
+# define VBOX_LISTENER_DECLARE(klazz)
+#endif
+
+#endif
diff --git a/include/VBox/com/mtlist.h b/include/VBox/com/mtlist.h
new file mode 100644
index 00000000..c4142c5f
--- /dev/null
+++ b/include/VBox/com/mtlist.h
@@ -0,0 +1,197 @@
+/* $Id: mtlist.h $ */
+/** @file
+ * MS COM / XPCOM Abstraction Layer - Thread-safe list classes declaration.
+ */
+
+/*
+ * Copyright (C) 2011 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_com_mtlist_h
+#define ___VBox_com_mtlist_h
+
+#include <VBox/com/ptr.h>
+#include <VBox/com/string.h>
+#include <iprt/cpp/mtlist.h>
+
+/**
+ * Specialized thread-safe list class for using with com::ComPtr<C>
+ *
+ * @note: This is necessary cause ComPtr<IFACE> has a size of 8.
+ */
+template <typename C>
+class RTCMTList< ComPtr<C> >: public RTCListBase< ComPtr<C>, ComPtr<C>*, true>
+{
+ /* Traits */
+ typedef ComPtr<C> T;
+ typedef T *ITYPE;
+ static const bool MT = true;
+ typedef RTCListBase<T, ITYPE, MT> BASE;
+
+public:
+ /**
+ * Creates a new list.
+ *
+ * This preallocates @a cCapacity elements within the list.
+ *
+ * @param cCapacitiy The initial capacity the list has.
+ * @throws std::bad_alloc
+ */
+ RTCList(size_t cCapacity = BASE::DefaultCapacity)
+ : BASE(cCapacity) {}
+
+ /* Define our own new and delete. */
+ RTMEMEF_NEW_AND_DELETE_OPERATORS();
+};
+
+/**
+ * Specialized thread-safe list class for using with com::ComObjPtr<C>
+ *
+ * @note: This is necessary cause ComObjPtr<IFACE> has a size of 8.
+ */
+template <typename C>
+class RTCMTList< ComObjPtr<C> >: public RTCListBase< ComObjPtr<C>, ComObjPtr<C>*, true>
+{
+ /* Traits */
+ typedef ComObjPtr<C> T;
+ typedef T *ITYPE;
+ static const bool MT = true;
+ typedef RTCListBase<T, ITYPE, MT> BASE;
+
+public:
+ /**
+ * Creates a new list.
+ *
+ * This preallocates @a cCapacity elements within the list.
+ *
+ * @param cCapacitiy The initial capacity the list has.
+ * @throws std::bad_alloc
+ */
+ RTCList(size_t cCapacity = BASE::DefaultCapacity)
+ : BASE(cCapacity) {}
+
+ /* Define our own new and delete. */
+ RTMEMEF_NEW_AND_DELETE_OPERATORS();
+};
+
+/**
+ * Specialized thread-safe list class for using with com::Utf8Str.
+ *
+ * The class offers methods for importing com::SafeArray's of com::Bstr's.
+ */
+template <>
+class RTCMTList<Utf8Str>: public RTCListBase<Utf8Str, Utf8Str*, true>
+{
+ /* Traits */
+ typedef Utf8Str T;
+ typedef T *ITYPE;
+ static const bool MT = true;
+ typedef RTCListBase<T, ITYPE, MT> BASE;
+
+public:
+ /**
+ * Creates a new list.
+ *
+ * This preallocates @a cCapacity elements within the list.
+ *
+ * @param cCapacitiy The initial capacity the list has.
+ * @throws std::bad_alloc
+ */
+ RTCMTList(size_t cCapacity = BASE::DefaultCapacity)
+ : BASE(cCapacity) {}
+
+ /**
+ * Creates a copy of another list.
+ *
+ * The other list will be fully copied and the capacity will be the same as
+ * the size of the other list. The com::Bstr's are silently converted to
+ * com::Utf8Str's.
+ *
+ * @param other The list to copy.
+ * @throws std::bad_alloc
+ */
+ RTCMTList(ComSafeArrayIn(IN_BSTR, other))
+ {
+ com::SafeArray<IN_BSTR> sfaOther(ComSafeArrayInArg(other));
+ realloc(sfaOther.size());
+ m_cSize = sfaOther.size();
+ for (size_t i = 0; i < m_cSize; ++i)
+ RTCListHelper<T, ITYPE>::set(m_pArray, i, T(sfaOther[i]));
+ }
+
+ /**
+ * Creates a copy of another list.
+ *
+ * The other list will be fully copied and the capacity will be the same as
+ * the size of the other list. The com::Bstr's are silently converted to
+ * com::Utf8Str's.
+ *
+ * @param other The list to copy.
+ * @throws std::bad_alloc
+ */
+ RTCMTList(const com::SafeArray<IN_BSTR> &other)
+ : BASE(other.size())
+ {
+ for (size_t i = 0; i < m_cSize; ++i)
+ RTCListHelper<T, ITYPE>::set(m_pArray, i, T(other[i]));
+ }
+
+ /**
+ * Copy the items of the other list into this list. All previous items of
+ * this list are deleted.
+ *
+ * @param other The list to copy.
+ * @return a reference to this list.
+ * @throws std::bad_alloc
+ */
+ RTCListBase<T, ITYPE, MT> &operator=(const com::SafeArray<IN_BSTR> &other)
+ {
+ m_guard.enterWrite();
+ /* Values cleanup */
+ RTCListHelper<T, ITYPE>::eraseRange(m_pArray, 0, m_cSize);
+ /* Copy */
+ if (other.size() != m_cCapacity)
+ realloc_no_elements_clean(other.size());
+ m_cSize = other.size();
+ for (size_t i = 0; i < other.size(); ++i)
+ RTCListHelper<T, ITYPE>::set(m_pArray, i, T(other[i]));
+ m_guard.leaveWrite();
+
+ return *this;
+ }
+
+ /**
+ * Implicit conversion to a RTCString list.
+ *
+ * This allows the usage of the RTCString::join method with this list type.
+ *
+ * @return a converted const reference to this list.
+ */
+ operator const RTCMTList<RTCString, RTCString*>&()
+ {
+ return *reinterpret_cast<RTCMTList<RTCString, RTCString*> *>(this);
+ }
+
+ /* Define our own new and delete. */
+ RTMEMEF_NEW_AND_DELETE_OPERATORS();
+};
+
+#endif /* !___VBox_com_mtlist_h */
+
diff --git a/include/VBox/com/ptr.h b/include/VBox/com/ptr.h
new file mode 100644
index 00000000..1942274b
--- /dev/null
+++ b/include/VBox/com/ptr.h
@@ -0,0 +1,493 @@
+/** @file
+ * MS COM / XPCOM Abstraction Layer:
+ * Smart COM pointer classes declaration
+ */
+
+/*
+ * Copyright (C) 2006-2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_com_ptr_h
+#define ___VBox_com_ptr_h
+
+/* Make sure all the stdint.h macros are included - must come first! */
+#ifndef __STDC_LIMIT_MACROS
+# define __STDC_LIMIT_MACROS
+#endif
+#ifndef __STDC_CONSTANT_MACROS
+# define __STDC_CONSTANT_MACROS
+#endif
+
+#if !defined (VBOX_WITH_XPCOM)
+ #include <atlbase.h>
+ #ifndef _ATL_IIDOF
+ # define _ATL_IIDOF(c) __uuidof(c)
+ #endif
+#else
+ #include <nsISupportsUtils.h>
+
+#endif /* !defined (VBOX_WITH_XPCOM) */
+
+#include <VBox/com/defs.h>
+
+#ifdef VBOX_WITH_XPCOM
+
+namespace com
+{
+// declare a couple of XPCOM helper methods (defined in glue/com.cpp)
+// so we don't have to include a ton of XPCOM implementation headers here
+HRESULT GlueCreateObjectOnServer(const CLSID &clsid,
+ const char *serverName,
+ const nsIID &id,
+ void** ppobj);
+HRESULT GlueCreateInstance(const CLSID &clsid,
+ const nsIID &id,
+ void** ppobj);
+}
+
+#endif // VBOX_WITH_XPCOM
+
+/**
+ * COM autopointer class which takes care of all required reference counting.
+ *
+ * This automatically calls the required basic COM methods on COM pointers
+ * given to it:
+ *
+ * -- AddRef() gets called automatically whenever a new COM pointer is assigned
+ * to the ComPtr instance (either in the copy constructor or by assignment);
+ *
+ * -- Release() gets called automatically by the destructor and when an existing
+ * object gets released in assignment;
+ *
+ * -- QueryInterface() gets called automatically when COM pointers get converted
+ * from one interface to another.
+ *
+ * Example usage:
+ *
+ * @code
+ *
+ * {
+ * ComPtr<IMachine> pMachine = findMachine("blah"); // calls AddRef()
+ * ComPtr<IUnknown> pUnknown = pMachine; // calls QueryInterface()
+ * } # ComPtr destructor of both instances calls Release()
+ *
+ * @endcode
+ */
+template <class T>
+class ComPtr
+{
+public:
+
+ /**
+ * Default constructor, sets up a NULL pointer.
+ */
+ ComPtr()
+ : m_p(NULL)
+ { }
+
+ /**
+ * Destructor. Calls Release() on the contained COM object.
+ */
+ ~ComPtr()
+ {
+ cleanup();
+ }
+
+ /**
+ * Copy constructor from another ComPtr of any interface.
+ *
+ * This calls QueryInterface(T) and can result in a NULL pointer if the input
+ * pointer p does not support the ComPtr interface T.
+ *
+ * Does not call AddRef explicitly because if QueryInterface succeeded, then
+ * the refcount will have been increased by one already .
+ */
+ template <class T2>
+ ComPtr(const ComPtr<T2> &that)
+ {
+ m_p = NULL;
+ if (!that.isNull())
+ that->QueryInterface(COM_IIDOF(T), (void**)&m_p);
+ }
+
+ /**
+ * Specialization: copy constructor from another ComPtr<T>. Calls AddRef().
+ */
+ ComPtr(const ComPtr &that)
+ {
+ copyFrom(that.m_p);
+ }
+
+ /**
+ * Copy constructor from another interface pointer of any interface.
+ *
+ * This calls QueryInterface(T) and can result in a NULL pointer if the input
+ * pointer p does not support the ComPtr interface T.
+ *
+ * Does not call AddRef explicitly because if QueryInterface succeeded, then
+ * the refcount will have been increased by one already .
+ */
+ template <class T2>
+ ComPtr(T2 *p)
+ {
+ m_p = NULL;
+ if (p)
+ p->QueryInterface(COM_IIDOF(T), (void**)&m_p);
+ }
+
+ /**
+ * Specialization: copy constructor from a plain T* pointer. Calls AddRef().
+ */
+ ComPtr(T *that_p)
+ {
+ copyFrom(that_p);
+ }
+
+ /**
+ * Assignment from another ComPtr of any interface.
+ *
+ * This calls QueryInterface(T) and can result in a NULL pointer if the input
+ * pointer p does not support the ComPtr interface T.
+ *
+ * Does not call AddRef explicitly because if QueryInterface succeeded, then
+ * the refcount will have been increased by one already .
+ */
+ template <class T2>
+ ComPtr& operator=(const ComPtr<T2> &that)
+ {
+ return operator=((T2*)that);
+ }
+
+ /**
+ * Specialization of the previous: assignment from another ComPtr<T>.
+ * Calls Release() on the previous member pointer, if any, and AddRef() on the new one.
+ */
+ ComPtr& operator=(const ComPtr &that)
+ {
+ return operator=((T*)that);
+ }
+
+ /**
+ * Assignment from another interface pointer of any interface.
+ *
+ * This calls QueryInterface(T) and can result in a NULL pointer if the input
+ * pointer p does not support the ComPtr interface T.
+ *
+ * Does not call AddRef explicitly because if QueryInterface succeeded, then
+ * the refcount will have been increased by one already .
+ */
+ template <class T2>
+ ComPtr& operator=(T2 *p)
+ {
+ cleanup();
+ if (p)
+ p->QueryInterface(COM_IIDOF(T), (void**)&m_p);
+ return *this;
+ }
+
+ /**
+ * Specialization of the previous: assignment from a plain T* pointer.
+ * Calls Release() on the previous member pointer, if any, and AddRef() on the new one.
+ */
+ ComPtr& operator=(T *p)
+ {
+ cleanup();
+ copyFrom(p);
+ return *this;
+ }
+
+ /**
+ * Resets the ComPtr to NULL. Works like a NULL assignment except it avoids the templates.
+ */
+ void setNull()
+ {
+ cleanup();
+ }
+
+ /**
+ * Returns true if the pointer is NULL.
+ */
+ bool isNull() const
+ {
+ return (m_p == NULL);
+ }
+
+ bool operator<(T* p) const
+ {
+ return m_p < p;
+ }
+
+ /**
+ * Conversion operator, most often used to pass ComPtr instances as
+ * parameters to COM method calls.
+ */
+ operator T*() const
+ {
+ return m_p;
+ }
+
+ /**
+ * Dereferences the instance (redirects the -> operator to the managed
+ * pointer).
+ */
+ T* operator->() const
+ {
+ return m_p;
+ }
+
+ /**
+ * Special method which allows using a ComPtr as an output argument of a COM method.
+ * The ComPtr will then accept the method's interface pointer without calling AddRef()
+ * itself, since by COM convention this must has been done by the method which created
+ * the object that is being accepted.
+ *
+ * The ComPtr destructor will then still invoke Release() so that the returned object
+ * can get cleaned up properly.
+ */
+ T** asOutParam()
+ {
+ cleanup();
+ return &m_p;
+ }
+
+ /**
+ * Converts the contained pointer to a different interface
+ * by calling QueryInterface() on it.
+ * @param pp
+ * @return
+ */
+ template <class T2>
+ HRESULT queryInterfaceTo(T2 **pp) const
+ {
+ if (pp)
+ {
+ if (m_p)
+ return m_p->QueryInterface(COM_IIDOF(T2), (void**)pp);
+ else
+ {
+ *pp = NULL;
+ return S_OK;
+ }
+ }
+
+ return E_INVALIDARG;
+ }
+
+ /**
+ * Equality test operator. By COM definition, two COM objects are considered
+ * equal if their IUnknown interface pointers are equal.
+ */
+ template <class T2>
+ bool operator==(T2* p)
+ {
+ IUnknown *p1 = NULL;
+ bool fNeedsRelease1 = false;
+ if (m_p)
+ fNeedsRelease1 = (SUCCEEDED(m_p->QueryInterface(COM_IIDOF(IUnknown), (void**)&p1)));
+
+ IUnknown *p2 = NULL;
+ bool fNeedsRelease2 = false;
+ if (p)
+ fNeedsRelease2 = (SUCCEEDED(p->QueryInterface(COM_IIDOF(IUnknown), (void**)&p2)));
+
+ bool f = p1 == p2;
+ if (fNeedsRelease1)
+ p1->Release();
+ if (fNeedsRelease2)
+ p2->Release();
+ return f;
+ }
+
+ /**
+ * Creates an in-process object of the given class ID and starts to
+ * manage a reference to the created object in case of success.
+ */
+ HRESULT createInprocObject(const CLSID &clsid)
+ {
+ HRESULT rc;
+ T *obj = NULL;
+#if !defined (VBOX_WITH_XPCOM)
+ rc = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, _ATL_IIDOF(T),
+ (void**)&obj);
+#else /* !defined (VBOX_WITH_XPCOM) */
+ using namespace com;
+ rc = GlueCreateInstance(clsid, NS_GET_IID(T), (void**)&obj);
+#endif /* !defined (VBOX_WITH_XPCOM) */
+ *this = obj;
+ if (SUCCEEDED(rc))
+ obj->Release();
+ return rc;
+ }
+
+ /**
+ * Creates a local (out-of-process) object of the given class ID and starts
+ * to manage a reference to the created object in case of success.
+ *
+ * Note: In XPCOM, the out-of-process functionality is currently emulated
+ * through in-process wrapper objects (that start a dedicated process and
+ * redirect all object requests to that process). For this reason, this
+ * method is fully equivalent to #createInprocObject() for now.
+ */
+ HRESULT createLocalObject(const CLSID &clsid)
+ {
+#if !defined (VBOX_WITH_XPCOM)
+ HRESULT rc;
+ T *obj = NULL;
+ rc = CoCreateInstance(clsid, NULL, CLSCTX_LOCAL_SERVER, _ATL_IIDOF(T),
+ (void**)&obj);
+ *this = obj;
+ if (SUCCEEDED(rc))
+ obj->Release();
+ return rc;
+#else /* !defined (VBOX_WITH_XPCOM) */
+ return createInprocObject(clsid);
+#endif /* !defined (VBOX_WITH_XPCOM) */
+ }
+
+#ifdef VBOX_WITH_XPCOM
+ /**
+ * Creates an object of the given class ID on the specified server and
+ * starts to manage a reference to the created object in case of success.
+ *
+ * @param serverName Name of the server to create an object within.
+ */
+ HRESULT createObjectOnServer(const CLSID &clsid, const char *serverName)
+ {
+ T *obj = NULL;
+ HRESULT rc = GlueCreateObjectOnServer(clsid, serverName, NS_GET_IID(T), (void**)&obj);
+ *this = obj;
+ if (SUCCEEDED(rc))
+ obj->Release();
+ return rc;
+ }
+#endif
+
+protected:
+ void copyFrom(T* p)
+ {
+ m_p = p;
+ if (m_p)
+ m_p->AddRef();
+ }
+
+ void cleanup()
+ {
+ if (m_p)
+ {
+ m_p->Release();
+ m_p = NULL;
+ }
+ }
+
+ T *m_p;
+};
+
+/**
+ * ComObjPtr is a more specialized variant of ComPtr designed to be used for implementation
+ * objects. For example, use ComPtr<IMachine> for a client pointer that calls the interface
+ * but ComObjPtr<Machine> for a pointer to an implementation object.
+ *
+ * The methods behave the same except that ComObjPtr has the additional createObject()
+ * method which allows for instantiating a new implementation object.
+ *
+ * Note: To convert a ComObjPtr<InterfaceImpl> to a ComObj<IInterface> you have
+ * to query the interface. See the following example code for the IProgress
+ * interface:
+ *
+ * @code
+ *
+ * {
+ * ComObjPtr<Progress> pProgress; // create the server side object
+ * pProgress.createObject(); // ...
+ * pProgress->init(...); // ...
+ * ComPtr<IProgress> pProgress2; // create an interface pointer
+ * pProgress.queryInterfaceTo(pProgress2.asOutParam()); // transfer the interface
+ * }
+ *
+ * @endcode
+ */
+template <class T>
+class ComObjPtr : public ComPtr<T>
+{
+public:
+
+ ComObjPtr()
+ : ComPtr<T>()
+ {}
+
+ ComObjPtr(const ComObjPtr &that)
+ : ComPtr<T>(that)
+ {}
+
+ ComObjPtr(T *that_p)
+ : ComPtr<T>(that_p)
+ {}
+
+ ComObjPtr& operator=(const ComObjPtr &that)
+ {
+ ComPtr<T>::operator=(that);
+ return *this;
+ }
+
+ ComObjPtr& operator=(T *that_p)
+ {
+ ComPtr<T>::operator=(that_p);
+ return *this;
+ }
+
+ /**
+ * Creates a new server-side object of the given component class and
+ * immediately starts to manage a pointer to the created object (the
+ * previous pointer, if any, is of course released when appropriate).
+ *
+ * @note Win32: when VBOX_COM_OUTOFPROC_MODULE is defined, the created
+ * object doesn't increase the lock count of the server module, as it
+ * does otherwise.
+ */
+ HRESULT createObject()
+ {
+ HRESULT rc;
+#if !defined (VBOX_WITH_XPCOM)
+# ifdef VBOX_COM_OUTOFPROC_MODULE
+ CComObjectNoLock<T> *obj = new CComObjectNoLock<T>();
+ if (obj)
+ {
+ obj->InternalFinalConstructAddRef();
+ rc = obj->FinalConstruct();
+ obj->InternalFinalConstructRelease();
+ }
+ else
+ rc = E_OUTOFMEMORY;
+# else
+ CComObject<T> *obj = NULL;
+ rc = CComObject<T>::CreateInstance(&obj);
+# endif
+#else /* !defined (VBOX_WITH_XPCOM) */
+ CComObject<T> *obj = new CComObject<T>();
+ if (obj)
+ rc = obj->FinalConstruct();
+ else
+ rc = E_OUTOFMEMORY;
+#endif /* !defined (VBOX_WITH_XPCOM) */
+ *this = obj;
+ return rc;
+ }
+};
+#endif
diff --git a/include/VBox/com/string.h b/include/VBox/com/string.h
new file mode 100644
index 00000000..3462818e
--- /dev/null
+++ b/include/VBox/com/string.h
@@ -0,0 +1,810 @@
+/* $Id: string.h $ */
+/** @file
+ * MS COM / XPCOM Abstraction Layer - Smart string classes declaration.
+ */
+
+/*
+ * Copyright (C) 2006-2012 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_com_string_h
+#define ___VBox_com_string_h
+
+/* Make sure all the stdint.h macros are included - must come first! */
+#ifndef __STDC_LIMIT_MACROS
+# define __STDC_LIMIT_MACROS
+#endif
+#ifndef __STDC_CONSTANT_MACROS
+# define __STDC_CONSTANT_MACROS
+#endif
+
+#if defined(VBOX_WITH_XPCOM)
+# include <nsMemory.h>
+#endif
+
+#include "VBox/com/defs.h"
+#include "VBox/com/assert.h"
+
+#include <iprt/mem.h>
+#include <iprt/cpp/ministring.h>
+
+namespace com
+{
+
+class Utf8Str;
+
+// global constant in glue/string.cpp that represents an empty BSTR
+extern const BSTR g_bstrEmpty;
+
+/**
+ * String class used universally in Main for COM-style Utf-16 strings.
+ *
+ * Unfortunately COM on Windows uses UTF-16 everywhere, requiring conversions
+ * back and forth since most of VirtualBox and our libraries use UTF-8.
+ *
+ * To make things more obscure, on Windows, a COM-style BSTR is not just a
+ * pointer to a null-terminated wide character array, but the four bytes (32
+ * bits) BEFORE the memory that the pointer points to are a length DWORD. One
+ * must therefore avoid pointer arithmetic and always use SysAllocString and
+ * the like to deal with BSTR pointers, which manage that DWORD correctly.
+ *
+ * For platforms other than Windows, we provide our own versions of the Sys*
+ * functions in Main/xpcom/helpers.cpp which do NOT use length prefixes though
+ * to be compatible with how XPCOM allocates string parameters to public
+ * functions.
+ *
+ * The Bstr class hides all this handling behind a std::string-like interface
+ * and also provides automatic conversions to RTCString and Utf8Str instances.
+ *
+ * The one advantage of using the SysString* routines is that this makes it
+ * possible to use it as a type of member variables of COM/XPCOM components and
+ * pass their values to callers through component methods' output parameters
+ * using the #cloneTo() operation. Also, the class can adopt (take ownership
+ * of) string buffers returned in output parameters of COM methods using the
+ * #asOutParam() operation and correctly free them afterwards.
+ *
+ * Starting with VirtualBox 3.2, like Utf8Str, Bstr no longer differentiates
+ * between NULL strings and empty strings. In other words, Bstr("") and
+ * Bstr(NULL) behave the same. In both cases, Bstr allocates no memory,
+ * reports a zero length and zero allocated bytes for both, and returns an
+ * empty C wide string from raw().
+ *
+ * @note All Bstr methods ASSUMES valid UTF-16 or UTF-8 input strings.
+ * The VirtualBox policy in this regard is to validate strings coming
+ * from external sources before passing them to Bstr or Utf8Str.
+ */
+class Bstr
+{
+public:
+
+ Bstr()
+ : m_bstr(NULL)
+ { }
+
+ Bstr(const Bstr &that)
+ {
+ copyFrom((const OLECHAR *)that.m_bstr);
+ }
+
+ Bstr(CBSTR that)
+ {
+ copyFrom((const OLECHAR *)that);
+ }
+
+#if defined(VBOX_WITH_XPCOM)
+ Bstr(const wchar_t *that)
+ {
+ AssertCompile(sizeof(wchar_t) == sizeof(OLECHAR));
+ copyFrom((const OLECHAR *)that);
+ }
+#endif
+
+ Bstr(const RTCString &that)
+ {
+ copyFrom(that.c_str());
+ }
+
+ Bstr(const char *that)
+ {
+ copyFrom(that);
+ }
+
+ Bstr(const char *a_pThat, size_t a_cchMax)
+ {
+ copyFromN(a_pThat, a_cchMax);
+ }
+
+ ~Bstr()
+ {
+ setNull();
+ }
+
+ Bstr& operator=(const Bstr &that)
+ {
+ cleanup();
+ copyFrom((const OLECHAR *)that.m_bstr);
+ return *this;
+ }
+
+ Bstr& operator=(CBSTR that)
+ {
+ cleanup();
+ copyFrom((const OLECHAR *)that);
+ return *this;
+ }
+
+#if defined(VBOX_WITH_XPCOM)
+ Bstr& operator=(const wchar_t *that)
+ {
+ cleanup();
+ copyFrom((const OLECHAR *)that);
+ return *this;
+ }
+#endif
+
+ Bstr& setNull()
+ {
+ cleanup();
+ return *this;
+ }
+
+#ifdef _MSC_VER
+# if _MSC_VER >= 1400
+ RTMEMEF_NEW_AND_DELETE_OPERATORS();
+# endif
+#else
+ RTMEMEF_NEW_AND_DELETE_OPERATORS();
+#endif
+
+ /** Case sensitivity selector. */
+ enum CaseSensitivity
+ {
+ CaseSensitive,
+ CaseInsensitive
+ };
+
+ /**
+ * Compares the member string to str.
+ * @param str
+ * @param cs Whether comparison should be case-sensitive.
+ * @return
+ */
+ int compare(CBSTR str, CaseSensitivity cs = CaseSensitive) const
+ {
+ if (cs == CaseSensitive)
+ return ::RTUtf16Cmp((PRTUTF16)m_bstr, (PRTUTF16)str);
+ return ::RTUtf16LocaleICmp((PRTUTF16)m_bstr, (PRTUTF16)str);
+ }
+
+ int compare(BSTR str, CaseSensitivity cs = CaseSensitive) const
+ {
+ return compare((CBSTR)str, cs);
+ }
+
+ int compare(const Bstr &that, CaseSensitivity cs = CaseSensitive) const
+ {
+ return compare(that.m_bstr, cs);
+ }
+
+ bool operator==(const Bstr &that) const { return !compare(that.m_bstr); }
+ bool operator!=(const Bstr &that) const { return !!compare(that.m_bstr); }
+ bool operator==(CBSTR that) const { return !compare(that); }
+ bool operator==(BSTR that) const { return !compare(that); }
+
+ bool operator!=(CBSTR that) const { return !!compare(that); }
+ bool operator!=(BSTR that) const { return !!compare(that); }
+ bool operator<(const Bstr &that) const { return compare(that.m_bstr) < 0; }
+ bool operator<(CBSTR that) const { return compare(that) < 0; }
+ bool operator<(BSTR that) const { return compare(that) < 0; }
+
+ /**
+ * Returns true if the member string has no length.
+ * This is true for instances created from both NULL and "" input strings.
+ *
+ * @note Always use this method to check if an instance is empty. Do not
+ * use length() because that may need to run through the entire string
+ * (Bstr does not cache string lengths).
+ */
+ bool isEmpty() const { return m_bstr == NULL || *m_bstr == 0; }
+
+ /**
+ * Returns true if the member string has a length of one or more.
+ *
+ * @returns true if not empty, false if empty (NULL or "").
+ */
+ bool isNotEmpty() const { return m_bstr != NULL && *m_bstr != 0; }
+
+ size_t length() const { return isEmpty() ? 0 : ::RTUtf16Len((PRTUTF16)m_bstr); }
+
+#if defined(VBOX_WITH_XPCOM)
+ /**
+ * Returns a pointer to the raw member UTF-16 string. If the member string is empty,
+ * returns a pointer to a global variable containing an empty BSTR with a proper zero
+ * length prefix so that Windows is happy.
+ */
+ CBSTR raw() const
+ {
+ if (m_bstr)
+ return m_bstr;
+
+ return g_bstrEmpty;
+ }
+#else
+ /**
+ * Windows-only hack, as the automatically generated headers use BSTR.
+ * So if we don't want to cast like crazy we have to be more loose than
+ * on XPCOM.
+ *
+ * Returns a pointer to the raw member UTF-16 string. If the member string is empty,
+ * returns a pointer to a global variable containing an empty BSTR with a proper zero
+ * length prefix so that Windows is happy.
+ */
+ BSTR raw() const
+ {
+ if (m_bstr)
+ return m_bstr;
+
+ return g_bstrEmpty;
+ }
+#endif
+
+ /**
+ * Returns a non-const raw pointer that allows to modify the string directly.
+ * As opposed to raw(), this DOES return NULL if the member string is empty
+ * because we cannot return a mutable pointer to the global variable with the
+ * empty string.
+ *
+ * @warning
+ * Be sure not to modify data beyond the allocated memory! The
+ * guaranteed size of the allocated memory is at least #length()
+ * bytes after creation and after every assignment operation.
+ */
+ BSTR mutableRaw() { return m_bstr; }
+
+ /**
+ * Intended to assign copies of instances to |BSTR| out parameters from
+ * within the interface method. Transfers the ownership of the duplicated
+ * string to the caller.
+ *
+ * If the member string is empty, this allocates an empty BSTR in *pstr
+ * (i.e. makes it point to a new buffer with a null byte).
+ *
+ * @deprecated Use cloneToEx instead to avoid throwing exceptions.
+ */
+ void cloneTo(BSTR *pstr) const
+ {
+ if (pstr)
+ {
+ *pstr = ::SysAllocString((const OLECHAR *)raw()); // raw() returns a pointer to "" if empty
+#ifdef RT_EXCEPTIONS_ENABLED
+ if (!*pstr)
+ throw std::bad_alloc();
+#endif
+ }
+ }
+
+ /**
+ * A version of cloneTo that does not throw any out of memory exceptions, but
+ * returns E_OUTOFMEMORY intead.
+ * @returns S_OK or E_OUTOFMEMORY.
+ */
+ HRESULT cloneToEx(BSTR *pstr) const
+ {
+ if (!pstr)
+ return S_OK;
+ *pstr = ::SysAllocString((const OLECHAR *)raw()); // raw() returns a pointer to "" if empty
+ return pstr ? S_OK : E_OUTOFMEMORY;
+ }
+
+ /**
+ * Intended to assign instances to |BSTR| out parameters from within the
+ * interface method. Transfers the ownership of the original string to the
+ * caller and resets the instance to null.
+ *
+ * As opposed to cloneTo(), this method doesn't create a copy of the
+ * string.
+ *
+ * If the member string is empty, this allocates an empty BSTR in *pstr
+ * (i.e. makes it point to a new buffer with a null byte).
+ *
+ * @param pbstrDst The BSTR variable to detach the string to.
+ *
+ * @throws std::bad_alloc if we failed to allocate a new empty string.
+ */
+ void detachTo(BSTR *pbstrDst)
+ {
+ if (m_bstr)
+ {
+ *pbstrDst = m_bstr;
+ m_bstr = NULL;
+ }
+ else
+ {
+ // allocate null BSTR
+ *pbstrDst = ::SysAllocString((const OLECHAR *)g_bstrEmpty);
+#ifdef RT_EXCEPTIONS_ENABLED
+ if (!*pbstrDst)
+ throw std::bad_alloc();
+#endif
+ }
+ }
+
+ /**
+ * A version of detachTo that does not throw exceptions on out-of-memory
+ * conditions, but instead returns E_OUTOFMEMORY.
+ *
+ * @param pbstrDst The BSTR variable to detach the string to.
+ * @returns S_OK or E_OUTOFMEMORY.
+ */
+ HRESULT detachToEx(BSTR *pbstrDst)
+ {
+ if (m_bstr)
+ {
+ *pbstrDst = m_bstr;
+ m_bstr = NULL;
+ }
+ else
+ {
+ // allocate null BSTR
+ *pbstrDst = ::SysAllocString((const OLECHAR *)g_bstrEmpty);
+ if (!*pbstrDst)
+ return E_OUTOFMEMORY;
+ }
+ return S_OK;
+ }
+
+ /**
+ * Intended to pass instances as |BSTR| out parameters to methods.
+ * Takes the ownership of the returned data.
+ */
+ BSTR *asOutParam()
+ {
+ cleanup();
+ return &m_bstr;
+ }
+
+ /**
+ * Static immutable empty-string object. May be used for comparison purposes.
+ */
+ static const Bstr Empty;
+
+protected:
+
+ void cleanup()
+ {
+ if (m_bstr)
+ {
+ ::SysFreeString(m_bstr);
+ m_bstr = NULL;
+ }
+ }
+
+ /**
+ * Protected internal helper to copy a string. This ignores the previous object
+ * state, so either call this from a constructor or call cleanup() first.
+ *
+ * This variant copies from a zero-terminated UTF-16 string (which need not
+ * be a BSTR, i.e. need not have a length prefix).
+ *
+ * If the source is empty, this sets the member string to NULL.
+ *
+ * @param a_bstrSrc The source string. The caller guarantees
+ * that this is valid UTF-16.
+ *
+ * @throws std::bad_alloc - the object is representing an empty string.
+ */
+ void copyFrom(const OLECHAR *a_bstrSrc)
+ {
+ if (a_bstrSrc && *a_bstrSrc)
+ {
+ m_bstr = ::SysAllocString(a_bstrSrc);
+#ifdef RT_EXCEPTIONS_ENABLED
+ if (!m_bstr)
+ throw std::bad_alloc();
+#endif
+ }
+ else
+ m_bstr = NULL;
+ }
+
+ /**
+ * Protected internal helper to copy a string. This ignores the previous object
+ * state, so either call this from a constructor or call cleanup() first.
+ *
+ * This variant copies and converts from a zero-terminated UTF-8 string.
+ *
+ * If the source is empty, this sets the member string to NULL.
+ *
+ * @param a_pszSrc The source string. The caller guarantees
+ * that this is valid UTF-8.
+ *
+ * @throws std::bad_alloc - the object is representing an empty string.
+ */
+ void copyFrom(const char *a_pszSrc)
+ {
+ copyFromN(a_pszSrc, RTSTR_MAX);
+ }
+
+ /**
+ * Variant of copyFrom for sub-string constructors.
+ *
+ * @param a_pszSrc The source string. The caller guarantees
+ * that this is valid UTF-8.
+ * @param a_cchMax The maximum number of chars (not
+ * codepoints) to copy. If you pass RTSTR_MAX
+ * it'll be exactly like copyFrom().
+ *
+ * @throws std::bad_alloc - the object is representing an empty string.
+ */
+ void copyFromN(const char *a_pszSrc, size_t a_cchSrc);
+
+ BSTR m_bstr;
+
+ friend class Utf8Str; /* to access our raw_copy() */
+};
+
+/* symmetric compare operators */
+inline bool operator==(CBSTR l, const Bstr &r) { return r.operator==(l); }
+inline bool operator!=(CBSTR l, const Bstr &r) { return r.operator!=(l); }
+inline bool operator==(BSTR l, const Bstr &r) { return r.operator==(l); }
+inline bool operator!=(BSTR l, const Bstr &r) { return r.operator!=(l); }
+
+
+
+
+/**
+ * String class used universally in Main for UTF-8 strings.
+ *
+ * This is based on RTCString, to which some functionality has been
+ * moved. Here we keep things that are specific to Main, such as conversions
+ * with UTF-16 strings (Bstr).
+ *
+ * Like RTCString, Utf8Str does not differentiate between NULL strings
+ * and empty strings. In other words, Utf8Str("") and Utf8Str(NULL) behave the
+ * same. In both cases, RTCString allocates no memory, reports
+ * a zero length and zero allocated bytes for both, and returns an empty
+ * C string from c_str().
+ *
+ * @note All Utf8Str methods ASSUMES valid UTF-8 or UTF-16 input strings.
+ * The VirtualBox policy in this regard is to validate strings coming
+ * from external sources before passing them to Utf8Str or Bstr.
+ */
+class Utf8Str : public RTCString
+{
+public:
+
+ Utf8Str() {}
+
+ Utf8Str(const RTCString &that)
+ : RTCString(that)
+ {}
+
+ Utf8Str(const char *that)
+ : RTCString(that)
+ {}
+
+ Utf8Str(const Bstr &that)
+ {
+ copyFrom(that.raw());
+ }
+
+ Utf8Str(CBSTR that)
+ {
+ copyFrom(that);
+ }
+
+ Utf8Str(const char *a_pszSrc, size_t a_cchSrc)
+ : RTCString(a_pszSrc, a_cchSrc)
+ {
+ }
+
+ /**
+ * Constructs a new string given the format string and the list of the
+ * arguments for the format string.
+ *
+ * @param a_pszFormat Pointer to the format string (UTF-8),
+ * @see pg_rt_str_format.
+ * @param a_va Argument vector containing the arguments
+ * specified by the format string.
+ * @sa RTCString::printfV
+ */
+ Utf8Str(const char *a_pszFormat, va_list a_va)
+ : RTCString(a_pszFormat, a_va)
+ {
+ }
+
+ Utf8Str& operator=(const RTCString &that)
+ {
+ RTCString::operator=(that);
+ return *this;
+ }
+
+ Utf8Str& operator=(const char *that)
+ {
+ RTCString::operator=(that);
+ return *this;
+ }
+
+ Utf8Str& operator=(const Bstr &that)
+ {
+ cleanup();
+ copyFrom(that.raw());
+ return *this;
+ }
+
+ Utf8Str& operator=(CBSTR that)
+ {
+ cleanup();
+ copyFrom(that);
+ return *this;
+ }
+
+ bool operator<(const RTCString &that) const { return RTCString::operator<(that); }
+
+ /**
+ * Extended assignment method that returns a COM status code instead of an
+ * exception on failure.
+ *
+ * @returns S_OK or E_OUTOFMEMORY.
+ * @param a_rSrcStr The source string
+ */
+ HRESULT assignEx(Utf8Str const &a_rSrcStr)
+ {
+ return copyFromExNComRC(a_rSrcStr.m_psz, a_rSrcStr.m_cch);
+ }
+
+ /**
+ * Extended assignment method that returns a COM status code instead of an
+ * exception on failure.
+ *
+ * @returns S_OK, E_OUTOFMEMORY or E_INVALIDARG.
+ * @param a_pcszSrc The source string
+ * @param a_offSrc The character (byte) offset of the substring.
+ * @param a_cchSrc The number of characters (bytes) to copy from the source
+ * string.
+ */
+ HRESULT assignEx(Utf8Str const &a_rSrcStr, size_t a_offSrc, size_t a_cchSrc)
+ {
+ if ( a_offSrc + a_cchSrc > a_rSrcStr.m_cch
+ || a_offSrc > a_rSrcStr.m_cch)
+ return E_INVALIDARG;
+ return copyFromExNComRC(a_rSrcStr.m_psz, a_rSrcStr.m_cch);
+ }
+
+ /**
+ * Extended assignment method that returns a COM status code instead of an
+ * exception on failure.
+ *
+ * @returns S_OK or E_OUTOFMEMORY.
+ * @param a_pcszSrc The source string
+ */
+ HRESULT assignEx(const char *a_pcszSrc)
+ {
+ return copyFromExNComRC(a_pcszSrc, a_pcszSrc ? strlen(a_pcszSrc) : 0);
+ }
+
+ /**
+ * Extended assignment method that returns a COM status code instead of an
+ * exception on failure.
+ *
+ * @returns S_OK or E_OUTOFMEMORY.
+ * @param a_pcszSrc The source string
+ * @param a_cchSrc The number of characters (bytes) to copy from the source
+ * string.
+ */
+ HRESULT assignEx(const char *a_pcszSrc, size_t a_cchSrc)
+ {
+ return copyFromExNComRC(a_pcszSrc, a_cchSrc);
+ }
+
+ RTMEMEF_NEW_AND_DELETE_OPERATORS();
+
+#if defined(VBOX_WITH_XPCOM)
+ /**
+ * Intended to assign instances to |char *| out parameters from within the
+ * interface method. Transfers the ownership of the duplicated string to the
+ * caller.
+ *
+ * This allocates a single 0 byte in the target if the member string is empty.
+ *
+ * This uses XPCOM memory allocation and thus only works on XPCOM. MSCOM doesn't
+ * like char* strings anyway.
+ */
+ void cloneTo(char **pstr) const;
+
+ /**
+ * A version of cloneTo that does not throw allocation errors but returns
+ * E_OUTOFMEMORY instead.
+ * @returns S_OK or E_OUTOFMEMORY (COM status codes).
+ */
+ HRESULT cloneToEx(char **pstr) const;
+#endif
+
+ /**
+ * Intended to assign instances to |BSTR| out parameters from within the
+ * interface method. Transfers the ownership of the duplicated string to the
+ * caller.
+ */
+ void cloneTo(BSTR *pstr) const
+ {
+ if (pstr)
+ {
+ Bstr bstr(*this);
+ bstr.cloneTo(pstr);
+ }
+ }
+
+ /**
+ * A version of cloneTo that does not throw allocation errors but returns
+ * E_OUTOFMEMORY instead.
+ *
+ * @param pbstr Where to store a clone of the string.
+ * @returns S_OK or E_OUTOFMEMORY (COM status codes).
+ */
+ HRESULT cloneToEx(BSTR *pbstr) const
+ {
+ if (!pbstr)
+ return S_OK;
+ Bstr bstr(*this);
+ return bstr.detachToEx(pbstr);
+ }
+
+ /**
+ * Safe assignment from BSTR.
+ *
+ * @param pbstrSrc The source string.
+ * @returns S_OK or E_OUTOFMEMORY (COM status codes).
+ */
+ HRESULT cloneEx(CBSTR pbstrSrc)
+ {
+ cleanup();
+ return copyFromEx(pbstrSrc);
+ }
+
+ /**
+ * Removes a trailing slash from the member string, if present.
+ * Calls RTPathStripTrailingSlash() without having to mess with mutableRaw().
+ */
+ Utf8Str& stripTrailingSlash();
+
+ /**
+ * Removes a trailing filename from the member string, if present.
+ * Calls RTPathStripFilename() without having to mess with mutableRaw().
+ */
+ Utf8Str& stripFilename();
+
+ /**
+ * Removes the path component from the member string, if present.
+ * Calls RTPathFilename() without having to mess with mutableRaw().
+ */
+ Utf8Str& stripPath();
+
+ /**
+ * Removes a trailing file name extension from the member string, if present.
+ * Calls RTPathStripExt() without having to mess with mutableRaw().
+ */
+ Utf8Str& stripExt();
+
+ /**
+ * Static immutable empty-string object. May be used for comparison purposes.
+ */
+ static const Utf8Str Empty;
+protected:
+
+ void copyFrom(CBSTR a_pbstr);
+ HRESULT copyFromEx(CBSTR a_pbstr);
+ HRESULT copyFromExNComRC(const char *a_pcszSrc, size_t a_cchSrc);
+
+ friend class Bstr; /* to access our raw_copy() */
+};
+
+/**
+ * Class with RTCString::printf as constructor for your convenience.
+ *
+ * Constructing a Utf8Str string object from a format string and a variable
+ * number of arguments can easily be confused with the other Utf8Str
+ * constructures, thus this child class.
+ *
+ * The usage of this class is like the following:
+ * @code
+ Utf8StrFmt strName("program name = %s", argv[0]);
+ @endcode
+ */
+class Utf8StrFmt : public Utf8Str
+{
+public:
+
+ /**
+ * Constructs a new string given the format string and the list of the
+ * arguments for the format string.
+ *
+ * @param a_pszFormat Pointer to the format string (UTF-8),
+ * @see pg_rt_str_format.
+ * @param ... Ellipsis containing the arguments specified by
+ * the format string.
+ */
+ explicit Utf8StrFmt(const char *a_pszFormat, ...)
+ {
+ va_list va;
+ va_start(va, a_pszFormat);
+ printfV(a_pszFormat, va);
+ va_end(va);
+ }
+
+ RTMEMEF_NEW_AND_DELETE_OPERATORS();
+
+protected:
+ Utf8StrFmt()
+ { }
+
+private:
+};
+
+/**
+ * The BstrFmt class is a shortcut to <tt>Bstr(Utf8StrFmt(...))</tt>.
+ */
+class BstrFmt : public Bstr
+{
+public:
+
+ /**
+ * Constructs a new string given the format string and the list of the
+ * arguments for the format string.
+ *
+ * @param aFormat printf-like format string (in UTF-8 encoding).
+ * @param ... List of the arguments for the format string.
+ */
+ explicit BstrFmt(const char *aFormat, ...)
+ {
+ va_list args;
+ va_start(args, aFormat);
+ copyFrom(Utf8Str(aFormat, args).c_str());
+ va_end(args);
+ }
+
+ RTMEMEF_NEW_AND_DELETE_OPERATORS();
+};
+
+/**
+ * The BstrFmtVA class is a shortcut to <tt>Bstr(Utf8Str(format,va))</tt>.
+ */
+class BstrFmtVA : public Bstr
+{
+public:
+
+ /**
+ * Constructs a new string given the format string and the list of the
+ * arguments for the format string.
+ *
+ * @param aFormat printf-like format string (in UTF-8 encoding).
+ * @param aArgs List of arguments for the format string
+ */
+ BstrFmtVA(const char *aFormat, va_list aArgs)
+ {
+ copyFrom(Utf8Str(aFormat, aArgs).c_str());
+ }
+
+ RTMEMEF_NEW_AND_DELETE_OPERATORS();
+};
+
+} /* namespace com */
+
+#endif /* !___VBox_com_string_h */
+