Skip to content

Commit a786ee6

Browse files
helper app now launches OBS
1 parent 1a90d52 commit a786ee6

File tree

1 file changed

+142
-65
lines changed

1 file changed

+142
-65
lines changed

loader/main.cpp

Lines changed: 142 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,101 +1,100 @@
11
#include <string>
22
#include <windows.h>
3+
#include <tlhelp32.h>
4+
#include <algorithm>
35

6+
#define BUFFER_SIZE 8000
47

5-
bool obs_is_running(std::wstring name) {
6-
for (size_t i = 0; i < name.size(); ++i) {
7-
if (!iswalnum(name[i]))
8-
name[i] = L'_';
9-
}
108

11-
printf("CHECKING %ls\n", name.c_str());
12-
HANDLE h = OpenMutexW(SYNCHRONIZE, false, name.c_str());
13-
return !!h;
9+
void ToLowerCase(std::wstring& str) {
10+
std::transform(str.begin(), str.end(), str.begin(), ::towlower);
1411
}
1512

16-
int main(int argc, char *argv[]) {
17-
if (argc < 2) {
18-
printf("Please provide an argument");
19-
return 1;
13+
bool IsObs64Running() {
14+
// Take a snapshot of all processes
15+
HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
16+
if (hProcessSnap == INVALID_HANDLE_VALUE) {
17+
return false; // Failed to take snapshot
2018
}
2119

22-
#define BUFFER_SIZE 8000
23-
DWORD buffer_size = BUFFER_SIZE;
24-
wchar_t buffer[BUFFER_SIZE];
25-
26-
std::wstring config_path;
27-
std::wstring launch_path;
28-
29-
/* auto status = RegGetValueW(HKEY_CURRENT_USER,
30-
L"SOFTWARE\\elgato\\obs",
31-
L"config path", RRF_RT_REG_SZ, nullptr, buffer,
32-
&buffer_size);
33-
if (status == ERROR_SUCCESS) {
34-
config_path = std::wstring(buffer, buffer_size);
35-
}*/
20+
PROCESSENTRY32 pe32;
21+
pe32.dwSize = sizeof(PROCESSENTRY32);
3622

37-
buffer_size = BUFFER_SIZE;
38-
auto status = RegGetValueW(HKEY_CURRENT_USER, L"SOFTWARE\\elgato\\obs", L"",
39-
RRF_RT_REG_SZ, nullptr, buffer, &buffer_size);
40-
// Ignore if the value is too long for our buffer. The user can suffer if OBS is installed in a path longer than 8000 characters long
41-
if (status == ERROR_SUCCESS) {
42-
launch_path = std::wstring(buffer, buffer_size);
43-
}
23+
// Start iterating through processes
24+
if (Process32First(hProcessSnap, &pe32)) {
25+
do {
26+
// Convert the process name to lowercase for comparison
27+
std::wstring processName(pe32.szExeFile);
28+
ToLowerCase(processName);
4429

45-
bool running = obs_is_running(L"OBSStudioCore");
46-
47-
if (!running) {
48-
config_path = launch_path;
49-
int remaining = 3;
50-
while (remaining-- > 0) {
51-
auto pos = config_path.find_last_of(L"\\/");
52-
if (pos != std::string::npos) {
53-
config_path.erase(config_path.begin() + pos,
54-
config_path.end());
30+
// Compare process name to "obs64.exe" in lowercase
31+
if (processName == L"obs64.exe") {
32+
CloseHandle(hProcessSnap);
33+
return true; // obs64.exe is running
5534
}
56-
}
57-
config_path += L"\\config";
58-
running = obs_is_running(std::wstring(L"OBSStudioPortable") + config_path);
35+
} while (Process32Next(hProcessSnap, &pe32)); // Move to next process
5936
}
6037

61-
int connect_attempts_remaining = 1;
38+
CloseHandle(hProcessSnap);
39+
return false; // obs64.exe is not running
40+
}
6241

63-
if (!running && launch_path.size() > 0) {
64-
auto wd = launch_path.substr(
65-
0, launch_path.find_last_of(L"\\/"));
42+
DWORD GetProcessIdFromExe(const std::wstring& exeName) {
43+
PROCESSENTRY32 processEntry;
44+
processEntry.dwSize = sizeof(PROCESSENTRY32);
6645

67-
STARTUPINFOW si;
68-
PROCESS_INFORMATION pi;
46+
// Create a snapshot of all running processes
47+
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
48+
if (hSnapshot == INVALID_HANDLE_VALUE) {
49+
printf("Error taking snapshot of processes.");
50+
return 0;
51+
}
6952

70-
printf("Try create %ls with %ls\n", launch_path.c_str(),
71-
wd.c_str());
53+
// Iterate through all processes
54+
if (Process32First(hSnapshot, &processEntry)) {
55+
do {
56+
// Compare the process executable name with the target exe name
57+
if (exeName == processEntry.szExeFile) {
58+
CloseHandle(hSnapshot);
59+
return processEntry.th32ProcessID; // Return the process ID
60+
}
61+
} while (Process32Next(hSnapshot, &processEntry));
62+
}
7263

73-
WCHAR lpCommandLine[] = L"";
74-
CreateProcessW(launch_path.c_str(), lpCommandLine, NULL, NULL, FALSE, 0, NULL, wd.c_str(), &si, &pi);
64+
CloseHandle(hSnapshot);
65+
return 0; // Not found
66+
}
7567

76-
CloseHandle(pi.hProcess);
77-
CloseHandle(pi.hThread);
68+
// Callback function to find the window associated with a given process ID
69+
BOOL CALLBACK WindowToForeground(HWND hwnd, LPARAM lParam) {
70+
DWORD processId;
71+
GetWindowThreadProcessId(hwnd, &processId);
7872

79-
connect_attempts_remaining = 6;
73+
if (processId == lParam) {
74+
// Bring the window to the foreground
75+
SetForegroundWindow(hwnd);
76+
ShowWindow(hwnd, SW_RESTORE); // Restore if minimized
77+
return FALSE; // Stop enumerating windows (we found the window)
8078
}
79+
return TRUE; // Continue enumerating windows
80+
}
8181

82-
83-
std::string payload = argv[1];
84-
82+
int send_auth_to_obs(std::string payload) {
8583
int pipe_number = 0;
8684
std::string pipe_name = "elgato_cloud";
8785
std::string base_name = "\\\\.\\pipe\\" + pipe_name;
8886
std::string attempt_name;
8987
HANDLE pipe = INVALID_HANDLE_VALUE;
88+
int connect_attempts_remaining = 6;
9089

9190
while (connect_attempts_remaining-- > 0 &&
92-
pipe == INVALID_HANDLE_VALUE) {
91+
pipe == INVALID_HANDLE_VALUE) {
9392
pipe_number = 0;
9493
while (pipe_number < 10) {
9594
attempt_name = base_name + std::to_string(pipe_number);
9695
printf("Attempting %s\n", attempt_name.c_str());
9796
pipe = CreateFileA(attempt_name.c_str(), GENERIC_WRITE,
98-
0, NULL, OPEN_EXISTING, 0, NULL);
97+
0, NULL, OPEN_EXISTING, 0, NULL);
9998
if (pipe != INVALID_HANDLE_VALUE) {
10099
printf("Success\n");
101100
break;
@@ -120,7 +119,7 @@ int main(int argc, char *argv[]) {
120119

121120
DWORD written = 0;
122121
success = WriteFile(pipe, payload.c_str(), static_cast<DWORD>(payload.size()), &written,
123-
NULL);
122+
NULL);
124123
if (!success || written < payload.size()) {
125124
printf("Failed to write to named pipe!");
126125
CloseHandle(pipe);
@@ -130,3 +129,81 @@ int main(int argc, char *argv[]) {
130129
CloseHandle(pipe);
131130
return 0;
132131
}
132+
133+
int launch_obs()
134+
{
135+
DWORD buffer_size = BUFFER_SIZE;
136+
wchar_t buffer[BUFFER_SIZE];
137+
138+
std::wstring config_path;
139+
std::wstring launch_path;
140+
141+
buffer_size = BUFFER_SIZE;
142+
auto status = RegGetValueW(HKEY_CURRENT_USER, L"SOFTWARE\\elgato\\obs", L"",
143+
RRF_RT_REG_SZ, nullptr, buffer, &buffer_size);
144+
// Ignore if the value is too long for our buffer. The user can suffer if OBS is installed in a path longer than 8000 characters long
145+
if (status == ERROR_SUCCESS) {
146+
launch_path = std::wstring(buffer, buffer_size);
147+
}
148+
149+
bool running = IsObs64Running();
150+
151+
if (!running && launch_path.size() > 0) {
152+
auto wd = launch_path.substr(
153+
0, launch_path.find_last_of(L"\\/"));
154+
155+
STARTUPINFOW si = { sizeof(STARTUPINFO) };
156+
PROCESS_INFORMATION pi;
157+
158+
printf("Try create %ls with %ls\n", launch_path.c_str(),
159+
wd.c_str());
160+
161+
//WCHAR lpCommandLine[] = L"";
162+
if (CreateProcess(launch_path.c_str(), NULL, NULL, NULL, FALSE, 0, NULL, wd.c_str(), &si, &pi) == 0) {
163+
printf("Failed to launch OBS.");
164+
return 1;
165+
}
166+
167+
CloseHandle(pi.hProcess);
168+
CloseHandle(pi.hThread);
169+
170+
return 0;
171+
} else if (running) {
172+
DWORD processId = GetProcessIdFromExe(L"obs64.exe");
173+
if (processId == 0) {
174+
printf("Process not found!");
175+
return 1;
176+
}
177+
EnumWindows(WindowToForeground, processId);
178+
}
179+
return 0;
180+
}
181+
182+
bool obs_is_running(std::wstring name) {
183+
for (size_t i = 0; i < name.size(); ++i) {
184+
if (!iswalnum(name[i]))
185+
name[i] = L'_';
186+
}
187+
188+
printf("CHECKING %ls\n", name.c_str());
189+
HANDLE h = OpenMutexW(SYNCHRONIZE, false, name.c_str());
190+
return !!h;
191+
}
192+
193+
int main(int argc, char *argv[]) {
194+
if (argc < 2) {
195+
printf("Please provide an argument");
196+
return 1;
197+
}
198+
199+
std::string payload = argv[1];
200+
201+
if (payload.find("elgatolink://auth") == 0) {
202+
// Send auth to OBS which requested it.
203+
return send_auth_to_obs(payload);
204+
} else {
205+
return launch_obs();
206+
}
207+
printf("No obs found to launch.");
208+
return 1;
209+
}

0 commit comments

Comments
 (0)