version 1.2, 2003/08/15 22:45:40
|
version 1.3, 2003/09/11 18:50:28
|
|
|
// Modified By: Mary Hinton (m.hinton@verizon.net) | // Modified By: Mary Hinton (m.hinton@verizon.net) |
// Sushma Fernandes (sushma_fernandes@hp.com) | // Sushma Fernandes (sushma_fernandes@hp.com) |
// Yi Zhou, Hewlett-Packard Company (yi_zhou@hp.com) | // Yi Zhou, Hewlett-Packard Company (yi_zhou@hp.com) |
|
// Tony Fiorentino (fiorentino_tony@emc.com) |
|
// Roger Kumpf, Hewlett-Packard Company (roger_kumpf@hp.com) |
|
// Jair Santos, Hewlett-Packard Company (jair.santos@hp.com) |
// | // |
//%///////////////////////////////////////////////////////////////////////////// | //%///////////////////////////////////////////////////////////////////////////// |
| |
|
|
#include <tchar.h> | #include <tchar.h> |
#include <direct.h> | #include <direct.h> |
| |
|
#include "service.cpp" |
|
|
PEGASUS_USING_PEGASUS; | PEGASUS_USING_PEGASUS; |
PEGASUS_USING_STD; | PEGASUS_USING_STD; |
| |
static DWORD dieNow = 0; |
//------------------------------------------------------------------------- |
String *runPath; |
// DEFINES |
|
//------------------------------------------------------------------------- |
|
#define PEGASUS_SERVICE_NAME "wmiserver" |
|
#define PEGASUS_DISPLAY_NAME "Pegasus WMI Mapper" |
|
#define PEGASUS_DESCRIPTION "Pegasus WBEM to WMI Mapper Manager Service" |
|
|
|
//------------------------------------------------------------------------- |
|
// GLOBALS |
|
//------------------------------------------------------------------------- |
CIMServer *server_windows; | CIMServer *server_windows; |
static SERVICE_STATUS pegasus_status; |
static Service pegasus_service(PEGASUS_SERVICE_NAME); |
static SERVICE_STATUS_HANDLE pegasus_status_handle; |
static HANDLE pegasus_service_event; |
|
static LPCSTR g_cimservice_key = TEXT("SYSTEM\\CurrentControlSet\\Services\\%s"); |
VOID WINAPI cimserver_windows_main(int argc, char **argv) ; |
static LPCSTR g_cimservice_home = TEXT("home"); |
VOID WINAPI cimserver_service_start(DWORD, LPTSTR *); |
|
VOID WINAPI cimserver_service_ctrl_handler(DWORD ); |
//------------------------------------------------------------------------- |
DWORD cimserver_initialization(DWORD, LPTSTR *, DWORD *) ; |
// PROTOTYPES |
|
//------------------------------------------------------------------------- |
void GetOptions( |
int cimserver_windows_main(int flag, int argc, char **argv); |
ConfigManager* cm, |
extern void GetOptions(ConfigManager *cm, |
int& argc, | int& argc, |
char** argv, | char** argv, |
const String& pegasusHome); | const String& pegasusHome); |
|
static bool _getRegInfo(const char *lpchKeyword, char *lpchRetValue); |
void cim_server_service(int argc, char **argv ) { cimserver_windows_main(argc, argv); exit(0); } |
static bool _setRegInfo(const char *lpchKeyword, const char *lpchValue); |
int cimserver_fork( ) { return(0); } |
void setHome(String & home); |
int cimserver_kill( ) { return(0); } |
|
Boolean isCIMServerRunning( ) { return(false); } |
//------------------------------------------------------------------------- |
|
// NO-OPs for windows platform |
// notify parent process to terminate so user knows that cimserver |
//------------------------------------------------------------------------- |
// is ready to serve CIM requests. If this plateform needs to implement |
int cimserver_fork(void) { return(0); } |
// this functionality, please see sample implementation in cimserver_unix.cpp |
int cimserver_kill(void) { return(0); } |
void notify_parent(void) |
void notify_parent(int id) { return; } |
{ |
|
} |
//------------------------------------------------------------------------- |
|
// START MONITOR Asynchronously |
|
//------------------------------------------------------------------------- |
static void __cdecl cimserver_windows_thread(void *parm) | static void __cdecl cimserver_windows_thread(void *parm) |
{ | { |
| |
|
|
| |
String pegasusHome; | String pegasusHome; |
| |
// mdh: need to get the environment for the Windows Service to run |
// Windows way to set home |
const char* tmp = getenv("PEGASUS_HOME"); |
setHome(pegasusHome); |
if (tmp) |
|
{ |
|
pegasusHome = tmp; |
|
} |
|
| |
ConfigManager::setPegasusHome(pegasusHome); | ConfigManager::setPegasusHome(pegasusHome); |
| |
ConfigManager* configManager = ConfigManager::getInstance(); | ConfigManager* configManager = ConfigManager::getInstance(); |
int dummy = 0; | int dummy = 0; |
//String pegasusHome; |
|
| |
try | try |
{ | { |
|
|
exit(1); | exit(1); |
} | } |
| |
// |
|
// Check the trace options and set global variable |
|
// |
|
Boolean pegasusIOTrace = false; |
|
|
|
if (String::equal(configManager->getCurrentValue("trace"), "true")) |
|
{ |
|
pegasusIOTrace = true; |
|
} |
|
|
|
// |
|
// Check the log trace options and set global variable |
|
// |
|
Boolean pegasusIOLog = false; |
|
|
|
if (String::equal(configManager->getCurrentValue("logtrace"), "true")) |
|
{ |
|
pegasusIOLog = true; |
|
} |
|
|
|
// The "SSL" property overrides the enableHttp*Connection properties and |
|
// enables only the HTTPS connection. |
|
Boolean enableHttpConnection = String::equal( | Boolean enableHttpConnection = String::equal( |
configManager->getCurrentValue("enableHttpConnection"), "true"); | configManager->getCurrentValue("enableHttpConnection"), "true"); |
|
|
Boolean enableHttpsConnection = String::equal( | Boolean enableHttpsConnection = String::equal( |
configManager->getCurrentValue("enableHttpsConnection"), "true"); | configManager->getCurrentValue("enableHttpsConnection"), "true"); |
| |
|
|
} | } |
| |
// Set up the Logger | // Set up the Logger |
Logger::setHomeDirectory("./logs"); |
String logsDirectory = String::EMPTY; |
|
logsDirectory = configManager->getCurrentValue("logdir"); |
|
logsDirectory = ConfigManager::getHomedPath(configManager->getCurrentValue("logdir")); |
|
|
|
Logger::setHomeDirectory(logsDirectory); |
| |
// Put server start message to the logger | // Put server start message to the logger |
Logger::put(Logger::STANDARD_LOG, "CIMServer", Logger::INFORMATION, |
Logger::put(Logger::STANDARD_LOG, PEGASUS_SERVICE_NAME, Logger::INFORMATION, |
"Start $0 %1 $2 ", 88, PEGASUS_NAME, PEGASUS_VERSION, |
"Started $0 version $1.", PEGASUS_NAME, PEGASUS_VERSION); |
(pegasusIOTrace ? " Tracing": " ")); |
|
// ATTN: Should this really be: ? |
|
//Logger::put(Logger::STANDARD_LOG, "CIMServer", Logger::INFORMATION, |
|
// "Started $0 version $1.", PEGASUS_NAME, PEGASUS_VERSION); |
|
| |
// try loop to bind the address, and run the server | // try loop to bind the address, and run the server |
try | try |
|
|
} | } |
| |
| |
///////////////////////////////////////////////////////////////// |
//------------------------------------------------------------------------- |
// Windows NT Service Control Code | // Windows NT Service Control Code |
///////////////////////////////////////////////////////////////// |
//------------------------------------------------------------------------- |
VOID WINAPI cimserver_windows_main(int argc, char **argv) |
|
{ |
|
int ccode; |
|
SERVICE_TABLE_ENTRY dispatch_table[] = |
|
{ |
|
{"wmiserver", cimserver_service_start}, |
|
{NULL, NULL} |
|
}; |
|
| |
/* let everyone know we are running (or trying to run) as an NT service */ |
//------------------------------------------------------------------------- |
if(!(ccode = StartServiceCtrlDispatcher(dispatch_table))) |
// SERVICE (no parameters) |
|
//------------------------------------------------------------------------- |
|
void cim_server_service(int argc, char **argv) |
{ | { |
ccode = GetLastError(); |
Service::ReturnCode status = Service::SERVICE_RETURN_SUCCESS; |
// Put server start message to the logger |
char console_title[_MAX_PATH] = {0}; |
Logger::put(Logger::STANDARD_LOG, "CIMServer_Windows", Logger::INFORMATION, |
|
"Started as a Windows Service"); |
|
} |
|
| |
|
// Check if running from a console window |
|
if (GetConsoleTitle(console_title, _MAX_PATH) > 0) |
return; | return; |
} |
|
| |
///////////////////////////////////////////////////////////////// |
pegasus_service_event = CreateEvent(NULL, FALSE, FALSE, NULL); |
// |
|
// called by the NT service control manager to start the SLP service |
|
// |
|
///////////////////////////////////////////////////////////////// |
|
VOID WINAPI cimserver_service_start(DWORD argc, LPTSTR *argv) |
|
{ |
|
| |
DWORD status; |
// Run should exit the process if a service |
DWORD specificError; |
status = pegasus_service.Run(cimserver_windows_main); |
pegasus_status.dwServiceType = SERVICE_WIN32; |
|
pegasus_status.dwCurrentState = SERVICE_START_PENDING; |
|
pegasus_status.dwControlsAccepted |
|
= SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN ; |
|
pegasus_status.dwWin32ExitCode = 0; |
|
pegasus_status.dwServiceSpecificExitCode = 0; |
|
pegasus_status.dwCheckPoint = 0; |
|
pegasus_status.dwWaitHint = 0; |
|
pegasus_status_handle = RegisterServiceCtrlHandler("wmiserver", cimserver_service_ctrl_handler); |
|
| |
if(pegasus_status_handle == (SERVICE_STATUS_HANDLE)0) |
// If we made it here there was a problem starting this process as a service |
{ |
// Log the problem to the log file |
Logger::put(Logger::STANDARD_LOG, "CIMServer_Windows", Logger::INFORMATION, |
|
"Error installing service handler"); |
// TODO: log or echo something here |
return; |
|
} | } |
| |
// mdday -- I need to replace this hack with registry code |
//------------------------------------------------------------------------- |
|
// START/STOP handler |
|
//------------------------------------------------------------------------- |
|
int cimserver_windows_main(int flag, int argc, char *argv[]) |
|
{ |
|
switch (flag) |
|
{ |
|
case Service::STARTUP_FLAG: |
|
if (_beginthread(cimserver_windows_thread, 0, NULL)) |
|
WaitForSingleObject(pegasus_service_event, INFINITE); |
|
break; |
| |
// this is an ugly hack because we should really be getting this data |
case Service::SHUTDOWN_FLAG: |
// out of the registry. We are essentially forcing pegasus to be run |
SetEvent(pegasus_service_event); |
// from its build tree. i.e.: |
break; |
// PEGASUS_HOME = binary_exe_path minus "\bin\cimserver.exe" |
|
| |
// so if my build environment is in "c:\my-programs\pegasus\ |
default: |
// I will install the service binary path as "c:\my-programs\pegasus\bin\cimserver.exe" |
break; |
// Therefore I will derive PEGASUS_HOME as "c:\my-programs\pegasus" |
} |
| |
// If I do something wierd and run pegasus from "c:\winnt" then this hack will break |
return 0; |
// the service will think its running but the CIMServer object will never have been instantiated. |
} |
| |
SC_HANDLE service_handle, sc_manager; |
//------------------------------------------------------------------------- |
if(NULL != (sc_manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS))) |
// IS RUNNING? |
|
//------------------------------------------------------------------------- |
|
Boolean isCIMServerRunning(void) |
{ | { |
if(NULL != (service_handle = OpenService(sc_manager, |
Service::State state; |
"wmiserver", |
pegasus_service.GetState(&state); |
SERVICE_ALL_ACCESS))) |
|
| |
{ |
return (state == Service::SERVICE_STATE_RUNNING) ? true : false; |
DWORD bytes_needed = 0; |
} |
QUERY_SERVICE_CONFIG *svc_config = NULL; |
|
| |
QueryServiceConfig(service_handle, svc_config, sizeof(svc_config), &bytes_needed); |
//------------------------------------------------------------------------- |
if(bytes_needed > 0) |
// INSTALL |
{ |
//------------------------------------------------------------------------- |
if(NULL != ( svc_config = (QUERY_SERVICE_CONFIG *) malloc(bytes_needed))) |
bool cimserver_install_nt_service(char *service_name) |
{ | { |
if(TRUE == QueryServiceConfig(service_handle, svc_config, bytes_needed, &bytes_needed)) |
Service::ReturnCode status = Service::SERVICE_RETURN_SUCCESS; |
{ |
char filename[_MAX_PATH] = {0}; |
Uint32 position; |
char displayname[_MAX_PATH] = {0}; |
runPath = new String(svc_config->lpBinaryPathName); |
|
if(PEG_NOT_FOUND != (position = runPath->reverseFind('\\'))) |
// If service name is specified, override default |
|
if (service_name == NULL) |
{ | { |
Uint32 len = runPath->size(); |
strcpy(displayname, PEGASUS_DISPLAY_NAME); |
runPath->remove(position, len - position); |
|
position = runPath->reverseFind('\\'); |
|
len = runPath->size(); |
|
runPath->remove(position, len - position); |
|
} | } |
|
else |
|
{ |
|
pegasus_service.SetServiceName(service_name); |
|
sprintf(displayname, "%s - %s", PEGASUS_DISPLAY_NAME, service_name); |
} | } |
| |
free(svc_config); |
GetModuleFileName(NULL, filename, sizeof(filename)); |
} |
status = pegasus_service.Install(displayname, PEGASUS_DESCRIPTION, filename); |
} |
|
| |
CloseServiceHandle(service_handle); |
// Upon success, set home in registry |
|
if (status == Service::SERVICE_RETURN_SUCCESS) |
|
{ |
|
char pegasus_homepath[_MAX_PATH]; |
|
System::extract_file_path(filename, pegasus_homepath); |
|
pegasus_homepath[strlen(pegasus_homepath)-1] = '\0'; |
|
strcpy(filename, pegasus_homepath); |
|
System::extract_file_path(filename, pegasus_homepath); |
|
pegasus_homepath[strlen(pegasus_homepath)-1] = '\0'; |
|
_setRegInfo(g_cimservice_home, pegasus_homepath); |
} | } |
| |
CloseServiceHandle(sc_manager); |
return (status == Service::SERVICE_RETURN_SUCCESS) ? true : false; |
} | } |
| |
status = cimserver_initialization(argc, argv, &specificError); |
//------------------------------------------------------------------------- |
if(status < 0) |
// REMOVE |
|
//------------------------------------------------------------------------- |
|
bool cimserver_remove_nt_service(char *service_name) |
{ | { |
pegasus_status.dwCurrentState = SERVICE_STOPPED; |
Service::ReturnCode status = Service::SERVICE_RETURN_SUCCESS; |
pegasus_status.dwCheckPoint = 0; |
|
pegasus_status.dwWaitHint = 0; |
|
pegasus_status.dwWin32ExitCode = status; |
|
pegasus_status.dwServiceSpecificExitCode = specificError; |
|
SetServiceStatus(pegasus_status_handle, &pegasus_status); |
|
Logger::put(Logger::STANDARD_LOG, "CIMServer_Windows", Logger::INFORMATION, |
|
"Error starting Cim Server"); |
|
return; |
|
} |
|
|
|
pegasus_status.dwCurrentState = SERVICE_RUNNING; |
|
pegasus_status.dwCheckPoint = 0; |
|
pegasus_status.dwWaitHint = 0; |
|
| |
if(!SetServiceStatus(pegasus_status_handle, &pegasus_status)) |
// If service name is specified, override default |
|
if (service_name != NULL) |
{ | { |
if(server_windows != NULL) |
pegasus_service.SetServiceName(service_name); |
server_windows->shutdown(); |
|
} | } |
| |
return; |
status = pegasus_service.Remove(); |
|
|
|
return (status == Service::SERVICE_RETURN_SUCCESS) ? true : false; |
} | } |
| |
///////////////////////////////////////////////////////////////// |
//------------------------------------------------------------------------- |
// |
// START |
///////////////////////////////////////////////////////////////// |
//------------------------------------------------------------------------- |
VOID WINAPI cimserver_service_ctrl_handler(DWORD opcode) |
bool cimserver_start_nt_service(char *service_name) |
{ | { |
switch(opcode) |
Service::ReturnCode status = Service::SERVICE_RETURN_SUCCESS; |
|
|
|
// If service name is specified, override default |
|
if (service_name != NULL) |
{ | { |
case SERVICE_CONTROL_STOP: |
pegasus_service.SetServiceName(service_name); |
case SERVICE_CONTROL_SHUTDOWN: |
|
if(server_windows != NULL) |
|
server_windows->shutdown(); |
|
pegasus_status.dwCurrentState = SERVICE_STOPPED; |
|
pegasus_status.dwCheckPoint = 0; |
|
pegasus_status.dwWaitHint = 0; |
|
pegasus_status.dwWin32ExitCode = 0; |
|
SetServiceStatus(pegasus_status_handle, &pegasus_status); |
|
return; |
|
break; |
|
default: |
|
break; |
|
} | } |
| |
SetServiceStatus(pegasus_status_handle, &pegasus_status); |
status = pegasus_service.Start(5); |
| |
return; |
return (status == Service::SERVICE_RETURN_SUCCESS) ? true : false; |
} | } |
| |
///////////////////////////////////////////////////////////////// |
//------------------------------------------------------------------------- |
// |
// STOP |
///////////////////////////////////////////////////////////////// |
//------------------------------------------------------------------------- |
DWORD cimserver_initialization(DWORD argc, LPTSTR *argv, DWORD *specificError) |
bool cimserver_stop_nt_service(char *service_name) |
{ | { |
return( _beginthread(cimserver_windows_thread, 0, NULL )); |
Service::ReturnCode status = Service::SERVICE_RETURN_SUCCESS; |
|
|
|
// If service name is specified, override default |
|
if (service_name != NULL) |
|
{ |
|
pegasus_service.SetServiceName(service_name); |
} | } |
| |
///////////////////////////////////////////////////////////////// |
status = pegasus_service.Stop(5); |
// |
|
///////////////////////////////////////////////////////////////// |
return (status == Service::SERVICE_RETURN_SUCCESS) ? true : false; |
Uint32 cimserver_install_nt_service(String &pegasusHome) |
} |
|
|
|
//------------------------------------------------------------------------- |
|
// HELPER Utilities |
|
//------------------------------------------------------------------------- |
|
static bool _getRegInfo(const char *lpchKeyword, char *lpchRetValue) |
{ | { |
SC_HANDLE service_handle, sc_manager; |
HKEY hKey; |
Uint32 ccode = 0; |
DWORD dw = _MAX_PATH; |
|
char subKey[_MAX_PATH] = {0}; |
|
|
|
sprintf(subKey, g_cimservice_key, pegasus_service.GetServiceName()); |
| |
pegasusHome.append("\\bin\\wmiserver.exe"); |
if ((RegOpenKeyEx(HKEY_LOCAL_MACHINE, |
|
subKey, |
|
0, |
|
KEY_READ, |
|
&hKey)) != ERROR_SUCCESS) |
|
{ |
|
return false; |
|
} |
| |
CString pegHome = pegasusHome.getCString() ; |
if ((RegQueryValueEx(hKey, |
LPCSTR path_name = (const char*) pegHome; |
lpchKeyword, |
|
|
if(NULL != (sc_manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS))) |
|
{ |
|
if(NULL != (service_handle = CreateService(sc_manager, |
|
"wmiserver", |
|
"Pegasus WMI Mapper", |
|
SERVICE_ALL_ACCESS, |
|
SERVICE_WIN32_OWN_PROCESS, |
|
SERVICE_DEMAND_START, |
|
SERVICE_ERROR_NORMAL, |
|
path_name, |
|
NULL, | NULL, |
NULL, | NULL, |
|
(LPBYTE)lpchRetValue, |
|
&dw)) != ERROR_SUCCESS) |
|
{ |
|
RegCloseKey(hKey); |
|
return false; |
|
} |
|
|
|
RegCloseKey(hKey); |
|
|
|
return true; |
|
} |
|
|
|
static bool _setRegInfo(const char *lpchKeyword, const char *lpchValue) |
|
{ |
|
HKEY hKey; |
|
DWORD dw = _MAX_PATH; |
|
char home_key[_MAX_PATH] = {0}; |
|
char subKey[_MAX_PATH] = {0}; |
|
|
|
if (lpchKeyword == NULL || lpchValue == NULL) |
|
return false; |
|
|
|
sprintf(subKey, g_cimservice_key, pegasus_service.GetServiceName()); |
|
|
|
if ((RegCreateKeyEx (HKEY_LOCAL_MACHINE, |
|
subKey, |
|
0, |
NULL, | NULL, |
|
0, |
|
KEY_ALL_ACCESS, |
NULL, | NULL, |
NULL))) |
&hKey, |
|
NULL) != ERROR_SUCCESS)) |
{ | { |
ccode = (Uint32)service_handle; |
return false; |
} | } |
| |
CloseServiceHandle(service_handle); |
if ((RegSetValueEx(hKey, |
|
lpchKeyword, |
|
0, |
|
REG_SZ, |
|
(CONST BYTE *)lpchValue, |
|
(DWORD)(strlen(lpchValue)+1))) != ERROR_SUCCESS) |
|
{ |
|
RegCloseKey(hKey); |
|
return false; |
} | } |
| |
return(ccode); |
RegCloseKey(hKey); |
|
|
|
return true; |
} | } |
| |
///////////////////////////////////////////////////////////////// |
void setHome(String & home) |
// |
|
///////////////////////////////////////////////////////////////// |
|
Uint32 cimserver_remove_nt_service(void) |
|
{ | { |
|
// Determine the absolute path to the running program |
|
char exe_pathname[_MAX_PATH] = {0}; |
|
char home_pathname[_MAX_PATH] = {0}; |
|
GetModuleFileName(NULL, exe_pathname, sizeof(exe_pathname)); |
| |
SC_HANDLE service_handle, sc_manager; |
// Pegasus home search rules: |
int ccode = 0; |
// - look in registry (if set) |
|
// - if not found, look in PEGASUS_HOME (if set) |
|
// - if not found, use exe directory minus one level |
| |
if(NULL != (sc_manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS))) |
bool found_reg = _getRegInfo("home", home_pathname); |
|
if (found_reg == true) |
{ | { |
if(NULL != (service_handle = OpenService(sc_manager, "wmiserver", DELETE))) |
// Make sure home matches |
|
String current_home(home_pathname); |
|
String current_exe(exe_pathname); |
|
current_home.toLower(); |
|
current_exe.toLower(); |
|
|
|
Uint32 pos = current_exe.find(current_home); |
|
if (pos != PEG_NOT_FOUND) |
{ | { |
DeleteService(service_handle); |
home = home_pathname; |
CloseServiceHandle(service_handle); |
} |
ccode = 1; |
else |
|
{ |
|
found_reg = false; |
|
} |
|
} |
|
if (found_reg == false) |
|
{ |
|
const char* tmp = getenv("PEGASUS_HOME"); |
|
if (tmp) |
|
{ |
|
home = tmp; |
|
} |
|
else |
|
{ |
|
// ASSUMPTION: At a minimum, the cimserver program is running |
|
// from a "bin" directory |
|
home = FileSystem::extractFilePath(exe_pathname); |
|
home.remove(home.size()-1, 1); |
|
home = FileSystem::extractFilePath(home); |
|
home.remove(home.size()-1, 1); |
} | } |
|
|
CloseServiceHandle(sc_manager); |
|
} | } |
|
|
return(ccode); |
|
} | } |