/* * PROJECT: ReactOS Utility Manager Resources DLL (UManDlg.dll) * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) * PURPOSE: Process handling functions * COPYRIGHT: Copyright 2019-2020 George Bișoc (george.bisoc@reactos.org) */ /* INCLUDES *******************************************************************/ #include "umandlg.h" /* FUNCTIONS ******************************************************************/ /** * @GetProcessID * * Returns the process executable ID based on the given executable name. * * @param[in] lpszProcessName * The name of the executable process. * * @return * Returns the ID number of the process, otherwise 0. * */ DWORD GetProcessID(IN LPCWSTR lpszProcessName) { 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, lpszProcessName) == 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] lpszProcessName * The name of the executable process. * * @return * Returns TRUE if the given process' name is running, * FALSE otherwise. * */ BOOL IsProcessRunning(IN LPCWSTR lpszProcessName) { DWORD dwReturn, dwProcessID; HANDLE hProcess; /* Get the process ID */ dwProcessID = GetProcessID(lpszProcessName); 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)\n", 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(IN LPCWSTR lpszProcessName) { STARTUPINFOW si; PROCESS_INFORMATION pi; HANDLE hUserToken, hProcessToken; BOOL bSuccess; WCHAR ExpandedCmdLine[MAX_PATH]; /* Expand the process path string */ ExpandEnvironmentStringsW(lpszProcessName, 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] lpszProcessName * The name of the executable process. * * @return * Returns TRUE if the process has been terminated successfully, * FALSE otherwise. * */ BOOL CloseProcess(IN LPCWSTR lpszProcessName) { HANDLE hProcess; DWORD dwProcessID; /* Get the process ID */ dwProcessID = GetProcessID(lpszProcessName); 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)\n", GetLastError()); return FALSE; } /* Terminate it */ TerminateProcess(hProcess, 0); CloseHandle(hProcess); return TRUE; }