Compare commits

...

5 Commits

Author SHA1 Message Date
EnderIce2
03d5e8dbc8
Add macOS support in GUI 2024-04-05 23:06:32 +03:00
EnderIce2
e5a09024ff
Add GUI creation if no command line arguments are provided 2024-04-05 22:39:14 +03:00
EnderIce2
aeda375cba
Update file paths 2024-04-05 22:36:05 +03:00
EnderIce2
7af098ab26
Add script for Steam (#2) 2024-04-05 21:11:45 +03:00
EnderIce2
7461479cbb
Added captions to MessageBoxes 2024-04-04 04:05:53 +03:00
7 changed files with 533 additions and 97 deletions

View File

@ -2,7 +2,11 @@
"C_Cpp.default.compilerPath": "/usr/bin/i686-w64-mingw32-gcc",
"files.associations": {
"*.su": "tsv",
"thread": "cpp",
"bitset": "cpp",
"initializer_list": "cpp",
"windows.h": "c",
"namedpipeapi.h": "c"
"namedpipeapi.h": "c",
"*.rh": "c"
}
}

View File

@ -440,17 +440,6 @@ void PipeBufferOutThread(LPVOID lpParam)
void CreateBridge()
{
static void(CDECL * wine_get_host_version)(const char **sysname, const char **release);
HMODULE hntdll = GetModuleHandle("ntdll.dll");
wine_get_host_version = (void *)GetProcAddress(hntdll, "wine_get_host_version");
assert(wine_get_host_version);
const char *__sysname;
const char *__release;
wine_get_host_version(&__sysname, &__release);
IsLinux = strcmp(__sysname, "Linux") == 0;
print("Running on %s\n", __sysname);
LPCTSTR lpszPipename = TEXT("\\\\.\\pipe\\discord-ipc-0");
NewConnection:
@ -461,8 +450,11 @@ NewConnection:
print("Pipe already exists: %s\n",
GetErrorMessage());
if (!RunningAsService)
{
MessageBox(NULL, GetErrorMessage(),
NULL, MB_OK | MB_ICONSTOP);
"Pipe already exists",
MB_OK | MB_ICONSTOP);
}
ExitProcess(1);
}
@ -477,8 +469,11 @@ NewConnection:
print("Failed to create pipe: %s\n",
GetErrorMessage());
if (!RunningAsService)
{
MessageBox(NULL, GetErrorMessage(),
NULL, MB_OK | MB_ICONSTOP);
"Failed to create pipe",
MB_OK | MB_ICONSTOP);
}
ExitProcess(1);
}
@ -537,7 +532,11 @@ NewConnection:
{
print("Failed to create threads: %s\n", GetErrorMessage());
if (!RunningAsService)
MessageBox(NULL, GetErrorMessage(), NULL, MB_OK | MB_ICONSTOP);
{
MessageBox(NULL, GetErrorMessage(),
"Failed to create threads",
MB_OK | MB_ICONSTOP);
}
ExitProcess(1);
}

32
build/bridge.sh Executable file
View File

@ -0,0 +1,32 @@
#! /bin/sh
# This script is used to run Steam Play with the bridge.
# Usage: /path/to/bridge.sh %command%
# Original script: https://github.com/0e4ef622/wine-discord-ipc-bridge/blob/master/winediscordipcbridge-steam.sh
# As requested by https://github.com/EnderIce2/rpc-bridge/issues/2
# Exporting BRIDGE_PATH to provide the bridge with its location.
export BRIDGE_PATH="$(dirname "$0")/bridge.exe"
# The "--steam" option prevents the game from
# hanging as "running" in Steam after it is closed.
# This is done by creating a dummy service with
# startup type SERVICE_DEMAND_START so this service
# is only started when we use this script.
BRIDGE_CMD="$BRIDGE_PATH --steam"
# Linux
TEMP_PATH="$XDG_RUNTIME_DIR"
# macOS but Steam Play is not supported on macOS https://github.com/ValveSoftware/Proton/issues/1344
TEMP_PATH=${TEMP_PATH:-"$TMPDIR"}
VESSEL_PATH="$BRIDGE_PATH"
IPC_PATHS="$TEMP_PATH /run/user/$UID $TEMP_PATH/snap.discord $TEMP_PATH/app/com.discordapp.Discord"
for discord_ipc in $IPC_PATHS; do
if [ -S "$discord_ipc"/discord-ipc-0 ]; then
VESSEL_PATH="$BRIDGE_PATH:$(echo "$discord_ipc"/discord-ipc-0)"
break
fi
done
PROTON_REMOTE_DEBUG_CMD="$BRIDGE_CMD" PRESSURE_VESSEL_FILESYSTEMS_RW="$VESSEL_PATH:$PRESSURE_VESSEL_FILESYSTEMS_RW" "$@"

9
game.c
View File

@ -55,7 +55,8 @@ void LaunchGame(int argc, char **argv)
if (!GetBinaryType(argv[1], &dwBinaryType))
{
MessageBox(NULL, GetErrorMessage(),
NULL, MB_OK | MB_ICONSTOP);
"GetBinaryType",
MB_OK | MB_ICONSTOP);
ExitProcess(1);
}
print("Executable type: %d\n", dwBinaryType);
@ -104,7 +105,8 @@ void LaunchGame(int argc, char **argv)
if (!CreateProcess(gamePath, gameArgs, NULL, NULL, FALSE,
0, NULL, NULL, &game_si, &game_pi))
{
MessageBox(NULL, GetErrorMessage(), NULL, MB_OK | MB_ICONSTOP);
MessageBox(NULL, GetErrorMessage(),
"CreateProcess", MB_OK | MB_ICONSTOP);
ExitProcess(1);
}
LocalFree(gameArgs);
@ -136,7 +138,8 @@ void LaunchGame(int argc, char **argv)
}
else
{
MessageBox(NULL, GetErrorMessage(), NULL, MB_OK | MB_ICONSTOP);
MessageBox(NULL, GetErrorMessage(),
"CreateToolhelp32Snapshot", MB_OK | MB_ICONSTOP);
ExitProcess(0);
}

241
gui.c Normal file
View File

@ -0,0 +1,241 @@
#include <windows.h>
#include <winuser.h>
#include <assert.h>
#include <stdio.h>
/**
* The entire code could be better written, but at least it works.
*
* This will make installation and removal of the bridge WAY easier.
*/
LPTSTR GetErrorMessage();
void print(char const *fmt, ...);
void InstallService(int ServiceStartType, LPCSTR Path);
void RemoveService();
void CreateBridge();
extern BOOL IsLinux;
HWND hwnd = NULL;
VOID HandleStartButton(BOOL Silent)
{
if (!IsLinux)
{
ShowWindow(hwnd, SW_MINIMIZE);
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CreateBridge,
NULL, 0, NULL);
HWND item = GetDlgItem(hwnd, /* Start Button */ 1);
EnableWindow(item, FALSE);
item = GetDlgItem(hwnd, 4);
SetWindowText(item, "Bridge is running...");
return;
}
SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (hSCManager == NULL)
{
print("OpenSCManager failed: %s\n", GetErrorMessage());
return;
}
SC_HANDLE schService = OpenService(hSCManager, "rpc-bridge",
SERVICE_QUERY_CONFIG | SERVICE_CHANGE_CONFIG | SERVICE_START);
if (schService == NULL)
{
print("OpenService failed: %s\n", GetErrorMessage());
return;
}
DWORD dwBytesNeeded;
QueryServiceConfig(schService, NULL, 0, &dwBytesNeeded);
LPQUERY_SERVICE_CONFIG lpqsc = (LPQUERY_SERVICE_CONFIG)LocalAlloc(LPTR, dwBytesNeeded);
if (lpqsc == NULL)
{
print("LocalAlloc failed: %s\n", GetErrorMessage());
return;
}
if (!QueryServiceConfig(schService, lpqsc, dwBytesNeeded, &dwBytesNeeded))
{
print("QueryServiceConfig failed: %s\n", GetErrorMessage());
return;
}
if (StartService(schService, 0, NULL) == FALSE)
{
if (GetLastError() == ERROR_SERVICE_ALREADY_RUNNING)
return;
print("StartService failed: %s\n", GetErrorMessage());
}
LocalFree(lpqsc);
CloseServiceHandle(schService);
CloseServiceHandle(hSCManager);
if (Silent == FALSE)
MessageBox(NULL, "Bridge service started successfully", "Info", MB_OK);
}
VOID HandleInstallButton()
{
char filename[MAX_PATH];
GetModuleFileName(NULL, filename, MAX_PATH);
CopyFile(filename, "C:\\windows\\bridge.exe", FALSE);
InstallService(SERVICE_AUTO_START, "C:\\windows\\bridge.exe --service");
MessageBox(NULL, "Bridge installed successfully", "Info", MB_OK);
HandleStartButton(TRUE);
ExitProcess(0);
}
VOID HandleRemoveButton()
{
RemoveService();
MessageBox(NULL, "Bridge removed successfully", "Info", MB_OK);
ExitProcess(0);
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case 1:
HandleStartButton(FALSE);
break;
case 2:
HandleInstallButton();
break;
case 3:
HandleRemoveButton();
break;
default:
break;
}
break;
}
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
ExitProcess(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
VOID SetButtonStyles(INT *btnStartStyle, INT *btnRemoveStyle, INT *btnInstallStyle)
{
*btnStartStyle = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON;
*btnRemoveStyle = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON;
*btnInstallStyle = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON;
if (!IsLinux)
{
*btnInstallStyle |= WS_DISABLED;
*btnRemoveStyle |= WS_DISABLED;
return;
}
SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
SC_HANDLE schService = OpenService(hSCManager, "rpc-bridge", SERVICE_START | SERVICE_QUERY_STATUS);
if (schService != NULL)
{
*btnInstallStyle |= WS_DISABLED;
SERVICE_STATUS_PROCESS ssStatus;
DWORD dwBytesNeeded;
assert(QueryServiceStatusEx(schService, SC_STATUS_PROCESS_INFO, (LPBYTE)&ssStatus,
sizeof(SERVICE_STATUS_PROCESS), &dwBytesNeeded));
if (ssStatus.dwCurrentState == SERVICE_RUNNING ||
ssStatus.dwCurrentState == SERVICE_START_PENDING)
*btnStartStyle |= WS_DISABLED;
}
else
{
*btnStartStyle |= WS_DISABLED;
*btnRemoveStyle |= WS_DISABLED;
}
CloseServiceHandle(schService);
CloseServiceHandle(hSCManager);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
INT btnStartStyle, btnRemoveStyle, btnInstallStyle;
SetButtonStyles(&btnStartStyle, &btnRemoveStyle, &btnInstallStyle);
const char szClassName[] = "BridgeWindowClass";
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = szClassName;
wc.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
assert(RegisterClassEx(&wc));
hwnd = CreateWindowEx(WS_EX_CLIENTEDGE,
szClassName,
"Discord RPC Bridge",
WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME,
(GetSystemMetrics(SM_CXSCREEN) - 400) / 2,
(GetSystemMetrics(SM_CYSCREEN) - 150) / 2,
400, 150,
NULL, NULL, hInstance, NULL);
CreateWindow("STATIC", "Do you want to start, install or remove the bridge?",
WS_CHILD | WS_VISIBLE | SS_CENTER,
0, 0, 400, 50,
hwnd, (HMENU)4, hInstance, NULL);
CreateWindow("BUTTON", "Start",
btnStartStyle,
50, 50, 100, 30,
hwnd, (HMENU)1, hInstance, NULL);
CreateWindow("BUTTON", "Install",
btnInstallStyle,
150, 50, 100, 30,
hwnd, (HMENU)2, hInstance, NULL);
CreateWindow("BUTTON", "Remove",
btnRemoveStyle,
250, 50, 100, 30,
hwnd, (HMENU)3, hInstance, NULL);
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
void CreateGUI()
{
ShowWindow(GetConsoleWindow(), SW_MINIMIZE);
ExitProcess(WinMain(GetModuleHandle(NULL), NULL, GetCommandLine(), SW_SHOWNORMAL));
}

243
main.c
View File

@ -6,11 +6,14 @@
FILE *g_logFile = NULL;
BOOL RunningAsService = FALSE;
void CreateGUI();
void CreateBridge();
void LaunchGame(int argc, char **argv);
void ServiceMain(int argc, char *argv[]);
void InstallService();
void InstallService(int ServiceStartType, LPCSTR Path);
char *native_getenv(const char *name);
void RemoveService();
extern BOOL IsLinux;
LPTSTR GetErrorMessage()
{
@ -45,7 +48,12 @@ void DetectWine()
{
HMODULE hNTdll = GetModuleHandle("ntdll.dll");
if (!hNTdll)
{
MessageBox(NULL, "Failed to load ntdll.dll",
GetErrorMessage(), MB_OK | MB_ICONERROR);
ExitProcess(1);
}
if (!GetProcAddress(hNTdll, "wine_get_version"))
{
MessageBox(NULL, "This program is only intended to run under Wine.",
@ -69,6 +77,9 @@ void DetectWine()
else if (result == IDNO)
ExitProcess(1);
}
IsLinux = strcmp(__sysname, "Linux") == 0;
printf("Running on %s\n", __sysname);
}
void print(char const *fmt, ...)
@ -82,10 +93,202 @@ void print(char const *fmt, ...)
va_end(args);
}
void HandleArguments(int argc, char *argv[])
{
if (strcmp(argv[1], "--service") == 0)
{
RunningAsService = TRUE;
print("Running as service\n");
SERVICE_TABLE_ENTRY ServiceTable[] =
{
{"rpc-bridge", (LPSERVICE_MAIN_FUNCTION)ServiceMain},
{NULL, NULL},
};
if (StartServiceCtrlDispatcher(ServiceTable) == FALSE)
{
print("Service failed to start\n");
ExitProcess(1);
}
}
else if (strcmp(argv[1], "--steam") == 0)
{
/* All this mess just so when you close the game,
it automatically closes the bridge and Steam
will not say that the game is still running. */
print("Running as Steam\n");
if (IsLinux == FALSE)
CreateBridge();
if (argc > 2)
{
if (strcmp(argv[2], "--no-service") == 0)
CreateBridge();
}
SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (hSCManager == NULL)
{
print("(Steam) OpenSCManager: %s\n", GetErrorMessage());
ExitProcess(1);
}
SC_HANDLE schService = OpenService(hSCManager, "rpc-bridge",
SERVICE_QUERY_CONFIG | SERVICE_CHANGE_CONFIG | SERVICE_START);
if (schService == NULL)
{
if (GetLastError() != ERROR_SERVICE_DOES_NOT_EXIST)
{
print("(Steam) OpenService: %s\n", GetErrorMessage());
ExitProcess(1);
}
print("(Steam) Service does not exist, registering...\n");
WCHAR *(CDECL * wine_get_dos_file_name)(LPCSTR str) =
(void *)GetProcAddress(GetModuleHandleA("KERNEL32"),
"wine_get_dos_file_name");
char *unixPath = native_getenv("BRIDGE_PATH");
if (unixPath == NULL)
{
print("(Steam) BRIDGE_PATH not set\n");
ExitProcess(1);
}
WCHAR *dosPath = wine_get_dos_file_name(unixPath);
LPSTR asciiPath = (LPSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MAX_PATH);
WideCharToMultiByte(CP_ACP, 0, dosPath, -1, asciiPath, MAX_PATH, NULL, NULL);
strcat_s(asciiPath, MAX_PATH, " --service");
print("(Steam) Binary path: %s\n", asciiPath);
InstallService(SERVICE_DEMAND_START, asciiPath);
HeapFree(GetProcessHeap(), 0, asciiPath);
/* Create handle for StartService below */
print("(Steam) Service registered, opening handle...\n");
/* FIXME: For some reason here it freezes??? */
schService = OpenService(hSCManager, "rpc-bridge", SERVICE_START);
if (schService == NULL)
{
print("(Steam) Cannot open service after creation: %s\n", GetErrorMessage());
ExitProcess(1);
}
}
else
{
DWORD dwBytesNeeded;
QueryServiceConfig(schService, NULL, 0, &dwBytesNeeded);
LPQUERY_SERVICE_CONFIG lpqsc = (LPQUERY_SERVICE_CONFIG)LocalAlloc(LPTR, dwBytesNeeded);
if (lpqsc == NULL)
{
print("(Steam) LocalAlloc: %s\n", GetErrorMessage());
ExitProcess(1);
}
if (!QueryServiceConfig(schService, lpqsc, dwBytesNeeded, &dwBytesNeeded))
{
print("(Steam) QueryServiceConfig: %s\n", GetErrorMessage());
ExitProcess(1);
}
WCHAR *(CDECL * wine_get_dos_file_name)(LPCSTR str) =
(void *)GetProcAddress(GetModuleHandleA("KERNEL32"),
"wine_get_dos_file_name");
char *unixPath = native_getenv("BRIDGE_PATH");
if (unixPath == NULL)
{
print("(Steam) BRIDGE_PATH not set\n");
ExitProcess(1);
}
WCHAR *dosPath = wine_get_dos_file_name(unixPath);
LPSTR asciiPath = (LPSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MAX_PATH);
WideCharToMultiByte(CP_ACP, 0, dosPath, -1, asciiPath, MAX_PATH, NULL, NULL);
strcat_s(asciiPath, MAX_PATH, " --service");
print("(Steam) Binary path: %s\n", asciiPath);
if (strcmp(lpqsc->lpBinaryPathName, asciiPath) != 0)
{
print("(Steam) Service binary path is not correct, updating...\n");
ChangeServiceConfig(schService, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE,
asciiPath, NULL, NULL, NULL, NULL, NULL, NULL);
}
else
print("(Steam) Service binary path is correct\n");
HeapFree(GetProcessHeap(), 0, asciiPath);
}
print("(Steam) Starting service...\n");
if (StartService(schService, 0, NULL) == FALSE)
{
if (GetLastError() == ERROR_SERVICE_ALREADY_RUNNING)
{
print("(Steam) Service is already running\n");
CloseServiceHandle(schService);
CloseServiceHandle(hSCManager);
ExitProcess(0);
}
print("StartService: %s\n", GetErrorMessage());
MessageBox(NULL, GetErrorMessage(),
"StartService",
MB_OK | MB_ICONSTOP);
ExitProcess(1);
}
print("(Steam) Service started successfully, exiting...\n");
CloseServiceHandle(schService);
CloseServiceHandle(hSCManager);
ExitProcess(0);
}
else if (strcmp(argv[1], "--install") == 0)
{
char filename[MAX_PATH];
GetModuleFileName(NULL, filename, MAX_PATH);
CopyFile(filename, "C:\\windows\\bridge.exe", FALSE);
InstallService(SERVICE_AUTO_START, "C:\\windows\\bridge.exe --service");
ExitProcess(0);
}
else if (strcmp(argv[1], "--uninstall") == 0)
{
RemoveService();
ExitProcess(0);
}
else if (strcmp(argv[1], "--help") == 0)
{
printf("Usage:\n");
printf(" %s [args]\n\n", argv[0]);
printf("Arguments:\n");
printf(" --help Show this help\n\n");
printf(" --install Install service\n");
printf(" This will copy the binary to C:\\windows\\bridge.exe and register it as a service\n\n");
printf(" --uninstall Uninstall service\n");
printf(" This will remove the service and delete C:\\windows\\bridge.exe\n\n");
printf(" --steam Reserved for Steam\n");
printf(" This will start the service and exit (used with bridge.sh)\n\n");
printf(" --no-service Do not run as service\n");
printf(" (only for --steam)\n\n");
printf(" --service Reserved for service\n\n");
printf("Note: If no arguments are provided, the GUI will be shown instead\n");
ExitProcess(0);
}
}
int main(int argc, char *argv[])
{
DetectWine();
char *logFilePath = "C:\\bridge.log";
char *logFilePath = "C:\\windows\\logs\\bridge.log";
g_logFile = fopen(logFilePath, "w");
if (g_logFile == NULL)
{
@ -95,39 +298,9 @@ int main(int argc, char *argv[])
}
if (argc > 1)
{
if (strcmp(argv[1], "--service") == 0)
{
RunningAsService = TRUE;
print("Running as service\n");
SERVICE_TABLE_ENTRY ServiceTable[] =
{
{"rpc-bridge", (LPSERVICE_MAIN_FUNCTION)ServiceMain},
{NULL, NULL},
};
if (StartServiceCtrlDispatcher(ServiceTable) == FALSE)
{
print("Service failed to start\n");
return GetLastError();
}
return 0;
}
else if (strcmp(argv[1], "--install") == 0)
InstallService();
else if (strcmp(argv[1], "--uninstall") == 0)
RemoveService();
else if (strcmp(argv[1], "--help") == 0)
{
printf("Usage:\n");
printf(" %s [args]\n", argv[0]);
printf(" --install - Install service\n");
printf(" --uninstall - Uninstall service\n");
printf(" --help - Show this help\n");
ExitProcess(0);
}
}
HandleArguments(argc, argv);
else
CreateGUI();
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CreateBridge,
NULL, 0, NULL);

View File

@ -8,6 +8,7 @@ SERVICE_STATUS_HANDLE g_StatusHandle = NULL;
void print(char const *fmt, ...);
void CreateBridge();
LPTSTR GetErrorMessage();
extern BOOL IsLinux;
void WINAPI ServiceCtrlHandler(DWORD CtrlCode)
{
@ -83,66 +84,47 @@ void ServiceMain(DWORD argc, LPTSTR *argv)
return;
}
void DetectDarwin()
void InstallService(int ServiceStartType, LPCSTR Path)
{
static void(CDECL * wine_get_host_version)(const char **sysname, const char **release);
wine_get_host_version = (void *)GetProcAddress(GetModuleHandle("ntdll.dll"),
"wine_get_host_version");
const char *__sysname;
const char *__release;
wine_get_host_version(&__sysname, &__release);
if (strcmp(__sysname, "Darwin") == 0)
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);
}
}
void InstallService()
{
print("Registering to run on startup\n");
DetectDarwin();
SC_HANDLE schSCManager, schService;
DWORD dwTagId;
schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
SC_HANDLE schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
if (schSCManager == NULL)
{
print("Failed to open service manager\n");
MessageBox(NULL, GetErrorMessage(),
NULL, MB_OK | MB_ICONSTOP);
"OpenSCManager",
MB_OK | MB_ICONSTOP);
ExitProcess(1);
}
schService =
CreateService(schSCManager,
"rpc-bridge", "Wine RPC Bridge",
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
"C:\\bridge.exe --service",
NULL, &dwTagId, NULL, NULL, NULL);
DWORD dwTagId;
SC_HANDLE schService = CreateService(schSCManager,
"rpc-bridge", "Wine RPC Bridge",
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
ServiceStartType, SERVICE_ERROR_NORMAL,
Path, NULL, &dwTagId, NULL, NULL, NULL);
if (schService == NULL)
{
print("Failed to create service\n");
MessageBox(NULL, GetErrorMessage(),
NULL, MB_OK | MB_ICONSTOP);
"CreateService",
MB_OK | MB_ICONSTOP);
ExitProcess(1);
}
else
{
char filename[MAX_PATH];
GetModuleFileName(NULL, filename, MAX_PATH);
CopyFile(filename, "C:\\bridge.exe", FALSE);
print("Service installed successfully\n");
CloseServiceHandle(schService);
}
print("Service installed successfully\n");
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
ExitProcess(0);
}
void RemoveService()
@ -152,11 +134,12 @@ void RemoveService()
SC_HANDLE schSCManager, schService;
SERVICE_STATUS ssSvcStatus;
schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (schSCManager == NULL)
{
MessageBox(NULL, GetErrorMessage(),
NULL, MB_OK | MB_ICONSTOP);
"OpenSCManager",
MB_OK | MB_ICONSTOP);
ExitProcess(1);
}
@ -166,7 +149,8 @@ void RemoveService()
if (schService == NULL)
{
MessageBox(NULL, GetErrorMessage(),
NULL, MB_OK | MB_ICONSTOP);
"OpenService",
MB_OK | MB_ICONSTOP);
ExitProcess(1);
}
@ -195,13 +179,13 @@ void RemoveService()
if (!DeleteService(schService))
{
MessageBox(NULL, GetErrorMessage(),
NULL, MB_OK | MB_ICONSTOP);
"DeleteService",
MB_OK | MB_ICONSTOP);
ExitProcess(1);
}
DeleteFile("C:\\bridge.exe");
DeleteFile("C:\\windows\\bridge.exe");
print("Service removed successfully\n");
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
ExitProcess(0);
}