Gray C++ Libraries  0.0.2
A set of C++ libraries for MSVC, GNU on Windows, WinCE, Linux
cOSProcess.h
Go to the documentation of this file.
1 //
5 //
6 
7 #ifndef _INC_cOSProcess_H
8 #define _INC_cOSProcess_H
9 #ifndef NO_PRAGMA_ONCE
10 #pragma once
11 #endif
12 
13 #include "cOSHandle.h"
14 #include "cFilePath.h"
15 #include "cThreadLock.h"
16 
17 namespace Gray
18 {
19  class cFile;
20 
21 #ifdef _WIN32
22  typedef int SHOWWINDOW_t;
23 #elif defined(__linux__)
24  enum SHOWWINDOW_t
25  {
28  SW_HIDE = 0,
29  SW_SHOWNORMAL = 1,
30  SW_SHOWMINIMIZED,
31  SW_SHOWMAXIMIZED,
32  SW_SHOWDEFAULT = 10,
34  };
35 #else
36 #error NOOS
37 #endif
38 
39 #ifdef _WIN32
40  typedef DWORD PROCESSID_t;
41  typedef DWORD APP_EXITCODE_t;
42 #elif defined(__linux__)
43  typedef pid_t PROCESSID_t;
44  typedef int APP_EXITCODE_t;
45 #endif
46  constexpr PROCESSID_t PROCESSID_BAD = 0;
47 
49  {
52 
54  APP_EXITCODE_OK = EXIT_SUCCESS,
55  APP_EXITCODE_FAIL = EXIT_FAILURE,
57 
58  // .. some other condition.
59 #ifdef _WIN32
60  APP_EXITCODE_STILL_ACTIVE = STILL_ACTIVE,
61 #elif defined(__linux__)
62  APP_EXITCODE_STILL_ACTIVE = 0x103,
63 #endif
64  APP_EXITCODE_UNK = SHRT_MAX,
65  };
66 
68  {
73 
74  protected:
75  PROCESSID_t m_nPid;
76 
77 #ifdef _WIN32
78  cOSHandle m_hProcess;
79  public:
80  cOSHandle m_hThread;
81 #elif defined(__linux__)
82  protected:
83  cStringF m_sPath;
84 #else
85 #error NOOS
86 #endif
87 
88  public:
89  cOSProcess() noexcept;
90  virtual ~cOSProcess();
91 
92 #ifdef _WIN32
93  cOSProcess(PROCESSID_t nPid, HANDLE h) noexcept
94  : m_nPid(nPid)
95  , m_hProcess(h)
96  {
97  // _WIN32 = ::GetCurrentProcess() = 0xFFFFFFFF as a shortcut.
98  }
99  HANDLE get_ProcessHandle() const noexcept
100  {
101  return m_hProcess.get_Handle();
102  }
103  void CloseProcessHandle();
104 #endif
105  HRESULT CreateProcessX(const FILECHAR_t* pszExeName, const FILECHAR_t* pszArgs = nullptr, SHOWWINDOW_t nShowCmd = SW_SHOWNORMAL, const FILECHAR_t* pszCurrentDir = nullptr, cFile* pFileOutPipe = nullptr);
106 
107  static inline bool GRAYCALL IsSystemPID(PROCESSID_t nProcessID) noexcept
108  {
109  if (nProcessID == 0) // PROCESSID_BAD
110  return true;
111 #ifdef _WIN32
112  if (nProcessID == 4)
113  return true;
114 #endif
115  return false;
116  }
117 
118  bool isValidProcess() const noexcept
119  {
120  // Is the process in memory/valid/active now ?
121 #ifdef _WIN32
122  return m_hProcess.isValidHandle();
123 #elif defined(__linux__)
124  return m_nPid != 0;
125 #endif
126  }
127 
128  PROCESSID_t get_ProcessId() const noexcept
129  {
130  return m_nPid;
131  }
132  virtual cStringF get_ProcessPath() const;
133  cStringF get_ProcessName() const;
134  HRESULT OpenProcessId(PROCESSID_t dwProcessID, DWORD dwDesiredAccess = 0, bool bInheritHandle = false);
135 
136 #ifdef _WIN32
137  HRESULT GetProcessCommandLine(OUT wchar_t* pwText, _Inout_ size_t* pdwTextSize) const;
138 #endif
139  cStringF get_CommandLine() const;
140 
141  HRESULT WaitForProcessExit(TIMESYSD_t nTimeWait, APP_EXITCODE_t* pnExitCode = nullptr);
142 
143  void AttachCurrentProcess() noexcept
144  {
146 #ifdef _WIN32
147  // 0xFFFFFFFF = current process. https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getcurrentprocess
148  m_nPid = ::GetCurrentProcessId();
149  m_hProcess.AttachHandle(::GetCurrentProcess());
150 #elif defined(__linux__)
151  m_nPid = ::getpid();
152 #endif
153  }
154 
155  HRESULT TerminateProcess(APP_EXITCODE_t uExitCode)
156  {
159 
160  if (!isValidProcess())
161  return S_FALSE;
162 #ifdef _WIN32
163  if (!::TerminateProcess(get_ProcessHandle(), uExitCode))
164 #elif defined(__linux__)
165  if (::kill(get_ProcessId(), SIGTERM) != 0) // send a signal(SIGTERM) to the process.
166 #endif
167  {
168  return HResult::GetLastDef();
169  }
170  return S_OK;
171  }
172 
174  DWORD get_PriorityClass() const noexcept
175  {
177 #if defined(_WIN32) && ! defined(UNDER_CE)
178  return ::GetPriorityClass(get_ProcessHandle());
179 #elif defined(__linux__)
180  ASSERT(0);
181  // TODO __linux__
182  return 0;
183 #endif
184 }
185  bool put_PriorityClass(DWORD dwPriorityClass) noexcept
186  {
189 #if defined(_WIN32) && ! defined(UNDER_CE)
190  return ::SetPriorityClass(get_ProcessHandle(), dwPriorityClass) ? true : false;
191 #elif defined(__linux__)
192  ASSERT(0);
193  // TODO __linux__
194  return false;
195 #endif
196  }
197 
198 #ifdef _WIN32
199 
200  HRESULT CreateRemoteThread(THREAD_FUNC_t pvFunc, const void* pvArgs, OUT cOSHandle& thread);
201 
202  void* AllocMemory(size_t nSize)
203  {
204  // Allocate space in the process memory.
205  return ::VirtualAllocEx(get_ProcessHandle(), NULL, nSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
206  }
207 
208  HRESULT WriteProcessMemory(void* pBaseAddress, const void* pData, size_t nSize)
209  {
212 
213  SIZE_T nSizeWrite = nSize;
214  const BOOL bSuccess = ::WriteProcessMemory(get_ProcessHandle(), pBaseAddress, pData, nSize, &nSizeWrite);
215  if (!bSuccess)
216  {
217  return HResult::GetLastDef(HRESULT_WIN32_C(ERROR_WRITE_FAULT));
218  }
219  return (HRESULT)nSizeWrite;
220  }
221 
222  HRESULT ReadProcessMemory(const void* pBaseAddress, void* pDataIn, size_t nSize) const
223  {
227 
228  SIZE_T nSizeRead = nSize;
229  const BOOL bSuccess = ::ReadProcessMemory(get_ProcessHandle(), pBaseAddress, pDataIn, nSize, &nSizeRead);
230  if (!bSuccess)
231  {
232  return HResult::GetLastDef(HRESULT_WIN32_C(ERROR_READ_FAULT));
233  }
234  return (HRESULT)nSizeRead;
235  }
236 
237  bool GetExitCodeProcess(OUT APP_EXITCODE_t* pnExitCode)
238  {
242  return ::GetExitCodeProcess(get_ProcessHandle(), pnExitCode) ? true : false;
243  }
244 
245  static inline PROCESSID_t FindProcessIdForWindow(HWND hWnd) noexcept
246  {
249  PROCESSID_t dwProcessIDRet = PROCESSID_BAD;
250  const THREADID_t dwThreadID = ::GetWindowThreadProcessId(hWnd, &dwProcessIDRet);
251  UNREFERENCED_PARAMETER(dwThreadID);
252  return dwProcessIDRet;
253  }
254 
255  // Stats
256 #ifndef UNDER_CE
257  bool GetStatTimes(OUT FILETIME* pCreationTime, OUT FILETIME* pExitTime, OUT FILETIME* pKernelTime, OUT FILETIME* pUserTime) const
258  {
260  return ::GetProcessTimes(get_ProcessHandle(), pCreationTime, pExitTime, pKernelTime, pUserTime) ? true : false;
261  }
262 
263  bool GetStatIoCounters(OUT IO_COUNTERS* pIoCounters) const
264  {
265  return ::GetProcessIoCounters(get_ProcessHandle(), pIoCounters) ? true : false;
266  }
267 #endif // UNDER_CE
268 
269 #if ( _WIN32_WINNT >= 0x0501 ) && ! defined(UNDER_CE)
270  bool GetStatHandleCount(OUT DWORD* pdwHandleCount) const
271  {
273  return ::GetProcessHandleCount(get_ProcessHandle(), pdwHandleCount);
274  }
275 #endif
276  static HWND GRAYCALL FindWindowForProcessID(PROCESSID_t nProcessID, DWORD dwStyleFlags, const GChar_t* pszClassName = nullptr); // WS_VISIBLE
277 #endif // _WIN32
278 
280  };
281 }
282 
283 #endif // _INC_cOSProcess_H
284 
#define GRAYCORE_LINK
Definition: GrayCore.h:47
#define GRAYCALL
declare calling convention for static functions so everyone knows the arg passing scheme....
Definition: GrayCore.h:36
#define HRESULT_WIN32_C(x)
a constant LSTATUS/error_status_t with no check, unlike HRESULT_FROM_WIN32()
Definition: HResult.h:79
#define UNREFERENCED_PARAMETER(P)
< _WIN32 type thing. get rid of stupid warning.
Definition: SysTypes.h:299
INT32 HRESULT
_WIN32 style error codes. INT32
Definition: SysTypes.h:465
#define ASSERT(exp)
Definition: cDebugAssert.h:87
#define UNITTEST_FRIEND(n)
Define this in the class body to be unit tested. Allow the unit test to access private/protected stuf...
Definition: cUnitTestDecl.h:17
static HRESULT GetLastDef(HRESULT hResDef=E_FAIL) noexcept
Definition: HResult.h:242
Definition: cOSHandle.h:59
void AttachHandle(HANDLE h) noexcept
Definition: cOSHandle.h:163
bool isValidHandle() const noexcept
Definition: cOSHandle.h:125
HANDLE get_Handle() const noexcept
Definition: cOSHandle.h:107
Definition: cOSProcess.h:68
PROCESSID_t get_ProcessId() const noexcept
Definition: cOSProcess.h:128
void AttachCurrentProcess() noexcept
Definition: cOSProcess.h:143
HRESULT TerminateProcess(APP_EXITCODE_t uExitCode)
Definition: cOSProcess.h:155
bool put_PriorityClass(DWORD dwPriorityClass) noexcept
Definition: cOSProcess.h:185
bool isValidProcess() const noexcept
Definition: cOSProcess.h:118
PROCESSID_t m_nPid
Process ID, 0 = PROCESSID_BAD = un-init.
Definition: cOSProcess.h:75
static bool __stdcall IsSystemPID(PROCESSID_t nProcessID) noexcept
Definition: cOSProcess.h:107
DWORD get_PriorityClass() const noexcept
CPU priority level for scheduling.
Definition: cOSProcess.h:174
< The main namespace for all Core functions.
Definition: GrayCore.cpp:14
constexpr PROCESSID_t PROCESSID_BAD
Invalid process id.
Definition: cOSProcess.h:46
INT32 TIMESYSD_t
Time delta. signed milli-Seconds Span. cTimeSys::k_DMAX, cTimeSys::k_INF = MAILSLOT_WAIT_FOREVER.
Definition: cTimeSys.h:28
char FILECHAR_t
a UTF8 char in a file name. like TCHAR
Definition: FileName.h:22
char GChar_t
My version of TCHAR, _TCHAR.
Definition: StrConst.h:26
THREAD_EXITCODE_t(_stdcall * THREAD_FUNC_t)(void *)
Definition: cThreadLock.h:52
APP_EXITCODE_TYPE
Definition: cOSProcess.h:49
@ APP_EXITCODE_OK
0=EXIT_SUCCESS (stdlib.h). App closed.
Definition: cOSProcess.h:54
@ APP_EXITCODE_UNK
handle not valid ?
Definition: cOSProcess.h:64
@ APP_EXITCODE_ABORT
3=Default error returned if "abort()" used (arbitrary?) App closed.
Definition: cOSProcess.h:56
@ APP_EXITCODE_ERRNO
See Posix 'errno' for why this process never started.
Definition: cOSProcess.h:53
@ APP_EXITCODE_FAIL
1=EXIT_FAILURE = generic error. App closed.
Definition: cOSProcess.h:55