Skip to content

Commit 1708add

Browse files
committed
try to catch relaunches through the steam client
1 parent 25835b8 commit 1708add

3 files changed

Lines changed: 117 additions & 21 deletions

File tree

DebugLoop.cpp

Lines changed: 58 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,18 @@ static void HandleNewProcess(DWORD pid, LPCWSTR filePath)
5252

5353
PID_DEBUG("starting %ws\n", pid, filePath);
5454

55+
GetCurrentDirectoryW(MAX_PATH, g_pathw);
56+
std::wstring currentDir(g_pathw);
57+
5558
GetModuleFileNameW(NULL, g_pathw, MAX_PATH);
5659
wcsrchr(g_pathw, L'\\')[1] = 0;
5760
SetCurrentDirectoryW(g_pathw);
5861

5962
WIN32_FIND_DATAW findData;
6063
HANDLE hFile = FindFirstFileW(L".\\UnrealKey64.dll", &findData);
6164

65+
SetCurrentDirectoryW(currentDir.c_str());
66+
6267
if (hFile != INVALID_HANDLE_VALUE)
6368
{
6469
// got DLL path, load it in the remote process
@@ -137,6 +142,21 @@ static void HandleIndexDataMessage(const PipeMessage& message)
137142
}
138143
}
139144

145+
// ----------------------------------------------------------------------------
146+
static bool HandleSteamAppIDMessage(const PipeMessage& message)
147+
{
148+
snprintf(g_path, sizeof(g_path), "%u", message.msgUInt);
149+
150+
if (SetEnvironmentVariableA("SteamAppID", g_path))
151+
{
152+
PID_DEBUG("Set SteamAppID successfully, app will restart...\n", message.pid);
153+
return true;
154+
}
155+
156+
PID_DEBUG("Couldn't set SteamAppID (error 0x%x)\n", message.pid, GetLastError());
157+
return false;
158+
}
159+
140160
// ----------------------------------------------------------------------------
141161
static bool BreakpointEvent(const DEBUG_EVENT& event, bool &detach)
142162
{
@@ -255,32 +275,44 @@ static BOOL WINAPI CtrlHandler(DWORD type)
255275
}
256276

257277
// ----------------------------------------------------------------------------
258-
int DebugLoop(LPCWSTR appPath)
278+
static bool StartProcess(LPCWSTR appPath, HANDLE hJob, PROCESS_INFORMATION& pi)
259279
{
260-
JOBOBJECT_EXTENDED_LIMIT_INFORMATION jobInfo = { 0 };
261-
HANDLE hJob = CreateJobObjectW(NULL, NULL);
262-
jobInfo.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
263-
SetInformationJobObject(hJob, JobObjectExtendedLimitInformation, &jobInfo, sizeof(jobInfo));
264-
265-
PROCESS_INFORMATION pi = { 0 };
266280
STARTUPINFO si = { 0 };
267281
si.cb = sizeof(si);
268282

269283
if (!CreateProcessW(appPath, NULL, NULL, NULL, FALSE,
270284
CREATE_SUSPENDED | CREATE_BREAKAWAY_FROM_JOB, NULL, NULL, &si, &pi))
271285
{
272286
printf("couldn't launch %ws (error 0x%x)\n", appPath, GetLastError());
273-
return 1;
287+
return false;
274288
}
275289

276-
printf("Starting the game now.\nClose the game or press Ctrl-C to stop.\n\n");
277-
278290
HandleNewProcess(pi.dwProcessId, appPath);
279291
AssignProcessToJobObject(hJob, pi.hProcess);
280292
ResumeThread(pi.hThread);
281293
CloseHandle(pi.hThread);
282294

295+
return true;
296+
}
297+
298+
// ----------------------------------------------------------------------------
299+
int DebugLoop(LPCWSTR appPath)
300+
{
301+
JOBOBJECT_EXTENDED_LIMIT_INFORMATION jobInfo = { 0 };
302+
HANDLE hJob = CreateJobObjectW(NULL, NULL);
303+
jobInfo.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
304+
SetInformationJobObject(hJob, JobObjectExtendedLimitInformation, &jobInfo, sizeof(jobInfo));
305+
306+
PROCESS_INFORMATION pi = { 0 };
307+
308+
printf("Starting the game now.\nClose the game or press Ctrl-C to stop.\n\n");
309+
310+
if (!StartProcess(appPath, hJob, pi))
311+
return 1;
312+
283313
g_running = true;
314+
int rc = 0;
315+
bool restart = false;
284316
DEBUG_EVENT event;
285317
PipeMessage message;
286318
DWORD dwTemp;
@@ -294,6 +326,17 @@ int DebugLoop(LPCWSTR appPath)
294326
{
295327
PID_DEBUG("process exited with code 0x%x\n", pi.dwProcessId, dwTemp);
296328

329+
// if we want to try to restart with a Steam App ID set (or something), do that now
330+
if (restart)
331+
{
332+
restart = false;
333+
334+
if (StartProcess(appPath, hJob, pi))
335+
continue;
336+
else
337+
rc = 1;
338+
}
339+
297340
g_running = false;
298341
break;
299342
}
@@ -315,6 +358,10 @@ int DebugLoop(LPCWSTR appPath)
315358
case IndexDataMessage:
316359
HandleIndexDataMessage(message);
317360
break;
361+
362+
case SteamAppIDMessage:
363+
restart = HandleSteamAppIDMessage(message);
364+
break;
318365
}
319366

320367
HANDLE hThread = OpenThread(THREAD_SUSPEND_RESUME, FALSE, message.tid);
@@ -405,5 +452,5 @@ int DebugLoop(LPCWSTR appPath)
405452
printf("\n\n");
406453
}
407454

408-
return 0;
455+
return rc;
409456
}

common.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ enum PipeMessageType
99
StringMessage,
1010
NewProcessMessage,
1111
IndexDataMessage,
12+
SteamAppIDMessage,
1213
};
1314

1415
struct PipeProcessData
@@ -36,5 +37,6 @@ struct PipeMessage
3637
WCHAR msgString[1024];
3738
PipeProcessData msgProcess;
3839
PipeIndexData msgIndex;
40+
UINT msgUInt;
3941
};
4042
};

dllmain.cpp

Lines changed: 57 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,18 +36,20 @@ std::vector<PakIndex> g_pakIndexes;
3636
static HANDLE g_hPipe;
3737

3838
// WinAPI function hooks
39-
auto orig_ReadFile = ReadFile;
4039
auto orig_CreateProcessW = CreateProcessW;
40+
auto orig_ShellExecuteA = ShellExecuteA;
41+
auto orig_ShellExecuteW = ShellExecuteW;
42+
auto orig_ReadFile = ReadFile;
4143
NTSTATUS (*orig_ZwSetInformationThread)(HANDLE, ULONG, PVOID, ULONG);
4244

4345
// ----------------------------------------------------------------------------
44-
static void SendPipeMessage(PipeMessage *msg)
46+
static void SendPipeMessage(PipeMessage& msg)
4547
{
46-
msg->pid = GetCurrentProcessId();
47-
msg->tid = GetCurrentThreadId();
48+
msg.pid = GetCurrentProcessId();
49+
msg.tid = GetCurrentThreadId();
4850

4951
DWORD dummy;
50-
if (WriteFile(g_hPipe, msg, sizeof(*msg), &dummy, NULL))
52+
if (WriteFile(g_hPipe, &msg, sizeof(msg), &dummy, NULL))
5153
{
5254
// wait for launcher to handle message
5355
SuspendThread(GetCurrentThread());
@@ -65,7 +67,7 @@ static void SendStringMessage(const WCHAR *str, ...)
6567
_vsnwprintf_s(msg.msgString, sizeof(msg.msgString) / sizeof(WCHAR), str, va);
6668
va_end(va);
6769

68-
SendPipeMessage(&msg);
70+
SendPipeMessage(msg);
6971
}
7072

7173
// ----------------------------------------------------------------------------
@@ -116,7 +118,7 @@ static BOOL WINAPI hook_CreateProcessW(LPCWSTR name, LPWSTR cmdLine, LPSECURITY_
116118

117119
msg.msgProcess.pid = pi->dwProcessId;
118120
msg.msgProcess.flags = flags;
119-
SendPipeMessage(&msg);
121+
SendPipeMessage(msg);
120122

121123
// if the process wasn't already supposed to be suspended, unsuspend it now
122124
if (!(flags & CREATE_SUSPENDED))
@@ -130,6 +132,49 @@ static BOOL WINAPI hook_CreateProcessW(LPCWSTR name, LPWSTR cmdLine, LPSECURITY_
130132
return FALSE;
131133
}
132134

135+
// ----------------------------------------------------------------------------
136+
static void RunWithSteamAppID(UINT appID)
137+
{
138+
SendStringMessage(L"Tried to launch Steam w/ app ID %u", appID);
139+
140+
PipeMessage msg;
141+
msg.msgType = SteamAppIDMessage;
142+
msg.msgUInt = appID;
143+
SendPipeMessage(msg);
144+
}
145+
146+
// ----------------------------------------------------------------------------
147+
static HINSTANCE WINAPI hook_ShellExecuteA(HWND hwnd, LPCSTR lpOperation, LPCSTR lpFile, LPCSTR lpParams, LPCSTR lpDir, INT nShowCmd)
148+
{
149+
UINT appID;
150+
151+
if (lpOperation && lpFile
152+
&& !strcmp(lpOperation, "open")
153+
&& sscanf_s(lpFile, "steam://run/%u", &appID) == 1)
154+
{
155+
RunWithSteamAppID(appID);
156+
return 0;
157+
}
158+
159+
return orig_ShellExecuteA(hwnd, lpOperation, lpFile, lpParams, lpDir, nShowCmd);
160+
}
161+
162+
// ----------------------------------------------------------------------------
163+
static HINSTANCE WINAPI hook_ShellExecuteW(HWND hwnd, LPCWSTR lpOperation, LPCWSTR lpFile, LPCWSTR lpParams, LPCWSTR lpDir, INT nShowCmd)
164+
{
165+
UINT appID;
166+
167+
if (lpFile && lpParams
168+
&& wcsstr(lpFile, L"steam.exe")
169+
&& swscanf_s(lpParams, L"steam://run/%u", &appID) == 1)
170+
{
171+
RunWithSteamAppID(appID);
172+
return 0;
173+
}
174+
175+
return orig_ShellExecuteW(hwnd, lpOperation, lpFile, lpParams, lpDir, nShowCmd);
176+
}
177+
133178
// ----------------------------------------------------------------------------
134179
static BOOL WINAPI hook_ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nSize, LPDWORD lpSize, LPOVERLAPPED lpOverlapped)
135180
{
@@ -174,7 +219,7 @@ static BOOL WINAPI hook_ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nSize, LPD
174219
// SendStringMessage(L"Reading encrypted pak index to 0x%p for %ws", lpBuffer, msg.msgIndex.filePath);
175220
SendStringMessage(L"Reading encrypted pak index for %ws", wcsrchr(msg.msgIndex.filePath, L'\\') + 1);
176221
// SendStringMessage(L"Buffer size is 0x%x", nSize);
177-
SendPipeMessage(&msg);
222+
SendPipeMessage(msg);
178223
}
179224
}
180225
}
@@ -214,6 +259,8 @@ static void Init()
214259
if (!hookStatus)
215260
{
216261
MH_CreateHook(CreateProcessW, hook_CreateProcessW, (LPVOID*)&orig_CreateProcessW);
262+
MH_CreateHook(ShellExecuteA, hook_ShellExecuteA, (LPVOID*)&orig_ShellExecuteA);
263+
MH_CreateHook(ShellExecuteW, hook_ShellExecuteW, (LPVOID*)&orig_ShellExecuteW);
217264
MH_CreateHook(ReadFile, hook_ReadFile, (LPVOID*)&orig_ReadFile);
218265
MH_CreateHook(GetProcAddress(GetModuleHandleA("ntdll"), "ZwSetInformationThread"),
219266
hook_ZwSetInformationThread, (LPVOID*)&orig_ZwSetInformationThread);
@@ -225,12 +272,12 @@ static void Init()
225272
}
226273
else
227274
{
228-
SendStringMessage(L"MinHook enable failed: %s", MH_StatusToString(hookStatus));
275+
SendStringMessage(L"MinHook enable failed: %hs", MH_StatusToString(hookStatus));
229276
}
230277
}
231278
else
232279
{
233-
SendStringMessage(L"MinHook init failed: %s", MH_StatusToString(hookStatus));
280+
SendStringMessage(L"MinHook init failed: %hs", MH_StatusToString(hookStatus));
234281
}
235282
}
236283

0 commit comments

Comments
 (0)