1
1
#include < string>
2
2
#include < windows.h>
3
+ #include < tlhelp32.h>
4
+ #include < algorithm>
3
5
6
+ #define BUFFER_SIZE 8000
4
7
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
- }
10
8
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);
14
11
}
15
12
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
20
18
}
21
19
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);
36
22
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);
44
29
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
55
34
}
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
59
36
}
60
37
61
- int connect_attempts_remaining = 1 ;
38
+ CloseHandle (hProcessSnap);
39
+ return false ; // obs64.exe is not running
40
+ }
62
41
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 );
66
45
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
+ }
69
52
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
+ }
72
63
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
+ }
75
67
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);
78
72
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)
80
78
}
79
+ return TRUE ; // Continue enumerating windows
80
+ }
81
81
82
-
83
- std::string payload = argv[1 ];
84
-
82
+ int send_auth_to_obs (std::string payload) {
85
83
int pipe_number = 0 ;
86
84
std::string pipe_name = " elgato_cloud" ;
87
85
std::string base_name = " \\\\ .\\ pipe\\ " + pipe_name;
88
86
std::string attempt_name;
89
87
HANDLE pipe = INVALID_HANDLE_VALUE;
88
+ int connect_attempts_remaining = 6 ;
90
89
91
90
while (connect_attempts_remaining-- > 0 &&
92
- pipe == INVALID_HANDLE_VALUE) {
91
+ pipe == INVALID_HANDLE_VALUE) {
93
92
pipe_number = 0 ;
94
93
while (pipe_number < 10 ) {
95
94
attempt_name = base_name + std::to_string (pipe_number);
96
95
printf (" Attempting %s\n " , attempt_name.c_str ());
97
96
pipe = CreateFileA (attempt_name.c_str (), GENERIC_WRITE,
98
- 0 , NULL , OPEN_EXISTING, 0 , NULL );
97
+ 0 , NULL , OPEN_EXISTING, 0 , NULL );
99
98
if (pipe != INVALID_HANDLE_VALUE) {
100
99
printf (" Success\n " );
101
100
break ;
@@ -120,7 +119,7 @@ int main(int argc, char *argv[]) {
120
119
121
120
DWORD written = 0 ;
122
121
success = WriteFile (pipe, payload.c_str (), static_cast <DWORD>(payload.size ()), &written,
123
- NULL );
122
+ NULL );
124
123
if (!success || written < payload.size ()) {
125
124
printf (" Failed to write to named pipe!" );
126
125
CloseHandle (pipe);
@@ -130,3 +129,81 @@ int main(int argc, char *argv[]) {
130
129
CloseHandle (pipe);
131
130
return 0 ;
132
131
}
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