1
0
Fork 0

Adding upstream version 7.0.20-dfsg.

Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
This commit is contained in:
Daniel Baumann 2025-06-22 09:56:04 +02:00
parent d0c7daf57c
commit df1bda4fe9
Signed by: daniel.baumann
GPG key ID: BCC918A2ABD66424
26643 changed files with 10005219 additions and 0 deletions

704
include/VBox/com/AutoLock.h Normal file
View file

@ -0,0 +1,704 @@
/** @file
* MS COM / XPCOM Abstraction Layer - Automatic locks, implementation.
*/
/*
* Copyright (C) 2006-2023 Oracle and/or its affiliates.
*
* This file is part of VirtualBox base platform packages, as
* available from https://www.virtualbox.org.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation, in version 3 of the
* License.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses>.
*
* The contents of this file may alternatively be used under the terms
* of the Common Development and Distribution License Version 1.0
* (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
* in the VirtualBox 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.
*
* SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
*/
#ifndef VBOX_INCLUDED_com_AutoLock_h
#define VBOX_INCLUDED_com_AutoLock_h
#ifndef RT_WITHOUT_PRAGMA_ONCE
# pragma once
#endif
#include <iprt/types.h>
/** @defgroup grp_com_autolock Automatic Locks
* @ingroup grp_com
* @{
*/
// 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)
LOCKCLASS_TRANSLATOR = 13 // translator internal lock
};
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 @c true if the current thread holds a read lock on this
* read/write semaphore. Intended for debugging only as it isn't always
* accurate given @a fWannaHear.
*/
virtual bool isReadLockedOnCurrentThread(bool fWannaHear = true) const = 0;
/**
* Returns the current write lock level of this semaphore. The lock level
* determines the number of nested #lockWrite() 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 bool isReadLockedOnCurrentThread(bool fWannaHear = true) 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;
DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP(RWLockHandle); /* Shuts up MSC warning C4625. */
};
/**
* 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 bool isReadLockedOnCurrentThread(bool fWannaHear = true) 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;
DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP(WriteLockHandle); /* Shuts up MSC warning C4625. */
};
////////////////////////////////////////////////////////////////////////////////
//
// 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:
virtual ~Lockable() { } /* To make VC++ 2019 happy. */
/**
* 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;
}
/**
* Equivalent to <tt>#lockHandle()->isReadLockedOnCurrentThread()</tt>.
* Returns @c false if lockHandle() returns @c NULL.
* @note Use with care, simple debug assertions and similar only.
*/
bool isReadLockedOnCurrentThread(bool fWannaHear = true) const
{
LockHandle *h = lockHandle();
return h ? h->isReadLockedOnCurrentThread(fWannaHear) : 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);
private:
DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP(AutoReadLock); /* Shuts up MSC warning C4625. */
};
////////////////////////////////////////////////////////////////////////////////
//
// 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);
private:
DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP(AutoWriteLockBase); /* Shuts up MSC warning C4625. */
};
////////////////////////////////////////////////////////////////////////////////
//
// 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 #acquire()
* call and destroys the instance.
*
* Note that if there there are nested #acquire() calls without the
* corresponding number of #release() 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;
bool isReadLockedOnCurrentThread(bool fWannaHear = true) const;
private:
DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP(AutoWriteLock); /* Shuts up MSC warning C4625. */
};
////////////////////////////////////////////////////////////////////////////////
//
// 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();
}
private:
DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP(AutoMultiWriteLock2); /* Shuts up MSC warning C4625. */
};
/**
* 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();
}
private:
DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP(AutoMultiWriteLock3); /* Shuts up MSC warning C4625. */
};
/**
* 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();
}
private:
DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP(AutoMultiWriteLock4); /* Shuts up MSC warning C4625. */
};
} /* namespace util */
/** @} */
#endif /* !VBOX_INCLUDED_com_AutoLock_h */
/* vi: set tabstop=4 shiftwidth=4 expandtab: */

View file

@ -0,0 +1,545 @@
/** @file
* MS COM / XPCOM Abstraction Layer - ErrorInfo class declaration.
*/
/*
* Copyright (C) 2006-2023 Oracle and/or its affiliates.
*
* This file is part of VirtualBox base platform packages, as
* available from https://www.virtualbox.org.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation, in version 3 of the
* License.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses>.
*
* The contents of this file may alternatively be used under the terms
* of the Common Development and Distribution License Version 1.0
* (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
* in the VirtualBox 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.
*
* SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
*/
#ifndef VBOX_INCLUDED_com_ErrorInfo_h
#define VBOX_INCLUDED_com_ErrorInfo_h
#ifndef RT_WITHOUT_PRAGMA_ONCE
# pragma once
#endif
#include "VBox/com/ptr.h"
#include "VBox/com/string.h"
#include "VBox/com/Guid.h"
#include "VBox/com/assert.h"
/** @defgroup grp_com_errinfo ErrorInfo Classes
* @ingroup grp_com
* @{
*/
COM_STRUCT_OR_CLASS(IProgress);
COM_STRUCT_OR_CLASS(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),
mResultDetail(0),
m_pNext(NULL)
{
init();
}
ErrorInfo(IUnknown *pObj, const GUID &aIID)
: mIsBasicAvailable(false),
mIsFullAvailable(false),
mResultCode(S_OK),
mResultDetail(0),
m_pNext(NULL)
{
init(pObj, aIID);
}
/** Specialization for the IVirtualBoxErrorInfo smart pointer */
ErrorInfo(const ComPtr<IVirtualBoxErrorInfo> &aPtr)
: mIsBasicAvailable(false), mIsFullAvailable(false)
, mResultCode(S_OK), mResultDetail(0)
{ 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), mResultDetail(0)
{ 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 (optional) result detail code of the failed operation.
*/
LONG getResultDetail() const
{
return mResultDetail;
}
/**
* 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.
*
* @todo broken ErrorInfo documentation links, possibly misleading.
*/
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.
*
* @todo broken ErrorInfo documentation links, possibly misleading.
*/
const Bstr& getCalleeName() const
{
return mCalleeName;
}
HRESULT getVirtualBoxErrorInfo(ComPtr<IVirtualBoxErrorInfo> &pVirtualBoxErrorInfo);
/**
* 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;
LONG mResultDetail;
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 */);
}
/**
* Constructs a new instance from an ErrorInfo object, to inject a full
* error info created elsewhere.
*
* @param aInfo @c true to prevent fetching error info and leave
* the instance uninitialized.
*/
ErrorInfoKeeper(const ErrorInfo &aInfo)
: ErrorInfo(false), mForgot(false)
{
copyFrom(aInfo);
}
/**
* 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 /* !VBOX_INCLUDED_com_ErrorInfo_h */

View file

@ -0,0 +1,151 @@
/* $Id: EventQueue.h $ */
/** @file
* MS COM / XPCOM Abstraction Layer - Event queue class declaration.
*/
/*
* Copyright (C) 2013-2023 Oracle and/or its affiliates.
*
* This file is part of VirtualBox base platform packages, as
* available from https://www.virtualbox.org.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation, in version 3 of the
* License.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses>.
*
* The contents of this file may alternatively be used under the terms
* of the Common Development and Distribution License Version 1.0
* (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
* in the VirtualBox 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.
*
* SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
*/
#ifndef VBOX_INCLUDED_com_EventQueue_h
#define VBOX_INCLUDED_com_EventQueue_h
#ifndef RT_WITHOUT_PRAGMA_ONCE
# pragma once
#endif
#include <list>
#include <iprt/asm.h>
#include <iprt/critsect.h>
#include <VBox/com/defs.h>
#include <VBox/com/assert.h>
/** @defgroup grp_com_evtqueue Event Queue Classes
* @ingroup grp_com
* @{
*/
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(void) :
mRefCount(0) { }
virtual ~Event(void) { AssertMsg(!mRefCount,
("Reference count of event=%p not 0 on destruction (is %RU32)\n",
this, mRefCount)); }
public:
uint32_t AddRef(void) { return ASMAtomicIncU32(&mRefCount); }
void Release(void)
{
Assert(mRefCount);
uint32_t cRefs = ASMAtomicDecU32(&mRefCount);
if (!cRefs)
delete this;
}
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(void) { return NULL; }
friend class EventQueue;
protected:
/** The event's reference count. */
uint32_t mRefCount;
};
typedef std::list< Event* > EventQueueList;
typedef std::list< Event* >::iterator EventQueueListIterator;
typedef std::list< Event* >::const_iterator EventQueueListIteratorConst;
/**
* Simple event queue.
*/
class EventQueue
{
public:
EventQueue(void);
virtual ~EventQueue(void);
public:
BOOL postEvent(Event *event);
int processEventQueue(RTMSINTERVAL cMsTimeout);
int processPendingEvents(size_t cNumEvents);
int interruptEventQueueProcessing();
private:
/** Critical section for serializing access to this
* event queue. */
RTCRITSECT mCritSect;
/** Number of concurrent users. At the moment we
* only support one concurrent user at a time when
calling processEventQueue(). */
uint32_t mUserCnt;
/** Event semaphore for getting notified on new
* events being handled. */
RTSEMEVENT mSemEvent;
/** The actual event queue, implemented as a list. */
EventQueueList mEvents;
/** Shutdown indicator. */
bool mShutdown;
};
} /* namespace com */
/** @} */
#endif /* !VBOX_INCLUDED_com_EventQueue_h */

526
include/VBox/com/Guid.h Normal file
View file

@ -0,0 +1,526 @@
/* $Id: Guid.h $ */
/** @file
* MS COM / XPCOM Abstraction Layer - Guid class declaration.
*/
/*
* Copyright (C) 2006-2023 Oracle and/or its affiliates.
*
* This file is part of VirtualBox base platform packages, as
* available from https://www.virtualbox.org.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation, in version 3 of the
* License.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses>.
*
* The contents of this file may alternatively be used under the terms
* of the Common Development and Distribution License Version 1.0
* (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
* in the VirtualBox 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.
*
* SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
*/
#ifndef VBOX_INCLUDED_com_Guid_h
#define VBOX_INCLUDED_com_Guid_h
#ifndef RT_WITHOUT_PRAGMA_ONCE
# pragma once
#endif
/* 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
#include "VBox/com/string.h"
#include <iprt/uuid.h>
/** @defgroup grp_com_guid GUID Class
* @ingroup grp_com
* @{
*/
namespace com
{
typedef enum GuidState_t
{
GUID_ZERO,
GUID_NORMAL,
GUID_INVALID
} GuidState_t;
/**
* Helper class that represents the UUID type and hides platform-specific
* implementation details.
*/
class Guid
{
public:
Guid()
{
clear();
}
Guid(const Guid &that)
{
mUuid = that.mUuid;
mGuidState = that.mGuidState;
dbg_refresh();
}
Guid(const RTUUID &that)
{
mUuid = that;
updateState();
dbg_refresh();
}
Guid(const GUID &that)
{
AssertCompileSize(GUID, sizeof(RTUUID));
::memcpy(&mUuid, &that, sizeof(GUID));
updateState();
dbg_refresh();
}
/**
* Construct a GUID from a string.
*
* @param that The UUID string. Can be with or without the curly
* brackets. Empty strings are translated to a zero
* GUID, and strings which are not confirming to
* valid GUID string representations are marked as
* invalid.
*/
Guid(const char *that)
{
initString(that);
}
/**
* Construct a GUID from a BSTR.
*
* @param that The UUID BSTR. Can be with or without the curly
* brackets. Empty strings are translated to a zero
* GUID, and strings which are not confirming to
* valid GUID string representations are marked as
* invalid.
*/
Guid(CBSTR that)
{
initBSTR(that);
}
/**
* Construct a GUID from a Utf8Str.
*
* @param that The UUID Utf8Str. Can be with or without the curly
* brackets. Empty strings are translated to a zero
* GUID, and strings which are not confirming to
* valid GUID string representations are marked as
*/
Guid(const Utf8Str &that)
{
initString(that.c_str());
}
/**
* Construct a GUID from a RTCString.
*
* @param that The UUID RTCString. Can be with or without the curly
* brackets. Empty strings are translated to a zero
* GUID, and strings which are not confirming to
* valid GUID string representations are marked as
*/
Guid(const RTCString &that)
{
initString(that.c_str());
}
/**
* Construct a GUID from a Bstr.
*
* @param that The UUID Bstr. Can be with or without the curly
* brackets. Empty strings are translated to a zero
* GUID, and strings which are not confirming to
* valid GUID string representations are marked as
*/
Guid(const Bstr &that)
{
initBSTR(that.raw());
}
Guid& operator=(const Guid &that)
{
mUuid = that.mUuid;
mGuidState = that.mGuidState;
dbg_refresh();
return *this;
}
Guid& operator=(const RTUUID &guid)
{
mUuid = guid;
updateState();
dbg_refresh();
return *this;
}
Guid& operator=(const GUID &guid)
{
AssertCompileSize(GUID, sizeof(RTUUID));
::memcpy(&mUuid, &guid, sizeof(GUID));
updateState();
dbg_refresh();
return *this;
}
Guid& operator=(const char *str)
{
initString(str);
return *this;
}
Guid& operator=(CBSTR str)
{
initBSTR(str);
return *this;
}
Guid& operator=(const Utf8Str &str)
{
return operator=(str.c_str());
}
Guid& operator=(const RTCString &str)
{
return operator=(str.c_str());
}
Guid& operator=(const Bstr &str)
{
return operator=(str.raw());
}
void create()
{
::RTUuidCreate(&mUuid);
mGuidState = GUID_NORMAL;
dbg_refresh();
}
void clear()
{
makeClear();
dbg_refresh();
}
/**
* Convert the GUID to a string.
*
* @returns String object containing the formatted GUID.
* @throws std::bad_alloc
*/
Utf8Str toString() const
{
if (mGuidState == GUID_INVALID)
{
/* What to return in case of wrong Guid */
return Utf8Str("00000000-0000-0000-0000-00000000000");
}
char buf[RTUUID_STR_LENGTH];
::memset(buf, '\0', sizeof(buf));
::RTUuidToStr(&mUuid, buf, sizeof(buf));
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
{
if (mGuidState == GUID_INVALID)
{
/* What to return in case of wrong Guid */
return Utf8Str("{00000000-0000-0000-0000-00000000000}");
}
char buf[RTUUID_STR_LENGTH + 2];
::memset(buf, '\0', sizeof(buf));
::RTUuidToStr(&mUuid, buf + 1, sizeof(buf) - 2);
buf[0] = '{';
buf[sizeof(buf) - 2] = '}';
return Utf8Str(buf);
}
/**
* Convert the GUID to a string.
*
* @returns Bstr object containing the formatted GUID.
* @throws std::bad_alloc
*/
Bstr toUtf16() const
{
if (mGuidState == GUID_INVALID)
{
/* What to return in case of wrong Guid */
return Bstr("00000000-0000-0000-0000-00000000000");
}
RTUTF16 buf[RTUUID_STR_LENGTH];
::memset(buf, '\0', sizeof(buf));
::RTUuidToUtf16(&mUuid, buf, RT_ELEMENTS(buf));
return Bstr(buf);
}
/**
* Convert the GUID to a C string.
*
* @returns See RTUuidToStr.
* @param pszUuid The output buffer
* @param cbUuid The size of the output buffer. Should be at least
* RTUUID_STR_LENGTH in length.
*/
int toString(char *pszUuid, size_t cbUuid) const
{
return ::RTUuidToStr(mGuidState != GUID_INVALID ? &mUuid : &Empty.mUuid, pszUuid, cbUuid);
}
bool isValid() const
{
return mGuidState != GUID_INVALID;
}
bool isZero() const
{
return mGuidState == GUID_ZERO;
}
bool operator==(const Guid &that) const { return ::RTUuidCompare(&mUuid, &that.mUuid) == 0; }
bool operator==(const RTUUID &guid) const { return ::RTUuidCompare(&mUuid, &guid) == 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 RTUUID &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; }
bool operator<(const RTUUID &guid) const { return ::RTUuidCompare(&mUuid, &guid) < 0; }
/** Compare with a UUID string representation.
* @note Not an operator as that could lead to confusion. */
bool equalsString(const char *pszUuid2) const { return ::RTUuidCompareStr(&mUuid, pszUuid2) == 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 reference 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.isZero())
{
outer = *ptr;
outer.dbg_refresh();
nsMemory::Free(ptr);
}
}
friend class Guid;
};
/** to pass instances as OUT_GUID parameters to interface methods */
GuidOutParam asOutParam() { return GuidOutParam(*this); }
#endif
/**
* Static immutable empty (zero) object. May be used for comparison purposes.
*/
static const Guid Empty;
private:
void makeClear()
{
::RTUuidClear(&mUuid);
mGuidState = GUID_ZERO;
}
void makeInvalid()
{
::RTUuidClear(&mUuid);
mGuidState = GUID_INVALID;
}
void updateState()
{
if (::RTUuidIsNull(&mUuid))
mGuidState = GUID_ZERO;
else
mGuidState = GUID_NORMAL;
}
void initString(const char *that)
{
if (!that || !*that)
{
makeClear();
}
else
{
int rc = ::RTUuidFromStr(&mUuid, that);
if (RT_SUCCESS(rc))
updateState();
else
makeInvalid();
}
dbg_refresh();
}
void initBSTR(CBSTR that)
{
if (!that || !*that)
{
makeClear();
}
else
{
int rc = ::RTUuidFromUtf16(&mUuid, that);
if (RT_SUCCESS(rc))
updateState();
else
makeInvalid();
}
dbg_refresh();
}
/**
* 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 dbg_refresh()
{
#ifdef DEBUG
switch (mGuidState)
{
case GUID_ZERO:
case GUID_NORMAL:
::RTUuidToStr(&mUuid, mszUuid, RTUUID_STR_LENGTH);
break;
default:
::memset(mszUuid, '\0', sizeof(mszUuid));
::RTStrCopy(mszUuid, sizeof(mszUuid), "INVALID");
break;
}
m_pcszUUID = mszUuid;
#endif
}
/** The UUID. */
RTUUID mUuid;
GuidState_t mGuidState;
#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
};
} /* namespace com */
/** @} */
#endif /* !VBOX_INCLUDED_com_Guid_h */

View file

View file

@ -0,0 +1,278 @@
/* $Id: MultiResult.h $ */
/** @file
* MS COM / XPCOM Abstraction Layer - MultiResult class declarations.
*/
/*
* Copyright (C) 2008-2023 Oracle and/or its affiliates.
*
* This file is part of VirtualBox base platform packages, as
* available from https://www.virtualbox.org.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation, in version 3 of the
* License.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses>.
*
* The contents of this file may alternatively be used under the terms
* of the Common Development and Distribution License Version 1.0
* (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
* in the VirtualBox 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.
*
* SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
*/
#ifndef VBOX_INCLUDED_com_MultiResult_h
#define VBOX_INCLUDED_com_MultiResult_h
#ifndef RT_WITHOUT_PRAGMA_ONCE
# pragma once
#endif
#include "VBox/com/defs.h"
#include "VBox/com/string.h"
#include <stdarg.h>
/** @defgroup grp_com_mr MultiResult Classes
* @ingroup grp_com
* @{
*/
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;
}
* @endcode
*
* @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_INCLUDED_com_MultiResult_h */

View file

@ -0,0 +1,161 @@
/** @file
* MS COM / XPCOM Abstraction Layer - Event and EventQueue class declaration.
*/
/*
* Copyright (C) 2006-2023 Oracle and/or its affiliates.
*
* This file is part of VirtualBox base platform packages, as
* available from https://www.virtualbox.org.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation, in version 3 of the
* License.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses>.
*
* The contents of this file may alternatively be used under the terms
* of the Common Development and Distribution License Version 1.0
* (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
* in the VirtualBox 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.
*
* SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
*/
#ifndef VBOX_INCLUDED_com_NativeEventQueue_h
#define VBOX_INCLUDED_com_NativeEventQueue_h
#ifndef RT_WITHOUT_PRAGMA_ONCE
# pragma once
#endif
#ifndef VBOX_WITH_XPCOM
# include <iprt/win/windows.h>
#else
# include <nsEventQueueUtils.h>
#endif
#include <VBox/com/defs.h>
#include <VBox/com/assert.h>
/** @defgroup grp_com_evt Event and EventQueue Classes
* @ingroup grp_com
* @{
*/
namespace com
{
class MainEventQueue;
/**
* 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 NativeEvent
{
public:
NativeEvent() {}
virtual ~NativeEvent() {};
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 NativeEventQueue;
};
/**
* 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 NativeEventQueue
{
public:
NativeEventQueue();
virtual ~NativeEventQueue();
BOOL postEvent(NativeEvent *event);
int processEventQueue(RTMSINTERVAL cMsTimeout);
int interruptEventQueueProcessing();
int getSelectFD();
static int init();
static int uninit();
static NativeEventQueue *getMainEventQueue();
#ifdef VBOX_WITH_XPCOM
already_AddRefed<nsIEventQueue> getIEventQueue()
{
return mEventQ.get();
}
#else
static int dispatchMessageOnWindows(MSG const *pMsg, int vrc);
#endif
private:
static NativeEventQueue *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 /* !VBOX_INCLUDED_com_NativeEventQueue_h */

View file

@ -0,0 +1,71 @@
/** @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-2023 Oracle and/or its affiliates.
*
* This file is part of VirtualBox base platform packages, as
* available from https://www.virtualbox.org.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation, in version 3 of the
* License.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses>.
*
* The contents of this file may alternatively be used under the terms
* of the Common Development and Distribution License Version 1.0
* (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
* in the VirtualBox 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.
*
* SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
*/
#ifndef VBOX_INCLUDED_com_VirtualBox_h
#define VBOX_INCLUDED_com_VirtualBox_h
#ifndef RT_WITHOUT_PRAGMA_ONCE
# pragma once
#endif
/* For XPCOM/C++ enum hack checks. */
#include <iprt/assertcompile.h>
/* Generated VirtualBox COM library definition file. */
#if !defined(VBOXCOM_NOINCLUDE)
# if !defined(VBOX_WITH_XPCOM)
# include <iprt/win/windows.h> /* Included by VirtualBox.h via rpc.h, so include our wrapper with cleanups. */
# include <VirtualBox.h>
# else
# define VBOX_WITH_XPCOM_CPP_ENUM_HACK
# include <VirtualBox_XPCOM.h>
# endif
#endif
/* For convenience. */
#include "VBox/com/defs.h"
#include "VBox/com/ptr.h"
#endif /* !VBOX_INCLUDED_com_VirtualBox_h */

1872
include/VBox/com/array.h Normal file

File diff suppressed because it is too large Load diff

135
include/VBox/com/assert.h Normal file
View file

@ -0,0 +1,135 @@
/** @file
* MS COM / XPCOM Abstraction Layer - Assertion macros for COM/XPCOM.
*/
/*
* Copyright (C) 2006-2023 Oracle and/or its affiliates.
*
* This file is part of VirtualBox base platform packages, as
* available from https://www.virtualbox.org.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation, in version 3 of the
* License.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses>.
*
* The contents of this file may alternatively be used under the terms
* of the Common Development and Distribution License Version 1.0
* (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
* in the VirtualBox 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.
*
* SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
*/
#ifndef VBOX_INCLUDED_com_assert_h
#define VBOX_INCLUDED_com_assert_h
#ifndef RT_WITHOUT_PRAGMA_ONCE
# pragma once
#endif
#include <iprt/assert.h>
/** @defgroup grp_com_assert Assertion Macros for COM/XPCOM
* @ingroup grp_com
* @{
*/
/**
* 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 hrc The COM result code
*/
#define AssertComRC(hrc) \
do { AssertMsg(SUCCEEDED(hrc), ("COM RC = %Rhrc (0x%08X)\n", hrc, hrc)); NOREF(hrc); } while (0)
/**
* Same as AssertComRC, except the caller already knows we failed.
*
* @param hrc The COM result code
*/
#define AssertComRCFailed(hrc) \
do { AssertMsgFailed(("COM RC = %Rhrc (0x%08X)\n", hrc, hrc)); NOREF(hrc); } while (0)
/**
* A special version of AssertComRC that returns the given expression
* if the result code is failed.
*
* @param hrc The COM result code
* @param RetExpr The expression to return
*/
#define AssertComRCReturn(hrc, RetExpr) \
AssertMsgReturn(SUCCEEDED(hrc), ("COM RC = %Rhrc (0x%08X)\n", hrc, hrc), RetExpr)
/**
* A special version of AssertComRC that returns the given result code
* if it is failed.
*
* @param hrc The COM result code
*/
#define AssertComRCReturnRC(hrc) \
AssertMsgReturn(SUCCEEDED(hrc), ("COM RC = %Rhrc (0x%08X)\n", hrc, hrc), hrc)
/**
* A special version of AssertComRC that returns if the result code is failed.
*
* @param hrc The COM result code
*/
#define AssertComRCReturnVoid(hrc) \
AssertMsgReturnVoid(SUCCEEDED(hrc), ("COM RC = %Rhrc (0x%08X)\n", hrc, hrc))
/**
* A special version of AssertComRC that evaluates the given expression and
* breaks if the result code is failed.
*
* @param hrc The COM result code
* @param PreBreakExpr The expression to evaluate on failure.
*/
#define AssertComRCBreak(hrc, PreBreakExpr) \
if (!SUCCEEDED(hrc)) { AssertComRCFailed(hrc); PreBreakExpr; 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 hrc The COM result code
* @param ThrowMeExpr The expression which result to be thrown on failure.
*/
#define AssertComRCThrow(hrc, ThrowMeExpr) \
do { if (SUCCEEDED(hrc)) { /*likely*/} else { AssertComRCFailed(hrc); throw (ThrowMeExpr); } } while (0)
/**
* A special version of AssertComRC that just breaks if the result code is
* failed.
*
* @param hrc The COM result code
*/
#define AssertComRCBreakRC(hrc) \
if (!SUCCEEDED(hrc)) { AssertComRCFailed(hrc); break; } else do {} while (0)
/**
* A special version of AssertComRC that just throws @a hrc if the result code
* is failed.
*
* @param hrc The COM result code
*/
#define AssertComRCThrowRC(hrc) \
do { if (SUCCEEDED(hrc)) { /*likely*/ } else { AssertComRCFailed(hrc); throw hrc; } } while (0)
/** @} */
#endif /* !VBOX_INCLUDED_com_assert_h */

102
include/VBox/com/com.h Normal file
View file

@ -0,0 +1,102 @@
/** @file
* MS COM / XPCOM Abstraction Layer - COM initialization / shutdown.
*/
/*
* Copyright (C) 2005-2023 Oracle and/or its affiliates.
*
* This file is part of VirtualBox base platform packages, as
* available from https://www.virtualbox.org.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation, in version 3 of the
* License.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses>.
*
* The contents of this file may alternatively be used under the terms
* of the Common Development and Distribution License Version 1.0
* (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
* in the VirtualBox 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.
*
* SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
*/
#ifndef VBOX_INCLUDED_com_com_h
#define VBOX_INCLUDED_com_com_h
#ifndef RT_WITHOUT_PRAGMA_ONCE
# pragma once
#endif
#include "VBox/com/defs.h"
#include "VBox/com/utils.h"
/** @defgroup grp_com MS COM / XPCOM Abstraction Layer
* @{
*/
namespace com
{
/** @name VBOX_COM_INIT_F_XXX - flags for com::Initialize().
* @{ */
/** Windows: Caller is the GUI and needs a STA rather than MTA apartment. */
#define VBOX_COM_INIT_F_GUI RT_BIT_32(0)
/** Windows: Auto registration updating, if privileged enough. */
#define VBOX_COM_INIT_F_AUTO_REG_UPDATE RT_BIT_32(1)
/** Windows: Opt-out of COM patching (client code should do this). */
#define VBOX_COM_INIT_F_NO_COM_PATCHING RT_BIT_32(2)
/** The default flags. */
#define VBOX_COM_INIT_F_DEFAULT (VBOX_COM_INIT_F_AUTO_REG_UPDATE)
/** @} */
/**
* 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.
*
* @return COM result code
*/
HRESULT Initialize(uint32_t fInitFlags = VBOX_COM_INIT_F_DEFAULT);
/**
* 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);
#ifdef RT_OS_WINDOWS
void PatchComBugs(void);
#endif
} /* namespace com */
/** @} */
#endif /* !VBOX_INCLUDED_com_com_h */

606
include/VBox/com/defs.h Normal file
View file

@ -0,0 +1,606 @@
/** @file
* MS COM / XPCOM Abstraction Layer - Common Definitions.
*/
/*
* Copyright (C) 2006-2023 Oracle and/or its affiliates.
*
* This file is part of VirtualBox base platform packages, as
* available from https://www.virtualbox.org.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation, in version 3 of the
* License.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses>.
*
* The contents of this file may alternatively be used under the terms
* of the Common Development and Distribution License Version 1.0
* (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
* in the VirtualBox 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.
*
* SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
*/
#ifndef VBOX_INCLUDED_com_defs_h
#define VBOX_INCLUDED_com_defs_h
#ifndef RT_WITHOUT_PRAGMA_ONCE
# pragma once
#endif
/* 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>
/** @defgroup grp_com_defs Common Definitions
* @ingroup grp_com
* @{
*/
#if !defined(VBOX_WITH_XPCOM)
#ifdef RT_OS_WINDOWS
// Windows COM
/////////////////////////////////////////////////////////////////////////////
# include <iprt/win/objbase.h>
# ifndef VBOX_COM_NO_ATL
/* Do not use actual ATL, just provide a superficial lookalike ourselves. */
# include <VBox/com/microatl.h>
# endif /* VBOX_COM_NO_ATL */
# 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.
* 0x80010108 - RPC_E_DISCONNECTED. Observed deregistering
* python event listener.
* 0x800706b5 - RPC_S_UNKNOWN_IF. Observed deregistering python
* event listener
*/
#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) \
|| (rc) == RPC_E_DISCONNECTED \
)
/** 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>
* &lt;param name="arg" ... dir="in" safearray="yes"/&gt;
* ...
* &lt;attribute name="arg" ... safearray="yes"/&gt;
* </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 @c 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 macro.
*
* @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>
* &lt;param name="arg" ... dir="out" safearray="yes"/&gt;
* &lt;param name="arg" ... dir="return" safearray="yes"/&gt;
* ...
* &lt;attribute name="arg" ... safearray="yes"/&gt;
* </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 @c 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)
/**
* Gets size of safearray parameter.
* @param aArg Parameter name.
*/
#define ComSafeArraySize(aArg) ((aArg) == NULL ? 0 : (aArg)->rgsabound[0].cElements)
/**
* Apply RT_NOREF_PV to a safearray parameter.
* @param aArg Parameter name.
*/
#define ComSafeArrayNoRef(aArg) RT_NOREF_PV(aArg)
/**
* Returns the const reference to the IID (i.e., |const GUID &|) of the given
* interface.
*
* @param I interface class
*/
#define COM_IIDOF(I) __uuidof(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 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)
/** safearray size */
#define ComSafeArraySize(aArg) ((aArg) == NULL ? 0 : (aArg##Size))
/** NOREF a COM safe array argument. */
#define ComSafeArrayNoRef(aArg) RT_NOREF2(aArg, aArg##Size)
/* CLSID and IID for compatibility with Win32 */
typedef nsCID CLSID;
typedef nsIID IID;
/* OLE error codes */
#define S_OK ((nsresult)NS_OK)
#define S_FALSE ((nsresult)1)
#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 STDMETHOD_(ret, meth) NS_IMETHOD_(ret) meth
#define COM_IIDOF(I) NS_GET_IID(I)
#define COM_STRUCT_OR_CLASS(I) class I
/* helper functions */
extern "C"
{
BSTR SysAllocString(const OLECHAR *sz);
BSTR SysAllocStringByteLen(char const *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);
}
#ifndef VBOX_COM_NO_ATL
namespace ATL
{
#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)
/* A few very simple ATL emulator classes to provide
* FinalConstruct()/FinalRelease() functionality with XPCOM. */
class CComMultiThreadModel
{
};
template <class DummyThreadModel> class CComObjectRootEx
{
public:
HRESULT FinalConstruct()
{
return S_OK;
}
void FinalRelease()
{
}
};
template <class Base> class CComObject : public Base
{
public:
virtual ~CComObject() { this->FinalRelease(); }
};
} /* namespace ATL */
/**
* '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; \
} \
\
ATL::CComObject<_InstanceClass> *inst = new ATL::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 /* !VBOX_COM_NO_ATL */
#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
{
#ifndef VBOX_COM_NO_ATL
// use this macro to implement scriptable interfaces
#ifdef RT_OS_WINDOWS
#define VBOX_SCRIPTABLE_IMPL(iface) \
public ATL::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; \
}
#else
#define VBOX_SCRIPTABLE_IMPL(iface) \
public iface
#define VBOX_SCRIPTABLE_DISPATCH_IMPL(iface)
#endif
#endif /* !VBOX_COM_NO_ATL */
} /* namespace com */
/** @} */
#endif /* !VBOX_INCLUDED_com_defs_h */

View file

@ -0,0 +1,401 @@
/** @file
* MS COM / XPCOM Abstraction Layer - Error Reporting.
*
* 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-2023 Oracle and/or its affiliates.
*
* This file is part of VirtualBox base platform packages, as
* available from https://www.virtualbox.org.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation, in version 3 of the
* License.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses>.
*
* The contents of this file may alternatively be used under the terms
* of the Common Development and Distribution License Version 1.0
* (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
* in the VirtualBox 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.
*
* SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
*/
#ifndef VBOX_INCLUDED_com_errorprint_h
#define VBOX_INCLUDED_com_errorprint_h
#ifndef RT_WITHOUT_PRAGMA_ONCE
# pragma once
#endif
#include <VBox/com/ErrorInfo.h>
/** @defgroup grp_com_error_reporting Error Reporting
* @ingroup grp_com
* @{
*/
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 uLine, bool fWarning = false);
void GluePrintRCMessage(HRESULT hrc);
void GlueHandleComError(ComPtr<IUnknown> iface, const char *pcszContext, HRESULT hrc, const char *pcszSourceFile, uint32_t uLine);
void GlueHandleComErrorNoCtx(ComPtr<IUnknown> iface, HRESULT hrc);
void GlueHandleComErrorProgress(ComPtr<IProgress> progress, const char *pcszContext, HRESULT hrc,
const char *pcszSourceFile, uint32_t uLine);
/**
* Extended macro that implements all the other CHECK_ERROR2XXX macros.
*
* Calls the method of the given interface and checks the return status code.
* If the status indicates failure, as much information as possible is reported
* about the error, including current source file and line.
*
* After reporting an error, the statement |stmtError| is executed.
*
* This macro family is intended for command line tools like VBoxManage, but
* could also be handy for debugging.
*
* @param type For defining @a hrc locally inside the the macro
* expansion, pass |HRESULT| otherwise |RT_NOTHING|.
* @param hrc Name of the HRESULT variable to assign the result of the
* method call to.
* @param iface The interface pointer (can be a smart pointer object).
* @param method The method to invoke together with the parameters.
* @param stmtError Statement to be executed after reporting failures. This
* can be a |break| or |return| statement, if so desired.
*
* @remarks Unlike CHECK_ERROR, CHECK_ERROR_RET and family, this macro family
* does not presuppose a |rc| variable but instead either let the user
* specify the variable to use or employs a local variable |hrcCheck|
* within its own scope.
*
* @sa CHECK_ERROR2, CHECK_ERROR2I, CHECK_ERROR2_STMT, CHECK_ERROR2I_STMT,
* CHECK_ERROR2_BREAK, CHECK_ERROR2I_BREAK, CHECK_ERROR2_RET,
* CHECK_ERROR2I_RET
*/
#define CHECK_ERROR2_EX(type, hrc, iface, method, stmtError) \
if (1) { \
type hrc = iface->method; \
if (SUCCEEDED(hrc) && !SUCCEEDED_WARNING(hrc)) \
{ /*likely*/ } \
else \
{ \
com::GlueHandleComError(iface, #method, (hrc), __FILE__, __LINE__); \
if (!SUCCEEDED_WARNING(hrc)) \
{ \
stmtError; \
} \
} \
} else do { /* nothing */ } while (0)
/**
* 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.
* @sa CHECK_ERROR2, CHECK_ERROR2I
*/
#define CHECK_ERROR(iface, method) \
do { \
hrc = iface->method; \
if (FAILED(hrc) || SUCCEEDED_WARNING(hrc)) \
com::GlueHandleComError(iface, #method, hrc, __FILE__, __LINE__); \
} while (0)
/**
* Simplified version of CHECK_ERROR2_EX, no error statement or type necessary.
*
* @param hrc Name of the HRESULT variable to assign the result of the
* method call to.
* @param iface The interface pointer (can be a smart pointer object).
* @param method The method to invoke together with the parameters.
* @sa CHECK_ERROR2I, CHECK_ERROR2_EX
*/
#define CHECK_ERROR2(hrc, iface, method) CHECK_ERROR2_EX(RT_NOTHING, hrc, iface, method, (void)1)
/**
* Simplified version of CHECK_ERROR2_EX that uses an internal variable
* |hrcCheck| for holding the result and have no error statement.
*
* @param iface The interface pointer (can be a smart pointer object).
* @param method The method to invoke together with the parameters.
* @sa CHECK_ERROR2, CHECK_ERROR2_EX
*/
#define CHECK_ERROR2I(iface, method) CHECK_ERROR2_EX(HRESULT, hrcCheck, iface, method, (void)1)
/**
* Same as CHECK_ERROR except that it also executes the statement |stmt| on
* failure.
* @sa CHECK_ERROR2_STMT, CHECK_ERROR2I_STMT
*/
#define CHECK_ERROR_STMT(iface, method, stmt) \
do { \
hrc = iface->method; \
if (FAILED(hrc) || SUCCEEDED_WARNING(hrc)) \
{ \
com::GlueHandleComError(iface, #method, hrc, __FILE__, __LINE__); \
if (!SUCCEEDED_WARNING(hrc) \
{ \
stmt; \
} \
} \
} while (0)
/**
* Simplified version of CHECK_ERROR2_EX (no @a hrc type).
*
* @param hrc Name of the HRESULT variable to assign the result of the
* method call to.
* @param iface The interface pointer (can be a smart pointer object).
* @param method The method to invoke together with the parameters.
* @param stmt Statement to be executed after reporting failures.
* @sa CHECK_ERROR2I_STMT, CHECK_ERROR2_EX
*/
#define CHECK_ERROR2_STMT(hrc, iface, method, stmt) CHECK_ERROR2_EX(RT_NOTHING, hrc, iface, method, stmt)
/**
* Simplified version of CHECK_ERROR2_EX that uses an internal variable
* |hrcCheck| for holding the result.
*
* @param iface The interface pointer (can be a smart pointer object).
* @param method The method to invoke together with the parameters.
* @param stmt Statement to be executed after reporting failures.
* @sa CHECK_ERROR2_STMT, CHECK_ERROR2_EX
*/
#define CHECK_ERROR2I_STMT(iface, method, stmt) CHECK_ERROR2_EX(HRESULT, hrcCheck, iface, method, stmt)
/**
* Does the same as CHECK_ERROR(), but executes the |break| statement on
* failure.
* @sa CHECK_ERROR2_BREAK, CHECK_ERROR2I_BREAK
*/
#ifdef __GNUC__
# define CHECK_ERROR_BREAK(iface, method) \
__extension__ \
({ \
hrc = iface->method; \
if (FAILED(hrc) || SUCCEEDED_WARNING(hrc)) \
{ \
com::GlueHandleComError(iface, #method, hrc, __FILE__, __LINE__); \
if (!SUCCEEDED_WARNING(hrc)) \
break; \
} \
})
#else
# define CHECK_ERROR_BREAK(iface, method) \
if (1) \
{ \
hrc = iface->method; \
if (FAILED(hrc)) \
{ \
com::GlueHandleComError(iface, #method, hrc, __FILE__, __LINE__); \
if (!SUCCEEDED_WARNING(hrc)) \
break; \
} \
} \
else do {} while (0)
#endif
/**
* Simplified version of CHECK_ERROR2_EX that executes the |break| statement
* after error reporting (no @a hrc type).
*
* @param hrc The result variable (type HRESULT).
* @param iface The interface pointer (can be a smart pointer object).
* @param method The method to invoke together with the parameters.
* @sa CHECK_ERROR2I_BREAK, CHECK_ERROR2_EX
*/
#define CHECK_ERROR2_BREAK(hrc, iface, method) CHECK_ERROR2_EX(RT_NOTHING, hrc, iface, method, break)
/**
* Simplified version of CHECK_ERROR2_EX that executes the |break| statement
* after error reporting and that uses an internal variable |hrcCheck| for
* holding the result.
*
* @param iface The interface pointer (can be a smart pointer object).
* @param method The method to invoke together with the parameters.
* @sa CHECK_ERROR2_BREAK, CHECK_ERROR2_EX
*/
#define CHECK_ERROR2I_BREAK(iface, method) CHECK_ERROR2_EX(HRESULT, hrcCheck, iface, method, break)
/**
* Simplified version of CHECK_ERROR2_EX that executes the |stmt;break|
* statements after error reporting and that uses an internal variable
* |hrcCheck| for holding the result.
*
* @param iface The interface pointer (can be a smart pointer object).
* @param method The method to invoke together with the parameters.
* @param stmt Statement to be executed after reporting failures.
* @sa CHECK_ERROR2_BREAK, CHECK_ERROR2_EX
*/
#define CHECK_ERROR2I_BREAK_STMT(iface, method, stmt) CHECK_ERROR2_EX(HRESULT, hrcCheck, iface, method, stmt; break)
/**
* Does the same as CHECK_ERROR(), but executes the |return ret| statement on
* failure.
* @sa CHECK_ERROR2_RET, CHECK_ERROR2I_RET
*/
#define CHECK_ERROR_RET(iface, method, ret) \
do { \
hrc = iface->method; \
if (FAILED(hrc) || SUCCEEDED_WARNING(hrc)) \
{ \
com::GlueHandleComError(iface, #method, hrc, __FILE__, __LINE__); \
if (!SUCCEEDED_WARNING(hrc)) \
return (ret); \
} \
} while (0)
/**
* Simplified version of CHECK_ERROR2_EX that executes the |return (rcRet)|
* statement after error reporting.
*
* @param hrc The result variable (type HRESULT).
* @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.
*/
#define CHECK_ERROR2_RET(hrc, iface, method, rcRet) CHECK_ERROR2_EX(RT_NOTHING, hrc, iface, method, return (rcRet))
/**
* Simplified version of CHECK_ERROR2_EX that executes the |return (rcRet)|
* statement after error reporting and that uses an internal variable |hrcCheck|
* for holding the result.
*
* @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_ERROR2I_RET(iface, method, rcRet) CHECK_ERROR2_EX(HRESULT, hrcCheck, iface, method, return (rcRet))
/**
* Check the progress object for an error and if there is one print out the
* extended error information.
* @remarks Requires HRESULT variable named @a rc.
*/
#define CHECK_PROGRESS_ERROR(progress, msg) \
do { \
LONG iRc; \
hrc = progress->COMGETTER(ResultCode)(&iRc); \
if (FAILED(hrc) || FAILED(iRc)) \
{ \
if (SUCCEEDED(hrc)) hrc = iRc; else iRc = hrc; \
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.
* @remarks Requires HRESULT variable named @a rc.
*/
#ifdef __GNUC__
# define CHECK_PROGRESS_ERROR_BREAK(progress, msg) \
__extension__ \
({ \
LONG iRc; \
hrc = progress->COMGETTER(ResultCode)(&iRc); \
if (FAILED(hrc) || FAILED(iRc)) \
{ \
if (SUCCEEDED(hrc)) hrc = iRc; else iRc = hrc; \
RTMsgError msg; \
com::GlueHandleComErrorProgress(progress, __PRETTY_FUNCTION__, iRc, __FILE__, __LINE__); \
break; \
} \
})
#else
# define CHECK_PROGRESS_ERROR_BREAK(progress, msg) \
if (1) \
{ \
LONG iRc; \
hrc = progress->COMGETTER(ResultCode)(&iRc); \
if (FAILED(hrc) || FAILED(iRc)) \
{ \
if (SUCCEEDED(hrc)) hrc = iRc; else iRc = hrc; \
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; \
HRESULT hrcCheck = progress->COMGETTER(ResultCode)(&iRc); \
if (SUCCEEDED(hrcCheck) && SUCCEEDED(iRc)) \
{ /* likely */ } \
else \
{ \
RTMsgError msg; \
com::GlueHandleComErrorProgress(progress, __PRETTY_FUNCTION__, \
SUCCEEDED(hrcCheck) ? iRc : hrcCheck, __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)
/**
* Does the same as ASSERT(), but executes the |return ret| statement if the
* expression to assert is false;
* @remarks WARNING! @a expr is evalutated TWICE!
*/
#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;
* @remarks WARNING! @a expr is evalutated TWICE!
*/
#define ASSERT_BREAK(expr, ret) \
if (1) { ASSERT(expr); if (!(expr)) break; } else do {} while (0)
} /* namespace com */
/** @} */
#endif /* !VBOX_INCLUDED_com_errorprint_h */

223
include/VBox/com/list.h Normal file
View file

@ -0,0 +1,223 @@
/* $Id: list.h $ */
/** @file
* MS COM / XPCOM Abstraction Layer - List classes declaration.
*/
/*
* Copyright (C) 2011-2023 Oracle and/or its affiliates.
*
* This file is part of VirtualBox base platform packages, as
* available from https://www.virtualbox.org.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation, in version 3 of the
* License.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses>.
*
* The contents of this file may alternatively be used under the terms
* of the Common Development and Distribution License Version 1.0
* (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
* in the VirtualBox 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.
*
* SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
*/
#ifndef VBOX_INCLUDED_com_list_h
#define VBOX_INCLUDED_com_list_h
#ifndef RT_WITHOUT_PRAGMA_ONCE
# pragma once
#endif
#include <VBox/com/ptr.h>
#include <VBox/com/string.h>
#include <VBox/com/array.h>
#include <iprt/cpp/list.h>
/** @defgroup grp_com_list List Classes
* @ingroup grp_com
* @{
*/
/**
* 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 cCapacity The initial capacity the list has.
* @throws std::bad_alloc
*/
RTCList(size_t cCapacity = BASE::kDefaultCapacity)
: 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 cCapacity The initial capacity the list has.
* @throws std::bad_alloc
*/
RTCList(size_t cCapacity = BASE::kDefaultCapacity)
: 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<com::Utf8Str>: public RTCListBase<com::Utf8Str, com::Utf8Str*, false>
{
/* Traits */
typedef com::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 cCapacity The initial capacity the list has.
* @throws std::bad_alloc
*/
RTCList(size_t cCapacity = BASE::kDefaultCapacity)
: 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));
size_t const cElementsOther = sfaOther.size();
resizeArray(cElementsOther);
m_cElements = cElementsOther;
for (size_t i = 0; i < cElementsOther; ++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_cElements; ++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_cElements);
/* Copy */
size_t cElementsOther = other.size();
if (cElementsOther != m_cCapacity)
resizeArrayNoErase(cElementsOther);
m_cElements = cElementsOther;
for (size_t i = 0; i < cElementsOther; ++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_INCLUDED_com_list_h */

View file

@ -0,0 +1,194 @@
/* $Id: listeners.h $ */
/** @file
* MS COM / XPCOM Abstraction Layer - Listener helpers.
*/
/*
* Copyright (C) 2010-2023 Oracle and/or its affiliates.
*
* This file is part of VirtualBox base platform packages, as
* available from https://www.virtualbox.org.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation, in version 3 of the
* License.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses>.
*
* The contents of this file may alternatively be used under the terms
* of the Common Development and Distribution License Version 1.0
* (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
* in the VirtualBox 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.
*
* SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
*/
#ifndef VBOX_INCLUDED_com_listeners_h
#define VBOX_INCLUDED_com_listeners_h
#ifndef RT_WITHOUT_PRAGMA_ONCE
# pragma once
#endif
#include <VBox/com/com.h>
#include <VBox/com/VirtualBox.h>
/** @defgroup grp_com_listeners Listener Helpers
* @ingroup grp_com
* @{
*/
#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 ATL::CComObjectRootEx<ATL::CComMultiThreadModel>,
VBOX_SCRIPTABLE_IMPL(IEventListener)
{
T* mListener;
#ifdef RT_OS_WINDOWS
/* FTM stuff */
ComPtr<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.m_p);
#else
return S_OK;
#endif
}
void FinalRelease()
{
uninit();
#ifdef RT_OS_WINDOWS
m_pUnkMarshaler.setNull();
#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.m_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;
HRESULT hrc = aEvent->COMGETTER(Type)(&aType);
AssertMsg(SUCCEEDED(hrc), ("hrc=%Rhrc\n", hrc)); RT_NOREF(hrc);
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 /* !VBOX_INCLUDED_com_listeners_h */

1408
include/VBox/com/microatl.h Normal file

File diff suppressed because it is too large Load diff

220
include/VBox/com/mtlist.h Normal file
View file

@ -0,0 +1,220 @@
/* $Id: mtlist.h $ */
/** @file
* MS COM / XPCOM Abstraction Layer - Thread-safe list classes declaration.
*/
/*
* Copyright (C) 2011-2023 Oracle and/or its affiliates.
*
* This file is part of VirtualBox base platform packages, as
* available from https://www.virtualbox.org.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation, in version 3 of the
* License.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses>.
*
* The contents of this file may alternatively be used under the terms
* of the Common Development and Distribution License Version 1.0
* (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
* in the VirtualBox 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.
*
* SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
*/
#ifndef VBOX_INCLUDED_com_mtlist_h
#define VBOX_INCLUDED_com_mtlist_h
#ifndef RT_WITHOUT_PRAGMA_ONCE
# pragma once
#endif
#include <VBox/com/ptr.h>
#include <VBox/com/string.h>
#include <VBox/com/array.h>
#include <iprt/cpp/mtlist.h>
/** @defgroup grp_com_mtlist Thread-safe List Classes
* @ingroup grp_com
* @{
*/
/**
* 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 cCapacity The initial capacity the list has.
* @throws std::bad_alloc
*/
RTCMTList(size_t cCapacity = BASE::kDefaultCapacity)
: 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 cCapacity The initial capacity the list has.
* @throws std::bad_alloc
*/
RTCMTList(size_t cCapacity = BASE::kDefaultCapacity)
: 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<com::Utf8Str>: public RTCListBase<com::Utf8Str, com::Utf8Str *, true>
{
/* Traits */
typedef com::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 cCapacity The initial capacity the list has.
* @throws std::bad_alloc
*/
RTCMTList(size_t cCapacity = BASE::kDefaultCapacity)
: 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));
size_t const cElementsOther = sfaOther.size();
resizeArray(cElementsOther);
m_cElements = cElementsOther;
for (size_t i = 0; i < cElementsOther; ++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_cElements; ++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_cElements);
/* Copy */
if (other.size() != m_cCapacity)
resizeArrayNoErase(other.size());
m_cElements = 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_INCLUDED_com_mtlist_h */

569
include/VBox/com/ptr.h Normal file
View file

@ -0,0 +1,569 @@
/** @file
* MS COM / XPCOM Abstraction Layer - Smart COM pointer classes declaration.
*/
/*
* Copyright (C) 2006-2023 Oracle and/or its affiliates.
*
* This file is part of VirtualBox base platform packages, as
* available from https://www.virtualbox.org.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation, in version 3 of the
* License.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses>.
*
* The contents of this file may alternatively be used under the terms
* of the Common Development and Distribution License Version 1.0
* (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
* in the VirtualBox 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.
*
* SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
*/
#ifndef VBOX_INCLUDED_com_ptr_h
#define VBOX_INCLUDED_com_ptr_h
#ifndef RT_WITHOUT_PRAGMA_ONCE
# pragma once
#endif
/* 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
#ifdef VBOX_WITH_XPCOM
# include <nsISupportsUtils.h>
#endif /* VBOX_WITH_XPCOM */
#include <VBox/com/defs.h>
#include <new> /* For bad_alloc. */
/** @defgroup grp_com_ptr Smart COM Pointer Classes
* @ingroup grp_com
* @{
*/
#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);
}
/**
* Returns true if the pointer is not NULL.
*/
bool isNotNull() 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);
*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;
#ifndef VBOX_WITH_XPCOM
rc = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, COM_IIDOF(T),
(void **)&obj);
#else /* VBOX_WITH_XPCOM */
using namespace com;
rc = GlueCreateInstance(clsid, NS_GET_IID(T), (void **)&obj);
#endif /* 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)
{
#ifndef VBOX_WITH_XPCOM
HRESULT rc;
T *obj = NULL;
rc = CoCreateInstance(clsid, NULL, CLSCTX_LOCAL_SERVER, COM_IIDOF(T),
(void **)&obj);
*this = obj;
if (SUCCEEDED(rc))
obj->Release();
return rc;
#else /* VBOX_WITH_XPCOM */
return createInprocObject(clsid);
#endif /* 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;
}
}
public:
// Do NOT access this member unless you really know what you're doing!
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.
*
* @note In order to make it easier to use, this method does _not_ throw
* bad_alloc, but instead returns E_OUTOFMEMORY.
*/
HRESULT createObject()
{
HRESULT hrc;
#ifndef VBOX_WITH_XPCOM
# ifdef VBOX_COM_OUTOFPROC_MODULE
ATL::CComObjectNoLock<T> *obj = NULL;
try
{
obj = new ATL::CComObjectNoLock<T>();
}
catch (std::bad_alloc &)
{
obj = NULL;
}
if (obj)
{
obj->InternalFinalConstructAddRef();
try
{
hrc = obj->FinalConstruct();
}
catch (std::bad_alloc &)
{
hrc = E_OUTOFMEMORY;
}
obj->InternalFinalConstructRelease();
if (FAILED(hrc))
{
delete obj;
obj = NULL;
}
}
else
hrc = E_OUTOFMEMORY;
# else
ATL::CComObject<T> *obj = NULL;
hrc = ATL::CComObject<T>::CreateInstance(&obj);
# endif
#else /* VBOX_WITH_XPCOM */
ATL::CComObject<T> *obj;
# ifndef RT_EXCEPTIONS_ENABLED
obj = new ATL::CComObject<T>();
# else
try
{
obj = new ATL::CComObject<T>();
}
catch (std::bad_alloc &)
{
obj = NULL;
}
# endif
if (obj)
{
# ifndef RT_EXCEPTIONS_ENABLED
hrc = obj->FinalConstruct();
# else
try
{
hrc = obj->FinalConstruct();
}
catch (std::bad_alloc &)
{
hrc = E_OUTOFMEMORY;
}
# endif
if (FAILED(hrc))
{
delete obj;
obj = NULL;
}
}
else
hrc = E_OUTOFMEMORY;
#endif /* VBOX_WITH_XPCOM */
*this = obj;
return hrc;
}
};
/** @} */
#endif /* !VBOX_INCLUDED_com_ptr_h */

1494
include/VBox/com/string.h Normal file

File diff suppressed because it is too large Load diff

132
include/VBox/com/utils.h Normal file
View file

@ -0,0 +1,132 @@
/** @file
* MS COM / XPCOM Abstraction Layer - COM initialization / shutdown.
*/
/*
* Copyright (C) 2005-2023 Oracle and/or its affiliates.
*
* This file is part of VirtualBox base platform packages, as
* available from https://www.virtualbox.org.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation, in version 3 of the
* License.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses>.
*
* The contents of this file may alternatively be used under the terms
* of the Common Development and Distribution License Version 1.0
* (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
* in the VirtualBox 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.
*
* SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
*/
#ifndef VBOX_INCLUDED_com_utils_h
#define VBOX_INCLUDED_com_utils_h
#ifndef RT_WITHOUT_PRAGMA_ONCE
# pragma once
#endif
#include "iprt/types.h"
/** @addtogroup grp_com
* @{
*/
namespace com
{
/**
* 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.
* @returns 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 pszEntity Human readable name of the program.
* @param pszLogFile Name of the release log file.
* @param fFlags Logger instance flags.
* @param pszGroupSettings Group logging settings.
* @param pszEnvVarBase 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 pErrInfo Where to return extended error information.
* Optional.
*
* @returns VBox status code.
*/
int VBoxLogRelCreate(const char *pszEntity, const char *pszLogFile,
uint32_t fFlags, const char *pszGroupSettings,
const char *pszEnvVarBase, uint32_t fDestFlags,
uint32_t cMaxEntriesPerGroup, uint32_t cHistory,
uint32_t uHistoryFileTime, uint64_t uHistoryFileSize,
PRTERRINFO pErrInfo);
/**
* Creates a release log file, used both in VBoxSVC and in API clients.
*
* @param pszEntity Human readable name of the program.
* @param pszLogFile Name of the release log file.
* @param fFlags Logger instance flags.
* @param pszGroupSettings Group logging settings.
* @param pszEnvVarBase 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 pOutputIf The optional file output interface, can be NULL which will
* make use of the default one.
* @param pvOutputIfUser The opaque user data to pass to the callbacks in the output interface.
* @param pErrInfo Where to return extended error information.
* Optional.
*
* @returns VBox status code.
*
* @note Can't include log.h here because of precompiled header fun, hence pOutputIf is void *...
*/
int VBoxLogRelCreateEx(const char *pszEntity, const char *pszLogFile,
uint32_t fFlags, const char *pszGroupSettings,
const char *pszEnvVarBase, uint32_t fDestFlags,
uint32_t cMaxEntriesPerGroup, uint32_t cHistory,
uint32_t uHistoryFileTime, uint64_t uHistoryFileSize,
const void *pOutputIf, void *pvOutputIfUser,
PRTERRINFO pErrInfo);
} /* namespace com */
/** @} */
#endif /* !VBOX_INCLUDED_com_utils_h */