r8932@totoro: nickm | 2006-10-07 20:29:03 -0400

Try to make mingw capable of producing a working tor binary for win98: make all NT-service-related functions get lazy-loaded on demand.  I have no idea if this even compiles.


svn:r8643
This commit is contained in:
Nick Mathewson 2006-10-08 00:33:35 +00:00
parent e230fe8ea6
commit 1c01797c16

View File

@ -1654,6 +1654,117 @@ do_hash_password(void)
} }
#ifdef MS_WINDOWS_SERVICE #ifdef MS_WINDOWS_SERVICE
struct service_fns {
int loaded;
BOOL WINAPI (ChangeServiceConfig2_fn*)(
SC_HANDLE hService,
DWORD dwInfoLevel,
LPVOID lpInfo);
BOOL WINAPI (CloseServiceHandle_fn*)(
SC_HANDLE hSCObject);
BOOL WINAPI (ControlService_fn*)(
SC_HANDLE hService,
DWORD dwControl,
LPSERVICE_STATUS lpServiceStatus);
SC_HANDLE WINAPI (CreateService_fn*)(
SC_HANDLE hSCManager,
LPCTSTR lpServiceName,
LPCTSTR lpDisplayName,
DWORD dwDesiredAccess,
DWORD dwServiceType,
DWORD dwStartType,
DWORD dwErrorControl,
LPCTSTR lpBinaryPathName,
LPCTSTR lpLoadOrderGroup,
LPDWORD lpdwTagId,
LPCTSTR lpDependencies,
LPCTSTR lpServiceStartName,
LPCTSTR lpPassword);
BOOL WINAPI (DeleteService_fn*)(
SC_HANDLE hService);
SC_HANDLE WINAPI (OpenSCManager_fn*)(
LPCTSTR lpMachineName,
LPCTSTR lpDatabaseName,
DWORD dwDesiredAccess);
SC_HANDLE WINAPI (OpenService_fn*)(
SC_HANDLE hSCManager,
LPCTSTR lpServiceName,
DWORD dwDesiredAccess);
BOOL WINAPI (QueryServiceStatus_fn*)(
SC_HANDLE hService,
LPSERVICE_STATUS lpServiceStatus);
SERVICE_STATUS_HANDLE WINAPI (RegisterServiceCtrlHandler_fn*)(
LPCTSTR lpServiceName,
LPHANDLER_FUNCTION lpHandlerProc);
BOOL WINAPI (SetServiceStatus_fn*)(SERVICE_STATUS_HANDLE,
LPSERVICE_STATUS);
BOOL WINAPI (StartServiceCtrlDispatcher_fn*)(
const SERVICE_TABLE_ENTRY* lpServiceTable);
BOOL WINAPI (StartService_fn*)(
SC_HANDLE hService,
DWORD dwNumServiceArgs,
LPCTSTR* lpServiceArgVectors);
} service_fns = { 0,
NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, };
static int
nt_service_loadlibrary(void)
{
HMODULE library = 0;
void *fn;
if (loaded)
return 0;
if (!(library = LoadLibrary("advapi32.dll"))) {
log_err(LD_GENERAL, "Couldn't open advapi32.dll. Are you trying to use "
"NT services on Windows 98? That doesn't work.");
return -1;
}
#define LOAD(f) do { \
if (!(fn = GetProcAddress(library, #f))) { \
log_err(LD_BUF, "Couldn't find %s in advapi32.dll! We probably got " \
"the name wrong.", #f); \
return -1; \
} else { \
service_fns.f ## _fn = fn; \
} \
} while (0)
LOAD(ChangeServiceConfig2);
LOAD(CloseServiceHandle);
LOAD(ControlService);
LOAD(CreateService);
LOAD(DeleteService);
LOAD(OpenSCManager);
LOAD(OpenService);
LOAD(QueryServiceStatus);
LOAD(RegisterServiceCtrlHandler);
LOAD(SetServiceStatus);
LOAD(StartServiceCtrlDispatcher);
LOAD(StartService);
service_fns.loaded = 1;
return 0;
}
/** Checks if torrc is present in the same directory /** Checks if torrc is present in the same directory
* as the service executable. * as the service executable.
* Return 1 if it is, 0 if it is not present. */ * Return 1 if it is, 0 if it is not present. */
@ -1704,10 +1815,13 @@ nt_torrc_is_present()
static int static int
nt_service_is_stopped(void) nt_service_is_stopped(void)
{ {
if (nt_service_loadlibrary()<0)
return -1;
if (service_status.dwCurrentState == SERVICE_STOP_PENDING) { if (service_status.dwCurrentState == SERVICE_STOP_PENDING) {
service_status.dwWin32ExitCode = 0; service_status.dwWin32ExitCode = 0;
service_status.dwCurrentState = SERVICE_STOPPED; service_status.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus(hStatus, &service_status); service_fns.SetServiceStatus_fn(hStatus, &service_status);
return 1; return 1;
} else if (service_status.dwCurrentState == SERVICE_STOPPED) { } else if (service_status.dwCurrentState == SERVICE_STOPPED) {
return 1; return 1;
@ -1723,6 +1837,9 @@ nt_service_control(DWORD request)
exit_now.tv_sec = 0; exit_now.tv_sec = 0;
exit_now.tv_usec = 0; exit_now.tv_usec = 0;
if (nt_service_loadlibrary()<0)
return;
switch (request) { switch (request) {
case SERVICE_CONTROL_STOP: case SERVICE_CONTROL_STOP:
case SERVICE_CONTROL_SHUTDOWN: case SERVICE_CONTROL_SHUTDOWN:
@ -1732,7 +1849,7 @@ nt_service_control(DWORD request)
event_loopexit(&exit_now); event_loopexit(&exit_now);
return; return;
} }
SetServiceStatus(hStatus, &service_status); service_fns.SetServiceStatus_fn(hStatus, &service_status);
} }
/** DOCDOC */ /** DOCDOC */
@ -1740,6 +1857,8 @@ void
nt_service_body(int argc, char **argv) nt_service_body(int argc, char **argv)
{ {
int r; int r;
if (nt_service_loadlibrary()<0)
return;
service_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS; service_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
service_status.dwCurrentState = SERVICE_START_PENDING; service_status.dwCurrentState = SERVICE_START_PENDING;
service_status.dwControlsAccepted = service_status.dwControlsAccepted =
@ -1748,7 +1867,7 @@ nt_service_body(int argc, char **argv)
service_status.dwServiceSpecificExitCode = 0; service_status.dwServiceSpecificExitCode = 0;
service_status.dwCheckPoint = 0; service_status.dwCheckPoint = 0;
service_status.dwWaitHint = 1000; service_status.dwWaitHint = 1000;
hStatus = RegisterServiceCtrlHandler(GENSRV_SERVICENAME, hStatus = service_fns.RegisterServiceCtrlHandler_fn(GENSRV_SERVICENAME,
(LPHANDLER_FUNCTION) nt_service_control); (LPHANDLER_FUNCTION) nt_service_control);
if (hStatus == 0) { if (hStatus == 0) {
@ -1775,11 +1894,11 @@ nt_service_body(int argc, char **argv)
service_status.dwCurrentState = SERVICE_STOPPED; service_status.dwCurrentState = SERVICE_STOPPED;
service_status.dwWin32ExitCode = r; service_status.dwWin32ExitCode = r;
service_status.dwServiceSpecificExitCode = r; service_status.dwServiceSpecificExitCode = r;
SetServiceStatus(hStatus, &service_status); service_fns.SetServiceStatus_fn(hStatus, &service_status);
return; return;
} }
service_status.dwCurrentState = SERVICE_RUNNING; service_status.dwCurrentState = SERVICE_RUNNING;
SetServiceStatus(hStatus, &service_status); service_fns.SetServiceStatus_fn(hStatus, &service_status);
do_main_loop(); do_main_loop();
tor_cleanup(); tor_cleanup();
return; return;
@ -1792,12 +1911,14 @@ nt_service_main(void)
SERVICE_TABLE_ENTRY table[2]; SERVICE_TABLE_ENTRY table[2];
DWORD result = 0; DWORD result = 0;
char *errmsg; char *errmsg;
if (nt_service_loadlibrary()<0)
return;
table[0].lpServiceName = GENSRV_SERVICENAME; table[0].lpServiceName = GENSRV_SERVICENAME;
table[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)nt_service_body; table[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)nt_service_body;
table[1].lpServiceName = NULL; table[1].lpServiceName = NULL;
table[1].lpServiceProc = NULL; table[1].lpServiceProc = NULL;
if (!StartServiceCtrlDispatcher(table)) { if (!service_fns.StartServiceCtrlDispatcher_fn(table)) {
result = GetLastError(); result = GetLastError();
errmsg = nt_strerror(result); errmsg = nt_strerror(result);
printf("Service error %d : %s\n", (int) result, errmsg); printf("Service error %d : %s\n", (int) result, errmsg);
@ -1833,9 +1954,10 @@ nt_service_open_scm(void)
{ {
SC_HANDLE hSCManager; SC_HANDLE hSCManager;
char *errmsg = NULL; char *errmsg = NULL;
if (nt_service_loadlibrary()<0)
if ((hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE)) return 0;
== NULL) { if ((hSCManager = service_fns.OpenSCManager_fn(
NULL, NULL, SC_MANAGER_CREATE_SERVICE)) == NULL) {
errmsg = nt_strerror(GetLastError()); errmsg = nt_strerror(GetLastError());
printf("OpenSCManager() failed : %s\n", errmsg); printf("OpenSCManager() failed : %s\n", errmsg);
LocalFree(errmsg); LocalFree(errmsg);
@ -1850,7 +1972,9 @@ nt_service_open(SC_HANDLE hSCManager)
SC_HANDLE hService; SC_HANDLE hService;
char *errmsg = NULL; char *errmsg = NULL;
if ((hService = OpenService(hSCManager, GENSRV_SERVICENAME, if (nt_service_loadlibrary()<0)
return 0;
if ((hService = service_fns.OpenService_fn(hSCManager, GENSRV_SERVICENAME,
SERVICE_ALL_ACCESS)) == NULL) { SERVICE_ALL_ACCESS)) == NULL) {
errmsg = nt_strerror(GetLastError()); errmsg = nt_strerror(GetLastError());
printf("OpenService() failed : %s\n", errmsg); printf("OpenService() failed : %s\n", errmsg);
@ -1865,15 +1989,18 @@ nt_service_start(SC_HANDLE hService)
{ {
char *errmsg = NULL; char *errmsg = NULL;
QueryServiceStatus(hService, &service_status); if (nt_service_loadlibrary()<0)
return -1;
service_fns.QueryServiceStatus_fn(hService, &service_status);
if (service_status.dwCurrentState == SERVICE_RUNNING) { if (service_status.dwCurrentState == SERVICE_RUNNING) {
printf("Service is already running\n"); printf("Service is already running\n");
return 1; return 1;
} }
if (StartService(hService, 0, NULL)) { if (service_fns.StartService_fn(hService, 0, NULL)) {
/* Loop until the service has finished attempting to start */ /* Loop until the service has finished attempting to start */
while (QueryServiceStatus(hService, &service_status)) { while (service_fns.QueryServiceStatus_fn(hService, &service_status)) {
if (service_status.dwCurrentState == SERVICE_START_PENDING) if (service_status.dwCurrentState == SERVICE_START_PENDING)
Sleep(500); Sleep(500);
else else
@ -1904,15 +2031,18 @@ int
nt_service_stop(SC_HANDLE hService) nt_service_stop(SC_HANDLE hService)
{ {
char *errmsg = NULL; char *errmsg = NULL;
if (nt_service_loadlibrary()<0)
return -1;
QueryServiceStatus(hService, &service_status); service_fns.QueryServiceStatus_fn(hService, &service_status);
if (service_status.dwCurrentState == SERVICE_STOPPED) { if (service_status.dwCurrentState == SERVICE_STOPPED) {
printf("Service is already stopped\n"); printf("Service is already stopped\n");
return 1; return 1;
} }
if (ControlService(hService, SERVICE_CONTROL_STOP, &service_status)) { if (service_fns.ControlService_fn(hService, SERVICE_CONTROL_STOP,
while (QueryServiceStatus(hService, &service_status)) { &service_status)) {
while (service_fns.QueryServiceStatus_fn(hService, &service_status)) {
if (service_status.dwCurrentState == SERVICE_STOP_PENDING) if (service_status.dwCurrentState == SERVICE_STOP_PENDING)
Sleep(500); Sleep(500);
else else
@ -1972,6 +2102,8 @@ nt_service_install(void)
char *errmsg; char *errmsg;
int len = 0; int len = 0;
if (nt_service_loadlibrary()<0)
return -1;
if (0 == GetModuleFileName(NULL, szPath, MAX_PATH)) if (0 == GetModuleFileName(NULL, szPath, MAX_PATH))
return 0; return 0;
@ -2002,7 +2134,7 @@ nt_service_install(void)
* - and changed the lpPassword param to "" instead of NULL as per an * - and changed the lpPassword param to "" instead of NULL as per an
* MSDN article. * MSDN article.
*/ */
if ((hService = CreateService(hSCManager, GENSRV_SERVICENAME, if ((hService = service_fns.CreateService_fn(hSCManager, GENSRV_SERVICENAME,
GENSRV_DISPLAYNAME, GENSRV_DISPLAYNAME,
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
SERVICE_AUTO_START, SERVICE_ERROR_IGNORE, SERVICE_AUTO_START, SERVICE_ERROR_IGNORE,
@ -2010,7 +2142,7 @@ nt_service_install(void)
NULL, NULL, NULL, NULL, "")) == NULL) { NULL, NULL, NULL, NULL, "")) == NULL) {
errmsg = nt_strerror(GetLastError()); errmsg = nt_strerror(GetLastError());
printf("CreateService() failed : %s\n", errmsg); printf("CreateService() failed : %s\n", errmsg);
CloseServiceHandle(hSCManager); service_fns.CloseServiceHandle_fn(hSCManager);
LocalFree(errmsg); LocalFree(errmsg);
tor_free(command); tor_free(command);
return 0; return 0;
@ -2018,14 +2150,15 @@ nt_service_install(void)
/* Set the service's description */ /* Set the service's description */
sdBuff.lpDescription = GENSRV_DESCRIPTION; sdBuff.lpDescription = GENSRV_DESCRIPTION;
ChangeServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION, &sdBuff); service_fns.ChangeServiceConfig2_fn(hService, SERVICE_CONFIG_DESCRIPTION,
&sdBuff);
printf("Service installed successfully\n"); printf("Service installed successfully\n");
/* Start the service initially */ /* Start the service initially */
nt_service_start(hService); nt_service_start(hService);
CloseServiceHandle(hService); service_fns.CloseServiceHandle_fn(hService);
CloseServiceHandle(hSCManager); service_fns.CloseServiceHandle_fn(hSCManager);
tor_free(command); tor_free(command);
return 0; return 0;
@ -2039,17 +2172,20 @@ nt_service_remove(void)
SC_HANDLE hService = NULL; SC_HANDLE hService = NULL;
char *errmsg; char *errmsg;
if (nt_service_loadlibrary()<0)
return -1;
if ((hSCManager = nt_service_open_scm()) == NULL) { if ((hSCManager = nt_service_open_scm()) == NULL) {
return 0; return 0;
} }
if ((hService = nt_service_open(hSCManager)) == NULL) { if ((hService = nt_service_open(hSCManager)) == NULL) {
CloseServiceHandle(hSCManager); service_fns.CloseServiceHandle_fn(hSCManager);
return 0; return 0;
} }
if (nt_service_stop(hService)) { if (nt_service_stop(hService)) {
if (DeleteService(hService)) { if (service_fns.DeleteService_fn(hService)) {
printf("Removed service successfully\n"); printf("Removed service successfully\n");
} }
else { else {
@ -2062,8 +2198,8 @@ nt_service_remove(void)
printf("Service could not be removed\n"); printf("Service could not be removed\n");
} }
CloseServiceHandle(hService); service_fns.CloseServiceHandle_fn(hService);
CloseServiceHandle(hSCManager); service_fns.CloseServiceHandle_fn(hSCManager);
return 0; return 0;
} }
@ -2151,6 +2287,10 @@ tor_main(int argc, char *argv[])
backup_argc = argc; backup_argc = argc;
if ((argc >= 3) && if ((argc >= 3) &&
(!strcmp(argv[1], "-service") || !strcmp(argv[1], "--service"))) { (!strcmp(argv[1], "-service") || !strcmp(argv[1], "--service"))) {
if (nt_service_loadlibrary() < 0) {
printf("Unable to load library support for NT services.\n");
return -1;
}
if (!strcmp(argv[2], "install")) if (!strcmp(argv[2], "install"))
return nt_service_install(); return nt_service_install();
if (!strcmp(argv[2], "remove")) if (!strcmp(argv[2], "remove"))
@ -2164,6 +2304,10 @@ tor_main(int argc, char *argv[])
} }
// These are left so as not to confuse people who are used to these options // These are left so as not to confuse people who are used to these options
if (argc >= 2) { if (argc >= 2) {
if (nt_service_loadlibrary() < 0) {
printf("Unable to load library support for NT services.\n");
return -1;
}
if (!strcmp(argv[1], "-install") || !strcmp(argv[1], "--install")) if (!strcmp(argv[1], "-install") || !strcmp(argv[1], "--install"))
return nt_service_install(); return nt_service_install();
if (!strcmp(argv[1], "-remove") || !strcmp(argv[1], "--remove")) if (!strcmp(argv[1], "-remove") || !strcmp(argv[1], "--remove"))