OLD | NEW |
| (Empty) |
1 // Copyright 2009-2010 Google Inc. | |
2 // | |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | |
4 // you may not use this file except in compliance with the License. | |
5 // You may obtain a copy of the License at | |
6 // | |
7 // http://www.apache.org/licenses/LICENSE-2.0 | |
8 // | |
9 // Unless required by applicable law or agreed to in writing, software | |
10 // distributed under the License is distributed on an "AS IS" BASIS, | |
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
12 // See the License for the specific language governing permissions and | |
13 // limitations under the License. | |
14 // ======================================================================== | |
15 | |
16 #include "omaha/common/update3_utils.h" | |
17 #include <atlsafe.h> | |
18 #include "goopdate/omaha3_idl.h" | |
19 #include "omaha/base/const_object_names.h" | |
20 #include "omaha/base/debug.h" | |
21 #include "omaha/base/logging.h" | |
22 #include "omaha/base/system.h" | |
23 #include "omaha/base/vistautil.h" | |
24 #include "omaha/goopdate/google_update3.h" | |
25 | |
26 namespace omaha { | |
27 | |
28 namespace update3_utils { | |
29 | |
30 namespace { | |
31 | |
32 template <typename Update3COMClassT> | |
33 HRESULT CreateGoogleUpdate3LocalClass(IGoogleUpdate3** server) { | |
34 CORE_LOG(L3, (_T("[CreateGoogleUpdate3LocalClass]"))); | |
35 ASSERT1(server); | |
36 | |
37 typedef CComObject<Update3COMClassT> Update3; | |
38 scoped_ptr<Update3> update3; | |
39 HRESULT hr = Update3::CreateInstance(address(update3)); | |
40 if (FAILED(hr)) { | |
41 CORE_LOG(LE, (_T("[Update3 creation failed][0x%x]"), hr)); | |
42 return hr; | |
43 } | |
44 | |
45 hr = update3->QueryInterface(server); | |
46 if (FAILED(hr)) { | |
47 CORE_LOG(LE, (_T("[Update3 QueryInterface failed][0x%x]"), hr)); | |
48 return hr; | |
49 } | |
50 | |
51 update3.release(); | |
52 | |
53 return S_OK; | |
54 } | |
55 | |
56 } // namespace | |
57 | |
58 HRESULT SetProxyBlanketAllowImpersonate(IUnknown* server) { | |
59 ASSERT1(server); | |
60 | |
61 HRESULT hr = ::CoSetProxyBlanket(server, RPC_C_AUTHN_DEFAULT, | |
62 RPC_C_AUTHZ_DEFAULT, COLE_DEFAULT_PRINCIPAL, RPC_C_AUTHN_LEVEL_DEFAULT, | |
63 RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_DEFAULT); | |
64 | |
65 // E_NOINTERFACE indicates an in-proc intra-apartment call. | |
66 if (FAILED(hr) && hr != E_NOINTERFACE) { | |
67 CORE_LOG(LE, (_T("[::CoSetProxyBlanket failed][0x%x]"), hr)); | |
68 return hr; | |
69 } | |
70 | |
71 return S_OK; | |
72 } | |
73 | |
74 HRESULT CreateGoogleUpdate3Class(bool is_machine, IGoogleUpdate3** server) { | |
75 CORE_LOG(L3, (_T("[CreateGoogleUpdate3Class][%d]"), is_machine)); | |
76 ASSERT1(server); | |
77 | |
78 CComPtr<IGoogleUpdate3> com_server; | |
79 HRESULT hr = is_machine ? CreateGoogleUpdate3MachineClass(&com_server) : | |
80 CreateGoogleUpdate3UserClass(&com_server); | |
81 if (FAILED(hr)) { | |
82 return hr; | |
83 } | |
84 | |
85 hr = SetProxyBlanketAllowImpersonate(com_server); | |
86 if (FAILED(hr)) { | |
87 return hr; | |
88 } | |
89 | |
90 *server = com_server.Detach(); | |
91 return S_OK; | |
92 } | |
93 | |
94 // Tries to CoCreate the service CLSID first. If that fails, tries to create the | |
95 // server in-proc. Finally, sets a security blanket on the interface to allow | |
96 // the server to impersonate the client. | |
97 HRESULT CreateGoogleUpdate3MachineClass(IGoogleUpdate3** machine_server) { | |
98 ASSERT1(machine_server); | |
99 ASSERT1(vista_util::IsUserAdmin()); | |
100 | |
101 CComPtr<IGoogleUpdate3> server; | |
102 HRESULT hr = server.CoCreateInstance(__uuidof(GoogleUpdate3ServiceClass)); | |
103 | |
104 if (FAILED(hr)) { | |
105 CORE_LOG(LE, (_T("[CoCreate GoogleUpdate3ServiceClass failed][0x%x]"), hr)); | |
106 | |
107 hr = CreateGoogleUpdate3LocalClass<Update3COMClassService>(&server); | |
108 if (hr == GOOPDATE_E_INSTANCES_RUNNING) { | |
109 CORE_LOG(L3, (_T("[Retry CoCreate GoogleUpdate3ServiceClass]"))); | |
110 hr = server.CoCreateInstance(__uuidof(GoogleUpdate3ServiceClass)); | |
111 } | |
112 | |
113 if (FAILED(hr)) { | |
114 CORE_LOG(LE, (_T("[Create GoogleUpdate3MachineClass failed][0x%x]"), hr)); | |
115 return hr; | |
116 } | |
117 } | |
118 | |
119 ASSERT1(server); | |
120 *machine_server = server.Detach(); | |
121 return S_OK; | |
122 } | |
123 | |
124 // Tries to CoCreate the LocalServer CLSID first. If that fails, tries to create | |
125 // the server in-proc. | |
126 HRESULT CreateGoogleUpdate3UserClass(IGoogleUpdate3** user_server) { | |
127 ASSERT1(user_server); | |
128 | |
129 CComPtr<IGoogleUpdate3> server; | |
130 HRESULT hr = server.CoCreateInstance(__uuidof(GoogleUpdate3UserClass)); | |
131 if (FAILED(hr)) { | |
132 CORE_LOG(LE, (_T("[CoCreate GoogleUpdate3UserClass failed][0x%x]"), hr)); | |
133 | |
134 // The primary reason for the LocalServer activation failing on Vista/Win7 | |
135 // is that COM does not look at HKCU registration when the code is running | |
136 // elevated. We fall back to an in-proc mode. The in-proc mode is limited to | |
137 // one install at a time, so we use it only as a backup mechanism. | |
138 OPT_LOG(LE, (_T("[IsElevatedWithUACMaybeOn][%d]"), | |
139 vista_util::IsElevatedWithUACMaybeOn())); | |
140 hr = CreateGoogleUpdate3LocalClass<Update3COMClassUser>(&server); | |
141 if (FAILED(hr)) { | |
142 return hr; | |
143 } | |
144 } | |
145 | |
146 ASSERT1(server); | |
147 *user_server = server.Detach(); | |
148 return S_OK; | |
149 } | |
150 | |
151 HRESULT CreateAppBundle(IGoogleUpdate3* server, IAppBundle** app_bundle) { | |
152 ASSERT1(server); | |
153 ASSERT1(app_bundle); | |
154 | |
155 CComPtr<IDispatch> idispatch; | |
156 HRESULT hr = server->createAppBundle(&idispatch); | |
157 if (FAILED(hr)) { | |
158 return hr; | |
159 } | |
160 | |
161 return idispatch.QueryInterface(app_bundle); | |
162 } | |
163 | |
164 HRESULT CreateApp(BSTR app_id, IAppBundle* app_bundle, IApp** app) { | |
165 ASSERT1(app_id); | |
166 ASSERT1(app_bundle); | |
167 ASSERT1(app); | |
168 | |
169 CComPtr<IDispatch> idispatch; | |
170 HRESULT hr = app_bundle->createApp(app_id, &idispatch); | |
171 if (FAILED(hr)) { | |
172 return hr; | |
173 } | |
174 | |
175 return idispatch.QueryInterface(app); | |
176 } | |
177 | |
178 HRESULT CreateInstalledApp(BSTR app_id, IAppBundle* app_bundle, IApp** app) { | |
179 ASSERT1(app_id); | |
180 ASSERT1(app_bundle); | |
181 ASSERT1(app); | |
182 | |
183 CComPtr<IDispatch> idispatch; | |
184 HRESULT hr = app_bundle->createInstalledApp(app_id, &idispatch); | |
185 if (FAILED(hr)) { | |
186 return hr; | |
187 } | |
188 | |
189 return idispatch.QueryInterface(app); | |
190 } | |
191 | |
192 HRESULT CreateAllInstalledApps(IAppBundle* app_bundle) { | |
193 ASSERT1(app_bundle); | |
194 | |
195 return app_bundle->createAllInstalledApps(); | |
196 } | |
197 | |
198 HRESULT GetApp(IAppBundle* app_bundle, long index, IApp** app) { // NOLINT | |
199 ASSERT1(app_bundle); | |
200 ASSERT1(index >= 0); | |
201 ASSERT1(app); | |
202 | |
203 CComPtr<IDispatch> app_idispatch; | |
204 HRESULT hr = app_bundle->get_Item(index, &app_idispatch); | |
205 if (FAILED(hr)) { | |
206 return hr; | |
207 } | |
208 ASSERT1(app_idispatch); | |
209 | |
210 return app_idispatch.QueryInterface(app); | |
211 } | |
212 | |
213 HRESULT GetCurrentAppVersion(IApp* app, IAppVersion** app_version) { | |
214 ASSERT1(app); | |
215 ASSERT1(app_version); | |
216 | |
217 CComPtr<IDispatch> idispatch; | |
218 HRESULT hr = app->get_currentVersion(&idispatch); | |
219 if (FAILED(hr)) { | |
220 return hr; | |
221 } | |
222 | |
223 return idispatch.QueryInterface(app_version); | |
224 } | |
225 | |
226 HRESULT GetNextAppVersion(IApp* app, IAppVersion** app_version) { | |
227 ASSERT1(app); | |
228 ASSERT1(app_version); | |
229 | |
230 CComPtr<IDispatch> idispatch; | |
231 HRESULT hr = app->get_nextVersion(&idispatch); | |
232 if (FAILED(hr)) { | |
233 return hr; | |
234 } | |
235 | |
236 return idispatch.QueryInterface(app_version); | |
237 } | |
238 | |
239 HRESULT GetAppCurrentState(IApp* app, | |
240 CurrentState* current_state, | |
241 ICurrentState** icurrent_state) { | |
242 ASSERT1(app); | |
243 ASSERT1(current_state); | |
244 ASSERT1(icurrent_state); | |
245 | |
246 CComPtr<IDispatch> idispatch; | |
247 HRESULT hr = app->get_currentState(&idispatch); | |
248 if (FAILED(hr)) { | |
249 return hr; | |
250 } | |
251 | |
252 hr = idispatch.QueryInterface(icurrent_state); | |
253 if (FAILED(hr)) { | |
254 return hr; | |
255 } | |
256 | |
257 LONG state = 0; | |
258 hr = (*icurrent_state)->get_stateValue(&state); | |
259 if (FAILED(hr)) { | |
260 return hr; | |
261 } | |
262 | |
263 *current_state = static_cast<CurrentState>(state); | |
264 return S_OK; | |
265 } | |
266 | |
267 } // namespace update3_utils | |
268 | |
269 } // namespace omaha | |
OLD | NEW |