Implement experimental bridge for kvm virtual machines

This commit is contained in:
EnderIce2 2024-05-30 05:32:56 +03:00
parent 20728818d2
commit 3ac5605a52
Signed by untrusted user who does not match committer: enderice2
GPG Key ID: EACC3AD603BAB4DD
9 changed files with 401 additions and 75 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
*.o *.o
*.exe *.exe
*.res *.res
*.elf

View File

@ -9,6 +9,17 @@
"cStandard": "c17", "cStandard": "c17",
"cppStandard": "gnu++17", "cppStandard": "gnu++17",
"intelliSenseMode": "windows-gcc-x64" "intelliSenseMode": "windows-gcc-x64"
},
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/**"
],
"defines": [],
"cStandard": "c17",
"cppStandard": "gnu++17",
"intelliSenseMode": "linux-gcc-x64",
"compilerPath": "/usr/bin/gcc"
} }
], ],
"version": 4 "version": 4

View File

@ -12,6 +12,7 @@ build: $(C_OBJECTS)
$(info Linking) $(info Linking)
x86_64-w64-mingw32-windres bridge.rc -O coff -o bridge.res x86_64-w64-mingw32-windres bridge.rc -O coff -o bridge.res
x86_64-w64-mingw32-gcc $(C_OBJECTS) bridge.res $(LFLAGS) $(DBGFLAGS) -o build/bridge.exe x86_64-w64-mingw32-gcc $(C_OBJECTS) bridge.res $(LFLAGS) $(DBGFLAGS) -o build/bridge.exe
gcc kvm.c -o build/rpc-bridge.elf
%.o: %.c %.o: %.c
$(info Compiling $<) $(info Compiling $<)

298
bridge.c
View File

@ -4,6 +4,8 @@
#include <assert.h> #include <assert.h>
#include <stdio.h> #include <stdio.h>
#include "bridge.h"
#define __linux_read 3 #define __linux_read 3
#define __linux_write 4 #define __linux_write 4
#define __linux_open 5 #define __linux_open 5
@ -64,7 +66,7 @@ void print(char const *fmt, ...);
LPTSTR GetErrorMessage(); LPTSTR GetErrorMessage();
extern BOOL RunningAsService; extern BOOL RunningAsService;
BOOL RetryNewConnection; BOOL RetryNewConnection;
BOOL IsLinux; OS_INFO OSInfo = {0};
HANDLE hOut = NULL; HANDLE hOut = NULL;
HANDLE hIn = NULL; HANDLE hIn = NULL;
@ -102,7 +104,7 @@ static naked int darwin_syscall(int num,
static inline int sys_read(int fd, void *buf, size_t count) static inline int sys_read(int fd, void *buf, size_t count)
{ {
if (IsLinux) if (OSInfo.IsLinux)
return linux_syscall(__linux_read, fd, buf, count, 0, 0, 0); return linux_syscall(__linux_read, fd, buf, count, 0, 0, 0);
else else
return darwin_syscall(__darwin_read, fd, buf, count, 0, 0, 0); return darwin_syscall(__darwin_read, fd, buf, count, 0, 0, 0);
@ -110,7 +112,7 @@ static inline int sys_read(int fd, void *buf, size_t count)
static inline int sys_write(int fd, const void *buf, size_t count) static inline int sys_write(int fd, const void *buf, size_t count)
{ {
if (IsLinux) if (OSInfo.IsLinux)
return linux_syscall(__linux_write, fd, buf, count, 0, 0, 0); return linux_syscall(__linux_write, fd, buf, count, 0, 0, 0);
else else
return darwin_syscall(__darwin_write, fd, buf, count, 0, 0, 0); return darwin_syscall(__darwin_write, fd, buf, count, 0, 0, 0);
@ -118,7 +120,7 @@ static inline int sys_write(int fd, const void *buf, size_t count)
static inline int sys_open(const char *pathname, int flags, int mode) static inline int sys_open(const char *pathname, int flags, int mode)
{ {
if (IsLinux) if (OSInfo.IsLinux)
return linux_syscall(__linux_open, pathname, flags, mode, 0, 0, 0); return linux_syscall(__linux_open, pathname, flags, mode, 0, 0, 0);
else else
return darwin_syscall(__darwin_open, pathname, flags, mode, 0, 0, 0); return darwin_syscall(__darwin_open, pathname, flags, mode, 0, 0, 0);
@ -126,7 +128,7 @@ static inline int sys_open(const char *pathname, int flags, int mode)
static inline int sys_close(int fd) static inline int sys_close(int fd)
{ {
if (IsLinux) if (OSInfo.IsLinux)
return linux_syscall(__linux_close, fd, 0, 0, 0, 0, 0); return linux_syscall(__linux_close, fd, 0, 0, 0, 0, 0);
else else
return darwin_syscall(__darwin_close, fd, 0, 0, 0, 0, 0); return darwin_syscall(__darwin_close, fd, 0, 0, 0, 0, 0);
@ -134,25 +136,25 @@ static inline int sys_close(int fd)
static inline unsigned int *sys_mmap(unsigned int *addr, size_t length, int prot, int flags, int fd, off_t offset) static inline unsigned int *sys_mmap(unsigned int *addr, size_t length, int prot, int flags, int fd, off_t offset)
{ {
assert(IsLinux); assert(OSInfo.IsLinux);
return linux_syscall(__linux_mmap2, addr, length, prot, flags, fd, offset); return linux_syscall(__linux_mmap2, addr, length, prot, flags, fd, offset);
} }
static inline int sys_munmap(unsigned int *addr, size_t length) static inline int sys_munmap(unsigned int *addr, size_t length)
{ {
assert(IsLinux); assert(OSInfo.IsLinux);
return linux_syscall(__linux_munmap, addr, length, 0, 0, 0, 0); return linux_syscall(__linux_munmap, addr, length, 0, 0, 0, 0);
} }
static inline int sys_socketcall(int call, unsigned long *args) static inline int sys_socketcall(int call, unsigned long *args)
{ {
assert(IsLinux); assert(OSInfo.IsLinux);
return linux_syscall(__linux_socketcall, call, args, 0, 0, 0, 0); return linux_syscall(__linux_socketcall, call, args, 0, 0, 0, 0);
} }
static inline int sys_socket(int domain, int type, int protocol) static inline int sys_socket(int domain, int type, int protocol)
{ {
if (IsLinux) if (OSInfo.IsLinux)
return linux_syscall(__linux_socket, domain, type, protocol, 0, 0, 0); return linux_syscall(__linux_socket, domain, type, protocol, 0, 0, 0);
else else
return darwin_syscall(__darwin_socket, domain, type, protocol, 0, 0, 0); return darwin_syscall(__darwin_socket, domain, type, protocol, 0, 0, 0);
@ -160,7 +162,7 @@ static inline int sys_socket(int domain, int type, int protocol)
static inline int sys_connect(int s, caddr_t name, socklen_t namelen) static inline int sys_connect(int s, caddr_t name, socklen_t namelen)
{ {
if (IsLinux) if (OSInfo.IsLinux)
return linux_syscall(__linux_connect, s, name, namelen, 0, 0, 0); return linux_syscall(__linux_connect, s, name, namelen, 0, 0, 0);
else else
return darwin_syscall(__darwin_connect, s, name, namelen, 0, 0, 0); return darwin_syscall(__darwin_connect, s, name, namelen, 0, 0, 0);
@ -174,7 +176,7 @@ char *native_getenv(const char *name)
if (ret != 0) if (ret != 0)
return lpBuffer; return lpBuffer;
if (!IsLinux) if (!OSInfo.IsLinux)
{ {
char *value = getenv(name); char *value = getenv(name);
if (value == NULL) if (value == NULL)
@ -251,9 +253,9 @@ void ConnectToSocket(int fd)
{ {
print("Connecting to socket\n"); print("Connecting to socket\n");
const char *runtime; const char *runtime;
if (IsLinux) if (OSInfo.IsLinux)
runtime = native_getenv("XDG_RUNTIME_DIR"); runtime = native_getenv("XDG_RUNTIME_DIR");
else else if (OSInfo.IsDarwin)
{ {
runtime = native_getenv("TMPDIR"); runtime = native_getenv("TMPDIR");
if (runtime == NULL) if (runtime == NULL)
@ -278,6 +280,11 @@ void ConnectToSocket(int fd)
} }
} }
} }
else
{
print("Unsupported OS\n");
ExitProcess(1);
}
print("IPC directory: %s\n", runtime); print("IPC directory: %s\n", runtime);
@ -302,7 +309,7 @@ void ConnectToSocket(int fd)
print("Connecting to %s\n", pipePath); print("Connecting to %s\n", pipePath);
if (IsLinux) if (OSInfo.IsLinux)
{ {
unsigned long socketArgs[] = { unsigned long socketArgs[] = {
(unsigned long)fd, (unsigned long)fd,
@ -480,6 +487,162 @@ void PipeBufferOutThread(LPVOID lpParam)
} }
} }
void COMPipeBufferInThread(LPVOID lpParam)
{
bridge_thread *bt = (bridge_thread *)lpParam;
print("COM In thread started using COM port and pipe %#x\n", bt->hPipe);
HANDLE hComPort = CreateFile("\\\\.\\COM2", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (hComPort == INVALID_HANDLE_VALUE)
{
print("Failed to open COM2 port: %s\n", GetErrorMessage());
return;
}
int EOFCount = 0;
while (TRUE)
{
char buffer[BUFFER_LENGTH];
DWORD bytesRead;
if (!ReadFile(hComPort, buffer, sizeof(buffer), &bytesRead, NULL))
{
print("Failed to read from COM2 port: %s\n", GetErrorMessage());
Sleep(1000);
continue;
}
if (EOFCount > 4)
{
print("EOF count exceeded\n");
RetryNewConnection = TRUE;
TerminateThread(hOut, 0);
break;
}
if (bytesRead == 0)
{
print("EOF\n");
Sleep(1000);
EOFCount++;
continue;
}
EOFCount = 0;
print("Reading %d bytes from COM2 port: \"", bytesRead);
for (DWORD i = 0; i < bytesRead; i++)
print("%c", buffer[i]);
print("\"\n");
DWORD dwWritten;
if (!WriteFile(bt->hPipe, buffer, bytesRead, &dwWritten, NULL))
{
if (GetLastError() == ERROR_BROKEN_PIPE)
{
RetryNewConnection = TRUE;
print("In Broken pipe\n");
break;
}
print("Failed to write to pipe: %s\n", GetErrorMessage());
Sleep(1000);
continue;
}
while (dwWritten < bytesRead)
{
int last_written = dwWritten;
if (!WriteFile(bt->hPipe, buffer + dwWritten, bytesRead - dwWritten, &dwWritten, NULL))
{
if (GetLastError() == ERROR_BROKEN_PIPE)
{
RetryNewConnection = TRUE;
print("In Broken pipe\n");
break;
}
print("Failed to write to pipe: %s\n", GetErrorMessage());
Sleep(1000);
continue;
}
if (last_written == dwWritten)
{
print("Failed to write to pipe: %s\n", GetErrorMessage());
Sleep(1000);
continue;
}
}
}
CloseHandle(hComPort);
}
void COMPipeBufferOutThread(LPVOID lpParam)
{
bridge_thread *bt = (bridge_thread *)lpParam;
print("COM Out thread started using COM port and pipe %#x\n", bt->hPipe);
HANDLE hComPort = CreateFile("\\\\.\\COM2", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (hComPort == INVALID_HANDLE_VALUE)
{
print("Failed to open COM2 port: %s\n", GetErrorMessage());
return;
}
while (TRUE)
{
char buffer[BUFFER_LENGTH];
DWORD dwRead;
if (!ReadFile(bt->hPipe, buffer, sizeof(buffer), &dwRead, NULL))
{
if (GetLastError() == ERROR_BROKEN_PIPE)
{
RetryNewConnection = TRUE;
print("Out Broken pipe\n");
break;
}
print("Failed to read from pipe: %s\n", GetErrorMessage());
Sleep(1000);
continue;
}
print("Writing %d bytes to COM2 port: \"", dwRead);
for (DWORD i = 0; i < dwRead; i++)
print("%c", buffer[i]);
print("\"\n");
DWORD bytesWritten;
if (!WriteFile(hComPort, buffer, dwRead, &bytesWritten, NULL))
{
print("Failed to write to COM2 port: %s\n", GetErrorMessage());
continue;
}
while (bytesWritten < dwRead)
{
int last_written = bytesWritten;
if (!WriteFile(hComPort, buffer + bytesWritten, dwRead - bytesWritten, &bytesWritten, NULL))
{
print("Failed to write to COM2 port: %s\n", GetErrorMessage());
Sleep(1000);
continue;
}
if (last_written == bytesWritten)
{
print("Failed to write to COM2 port: %s\n", GetErrorMessage());
Sleep(1000);
continue;
}
}
}
CloseHandle(hComPort);
}
void CreateBridge() void CreateBridge()
{ {
LPCTSTR lpszPipename = TEXT("\\\\.\\pipe\\discord-ipc-0"); LPCTSTR lpszPipename = TEXT("\\\\.\\pipe\\discord-ipc-0");
@ -533,43 +696,87 @@ NewConnection:
print("Pipe connected\n"); print("Pipe connected\n");
int fd; int fd;
if (IsLinux) if (!OSInfo.IsWine)
{ {
unsigned long socketArgs[] = { print("Running on Windows\n");
(unsigned long)AF_UNIX, /* KVM, send 0xBB1569 and wait with timeout (TODO) for response 0xB41D6E */
(unsigned long)SOCK_STREAM,
0}; print("Trying \\\\.\\COM2\n");
fd = sys_socketcall(SYS_SOCKET, socketArgs); HANDLE hComPort = CreateFile("\\\\.\\COM2", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
assert(hComPort != INVALID_HANDLE_VALUE);
DWORD dwWritten;
print("Writing to COM port\n");
char buffer[4] = "\x69\x15\xBB";
assert(WriteFile(hComPort, buffer, sizeof(buffer), &dwWritten, NULL));
print("Wrote %d bytes to COM port\n", dwWritten);
DWORD dwRead;
print("Reading from COM port\n");
assert(ReadFile(hComPort, buffer, sizeof(buffer), &dwRead, NULL));
print("Read %d bytes from COM port\n", dwRead);
if (dwRead != 4 || memcmp(buffer, "\x6E\x1D\xB4", 4) != 0)
{
CloseHandle(hComPort);
print("Failed to connect to COM2\n");
return;
}
CloseHandle(hComPort);
print("Connected to COM2\n");
bridge_thread bt = {0, hPipe};
hIn = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE)COMPipeBufferInThread,
(LPVOID)&bt,
0, NULL);
hOut = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE)COMPipeBufferOutThread,
(LPVOID)&bt,
0, NULL);
} }
else else
fd = sys_socket(AF_UNIX, SOCK_STREAM, 0);
print("Socket %d created\n", fd);
if (fd < 0)
{ {
print("Failed to create socket: %d\n", fd); if (OSInfo.IsLinux)
if (!RunningAsService) {
MessageBox(NULL, "Failed to create socket", unsigned long socketArgs[] = {
NULL, MB_OK | MB_ICONSTOP); (unsigned long)AF_UNIX,
ExitProcess(1); (unsigned long)SOCK_STREAM,
0};
fd = sys_socketcall(SYS_SOCKET, socketArgs);
}
else
fd = sys_socket(AF_UNIX, SOCK_STREAM, 0);
print("Socket %d created\n", fd);
if (fd < 0)
{
print("Failed to create socket: %d\n", fd);
if (!RunningAsService)
MessageBox(NULL, "Failed to create socket",
NULL, MB_OK | MB_ICONSTOP);
ExitProcess(1);
}
ConnectToSocket(fd);
print("Connected to Discord\n");
bridge_thread bt = {fd, hPipe};
hIn = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE)PipeBufferInThread,
(LPVOID)&bt,
0, NULL);
hOut = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE)PipeBufferOutThread,
(LPVOID)&bt,
0, NULL);
} }
ConnectToSocket(fd);
print("Connected to Discord\n");
bridge_thread bt = {fd, hPipe};
hIn = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE)PipeBufferInThread,
(LPVOID)&bt,
0, NULL);
print("Created in thread %#lx\n", hIn); print("Created in thread %#lx\n", hIn);
hOut = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE)PipeBufferOutThread,
(LPVOID)&bt,
0, NULL);
print("Created out thread %#lx\n", hOut); print("Created out thread %#lx\n", hOut);
if (hIn == NULL || hOut == NULL) if (hIn == NULL || hOut == NULL)
@ -600,7 +807,8 @@ NewConnection:
print("Failed to terminate thread: %s\n", print("Failed to terminate thread: %s\n",
GetErrorMessage()); GetErrorMessage());
sys_close(fd); if (OSInfo.IsWine)
sys_close(fd);
CloseHandle(hOut); CloseHandle(hOut);
CloseHandle(hIn); CloseHandle(hIn);
CloseHandle(hPipe); CloseHandle(hPipe);

13
bridge.h Normal file
View File

@ -0,0 +1,13 @@
#ifndef _BRIDGE_H
#define _BRIDGE_H
#include <windows.h>
typedef struct _OS_INFO
{
BOOL IsLinux;
BOOL IsDarwin;
BOOL IsWine;
} OS_INFO;
#endif // _BRIDGE_H

15
gui.c
View File

@ -4,6 +4,7 @@
#include <assert.h> #include <assert.h>
#include <stdio.h> #include <stdio.h>
#include "bridge.h"
#include "resource.h" #include "resource.h"
/** /**
@ -17,7 +18,8 @@ void print(char const *fmt, ...);
void InstallService(int ServiceStartType, LPCSTR Path); void InstallService(int ServiceStartType, LPCSTR Path);
void RemoveService(); void RemoveService();
void CreateBridge(); void CreateBridge();
extern BOOL IsLinux; extern OS_INFO OSInfo;
extern char *logFilePath;
HWND hwnd = NULL; HWND hwnd = NULL;
HANDLE hBridge = NULL; HANDLE hBridge = NULL;
@ -49,7 +51,7 @@ VOID HandleStartButton(BOOL Silent)
return; return;
} }
SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
if (hSCManager == NULL) if (hSCManager == NULL)
{ {
print("OpenSCManager failed: %s\n", GetErrorMessage()); print("OpenSCManager failed: %s\n", GetErrorMessage());
@ -180,7 +182,7 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
HandleRemoveButton(); HandleRemoveButton();
break; break;
case IDM_VIEW_LOG: case IDM_VIEW_LOG:
ShellExecute(NULL, "open", "C:\\windows\\notepad.exe", "C:\\windows\\logs\\bridge.log", NULL, SW_SHOW); ShellExecute(NULL, "open", "C:\\windows\\notepad.exe", logFilePath, NULL, SW_SHOW);
break; break;
case IDM_HELP_DOCUMENTATION: case IDM_HELP_DOCUMENTATION:
ShellExecute(NULL, "open", "https://enderice2.github.io/rpc-bridge/index.html", NULL, NULL, SW_SHOWNORMAL); ShellExecute(NULL, "open", "https://enderice2.github.io/rpc-bridge/index.html", NULL, NULL, SW_SHOWNORMAL);
@ -229,13 +231,6 @@ VOID SetButtonStyles(INT *btnStartStyle, INT *btnRemoveStyle, INT *btnInstallSty
*btnRemoveStyle = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP; *btnRemoveStyle = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP;
*btnInstallStyle = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP; *btnInstallStyle = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP;
// if (!IsLinux)
// {
// *btnInstallStyle |= WS_DISABLED;
// *btnRemoveStyle |= WS_DISABLED;
// return;
// }
SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
SC_HANDLE schService = OpenService(hSCManager, "rpc-bridge", SERVICE_START | SERVICE_QUERY_STATUS); SC_HANDLE schService = OpenService(hSCManager, "rpc-bridge", SERVICE_START | SERVICE_QUERY_STATUS);

100
kvm.c Normal file
View File

@ -0,0 +1,100 @@
#if defined(__linux__)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <signal.h>
void transferData(int fromSock, int toSock)
{
char buffer[256];
ssize_t bytesRead;
while ((bytesRead = read(fromSock, buffer, sizeof(buffer))) > 0)
{
write(toSock, buffer, bytesRead);
}
}
int connectToSocket(const char *socketPath)
{
int sock = socket(AF_UNIX, SOCK_STREAM, 0);
assert(sock >= 0);
struct sockaddr_un addr;
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, socketPath, sizeof(addr.sun_path) - 1);
int result = connect(sock, (struct sockaddr *)&addr, sizeof(addr));
assert(result == 0);
return sock;
}
int kvmSock;
int discordSock;
void sigintHandler(int sig)
{
close(kvmSock);
close(discordSock);
exit(0);
}
int main()
{
signal(SIGINT, sigintHandler);
const char *kvmSocketPath = "/tmp/kvm-rpc-bridge";
const char *discordSocketPath = getenv("XDG_RUNTIME_DIR");
if (discordSocketPath == NULL)
{
fprintf(stderr, "XDG_RUNTIME_DIR environment variable not set\n");
return EXIT_FAILURE;
}
char discordSocketFullPath[256];
snprintf(discordSocketFullPath, sizeof(discordSocketFullPath), "%s/discord-ipc-0", discordSocketPath);
printf("Trying Discord socket at %s\n", discordSocketFullPath);
discordSock = connectToSocket(discordSocketFullPath);
printf("Connected to Discord socket successfully\n");
// Connect to KVM socket
printf("Trying KVM socket at %s\n", kvmSocketPath);
kvmSock = connectToSocket(kvmSocketPath);
// Read specific message from KVM and send confirmation
const char kvmExpectedMsg[] = {0x69, 0x15, 0xBB};
const char kvmResponseMsg[] = {0x6E, 0x1D, 0xB4};
char buffer[3];
ssize_t bytesRead = read(kvmSock, buffer, sizeof(buffer));
printf("Read %ld bytes from KVM (%x %x %x)\n", bytesRead, buffer[0], buffer[1], buffer[2]);
assert(bytesRead == sizeof(kvmExpectedMsg));
assert(memcmp(buffer, kvmExpectedMsg, sizeof(kvmExpectedMsg)) == 0);
ssize_t bytesSent = write(kvmSock, kvmResponseMsg, sizeof(kvmResponseMsg));
assert(bytesSent == sizeof(kvmResponseMsg));
printf("Connected to KVM socket successfully\n");
// Transfer data between KVM and Discord sockets
if (fork() == 0)
{
// Child process: transfer data from KVM to Discord
transferData(kvmSock, discordSock);
}
else
{
// Parent process: transfer data from Discord to KVM
transferData(discordSock, kvmSock);
}
close(kvmSock);
close(discordSock);
return 0;
}
#endif // __linux__

28
main.c
View File

@ -3,10 +3,12 @@
#include <assert.h> #include <assert.h>
#include <stdio.h> #include <stdio.h>
#include "bridge.h"
#include "resource.h" #include "resource.h"
FILE *g_logFile = NULL; FILE *g_logFile = NULL;
BOOL RunningAsService = FALSE; BOOL RunningAsService = FALSE;
char *logFilePath = NULL;
void CreateGUI(); void CreateGUI();
void CreateBridge(); void CreateBridge();
@ -15,7 +17,7 @@ void ServiceMain(int argc, char *argv[]);
void InstallService(int ServiceStartType, LPCSTR Path); void InstallService(int ServiceStartType, LPCSTR Path);
char *native_getenv(const char *name); char *native_getenv(const char *name);
void RemoveService(); void RemoveService();
extern BOOL IsLinux; extern OS_INFO OSInfo;
LPTSTR GetErrorMessage() LPTSTR GetErrorMessage()
{ {
@ -57,11 +59,8 @@ void DetectWine()
} }
if (!GetProcAddress(hNTdll, "wine_get_version")) if (!GetProcAddress(hNTdll, "wine_get_version"))
{ return;
MessageBox(NULL, "This program is only intended to run under Wine.", OSInfo.IsWine = TRUE;
GetErrorMessage(), MB_OK | MB_ICONINFORMATION);
ExitProcess(1);
}
static void(CDECL * wine_get_host_version)(const char **sysname, const char **release); static void(CDECL * wine_get_host_version)(const char **sysname, const char **release);
wine_get_host_version = (void *)GetProcAddress(hNTdll, "wine_get_host_version"); wine_get_host_version = (void *)GetProcAddress(hNTdll, "wine_get_host_version");
@ -78,7 +77,8 @@ void DetectWine()
ExitProcess(1); ExitProcess(1);
} }
IsLinux = strcmp(__sysname, "Linux") == 0; OSInfo.IsLinux = strcmp(__sysname, "Linux") == 0;
OSInfo.IsDarwin = strcmp(__sysname, "Darwin") == 0;
} }
void print(char const *fmt, ...) void print(char const *fmt, ...)
@ -113,14 +113,13 @@ void HandleArguments(int argc, char *argv[])
} }
else if (strcmp(argv[1], "--steam") == 0) else if (strcmp(argv[1], "--steam") == 0)
{ {
assert(OSInfo.IsWine == TRUE);
/* All this mess just so when you close the game, /* All this mess just so when you close the game,
it automatically closes the bridge and Steam it automatically closes the bridge and Steam
will not say that the game is still running. */ will not say that the game is still running. */
print("Running as Steam\n"); print("Running as Steam\n");
if (IsLinux == FALSE)
CreateBridge();
if (argc > 2) if (argc > 2)
{ {
if (strcmp(argv[2], "--no-service") == 0) if (strcmp(argv[2], "--no-service") == 0)
@ -312,7 +311,14 @@ void HandleArguments(int argc, char *argv[])
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
DetectWine(); DetectWine();
char *logFilePath = "C:\\windows\\logs\\bridge.log"; if (OSInfo.IsWine)
logFilePath = "C:\\windows\\logs\\bridge.log";
else
{
logFilePath = (char *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MAX_PATH);
GetTempPath(MAX_PATH, logFilePath);
strcat_s(logFilePath, MAX_PATH, "bridge.log");
}
g_logFile = fopen(logFilePath, "w"); g_logFile = fopen(logFilePath, "w");
if (g_logFile == NULL) if (g_logFile == NULL)
{ {

View File

@ -8,7 +8,6 @@ SERVICE_STATUS_HANDLE g_StatusHandle = NULL;
void print(char const *fmt, ...); void print(char const *fmt, ...);
void CreateBridge(); void CreateBridge();
LPTSTR GetErrorMessage(); LPTSTR GetErrorMessage();
extern BOOL IsLinux;
void WINAPI ServiceCtrlHandler(DWORD CtrlCode) void WINAPI ServiceCtrlHandler(DWORD CtrlCode)
{ {
@ -88,14 +87,6 @@ void InstallService(int ServiceStartType, LPCSTR Path)
{ {
print("Registering service\n"); print("Registering service\n");
// if (IsLinux == FALSE)
// {
// /* FIXME: I don't know how to get the TMPDIR without getenv */
// MessageBox(NULL, "Registering as a service is not supported on macOS at the moment.",
// "Unsupported", MB_OK | MB_ICONINFORMATION);
// ExitProcess(1);
// }
SC_HANDLE schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE); SC_HANDLE schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
if (schSCManager == NULL) if (schSCManager == NULL)
{ {