1 mike 1.7 //%/////////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (c) 2000, 2001 The Open group, BMC Software, Tivoli Systems, IBM
4 //
5 // Permission is hereby granted, free of charge, to any person obtaining a copy
6 // of this software and associated documentation files (the "Software"), to
7 // deal in the Software without restriction, including without limitation the
8 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9 // sell copies of the Software, and to permit persons to whom the Software is
10 // furnished to do so, subject to the following conditions:
11 //
12 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
13 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
14 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
15 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
16 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
17 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
18 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
19 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 //
21 //==============================================================================
22 mike 1.7 //
23 // Author: Mike Day (mdday@us.ibm.com)
24 //
|
25 mary 1.11 // Modified By: Mary Hinton (m.hinton@verizon.net)
|
26 kumpf 1.12 // Sushma Fernandes (sushma_fernandes@hp.com)
|
27 mike 1.7 //
28 //%/////////////////////////////////////////////////////////////////////////////
29
30 #include <windows.h>
31 #include <process.h> /* _beginthread, _endthread */
32 #include <tchar.h>
33 #include <direct.h>
34
35
36 PEGASUS_USING_PEGASUS;
37 PEGASUS_USING_STD;
38
39 static DWORD dieNow = 0;
40 String *runPath;
41 CIMServer *server_windows;
42 static SERVICE_STATUS pegasus_status;
43 static SERVICE_STATUS_HANDLE pegasus_status_handle;
44
45 VOID WINAPI cimserver_windows_main(int argc, char **argv) ;
46 VOID WINAPI cimserver_service_start(DWORD, LPTSTR *);
47 VOID WINAPI cimserver_service_ctrl_handler(DWORD );
48 mike 1.7 DWORD cimserver_initialization(DWORD, LPTSTR *, DWORD *) ;
49
50 void GetOptions(
|
51 mike 1.8 ConfigManager* cm,
|
52 mike 1.7 int& argc,
53 char** argv,
|
54 mike 1.8 const String& pegasusHome);
|
55 mike 1.7
56 void cim_server_service(int argc, char **argv ) { cimserver_windows_main(argc, argv); exit(0); }
57 int cimserver_fork( ) { return(0); }
58
59 static void __cdecl cimserver_windows_thread(void *parm)
60 {
61
62 // Get options (from command line and from configuration file); this
63 // removes corresponding options and their arguments fromt he command
64 // line.
65
|
66 mike 1.8 PEGASUS_TRACE;
67 ConfigManager* configManager = ConfigManager::getInstance();
|
68 mike 1.7 int dummy = 0;
69 String pegasusHome;
|
70 mike 1.8
71 PEGASUS_TRACE;
|
72 mike 1.7 try
73 {
|
74 mike 1.8 PEGASUS_TRACE;
75 GetOptions(configManager, dummy, NULL, pegasusHome);
76 PEGASUS_TRACE;
|
77 mike 1.7 }
78 catch (Exception&)
79 {
80 exit(1);
81 }
|
82 mike 1.8 PEGASUS_TRACE;
|
83 mike 1.7
|
84 mike 1.8 //
|
85 mike 1.7 // Check the trace options and set global variable
|
86 mike 1.8 //
|
87 mike 1.7 Boolean pegasusIOTrace = false;
|
88 mike 1.8
89 if (String::equal(configManager->getCurrentValue("trace"), "true"))
|
90 mike 1.7 {
|
91 mike 1.8 pegasusIOTrace = true;
|
92 mike 1.7 }
93
|
94 mike 1.8 //
95 // Check the log trace options and set global variable
96 //
|
97 mike 1.7 Boolean pegasusIOLog = false;
|
98 mike 1.8
99 if (String::equal(configManager->getCurrentValue("logtrace"), "true"))
|
100 mike 1.7 {
|
101 mike 1.8 pegasusIOLog = true;
|
102 mike 1.7 }
|
103 mike 1.8 Boolean useSSL = false;
104
105 if (String::equal(configManager->getCurrentValue("SSL"), "true"))
106 {
107 useSSL = true;
108 }
109
|
110 mary 1.13 // mdh: need to get the environment for the Windows Service to run
111 const char* tmp = getenv("PEGASUS_HOME");
112 if (tmp)
113 {
114 pegasusHome = tmp;
115 }
116 ConfigManager::setPegasusHome(pegasusHome);
117
|
118 mike 1.8 PEGASUS_TRACE;
|
119 mike 1.7
120 // Grab the port otpion:
121
|
122 mike 1.8 String portOption = configManager->getCurrentValue("port");
|
123 mike 1.7 char* address = portOption.allocateCString();
124
|
125 mike 1.8 PEGASUS_TRACE;
|
126 mike 1.7 // Set up the Logger
127 Logger::setHomeDirectory("./logs");
128
129 // Put server start message to the logger
130 Logger::put(Logger::STANDARD_LOG, "CIMServer", Logger::INFORMATION,
131 "Start $0 %1 port $2 $3 ", 88, PEGASUS_NAME, PEGASUS_VERSION,
132 address, (pegasusIOTrace ? " Tracing": " "));
133 // try loop to bind the address, and run the server
134 try
135 {
|
136 mike 1.8 PEGASUS_TRACE;
137 Monitor monitor;
|
138 mike 1.7
|
139 kumpf 1.12 CIMServer server(&monitor, useSSL);
|
140 mike 1.7 server_windows = &server;
|
141 mike 1.8
142 char* end = 0;
143 long portNumber = strtol(address, &end, 10);
144 assert(end != 0 && *end == '\0');
|
145 mary 1.10
|
146 mike 1.8 server_windows->bind(portNumber);
147
|
148 mike 1.7 delete [] address;
|
149 mary 1.10
150 while(!server_windows->terminated())
151 {
152 server_windows->runForever();
153 }
|
154 mike 1.8 PEGASUS_TRACE;
|
155 mike 1.7 }
156 catch(Exception& e)
157 {
158 PEGASUS_STD(cerr) << "Error: " << e.getMessage() << PEGASUS_STD(endl);
159 }
160
|
161 mike 1.8 PEGASUS_TRACE;
|
162 mike 1.7 _endthreadex(NULL);
163 }
164
165
166 /////////////////////////////////////////////////////////////////
167 // Windows NT Service Control Code
168 /////////////////////////////////////////////////////////////////
169
170
171
172
173 VOID WINAPI cimserver_windows_main(int argc, char **argv)
174 {
|
175 mike 1.8 PEGASUS_TRACE;
|
176 mike 1.7 int ccode;
177 SERVICE_TABLE_ENTRY dispatch_table[] =
178 {
179 {"cimserver", cimserver_service_start},
180 {NULL, NULL}
181 };
182
183 /* let everyone know we are running (or trying to run) as an NT service */
184 if(!(ccode = StartServiceCtrlDispatcher(dispatch_table)))
185 {
186 ccode = GetLastError();
187 // Put server start message to the logger
188 Logger::put(Logger::STANDARD_LOG, "CIMServer_Windows", Logger::INFORMATION,
189 "Started as a Windows Service");
190 }
191 return;
192 }
193
194 /////////////////////////////////////////////////////////////////
195 //
196 // called by the NT service control manager to start the SLP service
197 mike 1.7 //
198 /////////////////////////////////////////////////////////////////
199
200 VOID WINAPI cimserver_service_start(DWORD argc, LPTSTR *argv)
201 {
202
203 DWORD status;
204 DWORD specificError;
205 pegasus_status.dwServiceType = SERVICE_WIN32;
206 pegasus_status.dwCurrentState = SERVICE_START_PENDING;
207 pegasus_status.dwControlsAccepted
208 = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN ;
209 pegasus_status.dwWin32ExitCode = 0;
210 pegasus_status.dwServiceSpecificExitCode = 0;
211 pegasus_status.dwCheckPoint = 0;
212 pegasus_status.dwWaitHint = 0;
213
214 pegasus_status_handle = RegisterServiceCtrlHandler("cimserver", cimserver_service_ctrl_handler);
215 if( pegasus_status_handle == (SERVICE_STATUS_HANDLE)0)
216 {
217 Logger::put(Logger::STANDARD_LOG, "CIMServer_Windows", Logger::INFORMATION,
218 mike 1.7 "Error installing service handler");
219 return;
220 }
221
222 // mdday -- I need to replace this hack with registry code
223
224 // this is an ugly hack because we should really be getting this data
225 // out of the registry. We are essentially forcing pegasus to be run
226 // from its build tree. i.e.:
227 // PEGASUS_HOME = binary_exe_path minus "\bin\cimserver.exe"
228
229 // so if my build environment is in "c:\my-programs\pegasus\
230 // I will install the service binary path as "c:\my-programs\pegasus\bin\cimserver.exe"
231 // Therefore I will derive PEGASUS_HOME as "c:\my-programs\pegasus"
232
233 // If I do something wierd and run pegasus from "c:\winnt" then this hack will break
234 // the service will think its running but the CIMServer object will never have been instantiated.
235
236 SC_HANDLE service_handle, sc_manager;
237 if(NULL != (sc_manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS)))
238 {
239 mike 1.7 if(NULL != (service_handle = OpenService(sc_manager,
240 "cimserver",
241 SERVICE_ALL_ACCESS)))
242
243 {
244 DWORD bytes_needed = 0;
245 QUERY_SERVICE_CONFIG *svc_config = NULL;
246
247 QueryServiceConfig(service_handle, svc_config, sizeof(svc_config), &bytes_needed);
248 if(bytes_needed > 0)
249 {
250 if(NULL != ( svc_config = (QUERY_SERVICE_CONFIG *) malloc(bytes_needed)))
251 {
252 if(TRUE == QueryServiceConfig(service_handle, svc_config, bytes_needed, &bytes_needed))
253 {
254 Uint32 position;
255 runPath = new String(svc_config->lpBinaryPathName);
256 if(PEG_NOT_FOUND != (position = runPath->reverseFind('\\')))
257 {
258 Uint32 len = runPath->size();
259 runPath->remove(position, len - position);
260 mike 1.7 position = runPath->reverseFind('\\');
261 len = runPath->size();
262 runPath->remove(position, len - position);
263 }
264 }
265 free(svc_config);
266 }
267 }
268 CloseServiceHandle(service_handle);
269 }
270 CloseServiceHandle(sc_manager);
271 }
272
273 status = cimserver_initialization(argc, argv, &specificError);
274 if(status < 0)
275 {
276 pegasus_status.dwCurrentState = SERVICE_STOPPED;
277 pegasus_status.dwCheckPoint = 0;
278 pegasus_status.dwWaitHint = 0;
279 pegasus_status.dwWin32ExitCode = status;
280 pegasus_status.dwServiceSpecificExitCode = specificError;
281 mike 1.7 SetServiceStatus(pegasus_status_handle, &pegasus_status);
282 Logger::put(Logger::STANDARD_LOG, "CIMServer_Windows", Logger::INFORMATION,
283 "Error starting Cim Server");
284 return;
285 }
286
287 pegasus_status.dwCurrentState = SERVICE_RUNNING;
288 pegasus_status.dwCheckPoint = 0;
289 pegasus_status.dwWaitHint = 0;
290
291 if(!SetServiceStatus(pegasus_status_handle, &pegasus_status))
292 {
293 if(server_windows != NULL)
|
294 mike 1.8 server_windows->shutdown();
|
295 mike 1.7 }
296
297 return;
298 }
299
300 VOID WINAPI cimserver_service_ctrl_handler(DWORD opcode)
301 {
302
303 switch(opcode) {
304 case SERVICE_CONTROL_STOP:
305 case SERVICE_CONTROL_SHUTDOWN:
306 if(server_windows != NULL)
|
307 mike 1.8 server_windows->shutdown();
|
308 mike 1.7 pegasus_status.dwCurrentState = SERVICE_STOPPED;
309 pegasus_status.dwCheckPoint = 0;
310 pegasus_status.dwWaitHint = 0;
311 pegasus_status.dwWin32ExitCode = 0;
312 SetServiceStatus(pegasus_status_handle, &pegasus_status);
313 return;
314 break;
315 default:
316 break;
317 }
318 SetServiceStatus(pegasus_status_handle, &pegasus_status);
319 return;
320 }
321
322 DWORD cimserver_initialization(DWORD argc, LPTSTR *argv, DWORD *specificError)
323 {
324
325 return( _beginthread(cimserver_windows_thread, 0, NULL ));
326 }
327
328
329 mike 1.7 Uint32 cimserver_install_nt_service(String &pegasusHome )
330 {
331 SC_HANDLE service_handle, sc_manager;
332 Uint32 ccode = 0;
333 pegasusHome += "\\bin\\cimserver.exe";
334 LPCSTR path_name = pegasusHome.allocateCString() ;
335 if(NULL != (sc_manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS)))
336 {
337 if(NULL != (service_handle = CreateService(sc_manager,
338 "cimserver",
339 "Pegasus CIM Object Manager",
340 SERVICE_ALL_ACCESS,
341 SERVICE_WIN32_OWN_PROCESS,
342 SERVICE_DEMAND_START,
343 SERVICE_ERROR_NORMAL,
344 path_name,
345 NULL, NULL, NULL, NULL, NULL)))
346 {
347 ccode = (Uint32)service_handle;
348 }
349 CloseServiceHandle(service_handle);
350 mike 1.7 }
351
352 return(ccode);
353 }
354
355 Uint32 cimserver_remove_nt_service(void)
356 {
357
358 SC_HANDLE service_handle, sc_manager;
359 int ccode = 0;
360 if(NULL != (sc_manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS)))
361 {
362 if(NULL != (service_handle = OpenService(sc_manager, "cimserver", DELETE)))
363 {
364 DeleteService(service_handle);
365 CloseServiceHandle(service_handle);
366 ccode = 1;
367 }
368 CloseServiceHandle(sc_manager);
369 }
370 return(ccode);
371 mike 1.7 }
|