mirror of
https://github.com/EnderIce2/rpc-bridge.git
synced 2025-05-27 15:04:34 +00:00
Compare commits
37 Commits
Author | SHA1 | Date | |
---|---|---|---|
c1078b5b8b | |||
1de80cdbb9 | |||
975ace70f9 | |||
ad076dfac7 | |||
8c54d5bb2f | |||
a0615229ef | |||
18c422101b | |||
77a2a748ad | |||
0d4f46e536 | |||
d065019137 | |||
e03dce1a7c | |||
7c806779d2 | |||
885cf775f9 | |||
7c07952df1 | |||
ea566cfdeb | |||
d56de21e74 | |||
26a016cb26 | |||
edfcce2ae9 | |||
9bec33c358 | |||
3e6b5dbb43 | |||
4c432a0e50 | |||
65b5625a57 | |||
|
9d2440f616 | ||
|
51cbb666f9 | ||
|
1deccc5a63 | ||
|
3412c3c011 | ||
|
c15c4df29e | ||
|
3a0b9ddb2a | ||
|
8786efd144 | ||
|
2024de9408 | ||
|
e8926edb41 | ||
|
9f1a9de3d7 | ||
|
ccf09806c9 | ||
|
7363ee64d5 | ||
|
a3023e349e | ||
|
39966d7149 | ||
|
a8904bf3f1 |
31
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
31
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: bug
|
||||
assignees: EnderIce2
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Log File**
|
||||
Located in `/path/to/prefix/drive_c/windows/logs/bridge.log` or a screenshot with the terminal should suffice.
|
||||
|
||||
**System Info (please complete the following information):**
|
||||
- OS: [e.g. SteamOS 3.0, Ubuntu 22.04, macOS 15, or output from command `uname -srm`]
|
||||
- Wine: [e.g. 10.5]
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: enhancement
|
||||
assignees: EnderIce2
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
35
.github/workflows/build.yml
vendored
Normal file
35
.github/workflows/build.yml
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
name: Build Project
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "master" ]
|
||||
paths-ignore:
|
||||
- 'ISSUE_TEMPLATE/**'
|
||||
- 'workflows/**'
|
||||
- '.vsocde/**'
|
||||
- 'docs/**'
|
||||
pull_request:
|
||||
branches: [ "master" ]
|
||||
paths-ignore:
|
||||
- 'ISSUE_TEMPLATE/**'
|
||||
- 'workflows/**'
|
||||
- '.vsocde/**'
|
||||
- 'docs/**'
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: dependencies
|
||||
run: sudo apt update && sudo apt -y install gcc-mingw-w64 make
|
||||
- name: make
|
||||
run: make
|
||||
- name: artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: bridge
|
||||
path: build
|
@ -1,29 +1,21 @@
|
||||
name: Build and Deploy docs
|
||||
name: Deploy Documentation
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "master" ]
|
||||
branches: [ master ]
|
||||
paths:
|
||||
- docs/**
|
||||
- mkdocs.yml
|
||||
pull_request:
|
||||
branches: [ "master" ]
|
||||
paths:
|
||||
- docs/**
|
||||
- mkdocs.yml
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: dependencies
|
||||
run: sudo apt-get update && sudo apt-get install gcc-mingw-w64 make
|
||||
- name: make
|
||||
run: make
|
||||
- name: artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: bridge
|
||||
path: build
|
||||
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@ -43,4 +35,5 @@ jobs:
|
||||
restore-keys: |
|
||||
mkdocs-material-
|
||||
- run: pip install mkdocs-material
|
||||
- run: pip install mkdocs-video
|
||||
- run: mkdocs gh-deploy --force
|
5
.vscode/c_cpp_properties.json
vendored
5
.vscode/c_cpp_properties.json
vendored
@ -5,7 +5,10 @@
|
||||
"includePath": [
|
||||
"${workspaceFolder}/**"
|
||||
],
|
||||
"defines": [],
|
||||
"defines": [
|
||||
"GIT_COMMIT",
|
||||
"GIT_BRANCH"
|
||||
],
|
||||
"cStandard": "c17",
|
||||
"cppStandard": "gnu++17",
|
||||
"intelliSenseMode": "windows-gcc-x64"
|
||||
|
128
CODE_OF_CONDUCT.md
Normal file
128
CODE_OF_CONDUCT.md
Normal file
@ -0,0 +1,128 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
We as members, contributors, and leaders pledge to make participation in our
|
||||
community a harassment-free experience for everyone, regardless of age, body
|
||||
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
||||
identity and expression, level of experience, education, socio-economic status,
|
||||
nationality, personal appearance, race, religion, or sexual identity
|
||||
and orientation.
|
||||
|
||||
We pledge to act and interact in ways that contribute to an open, welcoming,
|
||||
diverse, inclusive, and healthy community.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to a positive environment for our
|
||||
community include:
|
||||
|
||||
* Demonstrating empathy and kindness toward other people
|
||||
* Being respectful of differing opinions, viewpoints, and experiences
|
||||
* Giving and gracefully accepting constructive feedback
|
||||
* Accepting responsibility and apologizing to those affected by our mistakes,
|
||||
and learning from the experience
|
||||
* Focusing on what is best not just for us as individuals, but for the
|
||||
overall community
|
||||
|
||||
Examples of unacceptable behavior include:
|
||||
|
||||
* The use of sexualized language or imagery, and sexual attention or
|
||||
advances of any kind
|
||||
* Trolling, insulting or derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or email
|
||||
address, without their explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Enforcement Responsibilities
|
||||
|
||||
Community leaders are responsible for clarifying and enforcing our standards of
|
||||
acceptable behavior and will take appropriate and fair corrective action in
|
||||
response to any behavior that they deem inappropriate, threatening, offensive,
|
||||
or harmful.
|
||||
|
||||
Community leaders have the right and responsibility to remove, edit, or reject
|
||||
comments, commits, code, wiki edits, issues, and other contributions that are
|
||||
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
||||
decisions when appropriate.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies within all community spaces, and also applies when
|
||||
an individual is officially representing the community in public spaces.
|
||||
Examples of representing our community include using an official e-mail address,
|
||||
posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported to the community leaders responsible for enforcement at
|
||||
enderice2@protonmail.com.
|
||||
All complaints will be reviewed and investigated promptly and fairly.
|
||||
|
||||
All community leaders are obligated to respect the privacy and security of the
|
||||
reporter of any incident.
|
||||
|
||||
## Enforcement Guidelines
|
||||
|
||||
Community leaders will follow these Community Impact Guidelines in determining
|
||||
the consequences for any action they deem in violation of this Code of Conduct:
|
||||
|
||||
### 1. Correction
|
||||
|
||||
**Community Impact**: Use of inappropriate language or other behavior deemed
|
||||
unprofessional or unwelcome in the community.
|
||||
|
||||
**Consequence**: A private, written warning from community leaders, providing
|
||||
clarity around the nature of the violation and an explanation of why the
|
||||
behavior was inappropriate. A public apology may be requested.
|
||||
|
||||
### 2. Warning
|
||||
|
||||
**Community Impact**: A violation through a single incident or series
|
||||
of actions.
|
||||
|
||||
**Consequence**: A warning with consequences for continued behavior. No
|
||||
interaction with the people involved, including unsolicited interaction with
|
||||
those enforcing the Code of Conduct, for a specified period of time. This
|
||||
includes avoiding interactions in community spaces as well as external channels
|
||||
like social media. Violating these terms may lead to a temporary or
|
||||
permanent ban.
|
||||
|
||||
### 3. Temporary Ban
|
||||
|
||||
**Community Impact**: A serious violation of community standards, including
|
||||
sustained inappropriate behavior.
|
||||
|
||||
**Consequence**: A temporary ban from any sort of interaction or public
|
||||
communication with the community for a specified period of time. No public or
|
||||
private interaction with the people involved, including unsolicited interaction
|
||||
with those enforcing the Code of Conduct, is allowed during this period.
|
||||
Violating these terms may lead to a permanent ban.
|
||||
|
||||
### 4. Permanent Ban
|
||||
|
||||
**Community Impact**: Demonstrating a pattern of violation of community
|
||||
standards, including sustained inappropriate behavior, harassment of an
|
||||
individual, or aggression toward or disparagement of classes of individuals.
|
||||
|
||||
**Consequence**: A permanent ban from any sort of public interaction within
|
||||
the community.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||
version 2.0, available at
|
||||
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
|
||||
|
||||
Community Impact Guidelines were inspired by [Mozilla's code of conduct
|
||||
enforcement ladder](https://github.com/mozilla/diversity).
|
||||
|
||||
[homepage]: https://www.contributor-covenant.org
|
||||
|
||||
For answers to common questions about this code of conduct, see the FAQ at
|
||||
https://www.contributor-covenant.org/faq. Translations are available at
|
||||
https://www.contributor-covenant.org/translations.
|
2
LICENSE
2
LICENSE
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2024 EnderIce2
|
||||
Copyright (c) 2025 EnderIce2
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
11
Makefile
11
Makefile
@ -1,8 +1,13 @@
|
||||
C_SOURCES = $(shell find ./ -type f -name '*.c')
|
||||
C_OBJECTS = $(C_SOURCES:.c=.o)
|
||||
|
||||
CFLAGS = -std=c17 -Wno-int-conversion
|
||||
LFLAGS = -lgdi32
|
||||
GIT_COMMIT = $(shell git rev-parse --short HEAD)
|
||||
GIT_BRANCH = $(shell git rev-parse --abbrev-ref HEAD)
|
||||
|
||||
CWARNFLAGS = -Wno-int-conversion -Wno-incompatible-pointer-types
|
||||
|
||||
CFLAGS = -std=c17 -DGIT_COMMIT='"$(GIT_COMMIT)"' -DGIT_BRANCH='"$(GIT_BRANCH)"'
|
||||
LFLAGS = -lgdi32 -lws2_32
|
||||
|
||||
# DBGFLAGS = -Wl,--export-all-symbols -g -O0 -ggdb3 -Wall
|
||||
|
||||
@ -15,7 +20,7 @@ build: $(C_OBJECTS)
|
||||
|
||||
%.o: %.c
|
||||
$(info Compiling $<)
|
||||
x86_64-w64-mingw32-gcc $(CFLAGS) $(DBGFLAGS) -c $< -o $@
|
||||
x86_64-w64-mingw32-gcc $(CFLAGS) $(CWARNFLAGS) $(DBGFLAGS) -c $< -o $@
|
||||
|
||||
clean:
|
||||
rm -f $(C_OBJECTS) build/bridge.exe bridge.res
|
||||
|
@ -58,12 +58,14 @@ The steps for MacOS are almost the same, but due to the way `$TMPDIR` works, you
|
||||
|
||||
- Download the latest build from the [releases](https://github.com/EnderIce2/rpc-bridge/releases)
|
||||
- Open the archive and make the `launchd.sh` script executable by doing: `chmod +x launchd.sh`
|
||||
- To **install** the LaunchAgent, run `./launchd install` and to **remove** it simply run `./launchd remove`.
|
||||
- To **install** the LaunchAgent, run `./launchd.sh install` and to **remove** it simply run `./launchd.sh remove`.
|
||||
|
||||
The script will add a LaunchAgent to your user, that will symlink the `$TMPDIR` directory to `/tmp/rpc-bridge/tmpdir`.
|
||||
|
||||
*Note: You will need to launch the `bridge.exe` file manually in Wine at least once for it to register and launch automatically the next time.*
|
||||
|
||||
More details on how to install the LaunchAgent can be found in the [documentation](https://enderice2.github.io/rpc-bridge/).
|
||||
|
||||
## Compiling from source
|
||||
|
||||
- Install the `wine`, `gcc-mingw-w64` and `make` packages.
|
||||
|
194
bridge.c
194
bridge.c
@ -20,11 +20,13 @@
|
||||
#define __darwin_close 0x2000006
|
||||
#define __darwin_socket 0x2000061
|
||||
#define __darwin_connect 0x2000062
|
||||
#define __darwin_mmap 0x20000C5
|
||||
#define __darwin_fcntl 0x200005C
|
||||
#define __darwin_sysctl 0x20000CA
|
||||
|
||||
#define O_RDONLY 00
|
||||
|
||||
/* macos & linux are the same for PROT_READ, PROT_WRITE, MAP_FIXED & MAP_PRIVATE */
|
||||
#define PROT_READ 1
|
||||
#define PROT_WRITE 2
|
||||
#define MAP_PRIVATE 0x02
|
||||
@ -32,6 +34,8 @@
|
||||
#define MAP_ANON 0x20
|
||||
#define MAP_FAILED ((void *)-1)
|
||||
|
||||
#define __darwin_MAP_ANON 0x1000
|
||||
|
||||
#define SYS_SOCKET 1
|
||||
#define SYS_CONNECT 3
|
||||
|
||||
@ -134,8 +138,17 @@ 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)
|
||||
{
|
||||
assert(IsLinux);
|
||||
return linux_syscall(__linux_mmap2, addr, length, prot, flags, fd, offset);
|
||||
if (IsLinux)
|
||||
return linux_syscall(__linux_mmap2, addr, length, prot, flags, fd, offset);
|
||||
else
|
||||
{
|
||||
if (flags & MAP_ANON)
|
||||
{
|
||||
flags &= ~MAP_ANON;
|
||||
flags |= __darwin_MAP_ANON;
|
||||
}
|
||||
return darwin_syscall(__darwin_mmap, addr, length, prot, flags, fd, offset);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int sys_munmap(unsigned int *addr, size_t length)
|
||||
@ -195,11 +208,7 @@ char *native_getenv(const char *name)
|
||||
|
||||
/* I hope the 0x20000 is okay */
|
||||
if (environStr == NULL)
|
||||
{
|
||||
environStr = sys_mmap(0x20000, 4096, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
|
||||
print("Allocated 4096 bytes at %#lx\n", environStr);
|
||||
}
|
||||
environStr = sys_mmap(0x20000, 0x1000, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
|
||||
|
||||
if ((uintptr_t)environStr > 0x7effffff)
|
||||
print("Warning: environStr %#lx is above 2GB\n", environStr);
|
||||
@ -209,18 +218,17 @@ char *native_getenv(const char *name)
|
||||
|
||||
int fd = sys_open(environStr, O_RDONLY, 0);
|
||||
|
||||
// sys_munmap(environStr, 4096);
|
||||
if (fd < 0)
|
||||
{
|
||||
print("Failed to open /proc/self/environ: %d\n", fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char buffer[4096];
|
||||
char *buffer = sys_mmap(0x22000, 0x1000, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
|
||||
char *result = NULL;
|
||||
int bytesRead;
|
||||
|
||||
while ((bytesRead = sys_read(fd, buffer, sizeof(buffer) - 1)) > 0)
|
||||
while ((bytesRead = sys_read(fd, buffer, 0x1000 - 1)) > 0)
|
||||
{
|
||||
buffer[bytesRead] = '\0';
|
||||
char *env = buffer;
|
||||
@ -282,41 +290,68 @@ void ConnectToSocket(int fd)
|
||||
print("IPC directory: %s\n", runtime);
|
||||
|
||||
/* TODO: check for multiple discord instances and create a pipe for each */
|
||||
const char *discordUnixPipes[] = {
|
||||
"/discord-ipc-0",
|
||||
"/snap.discord/discord-ipc-0",
|
||||
"/app/com.discordapp.Discord/discord-ipc-0",
|
||||
const char *discordUnixSockets[] = {
|
||||
"%s/discord-ipc-%d",
|
||||
"%s/app/com.discordapp.Discord/discord-ipc-%d",
|
||||
"%s/.flatpak/dev.vencord.Vesktop/xdg-run/discord-ipc-%d",
|
||||
"%s/snap.discord/discord-ipc-%d",
|
||||
"%s/snap.discord-canary/discord-ipc-%d",
|
||||
};
|
||||
|
||||
struct sockaddr_un socketAddr;
|
||||
socketAddr.sun_family = AF_UNIX;
|
||||
char *pipePath = NULL;
|
||||
int sockRet = -1;
|
||||
|
||||
for (int i = 0; i < sizeof(discordUnixPipes) / sizeof(discordUnixPipes[0]); i++)
|
||||
int sockRet = 0;
|
||||
for (int i = 0; i < sizeof(discordUnixSockets) / sizeof(discordUnixSockets[0]); i++)
|
||||
{
|
||||
pipePath = malloc(strlen(runtime) + strlen(discordUnixPipes[i]) + 1);
|
||||
strcpy(pipePath, runtime);
|
||||
strcat(pipePath, discordUnixPipes[i]);
|
||||
strcpy_s(socketAddr.sun_path, sizeof(socketAddr.sun_path), pipePath);
|
||||
size_t pipePathLen = strlen(runtime) + strlen(discordUnixSockets[i]) + 1;
|
||||
char *pipePath = malloc(pipePathLen);
|
||||
|
||||
print("Connecting to %s\n", pipePath);
|
||||
|
||||
if (IsLinux)
|
||||
for (int j = 0; j < 16; j++)
|
||||
{
|
||||
unsigned long socketArgs[] = {
|
||||
(unsigned long)fd,
|
||||
(unsigned long)(intptr_t)&socketAddr,
|
||||
sizeof(socketAddr)};
|
||||
if (IsLinux)
|
||||
{
|
||||
struct sockaddr_un *socketAddr = sys_mmap(0x23000, 0x1000, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
|
||||
print("Socket address allocated at %#lx\n", socketAddr);
|
||||
socketAddr->sun_family = AF_UNIX;
|
||||
|
||||
sockRet = sys_socketcall(SYS_CONNECT, socketArgs);
|
||||
snprintf(pipePath, pipePathLen, discordUnixSockets[i], runtime, j);
|
||||
strcpy_s(socketAddr->sun_path, sizeof(socketAddr->sun_path), pipePath);
|
||||
print("Probing %s\n", pipePath);
|
||||
|
||||
// unsigned long socketArgs[] = {
|
||||
// (unsigned long)fd,
|
||||
// (unsigned long)(intptr_t)&socketAddr,
|
||||
// sizeof(socketAddr)};
|
||||
unsigned long *socketArgs = sys_mmap(0x24000, 0x1000, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
|
||||
socketArgs[0] = (unsigned long)fd;
|
||||
socketArgs[1] = (unsigned long)(intptr_t)socketAddr;
|
||||
socketArgs[2] = sizeof(struct sockaddr_un);
|
||||
socketArgs[3] = 0;
|
||||
|
||||
sockRet = sys_socketcall(SYS_CONNECT, socketArgs);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct sockaddr_un socketAddr;
|
||||
socketAddr.sun_family = AF_UNIX;
|
||||
|
||||
snprintf(pipePath, pipePathLen, discordUnixSockets[i], runtime, j);
|
||||
strcpy_s(socketAddr.sun_path, sizeof(socketAddr.sun_path), pipePath);
|
||||
print("Probing %s\n", pipePath);
|
||||
|
||||
sockRet = sys_connect(fd, (caddr_t)&socketAddr, sizeof(socketAddr));
|
||||
}
|
||||
|
||||
print(" error: %d\n", sockRet);
|
||||
if (sockRet >= 0)
|
||||
break;
|
||||
}
|
||||
else
|
||||
sockRet = sys_connect(fd, (caddr_t)&socketAddr, sizeof(socketAddr));
|
||||
|
||||
free(pipePath);
|
||||
if (sockRet >= 0)
|
||||
{
|
||||
print("Connecting to %s\n", pipePath);
|
||||
free(pipePath);
|
||||
break;
|
||||
}
|
||||
free(pipePath);
|
||||
}
|
||||
|
||||
if (sockRet < 0)
|
||||
@ -333,18 +368,22 @@ void ConnectToSocket(int fd)
|
||||
void PipeBufferInThread(LPVOID lpParam)
|
||||
{
|
||||
bridge_thread *bt = (bridge_thread *)lpParam;
|
||||
print("In thread started using fd %d and pipe %#x\n",
|
||||
bt->fd, bt->hPipe);
|
||||
print("In thread started using fd %d and pipe %#x\n", bt->fd, bt->hPipe);
|
||||
int EOFCount = 0;
|
||||
char *l_buffer;
|
||||
if (IsLinux)
|
||||
l_buffer = sys_mmap(0x25000, 0x1000, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
|
||||
else
|
||||
l_buffer = malloc(BUFFER_LENGTH);
|
||||
print("Buffer in thread allocated at %#lx\n", l_buffer);
|
||||
while (TRUE)
|
||||
{
|
||||
char buffer[BUFFER_LENGTH];
|
||||
int read = sys_read(bt->fd, buffer, sizeof(buffer));
|
||||
int read = sys_read(bt->fd, l_buffer, BUFFER_LENGTH);
|
||||
|
||||
if (unlikely(read < 0))
|
||||
{
|
||||
print("Failed to read from unix pipe: %d\n",
|
||||
GetErrorMessage());
|
||||
print("Failed to read from unix pipe: %d\n", read);
|
||||
Sleep(1000);
|
||||
continue;
|
||||
}
|
||||
@ -366,14 +405,16 @@ void PipeBufferInThread(LPVOID lpParam)
|
||||
}
|
||||
EOFCount = 0;
|
||||
|
||||
memcpy(buffer, l_buffer, read);
|
||||
|
||||
print("Reading %d bytes from unix pipe: \"", read);
|
||||
for (int i = 0; i < read; i++)
|
||||
print("%c", buffer[i]);
|
||||
print("\"\n");
|
||||
|
||||
DWORD dwWritten;
|
||||
if (unlikely(!WriteFile(bt->hPipe, buffer, read,
|
||||
&dwWritten, NULL)))
|
||||
WINBOOL bResult = WriteFile(bt->hPipe, buffer, read, &dwWritten, NULL);
|
||||
if (unlikely(bResult == FALSE))
|
||||
{
|
||||
if (GetLastError() == ERROR_BROKEN_PIPE)
|
||||
{
|
||||
@ -382,16 +423,14 @@ void PipeBufferInThread(LPVOID lpParam)
|
||||
break;
|
||||
}
|
||||
|
||||
print("Failed to read from pipe: %d\n",
|
||||
GetErrorMessage());
|
||||
print("Failed to read from pipe: %s\n", GetErrorMessage());
|
||||
Sleep(1000);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (unlikely(dwWritten < 0))
|
||||
{
|
||||
print("Failed to write to pipe: %d\n",
|
||||
GetErrorMessage());
|
||||
print("Failed to write to pipe: %s\n", GetErrorMessage());
|
||||
Sleep(1000);
|
||||
continue;
|
||||
}
|
||||
@ -399,8 +438,8 @@ void PipeBufferInThread(LPVOID lpParam)
|
||||
while (dwWritten < read)
|
||||
{
|
||||
int last_written = dwWritten;
|
||||
if (unlikely(!WriteFile(bt->hPipe, buffer + dwWritten,
|
||||
read - dwWritten, &dwWritten, NULL)))
|
||||
WINBOOL bResult = WriteFile(bt->hPipe, buffer + dwWritten, read - dwWritten, &dwWritten, NULL);
|
||||
if (unlikely(bResult == FALSE))
|
||||
{
|
||||
if (GetLastError() == ERROR_BROKEN_PIPE)
|
||||
{
|
||||
@ -409,16 +448,14 @@ void PipeBufferInThread(LPVOID lpParam)
|
||||
break;
|
||||
}
|
||||
|
||||
print("Failed to read from pipe: %d\n",
|
||||
GetErrorMessage());
|
||||
print("Failed to read from pipe: %s\n", GetErrorMessage());
|
||||
Sleep(1000);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (unlikely(last_written == dwWritten))
|
||||
{
|
||||
print("Failed to write to pipe: %d\n",
|
||||
GetErrorMessage());
|
||||
print("Failed to write to pipe: %s\n", GetErrorMessage());
|
||||
Sleep(1000);
|
||||
continue;
|
||||
}
|
||||
@ -429,15 +466,19 @@ void PipeBufferInThread(LPVOID lpParam)
|
||||
void PipeBufferOutThread(LPVOID lpParam)
|
||||
{
|
||||
bridge_thread *bt = (bridge_thread *)lpParam;
|
||||
print("Out thread started using fd %d and pipe %#x\n",
|
||||
bt->fd, bt->hPipe);
|
||||
print("Out thread started using fd %d and pipe %#x\n", bt->fd, bt->hPipe);
|
||||
char *l_buffer;
|
||||
if (IsLinux)
|
||||
l_buffer = sys_mmap(0x26000, 0x1000, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
|
||||
else
|
||||
l_buffer = malloc(BUFFER_LENGTH);
|
||||
print("Buffer out thread allocated at %#lx\n", l_buffer);
|
||||
while (TRUE)
|
||||
{
|
||||
char buffer[BUFFER_LENGTH];
|
||||
DWORD dwRead;
|
||||
|
||||
if (unlikely(!ReadFile(bt->hPipe, buffer, sizeof(buffer),
|
||||
&dwRead, NULL)))
|
||||
WINBOOL bResult = ReadFile(bt->hPipe, buffer, BUFFER_LENGTH, &dwRead, NULL);
|
||||
if (unlikely(bResult == FALSE))
|
||||
{
|
||||
if (GetLastError() == ERROR_BROKEN_PIPE)
|
||||
{
|
||||
@ -446,8 +487,7 @@ void PipeBufferOutThread(LPVOID lpParam)
|
||||
break;
|
||||
}
|
||||
|
||||
print("Failed to read from pipe: %d\n",
|
||||
GetErrorMessage());
|
||||
print("Failed to read from pipe: %s\n", GetErrorMessage());
|
||||
Sleep(1000);
|
||||
continue;
|
||||
}
|
||||
@ -457,11 +497,11 @@ void PipeBufferOutThread(LPVOID lpParam)
|
||||
print("%c", buffer[i]);
|
||||
print("\"\n");
|
||||
|
||||
int written = sys_write(bt->fd, buffer, dwRead);
|
||||
memcpy(l_buffer, buffer, dwRead);
|
||||
int written = sys_write(bt->fd, l_buffer, dwRead);
|
||||
if (unlikely(written < 0))
|
||||
{
|
||||
print("Failed to write to socket: %d\n",
|
||||
written);
|
||||
print("Failed to write to socket: %d\n", written);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -471,8 +511,7 @@ void PipeBufferOutThread(LPVOID lpParam)
|
||||
written += sys_write(bt->fd, buffer + written, dwRead - written);
|
||||
if (unlikely(last_written == written))
|
||||
{
|
||||
print("Failed to write to socket: %d\n",
|
||||
GetErrorMessage());
|
||||
print("Failed to write to socket: %s\n", GetErrorMessage());
|
||||
Sleep(1000);
|
||||
continue;
|
||||
}
|
||||
@ -535,16 +574,31 @@ NewConnection:
|
||||
int fd;
|
||||
if (IsLinux)
|
||||
{
|
||||
unsigned long socketArgs[] = {
|
||||
(unsigned long)AF_UNIX,
|
||||
(unsigned long)SOCK_STREAM,
|
||||
0};
|
||||
// unsigned long socketArgs[] = {
|
||||
// (unsigned long)AF_UNIX,
|
||||
// (unsigned long)SOCK_STREAM,
|
||||
// 0};
|
||||
unsigned long *socketArgs = sys_mmap(0x21000, 0x1000, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
|
||||
socketArgs[0] = (unsigned long)AF_UNIX;
|
||||
socketArgs[1] = (unsigned long)SOCK_STREAM;
|
||||
socketArgs[2] = 0;
|
||||
fd = sys_socketcall(SYS_SOCKET, socketArgs);
|
||||
|
||||
/* FIXME: WSAEAFNOSUPPORT: https://gitlab.winehq.org/wine/wine/-/merge_requests/2786 */
|
||||
// WSADATA wsaData;
|
||||
// int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
|
||||
// if (iResult != 0)
|
||||
// printf("WSAStartup failed: %d\n", iResult);
|
||||
// fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
}
|
||||
else
|
||||
fd = sys_socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
|
||||
print("Socket %d created\n", fd);
|
||||
if (fd == INVALID_SOCKET)
|
||||
{
|
||||
print("invalid socket: %d %d\n", fd, WSAGetLastError());
|
||||
ExitProcess(1);
|
||||
}
|
||||
|
||||
if (fd < 0)
|
||||
{
|
||||
@ -555,6 +609,8 @@ NewConnection:
|
||||
ExitProcess(1);
|
||||
}
|
||||
|
||||
print("Socket %d created\n", fd);
|
||||
|
||||
ConnectToSocket(fd);
|
||||
print("Connected to Discord\n");
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
<assemblyIdentity
|
||||
version="1.0.0.0"
|
||||
processorArchitecture="amd64"
|
||||
name="EnderIce2.rpc-bridge"
|
||||
name="com.enderice2.rpc-bridge"
|
||||
type="win32"
|
||||
/>
|
||||
<description>Simple bridge that allows you to use Discord Rich Presence with Wine games/software.</description>
|
||||
|
@ -19,7 +19,7 @@ BEGIN
|
||||
VALUE "FileDescription", "Simple bridge that allows you to use Discord Rich Presence with Wine games/software."
|
||||
VALUE "FileVersion", VER_VERSION_STR
|
||||
VALUE "InternalName", "bridge"
|
||||
VALUE "LegalCopyright", "Copyright (c) 2024 EnderIce2"
|
||||
VALUE "LegalCopyright", "Copyright (c) 2025 EnderIce2"
|
||||
VALUE "OriginalFilename", "bridge.exe"
|
||||
VALUE "ProductName", "rpc-bridge"
|
||||
VALUE "ProductVersion", VER_VERSION_STR
|
||||
|
@ -1,4 +1,4 @@
|
||||
#! /bin/sh
|
||||
#!/bin/sh
|
||||
|
||||
# This script is used to run Steam Play with the bridge.
|
||||
# Usage: /path/to/bridge.sh %command%
|
||||
@ -21,10 +21,10 @@ TEMP_PATH="$XDG_RUNTIME_DIR"
|
||||
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"
|
||||
IPC_PATHS="$TEMP_PATH /run/user/$UID $TEMP_PATH/app/com.discordapp.Discord $TEMP_PATH/.flatpak/dev.vencord.Vesktop/xdg-run $TEMP_PATH/snap.discord $TEMP_PATH/snap.discord-canary"
|
||||
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)"
|
||||
if [ -S "$discord_ipc"/discord-ipc-? ]; then
|
||||
VESSEL_PATH="$BRIDGE_PATH:$(echo "$discord_ipc"/discord-ipc-?)"
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
@ -1,3 +0,0 @@
|
||||
@echo off
|
||||
START /WAIT bridge.exe --install
|
||||
|
@ -8,6 +8,16 @@ LOCATION=~/Library/Application\ Support/rpc-bridge
|
||||
SCRIPT=$LOCATION/rpc-bridge
|
||||
AGENT=~/Library/LaunchAgents/com.enderice2.rpc-bridge.plist
|
||||
|
||||
function is_installed() {
|
||||
if [ -f "$AGENT" ]; then
|
||||
launchctl list | grep -q "com.enderice2.rpc-bridge"
|
||||
if [ $? -eq 0 ]; then
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
function install() {
|
||||
# Directories
|
||||
if [ ! -d "$SYMLINK" ]; then
|
||||
@ -71,9 +81,16 @@ fi
|
||||
|
||||
case $1 in
|
||||
install)
|
||||
if is_installed; then
|
||||
echo "LaunchAgent is already installed."
|
||||
exit 0
|
||||
fi
|
||||
install
|
||||
;;
|
||||
remove)
|
||||
if ! is_installed; then
|
||||
echo "LaunchAgent is not installed. Continuing anyway."
|
||||
fi
|
||||
remove
|
||||
;;
|
||||
*)
|
||||
|
@ -1,3 +0,0 @@
|
||||
@echo off
|
||||
START /WAIT bridge.exe --uninstall
|
||||
|
35
docs/README.md
Normal file
35
docs/README.md
Normal file
@ -0,0 +1,35 @@
|
||||
# Documentation
|
||||
|
||||
> **Note:** This documentation is built and deployed using [MkDocs Material](https://squidfunk.github.io/mkdocs-material/) (with mkdocs-video) via GitHub Actions. For the best experience, view it on the [published site](https://enderice2.github.io/rpc-bridge/) or with MkDocs locally. Some features (such as tabs, videos, or special formatting) may not display correctly in plain Markdown viewers.
|
||||
|
||||
This repository contains the documentation for the project. It is written in Markdown and rendered using MkDocs.
|
||||
|
||||
## Getting Started
|
||||
|
||||
To view the documentation locally, install the required Python packages:
|
||||
|
||||
```bash
|
||||
pip install mkdocs mkdocs-material mkdocs-video
|
||||
```
|
||||
|
||||
Once installed, you can serve the documentation locally by running:
|
||||
|
||||
```bash
|
||||
mkdocs serve
|
||||
```
|
||||
|
||||
This will start a local web server and you can view the documentation in your browser at `http://127.0.0.1:8000`.
|
||||
|
||||
## Contributing
|
||||
|
||||
If you want to contribute to the documentation, please follow these steps:
|
||||
|
||||
1. Fork the repository.
|
||||
2. Make your changes in a branch.
|
||||
3. Submit a pull request.
|
||||
|
||||
Please ensure that your changes are consistent with the existing style and structure of the documentation.
|
||||
|
||||
## License
|
||||
|
||||
This documentation is licensed under the MIT License. See the LICENSE file for more information.
|
BIN
docs/assets/contentwarning.png
Normal file
BIN
docs/assets/contentwarning.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.7 MiB |
Binary file not shown.
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 11 KiB |
BIN
docs/assets/hades.png
Normal file
BIN
docs/assets/hades.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.7 MiB |
BIN
docs/assets/lethalcompany.png
Normal file
BIN
docs/assets/lethalcompany.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 551 KiB |
BIN
docs/assets/macos-crossover.webm
Normal file
BIN
docs/assets/macos-crossover.webm
Normal file
Binary file not shown.
BIN
docs/assets/vividstasis.png
Normal file
BIN
docs/assets/vividstasis.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 945 KiB |
@ -9,7 +9,7 @@ Simple bridge that allows you to use Discord Rich Presence with Wine games/softw
|
||||
|
||||
[Download latest release](https://github.com/EnderIce2/rpc-bridge/releases/latest/download/bridge.zip "Recommended"){ .md-button .md-button--primary }
|
||||
[Download latest pre-release](https://github.com/EnderIce2/rpc-bridge/releases "Unstable builds with experimental features"){ .md-button }
|
||||
<!-- [Download latest build](https://github.com/EnderIce2/rpc-bridge/actions "Builds from the latest commits, here be dragons!"){ .md-button } -->
|
||||
[Download latest build](https://github.com/EnderIce2/rpc-bridge/actions/workflows/build.yml "Builds from the latest commits, here be dragons!"){ .md-button }
|
||||
|
||||
Works by running a small program in the background that creates a [named pipe](https://learn.microsoft.com/en-us/windows/win32/ipc/named-pipes) `\\.\pipe\discord-ipc-0` inside the prefix and forwards all data to the pipe `/run/user/1000/discord-ipc-0`.
|
||||
|
||||
@ -20,11 +20,61 @@ For v1.0, see [the original README](https://github.com/EnderIce2/rpc-bridge/blob
|
||||
|
||||
---
|
||||
|
||||
## Known Issues
|
||||
|
||||
- If you use **Vesktop**
|
||||
Some games may not show up in Discord. This is because Vesktop uses arRPC, which it doesn't work with some games [#4](https://github.com/EnderIce2/rpc-bridge/issues/4#issuecomment-2143549407). This is not an issue with the bridge.
|
||||
|
||||
---
|
||||
|
||||
## My game is not showing up in Discord
|
||||
|
||||
If your game is not showing up in Discord, please check the following:
|
||||
|
||||
- The game you are playing has [Rich Presence](https://discord.com/developers/docs/rich-presence/overview) support!
|
||||
- Some games may not have this feature. It's up to developers of the game to implement it.
|
||||
This is not an issue related to the bridge.
|
||||
|
||||
- You followed the installation steps correctly.
|
||||
|
||||
- You are using the latest version of the bridge. Currently is .
|
||||
|
||||
### I still want to see the game in Discord!
|
||||
|
||||
This is outside the scope of this project, but here are some workarounds:
|
||||
|
||||
- You can manually add the game to Discord by going to `User Settings >` under `Activity Settings` in `Registered Games` tab. [Official Article](https://support.discord.com/hc/en-us/articles/7931156448919-Activity-Status-Recent-Activity#h_01HTJA8QV5ABSA6FY6GEPMA946)
|
||||
- Tip: You can rename the game to whatever you want.
|
||||
|
||||
---
|
||||
|
||||
## Compiling from source
|
||||
|
||||
- Install the `wine`, `gcc-mingw-w64` and `make` packages.
|
||||
- Open a terminal in the directory that contains this file and run `make`.
|
||||
- The compiled executable will be located in `build/bridge.exe`.
|
||||
|
||||
---
|
||||
|
||||
## Examples
|
||||
|
||||
{ width="600" }
|
||||
[**League Of Legends**](https://www.leagueoflegends.com/en-us/) running under Wine using Lutris
|
||||
{ width="600" }
|
||||
|
||||
{ width="600" }
|
||||
[**Among Us**](https://store.steampowered.com/app/945360/Among_Us/) on Steam
|
||||
{ width="600" }
|
||||
|
||||
[**Content Warning**](https://store.steampowered.com/app/2881650/Content_Warning/) on Steam
|
||||
{ width="600" }
|
||||
|
||||
[**Hades**](https://store.steampowered.com/app/1145360/Hades/) on Steam
|
||||
{ width="600" }
|
||||
|
||||
[**Lethal Company**](https://store.steampowered.com/app/1966720/Lethal_Company/) ([modded](https://thunderstore.io/c/lethal-company/p/mrov/LethalRichPresence/)) on Steam
|
||||
{ width="600" }
|
||||
|
||||
[**vivid/stasis**](https://store.steampowered.com/app/2093940/vividstasis/) on Steam
|
||||
{ width="600" }
|
||||
|
||||
## Credits
|
||||
|
||||
|
@ -62,19 +62,6 @@ This method is recommended because it's easier to manage.
|
||||
- Globally
|
||||
- `flatpak override --user --filesystem=xdg-run/discord-ipc-0`
|
||||
|
||||
## macOS
|
||||
|
||||
The steps for MacOS are almost the same, but due to the way `$TMPDIR` works, you will have to install a **LaunchAgent**.
|
||||
|
||||
- Download the latest build from the [releases](https://github.com/EnderIce2/rpc-bridge/releases)
|
||||
- Open the archive and make the `launchd.sh` script executable by doing: `chmod +x launchd.sh`
|
||||
- To **install** the LaunchAgent, run `./launchd install` and to **remove** it simply run `./launchd remove`.
|
||||
|
||||
The script will add a LaunchAgent to your user, that will symlink the `$TMPDIR` directory to `/tmp/rpc-bridge/tmpdir`.
|
||||
|
||||
!!! info "Note"
|
||||
You will need to launch the `bridge.exe` file manually in Wine at least once for it to register and launch automatically the next time.
|
||||
|
||||
## Run without installing the service
|
||||
|
||||
If you prefer not to use the service, you can manually run `bridge.exe` within the Wine prefix.
|
||||
@ -84,28 +71,18 @@ In Lutris, you can achieve this by adding the path to `bridge.exe` in the `Execu
|
||||
|
||||
=== "Without bridge"
|
||||
|
||||
```
|
||||
Executable
|
||||
/mnt/games/lutris/league-of-legends/drive_c/Riot Games/League of Legends/LeagueClient.exe
|
||||
Arguments
|
||||
--locale=en_US --launch-product=league_of_legends --launch-patchline=live
|
||||
```
|
||||
- Executable
|
||||
- `/mnt/games/lutris/league-of-legends/drive_c/Riot Games/League of Legends/LeagueClient.exe`
|
||||
- Arguments
|
||||
- `--locale=en_US --launch-product=league_of_legends --launch-patchline=live`
|
||||
|
||||
=== "With bridge"
|
||||
|
||||
```
|
||||
Executable
|
||||
/mnt/games/lutris/league-of-legends/drive_c/bridge.exe
|
||||
Arguments
|
||||
"C:\Riot Games\League of Legends\LeagueClient.exe" --locale=en_US --launch-product=league_of_legends --launch-patchline=live
|
||||
```
|
||||
- Executable
|
||||
- `/mnt/games/lutris/league-of-legends/drive_c/bridge.exe`
|
||||
- Arguments
|
||||
- `"C:\Riot Games\League of Legends\LeagueClient.exe" --locale=en_US --launch-product=league_of_legends --launch-patchline=live`
|
||||
|
||||
In Wine, all you need to do is run `bridge.exe` and select `Start`.
|
||||
|
||||
## Compiling from source
|
||||
|
||||
- Install the `wine`, `gcc-mingw-w64` and `make` packages.
|
||||
- Open a terminal in the directory that contains this file and run `make`.
|
||||
- The compiled executable will be located in `build/bridge.exe`.
|
||||
|
||||
[^1]: As requested [here](https://github.com/EnderIce2/rpc-bridge/issues/2).
|
28
docs/macos.md
Normal file
28
docs/macos.md
Normal file
@ -0,0 +1,28 @@
|
||||
# Installation
|
||||
|
||||
Installation will copy itself to `C:\windows\bridge.exe` and create a Windows service.
|
||||
Logs are stored in `C:\windows\logs\bridge.log`.
|
||||
|
||||
## Preparing macOS for Installation
|
||||
|
||||
Before proceeding with the installation, you need to set up a **LaunchAgent** due to the way `$TMPDIR` works on macOS.
|
||||
|
||||
- Download the latest build from the [releases](https://github.com/EnderIce2/rpc-bridge/releases).
|
||||
- Open the archive and make the `launchd.sh` script executable by doing: `chmod +x launchd.sh`.
|
||||
- To **install** the LaunchAgent, run `./launchd.sh install` and to **remove** it simply run `./launchd.sh remove`.
|
||||
|
||||
The script will add a LaunchAgent to your user, that will symlink the `$TMPDIR` directory to `/tmp/rpc-bridge/tmpdir`.
|
||||
|
||||
## Video Tutorial on how to install the LaunchAgent + bridge inside CrossOver
|
||||
|
||||
{: style='width: 66%; height: 20vw;'}
|
||||
|
||||
## Wine (~/.wine)
|
||||
|
||||
- Double click `bridge.exe` and click `Install`.
|
||||
- 
|
||||
- To remove, the same process can be followed, but click `Remove` instead.
|
||||
|
||||
## Run without installing the service
|
||||
|
||||
If you prefer not to use the service, you can manually run `bridge.exe` within the prefix, and click on `Start` in the GUI.
|
@ -8,7 +8,7 @@
|
||||
- `Install` will install the service.
|
||||
- `Remove` will uninstall the service.
|
||||
|
||||
## Commands
|
||||
## CLI
|
||||
|
||||
- `--help` Show help message
|
||||
- This will show the help message
|
||||
|
13
gui.c
13
gui.c
@ -191,11 +191,14 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
case IDM_HELP_ABOUT:
|
||||
{
|
||||
char msg[256];
|
||||
sprintf(msg, "rpc-bridge v%s\n\n"
|
||||
"Simple bridge that allows you to use Discord Rich Presence with Wine games/software.\n\n"
|
||||
"Created by EnderIce2\n\n"
|
||||
"Licensed under the MIT License",
|
||||
VER_VERSION_STR);
|
||||
snprintf(msg, sizeof(msg),
|
||||
"rpc-bridge v%s\n"
|
||||
" branch: %s\n"
|
||||
" commit: %s\n\n"
|
||||
"Simple bridge that allows you to use Discord Rich Presence with Wine games/software.\n\n"
|
||||
"Created by EnderIce2\n\n"
|
||||
"Licensed under the MIT License",
|
||||
VER_VERSION_STR, GIT_BRANCH, GIT_COMMIT);
|
||||
MessageBox(NULL, msg, "About", MB_OK);
|
||||
break;
|
||||
}
|
||||
|
99
main.c
99
main.c
@ -59,7 +59,7 @@ void DetectWine()
|
||||
if (!GetProcAddress(hNTdll, "wine_get_version"))
|
||||
{
|
||||
MessageBox(NULL, "This program is only intended to run under Wine.",
|
||||
GetErrorMessage(), MB_OK | MB_ICONINFORMATION);
|
||||
"Error", MB_OK | MB_ICONINFORMATION);
|
||||
ExitProcess(1);
|
||||
}
|
||||
|
||||
@ -221,28 +221,26 @@ void HandleArguments(int argc, char *argv[])
|
||||
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("(Steam) Starting service and then exiting...\n");
|
||||
fclose(g_logFile);
|
||||
|
||||
print("StartService: %s\n", GetErrorMessage());
|
||||
MessageBox(NULL, GetErrorMessage(),
|
||||
"StartService",
|
||||
MB_OK | MB_ICONSTOP);
|
||||
ExitProcess(1);
|
||||
if (StartService(schService, 0, NULL) != FALSE)
|
||||
{
|
||||
CloseServiceHandle(schService);
|
||||
CloseServiceHandle(hSCManager);
|
||||
ExitProcess(0);
|
||||
}
|
||||
else if (GetLastError() == ERROR_SERVICE_ALREADY_RUNNING)
|
||||
{
|
||||
CloseServiceHandle(schService);
|
||||
CloseServiceHandle(hSCManager);
|
||||
ExitProcess(0);
|
||||
}
|
||||
|
||||
print("(Steam) Service started successfully, exiting...\n");
|
||||
CloseServiceHandle(schService);
|
||||
CloseServiceHandle(hSCManager);
|
||||
ExitProcess(0);
|
||||
MessageBox(NULL, GetErrorMessage(),
|
||||
"StartService",
|
||||
MB_OK | MB_ICONSTOP);
|
||||
ExitProcess(1);
|
||||
}
|
||||
else if (strcmp(argv[1], "--install") == 0)
|
||||
{
|
||||
@ -273,38 +271,38 @@ void HandleArguments(int argc, char *argv[])
|
||||
}
|
||||
else if (strcmp(argv[1], "--version") == 0)
|
||||
{
|
||||
printf("%s\n", VER_VERSION_STR);
|
||||
/* Already shows the version */
|
||||
ExitProcess(0);
|
||||
}
|
||||
else if (strcmp(argv[1], "--help") == 0)
|
||||
{
|
||||
printf("Usage:\n"
|
||||
" %s [args]\n"
|
||||
"\n"
|
||||
"Arguments:\n"
|
||||
" --help Show this help\n"
|
||||
"\n"
|
||||
" --version Show version\n"
|
||||
"\n"
|
||||
" --install Install service\n"
|
||||
" This will copy the binary to C:\\windows\\bridge.exe and register it as a service\n"
|
||||
"\n"
|
||||
" --uninstall Uninstall service\n"
|
||||
" This will remove the service and delete C:\\windows\\bridge.exe\n"
|
||||
"\n"
|
||||
" --steam Reserved for Steam\n"
|
||||
" This will start the service and exit (used with bridge.sh)\n"
|
||||
"\n"
|
||||
" --no-service Do not run as service\n"
|
||||
" (only for --steam)\n"
|
||||
"\n"
|
||||
" --service Reserved for service\n"
|
||||
"\n"
|
||||
" --rpc <dir> Set RPC_PATH environment variable\n"
|
||||
" This is used to specify the directory where 'discord-ipc-0' is located\n"
|
||||
"\n"
|
||||
"Note: If no arguments are provided, the GUI will be shown instead\n",
|
||||
argv[0]);
|
||||
print("Usage:\n"
|
||||
" %s [args]\n"
|
||||
"\n"
|
||||
"Arguments:\n"
|
||||
" --help Show this help\n"
|
||||
"\n"
|
||||
" --version Show version\n"
|
||||
"\n"
|
||||
" --install Install service\n"
|
||||
" This will copy the binary to C:\\windows\\bridge.exe and register it as a service\n"
|
||||
"\n"
|
||||
" --uninstall Uninstall service\n"
|
||||
" This will remove the service and delete C:\\windows\\bridge.exe\n"
|
||||
"\n"
|
||||
" --steam Reserved for Steam\n"
|
||||
" This will start the service and exit (used with bridge.sh)\n"
|
||||
"\n"
|
||||
" --no-service Do not run as service\n"
|
||||
" (only for --steam)\n"
|
||||
"\n"
|
||||
" --service Reserved for service\n"
|
||||
"\n"
|
||||
" --rpc <dir> Set RPC_PATH environment variable\n"
|
||||
" This is used to specify the directory where 'discord-ipc-0' is located\n"
|
||||
"\n"
|
||||
"Note: If no arguments are provided, the GUI will be shown instead\n",
|
||||
argv[0]);
|
||||
ExitProcess(0);
|
||||
}
|
||||
}
|
||||
@ -316,11 +314,12 @@ int main(int argc, char *argv[])
|
||||
g_logFile = fopen(logFilePath, "w");
|
||||
if (g_logFile == NULL)
|
||||
{
|
||||
printf("Failed to open logs file: %ld\n",
|
||||
GetLastError());
|
||||
MessageBox(NULL, "Failed to open logs file", "Error", MB_OK | MB_ICONERROR);
|
||||
printf("Failed to open logs file: %ld\n", GetLastError());
|
||||
ExitProcess(1);
|
||||
}
|
||||
|
||||
print("rpc-bridge v%s %s-%s\n", VER_VERSION_STR, GIT_BRANCH, GIT_COMMIT);
|
||||
if (argc > 1)
|
||||
HandleArguments(argc, argv);
|
||||
else
|
||||
|
16
mkdocs.yml
16
mkdocs.yml
@ -14,22 +14,22 @@ theme:
|
||||
palette:
|
||||
- media: "(prefers-color-scheme)"
|
||||
toggle:
|
||||
icon: material/weather-sunny
|
||||
name: Switch to light mode
|
||||
icon: material/brightness-auto
|
||||
name: Switch to dark mode
|
||||
- media: "(prefers-color-scheme: dark)"
|
||||
scheme: slate
|
||||
primary: black
|
||||
accent: indigo
|
||||
toggle:
|
||||
icon: material/brightness-4
|
||||
name: Switch to system preference
|
||||
name: Switch to light mode
|
||||
- media: "(prefers-color-scheme: light)"
|
||||
scheme: default
|
||||
primary: indigo
|
||||
accent: indigo
|
||||
toggle:
|
||||
icon: material/brightness-7
|
||||
name: Switch to dark mode
|
||||
name: Switch to system preference
|
||||
font:
|
||||
text: Roboto
|
||||
code: Roboto Mono
|
||||
@ -70,7 +70,13 @@ markdown_extensions:
|
||||
alternate_style: true
|
||||
plugins:
|
||||
- offline
|
||||
- mkdocs-video:
|
||||
is_video: true
|
||||
video_controls: true
|
||||
video_loop: false
|
||||
video_muted: false
|
||||
nav:
|
||||
- Home: index.md
|
||||
- Installation: installation.md
|
||||
- Linux: linux.md
|
||||
- macOS: macos.md
|
||||
- Usage: usage.md
|
||||
|
@ -5,5 +5,5 @@
|
||||
#define IDM_HELP_ABOUT 40003
|
||||
#define IDM_VIEW_LOG 40004
|
||||
|
||||
#define VER_VERSION 1, 2, 0, 0
|
||||
#define VER_VERSION_STR "1.2\0"
|
||||
#define VER_VERSION 1, 4, 0, 0
|
||||
#define VER_VERSION_STR "1.4.0.0\0"
|
||||
|
Loading…
x
Reference in New Issue
Block a user