summaryrefslogtreecommitdiffstats
path: root/ipc/mscom/Registration.h
blob: 3dfd5458cdc6a840bd1d6b6d904a66ead62c7e3b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/* -*- 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;

  void Clear();

  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