From 91be332b9d98e7d3138525721350267f6849a8e3 Mon Sep 17 00:00:00 2001 From: supervoidcoder Date: Tue, 6 Jan 2026 22:05:11 -0500 Subject: [PATCH 1/7] feat: finally made tree just like witr (this unironically took me 3 hours) --- .gitignore | 7 ++++ main.cpp | 99 +++++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 83 insertions(+), 23 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2406cdc --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +main.exe +win-witr.exe +main.obj +win-witr.obj +main.pdb +win-witr.pdb +vc140.pdb \ No newline at end of file diff --git a/main.cpp b/main.cpp index 1d1ed0a..47dcd31 100644 --- a/main.cpp +++ b/main.cpp @@ -15,6 +15,8 @@ #include #include #include +#include +#include #define windows_time_to_unix_epoch(x) ((x) - 116444736000000000LL) / 10000000LL // The above macro converts Windows FILETIME to Unix epoch time in seconds. @@ -197,58 +199,108 @@ std::string GetReadableFileTime(DWORD pid) { } -void PrintAncestry(DWORD pid, int depth = 0) { +void PrintAncestry(DWORD pid) { /* -TODO: This tree is flipped. The output should be like this, as shown in the original witr: +~~~~~~~~~~~~~TODO: This tree is flipped. The output should be like this, as shown in the original witr: systemd (pid 1) └─ PM2 v5.3.1: God (pid 1481580) └─ python (pid 1482060) +UPDATE: This is done now!! */ - if (pid == 0 || pid == 4) return; - - HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); - if (hSnapshot == INVALID_HANDLE_VALUE) return; + + PROCESSENTRY32 pe32{}; pe32.dwSize = sizeof(PROCESSENTRY32); DWORD parentPid = 0; std::string exeName = "Unknown/Dead Process"; + std::vector exeNames; + std::vector exeTimes; // sorry for the crap code but idk how to make multidimensional arrays yet 😭😭😭 + std::vector pidNames; // hopefully the compiler can fix it + std::vector parentPids; bool found = false; - + while (pid != 0 && pid != 4) { + HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (hSnapshot == INVALID_HANDLE_VALUE) return; if (Process32First(hSnapshot, &pe32)) { do { if (pe32.th32ProcessID == pid) { - parentPid = pe32.th32ParentProcessID; - exeName = WideToString(pe32.szExeFile); + // Without comments, this literally looks like alien gibberish so lemme explain + parentPid = pe32.th32ParentProcessID; // this is the parent process pid + ULONGLONG creationTime = GetProcessCreationTime(pid); // this stores the creation time of the CURRENT pid (not parent) + exeTimes.emplace_back(creationTime); // immediately stores the above to the list + exeName = WideToString(pe32.szExeFile); //this stores the NAME of the current pid, converted to something that the terminal won't choke and die on + exeNames.emplace_back(exeName); // this adds the above to the name list + pidNames.emplace_back(pid); // this adds the current pid (no need to store in var as already passed into if) + + DWORD parentPid = pe32.th32ParentProcessID; // this gets the pid of the PARENT pid (if there hopefully is one) + parentPids.emplace_back(pe32.th32ParentProcessID); // adds above to list + ULONGLONG parentTime = GetProcessCreationTime(parentPid); // this gets the creation time of that one + + if (parentPid == 0 || parentPid == 4 || parentTime == 0 || parentTime >= creationTime) { + // we can't be sure if the parent actually exists and windows isn't lying to us, + // so always double check + pid = 0; + } else { + + pid = parentPid; + } found = true; break; } } while (Process32Next(hSnapshot, &pe32)); + } CloseHandle(hSnapshot); + if (!found) break; + } - for (int i = 0; i < depth; ++i) std::cout << " "; - std::cout << exeName << " (PID " << pid << ")" << std::endl; - - if (found && parentPid != 0 && parentPid != pid) { - // VERIFICATION STEP: - ULONGLONG childTime = GetProcessCreationTime(pid); - ULONGLONG parentTime = GetProcessCreationTime(parentPid); + //phew thankfully we're done with that mess + // now we need to reverse all the vector lists we made so + // that the ancestry tree is correctly diisplayed from root to children like witr + // in c++20 there is a new way to reverse called ranges or smth but i won't use that + std::reverse(exeNames.begin(), exeNames.end()); + std::reverse(exeTimes.begin(), exeTimes.end()); + std::reverse(pidNames.begin(), pidNames.end()); + std::reverse(parentPids.begin(), parentPids.end()); + // now get the size of one of the lists to know how many we got (they should all be the same length) + size_t nameSize = exeNames.size(); + + for (size_t i = 0; i < nameSize; i++ ){ // size_t is an unsigned integer designed to be ridiculously big to handle monstrosities, + // idk just in case some psycho has a gazillion nested procs + + // surprise we have nested for loops + for (size_t j = 0; j <= i; j++) { + std::cout << " "; // this adds indentation + } + if (i > 0) { + + std::cout << "\u2514\u2500 "; // it's the little thingy thing └─ unicode from witr but escaped s + } + std::cout << exeNames[i] << " (PID " << pidNames[i] << ")" << std::endl; - // If parentTime is 0, the parent is dead. - // If parentTime > childTime, the parent is an impostor among us (recycled PID). - if (parentTime != 0 && parentTime < childTime) { - PrintAncestry(parentPid, depth + 1); - } else { - for (int i = 0; i < depth + 1; ++i) std::cout << " "; - std::cout << "[Parent Process Exited]" << std::endl; + } + + if (nameSize > 0) { + DWORD lastParentPid = parentPids.back(); + ULONGLONG lastParentTime = GetProcessCreationTime(lastParentPid); + ULONGLONG lastChildTime = exeTimes.back(); + + if (lastParentPid != 0 && lastParentPid != 4 && + (lastParentTime == 0 || lastParentTime >= lastChildTime)) { + for (size_t j = 0; j < nameSize; j++) { + std::cout << " "; } + std::cout << "└─ [Parent Process Exited]" << std::endl; } } + } + + @@ -349,6 +401,7 @@ int findMyProc(const char *procname) { int main(int argc, char* argv[]) { + SetConsoleOutputCP(CP_UTF8); for (int i = 0; i < argc; ++i) { std::string arg = argv[i]; From aae6b5986f50a41232dc6c9f0a5d67fda9a9ff54 Mon Sep 17 00:00:00 2001 From: supervoidcoder Date: Tue, 6 Jan 2026 22:15:06 -0500 Subject: [PATCH 2/7] fix: code review issues --- main.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/main.cpp b/main.cpp index 47dcd31..a7a80f2 100644 --- a/main.cpp +++ b/main.cpp @@ -15,7 +15,6 @@ #include #include #include -#include #include #define windows_time_to_unix_epoch(x) ((x) - 116444736000000000LL) / 10000000LL @@ -217,6 +216,8 @@ UPDATE: This is done now!! PROCESSENTRY32 pe32{}; pe32.dwSize = sizeof(PROCESSENTRY32); DWORD parentPid = 0; + HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (hSnapshot == INVALID_HANDLE_VALUE) return; std::string exeName = "Unknown/Dead Process"; std::vector exeNames; std::vector exeTimes; // sorry for the crap code but idk how to make multidimensional arrays yet 😭😭😭 @@ -224,8 +225,7 @@ UPDATE: This is done now!! std::vector parentPids; bool found = false; while (pid != 0 && pid != 4) { - HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); - if (hSnapshot == INVALID_HANDLE_VALUE) return; + if (Process32First(hSnapshot, &pe32)) { do { if (pe32.th32ProcessID == pid) { @@ -237,7 +237,7 @@ UPDATE: This is done now!! exeNames.emplace_back(exeName); // this adds the above to the name list pidNames.emplace_back(pid); // this adds the current pid (no need to store in var as already passed into if) - DWORD parentPid = pe32.th32ParentProcessID; // this gets the pid of the PARENT pid (if there hopefully is one) + parentPid = pe32.th32ParentProcessID; // this gets the pid of the PARENT pid (if there hopefully is one) parentPids.emplace_back(pe32.th32ParentProcessID); // adds above to list ULONGLONG parentTime = GetProcessCreationTime(parentPid); // this gets the creation time of that one From 001cc435ccf8c71128396ed235ef7c5bf55ccc55 Mon Sep 17 00:00:00 2001 From: supervoidcoder Date: Tue, 6 Jan 2026 22:19:42 -0500 Subject: [PATCH 3/7] fix: close handle right --- main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main.cpp b/main.cpp index a7a80f2..68e2939 100644 --- a/main.cpp +++ b/main.cpp @@ -255,10 +255,10 @@ UPDATE: This is done now!! } while (Process32Next(hSnapshot, &pe32)); } - CloseHandle(hSnapshot); + if (!found) break; } - +CloseHandle(hSnapshot); //phew thankfully we're done with that mess // now we need to reverse all the vector lists we made so // that the ancestry tree is correctly diisplayed from root to children like witr From b09017ef283783a411d8c6b77084433ddfd76807 Mon Sep 17 00:00:00 2001 From: supervoidcoder Date: Tue, 6 Jan 2026 22:20:44 -0500 Subject: [PATCH 4/7] fix: reset found every iteration --- main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.cpp b/main.cpp index 68e2939..f99d67c 100644 --- a/main.cpp +++ b/main.cpp @@ -225,7 +225,7 @@ UPDATE: This is done now!! std::vector parentPids; bool found = false; while (pid != 0 && pid != 4) { - + found = false; if (Process32First(hSnapshot, &pe32)) { do { if (pe32.th32ProcessID == pid) { From d82dc322418004ca42e9cc77ec401219fa68d6af Mon Sep 17 00:00:00 2001 From: supervoidcoder <88671013+supervoidcoder@users.noreply.github.com> Date: Tue, 6 Jan 2026 22:26:16 -0500 Subject: [PATCH 5/7] Update main.cpp Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.cpp b/main.cpp index f99d67c..5a50eb8 100644 --- a/main.cpp +++ b/main.cpp @@ -274,7 +274,7 @@ CloseHandle(hSnapshot); // idk just in case some psycho has a gazillion nested procs // surprise we have nested for loops - for (size_t j = 0; j <= i; j++) { + for (size_t j = 0; j < i; j++) { std::cout << " "; // this adds indentation } if (i > 0) { From 211f69724624d9385c3eccbaa643f3a4a29a00e0 Mon Sep 17 00:00:00 2001 From: supervoidcoder Date: Tue, 6 Jan 2026 22:48:32 -0500 Subject: [PATCH 6/7] fix: Remove redundant assignment of parentPid --- main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.cpp b/main.cpp index 5a50eb8..41f8944 100644 --- a/main.cpp +++ b/main.cpp @@ -230,7 +230,7 @@ UPDATE: This is done now!! do { if (pe32.th32ProcessID == pid) { // Without comments, this literally looks like alien gibberish so lemme explain - parentPid = pe32.th32ParentProcessID; // this is the parent process pid + ULONGLONG creationTime = GetProcessCreationTime(pid); // this stores the creation time of the CURRENT pid (not parent) exeTimes.emplace_back(creationTime); // immediately stores the above to the list exeName = WideToString(pe32.szExeFile); //this stores the NAME of the current pid, converted to something that the terminal won't choke and die on From dd92899385be32cfe69e25e9e1c4cf4c104a8c83 Mon Sep 17 00:00:00 2001 From: supervoidcoder Date: Tue, 6 Jan 2026 23:12:41 -0500 Subject: [PATCH 7/7] fix: clang --- .github/workflows/clang-lint.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/clang-lint.yml b/.github/workflows/clang-lint.yml index f123770..567627c 100644 --- a/.github/workflows/clang-lint.yml +++ b/.github/workflows/clang-lint.yml @@ -9,12 +9,12 @@ jobs: - uses: actions/checkout@v4 - name: clang-tidy review - uses: ZedThree/clang-tidy-review@v0.16.2 + uses: ZedThree/clang-tidy-review@v0.23.0 with: build_dir: . config_file: '' continue-on-error: true - name: Upload review comments - uses: ZedThree/clang-tidy-review/upload@v0.16.2 + uses: ZedThree/clang-tidy-review/upload@v0.23.0 continue-on-error: true \ No newline at end of file