Chromium Code Reviews| OLD | NEW |
|---|---|
| 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/plugin/daemon_controller.h" | 5 #include "remoting/host/plugin/daemon_controller.h" |
| 6 | 6 |
| 7 #include <objbase.h> | |
| 8 | |
| 7 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
| 10 #include "base/bind.h" | |
| 8 #include "base/compiler_specific.h" | 11 #include "base/compiler_specific.h" |
| 12 #include "base/file_path.h" | |
| 13 #include "base/file_util.h" | |
| 14 #include "base/json/json_reader.h" | |
| 15 #include "base/json/json_writer.h" | |
| 9 #include "base/logging.h" | 16 #include "base/logging.h" |
| 17 #include "base/synchronization/lock.h" | |
| 18 #include "base/threading/thread.h" | |
| 19 #include "base/utf_string_conversions.h" | |
| 10 #include "base/values.h" | 20 #include "base/values.h" |
| 21 #include "remoting/base/scoped_sc_handle_win.h" | |
| 22 #include "remoting/host/branding.h" | |
| 23 | |
| 24 // MIDL-generated declarations and definitions. | |
| 25 #include "elevated_controller.h" | |
| 26 #include "elevated_controller_i.c" | |
| 11 | 27 |
| 12 namespace remoting { | 28 namespace remoting { |
| 13 | 29 |
| 14 namespace { | 30 namespace { |
| 15 | 31 |
| 32 // The COM elevation moniker for the elevated controller. | |
|
Wez
2012/03/30 22:11:01
nit: Consider adding a sentence to explain what th
alexeypa (please no reviews)
2012/03/30 23:47:09
This is typical RTFM. I.e. one sentence is too lit
| |
| 33 const char kElevationMoniker[] = "Elevation:Administrator!new:" | |
| 34 "{430a9403-8176-4733-afdc-0b325a8fda84}"; | |
| 35 | |
| 36 // Name of the worker thread. | |
|
Wez
2012/03/30 22:11:01
nit: Similarly, what worker thread? What does the
alexeypa (please no reviews)
2012/03/30 23:47:09
Done.
| |
| 37 const char kWorkerThreadName[] = "Daemon Controller thread"; | |
| 38 | |
| 39 // A simple wrapper around base::Thread making sure that COM is initialized on | |
| 40 // the owner thread. | |
|
Wez
2012/03/30 22:11:01
nit: I think you mean "A base::Thread implementati
alexeypa (please no reviews)
2012/03/30 23:47:09
Done.
| |
| 41 class ComThread : public base::Thread { | |
| 42 public: | |
| 43 explicit ComThread(const char* name); | |
| 44 | |
| 45 // Activates an elevated instance of elevated controller and returns | |
|
Wez
2012/03/30 22:11:01
nit: ... elevated instance of the controller ...
alexeypa (please no reviews)
2012/03/30 23:47:09
Done.
| |
| 46 // the pointer to the control interface in |control_out|. This routine keeps | |
|
Wez
2012/03/30 22:11:01
nit: The routine can't keep ownership; do you mean
alexeypa (please no reviews)
2012/03/30 23:47:09
Done.
| |
| 47 // the ownership of the pointer so the caller should not call call AddRef() or | |
| 48 // Release(). | |
| 49 HRESULT ActivateElevatedController(IDaemonControl** control_out); | |
| 50 | |
| 51 protected: | |
| 52 virtual void Init() OVERRIDE; | |
| 53 virtual void CleanUp() OVERRIDE; | |
| 54 | |
| 55 IDaemonControl* control_; | |
|
Wez
2012/03/30 22:11:01
nit: Perhaps we should have a ScopedIPtr... ;)
alexeypa (please no reviews)
2012/03/30 23:47:09
It is not going to help in this case.
| |
| 56 | |
| 57 DISALLOW_COPY_AND_ASSIGN(ComThread); | |
| 58 }; | |
| 59 | |
| 16 class DaemonControllerWin : public remoting::DaemonController { | 60 class DaemonControllerWin : public remoting::DaemonController { |
| 17 public: | 61 public: |
| 18 DaemonControllerWin(); | 62 DaemonControllerWin(); |
| 63 virtual ~DaemonControllerWin(); | |
| 19 | 64 |
| 20 virtual State GetState() OVERRIDE; | 65 virtual State GetState() OVERRIDE; |
| 21 virtual void GetConfig(const GetConfigCallback& callback) OVERRIDE; | 66 virtual void GetConfig(const GetConfigCallback& callback) OVERRIDE; |
| 22 virtual void SetConfigAndStart( | 67 virtual void SetConfigAndStart( |
| 23 scoped_ptr<base::DictionaryValue> config) OVERRIDE; | 68 scoped_ptr<base::DictionaryValue> config) OVERRIDE; |
| 24 virtual void SetPin(const std::string& pin) OVERRIDE; | 69 virtual void SetPin(const std::string& pin) OVERRIDE; |
| 25 virtual void Stop() OVERRIDE; | 70 virtual void Stop() OVERRIDE; |
| 26 | 71 |
| 27 private: | 72 private: |
| 73 // Activates an elevated instance of elevated controller and returns | |
|
Wez
2012/03/30 22:11:01
nit: See above.
alexeypa (please no reviews)
2012/03/30 23:47:09
Stale code. Removed.
| |
| 74 // the pointer to the control interface in |control_out|. | |
| 75 HRESULT ActivateElevatedController(IDaemonControl** control_out); | |
| 76 | |
| 77 // Opens the controlled service handle. | |
|
Wez
2012/03/30 22:11:01
nit: What is the controlled service handle? You m
alexeypa (please no reviews)
2012/03/30 23:47:09
Reworded.
| |
| 78 DWORD OpenService(ScopedScHandle* service_out); | |
| 79 | |
| 80 // Worker functions called in the context of the worker thread. | |
|
Wez
2012/03/30 22:11:01
nit: Double use of the term "worker" makes this co
alexeypa (please no reviews)
2012/03/30 23:47:09
Done.
| |
| 81 void DoGetConfig(const GetConfigCallback& callback); | |
| 82 void DoSetConfigAndStart(scoped_ptr<base::DictionaryValue> config); | |
| 83 void DoStop(); | |
| 84 | |
| 85 // Converts SERVICE_XXX contants representing the service state (i.e. | |
| 86 // SERVICE_RUNNING, SERVICE_STOPPED) to the daemon state. | |
|
Wez
2012/03/30 22:11:01
nit: "Converts a Windows service status code to a
alexeypa (please no reviews)
2012/03/30 23:47:09
Done.
| |
| 87 static State ConvertToDaemonState(DWORD service_state); | |
| 88 | |
| 89 // Service status change notification callback. | |
|
Wez
2012/03/30 22:11:01
nit: Suggest rewording e.g. "Status change callbac
alexeypa (please no reviews)
2012/03/30 23:47:09
Stale code.
| |
| 90 static VOID CALLBACK OnServiceStatusChange(PVOID context); | |
| 91 | |
| 92 // The worker thread used for servicing long running operations. | |
| 93 ComThread worker_thread_; | |
| 94 | |
| 95 // The lock protecting access to all data members below. | |
| 96 base::Lock lock_; | |
| 97 | |
| 98 // The error occurred during the last transition. | |
| 99 HRESULT last_error_; | |
| 100 | |
| 101 // Cached daemon state. | |
|
Wez
2012/03/30 22:11:01
nit: This is the state as of the most recent statu
alexeypa (please no reviews)
2012/03/30 23:47:09
No, it is not. Reworded.
| |
| 102 State state_; | |
| 103 | |
| 104 // The state that should never be reported to JS unless there is an error. | |
| 105 // For instance, when Start() is called, the state of the service doesn't | |
| 106 // switch to "starting" immediately. This could lead to JS interpreting | |
| 107 // "stopped" as a failure to start the service. | |
|
Wez
2012/03/30 22:11:01
This comment is very confusing, as is the name |fo
alexeypa (please no reviews)
2012/03/30 23:47:09
forbidden_state_ is a hack and it is confusing bec
| |
| 108 // TODO(alexeypa): remove this variable once JS interafce supports callbacks. | |
|
Wez
2012/03/30 22:11:01
typo: interafce
alexeypa (please no reviews)
2012/03/30 23:47:09
Done.
| |
| 109 State forbidden_state_; | |
| 110 | |
| 28 DISALLOW_COPY_AND_ASSIGN(DaemonControllerWin); | 111 DISALLOW_COPY_AND_ASSIGN(DaemonControllerWin); |
| 29 }; | 112 }; |
| 30 | 113 |
| 31 DaemonControllerWin::DaemonControllerWin() { | 114 ComThread::ComThread(const char* name) : base::Thread(name), control_(NULL) { |
| 32 } | 115 } |
| 33 | 116 |
| 34 DaemonController::State DaemonControllerWin::GetState() { | 117 void ComThread::Init() { |
| 35 return DaemonController::STATE_NOT_IMPLEMENTED; | 118 CoInitialize(NULL); |
| 119 } | |
| 120 | |
| 121 void ComThread::CleanUp() { | |
| 122 if (control_ != NULL) { | |
| 123 control_->Release(); | |
| 124 } | |
| 125 | |
|
Wez
2012/03/30 22:11:01
nit: Personally I'd lose the {} on the if, and thi
alexeypa (please no reviews)
2012/03/30 23:47:09
Done.
| |
| 126 CoUninitialize(); | |
| 127 } | |
| 128 | |
| 129 HRESULT ComThread::ActivateElevatedController( | |
| 130 IDaemonControl** control_out) { | |
| 131 | |
|
Wez
2012/03/30 22:11:01
nit: No need for blank line.
alexeypa (please no reviews)
2012/03/30 23:47:09
I replaced it with a comment.
| |
| 132 if (control_ == NULL) { | |
| 133 BIND_OPTS3 bind_options; | |
| 134 memset(&bind_options, 0, sizeof(bind_options)); | |
| 135 bind_options.cbStruct = sizeof(bind_options); | |
| 136 bind_options.hwnd = NULL; | |
| 137 bind_options.dwClassContext = CLSCTX_LOCAL_SERVER; | |
| 138 | |
| 139 IDaemonControl* control = NULL; | |
|
Wez
2012/03/30 22:11:01
This doesn't seem to be used?
alexeypa (please no reviews)
2012/03/30 23:47:09
Done.
| |
| 140 HRESULT hr = ::CoGetObject(ASCIIToUTF16(kElevationMoniker).c_str(), | |
| 141 &bind_options, | |
| 142 IID_IDaemonControl, | |
| 143 reinterpret_cast<void**>(&control_)); | |
| 144 if (FAILED(hr)) { | |
| 145 LOG(ERROR) << "Failed to create the elevated controller (error: 0x" | |
| 146 << std::hex << hr << std::dec << ")."; | |
| 147 return hr; | |
| 148 } | |
| 149 } | |
| 150 | |
| 151 *control_out = control_; | |
| 152 return S_OK; | |
| 153 } | |
| 154 | |
| 155 DaemonControllerWin::DaemonControllerWin() | |
| 156 : last_error_(S_OK), | |
| 157 state_(STATE_UNKNOWN), | |
| 158 forbidden_state_(STATE_UNKNOWN), | |
| 159 worker_thread_(kWorkerThreadName) { | |
| 160 // N.B. The UI message loop is required for the single threaded COM apartment. | |
|
Wez
2012/03/30 22:11:01
typo: The UI ... is required for ... -> COM must
alexeypa (please no reviews)
2012/03/30 23:47:09
Done.
| |
| 161 base::Thread::Options thread_options(MessageLoop::TYPE_UI, 0); | |
| 162 if (!worker_thread_.StartWithOptions(thread_options)) { | |
|
Wez
2012/03/30 22:11:01
Since ComThread doesn't make sense unless started
alexeypa (please no reviews)
2012/03/30 23:47:09
Done.
| |
| 163 // N.B. StartWithOptions() does not report the error code returned by | |
| 164 // the system. | |
| 165 last_error_ = E_FAIL; | |
| 166 } | |
| 167 } | |
| 168 | |
| 169 DaemonControllerWin::~DaemonControllerWin() { | |
| 170 worker_thread_.Stop(); | |
| 171 } | |
| 172 | |
| 173 remoting::DaemonController::State DaemonControllerWin::GetState() { | |
| 174 // TODO(alexeypa): convert polling to async callbacks once there is a thread | |
| 175 // that can receive APC callbacks. | |
|
Wez
2012/03/30 22:11:01
nit: Suggest "Make the thread alertable, so we can
alexeypa (please no reviews)
2012/03/30 23:47:09
Done.
| |
| 176 ScopedScHandle service; | |
| 177 DWORD error = OpenService(&service); | |
| 178 | |
| 179 if (error == ERROR_SUCCESS) { | |
| 180 SERVICE_STATUS status; | |
| 181 if (::QueryServiceStatus(service, &status)) { | |
| 182 State new_state = ConvertToDaemonState(status.dwCurrentState); | |
| 183 | |
| 184 base::AutoLock lock(lock_); | |
| 185 // TODO(alexeypa): remove |forbidden_state_| hack once JS interface | |
| 186 // supports callbacks. | |
|
Wez
2012/03/30 22:11:01
nit: remove ... -> Remove ...
alexeypa (please no reviews)
2012/03/30 23:47:09
Done.
| |
| 187 if (forbidden_state_ != new_state || FAILED(last_error_)) { | |
| 188 state_ = new_state; | |
| 189 } | |
| 190 | |
| 191 // TODO(alexeypa): remove this hack once JS nicely reports errors. | |
|
Wez
2012/03/30 22:11:01
nit: It's not immediately obvious what the hack is
alexeypa (please no reviews)
2012/03/30 23:47:09
I'm sorry. It is there. Look more closely. :-)
| |
| 192 if (FAILED(last_error_)) { | |
| 193 state_ = STATE_START_FAILED; | |
| 194 } | |
| 195 | |
| 196 return state_; | |
| 197 } else { | |
| 198 error = GetLastError(); | |
| 199 LOG_GETLASTERROR(ERROR) | |
| 200 << "Failed to query the state of the '" << kWindowsServiceName | |
| 201 << "' service"; | |
| 202 } | |
| 203 } | |
| 204 | |
| 205 base::AutoLock lock(lock_); | |
| 206 if (error == ERROR_SERVICE_DOES_NOT_EXIST) { | |
| 207 state_ = STATE_NOT_IMPLEMENTED; | |
| 208 } else { | |
| 209 last_error_ = HRESULT_FROM_WIN32(error); | |
| 210 state_ = STATE_UNKNOWN; | |
| 211 } | |
| 212 | |
| 213 return state_; | |
| 36 } | 214 } |
| 37 | 215 |
| 38 void DaemonControllerWin::GetConfig(const GetConfigCallback& callback) { | 216 void DaemonControllerWin::GetConfig(const GetConfigCallback& callback) { |
| 39 NOTIMPLEMENTED(); | 217 worker_thread_.message_loop_proxy()->PostTask( |
| 218 FROM_HERE, | |
| 219 base::Bind(&DaemonControllerWin::DoGetConfig, | |
| 220 base::Unretained(this), callback)); | |
| 40 } | 221 } |
| 41 | 222 |
| 42 void DaemonControllerWin::SetConfigAndStart( | 223 void DaemonControllerWin::SetConfigAndStart( |
| 43 scoped_ptr<base::DictionaryValue> config) { | 224 scoped_ptr<base::DictionaryValue> config) { |
| 44 NOTIMPLEMENTED(); | 225 base::AutoLock lock(lock_); |
| 226 | |
| 227 // TODO(alexeypa): implement on-demand installation. | |
|
Wez
2012/03/30 22:11:01
typo: implement ... -> Implement ...
Wez
2012/03/30 22:11:01
nit: We generally prefer to create TODOs with an a
alexeypa (please no reviews)
2012/03/30 23:47:09
Done.
alexeypa (please no reviews)
2012/03/30 23:47:09
While being a good practice (I presume) I haven't
| |
| 228 if (state_ == STATE_STOPPED) { | |
| 229 last_error_ = S_OK; | |
| 230 forbidden_state_ = STATE_STOPPED; | |
| 231 state_ = STATE_STARTING; | |
| 232 worker_thread_.message_loop_proxy()->PostTask( | |
| 233 FROM_HERE, | |
| 234 base::Bind(&DaemonControllerWin::DoSetConfigAndStart, | |
| 235 base::Unretained(this), base::Passed(&config))); | |
| 236 } | |
| 45 } | 237 } |
| 46 | 238 |
| 47 void DaemonControllerWin::SetPin(const std::string& pin) { | 239 void DaemonControllerWin::SetPin(const std::string& pin) { |
| 48 NOTIMPLEMENTED(); | 240 NOTIMPLEMENTED(); |
| 49 } | 241 } |
| 50 | 242 |
| 51 void DaemonControllerWin::Stop() { | 243 void DaemonControllerWin::Stop() { |
| 52 NOTIMPLEMENTED(); | 244 base::AutoLock lock(lock_); |
| 245 | |
| 246 if (state_ == STATE_STARTING || | |
| 247 state_ == STATE_STARTED || | |
| 248 state_ == STATE_STOPPING) { | |
|
Wez
2012/03/30 22:11:01
These are cached states; isn't there a risk that s
alexeypa (please no reviews)
2012/03/30 23:47:09
There is no danger. The state is inherently out-on
| |
| 249 | |
|
Wez
2012/03/30 22:11:01
nit: Errant blank line.
alexeypa (please no reviews)
2012/03/30 23:47:09
Done.
| |
| 250 last_error_ = S_OK; | |
| 251 forbidden_state_ = STATE_STARTED; | |
| 252 state_ = STATE_STOPPING; | |
| 253 worker_thread_.message_loop_proxy()->PostTask( | |
| 254 FROM_HERE, | |
| 255 base::Bind(&DaemonControllerWin::DoStop, base::Unretained(this))); | |
| 256 } | |
| 257 } | |
| 258 | |
| 259 DWORD DaemonControllerWin::OpenService(ScopedScHandle* service_out) { | |
|
Wez
2012/03/30 22:11:01
nit: This function looks oddly familiar from Eleva
alexeypa (please no reviews)
2012/03/30 23:47:09
There is little benefit in sharing the same implem
| |
| 260 // Open the service and query its current state. | |
| 261 ScopedScHandle scmanager( | |
| 262 ::OpenSCManagerW(NULL, SERVICES_ACTIVE_DATABASE, | |
| 263 SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE)); | |
| 264 if (!scmanager.IsValid()) { | |
| 265 DWORD error = GetLastError(); | |
| 266 LOG_GETLASTERROR(ERROR) | |
| 267 << "Failed to connect to the service control manager"; | |
| 268 return error; | |
| 269 } | |
| 270 | |
| 271 ScopedScHandle service( | |
| 272 ::OpenServiceW(scmanager, ASCIIToUTF16(kWindowsServiceName).c_str(), | |
| 273 SERVICE_QUERY_STATUS)); | |
| 274 if (!service.IsValid()) { | |
| 275 DWORD error = GetLastError(); | |
| 276 if (error != ERROR_SERVICE_DOES_NOT_EXIST) { | |
| 277 LOG_GETLASTERROR(ERROR) | |
| 278 << "Failed to open to the '" << kWindowsServiceName << "' service"; | |
| 279 } | |
| 280 return error; | |
| 281 } | |
| 282 | |
| 283 service_out->Set(service.Take()); | |
| 284 return ERROR_SUCCESS; | |
| 285 } | |
| 286 | |
| 287 void DaemonControllerWin::DoGetConfig(const GetConfigCallback& callback) { | |
| 288 IDaemonControl* control = NULL; | |
| 289 HRESULT hr = worker_thread_.ActivateElevatedController(&control); | |
| 290 if (FAILED(hr)) { | |
| 291 callback.Run(scoped_ptr<base::DictionaryValue>()); | |
| 292 return; | |
| 293 } | |
| 294 | |
| 295 // Get the host configuration. | |
| 296 BSTR host_config = NULL; | |
|
Wez
2012/03/30 22:11:01
Is there no managed container for BSTR?
alexeypa (please no reviews)
2012/03/30 23:47:09
There is. It drags ATL. We don't want it here.
| |
| 297 hr = control->GetConfig(&host_config); | |
| 298 if (FAILED(hr)) { | |
| 299 callback.Run(scoped_ptr<base::DictionaryValue>()); | |
| 300 return; | |
| 301 } | |
| 302 | |
| 303 string16 file_content(static_cast<char16*>(host_config), | |
| 304 ::SysStringLen(host_config)); | |
| 305 SysFreeString(host_config); | |
| 306 | |
| 307 // Parse the string into a dictionary. | |
| 308 scoped_ptr<base::Value> config( | |
| 309 base::JSONReader::Read(UTF16ToUTF8(file_content), true)); | |
| 310 | |
| 311 base::DictionaryValue* dictionary; | |
| 312 if (config.get() == NULL || !config->GetAsDictionary(&dictionary)) { | |
| 313 callback.Run(scoped_ptr<base::DictionaryValue>()); | |
| 314 return; | |
| 315 } | |
| 316 | |
| 317 config.release(); | |
| 318 callback.Run(scoped_ptr<base::DictionaryValue>(dictionary)); | |
|
Wez
2012/03/30 22:11:01
Yup. Still gross ... :P
| |
| 319 } | |
| 320 | |
| 321 void DaemonControllerWin::DoSetConfigAndStart( | |
| 322 scoped_ptr<base::DictionaryValue> config) { | |
| 323 | |
|
Wez
2012/03/30 22:11:01
nit: Errant blank line.
alexeypa (please no reviews)
2012/03/30 23:47:09
Done.
| |
| 324 IDaemonControl* control = NULL; | |
| 325 HRESULT hr = worker_thread_.ActivateElevatedController(&control); | |
| 326 if (FAILED(hr)) { | |
| 327 base::AutoLock lock(lock_); | |
| 328 last_error_ = hr; | |
|
Wez
2012/03/30 22:11:01
Why do we lock when setting |last_error_|? Surely
alexeypa (please no reviews)
2012/03/30 23:47:09
Race is fine. Corruption (state_ is not synched wi
| |
| 329 return; | |
| 330 } | |
| 331 | |
| 332 // Set the configuration file | |
|
Wez
2012/03/30 22:11:01
Suggest "Store the configuration."
alexeypa (please no reviews)
2012/03/30 23:47:09
Done.
| |
| 333 std::string file_content; | |
| 334 base::JSONWriter::Write(config.get(), &file_content); | |
| 335 | |
| 336 BSTR host_config = ::SysAllocString(UTF8ToUTF16(file_content).c_str()); | |
| 337 if (host_config == NULL) { | |
| 338 base::AutoLock lock(lock_); | |
| 339 last_error_ = E_OUTOFMEMORY; | |
| 340 return; | |
| 341 } | |
| 342 | |
| 343 hr = control->SetConfig(host_config); | |
| 344 ::SysFreeString(host_config); | |
| 345 | |
|
Wez
2012/03/30 22:11:01
nit: No need for blank line.
alexeypa (please no reviews)
2012/03/30 23:47:09
Done.
| |
| 346 if (FAILED(hr)) { | |
| 347 base::AutoLock lock(lock_); | |
| 348 last_error_ = hr; | |
| 349 return; | |
| 350 } | |
| 351 | |
| 352 // Start daemon. | |
| 353 hr = control->StartDaemon(); | |
| 354 | |
|
Wez
2012/03/30 22:11:01
nit: No need for blank line.
alexeypa (please no reviews)
2012/03/30 23:47:09
Done.
| |
| 355 if (FAILED(hr)) { | |
| 356 base::AutoLock lock(lock_); | |
| 357 last_error_ = hr; | |
| 358 } | |
| 359 } | |
| 360 | |
| 361 void DaemonControllerWin::DoStop() { | |
| 362 IDaemonControl* control = NULL; | |
| 363 HRESULT hr = worker_thread_.ActivateElevatedController(&control); | |
| 364 if (FAILED(hr)) { | |
| 365 base::AutoLock lock(lock_); | |
| 366 last_error_ = hr; | |
| 367 return; | |
| 368 } | |
| 369 | |
| 370 hr = control->StopDaemon(); | |
| 371 | |
|
Wez
2012/03/30 22:11:01
nit: Blank line.
alexeypa (please no reviews)
2012/03/30 23:47:09
Done.
| |
| 372 if (FAILED(hr)) { | |
| 373 base::AutoLock lock(lock_); | |
| 374 last_error_ = hr; | |
| 375 } | |
| 376 } | |
| 377 | |
| 378 // static | |
| 379 remoting::DaemonController::State DaemonControllerWin::ConvertToDaemonState( | |
| 380 DWORD service_state) { | |
| 381 | |
|
Wez
2012/03/30 22:11:01
nit: Blank line.
alexeypa (please no reviews)
2012/03/30 23:47:09
Done.
| |
| 382 switch (service_state) { | |
| 383 case SERVICE_RUNNING: | |
| 384 return STATE_STARTED; | |
| 385 | |
|
Wez
2012/03/30 22:11:01
nit: No need for these blank lines.
alexeypa (please no reviews)
2012/03/30 23:47:09
My eyes hurt. It is unreadable.
| |
| 386 case SERVICE_CONTINUE_PENDING: | |
| 387 case SERVICE_START_PENDING: | |
| 388 return STATE_STARTING; | |
| 389 break; | |
|
Wez
2012/03/30 22:11:01
nit: Nor for this break, or the ones below.
alexeypa (please no reviews)
2012/03/30 23:47:09
See above.
| |
| 390 | |
| 391 case SERVICE_PAUSE_PENDING: | |
| 392 case SERVICE_STOP_PENDING: | |
| 393 return STATE_STOPPING; | |
| 394 break; | |
| 395 | |
| 396 case SERVICE_PAUSED: | |
| 397 case SERVICE_STOPPED: | |
| 398 return STATE_STOPPED; | |
| 399 break; | |
| 400 | |
| 401 default: | |
| 402 NOTREACHED(); | |
| 403 return STATE_UNKNOWN; | |
| 404 } | |
| 53 } | 405 } |
| 54 | 406 |
| 55 } // namespace | 407 } // namespace |
| 56 | 408 |
| 57 DaemonController* remoting::DaemonController::Create() { | 409 DaemonController* remoting::DaemonController::Create() { |
| 58 return new DaemonControllerWin(); | 410 return new DaemonControllerWin(); |
| 59 } | 411 } |
| 60 | 412 |
| 61 } // namespace remoting | 413 } // namespace remoting |
| OLD | NEW |