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
143
144
145
146
147
148
149
150
|
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ceee/ie/plugin/toolband/toolband_proxy.h"
#include <atlbase.h>
#include "base/logging.h"
#include "base/stringprintf.h"
#include "base/win/registry.h"
#include "ceee/common/com_utils.h"
#include "ceee/ie/plugin/toolband/resource.h"
#include "toolband.h" // NOLINT
extern "C" {
// Declare the entrypoint function(s) generated by MIDL for our proxy/stubs.
HRESULT STDAPICALLTYPE ToolbandProxyDllGetClassObject(REFCLSID clsid,
REFIID iid,
void** ppv);
} // extern "C"
namespace {
struct InterfaceInfo {
const wchar_t* name;
const IID* iid;
const IID* async_iid;
};
#define DECLARE_SYNC_INTERFACE(itf) \
{ L#itf, &IID_##itf, NULL },
#define DECLARE_ASYNC_INTERFACE(itf) \
{ L#itf, &IID_##itf, &IID_Async##itf }, \
DECLARE_SYNC_INTERFACE(Async##itf)
// If you add new executor interfaces to toolband.idl, make sure to add
// their IIDs here, or you will not be able to marshal them.
const InterfaceInfo kInterfaceInfo[] = {
DECLARE_SYNC_INTERFACE(ICeeeWindowExecutor)
DECLARE_ASYNC_INTERFACE(ICeeeTabExecutor)
DECLARE_SYNC_INTERFACE(ICeeeCookieExecutor)
DECLARE_SYNC_INTERFACE(ICeeeInfobarExecutor)
};
#ifndef NDEBUG
void CheckAsyncIidRegistered(const IID& iid, const IID& async_iid) {
std::wstring iid_str;
bool success = com::GuidToString(iid, &iid_str);
DCHECK(success);
std::wstring key_name = base::StringPrintf(
L"Interface\\%ls\\AsynchronousInterface", iid_str);
base::win::RegKey key;
if (key.Open(HKEY_CLASSES_ROOT, key_name.c_str(), KEY_READ)) {
// It's registered, the rest of this block is debug checking that
// the correct IID is indeed registered for the async interface.
std::wstring async_iid_str;
DCHECK(key.ReadValue(NULL, &async_iid_str));
IID read_async_iid;
DCHECK(SUCCEEDED(::IIDFromString(async_iid_str.c_str(), &read_async_iid)));
DCHECK(read_async_iid == async_iid);
} else {
LOG(WARNING) << "Sync->Async IID not registered. Key=" << key_name;
}
}
#endif // NDEBUG
} // namespace
bool RegisterProxyStubs(std::vector<DWORD>* cookies) {
bool succeeded = true;
for (size_t i = 0; i < arraysize(kInterfaceInfo); ++i) {
CComPtr<IUnknown> factory;
const InterfaceInfo& info = kInterfaceInfo[i];
HRESULT hr = ToolbandProxyDllGetClassObject(*info.iid, IID_IUnknown,
reinterpret_cast<void**>(&factory));
DWORD cookie = 0;
if (SUCCEEDED(hr)) {
hr = ::CoRegisterClassObject(*info.iid, factory, CLSCTX_INPROC_SERVER,
REGCLS_MULTIPLEUSE, &cookie);
}
if (SUCCEEDED(hr)) {
// Proxy/stubs have their own IID as class id.
hr = ::CoRegisterPSClsid(*info.iid, *info.iid);
if (SUCCEEDED(hr) && cookies != NULL) {
cookies->push_back(cookie);
}
}
#ifndef NDEBUG
// If there's a corresponding Async interface, check whether
// it's registered. This is a debugging aid only.
if (info.async_iid != NULL)
CheckAsyncIidRegistered(*info.iid, *info.async_iid);
#endif // NDEBUG
if (FAILED(hr)) {
succeeded = false;
LOG(ERROR) << "Failed to register proxy " << com::LogHr(hr);
}
}
VLOG(1) << "Registered toolband proxy/stubs in thread "
<< ::GetCurrentThreadId();
return succeeded;
}
void UnregisterProxyStubs(const std::vector<DWORD>& cookies) {
for (size_t i = 0; i < cookies.size(); ++i) {
HRESULT hr = ::CoRevokeClassObject(cookies[i]);
if (FAILED(hr)) {
LOG(ERROR) << "Failed to revoke class object " << com::LogHr(hr);
}
}
}
bool RegisterAsyncProxies(bool reg) {
for (size_t i = 0; i < arraysize(kInterfaceInfo); ++i) {
// Register the iid->async iid mapping for async interfaces.
if (kInterfaceInfo[i].async_iid != NULL) {
const InterfaceInfo& info = kInterfaceInfo[i];
std::wstring iid_str;
bool success = com::GuidToString(*info.iid, &iid_str);
DCHECK(success) << "Failed to stringify GUID";
std::wstring async_iid_str;
success = com::GuidToString(*info.async_iid, &async_iid_str);
DCHECK(success) << "Failed to stringify GUID";
_ATL_REGMAP_ENTRY entries[] = {
{ L"IID", iid_str.c_str() },
{ L"ASYNC_IID", async_iid_str.c_str() },
{ L"NAME", info.name },
{ NULL, NULL },
};
HRESULT hr = _pAtlModule->UpdateRegistryFromResource(
MAKEINTRESOURCE(IDR_TOOLBAND_PROXY), reg, entries);
if (FAILED(hr)) {
LOG(ERROR) << "Failed to register async interface for " <<
info.name << com::LogHr(hr);
return false;
}
}
}
return true;
}
|