1 kumpf 1.1 //%/////////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (c) 2000, 2001, 2002 BMC Software, Hewlett-Packard Company, IBM,
4 // The Open Group, Tivoli Systems
5 //
6 // Permission is hereby granted, free of charge, to any person obtaining a copy
7 // 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 // 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 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
14 // 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 // 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 // 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 kumpf 1.1 //==============================================================================
23 //
24 // Author: Mike Day (mdday@us.ibm.com)
25 //
26 // Modified By: Mary Hinton (m.hinton@verizon.net)
27 // Sushma Fernandes (sushma_fernandes@hp.com)
|
28 kumpf 1.2 // Yi Zhou, Hewlett-Packard Company (yi_zhou@hp.com)
|
29 kumpf 1.1 //
30 //%/////////////////////////////////////////////////////////////////////////////
31
32 #include <windows.h>
33 #include <process.h> /* _beginthread, _endthread */
34 #include <tchar.h>
35 #include <direct.h>
36
37 PEGASUS_USING_PEGASUS;
38 PEGASUS_USING_STD;
39
40 static DWORD dieNow = 0;
41 String *runPath;
42 CIMServer *server_windows;
43 static SERVICE_STATUS pegasus_status;
44 static SERVICE_STATUS_HANDLE pegasus_status_handle;
45
46 VOID WINAPI cimserver_windows_main(int argc, char **argv) ;
47 VOID WINAPI cimserver_service_start(DWORD, LPTSTR *);
48 VOID WINAPI cimserver_service_ctrl_handler(DWORD );
49 DWORD cimserver_initialization(DWORD, LPTSTR *, DWORD *) ;
50 kumpf 1.1
51 void GetOptions(
52 ConfigManager* cm,
53 int& argc,
54 char** argv,
55 const String& pegasusHome);
56
57 void cim_server_service(int argc, char **argv ) { cimserver_windows_main(argc, argv); exit(0); }
58 int cimserver_fork( ) { return(0); }
59 int cimserver_kill( ) { return(0); }
60 Boolean isCIMServerRunning( ) { return(false); }
61
|
62 kumpf 1.2 // notify parent process to terminate so user knows that cimserver
63 // is ready to serve CIM requests. If this plateform needs to implement
64 // this functionality, please see sample implementation in cimserver_unix.cpp
65 void notify_parent(void)
66 {
67 }
68
|
69 kumpf 1.1 static void __cdecl cimserver_windows_thread(void *parm)
70 {
71
|
72 kumpf 1.2 // Get options (from command line and from configuration file); this
73 // removes corresponding options and their arguments fromt he command
74 // line.
75
76 String pegasusHome;
77
78 // mdh: need to get the environment for the Windows Service to run
79 const char* tmp = getenv("PEGASUS_HOME");
80 if (tmp)
81 {
82 pegasusHome = tmp;
83 }
|
84 kumpf 1.1
|
85 kumpf 1.2 ConfigManager::setPegasusHome(pegasusHome);
86
87 ConfigManager* configManager = ConfigManager::getInstance();
|
88 kumpf 1.1 int dummy = 0;
|
89 kumpf 1.2 //String pegasusHome;
|
90 kumpf 1.1
|
91 kumpf 1.2 try
|
92 kumpf 1.1 {
|
93 kumpf 1.2 GetOptions(configManager, dummy, NULL, pegasusHome);
|
94 kumpf 1.1 }
95 catch (Exception&)
96 {
|
97 kumpf 1.2 exit(1);
|
98 kumpf 1.1 }
99
|
100 kumpf 1.2 //
|
101 kumpf 1.1 // Check the trace options and set global variable
102 //
103 Boolean pegasusIOTrace = false;
104
105 if (String::equal(configManager->getCurrentValue("trace"), "true"))
106 {
107 pegasusIOTrace = true;
108 }
109
|
110 kumpf 1.2 //
|
111 kumpf 1.1 // Check the log trace options and set global variable
112 //
113 Boolean pegasusIOLog = false;
114
115 if (String::equal(configManager->getCurrentValue("logtrace"), "true"))
116 {
117 pegasusIOLog = true;
118 }
|
119 kumpf 1.2
120 // The "SSL" property overrides the enableHttp*Connection properties and
121 // enables only the HTTPS connection.
122 Boolean enableHttpConnection = String::equal(
123 configManager->getCurrentValue("enableHttpConnection"), "true");
124
125 Boolean enableHttpsConnection = String::equal(
126 configManager->getCurrentValue("enableHttpsConnection"), "true");
127
128 if (!enableHttpConnection && !enableHttpsConnection)
|
129 kumpf 1.1 {
|
130 kumpf 1.2 Logger::put(Logger::STANDARD_LOG, "CIMServer", Logger::WARNING,
131 "Neither HTTP nor HTTPS connection is enabled. "
132 "CIMServer will not be started.");
133 cerr << "Neither HTTP nor HTTPS connection is enabled. "
134 "CIMServer will not be started." << endl;
135 exit(1);
|
136 kumpf 1.1 }
137
|
138 kumpf 1.2 // Get the connection port configurations
|
139 kumpf 1.1
|
140 kumpf 1.2 Uint32 portNumberHttps;
141 Uint32 portNumberHttp;
|
142 kumpf 1.1
|
143 kumpf 1.2 if (enableHttpsConnection)
|
144 kumpf 1.1 {
|
145 kumpf 1.2 String httpsPort = configManager->getCurrentValue("httpsPort");
146 CString portString = httpsPort.getCString();
147 char* end = 0;
148 Uint32 port = strtol(portString, &end, 10);
149 assert(end != 0 && *end == '\0');
150
151 //
152 // Look up the WBEM-HTTPS port number
153 //
154 portNumberHttps = System::lookupPort(WBEM_HTTPS_SERVICE_NAME, port);
|
155 kumpf 1.1 }
|
156 kumpf 1.2
157 if (enableHttpConnection)
|
158 kumpf 1.1 {
|
159 kumpf 1.2 String httpPort = configManager->getCurrentValue("httpPort");
160 CString portString = httpPort.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-HTTP port number
167 //
168 portNumberHttp = System::lookupPort(WBEM_HTTP_SERVICE_NAME, port);
|
169 kumpf 1.1 }
170
171 // Set up the Logger
172 Logger::setHomeDirectory("./logs");
173
174 // Put server start message to the logger
175 Logger::put(Logger::STANDARD_LOG, "CIMServer", Logger::INFORMATION,
|
176 kumpf 1.2 "Start $0 %1 $2 ", 88, PEGASUS_NAME, PEGASUS_VERSION,
177 (pegasusIOTrace ? " Tracing": " "));
178 // ATTN: Should this really be: ?
179 //Logger::put(Logger::STANDARD_LOG, "CIMServer", Logger::INFORMATION,
180 // "Started $0 version $1.", PEGASUS_NAME, PEGASUS_VERSION);
181
|
182 kumpf 1.1 // try loop to bind the address, and run the server
183 try
184 {
|
185 kumpf 1.2 Monitor monitor(true);
|
186 kumpf 1.1
|
187 kumpf 1.2 CIMServer server(&monitor);
188 server_windows = &server;
|
189 kumpf 1.1
|
190 kumpf 1.2 if (enableHttpConnection)
191 {
192 server_windows->addAcceptor(false, portNumberHttp, false);
193 Logger::put(Logger::STANDARD_LOG, "CIMServer", Logger::INFORMATION,
194 "Listening on HTTP port $0.", portNumberHttp);
195 }
196 if (enableHttpsConnection)
197 {
198 server_windows->addAcceptor(false, portNumberHttps, true);
199 Logger::put(Logger::STANDARD_LOG, "CIMServer", Logger::INFORMATION,
200 "Listening on HTTPS port $0.", portNumberHttps);
201 }
202
203 server_windows->bind();
|
204 kumpf 1.1
|
205 kumpf 1.2 while(!server_windows->terminated())
206 {
207 server_windows->runForever();
208 }
|
209 kumpf 1.1 }
210 catch(Exception& e)
211 {
|
212 kumpf 1.2 PEGASUS_STD(cerr) << "Error: " << e.getMessage() << PEGASUS_STD(endl);
|
213 kumpf 1.1 }
214
215 _endthreadex(NULL);
216 }
217
218
219 /////////////////////////////////////////////////////////////////
220 // Windows NT Service Control Code
221 /////////////////////////////////////////////////////////////////
|
222 kumpf 1.2 VOID WINAPI cimserver_windows_main(int argc, char **argv)
223 {
224 int ccode;
225 SERVICE_TABLE_ENTRY dispatch_table[] =
226 {
227 {"wmiserver", cimserver_service_start},
228 {NULL, NULL}
229 };
|
230 kumpf 1.1
|
231 kumpf 1.2 /* let everyone know we are running (or trying to run) as an NT service */
232 if(!(ccode = StartServiceCtrlDispatcher(dispatch_table)))
233 {
234 ccode = GetLastError();
235 // Put server start message to the logger
236 Logger::put(Logger::STANDARD_LOG, "CIMServer_Windows", Logger::INFORMATION,
237 "Started as a Windows Service");
238 }
|
239 kumpf 1.1
|
240 kumpf 1.2 return;
|
241 kumpf 1.1 }
242
243 /////////////////////////////////////////////////////////////////
244 //
245 // called by the NT service control manager to start the SLP service
246 //
247 /////////////////////////////////////////////////////////////////
248 VOID WINAPI cimserver_service_start(DWORD argc, LPTSTR *argv)
249 {
250
|
251 kumpf 1.2 DWORD status;
252 DWORD specificError;
253 pegasus_status.dwServiceType = SERVICE_WIN32;
254 pegasus_status.dwCurrentState = SERVICE_START_PENDING;
255 pegasus_status.dwControlsAccepted
256 = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN ;
257 pegasus_status.dwWin32ExitCode = 0;
258 pegasus_status.dwServiceSpecificExitCode = 0;
259 pegasus_status.dwCheckPoint = 0;
260 pegasus_status.dwWaitHint = 0;
261 pegasus_status_handle = RegisterServiceCtrlHandler("wmiserver", cimserver_service_ctrl_handler);
262
263 if(pegasus_status_handle == (SERVICE_STATUS_HANDLE)0)
264 {
265 Logger::put(Logger::STANDARD_LOG, "CIMServer_Windows", Logger::INFORMATION,
266 "Error installing service handler");
267 return;
268 }
|
269 kumpf 1.1
|
270 kumpf 1.2 // mdday -- I need to replace this hack with registry code
|
271 kumpf 1.1
|
272 kumpf 1.2 // this is an ugly hack because we should really be getting this data
273 // out of the registry. We are essentially forcing pegasus to be run
274 // from its build tree. i.e.:
275 // PEGASUS_HOME = binary_exe_path minus "\bin\cimserver.exe"
276
277 // so if my build environment is in "c:\my-programs\pegasus\
278 // I will install the service binary path as "c:\my-programs\pegasus\bin\cimserver.exe"
279 // Therefore I will derive PEGASUS_HOME as "c:\my-programs\pegasus"
|
280 kumpf 1.1
|
281 kumpf 1.2 // If I do something wierd and run pegasus from "c:\winnt" then this hack will break
282 // the service will think its running but the CIMServer object will never have been instantiated.
|
283 kumpf 1.1
|
284 kumpf 1.2 SC_HANDLE service_handle, sc_manager;
285 if(NULL != (sc_manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS)))
286 {
287 if(NULL != (service_handle = OpenService(sc_manager,
288 "wmiserver",
289 SERVICE_ALL_ACCESS)))
|
290 kumpf 1.1
|
291 kumpf 1.2 {
292 DWORD bytes_needed = 0;
293 QUERY_SERVICE_CONFIG *svc_config = NULL;
|
294 kumpf 1.1
|
295 kumpf 1.2 QueryServiceConfig(service_handle, svc_config, sizeof(svc_config), &bytes_needed);
296 if(bytes_needed > 0)
|
297 kumpf 1.1 {
|
298 kumpf 1.2 if(NULL != ( svc_config = (QUERY_SERVICE_CONFIG *) malloc(bytes_needed)))
299 {
300 if(TRUE == QueryServiceConfig(service_handle, svc_config, bytes_needed, &bytes_needed))
301 {
302 Uint32 position;
303 runPath = new String(svc_config->lpBinaryPathName);
304 if(PEG_NOT_FOUND != (position = runPath->reverseFind('\\')))
305 {
306 Uint32 len = runPath->size();
307 runPath->remove(position, len - position);
308 position = runPath->reverseFind('\\');
309 len = runPath->size();
310 runPath->remove(position, len - position);
311 }
312 }
313
314 free(svc_config);
315 }
|
316 kumpf 1.1 }
|
317 kumpf 1.2
318 CloseServiceHandle(service_handle);
|
319 kumpf 1.1 }
|
320 kumpf 1.2
321 CloseServiceHandle(sc_manager);
|
322 kumpf 1.1 }
323
|
324 kumpf 1.2 status = cimserver_initialization(argc, argv, &specificError);
325 if(status < 0)
|
326 kumpf 1.1 {
|
327 kumpf 1.2 pegasus_status.dwCurrentState = SERVICE_STOPPED;
328 pegasus_status.dwCheckPoint = 0;
329 pegasus_status.dwWaitHint = 0;
330 pegasus_status.dwWin32ExitCode = status;
331 pegasus_status.dwServiceSpecificExitCode = specificError;
332 SetServiceStatus(pegasus_status_handle, &pegasus_status);
333 Logger::put(Logger::STANDARD_LOG, "CIMServer_Windows", Logger::INFORMATION,
334 "Error starting Cim Server");
335 return;
336 }
|
337 kumpf 1.1
|
338 kumpf 1.2 pegasus_status.dwCurrentState = SERVICE_RUNNING;
339 pegasus_status.dwCheckPoint = 0;
340 pegasus_status.dwWaitHint = 0;
|
341 kumpf 1.1
|
342 kumpf 1.2 if(!SetServiceStatus(pegasus_status_handle, &pegasus_status))
343 {
344 if(server_windows != NULL)
345 server_windows->shutdown();
346 }
|
347 kumpf 1.1
|
348 kumpf 1.2 return;
|
349 kumpf 1.1 }
350
|
351 kumpf 1.2 /////////////////////////////////////////////////////////////////
352 //
353 /////////////////////////////////////////////////////////////////
|
354 kumpf 1.1 VOID WINAPI cimserver_service_ctrl_handler(DWORD opcode)
355 {
|
356 kumpf 1.2 switch(opcode)
357 {
358 case SERVICE_CONTROL_STOP:
359 case SERVICE_CONTROL_SHUTDOWN:
360 if(server_windows != NULL)
361 server_windows->shutdown();
362 pegasus_status.dwCurrentState = SERVICE_STOPPED;
363 pegasus_status.dwCheckPoint = 0;
364 pegasus_status.dwWaitHint = 0;
365 pegasus_status.dwWin32ExitCode = 0;
366 SetServiceStatus(pegasus_status_handle, &pegasus_status);
367 return;
368 break;
369 default:
370 break;
371 }
372
373 SetServiceStatus(pegasus_status_handle, &pegasus_status);
|
374 kumpf 1.1
|
375 kumpf 1.2 return;
|
376 kumpf 1.1 }
377
|
378 kumpf 1.2 /////////////////////////////////////////////////////////////////
379 //
380 /////////////////////////////////////////////////////////////////
|
381 kumpf 1.1 DWORD cimserver_initialization(DWORD argc, LPTSTR *argv, DWORD *specificError)
382 {
|
383 kumpf 1.2 return( _beginthread(cimserver_windows_thread, 0, NULL ));
|
384 kumpf 1.1 }
385
|
386 kumpf 1.2 /////////////////////////////////////////////////////////////////
387 //
388 /////////////////////////////////////////////////////////////////
389 Uint32 cimserver_install_nt_service(String &pegasusHome)
390 {
391 SC_HANDLE service_handle, sc_manager;
392 Uint32 ccode = 0;
393
394 pegasusHome.append("\\bin\\wmiserver.exe");
|
395 kumpf 1.1
|
396 kumpf 1.2 CString pegHome = pegasusHome.getCString() ;
397 LPCSTR path_name = (const char*) pegHome;
398
399 if(NULL != (sc_manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS)))
400 {
401 if(NULL != (service_handle = CreateService(sc_manager,
402 "wmiserver",
403 "Pegasus WMI Mapper",
404 SERVICE_ALL_ACCESS,
405 SERVICE_WIN32_OWN_PROCESS,
406 SERVICE_DEMAND_START,
407 SERVICE_ERROR_NORMAL,
408 path_name,
409 NULL,
410 NULL,
411 NULL,
412 NULL,
413 NULL)))
414 {
415 ccode = (Uint32)service_handle;
416 }
417 kumpf 1.2
418 CloseServiceHandle(service_handle);
|
419 kumpf 1.1 }
420
|
421 kumpf 1.2 return(ccode);
|
422 kumpf 1.1 }
423
|
424 kumpf 1.2 /////////////////////////////////////////////////////////////////
425 //
426 /////////////////////////////////////////////////////////////////
|
427 kumpf 1.1 Uint32 cimserver_remove_nt_service(void)
428 {
429
|
430 kumpf 1.2 SC_HANDLE service_handle, sc_manager;
431 int ccode = 0;
432
433 if(NULL != (sc_manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS)))
|
434 kumpf 1.1 {
|
435 kumpf 1.2 if(NULL != (service_handle = OpenService(sc_manager, "wmiserver", DELETE)))
436 {
437 DeleteService(service_handle);
438 CloseServiceHandle(service_handle);
439 ccode = 1;
440 }
441
442 CloseServiceHandle(sc_manager);
|
443 kumpf 1.1 }
|
444 kumpf 1.2
445 return(ccode);
|
446 kumpf 1.1 }
|