From 21f3647ef7dc344d0f89f33763442474e5cf0618 Mon Sep 17 00:00:00 2001 From: Doug Lardo Date: Wed, 22 Nov 2023 14:49:47 -0800 Subject: [PATCH 1/9] ProcessNameListToPause --- Main.c | 19 ++++++++++++++++++- Main.h | 1 + 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/Main.c b/Main.c index c8c681b..ce3931e 100644 --- a/Main.c +++ b/Main.c @@ -163,7 +163,7 @@ void HandlePauseKeyPress(void) // Either we configured it to pause/un-pause a specified process, or we will pause/un-pause // the currently in-focus foreground window. - if (wcslen(gConfig.ProcessNameToPause) > 0) + if (wcslen(gConfig.ProcessNameToPause) > 0 || wcslen(gConfig.ProcessNameListToPause)) { if (gIsPaused) { @@ -332,6 +332,14 @@ u32 LoadRegistrySettings(void) .MinValue = NULL, .MaxValue = NULL, .Destination = &gConfig.ProcessNameToPause + }, + { + .Name = L"ProcessNameListToPause", + .DataType = REG_SZ, + .DefaultValue = &(wchar_t[1024]) { L"" }, + .MinValue = NULL, + .MaxValue = NULL, + .Destination = &gConfig.ProcessNameListToPause } }; @@ -441,6 +449,15 @@ u32 LoadRegistrySettings(void) } } + // Combine ProcessNameToPause and ProcessNameListToPause + if (wcslen(gConfig.ProcessNameListToPause) > 0) + { + wcscat_s(gConfig.ProcessNameListToPause, sizeof(gConfig.ProcessNameListToPause), L", "); + } + wcscat_s(gConfig.ProcessNameListToPause, sizeof(gConfig.ProcessNameListToPause), gConfig.ProcessNameToPause); + + DbgPrint(L"Final List of Processes: %s.", gConfig.ProcessNameListToPause); + Exit: if (RegKey != NULL) { diff --git a/Main.h b/Main.h index ee8cbd3..5e43e5f 100644 --- a/Main.h +++ b/Main.h @@ -33,6 +33,7 @@ typedef struct _CONFIG u32 TrayIcon; u32 PauseKey; wchar_t ProcessNameToPause[128]; + wchar_t ProcessNameListToPause[1024]; } CONFIG; // Function declarations. From 5b9ac0a4361426280d280037cda088ddae7d6ddb Mon Sep 17 00:00:00 2001 From: Doug Lardo Date: Thu, 23 Nov 2023 00:26:16 -0800 Subject: [PATCH 2/9] Set data structure --- set.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ set.h | 19 +++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 set.c create mode 100644 set.h diff --git a/set.c b/set.c new file mode 100644 index 0000000..e9a51dd --- /dev/null +++ b/set.c @@ -0,0 +1,66 @@ +#pragma once + +#include "set.h" +#include + +void initializeSet(Set* set) { + for (size_t i = 0; i < MAX_PROCESSES; i++) { + set->elements[i] = 0; + } + set->size = 0; +} + +bool addToSet(Set* set, int element) { + // Check if the element is already in the set + for (size_t i = 0; i < set->size; i++) { + if (set->elements[i] == element) { + return false; // Element is already in the set + } + } + + // Add the element to the set + if (set->size < MAX_PROCESSES) { + set->elements[set->size++] = element; + return true; // Element added successfully + } + else { + return false; // Set is full + } +} + +bool removeFromSet(Set* set, int element) { + for (size_t i = 0; i < MAX_PROCESSES; i++) { + if (set->elements[i] == element) { + set->elements[i] = 0; + // Shift elements to the left to fill the gap + for (size_t j = i; j < MAX_PROCESSES - 1; j++) { + set->elements[j] = set->elements[j + 1]; + } + set->size--; + return true; // Element removed successfully + } + } + return false; // Element is not in the set +} + +bool isInSet(const Set* set, int element) { + for (size_t i = 0; i < set->size; i++) { + if (set->elements[i] == element) { + return true; // Element is in the set + } + } + return false; // Element is not in the set +} + +void printSet(const Set* set) { + printf("Set: "); + for (size_t i = 0; i < set->size; i++) { + printf("%ld ", set->elements[i]); + } + printf("\n"); +} + +bool isSetEmpty(const Set* set) +{ + return set->size == 0; +} diff --git a/set.h b/set.h new file mode 100644 index 0000000..5c547f6 --- /dev/null +++ b/set.h @@ -0,0 +1,19 @@ +#pragma once + +#include +#include "Globals.h" + +// #define MAX_PROCESSES 8 // todo: centralize +typedef unsigned long u32; + +typedef struct { + u32 elements[MAX_PROCESSES]; + size_t size; +} Set; + +void initializeSet(Set* set); +bool addToSet(Set* set, int element); +bool removeFromSet(Set* set, int element); +bool isInSet(const Set* set, int element); +void printSet(const Set* set); +bool isSetEmpty(const Set* set); From 0cff5f6879331caaebe5786fbd3bf723f46a1f65 Mon Sep 17 00:00:00 2001 From: Doug Lardo Date: Thu, 23 Nov 2023 00:26:56 -0800 Subject: [PATCH 3/9] refactor & multi PID pause --- Globals.h | 5 + Main.c | 274 +++++++++++++++++---------- Main.h | 16 +- UniversalPauseButton.vcxproj | 3 + UniversalPauseButton.vcxproj.filters | 9 + 5 files changed, 203 insertions(+), 104 deletions(-) create mode 100644 Globals.h diff --git a/Globals.h b/Globals.h new file mode 100644 index 0000000..5265921 --- /dev/null +++ b/Globals.h @@ -0,0 +1,5 @@ +#pragma once + +#define VERSION L"1.2.0" +#define APPNAME L"UniversalPauseButton" +#define MAX_PROCESSES 8 diff --git a/Main.c b/Main.c index ce3931e..3db65e7 100644 --- a/Main.c +++ b/Main.c @@ -18,14 +18,15 @@ #include #include "Main.h" #include "resource.h" +#include "set.h" CONFIG gConfig; HANDLE gDbgConsole = INVALID_HANDLE_VALUE; -BOOL gIsRunning = TRUE; -HANDLE gMutex; +BOOL gIsRunning = TRUE; // Tracks if the application is running +HANDLE gMutex; // Ensures only a single instance of the app is running NOTIFYICONDATA gTrayNotifyIconData; -BOOL gIsPaused; -u32 gPreviouslyPausedProcessId; +BOOL gIsPaused = FALSE; // Global pause state for all processes +Set gPids; // Process PIDs int WINAPI wWinMain(_In_ HINSTANCE Instance, _In_opt_ HINSTANCE PrevInstance, _In_ PWSTR CmdLine, _In_ int CmdShow) { @@ -37,6 +38,7 @@ int WINAPI wWinMain(_In_ HINSTANCE Instance, _In_opt_ HINSTANCE PrevInstance, _I MSG WndMsg = { 0 }; //HHOOK KeyboardHook = NULL; + initializeSet(&gPids); if (LoadRegistrySettings() != ERROR_SUCCESS) { goto Exit; @@ -143,10 +145,8 @@ int WINAPI wWinMain(_In_ HINSTANCE Instance, _In_opt_ HINSTANCE PrevInstance, _I { HandlePauseKeyPress(); } - DispatchMessageW(&WndMsg); } - Sleep(5); } @@ -154,135 +154,192 @@ int WINAPI wWinMain(_In_ HINSTANCE Instance, _In_opt_ HINSTANCE PrevInstance, _I return(0); } -void HandlePauseKeyPress(void) -{ - HANDLE ProcessHandle = NULL; +// returns PID or 0 on error +u32 PidLookup(wchar_t* ProcessName) { + HANDLE ProcessSnapshot = NULL; PROCESSENTRY32W ProcessEntry = { sizeof(PROCESSENTRY32W) }; u32 ProcessId = 0; - - // Either we configured it to pause/un-pause a specified process, or we will pause/un-pause - // the currently in-focus foreground window. - if (wcslen(gConfig.ProcessNameToPause) > 0 || wcslen(gConfig.ProcessNameListToPause)) + + ProcessSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (ProcessSnapshot == INVALID_HANDLE_VALUE) + { + MsgBox(L"Failed to create snapshot of running processes! Error 0x%08lx", APPNAME L" Error", MB_OK | MB_ICONERROR, GetLastError()); + return 0; + } + + if (Process32FirstW(ProcessSnapshot, &ProcessEntry) == FALSE) { - if (gIsPaused) + MsgBox(L"Failed to retrieve list of running processes! Error 0x%08lx", APPNAME L" Error", MB_OK | MB_ICONERROR, GetLastError()); + return 0; + } + + do + { + if (_wcsicmp(ProcessEntry.szExeFile, ProcessName) == 0) { - // Process currently paused, need to un-pause it. - UnpausePreviouslyPausedProcess(); + ProcessId = ProcessEntry.th32ProcessID; + DbgPrint(L"Found process %s with PID %d.", ProcessEntry.szExeFile, ProcessId); + + break; } - else - { - // Process needs to be paused. - DbgPrint(L"Pause key pressed. Attempting to pause named process %s...", gConfig.ProcessNameToPause); - ProcessSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); - if (ProcessSnapshot == INVALID_HANDLE_VALUE) - { - MsgBox(L"Failed to create snapshot of running processes! Error 0x%08lx", APPNAME L" Error", MB_OK | MB_ICONERROR, GetLastError()); - goto Exit; - } + } while (Process32NextW(ProcessSnapshot, &ProcessEntry)); - if (Process32FirstW(ProcessSnapshot, &ProcessEntry) == FALSE) - { - MsgBox(L"Failed to retrieve list of running processes! Error 0x%08lx", APPNAME L" Error", MB_OK | MB_ICONERROR, GetLastError()); - goto Exit; - } + CloseHandle(ProcessSnapshot); + + if (ProcessId == 0) + { + DbgPrint(L"Unable to locate any process with the name %s!", ProcessName); + return 0; + } - do - { - if (_wcsicmp(ProcessEntry.szExeFile, gConfig.ProcessNameToPause) == 0) - { - ProcessId = ProcessEntry.th32ProcessID; - DbgPrint(L"Found process %s with PID %d.", ProcessEntry.szExeFile, ProcessId); - break; - } - } while (Process32NextW(ProcessSnapshot, &ProcessEntry)); + return ProcessId; +} - if (ProcessId == 0) - { - DbgPrint(L"Unable to locate any process with the name %s!", gConfig.ProcessNameToPause); - goto Exit; - } - ProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcessId); - if (ProcessHandle == NULL) - { - MsgBox(L"Failed to open process %d! Error 0x%08lx", APPNAME L" Error", MB_OK | MB_ICONERROR, ProcessId, GetLastError()); - goto Exit; - } - NtSuspendProcess(ProcessHandle); - gIsPaused = TRUE; - gPreviouslyPausedProcessId = ProcessId; - DbgPrint(L"Process paused!"); - } +// returns 0 on success, -1 on error +i8 PauseProcess(u32 Pid) { + HANDLE ProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, Pid); + if (ProcessHandle == NULL) + { + MsgBox(L"Failed to open process %d! Error 0x%08lx", APPNAME L" Error", MB_OK | MB_ICONERROR, Pid, GetLastError()); + return -1; + } + + NtSuspendProcess(ProcessHandle); + gIsPaused = TRUE; + addToSet(&gPids, Pid); + DbgPrint(L"Process %d paused!", Pid); + return 0; +} + +u32 PidOfForegroundProcess(void) { + u32 ProcessId; + HWND ForegroundWindow = GetForegroundWindow(); + if (ForegroundWindow == NULL) + { + MsgBox(L"Failed to detect foreground window!", APPNAME L" Error", MB_OK | MB_ICONERROR); + return 0; + } + GetWindowThreadProcessId(ForegroundWindow, &ProcessId); + if (ProcessId == 0) + { + MsgBox(L"Failed to get PID from foreground window! Error code 0x%08lx", APPNAME L" Error", MB_OK | MB_ICONERROR, GetLastError()); + return 0; + } + HANDLE ProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcessId); + if (ProcessHandle == NULL) + { + MsgBox(L"Failed to open process %d! Error 0x%08lx", APPNAME L" Error", MB_OK | MB_ICONERROR, ProcessId, GetLastError()); + return 0; } else { - if (gIsPaused) - { - // Process currently paused, need to un-pause it. - UnpausePreviouslyPausedProcess(); + CloseHandle(ProcessHandle); + } + return ProcessId; +} + +void FindRegistryPids(void) { + if (wcslen(gConfig.ProcessNameListToPause) > 0) + { + u32 pid = 0; + // A required pointer which tracks the context between successive calls to wcstok_s(). + wchar_t* context = NULL; + wchar_t delim[] = L", "; + wchar_t myCopy[sizeof(gConfig.ProcessNameListToPause) / sizeof(wchar_t)]; + + wcscpy_s(myCopy, _countof(myCopy), gConfig.ProcessNameListToPause); + + // strtok modifies the original string during the parsing process + wchar_t* token = wcstok_s(myCopy, delim, &context); + // loop through all process names + while (token != NULL) { + trimWhitespaces(token); + pid = PidLookup(token); + if (pid) addToSet(&gPids, pid); + // Get the next token + token = wcstok_s(NULL, delim, &context); } - else - { - // Process needs to be paused. - DbgPrint(L"Pause key pressed. Attempting to pause current foreground window..."); - HWND ForegroundWindow = GetForegroundWindow(); - if (ForegroundWindow == NULL) - { - MsgBox(L"Failed to detect foreground window!", APPNAME L" Error", MB_OK | MB_ICONERROR); - goto Exit; - } - GetWindowThreadProcessId(ForegroundWindow, &ProcessId); - if (ProcessId == 0) - { - MsgBox(L"Failed to get PID from foreground window! Error code 0x%08lx", APPNAME L" Error", MB_OK | MB_ICONERROR, GetLastError()); - goto Exit; - } - ProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcessId); - if (ProcessHandle == NULL) - { - MsgBox(L"Failed to open process %d! Error 0x%08lx", APPNAME L" Error", MB_OK | MB_ICONERROR, ProcessId, GetLastError()); - goto Exit; - } - NtSuspendProcess(ProcessHandle); - gIsPaused = TRUE; - gPreviouslyPausedProcessId = ProcessId; - DbgPrint(L"Process paused!"); - } } +} -Exit: - if (ProcessSnapshot && ProcessSnapshot != INVALID_HANDLE_VALUE) +void FindForegroundPid(void) { + u32 pid = PidOfForegroundProcess(); + if (pid) addToSet(&gPids, pid); +} + +void TogglePause(void) { + // Iterate through Set of PIDs and pause/unpause as needed + + if (gIsPaused) { - CloseHandle(ProcessSnapshot); + DbgPrint(L"Resuming PIDs..."); + for (size_t i = 0; i < gPids.size; i++) { + u32 p = gPids.elements[i]; + ResumeProcess(p); + } + initializeSet(&gPids); + gIsPaused = false; } - if (ProcessHandle) + else { - CloseHandle(ProcessHandle); + DbgPrint(L"Pausing PIDs..."); + size_t length = gPids.size; + for (size_t i = 0; i < length; i++) { + u32 p = gPids.elements[i]; + PauseProcess(p); + addToSet(&gPids, p); + } + gIsPaused = true; + } +} + + +void HandlePauseKeyPress(void) +{ + // Either we configured it to pause/un-pause a specified process via the registry, + // or we will pause/un-pause the currently in-focus foreground window. + DbgPrint(L"Pause key pressed."); + + if (isSetEmpty(&gPids)) { + DbgPrint(L"Attempting to pause registry configured named processes %s...", gConfig.ProcessNameListToPause); + FindRegistryPids(); + + // If nothing is in the registry, use the foreground window + if (isSetEmpty(&gPids)) { + FindForegroundPid(); + DbgPrint(L"Attempting to pause current foreground window..."); + } + } + + if (!isSetEmpty(&gPids)) { + TogglePause(); } } -void UnpausePreviouslyPausedProcess(void) +// returns 0 on success, -1 on failure +i8 ResumeProcess(u32 Pid) { HANDLE ProcessHandle = NULL; - DbgPrint(L"Pause key pressed. Attempting to un-pause previously paused PID %d.", gPreviouslyPausedProcessId); + DbgPrint(L"Attempting to resume previously paused PID %d.", Pid); - ProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, gPreviouslyPausedProcessId); + ProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, Pid); if (ProcessHandle == NULL) { // Maybe the previously paused process was killed, no longer exists? - MsgBox(L"Failed to open process %d! Error 0x%08lx", APPNAME L" Error", MB_OK | MB_ICONERROR, gPreviouslyPausedProcessId, GetLastError()); + MsgBox(L"Failed to open process %d! Error 0x%08lx", APPNAME L" Error", MB_OK | MB_ICONERROR, Pid, GetLastError()); + return -1; } else { NtResumeProcess(ProcessHandle); - DbgPrint(L"Un-pause successful."); + DbgPrint(L"Resume of %d successful.", Pid); } - gIsPaused = FALSE; - gPreviouslyPausedProcessId = 0; if (ProcessHandle) { CloseHandle(ProcessHandle); } + return 0; } u32 LoadRegistrySettings(void) @@ -537,4 +594,23 @@ LRESULT CALLBACK SysTrayCallback(_In_ HWND Window, _In_ UINT Message, _In_ WPARA } } return(Result); +} + +// Function to trim leading and trailing whitespaces from a wide string +void trimWhitespaces(wchar_t* str) { + wchar_t* end; + + // Trim leading whitespaces + while (iswspace(str)) { // iswspace returns zero (false) if the char is not a whitespace + str++; // move pointer until we find the first whitespace char + } + + // Trim trailing whitespaces + end = str + wcslen(str) - 1; + while (end > str && iswspace(*end)) { + end--; + } + + // Null-terminate the trimmed string + *(end + 1) = L'\0'; } \ No newline at end of file diff --git a/Main.h b/Main.h index 5e43e5f..0610dfb 100644 --- a/Main.h +++ b/Main.h @@ -2,8 +2,7 @@ #pragma warning(disable:4820) // padding in structures -#define VERSION L"1.1.5" -#define APPNAME L"UniversalPauseButton" +#include "Globals.h" // The Lord's data types. typedef unsigned char u8; @@ -32,8 +31,8 @@ typedef struct _CONFIG u32 Debug; u32 TrayIcon; u32 PauseKey; - wchar_t ProcessNameToPause[128]; - wchar_t ProcessNameListToPause[1024]; + const wchar_t ProcessNameToPause[128]; + const wchar_t ProcessNameListToPause[MAX_PROCESSES * 128]; } CONFIG; // Function declarations. @@ -42,4 +41,11 @@ void MsgBox(const wchar_t* Message, const wchar_t* Caption, u32 Flags, ...); void DbgPrint(const wchar_t* Message, ...); LRESULT CALLBACK SysTrayCallback(_In_ HWND Window, _In_ UINT Message, _In_ WPARAM WParam, _In_ LPARAM LParam); void HandlePauseKeyPress(void); -void UnpausePreviouslyPausedProcess(void); \ No newline at end of file +i8 ResumeProcess(u32 Pid); +u32 PidLookup(wchar_t* ProcessName); +i8 PauseProcess(u32 Pid); +u32 PidOfForegroundProcess(void); +void trimWhitespaces(wchar_t* str); +void FindRegistryPids(void); +void FindForegroundPid(void); +void TogglePause(void); diff --git a/UniversalPauseButton.vcxproj b/UniversalPauseButton.vcxproj index 2998abb..60f3ee2 100644 --- a/UniversalPauseButton.vcxproj +++ b/UniversalPauseButton.vcxproj @@ -145,10 +145,13 @@ + + + diff --git a/UniversalPauseButton.vcxproj.filters b/UniversalPauseButton.vcxproj.filters index fc03361..368662d 100644 --- a/UniversalPauseButton.vcxproj.filters +++ b/UniversalPauseButton.vcxproj.filters @@ -21,6 +21,12 @@ Header Files + + Header Files + + + Header Files + @@ -36,5 +42,8 @@ Source Files + + Source Files + \ No newline at end of file From d994b19c8c85cb1b5154f7fce0f6ed31bff57484 Mon Sep 17 00:00:00 2001 From: Doug Lardo Date: Thu, 23 Nov 2023 12:38:01 -0800 Subject: [PATCH 4/9] fix compile warnings --- Main.c | 2 ++ Main.h | 11 ++++++----- set.c | 9 +++++---- set.h | 6 +++--- 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/Main.c b/Main.c index 3db65e7..17ef1b1 100644 --- a/Main.c +++ b/Main.c @@ -4,6 +4,8 @@ // ryanries09@gmail.com // https://github.com/ryanries/UniversalPauseButton/ +#pragma warning(disable: 5045) // Spectre memory vulnerability warnings + #ifndef UNICODE #define UNICODE #endif diff --git a/Main.h b/Main.h index 0610dfb..94039fc 100644 --- a/Main.h +++ b/Main.h @@ -1,6 +1,7 @@ #pragma once #pragma warning(disable:4820) // padding in structures +#pragma warning(disable:4711) // automatic inline expansion #include "Globals.h" @@ -28,11 +29,11 @@ _HungWindowFromGhostWindow HungWindowFromGhostWindow; // Configurable registry settings. typedef struct _CONFIG { - u32 Debug; - u32 TrayIcon; - u32 PauseKey; - const wchar_t ProcessNameToPause[128]; - const wchar_t ProcessNameListToPause[MAX_PROCESSES * 128]; + u32 Debug; + u32 TrayIcon; + u32 PauseKey; + wchar_t ProcessNameToPause[128]; + wchar_t ProcessNameListToPause[MAX_PROCESSES * 128]; } CONFIG; // Function declarations. diff --git a/set.c b/set.c index e9a51dd..f06ba03 100644 --- a/set.c +++ b/set.c @@ -1,4 +1,5 @@ #pragma once +#pragma warning(disable: 5045) // Spectre memory vulnerability warnings #include "set.h" #include @@ -10,7 +11,7 @@ void initializeSet(Set* set) { set->size = 0; } -bool addToSet(Set* set, int element) { +bool addToSet(Set* set, u32 element) { // Check if the element is already in the set for (size_t i = 0; i < set->size; i++) { if (set->elements[i] == element) { @@ -28,7 +29,7 @@ bool addToSet(Set* set, int element) { } } -bool removeFromSet(Set* set, int element) { +bool removeFromSet(Set* set, u32 element) { for (size_t i = 0; i < MAX_PROCESSES; i++) { if (set->elements[i] == element) { set->elements[i] = 0; @@ -43,7 +44,7 @@ bool removeFromSet(Set* set, int element) { return false; // Element is not in the set } -bool isInSet(const Set* set, int element) { +bool isInSet(const Set* set, u32 element) { for (size_t i = 0; i < set->size; i++) { if (set->elements[i] == element) { return true; // Element is in the set @@ -54,7 +55,7 @@ bool isInSet(const Set* set, int element) { void printSet(const Set* set) { printf("Set: "); - for (size_t i = 0; i < set->size; i++) { + for (size_t i = 0; i < set->size; i++) { printf("%ld ", set->elements[i]); } printf("\n"); diff --git a/set.h b/set.h index 5c547f6..cc36ab5 100644 --- a/set.h +++ b/set.h @@ -12,8 +12,8 @@ typedef struct { } Set; void initializeSet(Set* set); -bool addToSet(Set* set, int element); -bool removeFromSet(Set* set, int element); -bool isInSet(const Set* set, int element); +bool addToSet(Set* set, u32 element); +bool removeFromSet(Set* set, u32 element); +bool isInSet(const Set* set, u32 element); void printSet(const Set* set); bool isSetEmpty(const Set* set); From afe5295f686b62cf2b3ce51e8471d225f1028053 Mon Sep 17 00:00:00 2001 From: Doug Lardo Date: Thu, 23 Nov 2023 13:45:55 -0800 Subject: [PATCH 5/9] ShowDebug Console --- Main.c | 43 ++++++++++++++++++++++--------------------- Main.h | 3 ++- 2 files changed, 24 insertions(+), 22 deletions(-) diff --git a/Main.c b/Main.c index 17ef1b1..10fb111 100644 --- a/Main.c +++ b/Main.c @@ -256,7 +256,7 @@ void FindRegistryPids(void) { wchar_t* token = wcstok_s(myCopy, delim, &context); // loop through all process names while (token != NULL) { - trimWhitespaces(token); + TrimWhitespaces(token); pid = PidLookup(token); if (pid) addToSet(&gPids, pid); // Get the next token @@ -344,6 +344,22 @@ i8 ResumeProcess(u32 Pid) return 0; } +void ShowDebugConsole(void) { + if (AllocConsole() == FALSE) + { + MsgBox(L"Failed to allocate debug console!\nError: 0x%08lx", L"Error", MB_OK | MB_ICONERROR, GetLastError()); + return; + } + gDbgConsole = GetStdHandle(STD_OUTPUT_HANDLE); + if (gDbgConsole == INVALID_HANDLE_VALUE) + { + MsgBox(L"Failed to get stdout debug console handle!\nError: 0x%08lx", L"Error", MB_OK | MB_ICONERROR, GetLastError()); + return; + } + DbgPrint(L"%s version %s.", APPNAME, VERSION); + DbgPrint(L"To disable this debug console, delete the 'Debug' reg setting at HKCU\\SOFTWARE\\%s", APPNAME); +} + u32 LoadRegistrySettings(void) { u32 Result = ERROR_SUCCESS; @@ -422,7 +438,7 @@ u32 LoadRegistrySettings(void) Settings[s].Name, RRF_RT_DWORD, NULL, - Settings[s].Destination, + Settings[s].Destination, // Registry Value is stored here &BytesRead); if (Result != ERROR_SUCCESS) { @@ -450,22 +466,7 @@ u32 LoadRegistrySettings(void) // This is so the debug console can report on the other registry settings. if (Settings[s].Destination == &gConfig.Debug) { - if (gConfig.Debug) - { - if (AllocConsole() == FALSE) - { - MsgBox(L"Failed to allocate debug console!\nError: 0x%08lx", L"Error", MB_OK | MB_ICONERROR, GetLastError()); - goto Exit; - } - gDbgConsole = GetStdHandle(STD_OUTPUT_HANDLE); - if (gDbgConsole == INVALID_HANDLE_VALUE) - { - MsgBox(L"Failed to get stdout debug console handle!\nError: 0x%08lx", L"Error", MB_OK | MB_ICONERROR, GetLastError()); - goto Exit; - } - DbgPrint(L"%s version %s.", APPNAME, VERSION); - DbgPrint(L"To disable this debug console, delete the 'Debug' reg setting at HKCU\\SOFTWARE\\%s", APPNAME); - } + if (gConfig.Debug) ShowDebugConsole(); } DbgPrint(L"Using value 0n%d (0x%x) for registry setting '%s'.", *(u32*)Settings[s].Destination, *(u32*)Settings[s].Destination, Settings[s].Name); @@ -481,7 +482,7 @@ u32 LoadRegistrySettings(void) Settings[s].Name, RRF_RT_REG_SZ, NULL, - Settings[s].Destination, + Settings[s].Destination, // Registry Value is stored here &BytesRead); if (Result != ERROR_SUCCESS) { @@ -599,11 +600,11 @@ LRESULT CALLBACK SysTrayCallback(_In_ HWND Window, _In_ UINT Message, _In_ WPARA } // Function to trim leading and trailing whitespaces from a wide string -void trimWhitespaces(wchar_t* str) { +void TrimWhitespaces(wchar_t* str) { wchar_t* end; // Trim leading whitespaces - while (iswspace(str)) { // iswspace returns zero (false) if the char is not a whitespace + while (iswspace(*str)) { // iswspace returns zero (false) if the char is not a whitespace str++; // move pointer until we find the first whitespace char } diff --git a/Main.h b/Main.h index 94039fc..15e09fd 100644 --- a/Main.h +++ b/Main.h @@ -46,7 +46,8 @@ i8 ResumeProcess(u32 Pid); u32 PidLookup(wchar_t* ProcessName); i8 PauseProcess(u32 Pid); u32 PidOfForegroundProcess(void); -void trimWhitespaces(wchar_t* str); +void TrimWhitespaces(wchar_t* str); void FindRegistryPids(void); void FindForegroundPid(void); void TogglePause(void); +void ShowDebugConsole(void); From 888e1588be4664bbbfbdaa53be94e0d2b07ca6c2 Mon Sep 17 00:00:00 2001 From: Doug Lardo Date: Thu, 23 Nov 2023 14:35:35 -0800 Subject: [PATCH 6/9] process lookup debug messages --- Main.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Main.c b/Main.c index 10fb111..684b55f 100644 --- a/Main.c +++ b/Main.c @@ -258,6 +258,7 @@ void FindRegistryPids(void) { while (token != NULL) { TrimWhitespaces(token); pid = PidLookup(token); + DbgPrint(L"Found \"%s\" via the windows registry settings", token); if (pid) addToSet(&gPids, pid); // Get the next token token = wcstok_s(NULL, delim, &context); @@ -604,8 +605,8 @@ void TrimWhitespaces(wchar_t* str) { wchar_t* end; // Trim leading whitespaces - while (iswspace(*str)) { // iswspace returns zero (false) if the char is not a whitespace - str++; // move pointer until we find the first whitespace char + while (iswspace(*str)) { // iswspace returns zero (false) if the char is not a whitespace + str++; // move pointer until we find the first whitespace char } // Trim trailing whitespaces From af4fd51c866c5d129b95839ec43421be654108bf Mon Sep 17 00:00:00 2001 From: Doug Lardo Date: Thu, 23 Nov 2023 22:24:12 -0800 Subject: [PATCH 7/9] ProcessNameListToPause docs --- README.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index cf670e2..309b0be 100644 --- a/README.md +++ b/README.md @@ -77,7 +77,19 @@ If TrayIcon is enabled, which it is by default, there will be a small system tra If ProcessNameToPause is defined, then the app will only pause that process by name, regardless of foreground window. E.g., notepad.exe or mycoolgame.exe. Include the .exe file extension. It expects process name, not Window text. WARNING: In case there are multiple processes with the same name, only the first instance found will be paused. Please don't try dumb things like trying to pause svchost.exe or lsass.exe or csrss.exe... +**ProcessNameListToPause** + + Type: REG_SZ (String) + + Default: "" (Empty string) + + Minimum: n/a + + Maximum: n/a + + +If ProcessNameListToPause is defined, then the app will pause and resume all of the processes listed at the same time. Follow the same guidelines as ProcessNameToPause. Seperate each process by a comma. E.g., "VRising.exe, VRisingServer.exe, Spotify.exe". Note: You only need to use either ProcessNameToPause or ProcessNameListToPause, but both can be used simultaneously. As always, please try it out, and let me know if you find any bugs or have any feature requests. -Thanks! \ No newline at end of file +Thanks! From 4f149f3407236889ce20eb723f9dff8d538d15a3 Mon Sep 17 00:00:00 2001 From: Doug Lardo Date: Fri, 24 Nov 2023 17:27:48 -0800 Subject: [PATCH 8/9] CloseHandle Fixes --- Main.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/Main.c b/Main.c index 684b55f..b10034a 100644 --- a/Main.c +++ b/Main.c @@ -208,6 +208,7 @@ i8 PauseProcess(u32 Pid) { } NtSuspendProcess(ProcessHandle); + CloseHandle(ProcessHandle); gIsPaused = TRUE; addToSet(&gPids, Pid); DbgPrint(L"Process %d paused!", Pid); @@ -228,16 +229,15 @@ u32 PidOfForegroundProcess(void) { MsgBox(L"Failed to get PID from foreground window! Error code 0x%08lx", APPNAME L" Error", MB_OK | MB_ICONERROR, GetLastError()); return 0; } + HANDLE ProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcessId); if (ProcessHandle == NULL) { MsgBox(L"Failed to open process %d! Error 0x%08lx", APPNAME L" Error", MB_OK | MB_ICONERROR, ProcessId, GetLastError()); - return 0; - } - else - { CloseHandle(ProcessHandle); + return 0; } + CloseHandle(ProcessHandle); return ProcessId; } @@ -333,15 +333,10 @@ i8 ResumeProcess(u32 Pid) MsgBox(L"Failed to open process %d! Error 0x%08lx", APPNAME L" Error", MB_OK | MB_ICONERROR, Pid, GetLastError()); return -1; } - else - { - NtResumeProcess(ProcessHandle); - DbgPrint(L"Resume of %d successful.", Pid); - } - if (ProcessHandle) - { - CloseHandle(ProcessHandle); - } + + NtResumeProcess(ProcessHandle); + CloseHandle(ProcessHandle); + DbgPrint(L"Resume of %d successful.", Pid); return 0; } From 1fd36626f0c5194753b868d76faa5e8647859851 Mon Sep 17 00:00:00 2001 From: Doug Lardo Date: Sat, 25 Nov 2023 01:39:28 -0800 Subject: [PATCH 9/9] Suspend Result Code --- Main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Main.c b/Main.c index b10034a..d947648 100644 --- a/Main.c +++ b/Main.c @@ -207,7 +207,8 @@ i8 PauseProcess(u32 Pid) { return -1; } - NtSuspendProcess(ProcessHandle); + i32 SuspendResult = NtSuspendProcess(ProcessHandle); + DbgPrint(L"NtSuspendProcess() Result Code: %d", SuspendResult); CloseHandle(ProcessHandle); gIsPaused = TRUE; addToSet(&gPids, Pid);