Blob Blame History Raw
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef mozilla_mscom_Registration_h
#define mozilla_mscom_Registration_h

#include "mozilla/RefPtr.h"
#include "mozilla/UniquePtr.h"

#include <objbase.h>

struct ITypeInfo;
struct ITypeLib;

namespace mozilla {
namespace mscom {

/**
 * Assumptions:
 * (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.
 */
class RegisteredProxy {
 public:
  RegisteredProxy(uintptr_t aModule, IUnknown* aClassObject,
                  uint32_t aRegCookie, ITypeLib* aTypeLib);
  RegisteredProxy(IUnknown* aClassObject, uint32_t aRegCookie,
                  ITypeLib* aTypeLib);
  explicit RegisteredProxy(ITypeLib* aTypeLib);
  RegisteredProxy(RegisteredProxy&& aOther);
  RegisteredProxy& operator=(RegisteredProxy&& aOther);

  ~RegisteredProxy();

  HRESULT GetTypeInfoForGuid(REFGUID aGuid, ITypeInfo** aOutTypeInfo) const;

  static bool Find(REFIID aIid, ITypeInfo** aOutTypeInfo);

 private:
  RegisteredProxy() = delete;
  RegisteredProxy(RegisteredProxy&) = delete;
  RegisteredProxy& operator=(RegisteredProxy&) = delete;

  static void AddToRegistry(RegisteredProxy* aProxy);
  static void DeleteFromRegistry(RegisteredProxy* aProxy);

 private:
  // Not using Windows types here: We shouldn't #include windows.h
  // since it might pull in COM code which we want to do very carefully in
  // Registration.cpp.
  uintptr_t mModule;
  IUnknown* mClassObject;
  uint32_t mRegCookie;
  ITypeLib* mTypeLib;
#if defined(MOZILLA_INTERNAL_API)
  bool mIsRegisteredInMTA;
#endif  // defined(MOZILLA_INTERNAL_API)
};

enum class RegistrationFlags { eUseBinDirectory, eUseSystemDirectory };

// For our own DLL that we are currently executing in (ie, xul).
// Assumes corresponding TLB is embedded in resources.
UniquePtr<RegisteredProxy> RegisterProxy();

// For DLL files. Assumes corresponding TLB is embedded in resources.
UniquePtr<RegisteredProxy> RegisterProxy(
    const wchar_t* aLeafName,
    RegistrationFlags aFlags = RegistrationFlags::eUseBinDirectory);
// For standalone TLB files.
UniquePtr<RegisteredProxy> RegisterTypelib(
    const wchar_t* aLeafName,
    RegistrationFlags aFlags = RegistrationFlags::eUseBinDirectory);

#if defined(MOZILLA_INTERNAL_API)

/**
 * The COM interceptor uses type library information to build its interface
 * proxies. Unfortunately type libraries do not encode size_is and length_is
 * annotations that have been specified in IDL. This structure allows us to
 * explicitly declare such relationships so that the COM interceptor may
 * be made aware of them.
 */
struct ArrayData {
  enum class Flag {
    eNone = 0,
    eAllocatedByServer = 1  // This implies an extra level of indirection
  };

  ArrayData(REFIID aIid, ULONG aMethodIndex, ULONG aArrayParamIndex,
            VARTYPE aArrayParamType, REFIID aArrayParamIid,
            ULONG aLengthParamIndex, Flag aFlag = Flag::eNone)
      : mIid(aIid),
        mMethodIndex(aMethodIndex),
        mArrayParamIndex(aArrayParamIndex),
        mArrayParamType(aArrayParamType),
        mArrayParamIid(aArrayParamIid),
        mLengthParamIndex(aLengthParamIndex),
        mFlag(aFlag) {}

  ArrayData(const ArrayData& aOther) { *this = aOther; }

  ArrayData& operator=(const ArrayData& aOther) {
    mIid = aOther.mIid;
    mMethodIndex = aOther.mMethodIndex;
    mArrayParamIndex = aOther.mArrayParamIndex;
    mArrayParamType = aOther.mArrayParamType;
    mArrayParamIid = aOther.mArrayParamIid;
    mLengthParamIndex = aOther.mLengthParamIndex;
    mFlag = aOther.mFlag;
    return *this;
  }

  IID mIid;
  ULONG mMethodIndex;
  ULONG mArrayParamIndex;
  VARTYPE mArrayParamType;
  IID mArrayParamIid;
  ULONG mLengthParamIndex;
  Flag mFlag;
};

void RegisterArrayData(const ArrayData* aArrayData, size_t aLength);

template <size_t N>
inline void RegisterArrayData(const ArrayData (&aData)[N]) {
  RegisterArrayData(aData, N);
}

const ArrayData* FindArrayData(REFIID aIid, ULONG aMethodIndex);

#endif  // defined(MOZILLA_INTERNAL_API)

}  // namespace mscom
}  // namespace mozilla

#endif  // mozilla_mscom_Registration_h