//%///////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2000, 2001, 2002 BMC Software, Hewlett-Packard Company, IBM, // The Open Group, Tivoli Systems // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // //============================================================================== // // Author: Mike Day (mdday@us.ibm.com) // // Modified By: Mary Hinton (m.hinton@verizon.net) // Sushma Fernandes (sushma_fernandes@hp.com) // Yi Zhou, Hewlett-Packard Company (yi_zhou@hp.com) // //%///////////////////////////////////////////////////////////////////////////// #include #include /* _beginthread, _endthread */ #include #include PEGASUS_USING_PEGASUS; PEGASUS_USING_STD; static DWORD dieNow = 0; String *runPath; CIMServer *server_windows; static SERVICE_STATUS pegasus_status; static SERVICE_STATUS_HANDLE pegasus_status_handle; VOID WINAPI cimserver_windows_main(int argc, char **argv) ; VOID WINAPI cimserver_service_start(DWORD, LPTSTR *); VOID WINAPI cimserver_service_ctrl_handler(DWORD ); DWORD cimserver_initialization(DWORD, LPTSTR *, DWORD *) ; void GetOptions( ConfigManager* cm, int& argc, char** argv, const String& pegasusHome); void cim_server_service(int argc, char **argv ) { cimserver_windows_main(argc, argv); exit(0); } int cimserver_fork( ) { return(0); } int cimserver_kill( ) { return(0); } Boolean isCIMServerRunning( ) { return(false); } // notify parent process to terminate so user knows that cimserver // is ready to serve CIM requests. If this plateform needs to implement // this functionality, please see sample implementation in cimserver_unix.cpp void notify_parent(void) { } static void __cdecl cimserver_windows_thread(void *parm) { // Get options (from command line and from configuration file); this // removes corresponding options and their arguments fromt he command // line. String pegasusHome; // mdh: need to get the environment for the Windows Service to run const char* tmp = getenv("PEGASUS_HOME"); if (tmp) { pegasusHome = tmp; } ConfigManager::setPegasusHome(pegasusHome); ConfigManager* configManager = ConfigManager::getInstance(); int dummy = 0; //String pegasusHome; try { GetOptions(configManager, dummy, NULL, pegasusHome); } catch (Exception&) { 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( configManager->getCurrentValue("enableHttpConnection"), "true"); Boolean enableHttpsConnection = String::equal( configManager->getCurrentValue("enableHttpsConnection"), "true"); if (!enableHttpConnection && !enableHttpsConnection) { Logger::put(Logger::STANDARD_LOG, "CIMServer", Logger::WARNING, "Neither HTTP nor HTTPS connection is enabled. " "CIMServer will not be started."); cerr << "Neither HTTP nor HTTPS connection is enabled. " "CIMServer will not be started." << endl; exit(1); } // Get the connection port configurations Uint32 portNumberHttps; Uint32 portNumberHttp; if (enableHttpsConnection) { String httpsPort = configManager->getCurrentValue("httpsPort"); CString portString = httpsPort.getCString(); char* end = 0; Uint32 port = strtol(portString, &end, 10); assert(end != 0 && *end == '\0'); // // Look up the WBEM-HTTPS port number // portNumberHttps = System::lookupPort(WBEM_HTTPS_SERVICE_NAME, port); } if (enableHttpConnection) { String httpPort = configManager->getCurrentValue("httpPort"); CString portString = httpPort.getCString(); char* end = 0; Uint32 port = strtol(portString, &end, 10); assert(end != 0 && *end == '\0'); // // Look up the WBEM-HTTP port number // portNumberHttp = System::lookupPort(WBEM_HTTP_SERVICE_NAME, port); } // Set up the Logger Logger::setHomeDirectory("./logs"); // Put server start message to the logger Logger::put(Logger::STANDARD_LOG, "CIMServer", Logger::INFORMATION, "Start $0 %1 $2 ", 88, 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 { Monitor monitor(true); CIMServer server(&monitor); server_windows = &server; if (enableHttpConnection) { server_windows->addAcceptor(false, portNumberHttp, false); Logger::put(Logger::STANDARD_LOG, "CIMServer", Logger::INFORMATION, "Listening on HTTP port $0.", portNumberHttp); } if (enableHttpsConnection) { server_windows->addAcceptor(false, portNumberHttps, true); Logger::put(Logger::STANDARD_LOG, "CIMServer", Logger::INFORMATION, "Listening on HTTPS port $0.", portNumberHttps); } server_windows->bind(); while(!server_windows->terminated()) { server_windows->runForever(); } } catch(Exception& e) { PEGASUS_STD(cerr) << "Error: " << e.getMessage() << PEGASUS_STD(endl); } _endthreadex(NULL); } ///////////////////////////////////////////////////////////////// // 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))) { ccode = GetLastError(); // Put server start message to the logger Logger::put(Logger::STANDARD_LOG, "CIMServer_Windows", Logger::INFORMATION, "Started as a Windows Service"); } return; } ///////////////////////////////////////////////////////////////// // // called by the NT service control manager to start the SLP service // ///////////////////////////////////////////////////////////////// VOID WINAPI cimserver_service_start(DWORD argc, LPTSTR *argv) { DWORD status; DWORD specificError; 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) { Logger::put(Logger::STANDARD_LOG, "CIMServer_Windows", Logger::INFORMATION, "Error installing service handler"); return; } // mdday -- I need to replace this hack with registry code // this is an ugly hack because we should really be getting this data // out of the registry. We are essentially forcing pegasus to be run // from its build tree. i.e.: // PEGASUS_HOME = binary_exe_path minus "\bin\cimserver.exe" // so if my build environment is in "c:\my-programs\pegasus\ // I will install the service binary path as "c:\my-programs\pegasus\bin\cimserver.exe" // 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 // 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))) { if(NULL != (service_handle = OpenService(sc_manager, "wmiserver", SERVICE_ALL_ACCESS))) { DWORD bytes_needed = 0; QUERY_SERVICE_CONFIG *svc_config = NULL; QueryServiceConfig(service_handle, svc_config, sizeof(svc_config), &bytes_needed); if(bytes_needed > 0) { if(NULL != ( svc_config = (QUERY_SERVICE_CONFIG *) malloc(bytes_needed))) { if(TRUE == QueryServiceConfig(service_handle, svc_config, bytes_needed, &bytes_needed)) { Uint32 position; runPath = new String(svc_config->lpBinaryPathName); if(PEG_NOT_FOUND != (position = runPath->reverseFind('\\'))) { Uint32 len = runPath->size(); runPath->remove(position, len - position); position = runPath->reverseFind('\\'); len = runPath->size(); runPath->remove(position, len - position); } } free(svc_config); } } CloseServiceHandle(service_handle); } CloseServiceHandle(sc_manager); } status = cimserver_initialization(argc, argv, &specificError); if(status < 0) { pegasus_status.dwCurrentState = SERVICE_STOPPED; 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(server_windows != NULL) server_windows->shutdown(); } return; } ///////////////////////////////////////////////////////////////// // ///////////////////////////////////////////////////////////////// VOID WINAPI cimserver_service_ctrl_handler(DWORD opcode) { switch(opcode) { case SERVICE_CONTROL_STOP: 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); return; } ///////////////////////////////////////////////////////////////// // ///////////////////////////////////////////////////////////////// DWORD cimserver_initialization(DWORD argc, LPTSTR *argv, DWORD *specificError) { return( _beginthread(cimserver_windows_thread, 0, NULL )); } ///////////////////////////////////////////////////////////////// // ///////////////////////////////////////////////////////////////// Uint32 cimserver_install_nt_service(String &pegasusHome) { SC_HANDLE service_handle, sc_manager; Uint32 ccode = 0; pegasusHome.append("\\bin\\wmiserver.exe"); CString pegHome = pegasusHome.getCString() ; LPCSTR path_name = (const char*) pegHome; 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, NULL))) { ccode = (Uint32)service_handle; } CloseServiceHandle(service_handle); } return(ccode); } ///////////////////////////////////////////////////////////////// // ///////////////////////////////////////////////////////////////// Uint32 cimserver_remove_nt_service(void) { SC_HANDLE service_handle, sc_manager; int ccode = 0; if(NULL != (sc_manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS))) { if(NULL != (service_handle = OpenService(sc_manager, "wmiserver", DELETE))) { DeleteService(service_handle); CloseServiceHandle(service_handle); ccode = 1; } CloseServiceHandle(sc_manager); } return(ccode); }