Get active processname in vc++ - c++

Am working on a background appliation in vc++
How can i get the Process Name of the current Application for example "Iexplore" for Using Internet Explorer, "Skype" for window with tile "Skype - username", "Explorer" for using windows explorer ?
i referred this link but am getting Null error : http://www.codeproject.com/Articles/14843/Finding-module-name-from-the-window-handle

This can be done using the following code:
bool GetActiveProcessName(TCHAR *buffer, DWORD cchLen)
{
HWND fg = GetForegroundWindow();
if (fg)
{
DWORD pid;
GetWindowThreadProcessId(fg, &pid);
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
if (hProcess)
{
BOOL ret = QueryFullProcessImageName(hProcess, 0, buffer, &cchLen);
//here you can trim process name if necessary
CloseHandle(hProcess);
return (ret != FALSE);
}
}
return false;
}
and then
TCHAR buffer[MAX_PATH];
if(GetActiveProcessName(buffer, MAX_PATH))
{
_tprintf(_T("Active process: %s\n"), buffer);
}
else
{
_tprintf(_T("Cannot obtain active process name.\n"));
}
Note though that QueryFullProcessImageName function is only available since Windows Vista, on earlier systems you could use GetProcessImageFileName (it is similar, but requires linkage with psapi.dll and returns device path instead of usual win32 path)

I used this code in my QT5/C++ project to get the currently active process name and window title successfully, based on some research (thanks #dsi). Just wanted to share the code so that someone else would benefit from it.
# Put this two declarations in the top of the CPP file
#include <windows.h>
#pragma comment(lib, "user32.lib")
And put the following into a method:
// get handle of currently active window
HWND hwnd = GetForegroundWindow();
if (hwnd) {
// Get active app name
DWORD maxPath = MAX_PATH;
wchar_t app_path[MAX_PATH];
DWORD pid;
GetWindowThreadProcessId(hwnd, &pid);
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
if (hProcess) {
QueryFullProcessImageName(hProcess, 0, app_path, &maxPath);
// here you can trim process name if necessary
CloseHandle(hProcess);
QString appPath = QString::fromWCharArray(app_path).trimmed();
QFileInfo appFileInfo(appPath);
windowInfo.appName = appFileInfo.fileName();
}
// Get active window title
wchar_t wnd_title[256];
GetWindowText(hwnd, wnd_title, sizeof(wnd_title));
windowInfo.windowTitle = QString::fromWCharArray(wnd_title);
}
This code may not be compiled directly, because windowInfo is a parameter in my program. Please feel free to let me know in case you encountered any issues when trying this code.

Related

why openprocess function return different handle each time?

I want to get the process and thread handles about some games to inject dll, and I used OpenProcess() and OpenThread() to obtain these handles. But I found that I just get different handles each time I use these functions. And they are useless for me because they arent the true handles. Please tell me how I can get the true handles?
Thanks for your answers and comments! And I found that I did not describe my problem very well. Sorry.
Actually, if i used CreateProcess() funtion to launch a process and get handles from parameter lpProcessInformation pi. I could inject my dll into game through these handles named pi.hProcess and pi.hThread. And these handles seem like would not change during the program's runtime.
But if I got handles from OpenProcess() and OpenThread(), the process handle and thread handle were not same as the handle from CreateProcess() even though I got them in same run from a process.
So I thought that the handle from pi is the true handle, and the handle from OpenProcess() are fake. I dont know why they are different and why only handles from pi can work well.
Please tell me the difference about handles from OpenProcess() and
CreateProcess(). Or how I can get the handles same as CreateProcess() through PID.
This is the code how inject dll. And ony handles from pi.hProcess and pi.hThread can work.
void KInject::InjectDll(HANDLE hProcess, HANDLE hThread, ULONG_PTR param){
QueueUserAPC(
(PAPCFUNC)GetProcAddress(GetModuleHandleA("kernel32.dll"), "LoadLibraryA"),
hThread,
(ULONG_PTR)param
);
}
void KInject::Inject2(HANDLE hProcess, HANDLE hThread, const char* szDLL ){
SIZE_T len = strlen(szDLL) + 1;
PVOID param = VirtualAllocEx(hProcess, NULL, len, MEM_COMMIT | MEM_TOP_DOWN /*MEM_RESERVE*/, PAGE_READWRITE);
if (param != NULL)
{
SIZE_T ret;
if (WriteProcessMemory(hProcess, param, szDLL, len, &ret)) {
InjectDll(hProcess, hThread, (ULONG_PTR)param );
}
}
}
This is the code how i get handles.
#include <Windows.h>
#include "tlhelp32.h"
#include <stdio.h>
#include <string.h>
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{
HWND hq = FindWindow(NULL, "Temp");
RECT rect;
DWORD dwThreadID;
DWORD dwProcessId;
GetWindowThreadProcessId(hq, &dwProcessId);
GetWindowRect(hq, &rect);
DWORD a = GetWindowThreadProcessId(hq, &dwProcessId);
THREADENTRY32 te32 = { sizeof(te32) };
HANDLE hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if (Thread32First(hThreadSnap, &te32))
{
do {
if (dwProcessId == te32.th32OwnerProcessID)
{
dwThreadID = te32.th32ThreadID;
break;
}
} while (Thread32Next(hThreadSnap, &te32));
}
CloseHandle(hThreadSnap);
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, dwThreadID);
CloseHandle(hThread);
CloseHandle(hProcess);
return 0;
}
There is nothing wrong with the API in this regard. Their return values are just what they are supposed to be, i.e. "handles" to the actual processes and threads. Exactly the same way as when you open a file, you get a handle to it, and if you open the same file multiple times, you may get different handles.
Having said that, just in the same way that files do have a more permanent name—which is their paths—processes and threads also do have a more permanent name and its called their "ID".
You can use the Win32 functions GetProcessId(HANDLE handle) and GetThreadId(HANDLE handle) to get to these more permanent identifiers.

Detours: Prevent task kill of my software via another software

I have found a code that promises to intercept and detour calls to the TerminateProcess function and thus prevent my software from being killed directly from other program.
But this code is not working and I am still able to kill my process via other program.
Here is the last my attempt with a code I have found in this YouTube video:
PS: victim.exe is the killer program.
DLL
// DllRedirectAPI.cpp : Defines the exported functions for the DLL application.
//
#include "stdafx.h"
#include <Windows.h>
BYTE MOV[10] = { 0x48, 0xB8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
BYTE JMP_RAX[2] = { 0xFF, 0xE0 };
#define BuffSizeX64 (sizeof(MOV) + sizeof(JMP_RAX))
BOOL Hook_Det_x64(char LibName[], char API_Name[], LPVOID NewFun) {
DWORD OldProtect;
DWORD64 OrgAddress = (DWORD64)GetProcAddress(LoadLibraryA(LibName), API_Name);
if (OrgAddress == NULL) return 0;
memcpy(&MOV[2], &NewFun, 8);
VirtualProtect((LPVOID)OrgAddress, BuffSizeX64, PAGE_EXECUTE_READWRITE, &OldProtect);
memcpy((LPVOID)OrgAddress, MOV, sizeof(MOV));
memcpy((LPVOID)(OrgAddress + sizeof(MOV)), JMP_RAX, sizeof(JMP_RAX));
VirtualProtect((LPVOID)OrgAddress, BuffSizeX64, OldProtect, &OldProtect);
return 1;
}
int WINAPI MessageBoxAX(
HWND hWnd,
LPCSTR lpText,
LPCSTR lpCaption,
UINT uType) {
MessageBoxExA(0, "Hooked ...", "Mahmoud", 0, 0);
return 999;
}
BOOL WINAPI DllMain(HMODULE hModule, DWORD Call_Reason, LPVOID lpReserved) {
switch (Call_Reason) {
case DLL_PROCESS_ATTACH:
Hook_Det_x64("Kernel32.dll", "TerminateProcess", MessageBoxAX);
}
return 1;
}
INJECTOR
// Injector.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <windows.h>
#include <tlhelp32.h>
#include <shlwapi.h>
#include <conio.h>
#include <stdio.h>
#include <comdef.h>
#define WIN32_LEAN_AND_MEAN
#define CREATE_THREAD_ACCESS (PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ)
BOOL Inject(DWORD pID, const char * DLL_NAME);
DWORD GetTargetThreadIDFromProcName(const char * ProcName);
int main(int argc, char * argv[])
{
//############### CHANGE HERE ONLY ###################
char *Target_Process = "victim.exe"; //###
//#######################################################
char *buf;
DWORD pID = GetTargetThreadIDFromProcName(Target_Process);
buf = "DllRedirectAPI.dll";
if (!Inject(pID, buf))
{
printf("DLL Not Loaded!");
}
else{
printf("DLL is Injected in torget Process");
}
_getch();
return 0;
}
BOOL Inject(DWORD pID, const char * DLL_NAME)
{
HANDLE Proc;
char buf[50] = { 0 };
LPVOID RemoteString, LoadLibAddy;
if (!pID)
return false;
Proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pID);
if (!Proc)
{
sprintf_s(buf, "OpenProcess() failed: %d", GetLastError());
printf(buf);
return false;
}
LoadLibAddy = (LPVOID)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "LoadLibraryA");
RemoteString = (LPVOID)VirtualAllocEx(Proc, NULL, strlen(DLL_NAME), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
WriteProcessMemory(Proc, (LPVOID)RemoteString, DLL_NAME, strlen(DLL_NAME), NULL);
CreateRemoteThread(Proc, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibAddy, (LPVOID)RemoteString, NULL, NULL);
CloseHandle(Proc);
return true;
}
DWORD GetTargetThreadIDFromProcName(const char * ProcName)
{
PROCESSENTRY32 pe;
HANDLE thSnapShot;
BOOL retval, ProcFound = false;
thSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (thSnapShot == INVALID_HANDLE_VALUE)
{
printf("Error: Unable create toolhelp snapshot!");
return false;
}
pe.dwSize = sizeof(PROCESSENTRY32);
retval = Process32First(thSnapShot, &pe);
while (retval)
{
if (_bstr_t(pe.szExeFile) == _bstr_t(ProcName))
{
return pe.th32ProcessID;
}
retval = Process32Next(thSnapShot, &pe);
}
return 0;
}
Can someone help me, telling me where I'm making a mistake?
My system is Windows 7 Ultimate 64 Bits.
Thanks in advance.
(Wanted to write a comment, but it got quite long...)
As #AndrewMedico says in the comment: You need to hook the TerminateProcess of the Task Manager process to prevent the Task Manager from terminating anything.
I suggest you the following approach:
Try a simple DLL injection
a/ Make a DLL which prints some text in its DllMain, e.g. printf("I am here\n"); fflush(stdout);
b/ Try to inject it into some other command line process using the process hacker's Miscellaneous>Inject DLL...
c/ Verify your DLL was executed inside the target process by checking it's standard output
Try a simple API hook:
a/ Make a command line application which waits for a key and then terminates itself using some variant of TerminateProcess(GetCurrentProcess(), 1);. Add code to print some text after the TerminateProcess call.
b/ Run this application to verify the text after calling the TerminateProcess is not printed.
c/ Hook the TerminateProcess before waiting for the key using, e.g. mhook. Print some text in the replacement function and then return. Do not call the original TerminateProcess here.
d/ Run this application to verify the text inside the hook is printed and the text after the TerminateProcess call is printed as well (i.e. verify the process termination was suppressed).
Combine the results of previous steps to reach your goal:
a/ Put the hooking code from from step 2 into the DLL from step 1
b/ Inject it into the application from step 2b (i.e. the one without the hook) while it is waiting for the key and verify the text after TerminateProcess is printed.
c/ Enjoy (or debug/blame me)
Good luck!
EDIT>
OK, here is my view of what we have here:
Code in the question:
(Is an application very similar to what I suggest in "2b")
Hooks the TerminateProcess and shows a message box instead.
Should display a message box when executed
(Looks like it is a 32-bit only version)
YouTube video
Shows an application "Terminate process.exe" which terminates process given by name
After the "Injector.exe" is executed the application ceases to terminate the process and displays a message box instead (IMHO the "Injector.exe" injects a "DllFile.dll" into the running "Terminate process.exe")
Source code for the injector in the YouTube comments
This code injects DLL "C:\DllRedirectAPI.dll" into the first process with name "victim.exe" it finds
(It does not inject into "Terminate process.exe", it does not use "DllFile.dll")
Source code for the DLL in the YouTube comments
This code hooks function MessageBoxA that it shows a different message box instead. It is worth noting that the hook code itself calls the original MessageBoxA and takes the approach that it reverts the modification it did during the hooking, calls the original function and then re-applies the hook.
(It does not hook 'TerminateProcess' at all)
(Looks like it is a 32-bit only version)
64-bit version excerpts
Destructive hook of MessageBoxA (i.e. does not backup the original code)
The hook uses MessageBoxExA (which is intact) to display a different message box instead (i.e. it does not use the overwritten MessageBoxA)
(It does not hook 'TerminateProcess' at all)
(It is a 64-bit version)
Disclaimer: I am not that proficient with the topic to be 100% sure, feel free to correct/clarify me.
For the actual hooking I personally recommend to use the mhook library, which worked for me. It's documentation is worth reading as well.
See e.g. this for some alternatives (I have not tried any of them)...
EDIT>
This one works for me on Win XP inside VirtualBox:
#include <windows.h>
#include <stdio.h>
#include <mhook.h>
static BOOL WINAPI
(*_TerminateProcess)(
_In_ HANDLE hProcess,
_In_ UINT uExitCode
) = NULL;
BOOL WINAPI
TerminateProcessImpl(
_In_ HANDLE hProcess,
_In_ UINT uExitCode) {
printf("\nBlocked\n"); fflush(stdout);
return 0;
}
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD Reason, LPVOID Reserved) {
if(Reason==DLL_PROCESS_ATTACH) {
printf("\nDLL attached!\n"); fflush(stdout);
HMODULE h = LoadLibrary("Kernel32");
if(h!=NULL) {
printf("\nGot Kernel32!\n"); fflush(stdout);
_TerminateProcess=(void*)GetProcAddress(h,"TerminateProcess");
if(_TerminateProcess!=NULL) {
printf("\nAbout to hook...\n"); fflush(stdout);
if(Mhook_SetHook((void*)&_TerminateProcess, &TerminateProcessImpl)) {
printf("\nHooked OK!\n"); fflush(stdout);
} else {
printf("\nHook failed!\n"); fflush(stdout);
}
}
}
}
return TRUE;
}

Injected DLL and calling a function using CreateRemoteThread causes "has stopped working", what happens?

I`m trying to inject a DLL in a process and call a exported function in my DLL.
The DLL is injected alright with that code:
HANDLE Proc;
char buf[50] = { 0 };
LPVOID RemoteString, LoadLibAddy;
if (!pID)
return false;
Proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pID);
if (!Proc)
{
sprintf_s(buf, "OpenProcess() failed: %d", GetLastError());
printf(buf);
return false;
}
LoadLibAddy = (LPVOID)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryA");
// Allocate space in the process for our DLL
RemoteString = (LPVOID)VirtualAllocEx(Proc, NULL, strlen(DLL_NAME), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
// Write the string name of our DLL in the memory allocated
WriteProcessMemory(Proc, (LPVOID)RemoteString, DLL_NAME, strlen(DLL_NAME), NULL);
// Load our DLL
HANDLE hThread = CreateRemoteThread(Proc, NULL, 0, (LPTHREAD_START_ROUTINE)LoadLibAddy, (LPVOID)RemoteString, NULL, NULL);
The module of my DLL is created OK, like you see in that image of Process Hacker (BootstrapDLL.exe):
My exported functions is ok too, like you see in the list of functions exported on Process Hacker (ImplantDotNetAssembly):
The problems, I think, happens on the offset calculation to get the address of the "ImplantDotNetAssembly", because everything above is alright and when I do the calculation I get the address of the "ImplantDotNetAssembly", but when I call CreateRemoteThread again to call it, the window "Has stopped working..." of the windows is showed and the process stoped. What`s happening?
Here is the code of the calculation of the offset:
DWORD_PTR hBootstrap = GetRemoteModuleHandle(ProcId, L"BootstrapDLL.exe");
DWORD_PTR offset = GetFunctionOffset(L"C:\\Users\\Acaz\\Documents\\Visual Studio 2013\\Projects\\Contoso\\Debug\\BootstrapDLL.exe", "ImplantDotNetAssembly");
DWORD_PTR fnImplant = hBootstrap + offset;
HANDLE hThread2 = CreateRemoteThread(Proc, NULL, 0, (LPTHREAD_START_ROUTINE)fnImplant, NULL, 0, NULL);
Here are the functions GetRemoteModuleHandle and GetFunctionOffset:
DWORD_PTR GetFunctionOffset(const wstring& library, const char* functionName)
{
// load library into this process
HMODULE hLoaded = LoadLibrary(library.c_str());
// get address of function to invoke
void* lpInject = GetProcAddress(hLoaded, functionName);
// compute the distance between the base address and the function to invoke
DWORD_PTR offset = (DWORD_PTR)lpInject - (DWORD_PTR)hLoaded;
// unload library from this process
FreeLibrary(hLoaded);
// return the offset to the function
return offset;
}
DWORD_PTR GetRemoteModuleHandle(const int processId, const wchar_t* moduleName)
{
MODULEENTRY32 me32;
HANDLE hSnapshot = INVALID_HANDLE_VALUE;
// get snapshot of all modules in the remote process
me32.dwSize = sizeof(MODULEENTRY32);
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, processId);
// can we start looking?
if (!Module32First(hSnapshot, &me32))
{
CloseHandle(hSnapshot);
return 0;
}
// enumerate all modules till we find the one we are looking for or until every one of them is checked
while (wcscmp(me32.szModule, moduleName) != 0 && Module32Next(hSnapshot, &me32));
// close the handle
CloseHandle(hSnapshot);
// check if module handle was found and return it
if (wcscmp(me32.szModule, moduleName) == 0)
return (DWORD_PTR)me32.modBaseAddr;
return 0;
}
If someone know what is happening, I'll be very grateful!
I cant`t even debug the "has stopped work.." error. When I clik in the DEBUG button on the window, the error throw again and everything stop.
Thank you.
NEVER inject managed assemblies. If for some reason you must inject code into another process, use native code with either NO C library or a STATIC C library.

Duplicate Windows Handle of a local process

Use Case
I have a 64 bit server process which through IPC (COM+ RPC) gains access to the PID of a 32 bit Client Process. The Server Process Creates a new Window with a parent Window Handler. I need to display the New Window inside the Client's Window instead of a standalone popup on top of the Desktop Window.
Process Adopted
In order to Display the New Window on the parent Window, I first tried to
Get the Handle to the Top Window
Duplicate the Window Handle using DuplicateHandle
Create the new Window with the new Duplicate Window Handle
Code
In Order to Duplicate the Window Handle I adopted the following Code. Note this is not the actual code, but for brevity changed the non relevant parts. Also Note, the SetPriviledge Function was adopted from Enabling and Disabling Privileges in C++
bool Duplicate(HWND hWnd)
{
HANDLE pToken = NULL;
HANDLE hProcess = NULL;
HANDLE hDuplicateHandle = NULL;
DWORD pid = 0;
bool bReturn = true;
GetWindowThreadProcessId(hWnd, &pid);
if(!(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid)))
{
std::cout<<"Cannot Open Process:"<<GetLastError()<<std::endl;
bReturn = false;
}
if(bReturn && !OpenProcessToken(
hProcess,
TOKEN_ALL_ACCESS,
&pToken ))
{
std::cout<<"Cannot Open Token:"<<GetLastError()<<std::endl;
bReturn = false;
}
//The SetPriviledge function was adopted from
//http://msdn.microsoft.com/en-us/library/windows/desktop/aa446619(v=vs.85).aspx
if (bReturn && !SetPrivilege(
pToken,
SE_DEBUG_NAME,
true ))
{
std::cout<<"Error Setting Priveledge:error"<<GetLastError()<<std::endl;
bReturn = false;
}
if(bReturn && !DuplicateHandle(
hProcess,
hWnd,
GetCurrentProcess(),
&hDuplicateHandle,
NULL,
NULL,
DUPLICATE_SAME_ACCESS))
{
std::cout<<"Error Duplicating Handle: "<<GetLastError()<<std::endl;
std::cout<<"Source Handle is "<<hWnd<<" And the Duplicate Handle is "<<hDuplicateHandle<<std::endl;
bReturn = false;
}
if (hProcess)
{
CloseHandle(hProcess);
}
return bReturn;
}
O/P From the Above Code
Error Duplicating Handle: 6
Source Handle is 00150C1C And the Duplicate Handle is 00000000
Press any key to continue . . .
i.e. The Code fails with Error Code 6: ERROR_INVALID_HANDLE
Goal
To Make the above code work so that I can Duplicate a Remote Windows handle of a Local Process. Alternatively, determine if the above is the correct process.

Get path of current module after using RemoteThread

I need to get the current path of the module where my code executed (dll). I've made a dll injection from .NET into a native process and used RemoteThread.
I have tried getcwd, GetCurrentDirectory, GetModuleHandle.
Also tried this solution. But it doesn't work either. I get an empty string with the length of MAX_PATH.
https://stackoverflow.com/questions/6719140/get-path-of-current-module-after-using-remotethread/6719210#6719210
I already opened a thread but I can not login to my email to get the id.
Sorry but anyway thanks for your answer. I will rate this time!
C# Injection
public static IntPtr InjectLibrary(
Process targetProcess,
string libraryPath)
{
var libaryPathBytes = Encoding.GetBytes();
var hProc = NativeMethods.OpenProcess()
var hMemory = NativeMethods.VirtualAllocEx()
NativeMethods.WriteProcessMemory()
var hLoadLib = NativeMethods.GetProcAddress()
var hThread = NativeMethods.CreateRemoteThread()
return hThread;
}
Native Library
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
DWORD threadId;
CreateThread( NULL, 0, Bootstrap, NULL, 0, &threadId);
break;
}
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
DWORD WINAPI Bootstrap(LPVOID arg) {
DWORD currentProcessID = GetCurrentProcessId();
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, currentProcessID);
MODULEENTRY32 entry;
Module32First(snapshot, &entry);
MessageBox(NULL, entry.szLibPath, L"", MB_OK);//entry.szLibPath is empty string with the length if MAX_PATH like □□□□□□□□□□□□□□□□□□□□□□□....
HMODULE module = entry.hModule;
wchar_t currentPath[MAX_PATH];
GetModuleFileName(module, currentPath, MAX_PATH);
MessageBox(NULL, currentPath, L"", MB_OK);//currentPath isempty string with the length if MAX_PATH like □□□□□□□□□□□□□□□□□□□□□□□....
//all other options give me the same string or the executable path
return 0;
}
There's a "hidden" tool helper library mentionned by Raymond Chen that gets around several quirks in the Win32 APi. It seems you can use that to fetch the handle to the first module associated to a process (presumably the original executable). You can use that handle to get the path to the executable.
Looks something like:
// Get a listing of modules loaded in the process.
DWORD process = ...;
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, process);
// Get the handle to the first module loaded by that process.
MODULEENTRY32 entry;
Module32First(snapshot, &entry);
HANDLE module = entry.hModule;
// Get the path to the executable/DLL file containing the module.
GetModuleFileName(module, ...);
Edit: I've tried a complete example. You get an empty string using GetModuleFileName() because the module handle was not loaded using the LoadLibrary() function call.
However, it seems the MODULEENTRY32 structure already provides the full path to the module in its szExePath member. The following example works for me:
#include <Windows.h>
#include <TlHelp32.h>
#include <iostream>
int main ( int, char ** )
{
// Substitute `process` with appropriate process ID.
const ::DWORD process = ::GetCurrentProcessId();
const ::HANDLE snapshot =
::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, process);
if ( snapshot == INVALID_HANDLE_VALUE ) {
std::cerr << "Couldn't get snapshot!" << std::endl;
return (EXIT_FAILURE);
}
// Get 1st module info.
::MODULEENTRY32W module;
::ZeroMemory(&module, sizeof(module));
module.dwSize = sizeof(module);
const ::BOOL result = Module32FirstW(snapshot, &module);
if ( result == FALSE )
{
// Handle errors.
const ::DWORD error = ::GetLastError();
std::cerr
<< "Couldn't get 1st module (" << error << ")."
<< std::endl;
return (EXIT_FAILURE);
}
std::wcout
<< module.szExePath << std::endl;
// Cleanup.
::CloseHandle(snapshot);
return (EXIT_SUCCESS);
}