Implement Utility Manager software
[reactos.git] / base / applications / utilman / process.c
1 /*
2 * PROJECT: ReactOS Utility Manager (Accessibility)
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Process handling functions
5 * COPYRIGHT: Copyright 2019 Bișoc George (fraizeraust99 at gmail dot com)
6 */
7
8 /* INCLUDES *******************************************************************/
9
10 #include "precomp.h"
11
12 /* FUNCTIONS ******************************************************************/
13
14 /**
15 * @IsProcessRunning
16 *
17 * Checks if a process is running.
18 *
19 * @param[in] ProcName
20 * The name of the executable process.
21 *
22 * @return
23 * Returns TRUE if the given process' name is running,
24 * FALSE otherwise.
25 *
26 */
27 BOOL IsProcessRunning(IN LPCWSTR lpProcessName)
28 {
29 BOOL bIsRunning = FALSE;
30 PROCESSENTRY32W Process = {0};
31
32 /* Create a snapshot and check whether the given process' executable name is running */
33 HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
34
35 if (hSnapshot == INVALID_HANDLE_VALUE)
36 return FALSE;
37
38 Process.dwSize = sizeof(Process);
39
40 /* Enumerate the processes */
41 if (Process32FirstW(hSnapshot, &Process))
42 {
43 do
44 {
45 if (_wcsicmp(Process.szExeFile, lpProcessName) == 0)
46 {
47 /* The process we are searching for is running */
48 bIsRunning = TRUE;
49 break;
50 }
51 }
52 while (Process32NextW(hSnapshot, &Process));
53 }
54
55 /* Free the handle and return */
56 CloseHandle(hSnapshot);
57 return bIsRunning;
58 }
59
60 /**
61 * @LaunchProcess
62 *
63 * Executes a process.
64 *
65 * @param[in] lpProcessName
66 * The name of the executable process.
67 *
68 * @return
69 * Returns TRUE if the process has been launched successfully,
70 * FALSE otherwise.
71 *
72 */
73 BOOL LaunchProcess(LPCWSTR lpProcessName)
74 {
75 STARTUPINFOW si;
76 PROCESS_INFORMATION pi;
77 HANDLE hUserToken, hProcessToken;
78 BOOL bSuccess;
79 WCHAR ExpandedCmdLine[MAX_PATH];
80
81 /* Expand the process path string */
82 ExpandEnvironmentStringsW(lpProcessName, ExpandedCmdLine, ARRAYSIZE(ExpandedCmdLine));
83
84 ZeroMemory(&pi, sizeof(pi));
85 ZeroMemory(&si, sizeof(si));
86 si.cb = sizeof(si);
87 si.dwFlags = STARTF_USESHOWWINDOW;
88 si.wShowWindow = SW_SHOWNORMAL;
89
90 /* Get the token of the parent (current) process of the application */
91 bSuccess = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_DUPLICATE, &hUserToken);
92 if (!bSuccess)
93 {
94 DPRINT("OpenProcessToken() failed with error -> %lu\n", GetLastError());
95 return FALSE;
96 }
97
98 /* Duplicate a new token so that we can use it to create our process */
99 bSuccess = DuplicateTokenEx(hUserToken, TOKEN_ALL_ACCESS, NULL, SecurityIdentification, TokenPrimary, &hProcessToken);
100 if (!bSuccess)
101 {
102 DPRINT("DuplicateTokenEx() failed with error -> %lu\n", GetLastError());
103 CloseHandle(hUserToken);
104 return FALSE;
105 }
106
107 /* Finally create the process */
108 bSuccess = CreateProcessAsUserW(hProcessToken,
109 NULL,
110 ExpandedCmdLine,
111 NULL,
112 NULL,
113 FALSE,
114 0, // DETACHED_PROCESS, NORMAL_PRIORITY_CLASS
115 NULL,
116 NULL,
117 &si,
118 &pi);
119
120 if (!bSuccess)
121 {
122 DPRINT("CreateProcessAsUserW() failed with error -> %lu\n", GetLastError());
123 CloseHandle(hUserToken);
124 CloseHandle(hProcessToken);
125 return FALSE;
126 }
127
128 CloseHandle(pi.hProcess);
129 CloseHandle(pi.hThread);
130 CloseHandle(hUserToken);
131 CloseHandle(hProcessToken);
132 return TRUE;
133 }
134
135 /**
136 * @CloseProcess
137 *
138 * Closes a process.
139 *
140 * @param[in] lpProcessName
141 * The name of the executable process.
142 *
143 * @return
144 * Returns TRUE if the process has been terminated successfully,
145 * FALSE otherwise.
146 *
147 */
148 BOOL CloseProcess(IN LPCWSTR lpProcessName)
149 {
150 BOOL bSuccess = FALSE;
151 PROCESSENTRY32W Process = {0};
152
153 /* Create a snapshot and check if the given process' executable name is running */
154 HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
155
156 if (hSnapshot == INVALID_HANDLE_VALUE)
157 return FALSE;
158
159 Process.dwSize = sizeof(Process);
160
161 /* Enumerate the processes */
162 if (Process32FirstW(hSnapshot, &Process))
163 {
164 do
165 {
166 if (_wcsicmp(Process.szExeFile, lpProcessName) == 0)
167 {
168 /*
169 * We have found the process. However we must make
170 * sure that we DO NOT kill ourselves (the process ID
171 * matching with the current parent process ID).
172 */
173 HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, 0, Process.th32ProcessID);
174 if ((hProcess != NULL) && (Process.th32ProcessID != GetCurrentProcessId()))
175 {
176 TerminateProcess(hProcess, 0);
177 CloseHandle(hProcess);
178 }
179 bSuccess = TRUE;
180 break;
181 }
182 }
183 while (Process32NextW(hSnapshot, &Process));
184 }
185
186 /* Free the handle and return */
187 CloseHandle(hSnapshot);
188 return bSuccess;
189 }