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

Side by Side Diff: cloud_print/service/win/cloud_print_service.cc

Issue 10377080: Switched to chromium command line parsing code. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 7 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 | Annotate | Revision Log
« no previous file with comments | « cloud_print/service/win/cloud_print_service.h ('k') | cloud_print/service/win/service.gyp » ('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 "cloud_print/service/win/cloud_print_service.h" 5 #include "cloud_print/service/win/cloud_print_service.h"
6 6
7 #include <iomanip>
8 #include <iostream>
9
10 #include "base/at_exit.h"
11 #include "base/command_line.h"
12 #include "base/file_path.h"
13 #include "base/path_service.h"
7 #include "base/win/scoped_handle.h" 14 #include "base/win/scoped_handle.h"
8 #include "cloud_print/service/win/resource.h" 15 #include "cloud_print/service/win/resource.h"
9 16
17 namespace {
18
19 const char kInstallSwitch[] = "install";
20 const char kUninstallSwitch[] = "uninstall";
21 const char kStartSwitch[] = "start";
22 const char kStopSwitch[] = "stop";
23
24 const char kUserDataDirSwitch[] = "user-data-dir";
25 const char kQuietSwitch[] = "quiet";
26
10 // The traits class for Windows Service. 27 // The traits class for Windows Service.
11 class ServiceHandleTraits { 28 class ServiceHandleTraits {
12 public: 29 public:
13 typedef SC_HANDLE Handle; 30 typedef SC_HANDLE Handle;
14 31
15 // Closes the handle. 32 // Closes the handle.
16 static bool CloseHandle(Handle handle) { 33 static bool CloseHandle(Handle handle) {
17 return ::CloseServiceHandle(handle) != FALSE; 34 return ::CloseServiceHandle(handle) != FALSE;
18 } 35 }
19 36
(...skipping 12 matching lines...) Expand all
32 typedef base::win::GenericScopedHandle<ServiceHandleTraits> ServiceHandle; 49 typedef base::win::GenericScopedHandle<ServiceHandleTraits> ServiceHandle;
33 50
34 HRESULT HResultFromLastError() { 51 HRESULT HResultFromLastError() {
35 HRESULT hr = HRESULT_FROM_WIN32(GetLastError()); 52 HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
36 // Something already failed if function called. 53 // Something already failed if function called.
37 if (SUCCEEDED(hr)) 54 if (SUCCEEDED(hr))
38 hr = E_FAIL; 55 hr = E_FAIL;
39 return hr; 56 return hr;
40 } 57 }
41 58
59 void InvalidUsage() {
60 FilePath service_path;
61 CHECK(PathService::Get(base::FILE_EXE, &service_path));
62
63 std::cerr << "Usage: ";
gene 2012/05/10 22:11:45 cout?
Vitaly Buka (NO REVIEWS) 2012/05/10 22:49:12 Done.
64 std::cerr << service_path.BaseName().value();
65 std::cerr << " [";
66 std::cerr << "[";
67 std::cerr << "[";
68 std::cerr << " -" << kInstallSwitch;
69 std::cerr << " -" << kUserDataDirSwitch << "=DIRECTORY";
70 std::cerr << " [ -" << kQuietSwitch << " ]";
71 std::cerr << "]";
72 std::cerr << "]";
73 std::cerr << " | -" << kUninstallSwitch;
74 std::cerr << " | -" << kStartSwitch;
75 std::cerr << " | -" << kStopSwitch;
76 std::cerr << " ]\n";
77 std::cerr << "Manages cloud print service.\n\n";
78
79 static const char* kSwitchHelp[] = {
80 kInstallSwitch,
81 "Installs cloud print as windows service.",
82 kUserDataDirSwitch,
83 "User data directory with \"Service State\" file.",
84 kQuietSwitch,
85 "Fails without questions if something wrong.",
86 kUninstallSwitch,
87 "Uninstalls windows service.",
88 kStartSwitch,
89 "Starts windows service. May be combined with installation.",
90 kStopSwitch,
91 "Stops windows service.",
92 };
93
94 for (size_t i = 0; i < arraysize(kSwitchHelp) / 2; ++i) {
gene 2012/05/10 22:11:45 change this to not use i*2+1
Vitaly Buka (NO REVIEWS) 2012/05/10 22:49:12 Done.
95 std::cerr << std::setiosflags(std::ios::left);
96 std::cerr << " -" << std::setw(15) << kSwitchHelp[i * 2];
97 std::cerr << kSwitchHelp[i * 2 + 1] << "\n";
98 }
99 std::cerr << "\n";
100 }
101
102 } // namespace
103
42 class CloudPrintServiceModule 104 class CloudPrintServiceModule
43 : public ATL::CAtlServiceModuleT<CloudPrintServiceModule, IDS_SERVICENAME> { 105 : public ATL::CAtlServiceModuleT<CloudPrintServiceModule, IDS_SERVICENAME> {
44 public: 106 public:
45 typedef ATL::CAtlServiceModuleT<CloudPrintServiceModule, 107 typedef ATL::CAtlServiceModuleT<CloudPrintServiceModule,
46 IDS_SERVICENAME> Base; 108 IDS_SERVICENAME> Base;
47 109
48 DECLARE_REGISTRY_APPID_RESOURCEID(IDR_CLOUDPRINTSERVICE, 110 DECLARE_REGISTRY_APPID_RESOURCEID(IDR_CLOUDPRINTSERVICE,
49 "{8013FB7C-2E3E-4992-B8BD-05C0C4AB0627}") 111 "{8013FB7C-2E3E-4992-B8BD-05C0C4AB0627}")
50 112
51 HRESULT InitializeSecurity() { 113 HRESULT InitializeSecurity() {
52 // TODO(gene): Check if we need to call CoInitializeSecurity and provide 114 // TODO(gene): Check if we need to call CoInitializeSecurity and provide
53 // the appropriate security settings for service. 115 // the appropriate security settings for service.
54 return S_OK; 116 return S_OK;
55 } 117 }
56 118
57 // Override to set autostart and start service. 119 HRESULT Install(const FilePath& user_data_dir) {
58 HRESULT RegisterAppId(bool bService = false) { 120 if (!Uninstall())
gene 2012/05/10 22:11:45 We probably should not uninstall here, but rather
Vitaly Buka (NO REVIEWS) 2012/05/10 22:49:12 Done.
59 HRESULT hr = Base::RegisterAppId(bService); 121 return E_FAIL;
122
123 if (user_data_dir.empty()) {
gene 2012/05/10 22:11:45 you can probably check this condition in the Parse
Vitaly Buka (NO REVIEWS) 2012/05/10 22:49:12 Done.
124 std::cerr << "Invalid value --user_data_dir=" << user_data_dir.value() <<
125 "\n";
126 return E_INVALIDARG;
127 }
128
129 FilePath service_path;
130 CHECK(PathService::Get(base::FILE_EXE, &service_path));
131 CommandLine command_line(service_path);
132 command_line.AppendSwitchPath(kUserDataDirSwitch, user_data_dir);
133
134 ServiceHandle scm;
135 HRESULT hr = OpenServiceManager(&scm);
60 if (FAILED(hr)) 136 if (FAILED(hr))
61 return hr; 137 return hr;
62 138
63 ServiceHandle service; 139 ServiceHandle service(
64 hr = OpenService(SERVICE_CHANGE_CONFIG, &service); 140 ::CreateService(
65 if (FAILED(hr)) 141 scm, m_szServiceName, m_szServiceName, SERVICE_ALL_ACCESS,
66 return hr; 142 SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
143 command_line.GetCommandLineString().c_str(), NULL, NULL, NULL,
144 L"NT AUTHORITY\\LocalService", NULL));
67 145
68 if (!::ChangeServiceConfig(service, SERVICE_WIN32_OWN_PROCESS, 146 if (!service.IsValid())
69 SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, NULL, NULL, NULL, NULL,
70 L"NT AUTHORITY\\LocalService", NULL, NULL)) {
71 return HResultFromLastError(); 147 return HResultFromLastError();
72 }
73 148
74 return S_OK; 149 return S_OK;
75 } 150 }
76 151
77 // Override to handle service uninstall case manually.
78 bool ParseCommandLine(LPCTSTR lpCmdLine, HRESULT* pnRetCode) { 152 bool ParseCommandLine(LPCTSTR lpCmdLine, HRESULT* pnRetCode) {
79 if (!Base::ParseCommandLine(lpCmdLine, pnRetCode)) 153 CHECK(pnRetCode);
80 return false; 154 CommandLine command_line(CommandLine::NO_PROGRAM);
81 155 command_line.ParseFromString(lpCmdLine);
82 const wchar_t tokens[] = L"-/"; 156 *pnRetCode = ParseCommandLine(command_line);
83 *pnRetCode = S_OK; 157 if (*pnRetCode == S_OK)
84 158 return true; // Run as service.
85 for (const wchar_t* cur = lpCmdLine; cur = FindOneOf(cur, tokens);) { 159 if (FAILED(*pnRetCode)) {
86 if (WordCmpI(cur, L"UninstallService") == 0) { 160 LOG(ERROR) << "Operation failed. 0x" << std::setw(8) <<
87 if (!Uninstall()) 161 std::setbase(16) << *pnRetCode;
88 *pnRetCode = E_FAIL;
89 return false;
90 } else if (WordCmpI(cur, L"Start") == 0) {
91 *pnRetCode = StartService();
92 return false;
93 } else if (WordCmpI(cur, L"Stop") == 0) {
94 *pnRetCode = StopService();
95 return false;
96 }
97 } 162 }
98 return true; 163 return false; // Exit process.
99 } 164 }
100 165
101 HRESULT PreMessageLoop(int nShowCmd) { 166 HRESULT PreMessageLoop(int nShowCmd) {
102 HRESULT hr = Base::PreMessageLoop(nShowCmd); 167 HRESULT hr = Base::PreMessageLoop(nShowCmd);
103 if (FAILED(hr)) 168 if (FAILED(hr))
104 return hr; 169 return hr;
105 170
106 hr = StartConnector(); 171 hr = StartConnector();
107 if (FAILED(hr)) 172 if (FAILED(hr))
108 return hr; 173 return hr;
109 174
110 LogEvent(_T("Service started/resumed")); 175 LogEvent(_T("Service started/resumed"));
111 SetServiceStatus(SERVICE_RUNNING); 176 SetServiceStatus(SERVICE_RUNNING);
112 return hr; 177 return hr;
113 } 178 }
114 179
115 HRESULT PostMessageLoop() { 180 HRESULT PostMessageLoop() {
116 StopConnector(); 181 StopConnector();
117 return Base::PostMessageLoop(); 182 return Base::PostMessageLoop();
118 } 183 }
119 184
120 private: 185 private:
186 // Returns S_OK if it's called as service.
187 // Returns S_FALSE on success or usage error.
188 // Returns error code for any other error.
189 HRESULT ParseCommandLine(const CommandLine& command_line) {
190 HRESULT hr = E_INVALIDARG;
191 if (command_line.HasSwitch(kStopSwitch)) {
192 hr = StopService();
gene 2012/05/10 22:11:45 I think we shall return here no matter what StopSe
Vitaly Buka (NO REVIEWS) 2012/05/10 22:49:12 Done.
193 if (FAILED(hr))
194 return hr;
195 }
196
197 if (command_line.HasSwitch(kUninstallSwitch)) {
198 hr = Uninstall() ? S_OK : E_FAIL;
199 if (FAILED(hr))
gene 2012/05/10 22:11:45 Same as above here.
Vitaly Buka (NO REVIEWS) 2012/05/10 22:49:12 Done.
200 return hr;
201 }
202
203 if (command_line.HasSwitch(kInstallSwitch)) {
204 if (!command_line.HasSwitch(kUserDataDirSwitch)) {
205 InvalidUsage();
206 return S_FALSE;
207 }
208
209 FilePath data_dir = command_line.GetSwitchValuePath(kUserDataDirSwitch);
210 hr = Install(data_dir);
211 if (FAILED(hr))
212 return hr;
213 }
214
215 if (command_line.HasSwitch(kStartSwitch)) {
216 hr = StartService();
217 if (FAILED(hr))
218 return hr;
219 }
220
221 // No main switch matched, so it was called by SCM or just usage error.
222 if (hr == E_INVALIDARG) {
223 if (command_line.HasSwitch(kUserDataDirSwitch))
224 return S_OK;
225 InvalidUsage();
226 }
227
228 return S_FALSE;
229 }
230
231 HRESULT OpenServiceManager(ServiceHandle* service_manager) {
232 if (!service_manager)
233 return E_POINTER;
234
235 service_manager->Set(::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS));
236 if (!service_manager->IsValid())
237 return HResultFromLastError();
238
239 return S_OK;
240 }
241
121 HRESULT OpenService(DWORD access, ServiceHandle* service) { 242 HRESULT OpenService(DWORD access, ServiceHandle* service) {
122 if (!service) 243 if (!service)
123 return E_POINTER; 244 return E_POINTER;
124 245
125 ServiceHandle scm(::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS)); 246 ServiceHandle scm;
126 if (!scm.IsValid()) 247 HRESULT hr = OpenServiceManager(&scm);
127 return HResultFromLastError(); 248 if (FAILED(hr))
249 return hr;
128 250
129 service->Set(::OpenService(scm, m_szServiceName, access)); 251 service->Set(::OpenService(scm, m_szServiceName, access));
130 252
131 if (!service->IsValid()) 253 if (!service->IsValid())
132 return HResultFromLastError(); 254 return HResultFromLastError();
133 255
134 return S_OK; 256 return S_OK;
135 } 257 }
136 258
137 HRESULT StartService() { 259 HRESULT StartService() {
(...skipping 20 matching lines...) Expand all
158 HRESULT StartConnector() { 280 HRESULT StartConnector() {
159 return S_OK; 281 return S_OK;
160 } 282 }
161 283
162 void StopConnector() { 284 void StopConnector() {
163 } 285 }
164 }; 286 };
165 287
166 CloudPrintServiceModule _AtlModule; 288 CloudPrintServiceModule _AtlModule;
167 289
168 int WINAPI WinMain(__in HINSTANCE hInstance, 290 int main() {
169 __in HINSTANCE hPrevInstance, 291 base::AtExitManager at_exit;
170 __in LPSTR lpCmdLine, 292 return _AtlModule.WinMain(0);
171 __in int nCmdShow) {
172 return _AtlModule.WinMain(nCmdShow);
173 } 293 }
174
OLDNEW
« no previous file with comments | « cloud_print/service/win/cloud_print_service.h ('k') | cloud_print/service/win/service.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698