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 //
29 //%/////////////////////////////////////////////////////////////////////////////
30
31 #include <windows.h>
32 #include <process.h> /* _beginthread, _endthread */
33 #include <tchar.h>
34 #include <direct.h>
35
36
37 PEGASUS_USING_PEGASUS;
38 PEGASUS_USING_STD;
39
40 static DWORD dieNow = 0;
41 String *runPath;
42 CIMServer *server_windows;
43 kumpf 1.1 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
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 static void __cdecl cimserver_windows_thread(void *parm)
63 {
64 kumpf 1.1
65 // Get options (from command line and from configuration file); this
66 // removes corresponding options and their arguments fromt he command
67 // line.
68
69 ConfigManager* configManager = ConfigManager::getInstance();
70 int dummy = 0;
71 String pegasusHome;
72
73 try
74 {
75 GetOptions(configManager, dummy, NULL, pegasusHome);
76 }
77 catch (Exception&)
78 {
79 exit(1);
80 }
81
82 //
83 // Check the trace options and set global variable
84 //
85 kumpf 1.1 Boolean pegasusIOTrace = false;
86
87 if (String::equal(configManager->getCurrentValue("trace"), "true"))
88 {
89 pegasusIOTrace = true;
90 }
91
92 //
93 // Check the log trace options and set global variable
94 //
95 Boolean pegasusIOLog = false;
96
97 if (String::equal(configManager->getCurrentValue("logtrace"), "true"))
98 {
99 pegasusIOLog = true;
100 }
101 Boolean useSSL = false;
102
103 if (String::equal(configManager->getCurrentValue("SSL"), "true"))
104 {
105 useSSL = true;
106 kumpf 1.1 }
107
108 // mdh: need to get the environment for the Windows Service to run
109 const char* tmp = getenv("PEGASUS_HOME");
110 if (tmp)
111 {
112 pegasusHome = tmp;
113 }
114 ConfigManager::setPegasusHome(pegasusHome);
115
116 // Grab the port otpion:
117
118 String portOption;
119
120 if (useSSL)
121 {
122 portOption = configManager->getCurrentValue("httpsPort");
123 }
124 else
125 {
126 portOption = configManager->getCurrentValue("httpPort");
127 kumpf 1.1 }
128 CString address = portOption.getCString();
129
130 // Set up the Logger
131 Logger::setHomeDirectory("./logs");
132
133 // Put server start message to the logger
134 Logger::put(Logger::STANDARD_LOG, "CIMServer", Logger::INFORMATION,
135 "Start $0 %1 port $2 $3 ", 88, PEGASUS_NAME, PEGASUS_VERSION,
136 (const char*)address, (pegasusIOTrace ? " Tracing": " "));
137 // try loop to bind the address, and run the server
138 try
139 {
140 Monitor monitor;
141
142 CIMServer server(&monitor, useSSL);
143 server_windows = &server;
144
145 char* end = 0;
146 long portNumber = strtol(address, &end, 10);
147 assert(end != 0 && *end == '\0');
148 kumpf 1.1
149 server_windows->bind(portNumber);
150
151 while(!server_windows->terminated())
152 {
153 server_windows->runForever();
154 }
155 }
156 catch(Exception& e)
157 {
158 PEGASUS_STD(cerr) << "Error: " << e.getMessage() << PEGASUS_STD(endl);
159 }
160
161 _endthreadex(NULL);
162 }
163
164
165 /////////////////////////////////////////////////////////////////
166 // Windows NT Service Control Code
167 /////////////////////////////////////////////////////////////////
168
169 kumpf 1.1
170
171
172 VOID WINAPI cimserver_windows_main(int argc, char **argv)
173 {
174 int ccode;
175 SERVICE_TABLE_ENTRY dispatch_table[] =
176 {
177 {"cimserver", cimserver_service_start},
178 {NULL, NULL}
179 };
180
181 /* let everyone know we are running (or trying to run) as an NT service */
182 if(!(ccode = StartServiceCtrlDispatcher(dispatch_table)))
183 {
184 ccode = GetLastError();
185 // Put server start message to the logger
186 Logger::put(Logger::STANDARD_LOG, "CIMServer_Windows", Logger::INFORMATION,
187 "Started as a Windows Service");
188 }
189 return;
190 kumpf 1.1 }
191
192 /////////////////////////////////////////////////////////////////
193 //
194 // called by the NT service control manager to start the SLP service
195 //
196 /////////////////////////////////////////////////////////////////
197
198 VOID WINAPI cimserver_service_start(DWORD argc, LPTSTR *argv)
199 {
200
201 DWORD status;
202 DWORD specificError;
203 pegasus_status.dwServiceType = SERVICE_WIN32;
204 pegasus_status.dwCurrentState = SERVICE_START_PENDING;
205 pegasus_status.dwControlsAccepted
206 = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN ;
207 pegasus_status.dwWin32ExitCode = 0;
208 pegasus_status.dwServiceSpecificExitCode = 0;
209 pegasus_status.dwCheckPoint = 0;
210 pegasus_status.dwWaitHint = 0;
211 kumpf 1.1
212 pegasus_status_handle = RegisterServiceCtrlHandler("cimserver", cimserver_service_ctrl_handler);
213 if( pegasus_status_handle == (SERVICE_STATUS_HANDLE)0)
214 {
215 Logger::put(Logger::STANDARD_LOG, "CIMServer_Windows", Logger::INFORMATION,
216 "Error installing service handler");
217 return;
218 }
219
220 // mdday -- I need to replace this hack with registry code
221
222 // this is an ugly hack because we should really be getting this data
223 // out of the registry. We are essentially forcing pegasus to be run
224 // from its build tree. i.e.:
225 // PEGASUS_HOME = binary_exe_path minus "\bin\cimserver.exe"
226
227 // so if my build environment is in "c:\my-programs\pegasus\
228 // I will install the service binary path as "c:\my-programs\pegasus\bin\cimserver.exe"
229 // Therefore I will derive PEGASUS_HOME as "c:\my-programs\pegasus"
230
231 // If I do something wierd and run pegasus from "c:\winnt" then this hack will break
232 kumpf 1.1 // the service will think its running but the CIMServer object will never have been instantiated.
233
234 SC_HANDLE service_handle, sc_manager;
235 if(NULL != (sc_manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS)))
236 {
237 if(NULL != (service_handle = OpenService(sc_manager,
238 "cimserver",
239 SERVICE_ALL_ACCESS)))
240
241 {
242 DWORD bytes_needed = 0;
243 QUERY_SERVICE_CONFIG *svc_config = NULL;
244
245 QueryServiceConfig(service_handle, svc_config, sizeof(svc_config), &bytes_needed);
246 if(bytes_needed > 0)
247 {
248 if(NULL != ( svc_config = (QUERY_SERVICE_CONFIG *) malloc(bytes_needed)))
249 {
250 if(TRUE == QueryServiceConfig(service_handle, svc_config, bytes_needed, &bytes_needed))
251 {
252 Uint32 position;
253 kumpf 1.1 runPath = new String(svc_config->lpBinaryPathName);
254 if(PEG_NOT_FOUND != (position = runPath->reverseFind('\\')))
255 {
256 Uint32 len = runPath->size();
257 runPath->remove(position, len - position);
258 position = runPath->reverseFind('\\');
259 len = runPath->size();
260 runPath->remove(position, len - position);
261 }
262 }
263 free(svc_config);
264 }
265 }
266 CloseServiceHandle(service_handle);
267 }
268 CloseServiceHandle(sc_manager);
269 }
270
271 status = cimserver_initialization(argc, argv, &specificError);
272 if(status < 0)
273 {
274 kumpf 1.1 pegasus_status.dwCurrentState = SERVICE_STOPPED;
275 pegasus_status.dwCheckPoint = 0;
276 pegasus_status.dwWaitHint = 0;
277 pegasus_status.dwWin32ExitCode = status;
278 pegasus_status.dwServiceSpecificExitCode = specificError;
279 SetServiceStatus(pegasus_status_handle, &pegasus_status);
280 Logger::put(Logger::STANDARD_LOG, "CIMServer_Windows", Logger::INFORMATION,
281 "Error starting Cim Server");
282 return;
283 }
284
285 pegasus_status.dwCurrentState = SERVICE_RUNNING;
286 pegasus_status.dwCheckPoint = 0;
287 pegasus_status.dwWaitHint = 0;
288
289 if(!SetServiceStatus(pegasus_status_handle, &pegasus_status))
290 {
291 if(server_windows != NULL)
292 server_windows->shutdown();
293 }
294
295 kumpf 1.1 return;
296 }
297
298 VOID WINAPI cimserver_service_ctrl_handler(DWORD opcode)
299 {
300
301 switch(opcode) {
302 case SERVICE_CONTROL_STOP:
303 case SERVICE_CONTROL_SHUTDOWN:
304 if(server_windows != NULL)
305 server_windows->shutdown();
306 pegasus_status.dwCurrentState = SERVICE_STOPPED;
307 pegasus_status.dwCheckPoint = 0;
308 pegasus_status.dwWaitHint = 0;
309 pegasus_status.dwWin32ExitCode = 0;
310 SetServiceStatus(pegasus_status_handle, &pegasus_status);
311 return;
312 break;
313 default:
314 break;
315 }
316 kumpf 1.1 SetServiceStatus(pegasus_status_handle, &pegasus_status);
317 return;
318 }
319
320 DWORD cimserver_initialization(DWORD argc, LPTSTR *argv, DWORD *specificError)
321 {
322
323 return( _beginthread(cimserver_windows_thread, 0, NULL ));
324 }
325
326
327 Uint32 cimserver_install_nt_service(String &pegasusHome )
328 {
329 SC_HANDLE service_handle, sc_manager;
330 Uint32 ccode = 0;
331 pegasusHome.append("\\bin\\cimserver.exe");
332 CString pegHome = pegasusHome.getCString() ;
333 LPCSTR path_name = (const char*) pegHome;
334 if(NULL != (sc_manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS)))
335 {
336 if(NULL != (service_handle = CreateService(sc_manager,
337 kumpf 1.1 "cimserver",
338 "Pegasus CIM Object Manager",
339 SERVICE_ALL_ACCESS,
340 SERVICE_WIN32_OWN_PROCESS,
341 SERVICE_DEMAND_START,
342 SERVICE_ERROR_NORMAL,
343 path_name,
344 NULL, NULL, NULL, NULL, NULL)))
345 {
346 ccode = (Uint32)service_handle;
347 }
348 CloseServiceHandle(service_handle);
349 }
350
351 return(ccode);
352 }
353
354 Uint32 cimserver_remove_nt_service(void)
355 {
356
357 SC_HANDLE service_handle, sc_manager;
358 kumpf 1.1 int ccode = 0;
359 if(NULL != (sc_manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS)))
360 {
361 if(NULL != (service_handle = OpenService(sc_manager, "cimserver", DELETE)))
362 {
363 DeleteService(service_handle);
364 CloseServiceHandle(service_handle);
365 ccode = 1;
366 }
367 CloseServiceHandle(sc_manager);
368 }
369 return(ccode);
370 }
|