feat: add all flag [wip] - #93
Conversation
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
supervoidcoder
commented
Mar 3, 2026
@coderabbitai what do you think of what i'm gonna do for this pr |
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: Length of output: 12710
Main Issue: Code Duplication 🔄Right now, you've got the entire Questions 🤔Before going further, what's the actual difference you want between normal mode and
Suggested Approaches 💡Once you know what should differ, here are some better patterns: Option 1: Extract the differences voidPIDinspect(...) {
// Common setup code hereif (stats.all) {
// Only the code that's DIFFERENT for -a modeDisplayDetailedInfo(...);
} else {
// Only the code that's DIFFERENT for normal modeDisplayBasicInfo(...);
}
// Common code continues here
}Option 2: Use a flag to control specific behaviors voidPIDinspect(...) {
// Single implementation// Use stats.all checks only where behavior differsif (stats.all) {
// Show extra detail here
}
// Rest of the code runs for both modes
}Let me know what you're trying to accomplish with the 🧠 Learnings used |
supervoidcoder
commented
Mar 3, 2026
@coderabbitai yeah i know because i literally just started and made a placeholder, look at the entry in the help menu in int main... |
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: Length of output: 1689
So what kind of additional details are you thinking about showing with
Or something else entirely? Once you know what extra info you want, we can figure out the cleanest way to structure it without the duplication! 🚀 🧠 Learnings used |
supervoidcoder
commented
Mar 3, 2026
all of it. EVERY POSSIBLE INFORMATION we can possibly get from a process. this is because I wanted win-witr to say a lot omre info without sacrificing our runtime speed (which is usually less than 20 ms) and doing this would make it over a second so i'm separating it into an -all flag so i can just go all in iinstead |
Tip For best results, initiate chat on the files or code changes.
Comprehensive Process Information Categories 📊Here's everything you can realistically extract from a Windows process: 1. Memory Details (Beyond current Working Set)
2. CPU & Timing
3. Thread Information
4. Handles (You already planned this!)
5. Modules/DLLs
6. I/O Statistics
7. Security & Identity
8. Environment Variables
9. Window Information (if GUI)
10. Network Connections
11. Job Object Membership
12. GDI/USER Object Counts
Suggested Clean Architecture 🏗️voidPIDinspect(...) {
// === Fast Default Path (keep under 20ms) ===// Current essential info gathering// - Basic process info// - Command line// - Parent/children// - Handle count (fast)// - Basic memory/CPUif (!stats.all) {
DisplayStandardOutput(...);
return; // Early exit for fast path
}
// === Detailed Mode (can take 1+ seconds) ===DisplayStandardOutput(...); // Show the standard info first// Then add sections for additional details
std::cout << "\n" << SECTION_SEPARATOR << "\n";
std::cout << MAGENTA << "=== DETAILED INFORMATION ===" << RESET << "\n\n";
DisplayDetailedMemory(hProcess, pid);
DisplayThreadDetails(pid);
DisplayHandleDetails(hProcess, pid); // Use your existing opt-in code from `#77`DisplayModuleDetails(pid);
DisplayIOStatistics(hProcess);
DisplaySecurityInfo(hProcess);
DisplayEnvironmentVars(hProcess, pbi); // Reuse PEB readingDisplayWindowInfo(pid);
DisplayNetworkConnections(pid);
DisplayJobInfo(hProcess);
DisplayGDIUserObjects(hProcess);
}Each Performance Note 🚀The beauty of this approach: your default mode stays benchmark-winning fast, but Want me to help you implement any specific category first? I'd suggest starting with the easier ones like I/O Stats (single API call) before tackling the complex ones like handle enumeration. 💪 ✏️ Learnings added
🧠 Learnings used |
supervoidcoder
commented
Mar 3, 2026
@coderabbitai nah you don't need to help me, i can do this 😎 but uh |
Tip For best results, initiate chat on the files or code changes.
Thread Count: Windows 7 is Fine ✅Yes, Windows 7 (and even much older systems) can easily handle 8 threads. Windows has supported thousands of concurrent threads since the NT kernel days. Creating 8 threads is no problem at all, even on ancient hardware. BUT: Dynamic Sizing is Better 🎯Instead of hardcoding 8 threads, use the hardware's actual core count: // Get logical processor count (includes hyperthreading)unsignedint threadCount = std::thread::hardware_concurrency();
// Or use Win32 API directly:SYSTEM_INFO sysInfo;
GetSystemInfo(&sysInfo);
unsignedint threadCount = sysInfo.dwNumberOfProcessors;
// Optional: Cap it at a reasonable max (e.g., 16)
threadCount = std::min(threadCount, 16u);This way:
|
supervoidcoder
commented
Mar 3, 2026
@coderabbitai i was thinking just for the handles aand the cpu time. cpu % requires tracking cpu time for a bit for sampling so I can offload that to a thread. for handles, I can duplicate all the handles into my process and then send 7 threads to query each namee. this way my program won't hang or crash if a nt query object fails and it can keep querying names to actually get file handle names like handles.exe from sysinternals |
Tip For best results, initiate chat on the files or code changes.
CPU % Sampling Thread ✅Perfect use case! Since calculating CPU % requires: // Sample at T0GetProcessTimes(hProcess, ..., &userTime1, &kernelTime1);
Sleep(1000); // or 500ms// Sample at T1GetProcessTimes(hProcess, ..., &userTime2, &kernelTime2);
// Calculate: (userTime2-userTime1 + kernelTime2-kernelTime1) / elapsedOffloading this to a thread means your UI doesn't freeze during the 1-second sampling window. Great choice! Handle Duplication + Parallel Querying 🎯This is the right approach! Here's why: ✅ Why It Works:
|
supervoidcoder
commented
Mar 3, 2026
@coderabbitai well looky here what did i just find https://forums.codeguru.com/showthread.php?423112-RESOLVED-W2K-How-to-get-process-handles-details #pragma comment(linker, "/opt:nowin98")
#pragma comment(lib, "psapi.lib")
#pragma comment(lib, "ws2_32.lib")
#pragma comment(lib, "shlwapi.lib")
#define_WIN32_WINNT 0x0501
#include<winsock2.h>#include<windows.h>#include<stdio.h>#include<psapi.h>#include<shlwapi.h>// -------------------------------------------------------------------------typedefLONGNTSTATUS;
typedefstruct_IO_STATUS_BLOCK {
union {
NTSTATUSStatus;
PVOIDPointer;
};
ULONG_PTRInformation;
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
typedefvoid (WINAPI*PIO_APC_ROUTINE)(PVOID, PIO_STATUS_BLOCK, DWORD);
typedefLONGTDI_STATUS;
typedefPVOIDCONNECTION_CONTEXT; // connection contexttypedefstruct_TDI_REQUEST {
union {
HANDLEAddressHandle;
CONNECTION_CONTEXTConnectionContext;
HANDLEControlChannel;
} Handle;
PVOIDRequestNotifyObject;
PVOIDRequestContext;
TDI_STATUSTdiStatus;
} TDI_REQUEST, *PTDI_REQUEST;
typedefstruct_TDI_CONNECTION_INFORMATION {
LONGUserDataLength; // length of user data bufferPVOIDUserData; // pointer to user data bufferLONGOptionsLength; // length of following bufferPVOIDOptions; // pointer to buffer containing optionsLONGRemoteAddressLength; // length of following bufferPVOIDRemoteAddress; // buffer containing the remote address
} TDI_CONNECTION_INFORMATION, *PTDI_CONNECTION_INFORMATION;
typedefstruct_TDI_REQUEST_QUERY_INFORMATION {
TDI_REQUESTRequest;
ULONGQueryType; // class of information to be queried.PTDI_CONNECTION_INFORMATIONRequestConnectionInformation;
} TDI_REQUEST_QUERY_INFORMATION, *PTDI_REQUEST_QUERY_INFORMATION;
#defineTDI_QUERY_ADDRESS_INFO 0x00000003
#defineIOCTL_TDI_QUERY_INFORMATION CTL_CODE(FILE_DEVICE_TRANSPORT, 4, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
typedefVOID*POBJECT;
typedefstruct_SYSTEM_HANDLE {
ULONGuIdProcess;
UCHARObjectType; // OB_TYPE_* (OB_TYPE_TYPE, etc.)UCHARFlags; // HANDLE_FLAG_* (HANDLE_FLAG_INHERIT, etc.)USHORTHandle;
POBJECTpObject;
ACCESS_MASKGrantedAccess;
} SYSTEM_HANDLE, *PSYSTEM_HANDLE;
typedefstruct_SYSTEM_HANDLE_INFORMATION {
ULONGuCount;
SYSTEM_HANDLEHandles[1];
} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;
typedefstruct_UNICODE_STRING {
USHORTLength;
USHORTMaximumLength;
PWSTRBuffer;
} UNICODE_STRING;
typedefUNICODE_STRING*PUNICODE_STRING;
typedefconstUNICODE_STRING*PCUNICODE_STRING;
typedefUNICODE_STRINGOBJECT_NAME_INFORMATION;
typedefUNICODE_STRING*POBJECT_NAME_INFORMATION;
#defineSystemHandleInformation 16
typedefenum_OBJECT_INFORMATION_CLASS{
ObjectBasicInformation,
ObjectNameInformation,
ObjectTypeInformation,
ObjectAllTypesInformation,
ObjectHandleInformation
} OBJECT_INFORMATION_CLASS;
#defineSTATUS_SUCCESS ((NTSTATUS)0x00000000L)
#defineSTATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L)
#defineSTATUS_BUFFER_OVERFLOW ((NTSTATUS)0x80000005L)
// -------------------------------------------------------------------------typedefNTSTATUS (WINAPI*tNTQSI)(DWORDSystemInformationClass, PVOIDSystemInformation,
DWORDSystemInformationLength, PDWORDReturnLength);
typedefNTSTATUS (WINAPI*tNTQO)(HANDLEObjectHandle, OBJECT_INFORMATION_CLASSObjectInformationClass, PVOIDObjectInformation,
DWORDLength, PDWORDResultLength);
typedefNTSTATUS (WINAPI*tNTDIOCF)(HANDLEFileHandle, HANDLEEvent, PIO_APC_ROUTINEApcRoutine, PVOIDApcContext,
PIO_STATUS_BLOCKIoStatusBlock, DWORDIoControlCode,
PVOIDInputBuffer, DWORDInputBufferLength,
PVOIDOutputBuffer, DWORDOutputBufferLength);
voidEnableDebugPrivilege()
{
HANDLEhToken;
TOKEN_PRIVILEGEStokenPriv;
LUIDluidDebug;
if(OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken) != FALSE) {
if(LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luidDebug) != FALSE)
{
tokenPriv.PrivilegeCount=1;
tokenPriv.Privileges[0].Luid=luidDebug;
tokenPriv.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken, FALSE, &tokenPriv, sizeof(tokenPriv), NULL, NULL);
}
}
}
LPWSTRGetObjectInfo(HANDLEhObject, OBJECT_INFORMATION_CLASSobjInfoClass)
{
LPWSTRlpwsReturn=NULL;
tNTQOpNTQO= (tNTQO)GetProcAddress(GetModuleHandle("NTDLL.DLL"), "NtQueryObject");
if(pNTQO!=NULL){
DWORDdwSize=sizeof(OBJECT_NAME_INFORMATION);
POBJECT_NAME_INFORMATIONpObjectInfo= (POBJECT_NAME_INFORMATION) newBYTE[dwSize];
NTSTATUSntReturn=pNTQO(hObject, objInfoClass, pObjectInfo, dwSize, &dwSize);
if((ntReturn==STATUS_BUFFER_OVERFLOW) || (ntReturn==STATUS_INFO_LENGTH_MISMATCH)){
deletepObjectInfo;
pObjectInfo= (POBJECT_NAME_INFORMATION) newBYTE[dwSize];
ntReturn=pNTQO(hObject, objInfoClass, pObjectInfo, dwSize, &dwSize);
}
if((ntReturn >= STATUS_SUCCESS) && (pObjectInfo->Buffer!=NULL))
{
lpwsReturn= (LPWSTR) newBYTE[pObjectInfo->Length+sizeof(WCHAR)];
ZeroMemory(lpwsReturn, pObjectInfo->Length+sizeof(WCHAR));
CopyMemory(lpwsReturn, pObjectInfo->Buffer, pObjectInfo->Length);
}
deletepObjectInfo;
}
returnlpwsReturn;
}
voidOutputConnectionDetails(HANDLEhObject)
{
tNTDIOCFpNTDIOCF= (tNTDIOCF)GetProcAddress(GetModuleHandle("NTDLL.DLL"), "NtDeviceIoControlFile");
if(pNTDIOCF!=NULL){
IO_STATUS_BLOCKIoStatusBlock;
TDI_REQUEST_QUERY_INFORMATIONtdiRequestAddress= {{0}, TDI_QUERY_ADDRESS_INFO};
BYTEtdiAddress[128];
HANDLEhEvent2=CreateEvent(NULL, TRUE, FALSE, NULL);
NTSTATUSntReturn2=pNTDIOCF(hObject, hEvent2, NULL, NULL, &IoStatusBlock, IOCTL_TDI_QUERY_INFORMATION,
&tdiRequestAddress, sizeof(tdiRequestAddress), &tdiAddress, sizeof(tdiAddress));
if(hEvent2) CloseHandle(hEvent2);
if(ntReturn2==STATUS_SUCCESS){
structin_addr*pAddr= (structin_addr*)&tdiAddress[14];
printf("@%s:%d", inet_ntoa(*pAddr), ntohs(*(PUSHORT)&tdiAddress[12]));
}
}
printf("\n");
}
intmain(intargc, char*argv[])
{
printf("TCP/UDP Handle List - by Napalm\n");
printf("===============================\n\n");
EnableDebugPrivilege();
tNTQSIpNTQSI= (tNTQSI)GetProcAddress(GetModuleHandle("NTDLL.DLL"), "NtQuerySystemInformation");
if(pNTQSI!=NULL){
DWORDdwSize=sizeof(SYSTEM_HANDLE_INFORMATION);
PSYSTEM_HANDLE_INFORMATIONpHandleInfo= (PSYSTEM_HANDLE_INFORMATION) newBYTE[dwSize];
NTSTATUSntReturn=pNTQSI(SystemHandleInformation, pHandleInfo, dwSize, &dwSize);
if(ntReturn==STATUS_INFO_LENGTH_MISMATCH){
deletepHandleInfo;
pHandleInfo= (PSYSTEM_HANDLE_INFORMATION) newBYTE[dwSize];
ntReturn=pNTQSI(SystemHandleInformation, pHandleInfo, dwSize, &dwSize);
}
if(ntReturn==STATUS_SUCCESS){
printf(" Found %d Handles.\n\n", pHandleInfo->uCount);
printf(" PID\tHandle\t%-16s%-18sHandle Name\n", "Type", "Process Name");
for(DWORDdwIdx=0; dwIdx<pHandleInfo->uCount; dwIdx++)
{
HANDLEhProcess=OpenProcess(PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
FALSE, pHandleInfo->Handles[dwIdx].uIdProcess);
if(hProcess!=INVALID_HANDLE_VALUE)
{
HANDLEhObject=NULL;
if(DuplicateHandle(hProcess, (HANDLE)pHandleInfo->Handles[dwIdx].Handle,
GetCurrentProcess(), &hObject, STANDARD_RIGHTS_REQUIRED, FALSE, 0) != FALSE)
{
LPWSTRlpwsName=GetObjectInfo(hObject, ObjectNameInformation);
if(lpwsName!=NULL){
LPWSTRlpwsType=GetObjectInfo(hObject, ObjectTypeInformation);
LPSTRlpszProcess=newCHAR[MAX_PATH];
ZeroMemory(lpszProcess, MAX_PATH);
GetModuleFileNameEx(hProcess, NULL, lpszProcess, MAX_PATH);
printf("%5d\t%6d\t%-16ws%-18s%ws",
pHandleInfo->Handles[dwIdx].uIdProcess, pHandleInfo->Handles[dwIdx].Handle, lpwsType,
((lstrlen(lpszProcess) >0)?PathFindFileName(lpszProcess):"[System]"), lpwsName);
if(!wcscmp(lpwsName, L"\\Device\\Tcp") || !wcscmp(lpwsName, L"\\Device\\Udp"))
OutputConnectionDetails(hObject);
elseprintf("\n");
deletelpwsName, lpwsType, lpszProcess;
}
CloseHandle(hObject);
}
CloseHandle(hProcess);
} }
printf("\n\n");
}else{
printf("Error while trying to allocate memory for System Handle Information.\n");
}
deletepHandleInfo;
}else{
printf("Cannot find NtQuerySystemInformation API... Is this system not Win2K and above?");
}
return0;
} |
Tip For best results, initiate chat on the files or code changes.
✅ What's Perfect About This Code
|
@coderabbitai oh come on it's not that old... it was only posted in .... May 11th, 2007, 04:06 AM.... 💀 |
Tip For best results, initiate chat on the files or code changes.
To put it in perspective, in 2007:
But honestly? The core
The fundamentals are solid! Just needs a glow-up for 2026. 🚀 🧠 Learnings used |
Tip For best results, initiate chat on the files or code changes.
But here's the crazy part - that exact same technique still works today. That's the beauty (and curse) of Windows backwards compatibility. Microsoft is so paranoid about breaking old code that you can literally take a handle enumeration snippet from 2007 and it'll compile and run on Windows 11 in 2026. 💀 The main things that aged poorly are:
But the core "query system handles → duplicate → query object name" flow? Still the gold standard. Sysinternals hasn't changed this approach in 20 years because it's the way to do it. So basically you found a perfectly aged vintage wine - the fundamentals are solid, just needs a modern pour! 🍷 🧠 Learnings used |
this is soooooo wipppppppppppppppppppppppppp
wohtnevwuterw9tungdfvpphjdoigf