@@ -34,14 +34,89 @@ HRESULT WINAPI RoGetAgileReference(AgileReferenceOptions options, REFIID riid,
34
34
35
35
namespace mozilla {
36
36
namespace mscom {
37
+ namespace detail {
37
38
38
- AgileReference::AgileReference () : mIid (), mGitCookie (0 ) {}
39
+ GlobalInterfaceTableCookie::GlobalInterfaceTableCookie (IUnknown* aObject,
40
+ REFIID aIid,
41
+ HRESULT& aOutHResult)
42
+ : mCookie (0 ) {
43
+ IGlobalInterfaceTable* git = ObtainGit ();
44
+ MOZ_ASSERT (git);
45
+ if (!git) {
46
+ aOutHResult = E_POINTER;
47
+ return ;
48
+ }
49
+
50
+ aOutHResult = git->RegisterInterfaceInGlobal (aObject, aIid, &mCookie );
51
+ MOZ_ASSERT (SUCCEEDED (aOutHResult));
52
+ }
53
+
54
+ GlobalInterfaceTableCookie::~GlobalInterfaceTableCookie () {
55
+ IGlobalInterfaceTable* git = ObtainGit ();
56
+ MOZ_ASSERT (git);
57
+ if (!git) {
58
+ return ;
59
+ }
60
+
61
+ DebugOnly<HRESULT> hr = git->RevokeInterfaceFromGlobal (mCookie );
62
+ #if defined(MOZILLA_INTERNAL_API)
63
+ NS_WARNING_ASSERTION (
64
+ SUCCEEDED (hr),
65
+ nsPrintfCString(" IGlobalInterfaceTable::RevokeInterfaceFromGlobal failed "
66
+ " with HRESULT 0x%08lX" ,
67
+ ((HRESULT)hr))
68
+ .get());
69
+ #else
70
+ MOZ_ASSERT (SUCCEEDED(hr));
71
+ #endif // defined(MOZILLA_INTERNAL_API)
72
+ mCookie = 0 ;
73
+ }
74
+
75
+ HRESULT GlobalInterfaceTableCookie::GetInterface (REFIID aIid,
76
+ void ** aOutInterface) const {
77
+ IGlobalInterfaceTable* git = ObtainGit ();
78
+ MOZ_ASSERT (git);
79
+ if (!git) {
80
+ return E_UNEXPECTED;
81
+ }
82
+
83
+ MOZ_ASSERT (IsValid ());
84
+ return git->GetInterfaceFromGlobal (mCookie , aIid, aOutInterface);
85
+ }
86
+
87
+ /* static */
88
+ IGlobalInterfaceTable* GlobalInterfaceTableCookie::ObtainGit () {
89
+ // Internally to COM, the Global Interface Table is a singleton, therefore we
90
+ // don't worry about holding onto this reference indefinitely.
91
+ static IGlobalInterfaceTable* sGit = []() -> IGlobalInterfaceTable* {
92
+ IGlobalInterfaceTable* result = nullptr ;
93
+ DebugOnly<HRESULT> hr = ::CoCreateInstance (
94
+ CLSID_StdGlobalInterfaceTable, nullptr , CLSCTX_INPROC_SERVER,
95
+ IID_IGlobalInterfaceTable, reinterpret_cast <void **>(&result));
96
+ MOZ_ASSERT (SUCCEEDED (hr));
97
+ return result;
98
+ }();
99
+
100
+ return sGit ;
101
+ }
102
+
103
+ } // namespace detail
104
+
105
+ AgileReference::AgileReference () : mIid(), mHResult(E_NOINTERFACE) {}
39
106
40
107
AgileReference::AgileReference (REFIID aIid, IUnknown* aObject)
41
- : mIid (aIid), mGitCookie ( 0 ) {
108
+ : mIid(aIid), mHResult(E_UNEXPECTED ) {
42
109
AssignInternal (aObject);
43
110
}
44
111
112
+ AgileReference::AgileReference (AgileReference&& aOther)
113
+ : mIid(aOther.mIid ),
114
+ mAgileRef(std::move(aOther.mAgileRef )),
115
+ mGitCookie(std::move(aOther.mGitCookie )),
116
+ mHResult(aOther.mHResult ) {
117
+ aOther.mHResult = CO_E_RELEASED;
118
+ }
119
+
45
120
void AgileReference::Assign (REFIID aIid, IUnknown* aObject) {
46
121
Clear ();
47
122
mIid = aIid;
@@ -66,74 +141,49 @@ void AgileReference::AssignInternal(IUnknown* aObject) {
66
141
MOZ_ASSERT (aObject);
67
142
68
143
if (pRoGetAgileReference &&
69
- SUCCEEDED (pRoGetAgileReference (AGILEREFERENCE_DEFAULT, mIid , aObject,
70
- getter_AddRefs (mAgileRef )))) {
71
- return ;
72
- }
73
-
74
- IGlobalInterfaceTable* git = ObtainGit ();
75
- MOZ_ASSERT (git);
76
- if (!git) {
144
+ SUCCEEDED (mHResult =
145
+ pRoGetAgileReference (AGILEREFERENCE_DEFAULT, mIid , aObject,
146
+ getter_AddRefs (mAgileRef )))) {
77
147
return ;
78
148
}
79
149
80
- DebugOnly<HRESULT> hr =
81
- git->RegisterInterfaceInGlobal (aObject, mIid , &mGitCookie );
82
- MOZ_ASSERT (SUCCEEDED (hr));
83
- }
84
-
85
- AgileReference::AgileReference (AgileReference&& aOther)
86
- : mIid (aOther.mIid ),
87
- mAgileRef (std::move(aOther.mAgileRef )),
88
- mGitCookie(aOther.mGitCookie ) {
89
- aOther.mGitCookie = 0 ;
150
+ mGitCookie = new detail::GlobalInterfaceTableCookie (aObject, mIid , mHResult );
151
+ MOZ_ASSERT (mGitCookie ->IsValid ());
90
152
}
91
153
92
154
AgileReference::~AgileReference () { Clear (); }
93
155
94
156
void AgileReference::Clear () {
95
157
mIid = {};
158
+ mAgileRef = nullptr ;
159
+ mGitCookie = nullptr ;
160
+ mHResult = E_NOINTERFACE;
161
+ }
96
162
97
- if (!mGitCookie ) {
98
- mAgileRef = nullptr ;
99
- return ;
100
- }
101
-
102
- IGlobalInterfaceTable* git = ObtainGit ();
103
- MOZ_ASSERT (git);
104
- if (!git) {
105
- return ;
106
- }
107
-
108
- DebugOnly<HRESULT> hr = git->RevokeInterfaceFromGlobal (mGitCookie );
109
- #if defined(MOZILLA_INTERNAL_API)
110
- NS_WARNING_ASSERTION (
111
- SUCCEEDED (hr),
112
- nsPrintfCString(" IGlobalInterfaceTable::RevokeInterfaceFromGlobal failed "
113
- " with HRESULT "
114
- " 0x%08lX" ,
115
- ((HRESULT)hr))
116
- .get());
117
- #else
118
- MOZ_ASSERT (SUCCEEDED(hr));
119
- #endif // defined(MOZILLA_INTERNAL_API)
120
- mGitCookie = 0 ;
163
+ AgileReference& AgileReference::operator =(const AgileReference& aOther) {
164
+ Clear ();
165
+ mIid = aOther.mIid ;
166
+ mAgileRef = aOther.mAgileRef ;
167
+ mGitCookie = aOther.mGitCookie ;
168
+ mHResult = aOther.mHResult ;
169
+ return *this ;
121
170
}
122
171
123
172
AgileReference& AgileReference::operator =(AgileReference&& aOther) {
124
173
Clear ();
125
174
mIid = aOther.mIid ;
126
- aOther.mIid = {};
127
175
mAgileRef = std::move (aOther.mAgileRef );
128
- mGitCookie = aOther.mGitCookie ;
129
- aOther.mGitCookie = 0 ;
176
+ mGitCookie = std::move (aOther.mGitCookie );
177
+ mHResult = aOther.mHResult ;
178
+ aOther.mHResult = CO_E_RELEASED;
130
179
return *this ;
131
180
}
132
181
133
182
HRESULT
134
183
AgileReference::Resolve (REFIID aIid, void ** aOutInterface) const {
135
184
MOZ_ASSERT (aOutInterface);
136
- MOZ_ASSERT (mAgileRef || mGitCookie );
185
+ // This check is exclusive-OR; we should have one or the other, but not both
186
+ MOZ_ASSERT ((mAgileRef || mGitCookie ) && !(mAgileRef && mGitCookie ));
137
187
MOZ_ASSERT (IsCOMInitializedOnCurrentThread ());
138
188
139
189
if (!aOutInterface) {
@@ -151,15 +201,9 @@ AgileReference::Resolve(REFIID aIid, void** aOutInterface) const {
151
201
return E_UNEXPECTED;
152
202
}
153
203
154
- IGlobalInterfaceTable* git = ObtainGit ();
155
- MOZ_ASSERT (git);
156
- if (!git) {
157
- return E_UNEXPECTED;
158
- }
159
-
160
204
RefPtr<IUnknown> originalInterface;
161
- HRESULT hr = git-> GetInterfaceFromGlobal ( mGitCookie , mIid ,
162
- getter_AddRefs (originalInterface));
205
+ HRESULT hr =
206
+ mGitCookie -> GetInterface ( mIid , getter_AddRefs (originalInterface));
163
207
if (FAILED (hr)) {
164
208
return hr;
165
209
}
@@ -174,21 +218,5 @@ AgileReference::Resolve(REFIID aIid, void** aOutInterface) const {
174
218
return originalInterface->QueryInterface (aIid, aOutInterface);
175
219
}
176
220
177
- /* static */
178
- IGlobalInterfaceTable* AgileReference::ObtainGit () {
179
- // Internally to COM, the Global Interface Table is a singleton, therefore we
180
- // don't worry about holding onto this reference indefinitely.
181
- static IGlobalInterfaceTable* sGit = []() -> IGlobalInterfaceTable* {
182
- IGlobalInterfaceTable* result = nullptr ;
183
- DebugOnly<HRESULT> hr = ::CoCreateInstance (
184
- CLSID_StdGlobalInterfaceTable, nullptr , CLSCTX_INPROC_SERVER,
185
- IID_IGlobalInterfaceTable, reinterpret_cast <void **>(&result));
186
- MOZ_ASSERT (SUCCEEDED (hr));
187
- return result;
188
- }();
189
-
190
- return sGit ;
191
- }
192
-
193
221
} // namespace mscom
194
222
} // namespace mozilla
0 commit comments