mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-27 22:03:31 +01:00
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:
parent
e230fe8ea6
commit
1c01797c16
194
src/or/main.c
194
src/or/main.c
@ -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"))
|
||||||
|
Loading…
Reference in New Issue
Block a user