Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(151)

Side by Side Diff: remoting/host/win/elevated_controller.cc

Issue 810133003: replace NULL->nullptr in src/remoting. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « remoting/host/win/com_security.cc ('k') | remoting/host/win/entry_point.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "remoting/host/win/elevated_controller.h" 5 #include "remoting/host/win/elevated_controller.h"
6 6
7 #include "base/file_version_info.h" 7 #include "base/file_version_info.h"
8 #include "base/files/file_util.h" 8 #include "base/files/file_util.h"
9 #include "base/json/json_reader.h" 9 #include "base/json/json_reader.h"
10 #include "base/json/json_writer.h" 10 #include "base/json/json_writer.h"
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
63 // Determines if the client runs in the security context that allows performing 63 // Determines if the client runs in the security context that allows performing
64 // administrative tasks (i.e. the user belongs to the adminstrators group and 64 // administrative tasks (i.e. the user belongs to the adminstrators group and
65 // the client runs elevated). 65 // the client runs elevated).
66 bool IsClientAdmin() { 66 bool IsClientAdmin() {
67 HRESULT hr = CoImpersonateClient(); 67 HRESULT hr = CoImpersonateClient();
68 if (FAILED(hr)) { 68 if (FAILED(hr)) {
69 return false; 69 return false;
70 } 70 }
71 71
72 SID_IDENTIFIER_AUTHORITY nt_authority = SECURITY_NT_AUTHORITY; 72 SID_IDENTIFIER_AUTHORITY nt_authority = SECURITY_NT_AUTHORITY;
73 PSID administrators_group = NULL; 73 PSID administrators_group = nullptr;
74 BOOL result = AllocateAndInitializeSid(&nt_authority, 74 BOOL result = AllocateAndInitializeSid(&nt_authority,
75 2, 75 2,
76 SECURITY_BUILTIN_DOMAIN_RID, 76 SECURITY_BUILTIN_DOMAIN_RID,
77 DOMAIN_ALIAS_RID_ADMINS, 77 DOMAIN_ALIAS_RID_ADMINS,
78 0, 0, 0, 0, 0, 0, 78 0, 0, 0, 0, 0, 0,
79 &administrators_group); 79 &administrators_group);
80 if (result) { 80 if (result) {
81 if (!CheckTokenMembership(NULL, administrators_group, &result)) { 81 if (!CheckTokenMembership(nullptr, administrators_group, &result)) {
82 result = false; 82 result = false;
83 } 83 }
84 FreeSid(administrators_group); 84 FreeSid(administrators_group);
85 } 85 }
86 86
87 hr = CoRevertToSelf(); 87 hr = CoRevertToSelf();
88 CHECK(SUCCEEDED(hr)); 88 CHECK(SUCCEEDED(hr));
89 89
90 return !!result; 90 return !!result;
91 } 91 }
92 92
93 // Reads and parses the configuration file up to |kMaxConfigFileSize| in 93 // Reads and parses the configuration file up to |kMaxConfigFileSize| in
94 // size. 94 // size.
95 HRESULT ReadConfig(const base::FilePath& filename, 95 HRESULT ReadConfig(const base::FilePath& filename,
96 scoped_ptr<base::DictionaryValue>* config_out) { 96 scoped_ptr<base::DictionaryValue>* config_out) {
97 97
98 // Read raw data from the configuration file. 98 // Read raw data from the configuration file.
99 base::win::ScopedHandle file( 99 base::win::ScopedHandle file(
100 CreateFileW(filename.value().c_str(), 100 CreateFileW(filename.value().c_str(),
101 GENERIC_READ, 101 GENERIC_READ,
102 FILE_SHARE_READ | FILE_SHARE_WRITE, 102 FILE_SHARE_READ | FILE_SHARE_WRITE,
103 NULL, 103 nullptr,
104 OPEN_EXISTING, 104 OPEN_EXISTING,
105 FILE_FLAG_SEQUENTIAL_SCAN, 105 FILE_FLAG_SEQUENTIAL_SCAN,
106 NULL)); 106 nullptr));
107 107
108 if (!file.IsValid()) { 108 if (!file.IsValid()) {
109 DWORD error = GetLastError(); 109 DWORD error = GetLastError();
110 PLOG(ERROR) << "Failed to open '" << filename.value() << "'"; 110 PLOG(ERROR) << "Failed to open '" << filename.value() << "'";
111 return HRESULT_FROM_WIN32(error); 111 return HRESULT_FROM_WIN32(error);
112 } 112 }
113 113
114 scoped_ptr<char[]> buffer(new char[kMaxConfigFileSize]); 114 scoped_ptr<char[]> buffer(new char[kMaxConfigFileSize]);
115 DWORD size = kMaxConfigFileSize; 115 DWORD size = kMaxConfigFileSize;
116 if (!::ReadFile(file.Get(), &buffer[0], size, &size, NULL)) { 116 if (!::ReadFile(file.Get(), &buffer[0], size, &size, nullptr)) {
117 DWORD error = GetLastError(); 117 DWORD error = GetLastError();
118 PLOG(ERROR) << "Failed to read '" << filename.value() << "'"; 118 PLOG(ERROR) << "Failed to read '" << filename.value() << "'";
119 return HRESULT_FROM_WIN32(error); 119 return HRESULT_FROM_WIN32(error);
120 } 120 }
121 121
122 // Parse the JSON configuration, expecting it to contain a dictionary. 122 // Parse the JSON configuration, expecting it to contain a dictionary.
123 std::string file_content(buffer.get(), size); 123 std::string file_content(buffer.get(), size);
124 scoped_ptr<base::Value> value( 124 scoped_ptr<base::Value> value(
125 base::JSONReader::Read(file_content, base::JSON_ALLOW_TRAILING_COMMAS)); 125 base::JSONReader::Read(file_content, base::JSON_ALLOW_TRAILING_COMMAS));
126 126
127 base::DictionaryValue* dictionary; 127 base::DictionaryValue* dictionary;
128 if (value.get() == NULL || !value->GetAsDictionary(&dictionary)) { 128 if (value.get() == nullptr || !value->GetAsDictionary(&dictionary)) {
129 LOG(ERROR) << "Failed to read '" << filename.value() << "'."; 129 LOG(ERROR) << "Failed to read '" << filename.value() << "'.";
130 return E_FAIL; 130 return E_FAIL;
131 } 131 }
132 132
133 value.release(); 133 value.release();
134 config_out->reset(dictionary); 134 config_out->reset(dictionary);
135 return S_OK; 135 return S_OK;
136 } 136 }
137 137
138 base::FilePath GetTempLocationFor(const base::FilePath& filename) { 138 base::FilePath GetTempLocationFor(const base::FilePath& filename) {
(...skipping 21 matching lines...) Expand all
160 160
161 // Create a temporary file and write configuration to it. 161 // Create a temporary file and write configuration to it.
162 base::FilePath tempname = GetTempLocationFor(filename); 162 base::FilePath tempname = GetTempLocationFor(filename);
163 base::win::ScopedHandle file( 163 base::win::ScopedHandle file(
164 CreateFileW(tempname.value().c_str(), 164 CreateFileW(tempname.value().c_str(),
165 GENERIC_WRITE, 165 GENERIC_WRITE,
166 0, 166 0,
167 &security_attributes, 167 &security_attributes,
168 CREATE_ALWAYS, 168 CREATE_ALWAYS,
169 FILE_FLAG_SEQUENTIAL_SCAN, 169 FILE_FLAG_SEQUENTIAL_SCAN,
170 NULL)); 170 nullptr));
171 171
172 if (!file.IsValid()) { 172 if (!file.IsValid()) {
173 DWORD error = GetLastError(); 173 DWORD error = GetLastError();
174 PLOG(ERROR) << "Failed to create '" << filename.value() << "'"; 174 PLOG(ERROR) << "Failed to create '" << filename.value() << "'";
175 return HRESULT_FROM_WIN32(error); 175 return HRESULT_FROM_WIN32(error);
176 } 176 }
177 177
178 DWORD written; 178 DWORD written;
179 if (!WriteFile(file.Get(), content, static_cast<DWORD>(length), &written, 179 if (!WriteFile(file.Get(), content, static_cast<DWORD>(length), &written,
180 NULL)) { 180 nullptr)) {
181 DWORD error = GetLastError(); 181 DWORD error = GetLastError();
182 PLOG(ERROR) << "Failed to write to '" << filename.value() << "'"; 182 PLOG(ERROR) << "Failed to write to '" << filename.value() << "'";
183 return HRESULT_FROM_WIN32(error); 183 return HRESULT_FROM_WIN32(error);
184 } 184 }
185 185
186 return S_OK; 186 return S_OK;
187 } 187 }
188 188
189 // Moves a config file from its temporary location to its permanent location. 189 // Moves a config file from its temporary location to its permanent location.
190 HRESULT MoveConfigFileFromTemp(const base::FilePath& filename) { 190 HRESULT MoveConfigFileFromTemp(const base::FilePath& filename) {
(...skipping 16 matching lines...) Expand all
207 HRESULT WriteConfig(const char* content, size_t length, HWND owner_window) { 207 HRESULT WriteConfig(const char* content, size_t length, HWND owner_window) {
208 if (length > kMaxConfigFileSize) { 208 if (length > kMaxConfigFileSize) {
209 return E_FAIL; 209 return E_FAIL;
210 } 210 }
211 211
212 // Extract the configuration data that the user will verify. 212 // Extract the configuration data that the user will verify.
213 scoped_ptr<base::Value> config_value(base::JSONReader::Read(content)); 213 scoped_ptr<base::Value> config_value(base::JSONReader::Read(content));
214 if (!config_value.get()) { 214 if (!config_value.get()) {
215 return E_FAIL; 215 return E_FAIL;
216 } 216 }
217 base::DictionaryValue* config_dict = NULL; 217 base::DictionaryValue* config_dict = nullptr;
218 if (!config_value->GetAsDictionary(&config_dict)) { 218 if (!config_value->GetAsDictionary(&config_dict)) {
219 return E_FAIL; 219 return E_FAIL;
220 } 220 }
221 std::string email; 221 std::string email;
222 if (!config_dict->GetString(kHostOwnerEmailConfigPath, &email)) { 222 if (!config_dict->GetString(kHostOwnerEmailConfigPath, &email)) {
223 if (!config_dict->GetString(kHostOwnerConfigPath, &email)) { 223 if (!config_dict->GetString(kHostOwnerConfigPath, &email)) {
224 if (!config_dict->GetString(kXmppLoginConfigPath, &email)) { 224 if (!config_dict->GetString(kXmppLoginConfigPath, &email)) {
225 return E_FAIL; 225 return E_FAIL;
226 } 226 }
227 } 227 }
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
287 hr = MoveConfigFileFromTemp(unprivileged_config_file_path); 287 hr = MoveConfigFileFromTemp(unprivileged_config_file_path);
288 if (FAILED(hr)) { 288 if (FAILED(hr)) {
289 return hr; 289 return hr;
290 } 290 }
291 291
292 return S_OK; 292 return S_OK;
293 } 293 }
294 294
295 } // namespace 295 } // namespace
296 296
297 ElevatedController::ElevatedController() : owner_window_(NULL) { 297 ElevatedController::ElevatedController() : owner_window_(nullptr) {
298 } 298 }
299 299
300 HRESULT ElevatedController::FinalConstruct() { 300 HRESULT ElevatedController::FinalConstruct() {
301 return S_OK; 301 return S_OK;
302 } 302 }
303 303
304 void ElevatedController::FinalRelease() { 304 void ElevatedController::FinalRelease() {
305 } 305 }
306 306
307 STDMETHODIMP ElevatedController::GetConfig(BSTR* config_out) { 307 STDMETHODIMP ElevatedController::GetConfig(BSTR* config_out) {
308 base::FilePath config_dir = remoting::GetConfigDir(); 308 base::FilePath config_dir = remoting::GetConfigDir();
309 309
310 // Read the unprivileged part of host configuration. 310 // Read the unprivileged part of host configuration.
311 scoped_ptr<base::DictionaryValue> config; 311 scoped_ptr<base::DictionaryValue> config;
312 HRESULT hr = ReadConfig(config_dir.Append(kUnprivilegedConfigFileName), 312 HRESULT hr = ReadConfig(config_dir.Append(kUnprivilegedConfigFileName),
313 &config); 313 &config);
314 if (FAILED(hr)) { 314 if (FAILED(hr)) {
315 return hr; 315 return hr;
316 } 316 }
317 317
318 // Convert the config back to a string and return it to the caller. 318 // Convert the config back to a string and return it to the caller.
319 std::string file_content; 319 std::string file_content;
320 base::JSONWriter::Write(config.get(), &file_content); 320 base::JSONWriter::Write(config.get(), &file_content);
321 321
322 *config_out = ::SysAllocString(base::UTF8ToUTF16(file_content).c_str()); 322 *config_out = ::SysAllocString(base::UTF8ToUTF16(file_content).c_str());
323 if (config_out == NULL) { 323 if (config_out == nullptr) {
324 return E_OUTOFMEMORY; 324 return E_OUTOFMEMORY;
325 } 325 }
326 326
327 return S_OK; 327 return S_OK;
328 } 328 }
329 329
330 STDMETHODIMP ElevatedController::GetVersion(BSTR* version_out) { 330 STDMETHODIMP ElevatedController::GetVersion(BSTR* version_out) {
331 // Report the product version number of the daemon controller binary as 331 // Report the product version number of the daemon controller binary as
332 // the host version. 332 // the host version.
333 HMODULE binary = base::GetModuleFromAddress( 333 HMODULE binary = base::GetModuleFromAddress(
334 reinterpret_cast<void*>(&ReadConfig)); 334 reinterpret_cast<void*>(&ReadConfig));
335 scoped_ptr<FileVersionInfo> version_info( 335 scoped_ptr<FileVersionInfo> version_info(
336 FileVersionInfo::CreateFileVersionInfoForModule(binary)); 336 FileVersionInfo::CreateFileVersionInfoForModule(binary));
337 337
338 base::string16 version; 338 base::string16 version;
339 if (version_info.get()) { 339 if (version_info.get()) {
340 version = version_info->product_version(); 340 version = version_info->product_version();
341 } 341 }
342 342
343 *version_out = ::SysAllocString(version.c_str()); 343 *version_out = ::SysAllocString(version.c_str());
344 if (version_out == NULL) { 344 if (version_out == nullptr) {
345 return E_OUTOFMEMORY; 345 return E_OUTOFMEMORY;
346 } 346 }
347 347
348 return S_OK; 348 return S_OK;
349 } 349 }
350 350
351 STDMETHODIMP ElevatedController::SetConfig(BSTR config) { 351 STDMETHODIMP ElevatedController::SetConfig(BSTR config) {
352 // Determine the config directory path and create it if necessary. 352 // Determine the config directory path and create it if necessary.
353 base::FilePath config_dir = remoting::GetConfigDir(); 353 base::FilePath config_dir = remoting::GetConfigDir();
354 if (!base::CreateDirectory(config_dir)) { 354 if (!base::CreateDirectory(config_dir)) {
(...skipping 16 matching lines...) Expand all
371 HRESULT hr = OpenService(&service); 371 HRESULT hr = OpenService(&service);
372 if (FAILED(hr)) { 372 if (FAILED(hr)) {
373 return hr; 373 return hr;
374 } 374 }
375 375
376 // Change the service start type to 'auto'. 376 // Change the service start type to 'auto'.
377 if (!::ChangeServiceConfigW(service.Get(), 377 if (!::ChangeServiceConfigW(service.Get(),
378 SERVICE_NO_CHANGE, 378 SERVICE_NO_CHANGE,
379 SERVICE_AUTO_START, 379 SERVICE_AUTO_START,
380 SERVICE_NO_CHANGE, 380 SERVICE_NO_CHANGE,
381 NULL, 381 nullptr,
382 NULL, 382 nullptr,
383 NULL, 383 nullptr,
384 NULL, 384 nullptr,
385 NULL, 385 nullptr,
386 NULL, 386 nullptr,
387 NULL)) { 387 nullptr)) {
388 DWORD error = GetLastError(); 388 DWORD error = GetLastError();
389 PLOG(ERROR) << "Failed to change the '" << kWindowsServiceName 389 PLOG(ERROR) << "Failed to change the '" << kWindowsServiceName
390 << "'service start type to 'auto'"; 390 << "'service start type to 'auto'";
391 return HRESULT_FROM_WIN32(error); 391 return HRESULT_FROM_WIN32(error);
392 } 392 }
393 393
394 // Start the service. 394 // Start the service.
395 if (!StartService(service.Get(), 0, NULL)) { 395 if (!StartService(service.Get(), 0, nullptr)) {
396 DWORD error = GetLastError(); 396 DWORD error = GetLastError();
397 if (error != ERROR_SERVICE_ALREADY_RUNNING) { 397 if (error != ERROR_SERVICE_ALREADY_RUNNING) {
398 PLOG(ERROR) << "Failed to start the '" << kWindowsServiceName 398 PLOG(ERROR) << "Failed to start the '" << kWindowsServiceName
399 << "'service"; 399 << "'service";
400 400
401 return HRESULT_FROM_WIN32(error); 401 return HRESULT_FROM_WIN32(error);
402 } 402 }
403 } 403 }
404 404
405 return S_OK; 405 return S_OK;
406 } 406 }
407 407
408 STDMETHODIMP ElevatedController::StopDaemon() { 408 STDMETHODIMP ElevatedController::StopDaemon() {
409 ScopedScHandle service; 409 ScopedScHandle service;
410 HRESULT hr = OpenService(&service); 410 HRESULT hr = OpenService(&service);
411 if (FAILED(hr)) { 411 if (FAILED(hr)) {
412 return hr; 412 return hr;
413 } 413 }
414 414
415 // Change the service start type to 'manual'. 415 // Change the service start type to 'manual'.
416 if (!::ChangeServiceConfigW(service.Get(), 416 if (!::ChangeServiceConfigW(service.Get(),
417 SERVICE_NO_CHANGE, 417 SERVICE_NO_CHANGE,
418 SERVICE_DEMAND_START, 418 SERVICE_DEMAND_START,
419 SERVICE_NO_CHANGE, 419 SERVICE_NO_CHANGE,
420 NULL, 420 nullptr,
421 NULL, 421 nullptr,
422 NULL, 422 nullptr,
423 NULL, 423 nullptr,
424 NULL, 424 nullptr,
425 NULL, 425 nullptr,
426 NULL)) { 426 nullptr)) {
427 DWORD error = GetLastError(); 427 DWORD error = GetLastError();
428 PLOG(ERROR) << "Failed to change the '" << kWindowsServiceName 428 PLOG(ERROR) << "Failed to change the '" << kWindowsServiceName
429 << "'service start type to 'manual'"; 429 << "'service start type to 'manual'";
430 return HRESULT_FROM_WIN32(error); 430 return HRESULT_FROM_WIN32(error);
431 } 431 }
432 432
433 // Stop the service. 433 // Stop the service.
434 SERVICE_STATUS status; 434 SERVICE_STATUS status;
435 if (!ControlService(service.Get(), SERVICE_CONTROL_STOP, &status)) { 435 if (!ControlService(service.Get(), SERVICE_CONTROL_STOP, &status)) {
436 DWORD error = GetLastError(); 436 DWORD error = GetLastError();
437 if (error != ERROR_SERVICE_NOT_ACTIVE) { 437 if (error != ERROR_SERVICE_NOT_ACTIVE) {
438 PLOG(ERROR) << "Failed to stop the '" << kWindowsServiceName 438 PLOG(ERROR) << "Failed to stop the '" << kWindowsServiceName
439 << "'service"; 439 << "'service";
440 return HRESULT_FROM_WIN32(error); 440 return HRESULT_FROM_WIN32(error);
441 } 441 }
442 } 442 }
443 443
444 return S_OK; 444 return S_OK;
445 } 445 }
446 446
447 STDMETHODIMP ElevatedController::UpdateConfig(BSTR config) { 447 STDMETHODIMP ElevatedController::UpdateConfig(BSTR config) {
448 // Parse the config. 448 // Parse the config.
449 std::string config_str = base::UTF16ToUTF8( 449 std::string config_str = base::UTF16ToUTF8(
450 base::string16(static_cast<base::char16*>(config), ::SysStringLen(config))); 450 base::string16(static_cast<base::char16*>(config), ::SysStringLen(config)));
451 scoped_ptr<base::Value> config_value(base::JSONReader::Read(config_str)); 451 scoped_ptr<base::Value> config_value(base::JSONReader::Read(config_str));
452 if (!config_value.get()) { 452 if (!config_value.get()) {
453 return E_FAIL; 453 return E_FAIL;
454 } 454 }
455 base::DictionaryValue* config_dict = NULL; 455 base::DictionaryValue* config_dict = nullptr;
456 if (!config_value->GetAsDictionary(&config_dict)) { 456 if (!config_value->GetAsDictionary(&config_dict)) {
457 return E_FAIL; 457 return E_FAIL;
458 } 458 }
459 // Check for bad keys. 459 // Check for bad keys.
460 for (int i = 0; i < arraysize(kReadonlyKeys); ++i) { 460 for (int i = 0; i < arraysize(kReadonlyKeys); ++i) {
461 if (config_dict->HasKey(kReadonlyKeys[i])) { 461 if (config_dict->HasKey(kReadonlyKeys[i])) {
462 return HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED); 462 return HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED);
463 } 463 }
464 } 464 }
465 // Get the old config. 465 // Get the old config.
(...skipping 30 matching lines...) Expand all
496 return S_OK; 496 return S_OK;
497 } else { 497 } else {
498 return E_FAIL; 498 return E_FAIL;
499 } 499 }
500 } 500 }
501 501
502 HRESULT ElevatedController::OpenService(ScopedScHandle* service_out) { 502 HRESULT ElevatedController::OpenService(ScopedScHandle* service_out) {
503 DWORD error; 503 DWORD error;
504 504
505 ScopedScHandle scmanager( 505 ScopedScHandle scmanager(
506 ::OpenSCManagerW(NULL, SERVICES_ACTIVE_DATABASE, 506 ::OpenSCManagerW(nullptr, SERVICES_ACTIVE_DATABASE,
507 SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE)); 507 SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE));
508 if (!scmanager.IsValid()) { 508 if (!scmanager.IsValid()) {
509 error = GetLastError(); 509 error = GetLastError();
510 PLOG(ERROR) << "Failed to connect to the service control manager"; 510 PLOG(ERROR) << "Failed to connect to the service control manager";
511 511
512 return HRESULT_FROM_WIN32(error); 512 return HRESULT_FROM_WIN32(error);
513 } 513 }
514 514
515 DWORD desired_access = SERVICE_CHANGE_CONFIG | SERVICE_QUERY_STATUS | 515 DWORD desired_access = SERVICE_CHANGE_CONFIG | SERVICE_QUERY_STATUS |
516 SERVICE_START | SERVICE_STOP; 516 SERVICE_START | SERVICE_STOP;
517 ScopedScHandle service( 517 ScopedScHandle service(
518 ::OpenServiceW(scmanager.Get(), kWindowsServiceName, desired_access)); 518 ::OpenServiceW(scmanager.Get(), kWindowsServiceName, desired_access));
519 if (!service.IsValid()) { 519 if (!service.IsValid()) {
520 error = GetLastError(); 520 error = GetLastError();
521 PLOG(ERROR) << "Failed to open to the '" << kWindowsServiceName 521 PLOG(ERROR) << "Failed to open to the '" << kWindowsServiceName
522 << "' service"; 522 << "' service";
523 523
524 return HRESULT_FROM_WIN32(error); 524 return HRESULT_FROM_WIN32(error);
525 } 525 }
526 526
527 service_out->Set(service.Take()); 527 service_out->Set(service.Take());
528 return S_OK; 528 return S_OK;
529 } 529 }
530 530
531 } // namespace remoting 531 } // namespace remoting
OLDNEW
« no previous file with comments | « remoting/host/win/com_security.cc ('k') | remoting/host/win/entry_point.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698