Windows Service support.

Program can now be started as a Windows Service. No additional
arguments needed. Refer to `service_install` and `service_remove`
scripts in released zip file.
This commit is contained in:
ValdikSS 2017-12-20 17:03:22 +03:00
parent 95765f3ed9
commit 23babdc8fa
5 changed files with 103 additions and 21 deletions

View File

@ -79,26 +79,8 @@ And for x86_64:
# How to install as Windows Service # How to install as Windows Service
One way is using an [srvstart](http://www.rozanski.org.uk/software) program. Use `service_install_russia_blacklist.cmd`, `service_install_russia_blacklist_dnsredir.cmd` and `service_remove.cmd` scripts.
Unpack it to `goodbyedpi` directory and create 3 files: Modify them according to your own needs.
*goodbyedpi.ini*
```INI
[GoodByeDPI]
startup=goodbyedpi.exe
shutdown_method=winmessage
auto_restart=n
```
*srvinstall.bat*
```Batchfile
srvstart install GoodByeDPI -c %CD%\goodbyedpi.ini
```
*srvremove.bat*
```Batchfile
srvstart remove GoodByeDPI
```
Run these batch files as Administrator to install/remove service.
Open Windows Services panel to run service or make it start automaticaly.
# Similar projects # Similar projects

View File

@ -11,6 +11,7 @@
#include <getopt.h> #include <getopt.h>
#include "windivert.h" #include "windivert.h"
#include "goodbyedpi.h" #include "goodbyedpi.h"
#include "service.h"
#include "dnsredir.h" #include "dnsredir.h"
#include "blackwhitelist.h" #include "blackwhitelist.h"
@ -52,6 +53,7 @@
} \ } \
} while (0) } while (0)
static int running_from_service = 0;
static HANDLE filters[MAX_FILTERS]; static HANDLE filters[MAX_FILTERS];
static int filter_num = 0; static int filter_num = 0;
static const char *http10_redirect_302 = "HTTP/1.0 302 "; static const char *http10_redirect_302 = "HTTP/1.0 302 ";
@ -144,7 +146,7 @@ static int deinit(HANDLE handle) {
return FALSE; return FALSE;
} }
static void deinit_all() { void deinit_all() {
for (int i = 0; i < filter_num; i++) { for (int i = 0; i < filter_num; i++) {
deinit(filters[i]); deinit(filters[i]);
} }
@ -277,6 +279,15 @@ int main(int argc, char *argv[]) {
char *hdr_name_addr = NULL, *hdr_value_addr = NULL; char *hdr_name_addr = NULL, *hdr_value_addr = NULL;
int hdr_value_len; int hdr_value_len;
if (!running_from_service && service_register(argc, argv)) {
/* We've been called as a service. Register service
* and exit this thread. main() would be called from
* service.c next time.
*/
running_from_service = 1;
return 0;
}
if (filter_string == NULL) { if (filter_string == NULL) {
filter_string = malloc(strlen(filter_string_template) + 1); filter_string = malloc(strlen(filter_string_template) + 1);
strcpy(filter_string, filter_string_template); strcpy(filter_string, filter_string_template);

View File

@ -5,3 +5,6 @@
#else #else
#define debug(...) printf(__VA_ARGS__) #define debug(...) printf(__VA_ARGS__)
#endif #endif
int main(int argc, char *argv[]);
void deinit_all();

83
service.c Normal file
View File

@ -0,0 +1,83 @@
#include <windows.h>
#include <stdio.h>
#include "goodbyedpi.h"
#include "service.h"
#define SERVICE_NAME "GoodbyeDPI"
static SERVICE_STATUS ServiceStatus;
static SERVICE_STATUS_HANDLE hStatus;
static int service_argc;
static char **service_argv;
int service_register(int argc, char *argv[])
{
SERVICE_TABLE_ENTRY ServiceTable[] = {
{SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION)service_main},
{NULL, NULL}
};
/*
* Save argc & argv as service_main is called with different
* arguments, which are passed from "start" command, not
* from the program command line.
* We don't need this behaviour.
*/
service_argc = argc;
service_argv = malloc(sizeof(void*) * argc);
for (int i = 0; i < argc; i++) {
service_argv[i] = strdup(argv[i]);
}
return StartServiceCtrlDispatcher(ServiceTable);
}
void service_main(int argc __attribute__((unused)),
char *argv[] __attribute__((unused)))
{
ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
ServiceStatus.dwCurrentState = SERVICE_RUNNING;
ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwServiceSpecificExitCode = 0;
ServiceStatus.dwCheckPoint = 1;
ServiceStatus.dwWaitHint = 0;
hStatus = RegisterServiceCtrlHandler(
SERVICE_NAME,
(LPHANDLER_FUNCTION)service_controlhandler);
if (hStatus == (SERVICE_STATUS_HANDLE)0)
{
// Registering Control Handler failed
return;
}
SetServiceStatus(hStatus, &ServiceStatus);
// Calling main with saved argc & argv
main(service_argc, service_argv);
if (ServiceStatus.dwCurrentState != SERVICE_STOPPED) {
// If terminated with error
ServiceStatus.dwWin32ExitCode = 1;
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus (hStatus, &ServiceStatus);
}
return;
}
// Control handler function
void service_controlhandler(DWORD request)
{
switch(request)
{
case SERVICE_CONTROL_STOP:
case SERVICE_CONTROL_SHUTDOWN:
deinit_all();
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
default:
break;
}
// Report current status
SetServiceStatus (hStatus, &ServiceStatus);
return;
}

3
service.h Normal file
View File

@ -0,0 +1,3 @@
int service_register();
void service_main(int argc, char *argv[]);
void service_controlhandler(DWORD request);