Adding upstream version 7.0.20-dfsg.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
This commit is contained in:
parent
d0c7daf57c
commit
df1bda4fe9
26643 changed files with 10005219 additions and 0 deletions
704
include/VBox/com/AutoLock.h
Normal file
704
include/VBox/com/AutoLock.h
Normal 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: */
|
545
include/VBox/com/ErrorInfo.h
Normal file
545
include/VBox/com/ErrorInfo.h
Normal 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 */
|
||||
|
151
include/VBox/com/EventQueue.h
Normal file
151
include/VBox/com/EventQueue.h
Normal 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
526
include/VBox/com/Guid.h
Normal 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 */
|
||||
|
0
include/VBox/com/Makefile.kup
Normal file
0
include/VBox/com/Makefile.kup
Normal file
278
include/VBox/com/MultiResult.h
Normal file
278
include/VBox/com/MultiResult.h
Normal 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 */
|
||||
|
161
include/VBox/com/NativeEventQueue.h
Normal file
161
include/VBox/com/NativeEventQueue.h
Normal 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 */
|
||||
|
71
include/VBox/com/VirtualBox.h
Normal file
71
include/VBox/com/VirtualBox.h
Normal 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
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
135
include/VBox/com/assert.h
Normal 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
102
include/VBox/com/com.h
Normal 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
606
include/VBox/com/defs.h
Normal 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>
|
||||
* <param name="arg" ... dir="in" safearray="yes"/>
|
||||
* ...
|
||||
* <attribute name="arg" ... safearray="yes"/>
|
||||
* </pre>
|
||||
*
|
||||
* The method implementation should use the com::SafeArray helper class to work
|
||||
* with parameters declared using this define.
|
||||
*
|
||||
* @param aType Array element type.
|
||||
* @param aArg Parameter/attribute name.
|
||||
*/
|
||||
#define ComSafeArrayIn(aType, aArg) SAFEARRAY *aArg
|
||||
|
||||
/**
|
||||
* Expands to @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>
|
||||
* <param name="arg" ... dir="out" safearray="yes"/>
|
||||
* <param name="arg" ... dir="return" safearray="yes"/>
|
||||
* ...
|
||||
* <attribute name="arg" ... safearray="yes"/>
|
||||
* </pre>
|
||||
*
|
||||
* The method implementation should use the com::SafeArray helper class to work
|
||||
* with parameters declared using this define.
|
||||
*
|
||||
* @param aType Array element type.
|
||||
* @param aArg Parameter/attribute name.
|
||||
*/
|
||||
#define ComSafeArrayOut(aType, aArg) SAFEARRAY **aArg
|
||||
|
||||
/**
|
||||
* Expands to @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 */
|
||||
|
401
include/VBox/com/errorprint.h
Normal file
401
include/VBox/com/errorprint.h
Normal 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
223
include/VBox/com/list.h
Normal 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 */
|
||||
|
194
include/VBox/com/listeners.h
Normal file
194
include/VBox/com/listeners.h
Normal 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
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
220
include/VBox/com/mtlist.h
Normal 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
569
include/VBox/com/ptr.h
Normal 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
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
132
include/VBox/com/utils.h
Normal 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 */
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue