1 /* 2 * PROJECT: ReactOS Utility Manager Resources DLL (UManDlg.dll) 3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 * PURPOSE: Process handling functions 5 * COPYRIGHT: Copyright 2019-2020 George Bișoc (george.bisoc@reactos.org) 6 */ 7 8 /* INCLUDES *******************************************************************/ 9 10 #include "umandlg.h" 11 12 /* FUNCTIONS ******************************************************************/ 13 14 /** 15 * @GetProcessID 16 * 17 * Returns the process executable ID based on the given executable name. 18 * 19 * @param[in] lpszProcessName 20 * The name of the executable process. 21 * 22 * @return 23 * Returns the ID number of the process, otherwise 0. 24 * 25 */ 26 DWORD GetProcessID(IN LPCWSTR lpszProcessName) 27 { 28 PROCESSENTRY32W Process; 29 30 /* Create a snapshot and check if the given process name matches with the one from the process entry structure */ 31 HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); 32 33 if (hSnapshot == INVALID_HANDLE_VALUE) 34 return 0; 35 36 /* Get the whole size of the structure */ 37 Process.dwSize = sizeof(Process); 38 39 /* Enumerate the processes */ 40 if (Process32FirstW(hSnapshot, &Process)) 41 { 42 do 43 { 44 if (_wcsicmp(Process.szExeFile, lpszProcessName) == 0) 45 { 46 /* The names match, return the process ID we're interested */ 47 CloseHandle(hSnapshot); 48 return Process.th32ProcessID; 49 } 50 } 51 while (Process32NextW(hSnapshot, &Process)); 52 } 53 54 CloseHandle(hSnapshot); 55 return 0; 56 } 57 58 /** 59 * @IsProcessRunning 60 * 61 * Checks if a process is running. 62 * 63 * @param[in] lpszProcessName 64 * The name of the executable process. 65 * 66 * @return 67 * Returns TRUE if the given process' name is running, 68 * FALSE otherwise. 69 * 70 */ 71 BOOL IsProcessRunning(IN LPCWSTR lpszProcessName) 72 { 73 DWORD dwReturn, dwProcessID; 74 HANDLE hProcess; 75 76 /* Get the process ID */ 77 dwProcessID = GetProcessID(lpszProcessName); 78 if (dwProcessID == 0) 79 { 80 return FALSE; 81 } 82 83 /* Synchronize the process to get its signaling state */ 84 hProcess = OpenProcess(SYNCHRONIZE, FALSE, dwProcessID); 85 if (!hProcess) 86 { 87 DPRINT("IsProcessRunning(): Failed to open the process! (Error: %lu)\n", GetLastError()); 88 return FALSE; 89 } 90 91 /* Wait for the process */ 92 dwReturn = WaitForSingleObject(hProcess, 0); 93 if (dwReturn == WAIT_TIMEOUT) 94 { 95 /* The process is still running */ 96 CloseHandle(hProcess); 97 return TRUE; 98 } 99 100 CloseHandle(hProcess); 101 return FALSE; 102 } 103 104 /** 105 * @LaunchProcess 106 * 107 * Executes a process. 108 * 109 * @param[in] lpProcessName 110 * The name of the executable process. 111 * 112 * @return 113 * Returns TRUE if the process has been launched successfully, 114 * FALSE otherwise. 115 * 116 */ 117 BOOL LaunchProcess(IN LPCWSTR lpszProcessName) 118 { 119 STARTUPINFOW si; 120 PROCESS_INFORMATION pi; 121 HANDLE hUserToken, hProcessToken; 122 BOOL bSuccess; 123 WCHAR ExpandedCmdLine[MAX_PATH]; 124 125 /* Expand the process path string */ 126 ExpandEnvironmentStringsW(lpszProcessName, ExpandedCmdLine, ARRAYSIZE(ExpandedCmdLine)); 127 128 ZeroMemory(&pi, sizeof(pi)); 129 ZeroMemory(&si, sizeof(si)); 130 si.cb = sizeof(si); 131 si.dwFlags = STARTF_USESHOWWINDOW; 132 si.wShowWindow = SW_SHOWNORMAL; 133 134 /* Get the token of the parent (current) process of the application */ 135 bSuccess = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_DUPLICATE, &hUserToken); 136 if (!bSuccess) 137 { 138 DPRINT("OpenProcessToken() failed with error -> %lu\n", GetLastError()); 139 return FALSE; 140 } 141 142 /* Duplicate a new token so that we can use it to create our process */ 143 bSuccess = DuplicateTokenEx(hUserToken, TOKEN_ALL_ACCESS, NULL, SecurityIdentification, TokenPrimary, &hProcessToken); 144 if (!bSuccess) 145 { 146 DPRINT("DuplicateTokenEx() failed with error -> %lu\n", GetLastError()); 147 CloseHandle(hUserToken); 148 return FALSE; 149 } 150 151 /* Finally create the process */ 152 bSuccess = CreateProcessAsUserW(hProcessToken, 153 NULL, 154 ExpandedCmdLine, 155 NULL, 156 NULL, 157 FALSE, 158 0, // DETACHED_PROCESS, NORMAL_PRIORITY_CLASS 159 NULL, 160 NULL, 161 &si, 162 &pi); 163 164 if (!bSuccess) 165 { 166 DPRINT("CreateProcessAsUserW() failed with error -> %lu\n", GetLastError()); 167 CloseHandle(hUserToken); 168 CloseHandle(hProcessToken); 169 return FALSE; 170 } 171 172 CloseHandle(pi.hProcess); 173 CloseHandle(pi.hThread); 174 CloseHandle(hUserToken); 175 CloseHandle(hProcessToken); 176 return TRUE; 177 } 178 179 /** 180 * @CloseProcess 181 * 182 * Closes a process. 183 * 184 * @param[in] lpszProcessName 185 * The name of the executable process. 186 * 187 * @return 188 * Returns TRUE if the process has been terminated successfully, 189 * FALSE otherwise. 190 * 191 */ 192 BOOL CloseProcess(IN LPCWSTR lpszProcessName) 193 { 194 HANDLE hProcess; 195 DWORD dwProcessID; 196 197 /* Get the process ID */ 198 dwProcessID = GetProcessID(lpszProcessName); 199 if (dwProcessID == 0) 200 { 201 return FALSE; 202 } 203 204 /* Make sure that the given process ID is not ours, the parent process, so that we do not kill ourselves */ 205 if (dwProcessID == GetCurrentProcessId()) 206 { 207 return FALSE; 208 } 209 210 /* Open the process so that we can terminate it */ 211 hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, dwProcessID); 212 if (!hProcess) 213 { 214 DPRINT("CloseProcess(): Failed to open the process for termination! (Error: %lu)\n", GetLastError()); 215 return FALSE; 216 } 217 218 /* Terminate it */ 219 TerminateProcess(hProcess, 0); 220 CloseHandle(hProcess); 221 return TRUE; 222 } 223