From 66eb3856346c59ec3a724eb41cc0e34e243c4c75 Mon Sep 17 00:00:00 2001
From: Rom Walton
Date: Thu, 29 Apr 2004 00:57:26 +0000
Subject: [PATCH] *** empty log message ***
svn path=/trunk/boinc/; revision=3305
---
checkin_notes | 21 +++++++-
client/cs_cmdline.C | 4 +-
client/main.C | 7 ++-
client/win/win_service.cpp | 106 ++++++++++++++++++++++++-------------
client/win/win_service.h | 7 +++
doc/contact.php | 1 +
win_build/boinc_cli.vcproj | 4 +-
7 files changed, 105 insertions(+), 45 deletions(-)
diff --git a/checkin_notes b/checkin_notes
index c7b6376748..ebd4b63e77 100755
--- a/checkin_notes
+++ b/checkin_notes
@@ -11814,9 +11814,9 @@ Rom April 28 2004
/
set-version
- /client
+ client/
Makefile.am
- /client/win
+ client/win/
*.rc
update* (deleted)
@@ -11825,3 +11825,20 @@ David April 28 2004
client/
hostinfo_unix.C
+
+Rom April 28 2004
+ - Fixup Windows service controls so that pause/resume/start/stop work as
+ expected, when running as a service log to the Windows event log.
+ - When attempting to change the service description use runtime dynamic
+ linking for the call to ChangeServiceConfig2 so that we will work even
+ on NT 4.0 systems.
+ - Some of these fixes were based on code from Mathias Walter
+
+ client/
+ cs_cmdline.C
+ main.C
+ client/win/
+ win_service.cpp, .h
+ win_build/
+ boinc_cli.vcproj
+
diff --git a/client/cs_cmdline.C b/client/cs_cmdline.C
index 4ab09cb686..28fb590741 100644
--- a/client/cs_cmdline.C
+++ b/client/cs_cmdline.C
@@ -39,7 +39,7 @@ static void print_options(char* prog) {
" -install install boinc as a Windows Service\n"
" -uninstall uninstall boinc as a Windows Service\n"
#endif
- " -show_projects show attached projects\n"
+ " -show_projects show attached projects\n"
" -detach_project URL detach from a project\n"
" -reset_project URL reset (clear) a project\n"
" -attach_project attach to a project (will prompt for URL, account key)\n"
@@ -117,8 +117,6 @@ void CLIENT_STATE::parse_cmdline(int argc, char** argv) {
else pers_giveup = atoi(argv[++i]);
} else if (ARG(debug_fake_exponential_backoff)) {
debug_fake_exponential_backoff = true;
- } else if (ARG(win_service)) {
- executing_as_windows_service = true;
// the above options are private (i.e. not shown by -help)
// Public options follow.
diff --git a/client/main.C b/client/main.C
index 7c4195d1aa..d97332a037 100644
--- a/client/main.C
+++ b/client/main.C
@@ -156,7 +156,7 @@ int add_new_project() {
}
void quit_client(int a) {
- gstate.requested_exit = true;
+ gstate.cleanup_and_exit();
}
void susp_client(int a) {
@@ -306,6 +306,11 @@ int main(int argc, char** argv) {
} else if ( _stricmp( "uninstall", argv[1]+1 ) == 0 ) {
CmdUninstallService();
} else if ( _stricmp( "win_service", argv[1]+1 ) == 0 ) {
+
+ // allow the system to know it is running as a Windows service
+ // and adjust it's diagnostics schemes accordingly.
+ gstate.executing_as_windows_service = true;
+
printf( "\nStartServiceCtrlDispatcher being called.\n" );
printf( "This may take several seconds. Please wait.\n" );
diff --git a/client/win/win_service.cpp b/client/win/win_service.cpp
index 39b7405783..427a9f873d 100644
--- a/client/win/win_service.cpp
+++ b/client/win/win_service.cpp
@@ -22,15 +22,18 @@
#include "stdafx.h"
+#include "diagnostics.h"
#include "win_service.h"
#include "util.h"
+
// internal variables
SERVICE_STATUS ssStatus; // current status of the service
SERVICE_STATUS_HANDLE sshStatusHandle;
DWORD dwErr = 0;
TCHAR szErr[1024];
+
// define the execution engine start point
extern int boinc_main_loop(int argc, char** argv);
extern void quit_client(int a);
@@ -38,9 +41,8 @@ extern void susp_client(int a);
extern void resume_client(int a);
-
-// internal function prototypes not defined in the header
-LPTSTR GetLastErrorText( LPTSTR lpszBuf, DWORD dwSize );
+// Define API's that are going to be used through LoadLibrary calls.
+typedef WINADVAPI BOOL (WINAPI *PROCCHANGESERVICECONFIG2)(SC_HANDLE, DWORD, LPCVOID);
//
@@ -62,36 +64,49 @@ LPTSTR GetLastErrorText( LPTSTR lpszBuf, DWORD dwSize );
//
void WINAPI service_main(DWORD dwArgc, LPTSTR *lpszArgv)
{
+ TCHAR szPath[MAX_PATH-1];
+
+
// SERVICE_STATUS members that don't change in example
//
ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
- ssStatus.dwControlsAccepted =
- SERVICE_ACCEPT_STOP |
- SERVICE_ACCEPT_PAUSE_CONTINUE |
- SERVICE_ACCEPT_SHUTDOWN;
+ ssStatus.dwControlsAccepted = SERVICE_ACCEPTED_ACTIONS;
ssStatus.dwServiceSpecificExitCode = 0;
+
// register our service control handler:
//
sshStatusHandle = RegisterServiceCtrlHandler( TEXT(SZSERVICENAME), service_ctrl);
if (!sshStatusHandle)
goto cleanup;
- if (!ReportStatus(
+ if (!ReportStatus(
SERVICE_RUNNING, // service state
ERROR_SUCCESS, // exit code
0)) // wait hint
goto cleanup;
+
+ // change the current directory to the boinc install directory
+ if (!GetModuleFileName(NULL, szPath, (sizeof(szPath)/sizeof(TCHAR))))
+ goto cleanup;
+
+ TCHAR *pszProg = strrchr(szPath, '\\');
+ if (pszProg) {
+ szPath[pszProg - szPath + 1] = 0;
+ SetCurrentDirectory(szPath);
+ }
+
dwErr = boinc_main_loop(dwArgc, lpszArgv);
+
cleanup:
// try to report the stopped status to the service control manager.
//
if (sshStatusHandle)
(VOID)ReportStatus(
- SERVICE_STOPPED,
+ SERVICE_STOPPED,
dwErr,
0);
}
@@ -125,11 +140,6 @@ VOID WINAPI service_ctrl(DWORD dwCtrlCode)
// which may result in a 1053 - The Service did not respond...
// error.
case SERVICE_CONTROL_STOP:
- ReportStatus(SERVICE_STOP_PENDING, ERROR_SUCCESS, 10000);
- quit_client(NULL);
- ReportStatus(SERVICE_STOPPED, ERROR_SUCCESS, 10000);
- return;
-
case SERVICE_CONTROL_SHUTDOWN:
ReportStatus(SERVICE_STOP_PENDING, ERROR_SUCCESS, 10000);
quit_client(NULL);
@@ -148,7 +158,7 @@ VOID WINAPI service_ctrl(DWORD dwCtrlCode)
//
case SERVICE_CONTROL_CONTINUE:
ReportStatus(SERVICE_CONTINUE_PENDING, ERROR_SUCCESS, 10000);
- susp_client(NULL);
+ resume_client(NULL);
ReportStatus(SERVICE_RUNNING, ERROR_SUCCESS, 10000);
return;
@@ -195,10 +205,7 @@ BOOL ReportStatus(DWORD dwCurrentState,
if (dwCurrentState == SERVICE_START_PENDING)
ssStatus.dwControlsAccepted = 0;
else
- ssStatus.dwControlsAccepted =
- SERVICE_ACCEPT_STOP |
- SERVICE_ACCEPT_PAUSE_CONTINUE |
- SERVICE_ACCEPT_SHUTDOWN;
+ ssStatus.dwControlsAccepted = SERVICE_ACCEPTED_ACTIONS;
ssStatus.dwCurrentState = dwCurrentState;
ssStatus.dwWin32ExitCode = dwWin32ExitCode;
@@ -254,7 +261,7 @@ VOID LogEventErrorMessage(LPTSTR lpszMsg)
ReportEvent(hEventSource, // handle of event source
EVENTLOG_ERROR_TYPE, // event type
0, // event category
- 0, // event ID
+ 1, // event ID
NULL, // current user's SID
2, // strings in lpszStrings
0, // no bytes of raw data
@@ -263,7 +270,7 @@ VOID LogEventErrorMessage(LPTSTR lpszMsg)
(VOID) DeregisterEventSource(hEventSource);
}
-}
+ }
//
@@ -299,7 +306,7 @@ VOID LogEventWarningMessage(LPTSTR lpszMsg)
ReportEvent(hEventSource, // handle of event source
EVENTLOG_WARNING_TYPE,// event type
0, // event category
- 0, // event ID
+ 1, // event ID
NULL, // current user's SID
2, // strings in lpszStrings
0, // no bytes of raw data
@@ -344,7 +351,7 @@ VOID LogEventInfoMessage(LPTSTR lpszMsg)
ReportEvent(hEventSource, // handle of event source
EVENTLOG_INFORMATION_TYPE,// event type
0, // event category
- 0, // event ID
+ 1, // event ID
NULL, // current user's SID
2, // strings in lpszStrings
0, // no bytes of raw data
@@ -370,14 +377,16 @@ VOID LogEventInfoMessage(LPTSTR lpszMsg)
//
void CmdInstallService()
{
- SC_HANDLE schService;
- SC_HANDLE schSCManager;
+ SC_HANDLE schService;
+ SC_HANDLE schSCManager;
+ HINSTANCE hinstAdvAPI32;
+ PROCCHANGESERVICECONFIG2 ProcChangeServiceConfig2;
TCHAR szPath[512];
if ( GetModuleFileName( NULL, szPath, 512 ) == 0 )
{
- _tprintf(TEXT("Unable to install %s - %s\n"), TEXT(SZSERVICEDISPLAYNAME), windows_error_string(szErr, sizeof(szErr)));
+ _tprintf(TEXT("Unable to install %s - %s\n"), TEXT(SZSERVICEDISPLAYNAME), windows_error_string(szErr, (sizeof(szErr)/sizeof(TCHAR))));
return;
}
@@ -435,23 +444,48 @@ void CmdInstallService()
SERVICE_DESCRIPTION sdDescription;
sdDescription.lpDescription = TEXT(SZSERVICEDESCRIPTION);
- if ( ChangeServiceConfig2(schService, SERVICE_CONFIG_DESCRIPTION, &sdDescription) ){
- _tprintf(TEXT("%s service description installed.\n"), TEXT(SZSERVICEDISPLAYNAME) );
- } else {
- _tprintf(TEXT("ChangeServiceConfig2 failed - %s\n"), windows_error_string(szErr, sizeof(szErr)));
- }
+ hinstAdvAPI32 = LoadLibrary("ADVAPI32");
+
+ // If the handle is valid, try to get the function address.
+ if ( NULL != hinstAdvAPI32 )
+ {
+#ifdef _UNICODE
+ ProcChangeServiceConfig2 = (PROCCHANGESERVICECONFIG2)GetProcAddress(
+ hinstAdvAPI32,
+ TEXT("ChangeServiceConfig2W")
+ );
+#else
+ ProcChangeServiceConfig2 = (PROCCHANGESERVICECONFIG2)GetProcAddress(
+ hinstAdvAPI32,
+ TEXT("ChangeServiceConfig2A")
+ );
+#endif
+
+ // If the function address is valid, call the function.
+ if ( NULL != ProcChangeServiceConfig2 )
+ {
+ if ( ProcChangeServiceConfig2(schService, SERVICE_CONFIG_DESCRIPTION, &sdDescription) ){
+ _tprintf(TEXT("%s service description installed.\n"), TEXT(SZSERVICEDISPLAYNAME) );
+ } else {
+ _tprintf(TEXT("ChangeServiceConfig2 failed - %s\n"), windows_error_string(szErr, (sizeof(szErr)/sizeof(TCHAR))));
+ }
+ }
+
+ // Free the DLL module
+ FreeLibrary( hinstAdvAPI32 );
+ }
CloseServiceHandle(schService);
}
else
{
- _tprintf(TEXT("CreateService failed - %s\n"), windows_error_string(szErr, sizeof(szErr)));
+ _tprintf(TEXT("CreateService failed - %s\n"), windows_error_string(szErr, (sizeof(szErr)/sizeof(TCHAR))));
}
CloseServiceHandle(schSCManager);
}
else
- _tprintf(TEXT("OpenSCManager failed - %s\n"), windows_error_string(szErr,sizeof(szErr)));
+ _tprintf(TEXT("OpenSCManager failed - %s\n"), windows_error_string(szErr, (sizeof(szErr)/sizeof(TCHAR))));
}
@@ -513,18 +547,18 @@ void CmdUninstallService()
if( DeleteService(schService) )
_tprintf(TEXT("%s removed.\n"), TEXT(SZSERVICEDISPLAYNAME) );
else
- _tprintf(TEXT("DeleteService failed - %s\n"), windows_error_string(szErr,sizeof(szErr)));
+ _tprintf(TEXT("DeleteService failed - %s\n"), windows_error_string(szErr, (sizeof(szErr)/sizeof(TCHAR))));
CloseServiceHandle(schService);
}
else
- _tprintf(TEXT("OpenService failed - %s\n"), windows_error_string(szErr,sizeof(szErr)));
+ _tprintf(TEXT("OpenService failed - %s\n"), windows_error_string(szErr, (sizeof(szErr)/sizeof(TCHAR))));
CloseServiceHandle(schSCManager);
}
else
- _tprintf(TEXT("OpenSCManager failed - %s\n"), windows_error_string(szErr,sizeof(szErr)));
+ _tprintf(TEXT("OpenSCManager failed - %s\n"), windows_error_string(szErr, (sizeof(szErr)/sizeof(TCHAR))));
}
diff --git a/client/win/win_service.h b/client/win/win_service.h
index 044997c449..218b1aa8e4 100644
--- a/client/win/win_service.h
+++ b/client/win/win_service.h
@@ -27,6 +27,7 @@
extern "C" {
#endif
+
// internal name of the service
#define SZSERVICENAME "BOINC"
@@ -36,6 +37,12 @@ extern "C" {
// displayed description of the service
#define SZSERVICEDESCRIPTION "Berkeley Open Infrastructure for Network Computing"
+// Service Accepted Actions
+#define SERVICE_ACCEPTED_ACTIONS ( \
+ SERVICE_ACCEPT_STOP | \
+ SERVICE_ACCEPT_PAUSE_CONTINUE | \
+ SERVICE_ACCEPT_SHUTDOWN )
+
// Service Control Manager Routines
VOID WINAPI service_main(DWORD dwArgc, LPTSTR *lpszArgv);
VOID WINAPI service_ctrl(DWORD dwCtrlCode);
diff --git a/doc/contact.php b/doc/contact.php
index 11c2cd364c..e9e121eea8 100644
--- a/doc/contact.php
+++ b/doc/contact.php
@@ -28,6 +28,7 @@ Sebastian Masch,
Stephen Pellicer,
Jens Seidler,
Christian Soettrup,
+Mathias Walter,
Rom Walton,
Oliver Wang
diff --git a/win_build/boinc_cli.vcproj b/win_build/boinc_cli.vcproj
index 1e37925dfa..d075c7b868 100644
--- a/win_build/boinc_cli.vcproj
+++ b/win_build/boinc_cli.vcproj
@@ -26,6 +26,7 @@
PreprocessorDefinitions="WIN32;_DEBUG;_MT;_WINDOWS;_CONSOLE"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
+ RuntimeTypeInfo="FALSE"
UsePrecompiledHeader="2"
PrecompiledHeaderThrough="../client/StdAfx.h"
PrecompiledHeaderFile=".\Build\Debug\boinc_cli\obj/boinc_cli.pch"
@@ -1129,9 +1130,6 @@
-
-