Merge pull request #404 from pvpgn/master
Pull changes in master branch into develop branch
This commit is contained in:
commit
bd58cf32c5
8 changed files with 325 additions and 225 deletions
|
@ -79,7 +79,7 @@ make
|
|||
make install
|
||||
```
|
||||
|
||||
#### Ubuntu 16.04
|
||||
#### Ubuntu 16.04, 18.04
|
||||
```
|
||||
sudo apt-get -y install build-essential git cmake zlib1g-dev
|
||||
git clone https://github.com/pvpgn/pvpgn-server.git
|
||||
|
@ -102,7 +102,7 @@ cd pvpgn-server && cmake -G "Unix Makefiles" -H./ -B./build
|
|||
cd build && make
|
||||
```
|
||||
|
||||
#### Debian 8
|
||||
#### Debian 8 with clang compiler
|
||||
```
|
||||
sudo apt-get -y install build-essential zlib1g-dev clang libc++-dev git
|
||||
wget https://cmake.org/files/v3.7/cmake-3.7.1-Linux-x86_64.tar.gz
|
||||
|
@ -143,6 +143,11 @@ cd build && make
|
|||
|
||||
Full instructions: [Русский](http://harpywar.com/?a=articles&b=2&c=1&d=74) | [English](http://harpywar.com/?a=articles&b=2&c=1&d=74&lang=en)
|
||||
|
||||
## Hosting on LAN or VPS with private IP address
|
||||
Some VPS providers do not assign your server a direct public IP. If that is the case or you host at home behind NAT you need to setup the route translation in `address_translation.conf`. The public address is pushed as the route server address to game clients when seeking games. Failure to push the correct address to game clients results in players not being able to match and join games (long game search and error).
|
||||
|
||||
If your network interface is directly bound to public IP, PvPGN can figure it out on it's own and this step is not necessary.
|
||||
|
||||
## License
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
|
|
|
@ -35,24 +35,44 @@
|
|||
# ${-19} - substitute arguments 0-19 here #
|
||||
# ${2-} - substitue all arguments from 2 until the end here #
|
||||
# #
|
||||
@
|
||||
//doubt //dt //d
|
||||
[0]/me looks with doubt
|
||||
[1+]/me looks at ${1-} with doubt
|
||||
@
|
||||
//numusers //nu
|
||||
[0]%IThere are %u users online.
|
||||
[0]%IThere are %g games online.
|
||||
[0]%IThere are %c channels online.
|
||||
[1+]%EThat command does not take any arguments.
|
||||
@
|
||||
//askban //ab
|
||||
[2+]/w $1 Please ban ${2-}.
|
||||
@
|
||||
//statsme //sm
|
||||
[0]/stats %u
|
||||
@
|
||||
//pvpgn
|
||||
[*]/announce PVPGN rulez!
|
||||
# %a - Number of registered accounts #
|
||||
# %c - Number of existing channels #
|
||||
# %g - Number of running games #
|
||||
# %G - Number of games with the same clienttag #
|
||||
# %h - Hostname of the server #
|
||||
# %H - Contact name (as set in bnetd.conf) #
|
||||
# %i - The userid of the user #
|
||||
# %I - The username of the user #
|
||||
# %N - Name of the game the user has connected with #
|
||||
# %m - Check the user's mail #
|
||||
# %r - IP address of the user #
|
||||
# %s - Servername #
|
||||
# %t - The clienttag of the user #
|
||||
# %u - Number of users currently logged in #
|
||||
# %U - Number of users logged in with the same clienttag #
|
||||
# %v - Server version #
|
||||
# #
|
||||
# Examples #
|
||||
#@
|
||||
#//doubt //dt //d
|
||||
#[0]/me looks with doubt
|
||||
#[1+]/me looks at ${1-} with doubt
|
||||
#@
|
||||
#//numusers //nu
|
||||
#[0]%IThere are %u users online.
|
||||
#[0]%IThere are %g games online.
|
||||
#[0]%IThere are %c channels online.
|
||||
#[1+]%EThat command does not take any arguments.
|
||||
#@
|
||||
#//askban //ab
|
||||
#[2+]/w $1 Please ban ${2-}.
|
||||
#@
|
||||
#//statsme //sm
|
||||
#[0]/stats %u
|
||||
#@
|
||||
#//pvpgn
|
||||
#[*]/announce PVPGN rulez!
|
||||
#
|
||||
|
||||
# #
|
||||
##############################################################################
|
||||
|
|
|
@ -419,12 +419,12 @@ max_friends = 20
|
|||
# Set track=0 to disable tracking. Any other number will set number
|
||||
# of seconds between sending tracking packets. This is ON by default.
|
||||
#track = 0
|
||||
track = 0
|
||||
track = 60
|
||||
|
||||
# Tracking server(s)
|
||||
# Use a comma delimited list of hostnames with optional UDP port numbers
|
||||
# after colons. (port 6114 is the default for the newer tracking protocol)
|
||||
trackaddrs = "track.pvpgn.org,bntrack.darkwings.org,bnet.mivabe.nl,track.eurobattle.net"
|
||||
trackaddrs = "track.pvpgn.pro,track.pvpgn.org,bntrack.darkwings.org,bnet.mivabe.nl,track.eurobattle.net"
|
||||
|
||||
# Change these to match your system, for example:
|
||||
location = "unknown"
|
||||
|
|
|
@ -407,7 +407,7 @@ track = 60
|
|||
# Tracking server(s)
|
||||
# Use a comma delimited list of hostnames with optional UDP port numbers
|
||||
# after colons. (port 6114 is the default for the newer tracking protocol)
|
||||
trackaddrs = "track.pvpgn.org,bntrack.darkwings.org,bnet.mivabe.nl,track.eurobattle.net"
|
||||
trackaddrs = "track.pvpgn.pro,track.pvpgn.org,bntrack.darkwings.org,bnet.mivabe.nl,track.eurobattle.net"
|
||||
|
||||
# Change these to match your system, for example:
|
||||
location = "unknown"
|
||||
|
|
|
@ -864,6 +864,21 @@
|
|||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"PMAC": {
|
||||
"0x4f": {
|
||||
"checkRevisionFile": "PMACver1.mpq",
|
||||
"equation": "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B",
|
||||
"entries": [
|
||||
{
|
||||
"title": "Warcraft II BNE 2.02",
|
||||
"version": "2.0.2.1",
|
||||
"hash": "0xaed93b05",
|
||||
"fileMetadata": "Warcraft II BNE 05/21/101 15:44:14 931587",
|
||||
"versionTag": "W2BN_202"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"STAR": {
|
||||
|
@ -1329,6 +1344,21 @@
|
|||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"PMAC": {
|
||||
"0xd1": {
|
||||
"checkRevisionFile": "PMACver1.mpq",
|
||||
"equation": "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B",
|
||||
"entries": [
|
||||
{
|
||||
"title": "Starcraft - Broodwar (Expansion) 1.15 - (Starcraft mode)",
|
||||
"version": "1.15.0.1",
|
||||
"hash": "0xeb5f82bd",
|
||||
"fileMetadata": "Starcraft 07/16/107 18:00:00 1606200",
|
||||
"versionTag": "STAR_115"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"SEXP": {
|
||||
|
@ -1613,6 +1643,21 @@
|
|||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"PMAC": {
|
||||
"0xd1": {
|
||||
"checkRevisionFile": "PMACver1.mpq",
|
||||
"equation": "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B",
|
||||
"entries": [
|
||||
{
|
||||
"title": "Starcraft - Broodwar (Expansion) 1.15 - (Broodwar mode)",
|
||||
"version": "1.15.0.1",
|
||||
"hash": "0xeb5f82bd",
|
||||
"fileMetadata": "Starcraft 07/16/107 18:00:00 1606200",
|
||||
"versionTag": "SEXP_115"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"DRTL": {
|
||||
|
@ -1650,6 +1695,34 @@
|
|||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"PMAC": {
|
||||
"0x2a": {
|
||||
"checkRevisionFile": "PMACver1.mpq",
|
||||
"equation": "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B",
|
||||
"entries": [
|
||||
{
|
||||
"title": "Diablo 109",
|
||||
"version": "1.0.9.2",
|
||||
"hash": "0x2b079060",
|
||||
"fileMetadata": "Diablo 05/12/101 15:42:00 1160990",
|
||||
"versionTag": "DRTL_109"
|
||||
}
|
||||
]
|
||||
},
|
||||
"0x28": {
|
||||
"checkRevisionFile": "PMACver1.mpq",
|
||||
"equation": "A=3845581634 B=880823580 C=1363937103 4 A=A-S B=B-C C=C-A A=A-B",
|
||||
"entries": [
|
||||
{
|
||||
"title": "Diablo 108",
|
||||
"version": "1.0.8.0",
|
||||
"hash": "0x82f94d6a",
|
||||
"fileMetadata": "Diablo 06/13/100 12:00:00 1113966",
|
||||
"versionTag": "DRTL_108"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"D2XP": {
|
||||
|
|
|
@ -854,57 +854,74 @@ static int on_client_charlistreq(t_connection * c, t_packet * packet)
|
|||
packet_set_type(rpacket,D2CS_CLIENT_CHARLISTREPLY);
|
||||
bn_short_set(&rpacket->u.d2cs_client_charlistreply.u1,0);
|
||||
n=0;
|
||||
try {
|
||||
Directory dir(path);
|
||||
while ((charname=dir.read())) {
|
||||
charinfo = (t_d2charinfo_file*)xmalloc(sizeof(t_d2charinfo_file));
|
||||
if (d2charinfo_load(account,charname,charinfo)<0) {
|
||||
eventlog(eventlog_level_error,__FUNCTION__,"error loading charinfo for {}(*{})",charname,account);
|
||||
xfree((void *)charinfo);
|
||||
continue;
|
||||
bool retry = true;
|
||||
while (retry)
|
||||
{
|
||||
try {
|
||||
Directory dir(path);
|
||||
while ((charname = dir.read())) {
|
||||
charinfo = (t_d2charinfo_file*)xmalloc(sizeof(t_d2charinfo_file));
|
||||
if (d2charinfo_load(account, charname, charinfo) < 0) {
|
||||
eventlog(eventlog_level_error, __FUNCTION__, "error loading charinfo for {}(*{})", charname, account);
|
||||
xfree((void*)charinfo);
|
||||
continue;
|
||||
}
|
||||
eventlog(eventlog_level_debug, __FUNCTION__, "adding char {} (*{})", charname, account);
|
||||
d2charlist_add_char(&charlist_head, charinfo, 0);
|
||||
n++;
|
||||
if (n >= maxchar) break;
|
||||
}
|
||||
eventlog(eventlog_level_debug,__FUNCTION__,"adding char {} (*{})", charname, account);
|
||||
d2charlist_add_char(&charlist_head,charinfo,0);
|
||||
n++;
|
||||
if (n>=maxchar) break;
|
||||
}
|
||||
if (prefs_allow_newchar() && (n<maxchar)) {
|
||||
bn_short_set(&rpacket->u.d2cs_client_charlistreply.maxchar,maxchar);
|
||||
} else {
|
||||
bn_short_set(&rpacket->u.d2cs_client_charlistreply.maxchar,0);
|
||||
}
|
||||
if (!std::strcmp(charlist_sort_order, "ASC"))
|
||||
{
|
||||
t_elist * curr, * safe;
|
||||
t_d2charlist * ccharlist;
|
||||
if (prefs_allow_newchar() && (n < maxchar)) {
|
||||
bn_short_set(&rpacket->u.d2cs_client_charlistreply.maxchar, maxchar);
|
||||
}
|
||||
else {
|
||||
bn_short_set(&rpacket->u.d2cs_client_charlistreply.maxchar, 0);
|
||||
}
|
||||
if (!std::strcmp(charlist_sort_order, "ASC"))
|
||||
{
|
||||
t_elist* curr, * safe;
|
||||
t_d2charlist* ccharlist;
|
||||
|
||||
elist_for_each_safe(curr,&charlist_head,safe)
|
||||
{
|
||||
ccharlist = elist_entry(curr,t_d2charlist,list);
|
||||
packet_append_string(rpacket,(char*)ccharlist->charinfo->header.charname);
|
||||
packet_append_string(rpacket,(char *)&ccharlist->charinfo->portrait);
|
||||
xfree((void *)ccharlist->charinfo);
|
||||
xfree((void *)ccharlist);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
t_elist * curr, * safe;
|
||||
t_d2charlist * ccharlist;
|
||||
elist_for_each_safe(curr, &charlist_head, safe)
|
||||
{
|
||||
ccharlist = elist_entry(curr, t_d2charlist, list);
|
||||
packet_append_string(rpacket, (char*)ccharlist->charinfo->header.charname);
|
||||
packet_append_string(rpacket, (char*)&ccharlist->charinfo->portrait);
|
||||
xfree((void*)ccharlist->charinfo);
|
||||
xfree((void*)ccharlist);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
t_elist* curr, * safe;
|
||||
t_d2charlist* ccharlist;
|
||||
|
||||
elist_for_each_safe_rev(curr,&charlist_head,safe)
|
||||
{
|
||||
ccharlist = elist_entry(curr,t_d2charlist,list);
|
||||
packet_append_string(rpacket,(char*)ccharlist->charinfo->header.charname);
|
||||
packet_append_string(rpacket,(char *)&ccharlist->charinfo->portrait);
|
||||
xfree((void *)ccharlist->charinfo);
|
||||
xfree((void *)ccharlist);
|
||||
elist_for_each_safe_rev(curr, &charlist_head, safe)
|
||||
{
|
||||
ccharlist = elist_entry(curr, t_d2charlist, list);
|
||||
packet_append_string(rpacket, (char*)ccharlist->charinfo->header.charname);
|
||||
packet_append_string(rpacket, (char*)&ccharlist->charinfo->portrait);
|
||||
xfree((void*)ccharlist->charinfo);
|
||||
xfree((void*)ccharlist);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
retry = false;
|
||||
}
|
||||
catch (const Directory::OpenError&) {
|
||||
ERROR1("(*{}) charinfo directory do not exist, building it", account);
|
||||
if (p_mkdir(path, S_IRWXU) == 0)
|
||||
{
|
||||
INFO1("Successfully created charinfo directory ({})", path);
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR2("Failed to create charinfo directory ({}), errno = {}", path, errno);
|
||||
retry = false;
|
||||
bn_short_set(&rpacket->u.d2cs_client_charlistreply.maxchar, 0);
|
||||
}
|
||||
}
|
||||
} catch(const Directory::OpenError&) {
|
||||
INFO1("(*{}) charinfo directory do not exist, building it",account);
|
||||
p_mkdir(path,S_IRWXU);
|
||||
}
|
||||
bn_short_set(&rpacket->u.d2cs_client_charlistreply.currchar,n);
|
||||
bn_short_set(&rpacket->u.d2cs_client_charlistreply.currchar2,n);
|
||||
|
@ -953,70 +970,87 @@ static int on_client_charlistreq_110(t_connection * c, t_packet * packet)
|
|||
packet_set_type(rpacket,D2CS_CLIENT_CHARLISTREPLY_110);
|
||||
bn_short_set(&rpacket->u.d2cs_client_charlistreply_110.u1,0);
|
||||
n=0;
|
||||
try {
|
||||
Directory dir(path);
|
||||
bool retry = true;
|
||||
while (retry)
|
||||
{
|
||||
try {
|
||||
Directory dir(path);
|
||||
|
||||
exp_time = prefs_get_char_expire_time();
|
||||
while ((charname=dir.read())) {
|
||||
charinfo = (t_d2charinfo_file*)xmalloc(sizeof(t_d2charinfo_file));
|
||||
if (d2charinfo_load(account,charname,charinfo)<0) {
|
||||
eventlog(eventlog_level_error,__FUNCTION__,"error loading charinfo for {}(*{})",charname,account);
|
||||
xfree(charinfo);
|
||||
continue;
|
||||
exp_time = prefs_get_char_expire_time();
|
||||
while ((charname = dir.read())) {
|
||||
charinfo = (t_d2charinfo_file*)xmalloc(sizeof(t_d2charinfo_file));
|
||||
if (d2charinfo_load(account, charname, charinfo) < 0) {
|
||||
eventlog(eventlog_level_error, __FUNCTION__, "error loading charinfo for {}(*{})", charname, account);
|
||||
xfree(charinfo);
|
||||
continue;
|
||||
}
|
||||
if (exp_time) {
|
||||
curr_exp_time = bn_int_get(charinfo->header.last_time) + exp_time;
|
||||
}
|
||||
else {
|
||||
curr_exp_time = 0x7FFFFFFF;
|
||||
}
|
||||
eventlog(eventlog_level_debug, __FUNCTION__, "adding char {} (*{})", charname, account);
|
||||
d2charlist_add_char(&charlist_head, charinfo, curr_exp_time);
|
||||
n++;
|
||||
if (n >= maxchar) break;
|
||||
}
|
||||
if (exp_time) {
|
||||
curr_exp_time = bn_int_get(charinfo->header.last_time)+exp_time;
|
||||
} else {
|
||||
curr_exp_time = 0x7FFFFFFF;
|
||||
if (n >= maxchar)
|
||||
maxchar = 0;
|
||||
|
||||
if (!std::strcmp(charlist_sort_order, "ASC"))
|
||||
{
|
||||
t_elist* curr, * safe;
|
||||
t_d2charlist* ccharlist;
|
||||
|
||||
elist_for_each_safe(curr, &charlist_head, safe)
|
||||
{
|
||||
bn_int bn_exp_time;
|
||||
|
||||
ccharlist = elist_entry(curr, t_d2charlist, list);
|
||||
bn_int_set(&bn_exp_time, ccharlist->expiration_time);
|
||||
packet_append_data(rpacket, bn_exp_time, sizeof(bn_exp_time));
|
||||
packet_append_string(rpacket, (char*)ccharlist->charinfo->header.charname);
|
||||
packet_append_string(rpacket, (char*)&ccharlist->charinfo->portrait);
|
||||
xfree((void*)ccharlist->charinfo);
|
||||
xfree((void*)ccharlist);
|
||||
}
|
||||
}
|
||||
eventlog(eventlog_level_debug,__FUNCTION__,"adding char {} (*{})", charname, account);
|
||||
d2charlist_add_char(&charlist_head,charinfo,curr_exp_time);
|
||||
n++;
|
||||
if (n>=maxchar) break;
|
||||
else
|
||||
{
|
||||
t_elist* curr, * safe;
|
||||
t_d2charlist* ccharlist;
|
||||
|
||||
elist_for_each_safe_rev(curr, &charlist_head, safe)
|
||||
{
|
||||
bn_int bn_exp_time;
|
||||
|
||||
ccharlist = elist_entry(curr, t_d2charlist, list);
|
||||
bn_int_set(&bn_exp_time, ccharlist->expiration_time);
|
||||
packet_append_data(rpacket, bn_exp_time, sizeof(bn_exp_time));
|
||||
packet_append_string(rpacket, (char*)ccharlist->charinfo->header.charname);
|
||||
packet_append_string(rpacket, (char*)&ccharlist->charinfo->portrait);
|
||||
xfree((void*)ccharlist->charinfo);
|
||||
xfree((void*)ccharlist);
|
||||
}
|
||||
}
|
||||
|
||||
retry = false;
|
||||
}
|
||||
if (n>=maxchar)
|
||||
maxchar = 0;
|
||||
|
||||
if (!std::strcmp(charlist_sort_order, "ASC"))
|
||||
{
|
||||
t_elist * curr, *safe;
|
||||
t_d2charlist * ccharlist;
|
||||
|
||||
elist_for_each_safe(curr,&charlist_head,safe)
|
||||
{
|
||||
bn_int bn_exp_time;
|
||||
|
||||
ccharlist = elist_entry(curr,t_d2charlist,list);
|
||||
bn_int_set(&bn_exp_time,ccharlist->expiration_time);
|
||||
packet_append_data(rpacket,bn_exp_time,sizeof(bn_exp_time));
|
||||
packet_append_string(rpacket,(char*)ccharlist->charinfo->header.charname);
|
||||
packet_append_string(rpacket,(char *)&ccharlist->charinfo->portrait);
|
||||
xfree((void *)ccharlist->charinfo);
|
||||
xfree((void *)ccharlist);
|
||||
}
|
||||
catch (const Directory::OpenError&) {
|
||||
ERROR1("(*{}) charinfo directory do not exist, building it", account);
|
||||
if (p_mkdir(path, S_IRWXU) == 0)
|
||||
{
|
||||
INFO1("Successfully created charinfo directory ({})", path);
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR2("Failed to create charinfo directory ({}), errno = {}", path, errno);
|
||||
retry = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
t_elist * curr, *safe;
|
||||
t_d2charlist * ccharlist;
|
||||
|
||||
elist_for_each_safe_rev(curr,&charlist_head,safe)
|
||||
{
|
||||
bn_int bn_exp_time;
|
||||
|
||||
ccharlist = elist_entry(curr,t_d2charlist,list);
|
||||
bn_int_set(&bn_exp_time,ccharlist->expiration_time);
|
||||
packet_append_data(rpacket,bn_exp_time,sizeof(bn_exp_time));
|
||||
packet_append_string(rpacket,(char*)ccharlist->charinfo->header.charname);
|
||||
packet_append_string(rpacket,(char *)&ccharlist->charinfo->portrait);
|
||||
xfree((void *)ccharlist->charinfo);
|
||||
xfree((void *)ccharlist);
|
||||
}
|
||||
}
|
||||
} catch (const Directory::OpenError&) {
|
||||
INFO1("(*{}) charinfo directory do not exist, building it",account);
|
||||
p_mkdir(path,S_IRWXU);
|
||||
}
|
||||
|
||||
bn_short_set(&rpacket->u.d2cs_client_charlistreply.currchar,n);
|
||||
bn_short_set(&rpacket->u.d2cs_client_charlistreply.currchar2,n);
|
||||
bn_short_set(&rpacket->u.d2cs_client_charlistreply.maxchar,maxchar);
|
||||
|
|
|
@ -1,5 +1,15 @@
|
|||
#include "console_resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
#ifndef __BORLANDC__
|
||||
#ifdef __AFXRES_H__
|
||||
#include "afxres.h"
|
||||
#else
|
||||
#include "winres.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Icon */
|
||||
ID_ICON1 ICON DISCARDABLE "win32/logo01.ico"
|
||||
|
||||
|
|
|
@ -17,13 +17,9 @@
|
|||
#ifdef WIN32
|
||||
|
||||
#include <cstring>
|
||||
#include <cwchar>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#ifndef WINADVAPI
|
||||
#if !defined(WINADVAPI)
|
||||
#if !defined(_ADVAPI32_)
|
||||
#define WINADVAPI DECLSPEC_IMPORT
|
||||
#else
|
||||
|
@ -38,100 +34,72 @@ extern char serviceDescription[];
|
|||
extern int g_ServiceStatus;
|
||||
|
||||
#ifdef WIN32_GUI
|
||||
extern int app_main(int argc, char ** argv);
|
||||
extern int app_main(int argc, char** argv);
|
||||
#else
|
||||
extern int main(int argc, char ** argv);
|
||||
extern int main(int argc, char** argv);
|
||||
#endif
|
||||
|
||||
SERVICE_STATUS serviceStatus;
|
||||
SERVICE_STATUS_HANDLE serviceStatusHandle = 0;
|
||||
|
||||
typedef WINADVAPI BOOL(WINAPI *CSD_T)(SC_HANDLE hService, DWORD dwInfoLevel, LPVOID lpInfo);
|
||||
typedef WINADVAPI BOOL(WINAPI* CSD_T)(SC_HANDLE, DWORD, LPCVOID);
|
||||
|
||||
void Win32_ServiceInstall()
|
||||
{
|
||||
SC_HANDLE serviceControlManager = OpenSCManagerW(nullptr, nullptr, SC_MANAGER_CREATE_SERVICE);
|
||||
if (!serviceControlManager)
|
||||
{
|
||||
return;
|
||||
}
|
||||
SERVICE_DESCRIPTIONA sdBuf;
|
||||
CSD_T ChangeServiceDescription;
|
||||
HMODULE advapi32;
|
||||
SC_HANDLE serviceControlManager = OpenSCManagerA(0, 0, SC_MANAGER_CREATE_SERVICE);
|
||||
|
||||
wchar_t path[MAX_PATH + 10] = {};
|
||||
if (GetModuleFileNameW(nullptr, path, sizeof path / sizeof *path) != 0)
|
||||
if (serviceControlManager)
|
||||
{
|
||||
return;
|
||||
}
|
||||
char path[_MAX_PATH + 10];
|
||||
if (GetModuleFileNameA(0, path, sizeof(path) / sizeof(path[0])) > 0)
|
||||
{
|
||||
SC_HANDLE service;
|
||||
std::strcat(path, " --service");
|
||||
service = CreateServiceA(serviceControlManager,
|
||||
serviceName, serviceLongName,
|
||||
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
|
||||
SERVICE_AUTO_START, SERVICE_ERROR_IGNORE, path,
|
||||
0, 0, 0, 0, 0);
|
||||
if (service)
|
||||
{
|
||||
sdBuf.lpDescription = serviceDescription;
|
||||
|
||||
std::wcscat(path, L"--service");
|
||||
if (!(advapi32 = GetModuleHandleA("ADVAPI32.DLL")))
|
||||
{
|
||||
CloseServiceHandle(service);
|
||||
CloseServiceHandle(serviceControlManager);
|
||||
return;
|
||||
}
|
||||
|
||||
auto utf8_decode = [](const std::string& str)
|
||||
{
|
||||
if (str.empty())
|
||||
return std::wstring();
|
||||
int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0);
|
||||
std::wstring wstrTo(size_needed, 0);
|
||||
MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &wstrTo[0], size_needed);
|
||||
return wstrTo;
|
||||
};
|
||||
if (!(ChangeServiceDescription = (CSD_T)GetProcAddress(advapi32, "ChangeServiceConfig2A")))
|
||||
{
|
||||
CloseServiceHandle(service);
|
||||
CloseServiceHandle(serviceControlManager);
|
||||
return;
|
||||
}
|
||||
|
||||
SC_HANDLE service = CreateServiceW(serviceControlManager,
|
||||
utf8_decode(serviceName).c_str(), utf8_decode(serviceLongName).c_str(),
|
||||
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
|
||||
SERVICE_AUTO_START, SERVICE_ERROR_IGNORE, path,
|
||||
0, 0, 0, 0, 0);
|
||||
if (service == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SERVICE_DESCRIPTIONW sdBuf = {};
|
||||
auto temp = utf8_decode(serviceDescription);
|
||||
std::vector<wchar_t> buffer(temp.begin(), temp.end());
|
||||
sdBuf.lpDescription = buffer.data();
|
||||
|
||||
HMODULE advapi32 = GetModuleHandleW(L"advapi32.dll");
|
||||
if (advapi32 == NULL)
|
||||
{
|
||||
CloseServiceHandle(service);
|
||||
ChangeServiceDescription(
|
||||
service, // handle to service
|
||||
SERVICE_CONFIG_DESCRIPTION, // change: description
|
||||
&sdBuf);
|
||||
CloseServiceHandle(service);
|
||||
}
|
||||
}
|
||||
CloseServiceHandle(serviceControlManager);
|
||||
return;
|
||||
}
|
||||
|
||||
auto ChangeServiceDescription = reinterpret_cast<CSD_T>(GetProcAddress(advapi32, "ChangeServiceConfig2W"));
|
||||
if (ChangeServiceDescription == NULL)
|
||||
{
|
||||
CloseServiceHandle(service);
|
||||
CloseServiceHandle(serviceControlManager);
|
||||
return;
|
||||
}
|
||||
|
||||
ChangeServiceDescription(
|
||||
service, // handle to service
|
||||
SERVICE_CONFIG_DESCRIPTION, // change: description
|
||||
&sdBuf);
|
||||
CloseServiceHandle(service);
|
||||
|
||||
CloseServiceHandle(serviceControlManager);
|
||||
}
|
||||
|
||||
void Win32_ServiceUninstall()
|
||||
{
|
||||
SC_HANDLE serviceControlManager = OpenSCManagerW(nullptr, nullptr, SC_MANAGER_CONNECT);
|
||||
SC_HANDLE serviceControlManager = OpenSCManagerA(0, 0, SC_MANAGER_CONNECT);
|
||||
|
||||
if (serviceControlManager)
|
||||
{
|
||||
auto utf8_decode = [](const std::string& str)
|
||||
{
|
||||
if (str.empty())
|
||||
return std::wstring();
|
||||
int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0);
|
||||
std::wstring wstrTo(size_needed, 0);
|
||||
MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &wstrTo[0], size_needed);
|
||||
return wstrTo;
|
||||
};
|
||||
|
||||
SC_HANDLE service = OpenServiceW(serviceControlManager,
|
||||
utf8_decode(serviceName).c_str(), SERVICE_QUERY_STATUS | DELETE);
|
||||
SC_HANDLE service = OpenServiceA(serviceControlManager,
|
||||
serviceName, SERVICE_QUERY_STATUS | DELETE);
|
||||
if (service)
|
||||
{
|
||||
SERVICE_STATUS serviceStatus;
|
||||
|
@ -201,29 +169,17 @@ void WINAPI ServiceMain(DWORD argc, char* argv[])
|
|||
serviceStatus.dwCheckPoint = 0;
|
||||
serviceStatus.dwWaitHint = 0;
|
||||
|
||||
auto utf8_decode = [](const std::string& str)
|
||||
{
|
||||
if (str.empty())
|
||||
return std::wstring();
|
||||
int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0);
|
||||
std::wstring wstrTo(size_needed, 0);
|
||||
MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &wstrTo[0], size_needed);
|
||||
return wstrTo;
|
||||
};
|
||||
|
||||
serviceStatusHandle = RegisterServiceCtrlHandlerW(utf8_decode(serviceName).c_str(), ServiceControlHandler);
|
||||
serviceStatusHandle = RegisterServiceCtrlHandlerA(serviceName, ServiceControlHandler);
|
||||
|
||||
if (serviceStatusHandle)
|
||||
{
|
||||
wchar_t path[MAX_PATH + 1] = {};
|
||||
unsigned last_slash = 0;
|
||||
char path[_MAX_PATH + 1];
|
||||
unsigned int i, last_slash = 0;
|
||||
|
||||
GetModuleFileNameW(0, path, sizeof path / sizeof *path);
|
||||
GetModuleFileNameA(0, path, sizeof(path) / sizeof(path[0]));
|
||||
|
||||
for (std::size_t i = 0; i < std::wcslen(path); i++)
|
||||
{
|
||||
if (path[i] == '\\')
|
||||
last_slash = i;
|
||||
for (i = 0; i < std::strlen(path); i++) {
|
||||
if (path[i] == '\\') last_slash = i;
|
||||
}
|
||||
|
||||
path[last_slash] = 0;
|
||||
|
@ -233,7 +189,7 @@ void WINAPI ServiceMain(DWORD argc, char* argv[])
|
|||
SetServiceStatus(serviceStatusHandle, &serviceStatus);
|
||||
|
||||
// do initialisation here
|
||||
SetCurrentDirectoryW(path);
|
||||
SetCurrentDirectoryA(path);
|
||||
|
||||
// running
|
||||
serviceStatus.dwControlsAccepted |= (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN);
|
||||
|
@ -277,7 +233,9 @@ void Win32_ServiceRun()
|
|||
{ 0, 0 }
|
||||
};
|
||||
|
||||
StartServiceCtrlDispatcherA(serviceTable);
|
||||
if (!StartServiceCtrlDispatcherA(serviceTable))
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
Loading…
Add table
Reference in a new issue