1 mike 1.7 //%/////////////////////////////////////////////////////////////////////////////
2 //
|
3 kumpf 1.16 // Copyright (c) 2000, 2001, 2002 BMC Software, Hewlett-Packard Company, IBM,
4 // The Open Group, Tivoli Systems
|
5 mike 1.7 //
6 // Permission is hereby granted, free of charge, to any person obtaining a copy
|
7 kumpf 1.16 // of this software and associated documentation files (the "Software"), to
8 // deal in the Software without restriction, including without limitation the
9 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
10 mike 1.7 // sell copies of the Software, and to permit persons to whom the Software is
11 // furnished to do so, subject to the following conditions:
12 //
|
13 kumpf 1.16 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
|
14 mike 1.7 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
15 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
16 kumpf 1.16 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
17 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
18 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
19 mike 1.7 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 //
22 //==============================================================================
23 //
24 // Author: Mike Day (mdday@us.ibm.com)
25 //
|
26 mary 1.11 // Modified By: Mary Hinton (m.hinton@verizon.net)
|
27 kumpf 1.12 // Sushma Fernandes (sushma_fernandes@hp.com)
|
28 tony 1.22 // Yi Zhou, Hewlett-Packard Company (yi_zhou@hp.com)
29 // Tony Fiorentino (fiorentino_tony@emc.com)
|
30 kumpf 1.23 // Roger Kumpf, Hewlett-Packard Company (roger_kumpf@hp.com)
|
31 mike 1.7 //
32 //%/////////////////////////////////////////////////////////////////////////////
33
34 #include <windows.h>
35 #include <process.h> /* _beginthread, _endthread */
36 #include <tchar.h>
37 #include <direct.h>
|
38 humberto 1.30 #include <Pegasus/Common/MessageLoader.h> //l10n
|
39 chuck 1.31 #include <Pegasus/Common/Thread.h> // l10n
|
40 mike 1.7
|
41 tony 1.22 #include "service.cpp"
|
42 mike 1.7
43 PEGASUS_USING_PEGASUS;
44 PEGASUS_USING_STD;
45
|
46 tony 1.22 //-------------------------------------------------------------------------
47 // DEFINES
48 //-------------------------------------------------------------------------
49 #define PEGASUS_SERVICE_NAME "cimserver"
50 #define PEGASUS_DISPLAY_NAME "Pegasus CIM Object Manager"
51 #define PEGASUS_DESCRIPTION "Pegasus CIM Object Manager Service"
52
53 //-------------------------------------------------------------------------
54 // GLOBALS
55 //-------------------------------------------------------------------------
|
56 mike 1.7 CIMServer *server_windows;
|
57 tony 1.22 static Service pegasus_service(PEGASUS_SERVICE_NAME);
58 static HANDLE pegasus_service_event;
|
59 tony 1.26 static LPCSTR g_cimservice_key = TEXT("SYSTEM\\CurrentControlSet\\Services\\%s");
|
60 tony 1.22 static LPCSTR g_cimservice_home = TEXT("home");
61
62 //-------------------------------------------------------------------------
63 // PROTOTYPES
64 //-------------------------------------------------------------------------
65 int cimserver_windows_main(int flag, int argc, char **argv);
66 extern void GetOptions(ConfigManager *cm,
67 int &argc,
68 char **argv,
69 const String &pegasusHome);
70 static bool _getRegInfo(const char *lpchKeyword, char *lpchRetValue);
71 static bool _setRegInfo(const char *lpchKeyword, const char *lpchValue);
72 void setHome(String & home);
73
74 //-------------------------------------------------------------------------
75 // NO-OPs for windows platform
76 //-------------------------------------------------------------------------
77 int cimserver_fork(void) { return(0); }
78 int cimserver_kill(void) { return(0); }
|
79 konrad.r 1.29 void notify_parent(int id) { return; }
|
80 tony 1.22
|
81 chuck 1.31 // l10n
82 //-------------------------------------------------------------------------
83 // Dummy function for the Thread object associated with the initial thread.
84 // Since the initial thread is used to process CIM requests, this is
85 // needed to localize the exceptions thrown during CIM request processing.
86 // Note: This function should never be called!
87 //-------------------------------------------------------------------------
88 PEGASUS_THREAD_RETURN PEGASUS_THREAD_CDECL dummyThreadFuncWindows(void *parm)
89 {
90 return((PEGASUS_THREAD_RETURN)0);
91 }
92
|
93 tony 1.22 //-------------------------------------------------------------------------
94 // START MONITOR Asynchronously
95 //-------------------------------------------------------------------------
96 static void __cdecl cimserver_windows_thread(void *parm)
97 {
|
98 chuck 1.31 //l10n
99 // Set Message loading to process locale
100 MessageLoader::_useProcessLocale = true;
|
101 tony 1.22
102 // Get options (from command line and from configuration file); this
103 // removes corresponding options and their arguments fromt he command
104 // line.
|
105 mike 1.7
|
106 tony 1.22 String pegasusHome;
|
107 mike 1.7
|
108 tony 1.22 // Windows way to set home
109 setHome(pegasusHome);
|
110 mike 1.7
|
111 tony 1.22 ConfigManager::setPegasusHome(pegasusHome);
|
112 mike 1.7
|
113 tony 1.22 ConfigManager* configManager = ConfigManager::getInstance();
114 int dummy = 0;
|
115 mike 1.8
|
116 tony 1.22 try
|
117 mike 1.7 {
|
118 tony 1.22 GetOptions(configManager, dummy, NULL, pegasusHome);
|
119 mike 1.7 }
|
120 tony 1.22 catch (Exception&)
|
121 mike 1.7 {
122 exit(1);
123 }
124
|
125 chuck 1.31 // l10n
126 String messagesDir = ConfigManager::getHomedPath("msg");
127 MessageLoader::setPegasusMsgHome(messagesDir);
128
|
129 kumpf 1.25 Boolean enableHttpConnection = String::equal(
130 configManager->getCurrentValue("enableHttpConnection"), "true");
131 Boolean enableHttpsConnection = String::equal(
132 configManager->getCurrentValue("enableHttpsConnection"), "true");
|
133 tony 1.22
|
134 kumpf 1.23 if (!enableHttpConnection && !enableHttpsConnection)
135 {
|
136 humberto 1.30 //l10n
137 //Logger::put(Logger::STANDARD_LOG, "CIMServer", Logger::WARNING,
138 //"Neither HTTP nor HTTPS connection is enabled. "
139 //"CIMServer will not be started.");
140 Logger::put_l(Logger::STANDARD_LOG, "CIMServer", Logger::WARNING,
141 "src.Server.cimserver_windows.HTTP_NOT_ENABLED_SERVER_NOT_STARTING",
142 "Neither HTTP nor HTTPS connection is enabled. CIMServer will not be started.");
143
144 MessageLoaderParms parms("src.Server.cimserver_windows.HTTP_NOT_ENABLED_SERVER_NOT_STARTING",
145 "Neither HTTP nor HTTPS connection is enabled. CIMServer will not be started.");
146 //cerr << "Neither HTTP nor HTTPS connection is enabled. "
147 //"CIMServer will not be started." << endl;
148 cerr << MessageLoader::getMessage(parms) << endl;
|
149 kumpf 1.23 exit(1);
150 }
|
151 mike 1.8
|
152 kumpf 1.23 // Get the connection port configurations
|
153 tony 1.22
|
154 kumpf 1.23 Uint32 portNumberHttps;
155 Uint32 portNumberHttp;
|
156 tony 1.22
|
157 kumpf 1.23 if (enableHttpsConnection)
|
158 tony 1.22 {
|
159 kumpf 1.23 String httpsPort = configManager->getCurrentValue("httpsPort");
160 CString portString = httpsPort.getCString();
161 char* end = 0;
162 Uint32 port = strtol(portString, &end, 10);
163 assert(end != 0 && *end == '\0');
164
165 //
166 // Look up the WBEM-HTTPS port number
167 //
168 portNumberHttps = System::lookupPort(WBEM_HTTPS_SERVICE_NAME, port);
|
169 tony 1.22 }
|
170 kumpf 1.23
171 if (enableHttpConnection)
|
172 tony 1.22 {
|
173 kumpf 1.23 String httpPort = configManager->getCurrentValue("httpPort");
174 CString portString = httpPort.getCString();
175 char* end = 0;
176 Uint32 port = strtol(portString, &end, 10);
177 assert(end != 0 && *end == '\0');
178
179 //
180 // Look up the WBEM-HTTP port number
181 //
182 portNumberHttp = System::lookupPort(WBEM_HTTP_SERVICE_NAME, port);
|
183 tony 1.22 }
184
185 // Set up the Logger
186 String logsDirectory = String::EMPTY;
187 logsDirectory = configManager->getCurrentValue("logdir");
188 logsDirectory = ConfigManager::getHomedPath(configManager->getCurrentValue("logdir"));
189
190 Logger::setHomeDirectory(logsDirectory);
191
192 // Put server start message to the logger
|
193 humberto 1.30 //l10n
194 //Logger::put(Logger::STANDARD_LOG, PEGASUS_SERVICE_NAME, Logger::INFORMATION,
195 //"Started $0 version $1.", PEGASUS_NAME, PEGASUS_VERSION);
196 Logger::put_l(Logger::STANDARD_LOG, PEGASUS_SERVICE_NAME, Logger::INFORMATION,
197 "src.Server.cimserver_windows.STARTED_VERSION",
198 "Started $0 version $1.", PEGASUS_NAME, PEGASUS_VERSION);
|
199 kumpf 1.23
|
200 tony 1.22 // try loop to bind the address, and run the server
201 try
202 {
203 Monitor monitor(true);
204
|
205 kumpf 1.23 CIMServer server(&monitor);
|
206 tony 1.22 server_windows = &server;
207
|
208 kumpf 1.23 if (enableHttpConnection)
209 {
210 server_windows->addAcceptor(false, portNumberHttp, false);
|
211 humberto 1.32 //l10n 485
|
212 humberto 1.30 //Logger::put(Logger::STANDARD_LOG, "CIMServer", Logger::INFORMATION,
213 //"Listening on HTTP port $0.", portNumberHttp);
214 Logger::put_l(Logger::STANDARD_LOG, "CIMServer", Logger::INFORMATION,
|
215 humberto 1.32 "src.Server.cimserver_windows.LISTENING_ON_HTTP_PORT",
216 "Listening on HTTP port $0.", portNumberHttp);
|
217 kumpf 1.23 }
218 if (enableHttpsConnection)
219 {
220 server_windows->addAcceptor(false, portNumberHttps, true);
|
221 humberto 1.32 //l10n 485
|
222 humberto 1.30 //Logger::put(Logger::STANDARD_LOG, "CIMServer", Logger::INFORMATION,
223 // "Listening on HTTPS port $0.", portNumberHttps);
224 Logger::put_l(Logger::STANDARD_LOG, "CIMServer", Logger::INFORMATION,
|
225 humberto 1.32 "src.Server.cimserver_windows.LISTENING_ON_HTTPS_PORT",
226 "Listening on HTTPS port $0.", "HTTPS", portNumberHttps);
|
227 kumpf 1.23 }
|
228 tony 1.22
|
229 kumpf 1.23 server_windows->bind();
|
230 chuck 1.31
231 //l10n
232 // reset message loading to NON-process locale
233 MessageLoader::_useProcessLocale = false;
234 // l10n
235 // Now we are about to run the server..
236 // Create a dummy Thread object that can be used to store the
237 // AcceptLanguages object for CIM requests that are serviced
238 // by this thread (initial thread of server). Need to do this
239 // because this thread is not in a ThreadPool, but is used
240 // to service CIM requests.
241 // The run function for the dummy Thread should never be called,
242 Thread *dummyInitialThread = new Thread(dummyThreadFuncWindows, NULL, false);
243 Thread::setCurrent(dummyInitialThread);
244 AcceptLanguages default_al = AcceptLanguages::getDefaultAcceptLanguages();
245 Thread::setLanguages(new AcceptLanguages(default_al));
|
246 tony 1.22
247 while(!server_windows->terminated())
248 {
249 server_windows->runForever();
250 }
251 }
252 catch(Exception& e)
253 {
254 PEGASUS_STD(cerr) << "Error: " << e.getMessage() << PEGASUS_STD(endl);
255 }
256
257 _endthreadex(NULL);
258 }
|
259 mary 1.13
|
260 mike 1.7
|
261 tony 1.22 //-------------------------------------------------------------------------
262 // Windows NT Service Control Code
263 //-------------------------------------------------------------------------
|
264 kumpf 1.14
|
265 tony 1.22 //-------------------------------------------------------------------------
266 // SERVICE (no parameters)
267 //-------------------------------------------------------------------------
268 void cim_server_service(int argc, char **argv)
269 {
270 Service::ReturnCode status = Service::SERVICE_RETURN_SUCCESS;
271 char console_title[_MAX_PATH] = {0};
|
272 mike 1.7
|
273 tony 1.22 // Check if running from a console window
274 if (GetConsoleTitle(console_title, _MAX_PATH) > 0)
275 return;
|
276 mike 1.7
|
277 tony 1.22 pegasus_service_event = CreateEvent(NULL, FALSE, FALSE, NULL);
|
278 mike 1.8
|
279 tony 1.22 // Run should exit the process if a service
280 status = pegasus_service.Run(cimserver_windows_main);
|
281 mike 1.8
|
282 tony 1.22 // If we made it here there was a problem starting this process as a service
283 // Log the problem to the log file
|
284 mike 1.7
|
285 tony 1.22 // TODO: log or echo something here
|
286 mike 1.7 }
287
|
288 tony 1.22 //-------------------------------------------------------------------------
289 // START/STOP handler
290 //-------------------------------------------------------------------------
291 int cimserver_windows_main(int flag, int argc, char *argv[])
292 {
293 switch (flag)
294 {
295 case Service::STARTUP_FLAG:
296 if (_beginthread(cimserver_windows_thread, 0, NULL))
297 WaitForSingleObject(pegasus_service_event, INFINITE);
298 break;
|
299 mike 1.7
|
300 tony 1.22 case Service::SHUTDOWN_FLAG:
301 SetEvent(pegasus_service_event);
302 break;
303
304 default:
305 break;
306 }
|
307 mike 1.7
|
308 tony 1.22 return 0;
309 }
|
310 mike 1.7
|
311 tony 1.22 //-------------------------------------------------------------------------
312 // IS RUNNING?
313 //-------------------------------------------------------------------------
314 Boolean isCIMServerRunning(void)
315 {
316 Service::State state;
317 pegasus_service.GetState(&state);
|
318 mike 1.7
|
319 tony 1.22 return (state == Service::SERVICE_STATE_RUNNING) ? true : false;
320 }
|
321 mike 1.7
|
322 tony 1.22 //-------------------------------------------------------------------------
323 // INSTALL
324 //-------------------------------------------------------------------------
|
325 tony 1.26 bool cimserver_install_nt_service(char *service_name)
|
326 mike 1.7 {
|
327 tony 1.22 Service::ReturnCode status = Service::SERVICE_RETURN_SUCCESS;
|
328 tony 1.26 char filename[_MAX_PATH] = {0};
329 char displayname[_MAX_PATH] = {0};
330
331 // If service name is specified, override default
332 if (service_name == NULL)
333 {
334 strcpy(displayname, PEGASUS_DISPLAY_NAME);
335 }
336 else
337 {
338 pegasus_service.SetServiceName(service_name);
339 sprintf(displayname, "%s - %s", PEGASUS_DISPLAY_NAME, service_name);
340 }
|
341 tony 1.22
342 GetModuleFileName(NULL, filename, sizeof(filename));
|
343 tony 1.26 status = pegasus_service.Install(displayname, PEGASUS_DESCRIPTION, filename);
|
344 mike 1.7
|
345 tony 1.22 // Upon success, set home in registry
346 if (status == Service::SERVICE_RETURN_SUCCESS)
|
347 mike 1.7 {
|
348 tony 1.22 char pegasus_homepath[_MAX_PATH];
349 System::extract_file_path(filename, pegasus_homepath);
350 pegasus_homepath[strlen(pegasus_homepath)-1] = '\0';
351 strcpy(filename, pegasus_homepath);
352 System::extract_file_path(filename, pegasus_homepath);
353 pegasus_homepath[strlen(pegasus_homepath)-1] = '\0';
354 _setRegInfo(g_cimservice_home, pegasus_homepath);
|
355 mike 1.7 }
|
356 tony 1.22
357 return (status == Service::SERVICE_RETURN_SUCCESS) ? true : false;
358 }
359
360 //-------------------------------------------------------------------------
361 // REMOVE
362 //-------------------------------------------------------------------------
|
363 tony 1.26 bool cimserver_remove_nt_service(char *service_name)
|
364 tony 1.22 {
365 Service::ReturnCode status = Service::SERVICE_RETURN_SUCCESS;
366
|
367 tony 1.26 // If service name is specified, override default
368 if (service_name != NULL)
369 {
370 pegasus_service.SetServiceName(service_name);
371 }
372
|
373 tony 1.22 status = pegasus_service.Remove();
374
375 return (status == Service::SERVICE_RETURN_SUCCESS) ? true : false;
|
376 mike 1.7 }
377
|
378 tony 1.22 //-------------------------------------------------------------------------
379 // START
380 //-------------------------------------------------------------------------
|
381 tony 1.26 bool cimserver_start_nt_service(char *service_name)
|
382 tony 1.22 {
383 Service::ReturnCode status = Service::SERVICE_RETURN_SUCCESS;
384
|
385 tony 1.26 // If service name is specified, override default
386 if (service_name != NULL)
387 {
388 pegasus_service.SetServiceName(service_name);
389 }
390
|
391 tony 1.22 status = pegasus_service.Start(5);
392
393 return (status == Service::SERVICE_RETURN_SUCCESS) ? true : false;
394 }
|
395 mike 1.7
|
396 tony 1.22 //-------------------------------------------------------------------------
397 // STOP
398 //-------------------------------------------------------------------------
|
399 tony 1.26 bool cimserver_stop_nt_service(char *service_name)
|
400 mike 1.7 {
|
401 tony 1.22 Service::ReturnCode status = Service::SERVICE_RETURN_SUCCESS;
|
402 mike 1.7
|
403 tony 1.26 // If service name is specified, override default
404 if (service_name != NULL)
405 {
406 pegasus_service.SetServiceName(service_name);
407 }
408
|
409 tony 1.22 status = pegasus_service.Stop(5);
410
411 return (status == Service::SERVICE_RETURN_SUCCESS) ? true : false;
412 }
|
413 mike 1.7
|
414 tony 1.22 //-------------------------------------------------------------------------
415 // HELPER Utilities
416 //-------------------------------------------------------------------------
417 static bool _getRegInfo(const char *lpchKeyword, char *lpchRetValue)
418 {
419 HKEY hKey;
420 DWORD dw = _MAX_PATH;
|
421 tony 1.26 char subKey[_MAX_PATH] = {0};
422
423 sprintf(subKey, g_cimservice_key, pegasus_service.GetServiceName());
|
424 mike 1.7
|
425 tony 1.22 if ((RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
426 tony 1.26 subKey,
|
427 tony 1.22 0,
428 KEY_READ,
429 &hKey)) != ERROR_SUCCESS)
|
430 mike 1.7 {
|
431 tony 1.22 return false;
|
432 mike 1.7 }
433
|
434 tony 1.22 if ((RegQueryValueEx(hKey,
435 lpchKeyword,
436 NULL,
437 NULL,
438 (LPBYTE)lpchRetValue,
439 &dw)) != ERROR_SUCCESS)
|
440 mike 1.7 {
|
441 tony 1.22 RegCloseKey(hKey);
442 return false;
|
443 mike 1.7 }
444
|
445 tony 1.22 RegCloseKey(hKey);
446
447 return true;
|
448 mike 1.7 }
449
|
450 tony 1.22 static bool _setRegInfo(const char *lpchKeyword, const char *lpchValue)
|
451 mike 1.7 {
|
452 tony 1.22 HKEY hKey;
453 DWORD dw = _MAX_PATH;
454 char home_key[_MAX_PATH] = {0};
|
455 tony 1.26 char subKey[_MAX_PATH] = {0};
|
456 tony 1.22
457 if (lpchKeyword == NULL || lpchValue == NULL)
458 return false;
459
|
460 tony 1.26 sprintf(subKey, g_cimservice_key, pegasus_service.GetServiceName());
461
462 if ((RegCreateKeyEx (HKEY_LOCAL_MACHINE,
463 subKey,
|
464 tony 1.22 0,
465 NULL,
466 0,
467 KEY_ALL_ACCESS,
468 NULL,
469 &hKey,
470 NULL) != ERROR_SUCCESS))
471 {
472 return false;
473 }
474
475 if ((RegSetValueEx(hKey,
476 lpchKeyword,
477 0,
478 REG_SZ,
479 (CONST BYTE *)lpchValue,
480 (DWORD)(strlen(lpchValue)+1))) != ERROR_SUCCESS)
481 {
482 RegCloseKey(hKey);
483 return false;
484 }
|
485 mike 1.7
|
486 tony 1.22 RegCloseKey(hKey);
487
488 return true;
|
489 mike 1.7 }
490
|
491 tony 1.22 void setHome(String & home)
|
492 mike 1.7 {
|
493 tony 1.22 // Determine the absolute path to the running program
|
494 tony 1.27 char exe_pathname[_MAX_PATH] = {0};
495 char home_pathname[_MAX_PATH] = {0};
|
496 tony 1.22 GetModuleFileName(NULL, exe_pathname, sizeof(exe_pathname));
497
498 // Pegasus home search rules:
499 // - look in registry (if set)
500 // - if not found, look in PEGASUS_HOME (if set)
501 // - if not found, use exe directory minus one level
502
|
503 tony 1.27 bool found_reg = _getRegInfo("home", home_pathname);
504 if (found_reg == true)
|
505 tony 1.22 {
|
506 tony 1.27 // Make sure home matches
507 String current_home(home_pathname);
508 String current_exe(exe_pathname);
509 current_home.toLower();
510 current_exe.toLower();
511
512 Uint32 pos = current_exe.find(current_home);
513 if (pos != PEG_NOT_FOUND)
514 {
515 home = home_pathname;
516 }
517 else
518 {
519 found_reg = false;
520 }
|
521 tony 1.22 }
|
522 tony 1.27 if (found_reg == false)
|
523 tony 1.22 {
524 const char* tmp = getenv("PEGASUS_HOME");
525 if (tmp)
526 {
527 home = tmp;
528 }
529 else
530 {
531 // ASSUMPTION: At a minimum, the cimserver program is running
532 // from a "bin" directory
533 home = FileSystem::extractFilePath(exe_pathname);
534 home.remove(home.size()-1, 1);
535 home = FileSystem::extractFilePath(home);
536 home.remove(home.size()-1, 1);
537 }
|
538 mike 1.7 }
539 }
540
541
|
542 tony 1.22
|