||This is used for stabilizing a COM object's reference count during
construction when that object aggregates other objects. Since the aggregated
object(s) may AddRef() or Release(), we need to artifically boost the
refcount to prevent premature destruction. Note that we increment/decrement
instead of AddRef()/Release() in this class because we want to adjust the
refcount without causing any other side effects (like object destruction).
||This class encapsulates an "agile reference." These are references that
allow you to pass COM interfaces between apartments. When you have an
interface that you would like to pass between apartments, you wrap that
interface in an AgileReference and pass the agile reference instead. Then
you unwrap the interface by calling AgileReference::Resolve.
// In the multithreaded apartment, foo is an IFoo*
auto myAgileRef = MakeUnique<AgileReference>(IID_IFoo, foo);
// myAgileRef is passed to our main thread, which runs in a single-threaded
HRESULT hr = myAgileRef->Resolve(IID_IFoo, getter_AddRefs(foo));
// Now foo may be called from the main thread
||This constructor is to be used when we want to instantiate the object but
we do not yet know which type of apartment we want. Call Init() to
||This constructor just ensures that the MTA thread is up and running.
||When we are marshaling to the parent process main thread, we want to turn
off COM's ping functionality. That functionality is designed to free
strong references held by defunct client processes. Since our content
processes cannot outlive our parent process, we turn off pings when we know
that the COM client is going to be our parent process. This provides a
significant performance boost in a11y code due to large numbers of remote
objects being created and destroyed within a short period of time.
||Determine whether this interface might be supported by objects using
This is used to avoid unnecessary cross-thread QueryInterface calls for
interfaces known to be unsupported.
Return S_OK if the interface might be supported, E_NOINTERFACE if it
definitely isn't supported.
||We don't use the normal XPCOM BaseAutoLock because we need the ability
to explicitly Unlock.
||The COM interceptor is the core functionality in mscom that allows us to
redirect method calls to different threads. It emulates the vtable of a
target interface. When a call is made on this emulated vtable, the call is
packaged up into an instance of the ICallFrame interface which may be passed
to other contexts for execution.
In order to accomplish this, COM itself provides the CoGetInterceptor
function, which instantiates an ICallInterceptor. Note, however, that
ICallInterceptor only works on a single interface; we need to be able to
interpose QueryInterface calls so that we can instantiate a new
ICallInterceptor for each new interface that is requested.
We accomplish this by using COM aggregation, which means that the
ICallInterceptor delegates its IUnknown implementation to its outer object
(the mscom::Interceptor we implement and control).
||SyncRunnable implements different code paths depending on whether or not
we are running on a multiprocessor system. In the multiprocessor case, we
leave the thread in a spin loop while waiting for the main thread to execute
our runnable. Since spinning is pointless in the uniprocessor case, we block
on an event that is set by the main thread once it has finished the runnable.
||Given a buffer containing a serialized proxy to an interface with a handler,
this function strips out the handler and converts it to a standard one.
@param aStream IStream containing a serialized proxy.
There should be nothing else written to the stream past the
@param aStart Absolute position of the beginning of the OBJREF.
@param aEnd Absolute position of the end of the OBJREF.
@return true if the handler was successfully stripped, otherwise false.
||@return 0 if call is in-process or resolving the calling thread failed,
otherwise contains the thread id of the calling thread.
||The glue code in mozilla::mscom often needs to pass around interface pointers
belonging to a different apartment from the current one. We must not touch
the reference counts of those objects on the wrong apartment. By using these
UniquePtr specializations, we may ensure that the reference counts are always
||This code MUST NOT use any non-inlined internal Mozilla APIs, as it will be
compiled into DLLs that COM may load into non-Mozilla processes!
(1) The DLL exports GetProxyDllInfo. This is not exported by default; it must
be specified in the EXPORTS section of the DLL's module definition file.
||This function fails unless the entire string has been converted.
(eg, the string "FLAGS" will convert to 0xF but we will return false)
||These functions need to be defined in order for the types that use
mozilla::mscom::StructToStream and mozilla::mscom::StructFromStream to work.
||This code is used for (de)serializing data structures that have been
declared using midl, thus allowing us to use Microsoft RPC for marshaling
data for our COM handlers that may run in other processes that are not ours.
||Given a buffer, create a new IStream object.
@param aBuf Buffer containing data to initialize the stream. This parameter
may be nullptr, causing the stream to be created with aBufLen
bytes of uninitialized data.
@param aBufLen Length of data in aBuf, or desired stream size if aBuf is
@param aOutStream Outparam to receive the newly created stream.
@return HRESULT error code.
||This function constructs an interface with |aVtblSize| entries, where the
IUnknown methods are valid and redirect to |aUnk|. Other than the IUnknown
methods, the resulting interface is not intended to actually be called; the
remaining vtable entries are null pointers to enforce that.
@param aUnk The IUnknown to which the null vtable will redirect its IUnknown
@param aVtblSize The total size of the vtable, including the IUnknown
entries (thus this parameter must be >= 3).
@return The resulting IUnknown, or nullptr on error.
||Thread-safe weak references for COM that works pre-Windows 8 and do not