mirror of
https://github.com/moonlight-stream/GS-IPv6-Forwarder.git
synced 2025-07-01 23:35:41 +00:00
Initial code drop
This commit is contained in:
parent
3c6a83a514
commit
8bec741daf
39
GSv6Fwd.sln
Normal file
39
GSv6Fwd.sln
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio 15
|
||||||
|
VisualStudioVersion = 15.0.26730.10
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GSv6Fwd", "GSv6Fwd\GSv6Fwd.vcxproj", "{87DEAE49-7638-4CDB-88EB-054B1F3CB0D2}"
|
||||||
|
EndProject
|
||||||
|
Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "GSv6FwdSetup", "GSv6FwdSetup\GSv6FwdSetup.wixproj", "{F8171B99-F5F9-4ABF-9FE5-6753539611AF}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|x64 = Debug|x64
|
||||||
|
Debug|x86 = Debug|x86
|
||||||
|
Release|x64 = Release|x64
|
||||||
|
Release|x86 = Release|x86
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{87DEAE49-7638-4CDB-88EB-054B1F3CB0D2}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{87DEAE49-7638-4CDB-88EB-054B1F3CB0D2}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{87DEAE49-7638-4CDB-88EB-054B1F3CB0D2}.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
|
{87DEAE49-7638-4CDB-88EB-054B1F3CB0D2}.Debug|x86.Build.0 = Debug|Win32
|
||||||
|
{87DEAE49-7638-4CDB-88EB-054B1F3CB0D2}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{87DEAE49-7638-4CDB-88EB-054B1F3CB0D2}.Release|x64.Build.0 = Release|x64
|
||||||
|
{87DEAE49-7638-4CDB-88EB-054B1F3CB0D2}.Release|x86.ActiveCfg = Release|Win32
|
||||||
|
{87DEAE49-7638-4CDB-88EB-054B1F3CB0D2}.Release|x86.Build.0 = Release|Win32
|
||||||
|
{F8171B99-F5F9-4ABF-9FE5-6753539611AF}.Debug|x64.ActiveCfg = Debug|x86
|
||||||
|
{F8171B99-F5F9-4ABF-9FE5-6753539611AF}.Debug|x86.ActiveCfg = Debug|x86
|
||||||
|
{F8171B99-F5F9-4ABF-9FE5-6753539611AF}.Debug|x86.Build.0 = Debug|x86
|
||||||
|
{F8171B99-F5F9-4ABF-9FE5-6753539611AF}.Release|x64.ActiveCfg = Release|x86
|
||||||
|
{F8171B99-F5F9-4ABF-9FE5-6753539611AF}.Release|x86.ActiveCfg = Release|x86
|
||||||
|
{F8171B99-F5F9-4ABF-9FE5-6753539611AF}.Release|x86.Build.0 = Release|x86
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {9C375CA2-3B67-4C23-B946-B3A5C8A79190}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
557
GSv6Fwd/GSv6Fwd.cpp
Normal file
557
GSv6Fwd/GSv6Fwd.cpp
Normal file
@ -0,0 +1,557 @@
|
|||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#pragma comment(lib, "ws2_32")
|
||||||
|
#include <WinSock2.h>
|
||||||
|
#include <Ws2ipdef.h>
|
||||||
|
|
||||||
|
#pragma comment(lib, "iphlpapi")
|
||||||
|
#include <Iphlpapi.h>
|
||||||
|
|
||||||
|
#define SERVICE_NAME L"GSv6FwdSvc"
|
||||||
|
|
||||||
|
static const unsigned short UDP_PORTS[] = {
|
||||||
|
47998, 47999, 48000, 48010
|
||||||
|
};
|
||||||
|
|
||||||
|
static const unsigned short TCP_PORTS[] = {
|
||||||
|
47984, 47989
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct _SOCKET_TUPLE {
|
||||||
|
SOCKET s1;
|
||||||
|
SOCKET s2;
|
||||||
|
} SOCKET_TUPLE, *PSOCKET_TUPLE;
|
||||||
|
|
||||||
|
typedef struct _LISTENER_TUPLE {
|
||||||
|
SOCKET listener;
|
||||||
|
unsigned short port;
|
||||||
|
} LISTENER_TUPLE, *PLISTENER_TUPLE;
|
||||||
|
|
||||||
|
typedef struct _UDP_TUPLE {
|
||||||
|
SOCKET ipv6Socket;
|
||||||
|
SOCKET ipv4Socket;
|
||||||
|
unsigned short port;
|
||||||
|
} UDP_TUPLE, *PUDP_TUPLE;
|
||||||
|
|
||||||
|
int
|
||||||
|
ForwardSocketData(SOCKET from, SOCKET to)
|
||||||
|
{
|
||||||
|
char buffer[4096];
|
||||||
|
int len;
|
||||||
|
|
||||||
|
len = recv(from, buffer, sizeof(buffer), 0);
|
||||||
|
if (len <= 0) {
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (send(to, buffer, len, 0) != len) {
|
||||||
|
return SOCKET_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD
|
||||||
|
WINAPI
|
||||||
|
TcpRelayThreadProc(LPVOID Context)
|
||||||
|
{
|
||||||
|
PSOCKET_TUPLE tuple = (PSOCKET_TUPLE)Context;
|
||||||
|
fd_set fds;
|
||||||
|
int err;
|
||||||
|
bool s1ReadShutdown = false;
|
||||||
|
bool s2ReadShutdown = false;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
FD_ZERO(&fds);
|
||||||
|
|
||||||
|
if (!s1ReadShutdown) {
|
||||||
|
FD_SET(tuple->s1, &fds);
|
||||||
|
}
|
||||||
|
if (!s2ReadShutdown) {
|
||||||
|
FD_SET(tuple->s2, &fds);
|
||||||
|
}
|
||||||
|
if (s1ReadShutdown && s2ReadShutdown) {
|
||||||
|
// Both sides gracefully closed
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = select(0, &fds, NULL, NULL, NULL);
|
||||||
|
if (err <= 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (FD_ISSET(tuple->s1, &fds)) {
|
||||||
|
err = ForwardSocketData(tuple->s1, tuple->s2);
|
||||||
|
if (err == 0) {
|
||||||
|
// Graceful closure from s1. Propagate to s2.
|
||||||
|
shutdown(tuple->s2, SD_SEND);
|
||||||
|
s1ReadShutdown = true;
|
||||||
|
}
|
||||||
|
else if (err < 0) {
|
||||||
|
// Forceful closure. Tear down the whole connection.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (FD_ISSET(tuple->s2, &fds)) {
|
||||||
|
err = ForwardSocketData(tuple->s2, tuple->s1);
|
||||||
|
if (err == 0) {
|
||||||
|
// Graceful closure from s2. Propagate to s1.
|
||||||
|
shutdown(tuple->s1, SD_SEND);
|
||||||
|
s2ReadShutdown = true;
|
||||||
|
}
|
||||||
|
else if (err < 0) {
|
||||||
|
// Forceful closure. Tear down the whole connection.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
closesocket(tuple->s1);
|
||||||
|
closesocket(tuple->s2);
|
||||||
|
free(tuple);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
FindLocalAddressBySocket(SOCKET s, PIN_ADDR targetAddress)
|
||||||
|
{
|
||||||
|
union {
|
||||||
|
IP_ADAPTER_ADDRESSES addresses;
|
||||||
|
char buffer[8192];
|
||||||
|
};
|
||||||
|
ULONG error;
|
||||||
|
ULONG length;
|
||||||
|
PIP_ADAPTER_ADDRESSES currentAdapter;
|
||||||
|
PIP_ADAPTER_UNICAST_ADDRESS currentAddress;
|
||||||
|
SOCKADDR_IN6 localSockAddr;
|
||||||
|
int localSockAddrLen;
|
||||||
|
|
||||||
|
// Get local address of the accepted socket so we can find the interface
|
||||||
|
localSockAddrLen = sizeof(localSockAddr);
|
||||||
|
if (getsockname(s, (PSOCKADDR)&localSockAddr, &localSockAddrLen) == SOCKET_ERROR) {
|
||||||
|
fprintf(stderr, "getsockname() failed: %d\n", WSAGetLastError());
|
||||||
|
return WSAGetLastError();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get a list of all interfaces and addresses on the system
|
||||||
|
length = sizeof(buffer);
|
||||||
|
error = GetAdaptersAddresses(AF_UNSPEC,
|
||||||
|
GAA_FLAG_SKIP_ANYCAST |
|
||||||
|
GAA_FLAG_SKIP_MULTICAST |
|
||||||
|
GAA_FLAG_SKIP_DNS_SERVER |
|
||||||
|
GAA_FLAG_SKIP_FRIENDLY_NAME,
|
||||||
|
NULL,
|
||||||
|
&addresses,
|
||||||
|
&length);
|
||||||
|
if (error != ERROR_SUCCESS) {
|
||||||
|
fprintf(stderr, "GetAdaptersAddresses() failed: %d\n", error);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// First, find the interface that owns the incoming address
|
||||||
|
currentAdapter = &addresses;
|
||||||
|
while (currentAdapter != NULL) {
|
||||||
|
// Check if this interface has the IP address we want
|
||||||
|
currentAddress = currentAdapter->FirstUnicastAddress;
|
||||||
|
while (currentAddress != NULL) {
|
||||||
|
if (currentAddress->Address.lpSockaddr->sa_family == AF_INET6) {
|
||||||
|
PSOCKADDR_IN6 ifaceAddrV6 = (PSOCKADDR_IN6)currentAddress->Address.lpSockaddr;
|
||||||
|
if (RtlEqualMemory(&localSockAddr.sin6_addr, &ifaceAddrV6->sin6_addr, sizeof(IN6_ADDR))) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
currentAddress = currentAddress->Next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentAddress != NULL) {
|
||||||
|
// It does, bail out
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentAdapter = currentAdapter->Next;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if we found the incoming interface
|
||||||
|
if (currentAdapter == NULL) {
|
||||||
|
// Hopefully the error is caused by transient interface reconfiguration
|
||||||
|
fprintf(stderr, "Unable to find incoming interface\n");
|
||||||
|
return WSAENETDOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now find an IPv4 address on this interface
|
||||||
|
currentAddress = currentAdapter->FirstUnicastAddress;
|
||||||
|
while (currentAddress != NULL) {
|
||||||
|
if (currentAddress->Address.lpSockaddr->sa_family == AF_INET) {
|
||||||
|
PSOCKADDR_IN ifaceAddrV4 = (PSOCKADDR_IN)currentAddress->Address.lpSockaddr;
|
||||||
|
*targetAddress = ifaceAddrV4->sin_addr;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentAddress = currentAddress->Next;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we get here, there was no IPv4 address on this interface.
|
||||||
|
// This is a valid situation, for example if the IPv6 interface
|
||||||
|
// has no IPv4 connectivity. In this case, we can preserve most
|
||||||
|
// functionality by forwarding via localhost. WoL won't work but
|
||||||
|
// the basic stuff will.
|
||||||
|
fprintf(stderr, "WARNING: No IPv4 connectivity on incoming interface\n");
|
||||||
|
targetAddress->S_un.S_addr = htonl(INADDR_LOOPBACK);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD
|
||||||
|
WINAPI
|
||||||
|
TcpListenerThreadProc(LPVOID Context)
|
||||||
|
{
|
||||||
|
PLISTENER_TUPLE tuple = (PLISTENER_TUPLE)Context;
|
||||||
|
SOCKET acceptedSocket, targetSocket;
|
||||||
|
SOCKADDR_IN targetAddress;
|
||||||
|
PSOCKET_TUPLE relayTuple;
|
||||||
|
HANDLE thread;
|
||||||
|
|
||||||
|
printf("TCP relay running for port %d\n", tuple->port);
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
acceptedSocket = accept(tuple->listener, NULL, 0);
|
||||||
|
if (acceptedSocket == INVALID_SOCKET) {
|
||||||
|
fprintf(stderr, "accept() failed: %d\n", WSAGetLastError());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
targetSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||||
|
if (targetSocket == INVALID_SOCKET) {
|
||||||
|
fprintf(stderr, "socket() failed: %d\n", WSAGetLastError());
|
||||||
|
closesocket(acceptedSocket);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
RtlZeroMemory(&targetAddress, sizeof(targetAddress));
|
||||||
|
targetAddress.sin_family = AF_INET;
|
||||||
|
targetAddress.sin_port = htons(tuple->port);
|
||||||
|
if (FindLocalAddressBySocket(acceptedSocket, &targetAddress.sin_addr) != 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (connect(targetSocket, (PSOCKADDR)&targetAddress, sizeof(targetAddress)) == SOCKET_ERROR) {
|
||||||
|
fprintf(stderr, "connect() failed: %d\n", WSAGetLastError());
|
||||||
|
closesocket(acceptedSocket);
|
||||||
|
closesocket(targetSocket);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
relayTuple = (PSOCKET_TUPLE)malloc(sizeof(*relayTuple));
|
||||||
|
if (relayTuple == NULL) {
|
||||||
|
closesocket(acceptedSocket);
|
||||||
|
closesocket(targetSocket);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
relayTuple->s1 = acceptedSocket;
|
||||||
|
relayTuple->s2 = targetSocket;
|
||||||
|
|
||||||
|
thread = CreateThread(NULL, 0, TcpRelayThreadProc, relayTuple, 0, NULL);
|
||||||
|
if (thread == INVALID_HANDLE_VALUE) {
|
||||||
|
fprintf(stderr, "CreateThread() failed: %d\n", GetLastError());
|
||||||
|
closesocket(acceptedSocket);
|
||||||
|
closesocket(targetSocket);
|
||||||
|
free(relayTuple);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseHandle(thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
closesocket(tuple->listener);
|
||||||
|
free(tuple);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int StartTcpRelay(unsigned short Port)
|
||||||
|
{
|
||||||
|
SOCKET listeningSocket;
|
||||||
|
SOCKADDR_IN6 addr6;
|
||||||
|
HANDLE thread;
|
||||||
|
PLISTENER_TUPLE tuple;
|
||||||
|
|
||||||
|
listeningSocket = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
|
||||||
|
if (listeningSocket == INVALID_SOCKET) {
|
||||||
|
fprintf(stderr, "socket() failed: %d\n", WSAGetLastError());
|
||||||
|
return WSAGetLastError();
|
||||||
|
}
|
||||||
|
|
||||||
|
RtlZeroMemory(&addr6, sizeof(addr6));
|
||||||
|
addr6.sin6_family = AF_INET6;
|
||||||
|
addr6.sin6_port = htons(Port);
|
||||||
|
if (bind(listeningSocket, (PSOCKADDR)&addr6, sizeof(addr6)) == SOCKET_ERROR) {
|
||||||
|
fprintf(stderr, "bind() failed: %d\n", WSAGetLastError());
|
||||||
|
return WSAGetLastError();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (listen(listeningSocket, SOMAXCONN) == SOCKET_ERROR) {
|
||||||
|
fprintf(stderr, "listen() failed: %d\n", WSAGetLastError());
|
||||||
|
return WSAGetLastError();
|
||||||
|
}
|
||||||
|
|
||||||
|
tuple = (PLISTENER_TUPLE)malloc(sizeof(*tuple));
|
||||||
|
if (tuple == NULL) {
|
||||||
|
return ERROR_OUTOFMEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
tuple->listener = listeningSocket;
|
||||||
|
tuple->port = Port;
|
||||||
|
|
||||||
|
thread = CreateThread(NULL, 0, TcpListenerThreadProc, tuple, 0, NULL);
|
||||||
|
if (thread == INVALID_HANDLE_VALUE) {
|
||||||
|
fprintf(stderr, "CreateThread() failed: %d\n", GetLastError());
|
||||||
|
return GetLastError();
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseHandle(thread);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ForwardUdpPacket(SOCKET from, SOCKET to,
|
||||||
|
PSOCKADDR target, int targetLen,
|
||||||
|
PSOCKADDR source, int sourceLen)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
char buffer[4096];
|
||||||
|
|
||||||
|
len = recvfrom(from, buffer, sizeof(buffer), 0, source, &sourceLen);
|
||||||
|
if (len < 0) {
|
||||||
|
fprintf(stderr, "recvfrom() failed: %d\n", WSAGetLastError());
|
||||||
|
return WSAGetLastError();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sendto(to, buffer, len, 0, target, targetLen) != len) {
|
||||||
|
fprintf(stderr, "sendto() failed: %d\n", WSAGetLastError());
|
||||||
|
// Fake success, since we may just be waiting for a target address
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD
|
||||||
|
WINAPI
|
||||||
|
UdpRelayThreadProc(LPVOID Context)
|
||||||
|
{
|
||||||
|
PUDP_TUPLE tuple = (PUDP_TUPLE)Context;
|
||||||
|
fd_set fds;
|
||||||
|
int err;
|
||||||
|
SOCKADDR_IN6 lastRemote;
|
||||||
|
SOCKADDR_IN localTarget;
|
||||||
|
|
||||||
|
printf("UDP relay running for port %d\n", tuple->port);
|
||||||
|
|
||||||
|
RtlZeroMemory(&localTarget, sizeof(localTarget));
|
||||||
|
localTarget.sin_family = AF_INET;
|
||||||
|
localTarget.sin_port = htons(tuple->port);
|
||||||
|
localTarget.sin_addr.S_un.S_addr = htonl(INADDR_LOOPBACK);
|
||||||
|
|
||||||
|
RtlZeroMemory(&lastRemote, sizeof(lastRemote));
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
FD_ZERO(&fds);
|
||||||
|
|
||||||
|
FD_SET(tuple->ipv6Socket, &fds);
|
||||||
|
FD_SET(tuple->ipv4Socket, &fds);
|
||||||
|
|
||||||
|
err = select(0, &fds, NULL, NULL, NULL);
|
||||||
|
if (err <= 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (FD_ISSET(tuple->ipv6Socket, &fds)) {
|
||||||
|
// Forwarding incoming IPv6 packets to the IPv4 port
|
||||||
|
// and storing the source address as our current remote
|
||||||
|
// target for sending IPv4 data back.
|
||||||
|
err = ForwardUdpPacket(tuple->ipv6Socket, tuple->ipv4Socket,
|
||||||
|
(PSOCKADDR)&localTarget, sizeof(localTarget),
|
||||||
|
(PSOCKADDR)&lastRemote, sizeof(lastRemote));
|
||||||
|
if (err < 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (FD_ISSET(tuple->ipv4Socket, &fds)) {
|
||||||
|
// Forwarding incoming IPv4 packets to the last known
|
||||||
|
// address IPv6 address we've heard from. Discard the source.
|
||||||
|
SOCKADDR_STORAGE unused;
|
||||||
|
err = ForwardUdpPacket(tuple->ipv4Socket, tuple->ipv6Socket,
|
||||||
|
(PSOCKADDR)&lastRemote, sizeof(lastRemote),
|
||||||
|
(PSOCKADDR)&unused, sizeof(unused));
|
||||||
|
if (err < 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
closesocket(tuple->ipv6Socket);
|
||||||
|
closesocket(tuple->ipv4Socket);
|
||||||
|
free(tuple);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int StartUdpRelay(unsigned short Port)
|
||||||
|
{
|
||||||
|
SOCKET ipv6Socket;
|
||||||
|
SOCKET ipv4Socket;
|
||||||
|
SOCKADDR_IN6 addr6;
|
||||||
|
SOCKADDR_IN addr;
|
||||||
|
PUDP_TUPLE tuple;
|
||||||
|
HANDLE thread;
|
||||||
|
|
||||||
|
ipv6Socket = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
|
||||||
|
if (ipv6Socket == INVALID_SOCKET) {
|
||||||
|
fprintf(stderr, "socket() failed: %d\n", WSAGetLastError());
|
||||||
|
return WSAGetLastError();
|
||||||
|
}
|
||||||
|
|
||||||
|
RtlZeroMemory(&addr6, sizeof(addr6));
|
||||||
|
addr6.sin6_family = AF_INET6;
|
||||||
|
addr6.sin6_port = htons(Port);
|
||||||
|
if (bind(ipv6Socket, (PSOCKADDR)&addr6, sizeof(addr6)) == SOCKET_ERROR) {
|
||||||
|
fprintf(stderr, "bind() failed: %d\n", WSAGetLastError());
|
||||||
|
return WSAGetLastError();
|
||||||
|
}
|
||||||
|
|
||||||
|
ipv4Socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||||
|
if (ipv4Socket == INVALID_SOCKET) {
|
||||||
|
fprintf(stderr, "socket() failed: %d\n", WSAGetLastError());
|
||||||
|
return WSAGetLastError();
|
||||||
|
}
|
||||||
|
|
||||||
|
RtlZeroMemory(&addr, sizeof(addr));
|
||||||
|
addr.sin_family = AF_INET;
|
||||||
|
addr.sin_addr.S_un.S_addr = htonl(INADDR_LOOPBACK);
|
||||||
|
if (bind(ipv4Socket, (PSOCKADDR)&addr, sizeof(addr)) == SOCKET_ERROR) {
|
||||||
|
fprintf(stderr, "bind() failed: %d\n", WSAGetLastError());
|
||||||
|
return WSAGetLastError();
|
||||||
|
}
|
||||||
|
|
||||||
|
tuple = (PUDP_TUPLE)malloc(sizeof(*tuple));
|
||||||
|
if (tuple == NULL) {
|
||||||
|
return ERROR_OUTOFMEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
tuple->ipv4Socket = ipv4Socket;
|
||||||
|
tuple->ipv6Socket = ipv6Socket;
|
||||||
|
tuple->port = Port;
|
||||||
|
|
||||||
|
thread = CreateThread(NULL, 0, UdpRelayThreadProc, tuple, 0, NULL);
|
||||||
|
if (thread == INVALID_HANDLE_VALUE) {
|
||||||
|
fprintf(stderr, "CreateThread() failed: %d\n", GetLastError());
|
||||||
|
return GetLastError();
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseHandle(thread);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Run(void)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
WSADATA data;
|
||||||
|
|
||||||
|
err = WSAStartup(MAKEWORD(2, 0), &data);
|
||||||
|
if (err == SOCKET_ERROR) {
|
||||||
|
fprintf(stderr, "WSAStartup() failed: %d\n", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < ARRAYSIZE(TCP_PORTS); i++) {
|
||||||
|
err = StartTcpRelay(TCP_PORTS[i]);
|
||||||
|
if (err != 0) {
|
||||||
|
fprintf(stderr, "Failed to start relay on TCP %d: %d\n", TCP_PORTS[i], err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < ARRAYSIZE(UDP_PORTS); i++) {
|
||||||
|
err = StartUdpRelay(UDP_PORTS[i]);
|
||||||
|
if (err != 0) {
|
||||||
|
fprintf(stderr, "Failed to start relay on UDP %d: %d\n", UDP_PORTS[i], err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SERVICE_STATUS_HANDLE ServiceStatusHandle;
|
||||||
|
static SERVICE_STATUS ServiceStatus;
|
||||||
|
|
||||||
|
DWORD
|
||||||
|
WINAPI
|
||||||
|
HandlerEx(DWORD dwControl, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext)
|
||||||
|
{
|
||||||
|
switch (dwControl)
|
||||||
|
{
|
||||||
|
case SERVICE_CONTROL_INTERROGATE:
|
||||||
|
return NO_ERROR;
|
||||||
|
|
||||||
|
case SERVICE_CONTROL_STOP:
|
||||||
|
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
|
||||||
|
SetServiceStatus(ServiceStatusHandle, &ServiceStatus);
|
||||||
|
return NO_ERROR;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return NO_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
WINAPI
|
||||||
|
ServiceMain(DWORD dwArgc, LPTSTR *lpszArgv)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
ServiceStatusHandle = RegisterServiceCtrlHandlerEx(SERVICE_NAME, HandlerEx, NULL);
|
||||||
|
if (ServiceStatusHandle == NULL) {
|
||||||
|
fprintf(stderr, "RegisterServiceCtrlHandlerEx() failed: %d\n", GetLastError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
|
||||||
|
ServiceStatus.dwServiceSpecificExitCode = 0;
|
||||||
|
ServiceStatus.dwWin32ExitCode = NO_ERROR;
|
||||||
|
ServiceStatus.dwWaitHint = 0;
|
||||||
|
ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
|
||||||
|
ServiceStatus.dwCheckPoint = 0;
|
||||||
|
|
||||||
|
// Start the relay
|
||||||
|
err = Run();
|
||||||
|
if (err != 0) {
|
||||||
|
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
|
||||||
|
ServiceStatus.dwWin32ExitCode = err;
|
||||||
|
SetServiceStatus(ServiceStatusHandle, &ServiceStatus);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tell SCM we're running
|
||||||
|
ServiceStatus.dwCurrentState = SERVICE_RUNNING;
|
||||||
|
SetServiceStatus(ServiceStatusHandle, &ServiceStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const SERVICE_TABLE_ENTRY ServiceTable[] = {
|
||||||
|
{ SERVICE_NAME, ServiceMain },
|
||||||
|
{ NULL, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
if (argc == 2 && !strcmp(argv[1], "exe")) {
|
||||||
|
Run();
|
||||||
|
SuspendThread(GetCurrentThread());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return StartServiceCtrlDispatcher(ServiceTable);
|
||||||
|
}
|
||||||
|
|
155
GSv6Fwd/GSv6Fwd.vcxproj
Normal file
155
GSv6Fwd/GSv6Fwd.vcxproj
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|Win32">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Debug|x64">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|x64">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<VCProjectVersion>15.0</VCProjectVersion>
|
||||||
|
<ProjectGuid>{87DEAE49-7638-4CDB-88EB-054B1F3CB0D2}</ProjectGuid>
|
||||||
|
<Keyword>Win32Proj</Keyword>
|
||||||
|
<RootNamespace>GSv6Fwd</RootNamespace>
|
||||||
|
<WindowsTargetPlatformVersion>10.0.15063.0</WindowsTargetPlatformVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="Shared">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="GSv6Fwd.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
22
GSv6Fwd/GSv6Fwd.vcxproj.filters
Normal file
22
GSv6Fwd/GSv6Fwd.vcxproj.filters
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<Filter Include="Source Files">
|
||||||
|
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||||
|
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Header Files">
|
||||||
|
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||||
|
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Resource Files">
|
||||||
|
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||||
|
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="GSv6Fwd.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
47
GSv6FwdSetup/GSv6FwdSetup.wixproj
Normal file
47
GSv6FwdSetup/GSv6FwdSetup.wixproj
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" DefaultTargets="Build" InitialTargets="EnsureWixToolsetInstalled" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
|
||||||
|
<ProductVersion>3.10</ProductVersion>
|
||||||
|
<ProjectGuid>f8171b99-f5f9-4abf-9fe5-6753539611af</ProjectGuid>
|
||||||
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
|
<OutputName>GSv6FwdSetup</OutputName>
|
||||||
|
<OutputType>Package</OutputType>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||||
|
<OutputPath>bin\$(Configuration)\</OutputPath>
|
||||||
|
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
|
||||||
|
<DefineConstants>Debug</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||||
|
<OutputPath>bin\$(Configuration)\</OutputPath>
|
||||||
|
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="Product.wxs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\GSv6Fwd\GSv6Fwd.vcxproj">
|
||||||
|
<Name>GSv6Fwd</Name>
|
||||||
|
<Project>{87deae49-7638-4cdb-88eb-054b1f3cb0d2}</Project>
|
||||||
|
<Private>True</Private>
|
||||||
|
<DoNotHarvest>True</DoNotHarvest>
|
||||||
|
<RefProjectOutputGroups>Binaries;Content;Satellites</RefProjectOutputGroups>
|
||||||
|
<RefTargetDir>INSTALLFOLDER</RefTargetDir>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(WixTargetsPath)" Condition=" '$(WixTargetsPath)' != '' " />
|
||||||
|
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets" Condition=" '$(WixTargetsPath)' == '' AND Exists('$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets') " />
|
||||||
|
<Target Name="EnsureWixToolsetInstalled" Condition=" '$(WixTargetsImported)' != 'true' ">
|
||||||
|
<Error Text="The WiX Toolset v3.11 (or newer) build tools must be installed to build this project. To download the WiX Toolset, see http://wixtoolset.org/releases/" />
|
||||||
|
</Target>
|
||||||
|
<!--
|
||||||
|
To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||||
|
Other similar extension points exist, see Wix.targets.
|
||||||
|
<Target Name="BeforeBuild">
|
||||||
|
</Target>
|
||||||
|
<Target Name="AfterBuild">
|
||||||
|
</Target>
|
||||||
|
-->
|
||||||
|
</Project>
|
40
GSv6FwdSetup/Product.wxs
Normal file
40
GSv6FwdSetup/Product.wxs
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
|
||||||
|
<Product Id="*" Name="IPv6 Forwarder for GS Protocol" Language="1033" Version="1.0.0.0" Manufacturer="Cameron Gutman" UpgradeCode="cae27153-26ed-4da2-8dd5-8cddc7126a05">
|
||||||
|
<Package InstallerVersion="500" Compressed="yes" InstallScope="perMachine" />
|
||||||
|
|
||||||
|
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
|
||||||
|
<MediaTemplate EmbedCab="yes" />
|
||||||
|
|
||||||
|
<Feature Id="ProductFeature" Title="GSv6FwdSetup" Level="1">
|
||||||
|
<ComponentGroupRef Id="ProductComponents" />
|
||||||
|
</Feature>
|
||||||
|
</Product>
|
||||||
|
|
||||||
|
<Fragment>
|
||||||
|
<Directory Id="TARGETDIR" Name="SourceDir">
|
||||||
|
<Directory Id="ProgramFilesFolder">
|
||||||
|
<Directory Id="INSTALLFOLDER" Name="GSv6FwdSetup" />
|
||||||
|
</Directory>
|
||||||
|
</Directory>
|
||||||
|
</Fragment>
|
||||||
|
|
||||||
|
<Fragment>
|
||||||
|
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
|
||||||
|
<Component Id="ProductComponent">
|
||||||
|
<File Source="$(var.GSv6Fwd.TargetPath)" KeyPath="yes"/>
|
||||||
|
<ServiceInstall Type="ownProcess"
|
||||||
|
Name="GSv6FwdSvc"
|
||||||
|
DisplayName="IPv6 Forwarder for GS Protocol"
|
||||||
|
Description="Provides access to GameStream servers over IPv6 networks"
|
||||||
|
Start="auto"
|
||||||
|
Account="LocalSystem"
|
||||||
|
ErrorControl="ignore"
|
||||||
|
Interactive="no">
|
||||||
|
<ServiceConfig DelayedAutoStart="yes" OnInstall="yes" OnReinstall="yes" />
|
||||||
|
</ServiceInstall>
|
||||||
|
<ServiceControl Id="StartService" Start="install" Stop="both" Remove="uninstall" Name="GSv6FwdSvc" Wait="yes" />
|
||||||
|
</Component>
|
||||||
|
</ComponentGroup>
|
||||||
|
</Fragment>
|
||||||
|
</Wix>
|
Loading…
x
Reference in New Issue
Block a user