version 1.2, 2006/01/30 16:19:34
|
version 1.3, 2007/06/19 17:58:04
|
|
|
//------------------------------------------------------------------------- | //------------------------------------------------------------------------- |
// P U B L I C | // P U B L I C |
//------------------------------------------------------------------------- | //------------------------------------------------------------------------- |
Service::Service(void) |
Service::Service() |
{ | { |
} | } |
| |
Service::Service(const char *service_name) | Service::Service(const char *service_name) |
{ | { |
//ATTN: I have to allocate memory here, unless I want to change the char* g_service_name to a char[]. |
// ATTN: I have to allocate memory here, unless I want to change the |
//Changing to an array of char affects a lot more code. Previously, this method had a char* for its |
// char* g_service_name to a char[]. Changing to an array of char |
//input parameter, and since we were using #define's the values were always in memory. |
// affects a lot more code. Previously, this method had a char* for its |
|
// input parameter, and since we were using #define's the values were |
|
// always in memory. |
//Now we are using an interface method that returns const char* -hns PEP222 | //Now we are using an interface method that returns const char* -hns PEP222 |
g_service_name = (char*) malloc(strlen(service_name)+1); | g_service_name = (char*) malloc(strlen(service_name)+1); |
memset(g_service_name, '\0', strlen(service_name)+1); | memset(g_service_name, '\0', strlen(service_name)+1); |
strncpy(g_service_name, service_name, strlen(service_name)); | strncpy(g_service_name, service_name, strlen(service_name)); |
} | } |
| |
Service::Service(const char *service_name, char *event_source) |
Service::Service( |
|
const char* service_name, |
|
char* event_source) |
{ | { |
g_event_source = event_source; | g_event_source = event_source; |
| |
|
|
strncpy(g_service_name, service_name, strlen(service_name)); | strncpy(g_service_name, service_name, strlen(service_name)); |
} | } |
| |
Service::~Service(void) |
Service::~Service() |
{ | { |
//ATTN: Will open Bugzilla on this. I need to change this to either use char arrays OR deallocate the memory |
// ATTN: Will open Bugzilla on this. I need to change this to either use |
//elsewhere. I cannot use any fancy AutoPtr stuff since Pegasus code is kept out of this OS-specific file |
// char arrays OR deallocate the memory elsewhere. I cannot use any fancy |
|
// AutoPtr stuff since Pegasus code is kept out of this OS-specific file |
// -hns PEP#222 | // -hns PEP#222 |
/*if (g_service_name != NULL) | /*if (g_service_name != NULL) |
{ | { |
|
|
* NOTE: If the process is successfully launched as a Win32 service, this * | * NOTE: If the process is successfully launched as a Win32 service, this * |
* function never returns, but calls exit() instead. * | * function never returns, but calls exit() instead. * |
*-------------------------------------------------------------------------*/ | *-------------------------------------------------------------------------*/ |
Service::ReturnCode |
Service::ReturnCode Service::Install( |
Service::Install( |
|
char *display_name, | char *display_name, |
char *description, | char *description, |
char *exe_name) | char *exe_name) |
|
|
| |
if (g_service_name == NULL || display_name == NULL || exe_name == NULL) | if (g_service_name == NULL || display_name == NULL || exe_name == NULL) |
return SERVICE_ERROR_NOT_FOUND; // SERVICE_ERROR_NOT_FOUND | return SERVICE_ERROR_NOT_FOUND; // SERVICE_ERROR_NOT_FOUND |
else if ((sch = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE)) == NULL) |
else if ((sch = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE)) == |
|
NULL) |
status = get_error(GetLastError(), "open"); | status = get_error(GetLastError(), "open"); |
else | else |
{ | { |
|
|
* Description: * | * Description: * |
* Removes the service. * | * Removes the service. * |
*-------------------------------------------------------------------------*/ | *-------------------------------------------------------------------------*/ |
Service::ReturnCode |
Service::ReturnCode Service::Remove() |
Service::Remove(void) |
|
{ | { |
ReturnCode status = SERVICE_RETURN_SUCCESS; | ReturnCode status = SERVICE_RETURN_SUCCESS; |
SC_HANDLE sch; | SC_HANDLE sch; |
| |
if (g_service_name == NULL) | if (g_service_name == NULL) |
return SERVICE_ERROR_NOT_FOUND; /* SERVICE_ERROR_NOT_FOUND */ | return SERVICE_ERROR_NOT_FOUND; /* SERVICE_ERROR_NOT_FOUND */ |
else if ((sch = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE)) == NULL) |
else if ((sch = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE)) == |
|
NULL) |
status = get_error(GetLastError(), "open"); | status = get_error(GetLastError(), "open"); |
else | else |
{ | { |
|
|
* Description: * | * Description: * |
* Attempt to start the service. * | * Attempt to start the service. * |
*-------------------------------------------------------------------------*/ | *-------------------------------------------------------------------------*/ |
Service::ReturnCode |
Service::ReturnCode Service::Start(int wait_time) |
Service::Start(int wait_time) |
|
{ | { |
ReturnCode status = SERVICE_RETURN_SUCCESS; | ReturnCode status = SERVICE_RETURN_SUCCESS; |
SERVICE_STATUS service_status; | SERVICE_STATUS service_status; |
|
|
status = get_error(GetLastError(), "open"); | status = get_error(GetLastError(), "open"); |
else | else |
{ | { |
SC_HANDLE service = OpenService(sch, g_service_name, SERVICE_START | SERVICE_QUERY_STATUS); |
SC_HANDLE service = OpenService( |
|
sch, g_service_name, SERVICE_START | SERVICE_QUERY_STATUS); |
| |
if (service == NULL) | if (service == NULL) |
status = get_error(GetLastError(), "open"); | status = get_error(GetLastError(), "open"); |
|
|
Sleep(1 * CLOCKS_PER_SEC); | Sleep(1 * CLOCKS_PER_SEC); |
} | } |
| |
status = (i < max) ? SERVICE_RETURN_SUCCESS : SERVICE_ERROR_REQUEST_TIMEOUT; |
status = (i < max) ? |
|
SERVICE_RETURN_SUCCESS : SERVICE_ERROR_REQUEST_TIMEOUT; |
| |
CloseServiceHandle(service); | CloseServiceHandle(service); |
} | } |
|
|
* Description: * | * Description: * |
* Attempt to stop the service. * | * Attempt to stop the service. * |
*-------------------------------------------------------------------------*/ | *-------------------------------------------------------------------------*/ |
Service::ReturnCode |
Service::ReturnCode Service::Stop(int wait_time) |
Service::Stop(int wait_time) |
|
{ | { |
ReturnCode status = SERVICE_RETURN_SUCCESS; | ReturnCode status = SERVICE_RETURN_SUCCESS; |
SERVICE_STATUS service_status; | SERVICE_STATUS service_status; |
|
|
// show_error("OpenSCMManager", "service", GetLastError()); | // show_error("OpenSCMManager", "service", GetLastError()); |
else | else |
{ | { |
SC_HANDLE service = OpenService(sch, g_service_name, SERVICE_STOP | SERVICE_QUERY_STATUS); |
SC_HANDLE service = OpenService( |
|
sch, g_service_name, SERVICE_STOP | SERVICE_QUERY_STATUS); |
| |
if (service == NULL) | if (service == NULL) |
status = get_error(GetLastError(), "open"); | status = get_error(GetLastError(), "open"); |
else if (!ControlService(service, SERVICE_CONTROL_STOP, &service_status)) |
else if (!ControlService( |
|
service, SERVICE_CONTROL_STOP, &service_status)) |
status = get_error(GetLastError(), "stop"); | status = get_error(GetLastError(), "stop"); |
else | else |
{ | { |
|
|
Sleep(1 * CLOCKS_PER_SEC); | Sleep(1 * CLOCKS_PER_SEC); |
} | } |
| |
status = (i < max) ? SERVICE_RETURN_SUCCESS : SERVICE_ERROR_REQUEST_TIMEOUT; |
status = (i < max) ? |
|
SERVICE_RETURN_SUCCESS : SERVICE_ERROR_REQUEST_TIMEOUT; |
| |
CloseServiceHandle(service); | CloseServiceHandle(service); |
} | } |
|
|
* function never returns, but calls exit() instead. * | * function never returns, but calls exit() instead. * |
*-------------------------------------------------------------------------*/ | *-------------------------------------------------------------------------*/ |
| |
Service::ReturnCode |
Service::ReturnCode Service::Run(SERVICE_MAIN_T service_main, DWORD flags) |
Service::Run(SERVICE_MAIN_T service_main, DWORD flags) |
|
{ | { |
ReturnCode status = SERVICE_RETURN_SUCCESS; | ReturnCode status = SERVICE_RETURN_SUCCESS; |
| |
|
|
* Description: * | * Description: * |
* Returns the state of the service into "state". * | * Returns the state of the service into "state". * |
*-------------------------------------------------------------------------*/ | *-------------------------------------------------------------------------*/ |
Service::ReturnCode |
Service::ReturnCode Service::GetState(State* state) |
Service::GetState(State *state) |
|
{ | { |
ReturnCode status = SERVICE_RETURN_SUCCESS; | ReturnCode status = SERVICE_RETURN_SUCCESS; |
SERVICE_STATUS service_status; | SERVICE_STATUS service_status; |
|
|
status = get_error(GetLastError(), "open"); | status = get_error(GetLastError(), "open"); |
else | else |
{ | { |
SC_HANDLE service = OpenService(sch, g_service_name, SERVICE_QUERY_STATUS); |
SC_HANDLE service = |
|
OpenService(sch, g_service_name, SERVICE_QUERY_STATUS); |
| |
if (service == NULL) | if (service == NULL) |
status = get_error(GetLastError(), "open"); | status = get_error(GetLastError(), "open"); |
|
|
* true if event was successfully logged * | * true if event was successfully logged * |
* false if the event could not be logged * | * false if the event could not be logged * |
*-------------------------------------------------------------------------*/ | *-------------------------------------------------------------------------*/ |
bool |
bool Service::LogEvent(WORD event_type, DWORD event_id, const char *string) |
Service::LogEvent(WORD event_type, DWORD event_id, const char *string) |
|
{ | { |
BOOL status; | BOOL status; |
HANDLE h_event_source = RegisterEventSource(NULL, g_event_source); | HANDLE h_event_source = RegisterEventSource(NULL, g_event_source); |
|
|
if (h_event_source == NULL) | if (h_event_source == NULL) |
FALSE; | FALSE; |
| |
status = ReportEvent (h_event_source, |
status = ReportEvent( |
|
h_event_source, |
event_type, | event_type, |
0, | 0, |
event_id, | event_id, |
|
|
| |
DeregisterEventSource(h_event_source); | DeregisterEventSource(h_event_source); |
| |
return (status == TRUE) ? true : false; |
return (status == TRUE); |
} | } |
| |
//------------------------------------------------------------------------- | //------------------------------------------------------------------------- |
|
|
| |
// Start service actions | // Start service actions |
| |
g_service_status_handle = RegisterServiceCtrlHandler (g_service_name, |
g_service_status_handle = |
service_control_handler); |
RegisterServiceCtrlHandler(g_service_name, service_control_handler); |
| |
if (g_service_status_handle == 0) | if (g_service_status_handle == 0) |
{ | { |
|
|
* true if the string was found * | * true if the string was found * |
* false if the string was not found * | * false if the string was not found * |
*-------------------------------------------------------------------------*/ | *-------------------------------------------------------------------------*/ |
bool |
bool Service::check_args_for_string(char* string) |
Service::check_args_for_string(char *string) |
|
{ | { |
int i; | int i; |
| |
|
|
* true if the status was successfully reported * | * true if the status was successfully reported * |
* false if the status could not be reported * | * false if the status could not be reported * |
*-------------------------------------------------------------------------*/ | *-------------------------------------------------------------------------*/ |
bool |
bool Service::report_status( |
Service::report_status( |
|
DWORD current_state, | DWORD current_state, |
DWORD exit_code, | DWORD exit_code, |
DWORD check_point, | DWORD check_point, |
|
|
| |
g_current_state = current_state; | g_current_state = current_state; |
| |
return (SetServiceStatus(g_service_status_handle, ¤t_status) == TRUE) ? true : false; |
return (SetServiceStatus(g_service_status_handle, ¤t_status) == TRUE); |
} | } |
| |
/*-------------------------------------------------------------------------* | /*-------------------------------------------------------------------------* |
|
|
* first appeared in Windows2000. Therefore, this code checks the * | * first appeared in Windows2000. Therefore, this code checks the * |
* OS version, before calling ChangeServiceConfig2(). * | * OS version, before calling ChangeServiceConfig2(). * |
*-------------------------------------------------------------------------*/ | *-------------------------------------------------------------------------*/ |
void |
void Service::change_service_description(SC_HANDLE service, char *description) |
Service::change_service_description(SC_HANDLE service, char *description) |
|
{ | { |
OSVERSIONINFO osvi; | OSVERSIONINFO osvi; |
| |
|
|
osvi.dwPlatformId == VER_PLATFORM_WIN32_NT && | osvi.dwPlatformId == VER_PLATFORM_WIN32_NT && |
osvi.dwMajorVersion >= 5) | osvi.dwMajorVersion >= 5) |
{ | { |
typedef BOOL (WINAPI *CHANGE_SERVICE_CONFIG2_T)(SC_HANDLE, DWORD, LPVOID); |
typedef BOOL |
|
(WINAPI *CHANGE_SERVICE_CONFIG2_T)(SC_HANDLE, DWORD, LPVOID); |
| |
HINSTANCE hdll = LoadLibrary("advapi32.dll"); | HINSTANCE hdll = LoadLibrary("advapi32.dll"); |
| |
|
|
SERVICE_DESCRIPTION sd; | SERVICE_DESCRIPTION sd; |
CHANGE_SERVICE_CONFIG2_T csc; | CHANGE_SERVICE_CONFIG2_T csc; |
| |
csc = (CHANGE_SERVICE_CONFIG2_T) GetProcAddress(hdll, "ChangeServiceConfig2A"); |
csc = (CHANGE_SERVICE_CONFIG2_T) |
|
GetProcAddress(hdll, "ChangeServiceConfig2A"); |
| |
if (csc) | if (csc) |
{ | { |
|
|
* true if event was successfully logged * | * true if event was successfully logged * |
* false if the event could not be logged * | * false if the event could not be logged * |
*-------------------------------------------------------------------------*/ | *-------------------------------------------------------------------------*/ |
bool |
bool Service::show_error(const char *action, const char *object, DWORD hr) |
Service::show_error(const char *action, const char *object, DWORD hr) |
|
{ | { |
char console_title[_MAX_PATH] = {0}; | char console_title[_MAX_PATH] = {0}; |
char txt[_MAX_PATH] = ""; | char txt[_MAX_PATH] = ""; |
|
|
if (msg[nchars - 2] == '\r') msg[nchars - 2] = '\0'; | if (msg[nchars - 2] == '\r') msg[nchars - 2] = '\0'; |
} | } |
| |
sprintf(txt, "Failed to %s %s %s. Reason: %s", action, object, g_service_name, msg); |
sprintf(txt, |
|
"Failed to %s %s %s. Reason: %s", |
|
action, |
|
object, |
|
g_service_name, |
|
msg); |
| |
// Running from a console window | // Running from a console window |
// send courtesy message txt to stderr | // send courtesy message txt to stderr |
|
|
return LogEvent(EVENTLOG_ERROR_TYPE, 1, txt); | return LogEvent(EVENTLOG_ERROR_TYPE, 1, txt); |
} | } |
| |
Service::State |
Service::State Service::get_state(DWORD scm_state) |
Service::get_state(DWORD scm_state) |
|
{ | { |
return (State)scm_state; | return (State)scm_state; |
} | } |
| |
Service::ReturnCode |
Service::ReturnCode Service::get_error(DWORD error_status, const char *action) |
Service::get_error(DWORD error_status, const char *action) |
|
{ | { |
switch (error_status) | switch (error_status) |
{ | { |