summaryrefslogtreecommitdiff
path: root/cpp/src/Ice/Service.cpp
diff options
context:
space:
mode:
authorMatthew Newhook <matthew@zeroc.com>2007-02-28 09:49:22 +0000
committerMatthew Newhook <matthew@zeroc.com>2007-02-28 09:49:22 +0000
commit6b880991ccad39ab5189558c99016add754fea4a (patch)
tree2bb643f7dffef7dda5f1b92539330b61cecf459a /cpp/src/Ice/Service.cpp
parentFixed bug 1952 (diff)
downloadice-6b880991ccad39ab5189558c99016add754fea4a.tar.bz2
ice-6b880991ccad39ab5189558c99016add754fea4a.tar.xz
ice-6b880991ccad39ab5189558c99016add754fea4a.zip
http://bugzilla.zeroc.com/bugzilla/show_bug.cgi?id=1722,
http://bugzilla.zeroc.com/bugzilla/show_bug.cgi?id=1721, http://bugzilla.zeroc.com/bugzilla/show_bug.cgi?id=1926
Diffstat (limited to 'cpp/src/Ice/Service.cpp')
-rwxr-xr-xcpp/src/Ice/Service.cpp353
1 files changed, 272 insertions, 81 deletions
diff --git a/cpp/src/Ice/Service.cpp b/cpp/src/Ice/Service.cpp
index a5690ba166c..75277c7cf62 100755
--- a/cpp/src/Ice/Service.cpp
+++ b/cpp/src/Ice/Service.cpp
@@ -21,7 +21,7 @@
#ifdef _WIN32
# include <winsock2.h>
-# include <Ice/EventLoggerI.h>
+# include <Ice/EventLoggerMsg.h>
#else
# include <Ice/Logger.h>
# include <Ice/Network.h>
@@ -32,6 +32,7 @@
#endif
using namespace std;
+using namespace Ice;
Ice::Service* Ice::Service::_instance = 0;
static IceUtil::CtrlCHandler* _ctrlCHandler = 0;
@@ -71,7 +72,7 @@ Ice_Service_CtrlHandler(DWORD ctrl)
service->control(ctrl);
}
-namespace Ice
+namespace
{
class ServiceStatusManager : public IceUtil::Monitor<IceUtil::Mutex>
@@ -130,9 +131,180 @@ private:
bool _stopped;
};
-}
+static ServiceStatusManager* serviceStatusManager;
+
+static IceUtil::StaticMutex outputMutex = ICE_STATIC_MUTEX_INITIALIZER;
+
+class SMEventLoggerI : public Ice::Logger
+{
+ static string
+ mangleService(string name)
+ {
+ //
+ // The application name cannot contain backslashes.
+ //
+ string::size_type pos = 0;
+ while((pos = name.find('\\', pos)) != string::npos)
+ {
+ name[pos] = '/';
+ }
+ return name;
+ }
+
+ static string
+ createKey(string name)
+ {
+ //
+ // The registry key is:
+ //
+ // HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EventLog\Application.
+ //
+ return "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\" + mangleService(name);
+ }
+
+public:
+
+ SMEventLoggerI(const string& service)
+ {
+ _source = RegisterEventSource(0, mangleService(service).c_str());
+ if(_source == 0)
+ {
+ SyscallException ex(__FILE__, __LINE__);
+ ex.error = GetLastError();
+ throw ex;
+ }
+ }
+
+ ~SMEventLoggerI()
+ {
+ assert(_source != 0);
+ DeregisterEventSource(_source);
+ }
+
+ static void
+ addKeys(const string& service)
+ {
+ HKEY hKey;
+ DWORD d;
+ LONG err = RegCreateKeyEx(HKEY_LOCAL_MACHINE, createKey(service).c_str(), 0, "REG_SZ",
+ REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, 0, &hKey, &d);
+ if(err != ERROR_SUCCESS)
+ {
+ SyscallException ex(__FILE__, __LINE__);
+ ex.error = err;
+ throw ex;
+ }
-static Ice::ServiceStatusManager* serviceStatusManager;
+ //
+ // Get the filename of this DLL.
+ //
+ char path[_MAX_PATH];
+ assert(_module != 0);
+ if(!GetModuleFileName(_module, path, _MAX_PATH))
+ {
+ RegCloseKey(hKey);
+ SyscallException ex(__FILE__, __LINE__);
+ ex.error = GetLastError();
+ throw ex;
+ }
+
+ //
+ // The event resources are bundled into this DLL, therefore
+ // the "EventMessageFile" key should contain the path to this
+ // DLL.
+ //
+ err = RegSetValueEx(hKey, "EventMessageFile", 0, REG_EXPAND_SZ,
+ reinterpret_cast<unsigned char*>(path), static_cast<DWORD>(strlen(path) + 1));
+ if(err == ERROR_SUCCESS)
+ {
+ //
+ // The "TypesSupported" key indicates the supported event
+ // types.
+ //
+ DWORD typesSupported = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE;
+ err = RegSetValueEx(hKey, "TypesSupported", 0, REG_DWORD,
+ reinterpret_cast<unsigned char*>(&typesSupported), sizeof(typesSupported));
+ }
+ if(err != ERROR_SUCCESS)
+ {
+ RegCloseKey(hKey);
+ SyscallException ex(__FILE__, __LINE__);
+ ex.error = err;
+ throw ex;
+ }
+
+ RegCloseKey(hKey);
+ }
+
+ static void
+ removeKeys(const string& theService)
+ {
+ LONG err = RegDeleteKey(HKEY_LOCAL_MACHINE, createKey(theService).c_str());
+ if(err != ERROR_SUCCESS)
+ {
+ SyscallException ex(__FILE__, __LINE__);
+ ex.error = err;
+ throw ex;
+ }
+ }
+
+ virtual void
+ print(const string& message)
+ {
+ const char* str[1];
+ str[0] = message.c_str();
+ // We ignore any failures from ReportEvent since there isn't
+ // anything we can do about it.
+ ReportEvent(_source, EVENTLOG_INFORMATION_TYPE, 0, EVENT_LOGGER_MSG, 0, 1, 0, str, 0);
+ }
+
+ void
+ trace(const string& category, const string& message)
+ {
+ string s;
+ if(!category.empty())
+ {
+ s = category;
+ s.append(": ");
+ }
+ s.append(message);
+
+ const char* str[1];
+ str[0] = s.c_str();
+ ReportEvent(_source, EVENTLOG_INFORMATION_TYPE, 0, EVENT_LOGGER_MSG, 0, 1, 0, str, 0);
+ }
+
+ virtual void
+ warning(const string& message)
+ {
+ const char* str[1];
+ str[0] = message.c_str();
+ ReportEvent(_source, EVENTLOG_WARNING_TYPE, 0, EVENT_LOGGER_MSG, 0, 1, 0, str, 0);
+ }
+
+ virtual void
+ error(const string& message)
+ {
+ const char* str[1];
+ str[0] = message.c_str();
+ ReportEvent(_source, EVENTLOG_ERROR_TYPE, 0, EVENT_LOGGER_MSG, 0, 1, 0, str, 0);
+ }
+
+ static void
+ setModuleHandle(HMODULE module)
+ {
+ _module = module;
+ }
+
+private:
+
+ HANDLE _source;
+ static HMODULE _module;
+};
+
+HMODULE SMEventLoggerI::_module = 0;
+
+}
#endif
@@ -205,49 +377,6 @@ Ice::Service::main(int& argc, char* argv[], const InitializationData& initData)
{
if(strcmp(argv[idx], "--service") == 0)
{
- //
- // When running as a service, we need a logger to use for reporting any
- // failures that occur prior to initializing a communicator. After we have
- // a communicator, we can use the configured logger instead. If a logger
- // is defined in InitializationData, we'll use that. Otherwise, we create
- // a temporary event logger.
- //
- // We postpone the initialization of the communicator until serviceMain so
- // that we can incorporate the executable's arguments and the service's
- // arguments into one vector.
- //
- _logger = initData.logger;
- if(!_logger)
- {
- try
- {
- //
- // Use the executable name as the source for the temporary logger.
- //
- string loggerName = _name;
- transform(loggerName.begin(), loggerName.end(), loggerName.begin(), ::tolower);
- string::size_type pos = loggerName.find_last_of("\\/");
- if(pos != string::npos)
- {
- loggerName.erase(0, pos + 1); // Remove leading path.
- }
- pos = loggerName.rfind(".exe");
- if(pos != string::npos)
- {
- loggerName.erase(pos, loggerName.size() - pos); // Remove .exe extension.
- }
-
- _logger = new EventLoggerI(loggerName);
- }
- catch(const IceUtil::Exception& ex)
- {
- ostringstream ostr;
- ostr << ex;
- error("unable to create EventLogger:\n" + ostr.str());
- return EXIT_FAILURE;
- }
- }
-
if(idx + 1 >= argc)
{
error("service name argument expected for `" + string(argv[idx]) + "'");
@@ -256,6 +385,18 @@ Ice::Service::main(int& argc, char* argv[], const InitializationData& initData)
name = argv[idx + 1];
+ //
+ // The logger for the process is either the configured
+ // logger, or an event logger using the service name.
+ //
+ // We postpone the initialization of the communicator
+ // until serviceMain so that we can incorporate the
+ // executable's arguments and the service's arguments into
+ // one vector.
+ //
+ _logger = (initData.logger) ? initData.logger : new SMEventLoggerI(name);
+ setProcessLogger(_logger);
+
for(int i = idx; i + 2 < argc; ++i)
{
argv[i] = argv[i + 2];
@@ -373,11 +514,36 @@ Ice::Service::main(int& argc, char* argv[], const InitializationData& initData)
{
args.push_back(argv[idx]);
}
- return installService(name, display, executable, args);
+ try
+ {
+ //
+ // Add the registry keys for the event logger if
+ // initData.logger is empty (which is the case if the
+ // user wants to use the service default logger).
+ //
+ return installService(!initData.logger, name, display, executable, args);
+ }
+ catch(const Ice::Exception& ex)
+ {
+ ostringstream ostr;
+ ostr << ex;
+ error(ostr.str());
+ return EXIT_FAILURE;
+ }
}
else if(op == "--uninstall")
{
- return uninstallService(name);
+ try
+ {
+ return uninstallService(!initData.logger, name);
+ }
+ catch(const Ice::Exception& ex)
+ {
+ ostringstream ostr;
+ ostr << ex;
+ error(ostr.str());
+ return EXIT_FAILURE;
+ }
}
else if(op == "--start")
{
@@ -644,7 +810,7 @@ Ice::Service::configureService(const string& name)
}
int
-Ice::Service::installService(const string& name, const string& display, const string& executable,
+Ice::Service::installService(bool useEventLogger, const string& name, const string& display, const string& executable,
const vector<string>& args)
{
string disp, exec;
@@ -662,7 +828,7 @@ Ice::Service::installService(const string& name, const string& display, const st
// Use this executable if none is specified.
//
char buf[_MAX_PATH];
- if(GetModuleFileName(NULL, buf, _MAX_PATH) == 0)
+ if(GetModuleFileName(0, buf, _MAX_PATH) == 0)
{
error("unable to obtain file name of executable");
return EXIT_FAILURE;
@@ -701,8 +867,8 @@ Ice::Service::installService(const string& name, const string& display, const st
}
}
- SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
- if(hSCM == NULL)
+ SC_HANDLE hSCM = OpenSCManager(0, 0, SC_MANAGER_ALL_ACCESS);
+ if(hSCM == 0)
{
syserror("failure in OpenSCManager");
return EXIT_FAILURE;
@@ -716,13 +882,13 @@ Ice::Service::installService(const string& name, const string& display, const st
SERVICE_AUTO_START,
SERVICE_ERROR_NORMAL,
command.c_str(),
- NULL,
- NULL,
- NULL,
- NULL,
- NULL);
+ 0,
+ 0,
+ 0,
+ 0,
+ 0);
- if(hService == NULL)
+ if(hService == 0)
{
syserror("unable to install service `" + name + "'");
CloseServiceHandle(hSCM);
@@ -732,21 +898,31 @@ Ice::Service::installService(const string& name, const string& display, const st
CloseServiceHandle(hSCM);
CloseServiceHandle(hService);
+ //
+ // Add the registry keys for the event logger if _logger is
+ // empty (which is the case if the user wants to use
+ // the service default logger).
+ //
+ if(useEventLogger)
+ {
+ SMEventLoggerI::addKeys(name);
+ }
+
return EXIT_SUCCESS;
}
int
-Ice::Service::uninstallService(const string& name)
+Ice::Service::uninstallService(bool useEventLogger, const string& name)
{
- SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
- if(hSCM == NULL)
+ SC_HANDLE hSCM = OpenSCManager(0, 0, SC_MANAGER_ALL_ACCESS);
+ if(hSCM == 0)
{
syserror("failure in OpenSCManager");
return EXIT_FAILURE;
}
SC_HANDLE hService = OpenService(hSCM, name.c_str(), SERVICE_ALL_ACCESS);
- if(hService == NULL)
+ if(hService == 0)
{
syserror("unable to open service `" + name + "'");
CloseServiceHandle(hSCM);
@@ -766,21 +942,29 @@ Ice::Service::uninstallService(const string& name)
CloseServiceHandle(hSCM);
CloseServiceHandle(hService);
+ //
+ // Rrmove the registry keys for the event logger if necessary.
+ //
+ if(useEventLogger)
+ {
+ SMEventLoggerI::removeKeys(name);
+ }
+
return EXIT_SUCCESS;
}
int
Ice::Service::startService(const string& name, const vector<string>& args)
{
- SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
- if(hSCM == NULL)
+ SC_HANDLE hSCM = OpenSCManager(0, 0, SC_MANAGER_ALL_ACCESS);
+ if(hSCM == 0)
{
syserror("failure in OpenSCManager");
return EXIT_FAILURE;
}
SC_HANDLE hService = OpenService(hSCM, name.c_str(), SERVICE_ALL_ACCESS);
- if(hService == NULL)
+ if(hService == 0)
{
syserror("unable to open service `" + name + "'");
CloseServiceHandle(hSCM);
@@ -788,9 +972,10 @@ Ice::Service::startService(const string& name, const vector<string>& args)
}
//
- // Create argument vector. Note that StartService() automatically adds the service name
- // in argv[0], so the argv that is passed to StartService() must *not* include the
- // the service name in argv[0].
+ // Create argument vector. Note that StartService() automatically
+ // adds the service name in argv[0], so the argv that is passed to
+ // StartService() must *not* include the the service name in
+ // argv[0].
//
const int argc = static_cast<int>(args.size());
LPCSTR* argv = new LPCSTR[argc];
@@ -855,15 +1040,15 @@ Ice::Service::startService(const string& name, const vector<string>& args)
int
Ice::Service::stopService(const string& name)
{
- SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
- if(hSCM == NULL)
+ SC_HANDLE hSCM = OpenSCManager(0, 0, SC_MANAGER_ALL_ACCESS);
+ if(hSCM == 0)
{
syserror("failure in OpenSCManager");
return EXIT_FAILURE;
}
SC_HANDLE hService = OpenService(hSCM, name.c_str(), SERVICE_ALL_ACCESS);
- if(hService == NULL)
+ if(hService == 0)
{
syserror("unable to open service `" + name + "'");
CloseServiceHandle(hSCM);
@@ -910,6 +1095,12 @@ Ice::Service::stopService(const string& name)
return EXIT_SUCCESS;
}
+void
+Ice::Service::setModuleHandle(HMODULE module)
+{
+ SMEventLoggerI::setModuleHandle(module);
+}
+
#else
void
@@ -976,12 +1167,12 @@ Ice::Service::syserror(const string& msg)
DWORD ok = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL,
+ 0,
err,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR)&lpMsgBuf,
0,
- NULL);
+ 0);
if(ok)
{
LPCTSTR str = (LPCTSTR)lpMsgBuf;
@@ -1118,7 +1309,7 @@ Ice::Service::runService(int argc, char* argv[], const InitializationData& initD
SERVICE_TABLE_ENTRY ste[] =
{
{ const_cast<char*>(_name.c_str()), Ice_Service_ServiceMain },
- { NULL, NULL },
+ { 0, 0 },
};
//
@@ -1425,7 +1616,7 @@ Ice::Service::control(int ctrl)
}
}
-Ice::ServiceStatusManager::ServiceStatusManager(SERVICE_STATUS_HANDLE handle) :
+ServiceStatusManager::ServiceStatusManager(SERVICE_STATUS_HANDLE handle) :
_handle(handle), _stopped(false)
{
_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
@@ -1437,7 +1628,7 @@ Ice::ServiceStatusManager::ServiceStatusManager(SERVICE_STATUS_HANDLE handle) :
}
void
-Ice::ServiceStatusManager::startUpdate(DWORD state)
+ServiceStatusManager::startUpdate(DWORD state)
{
Lock sync(*this);
@@ -1454,7 +1645,7 @@ Ice::ServiceStatusManager::startUpdate(DWORD state)
}
void
-Ice::ServiceStatusManager::stopUpdate()
+ServiceStatusManager::stopUpdate()
{
IceUtil::ThreadPtr thread;
@@ -1477,7 +1668,7 @@ Ice::ServiceStatusManager::stopUpdate()
}
void
-Ice::ServiceStatusManager::changeStatus(DWORD state, DWORD controlsAccepted)
+ServiceStatusManager::changeStatus(DWORD state, DWORD controlsAccepted)
{
Lock sync(*this);
@@ -1488,7 +1679,7 @@ Ice::ServiceStatusManager::changeStatus(DWORD state, DWORD controlsAccepted)
}
void
-Ice::ServiceStatusManager::reportStatus()
+ServiceStatusManager::reportStatus()
{
Lock sync(*this);
@@ -1496,7 +1687,7 @@ Ice::ServiceStatusManager::reportStatus()
}
void
-Ice::ServiceStatusManager::run()
+ServiceStatusManager::run()
{
Lock sync(*this);