reactos/base/applications/utilman/process.c
Bișoc George dfe5e810cc
[UTILMAN] Small refactor on process management code (#2375)
Implement a small helper, GetProcessID(), that will be used to return the process ID which we are interested in. This largely removes some duplicated code. The following patch addresses the Jansen's comment on #1608 PR.
2020-02-28 02:45:21 +09:00

223 lines
5.8 KiB
C

/*
* PROJECT: ReactOS Utility Manager (Accessibility)
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: Process handling functions
* COPYRIGHT: Copyright 2019 Bișoc George (fraizeraust99 at gmail dot com)
*/
/* INCLUDES *******************************************************************/
#include "precomp.h"
/* FUNCTIONS ******************************************************************/
/**
* @GetProcessID
*
* Returns the process executable ID based on the given executable name.
*
* @param[in] lpProcessName
* The name of the executable process.
*
* @return
* Returns the ID number of the process, otherwise 0.
*
*/
DWORD GetProcessID(IN LPCWSTR lpProcessName)
{
PROCESSENTRY32W Process;
/* Create a snapshot and check if the given process name matches with the one from the process entry structure */
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnapshot == INVALID_HANDLE_VALUE)
return 0;
/* Get the whole size of the structure */
Process.dwSize = sizeof(Process);
/* Enumerate the processes */
if (Process32FirstW(hSnapshot, &Process))
{
do
{
if (_wcsicmp(Process.szExeFile, lpProcessName) == 0)
{
/* The names match, return the process ID we're interested */
CloseHandle(hSnapshot);
return Process.th32ProcessID;
}
}
while (Process32NextW(hSnapshot, &Process));
}
CloseHandle(hSnapshot);
return 0;
}
/**
* @IsProcessRunning
*
* Checks if a process is running.
*
* @param[in] lpProcessName
* The name of the executable process.
*
* @return
* Returns TRUE if the given process' name is running,
* FALSE otherwise.
*
*/
BOOL IsProcessRunning(IN LPCWSTR lpProcessName)
{
DWORD dwReturn, dwProcessID;
HANDLE hProcess;
/* Get the process ID */
dwProcessID = GetProcessID(lpProcessName);
if (dwProcessID == 0)
{
return FALSE;
}
/* Synchronize the process to get its signaling state */
hProcess = OpenProcess(SYNCHRONIZE, FALSE, dwProcessID);
if (!hProcess)
{
DPRINT("IsProcessRunning(): Failed to open the process! (Error: %lu)", GetLastError());
return FALSE;
}
/* Wait for the process */
dwReturn = WaitForSingleObject(hProcess, 0);
if (dwReturn == WAIT_TIMEOUT)
{
/* The process is still running */
CloseHandle(hProcess);
return TRUE;
}
CloseHandle(hProcess);
return FALSE;
}
/**
* @LaunchProcess
*
* Executes a process.
*
* @param[in] lpProcessName
* The name of the executable process.
*
* @return
* Returns TRUE if the process has been launched successfully,
* FALSE otherwise.
*
*/
BOOL LaunchProcess(LPCWSTR lpProcessName)
{
STARTUPINFOW si;
PROCESS_INFORMATION pi;
HANDLE hUserToken, hProcessToken;
BOOL bSuccess;
WCHAR ExpandedCmdLine[MAX_PATH];
/* Expand the process path string */
ExpandEnvironmentStringsW(lpProcessName, ExpandedCmdLine, ARRAYSIZE(ExpandedCmdLine));
ZeroMemory(&pi, sizeof(pi));
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_SHOWNORMAL;
/* Get the token of the parent (current) process of the application */
bSuccess = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_DUPLICATE, &hUserToken);
if (!bSuccess)
{
DPRINT("OpenProcessToken() failed with error -> %lu\n", GetLastError());
return FALSE;
}
/* Duplicate a new token so that we can use it to create our process */
bSuccess = DuplicateTokenEx(hUserToken, TOKEN_ALL_ACCESS, NULL, SecurityIdentification, TokenPrimary, &hProcessToken);
if (!bSuccess)
{
DPRINT("DuplicateTokenEx() failed with error -> %lu\n", GetLastError());
CloseHandle(hUserToken);
return FALSE;
}
/* Finally create the process */
bSuccess = CreateProcessAsUserW(hProcessToken,
NULL,
ExpandedCmdLine,
NULL,
NULL,
FALSE,
0, // DETACHED_PROCESS, NORMAL_PRIORITY_CLASS
NULL,
NULL,
&si,
&pi);
if (!bSuccess)
{
DPRINT("CreateProcessAsUserW() failed with error -> %lu\n", GetLastError());
CloseHandle(hUserToken);
CloseHandle(hProcessToken);
return FALSE;
}
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
CloseHandle(hUserToken);
CloseHandle(hProcessToken);
return TRUE;
}
/**
* @CloseProcess
*
* Closes a process.
*
* @param[in] lpProcessName
* The name of the executable process.
*
* @return
* Returns TRUE if the process has been terminated successfully,
* FALSE otherwise.
*
*/
BOOL CloseProcess(IN LPCWSTR lpProcessName)
{
HANDLE hProcess;
DWORD dwProcessID;
/* Get the process ID */
dwProcessID = GetProcessID(lpProcessName);
if (dwProcessID == 0)
{
return FALSE;
}
/* Make sure that the given process ID is not ours, the parent process, so that we do not kill ourselves */
if (dwProcessID == GetCurrentProcessId())
{
return FALSE;
}
/* Open the process so that we can terminate it */
hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, dwProcessID);
if (!hProcess)
{
DPRINT("CloseProcess(): Failed to open the process for termination! (Error: %lu)", GetLastError());
return FALSE;
}
/* Terminate it */
TerminateProcess(hProcess, 0);
CloseHandle(hProcess);
return TRUE;
}