C++ Check if specific process is running - c++

I have a C++ DLL that i am writing that needs to check if a particular process is running.
the dll will be launched application will be running in:
c:\Directory\application.exe
there is a subdirectory within that that has another executable in it:
c:\Directory\SubDirectory\application2.exe
What the DLL needs to do when it runs if check that application2.exe is running, most importantly that it is running within that folder -- there will be multiple copies running, so we need to ensure that the correct one is running.
I have the following code that is working well at detecting that the application2.exe is running, but it does not take the file path into consideration:
HANDLE pss = CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);
PROCESSENTRY32 pe = { 0 };
pe.dwSize = sizeof(pe);
if (Process32First(pss, &pe))
{
do
{
if(wcscmp(pe.szExeFile, L"application2.exe") == 0)
{
CloseHandle(pss);
return (1);
}
}
while(Process32Next(pss, &pe));
}
CloseHandle(pss);
How can I check that the path of the process matches the path of the application which called the DLL?

Use WMI for this.
From the command line you can do:
wmic process where "executablepath = 'c:\path\to\executable.exe'" get ProcessId
You can use the WMI apis from C++ to do something similar.
http://www.codeproject.com/Articles/10539/Making-WMI-Queries-In-C

I have been given a solution that works for this, in case anyone else searching here it is:
HANDLE ProcessSnap;
PROCESSENTRY32 Pe32;
unsigned int LoopCounter = 0;
Pe32.dwSize = sizeof(PROCESSENTRY32);
ProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
Process32First(ProcessSnap, &Pe32);
wchar_t TermPath[MAX_PATH];
GetModuleFileName(NULL, TermPath, MAX_PATH);
wstring WTermPath(TermPath);
int index = WTermPath.find(L"\\application.exe");
wstring Path = WTermPath.substr(0, (index));
Path = Path + L"\\SubDirectory\\Application2.exe";
do
{
HANDLE Process;
wchar_t FilePath[MAX_PATH];
Process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, 0, Pe32.th32ProcessID);
if (Process)
{
GetModuleFileNameEx(Process, 0, FilePath, MAX_PATH);
wstring WFilePath(FilePath);
if(WFilePath == Path)
{
CloseHandle(ProcessSnap);
return (1);
}
CloseHandle(Process);
}
LoopCounter++;
} while (Process32Next(ProcessSnap, &Pe32));
CloseHandle(ProcessSnap);

Related

C++ | Windows - Is there a way to find out which process has ownership of the locked file?

What I want to know is it possible to try an open a file (and when it fails because it's opened with another process with sharing off) to figure out which process is using said file?
The reason I am wanting to know this information is because I am making a little application that will "fix" malicious files.
For example, some malicious/adware etc set the file security descriptor so the user can't delete the file, etc. My application just resets the security descriptor allowing the user to regain control.
I have also seen a file open up its child process with for example (CreateFile) and have Shared Mode turned off so the file can't be touched, then the application would execute the childprocess from memory.
Yes, you can in general just use the openfiles command, after having enabled collection of this information via, it appears, openfiles /local on.
In Windows NT up to and including (it seems) Windows XP there was a similar Resource Kit command named oh, short for open handles.
An alternative to both is to use SysInternal's Process Explorer.
Note: In some cases openfiles will fail to list some handle. This happens for me when Windows refuses to unmount an USB disk, claiming that some process is using a file on that disk. No such process ever shows up.
I have developed a function to locate such process, kill it and delete the locked file.
bool ForceDeleteFile(LPWSTR FileName);
Here is the full source code:
bool KillFileProcess(LPWSTR FileName)
{
HANDLE hProcessSnap;
HANDLE hProcess;
PROCESSENTRY32 pe32;
DWORD dwPriorityClass;
bool result = false;
// Take a snapshot of all processes in the system.
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnap == INVALID_HANDLE_VALUE)
{
//printError(TEXT("CreateToolhelp32Snapshot (of processes)"));
return(FALSE);
}
// Set the size of the structure before using it.
pe32.dwSize = sizeof(PROCESSENTRY32);
// Retrieve information about the first process,
// and exit if unsuccessful
if (!Process32First(hProcessSnap, &pe32))
{
//printError(TEXT("Process32First")); // show cause of failure
CloseHandle(hProcessSnap); // clean the snapshot object
return(FALSE);
}
// Now walk the snapshot of processes, and
// display information about each process in turn
do
{
// Retrieve the priority class.
dwPriorityClass = 0;
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID);
if (hProcess == NULL)
{
//printError(TEXT("OpenProcess"));
}
else
{
dwPriorityClass = GetPriorityClass(hProcess);
if (!dwPriorityClass)
{
//printError(TEXT("GetPriorityClass"));
}
CloseHandle(hProcess);
if (HANDLE hProcess = ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pe32.th32ProcessID))
{
WCHAR filename[MAX_PATH] = {};
if (GetModuleFileNameEx(hProcess, NULL, filename, MAX_PATH))
{
if (_wcsicmp((const wchar_t *)FileName, (const wchar_t *)filename) == NULL)
{
if (TerminateProcess(pe32.th32ProcessID, 0))
{
_tprintf(L"Found: Process full killed\nKILLED!\n");
result = true;
}
else
{
_tprintf(L"Found: Process full \nFailed to terminate\n");
DoRun(((CString)L"taskkill /F /IM " + (CString)pe32.szExeFile).GetBuffer());
result = false;
}
}
}
else
{
// handle error
}
CloseHandle(hProcess);
}
}
} while (Process32Next(hProcessSnap, &pe32));
CloseHandle(hProcessSnap);
return(result);
}
bool ForceDeleteFile(LPWSTR FileName)
{
bool result = DeleteFile(FileName);
if (!result)
{
_tprintf(L"Can't delete file. using DeleteFile(). Trying to locate process and kill it\n");
result = KillFileProcess(FileName);
if (!result)
_tprintf(L"Couldn't find the process\n");
else
{
Sleep(1000);
result = DeleteFile(FileName);
if (result)
_tprintf(L"DeleteFile success");
else
_tprintf(L"DeleteFile ============== failed ===============");
}
}
return result;
}
BOOL TerminateProcess(DWORD dwProcessId, UINT uExitCode)
{
DWORD dwDesiredAccess = PROCESS_TERMINATE;
BOOL bInheritHandle = FALSE;
HANDLE hProcess = OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId);
if (hProcess == NULL)
return FALSE;
BOOL result = TerminateProcess(hProcess, uExitCode);
CloseHandle(hProcess);
return result;
}

TerminateProcess not suceeding on Windows 10

Our C++ app launches a separate .exe ( which may start its own sub-processes) using CreateProcess as below.
BOOL started = ::CreateProcess(NULL, // application
p, // parameters
NULL, // process security
NULL, // thread security
TRUE, // inherit handles flag
0, // flags
NULL, // inherit environment
dirLP, // inherit directory
&startup, // STARTUPINFO
&procinfo); // PROCESS_INFORMATIO
In case we need cancel the "job" we use CreateToolhelp32Snapshot to iterate through the process list to find any child processes of the one we launched.
static BOOL TerminateProcessTree (HANDLE parentProcess,UINT exitCode)
{
BOOL result=TRUE;
HANDLE hProcessSnap = NULL;
PROCESSENTRY32 pe32 = {0};
// Take a snapshot of all processes in the system.
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnap == INVALID_HANDLE_VALUE)
return (FALSE);
pe32.dwSize = sizeof(PROCESSENTRY32);
// Walk the snapshot of the processes
DWORD parentID=GetProcessId(parentProcess);
if(parentID==0){
PrintLastError("GetProcessId");
return FALSE;
}
if (Process32First(hProcessSnap, &pe32)) {
do{
if(pe32.th32ParentProcessID==parentID){
HANDLE hProcess = OpenProcess (PROCESS_TERMINATE | PROCESS_QUERY_INFORMATION, FALSE, pe32.th32ProcessID);
if(hProcess!=NULL){
BOOL terminateChildren=TerminateProcessTree(hProcess,exitCode);
BOOL terminatedChild = TerminateProcess(hProcess, exitCode);
if (!terminatedChild){
PrintLastError("TerminateProcess");
}
CloseHandle(hProcess);
if(!terminatedChild || !terminateChildren){
result=FALSE;
break;
}
} else{
PrintLastError("OpenProcess");
}
}
}while (Process32Next(hProcessSnap, &pe32));
}
CloseHandle (hProcessSnap);
DWORD checkCode=0;
BOOL terminated;
if(GetExitCodeProcess(parentProcess,&checkCode) && checkCode==STILL_ACTIVE){
terminated=TerminateProcess(parentProcess,exitCode);
if (!terminated){
PrintLastError("TerminateProcess");
result= FALSE;
}
}
return result;
}
As noted, this works fine on Windows 7. Windows 10 fails with "Access Denied" on the first call "TerminateProcess". Clearly something has changed in the Windows security model when it comes to processes.
The robust way to deal with controlling a process tree of objects is to use Job objects as noted in the comment threads.
The one thing to keep in mind is that a process can only belong to a single job, and by default any EXE that the OS determines needs appcompat help is put into a job object automatically managed by the "Program Compatibility Assistant". This makes using a Job object to manage arbitrary 3rd party EXEs a little bit more complicated (i.e. AssignProcessToJobObject fails for these processes).
If you are using CreateProcess you can make use of the flag CREATE_BREAKAWAY_FROM_JOB. See this blog post. This works fine as long as the target EXE has the same rights as the calling object.
For a Standard User EXE to run an EXE that might need Administrator rights (i.e. they contain a manifest which marks it as requireAdministrator), you have to use ShellExecute or ShellExecuteEx as calling CreateProcess in this case will fail. If your target EXEs are all using the proper manifest elements then it won't be put into a PCA Job object.. You can use the trick of passing SEE_MASK_FLAG_NO_UI which will have the side-effect of avoiding the PCA job behavior. If you are launching arbitrary 3rd party EXEs, you should use ShellExecuteEx and not CreateProcess.
bool SpawnProcess( const WCHAR* szExePath, const WCHAR* szExeArgs )
{
if( !szExePath )
return false;
// NOTE: szExeArgs can be nullptr.
// Get working directory from executable path.
WCHAR szDirectory[MAX_PATH] = {0};
wcscpy_s( szDirectory, szExePath );
PathRemoveFileSpec( szDirectory );
// ShellExecute or ShellExecuteEx must be used instead of CreateProcess
// to permit the shell to display a UAC prompt asking for consent to
// elevate when the target executable's manifest specifies a run level
// of "requireAdministrator".
//
// You can only use CreateProcess if you know that the application you
// are spawning will be at the same run level as the current process.
// Otherwise, you will receive ERROR_ACCESS_DENIED if the elevation
// consent could not be obtained.
SHELLEXECUTEINFO info = {};
info.cbSize = sizeof( info );
info.lpVerb = L"open";
info.fMask = SEE_MASK_FLAG_NO_UI;
info.lpFile = szExePath;
info.lpParameters = szExeArgs;
info.lpDirectory = szDirectory;
info.nShow = SW_SHOW;
if( !ShellExecuteEx( &info ) )
return false;
return true;
}
Note that if you want to wait until this process exits, you can use:
bool SpawnProcessAndWait( const WCHAR *szExePath, const WCHAR *szExeArgs, DWORD *pdwExitCode )
{
if( !szExePath )
return false;
// NOTE: szExeArgs and pExitCode can be nullptr.
// Get working directory from executable path.
WCHAR szDirectory[MAX_PATH] = {0};
wcscpy_s( szDirectory, szExePath );
PathRemoveFileSpec( szDirectory );
// See SpawnProcess for information why ShellExecute or ShellExecuteEx
// must be used instead of CreateProcess.
SHELLEXECUTEINFO info = {};
info.cbSize = sizeof( info );
info.lpVerb = L"open";
info.fMask = SEE_MASK_FLAG_NO_UI | SEE_MASK_NOASYNC | SEE_MASK_NOCLOSEPROCESS;
info.lpFile = szExePath;
info.lpParameters = szExeArgs;
info.lpDirectory = szDirectory;
info.nShow = SW_SHOW;
if( !ShellExecuteEx( &info ) )
return false;
// Wait for process to finish.
WaitForSingleObject( info.hProcess, INFINITE );
// Return exit code from process, if requested by caller.
if( pdwExitCode )
GetExitCodeProcess( info.hProcess, pdwExitCode );
CloseHandle( info.hProcess );
return true;
}
You haven't noted if your "master" application here is using administrator or Standard User rights. Ideally it is using Standard User rights per the User Account Control guidelines dating back to Windows Vista. If your app is running as Standard User, then it's likely that your code no longer works due to security improvements to keep non-Administrator malware from doing this kind of thing to other processes.
For general appcompat questions about Windows 10, be sure to read the Windows and Windows Server compatibility cookbook and look back at the Windows 8.0 and Windows 8.1 material if you are jumping directly from Windows 7 to Windows 10.

OpenProcess Failure (SeDebugPrivilege?)

I'm trying to use OpenProcess, for some reason it keeps failing.
HANDLE GetProcessPid()
{
DWORD pid = 0;
wchar_t ProcessName[] = L"notepad.exe";
// Create toolhelp snapshot.
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 process;
ZeroMemory(&process, sizeof(process));
process.dwSize = sizeof(process);
// Walkthrough all processes.
if (Process32First(snapshot, &process))
{
do
{
if (wcscmp(process.szExeFile, ProcessName) == 0)
{
pid = process.th32ProcessID;
break;
}
} while (Process32Next(snapshot, &process));
}
CloseHandle(snapshot);
if (pid != 0)
{
return OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
}
return NULL;
}
This always returns 0xcccccccccccccccc or 0x0000000000000020 even when I've set the pid manually when calling OpenProcess.
I've tried running as admin outside of debugging inside visual studio and get the same results, after searching, I think I need to enable debug priviledges (SeDebugPrivilege), how do I do this in visual studio 2013?
Your code is fine, you just need to run your executable as administrator and it works, I just tested it.

C++ How to Check if an Outlook Process is already running

I am new to C++ programming but I would like to know if there is an easy way to check if an Outlook Process is already running, or in other words check if Outlook is already open.
Can anyone show me, please?
Thanks
You can check the running instance of the outlook OLE:
static const bool isOutlookRunning()
{
CLSID clsid;
HRESULT hr = CLSIDFromProgID( _T("Outlook.Application"), &clsid );
if( hr != S_OK ) return false;
IUnknown *pUnknown = NULL;
hr = GetActiveObject( clsid, 0, &pUnknown );
return ( hr == S_OK );
}
This code will not work if the app from you invoke it is running in different user security context than Outlook.
Its better to check for the process name.
//////////////////////////////////////////////////////////////////////
// IsProcessRunning
//////////////////////////////////////////////////////////////////////
bool IsProcessRunning(string &strProcessFullPathName)
{
// Get the list of process identifiers.
DWORD dwProcesses[2048];
DWORD dwSizeNeeded = 0;
DWORD dwProcessesCount = 0;
if ( !EnumProcesses( dwProcesses, sizeof(dwProcesses), &dwSizeNeeded ) )
{
_dwLastErrorCode = GetLastError();
_strLastError = "EnumProcesses";
return false;
}
dwProcessesCount = dwSizeNeeded / sizeof(DWORD);
string strToCheck = strProcessFullPathName;
transform(strToCheck.begin(), strToCheck.end(), strToCheck.begin(), tolower);
for(int i=0; i<(int)dwProcessesCount; i++ )
{
if( dwProcesses[i] != 0 )
{
HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwProcesses[i]);
if(hProcess)
{
HMODULE hModule = NULL;
dwSizeNeeded = 0;
char cName[MAX_PATH];
if(EnumProcessModules(hProcess, &hModule, sizeof(DWORD), &dwSizeNeeded) )
{
if(GetModuleFileNameEx(hProcess, hModule, cName, MAX_PATH ) != 0)
{
string strName(cName);
// Convert to LowerCase
transform(strName.begin(), strName.end(), strName.begin(), tolower);
if(strName == strToCheck)
{
CloseHandle(hProcess);
return true;
}
}
}
CloseHandle(hProcess);
}
}
}
return false;
}
I assume that you are using Windows as platform, since Outlook normally runs under a Windows OS.
For a simple check you can use the Windows API functions EnumProcesses() and GetModuleBaseName() to determine the executable filename of the running processes and check if the executable name is "outlook.exe". A reference for the functions can be found in the MSDN.
Be aware that the this check may fail if the user runs another program that is using the same executable filename as Outlook. Another trap with the provided solution might be the access rights a user needs for the specified API calls.
Improvements might be to check the version information in the executable file too by using GetFileVersionInfo().
You can use CreateToolhelp32Snapshot and iterate through the running processes. If you need to heck for Outlook again (say you need to poll for the process), then save the process ID and use OpenProcess (many times faster). More details are given in the answer to this question:
Check whether one specific process is running on windows with C++

How to get the process name in C++

How do I get the process name from a PID using C++ in Windows?
I guess the OpenProcess function should help, given that your process possesses the necessary rights. Once you obtain a handle to the process, you can use the GetModuleFileNameEx function to obtain full path (path to the .exe file) of the process.
#include "stdafx.h"
#include "windows.h"
#include "tchar.h"
#include "stdio.h"
#include "psapi.h"
// Important: Must include psapi.lib in additional dependencies section
// In VS2005... Project > Project Properties > Configuration Properties > Linker > Input > Additional Dependencies
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE Handle = OpenProcess(
PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
FALSE,
8036 /* This is the PID, you can find one from windows task manager */
);
if (Handle)
{
TCHAR Buffer[MAX_PATH];
if (GetModuleFileNameEx(Handle, 0, Buffer, MAX_PATH))
{
// At this point, buffer contains the full path to the executable
}
else
{
// You better call GetLastError() here
}
CloseHandle(Handle);
}
return 0;
}
You can obtain the process name by using the WIN32 API GetModuleBaseName after having the process handle. You can get the process handle by using OpenProcess.
To get the executable name you can also use GetProcessImageFileName.
All the above methods require psapi.dll to be loaded (Read the remarks section) and iterating through process snapshot is an option one should not even consider for getting a name of the executable file from an efficiency standpoint.
The best approach, even according to MSDN recommendation, is to use QueryFullProcessImageName.
std::string ProcessIdToName(DWORD processId)
{
std::string ret;
HANDLE handle = OpenProcess(
PROCESS_QUERY_LIMITED_INFORMATION,
FALSE,
processId /* This is the PID, you can find one from windows task manager */
);
if (handle)
{
DWORD buffSize = 1024;
CHAR buffer[1024];
if (QueryFullProcessImageNameA(handle, 0, buffer, &buffSize))
{
ret = buffer;
}
else
{
printf("Error GetModuleBaseNameA : %lu", GetLastError());
}
CloseHandle(handle);
}
else
{
printf("Error OpenProcess : %lu", GetLastError());
}
return ret;
}
If you are trying to get the executable image name of a given process, take a look at GetModuleFileName.
Check out the enumprocess functions in the tool help library:
http://msdn.microsoft.com/en-us/library/ms682629(v=vs.85).aspx
Good example # http://msdn.microsoft.com/en-us/library/ms682623(v=vs.85).aspx
Try this function :
std::wstring GetProcName(DWORD aPid)
{
PROCESSENTRY32 processInfo;
processInfo.dwSize = sizeof(processInfo);
HANDLE processesSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
if (processesSnapshot == INVALID_HANDLE_VALUE)
{
std::wcout << "can't get a process snapshot ";
return 0;
}
for(BOOL bok =Process32First(processesSnapshot, &processInfo);bok; bok = Process32Next(processesSnapshot, &processInfo))
{
if( aPid == processInfo.th32ProcessID)
{
std::wcout << "found running process: " << processInfo.szExeFile;
CloseHandle(processesSnapshot);
return processInfo.szExeFile;
}
}
std::wcout << "no process with given pid" << aPid;
CloseHandle(processesSnapshot);
return std::wstring();
}