d/control: Recommend gdb
[gammaray-debian.git] / injector / windllinjector.cpp
blob4ca66b8c26de0c9df66ababb59a14c5d57a7edcd
1 /*
2 windllinjector.cpp
4 This file is part of GammaRay, the Qt application inspection and
5 manipulation tool.
7 Copyright (C) 2010-2011 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
8 Author: Patrick Spendrin <ps_ml@gmx.de>
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation, either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 //krazy:excludeall=null,captruefalse
25 #include "windllinjector.h"
27 #include <QtCore/QDebug>
29 #ifdef Q_OS_WIN
30 #include <windows.h>
31 #include <cstdlib>
33 using namespace GammaRay;
35 WinDllInjector::WinDllInjector() :
36 m_destProcess(NULL),
37 m_destThread(NULL),
38 mExitCode(-1),
39 mProcessError(QProcess::UnknownError),
40 mExitStatus(QProcess::NormalExit)
44 bool WinDllInjector::launch(const QStringList &programAndArgs,
45 const QString &probeDll, const QString &/*probeFunc*/)
47 DWORD dwCreationFlags = CREATE_NO_WINDOW;
48 dwCreationFlags |= CREATE_UNICODE_ENVIRONMENT;
49 dwCreationFlags |= CREATE_SUSPENDED;
50 STARTUPINFOW startupInfo = { sizeof(STARTUPINFO), 0, 0, 0,
51 (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT,
52 (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT,
53 0, 0, 0, STARTF_USESTDHANDLES, 0, 0, 0,
54 GetStdHandle(STD_INPUT_HANDLE),
55 GetStdHandle(STD_OUTPUT_HANDLE),
56 GetStdHandle(STD_ERROR_HANDLE)
58 PROCESS_INFORMATION pid;
59 memset(&pid, 0, sizeof(PROCESS_INFORMATION));
61 const QString applicationName = programAndArgs.join(" ");
62 BOOL success = CreateProcess(0, (wchar_t *)applicationName.utf16(),
63 0, 0, TRUE, dwCreationFlags,
64 0, 0,
65 &startupInfo, &pid);
66 if (!success) {
67 return false;
70 m_destProcess = pid.hProcess;
71 m_destThread = pid.hThread;
72 m_dllPath = probeDll;
73 m_dllPath.replace('/', '\\');
74 inject();
75 ResumeThread(pid.hThread);
76 WaitForSingleObject(pid.hProcess, INFINITE);
77 DWORD exitCode;
78 GetExitCodeProcess(pid.hProcess, &exitCode);
80 mExitCode = exitCode;
81 //TODO mProcessError = proc.error();
82 //TODO mExitStatus = proc.exitStatus();
83 //TODO mErrorString = proc.errorString();
85 return mExitCode == EXIT_SUCCESS;
88 bool WinDllInjector::attach(int pid, const QString &probeDll, const QString &/*probeFunc*/)
90 m_dllPath = probeDll;
91 m_dllPath.replace('/', '\\');
93 m_destProcess = OpenProcess(PROCESS_ALL_ACCESS, false, pid);
95 if (!m_destProcess) {
96 return false;
99 return inject();
102 int WinDllInjector::exitCode()
104 return mExitCode;
107 QProcess::ProcessError WinDllInjector::processError()
109 return mProcessError;
112 QProcess::ExitStatus WinDllInjector::exitStatus()
114 return mExitStatus;
117 bool WinDllInjector::inject()
119 int strsize = (m_dllPath.size() * 2) + 2;
120 void *mem = VirtualAllocEx(m_destProcess, NULL, strsize, MEM_COMMIT, PAGE_READWRITE);
121 WriteProcessMemory(m_destProcess, mem, (void*)m_dllPath.utf16(), strsize, NULL);
122 HMODULE kernel32handle = GetModuleHandleW(L"Kernel32");
123 FARPROC loadLib = GetProcAddress(kernel32handle, "LoadLibraryW");
124 m_destThread = CreateRemoteThread(m_destProcess, NULL, 0,
125 (LPTHREAD_START_ROUTINE)loadLib,
126 mem, 0, NULL);
128 WaitForSingleObject(m_destThread, INFINITE);
130 DWORD result;
131 GetExitCodeThread(m_destThread, &result);
133 CloseHandle(m_destThread);
134 VirtualFreeEx(m_destProcess, mem, strsize, MEM_RELEASE);
135 return true;
138 QString WinDllInjector::errorString()
140 return mErrorString;
143 #endif