blob: 66b51cea65118ee04e915700bf8520e2de67a821 [file] [log] [blame]
#include <stdint.h>
#include <windows.h>
#include <limits.h>
#include <shellapi.h>
#include "dbg.h"
#include "fsatrace.h"
void
injectProcess(HANDLE proc)
{
HANDLE tid;
BOOL is32;
FARPROC addr;
LPVOID arg;
size_t argsz;
char dll[PATH_MAX];
int ndll;
DWORD rc;
static int injecting;
extern IMAGE_DOS_HEADER __ImageBase;
ASSERT(proc);
ZeroMemory(dll, sizeof(dll));
CHK(ndll = GetModuleFileNameA((HMODULE)&__ImageBase, dll, sizeof(dll)));
// dll is one of mypath\fsatrace.exe, mypath\fsatrace64.dll or
// mypath\fsatrace32.dll
CHK(IsWow64Process(proc, &is32));
if (strcasecmp(&dll[ndll - 4], ".exe") == 0)
ndll -= 4; // .exe
else
ndll -= 6; // 32.dll or 64.dll
memcpy(&dll[ndll], is32 ? "32.dll" : "64.dll", 6);
argsz = strlen(dll) + 1;
CHK(0 !=
(arg = VirtualAllocEx(
proc, 0, argsz, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE)));
if (is32 && !IS32) {
STARTUPINFO si;
PROCESS_INFORMATION pi;
const char * helpername = "fsatracehelper.exe";
char helper[PATH_MAX];
char * p;
// On 32bit Windows when we spawn fsatracehelper it reenters
// and tries to run itself again, if we detect this we abort
// since we don't need to trace the command fsatracehelper
// itself
if (injecting)
return;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
memcpy(helper, dll, argsz);
p = strrchr(helper, '\\');
memcpy(p + 1, helpername, strlen(helpername) + 1);
injecting = 1;
CHK(CreateProcessA(0, helper, 0, 0, 0, 0, 0, 0, &si, &pi));
injecting = 0;
CHK(WAIT_OBJECT_0 ==
WaitForSingleObject(pi.hProcess, INFINITE));
CHK(GetExitCodeProcess(pi.hProcess, &rc));
CHK(CloseHandle(pi.hProcess));
CHK(CloseHandle(pi.hThread));
addr = (FARPROC)(uintptr_t)rc;
} else
addr = GetProcAddress(
GetModuleHandle("kernel32.dll"), "LoadLibraryA");
CHK(addr);
CHK(WriteProcessMemory(proc, arg, dll, argsz, NULL));
CHK(0 !=
(tid = CreateRemoteThread(
proc, 0, 0, (LPTHREAD_START_ROUTINE)addr, arg, 0, 0)));
CHK(-1 != ResumeThread(tid));
CHK(WAIT_OBJECT_0 == WaitForSingleObject(tid, INFINITE));
CHK(CloseHandle(tid));
CHK(VirtualFreeEx(proc, arg, 0, MEM_RELEASE));
}
void
injectPID(DWORD pid)
{
HANDLE h;
CHK(0 != (h = OpenProcess(PROCESS_ALL_ACCESS, TRUE, pid)));
injectProcess(h);
CHK(CloseHandle(h));
}