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