/* * swrun_cygwin.c: * hrSWRunTable data access: * Cygwin interface */ #include #include #ifdef HAVE_STDLIB_H #include #endif #ifdef HAVE_UNISTD_H #include #endif #ifdef HAVE_SYS_TYPES_H #include #endif #include #include #include #include #include #include #include #include #include #include #include "swrun_private.h" /* * a lot of this is "stolen" from cygwin ps.cc */ typedef BOOL(WINAPI * ENUMPROCESSMODULES) (HANDLE hProcess, HMODULE * lphModule, DWORD cb, LPDWORD lpcbNeeded); typedef DWORD(WINAPI * GETMODULEFILENAME) (HANDLE hProcess, HMODULE hModule, LPTSTR lpstrFIleName, DWORD nSize); typedef DWORD(WINAPI * GETPROCESSMEMORYINFO) (HANDLE hProcess, PPROCESS_MEMORY_COUNTERS pmc, DWORD nSize); typedef HANDLE(WINAPI * CREATESNAPSHOT) (DWORD dwFlags, DWORD th32ProcessID); typedef BOOL(WINAPI * PROCESSWALK) (HANDLE hSnapshot, LPPROCESSENTRY32 lppe); ENUMPROCESSMODULES myEnumProcessModules; GETMODULEFILENAME myGetModuleFileNameEx; CREATESNAPSHOT myCreateToolhelp32Snapshot; PROCESSWALK myProcess32First; PROCESSWALK myProcess32Next; GETPROCESSMEMORYINFO myGetProcessMemoryInfo = NULL; cygwin_getinfo_types query = CW_GETPINFO; static BOOL WINAPI dummyprocessmodules(HANDLE hProcess, HMODULE * lphModule, DWORD cb, LPDWORD lpcbNeeded) { lphModule[0] = (HMODULE) * lpcbNeeded; *lpcbNeeded = 1; return 1; } static DWORD WINAPI GetModuleFileNameEx95(HANDLE hProcess, HMODULE hModule, LPTSTR lpstrFileName, DWORD n) { HANDLE h; DWORD pid = (DWORD) hModule; PROCESSENTRY32 proc; h = myCreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (!h) return 0; proc.dwSize = sizeof(proc); if (myProcess32First(h, &proc)) do if (proc.th32ProcessID == pid) { CloseHandle(h); strcpy(lpstrFileName, proc.szExeFile); return 1; } while (myProcess32Next(h, &proc)); CloseHandle(h); return 0; } #define FACTOR (0x19db1ded53ea710LL) #define NSPERSEC 10000000LL #define NSPERMSEC 10000LL static time_t __stdcall to_time_t(PFILETIME ptr) { long rem; long long x = ((long long) ptr->dwHighDateTime << 32) + ((unsigned) ptr->dwLowDateTime); x -= FACTOR; rem = x % NSPERSEC; rem += NSPERSEC / 2; x /= NSPERSEC; x += rem / NSPERSEC; return x; } static long to_msec(PFILETIME ptr) { long long x = ((long long) ptr->dwHighDateTime << 32) + (unsigned) ptr->dwLowDateTime; x /= NSPERMSEC; return x; } HMODULE h; /* --------------------------------------------------------------------- */ void netsnmp_arch_swrun_init(void) { if ((h = LoadLibrary("psapi.dll")) != NULL) { myEnumProcessModules = (ENUMPROCESSMODULES) GetProcAddress(h, "EnumProcessModules"); myGetModuleFileNameEx = (GETMODULEFILENAME) GetProcAddress(h, "GetModuleFileNameExA"); myGetProcessMemoryInfo = (GETPROCESSMEMORYINFO) GetProcAddress(h, "GetProcessMemoryInfo"); if (myEnumProcessModules && myGetModuleFileNameEx) query = CW_GETPINFO_FULL; else snmp_log(LOG_ERR, "hr_swrun failed NT init\n"); } elif ((h = GetModuleHandle("KERNEL32.DLL")) != NULL) { myCreateToolhelp32Snapshot = (CREATESNAPSHOT) GetProcAddress(h, "CreateToolhelp32Snapshot"); myProcess32First = (PROCESSWALK) GetProcAddress(h, "Process32First"); myProcess32Next = (PROCESSWALK) GetProcAddress(h, "Process32Next"); myEnumProcessModules = dummyprocessmodules; myGetModuleFileNameEx = GetModuleFileNameEx95; if (myCreateToolhelp32Snapshot && myProcess32First && myProcess32Next) #if 0 /* * This doesn't work at all on Win98 SE */ query = CW_GETPINFO_FULL; #else query = CW_GETPINFO; #endif else snmp_log(LOG_ERR, "hr_swrun failed non-NT init\n"); } } /* --------------------------------------------------------------------- */ int netsnmp_arch_swrun_container_load( netsnmp_container *container, u_int flags) { struct external_pinfo *curproc; pid_t curpid = 0; DWORD n; HANDLE h; FILETIME ct, et, kt, ut; PROCESS_MEMORY_COUNTERS pmc; char *cp1, *cp2; netsnmp_swrun_entry *entry; cygwin_internal(CW_LOCK_PINFO, 1000); while (curproc = (struct external_pinfo *) cygwin_internal(query, curpid | CW_NEXTPID)) { curpid = curproc->pid; if (( PID_EXITED & curproc.process_state ) || ( ~0xffff & curproc.exitcode )) continue; entry = netsnmp_swrun_entry_create(curpid); if (NULL == entry) continue; /* error already logged by function */ rc = CONTAINER_INSERT(container, entry); n = lowproc.dwProcessId & 0xffff; h = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, n); if (curproc.ppid) { entry->hrSWRunPath_len = sprintf(entry->hrSWRunPath, "%.*s", (int)sizeof(entry->hrSWRunPath) - 1, cygwin_conv_to_posix_path(curproc.progname)); } else if (query == CW_GETPINFO_FULL) { if (h) { HMODULE hm[1000]; if (!myEnumProcessModules(h, hm, sizeof hm, &n)) n = 0; if (n && myGetModuleFileNameEx(h, hm[0], string, sizeof string)) { entry->hrSWRunPath_len = sprintf(entry->hrSWRunPath, "%.*s", (int)sizeof(entry->hrSWRunPath) - 1, string); } } } /* * Set hrSWRunName to be the last component of hrSWRunPath, * but without any file extension */ if ( entry->hrSWRunPath_len ) { cp1 = strrchr( entry->hrSWRunPath, '.' ); if ( cp1 ) *cp1 = '\0'; /* Mask the file extension */ cp2 = strrchr( entry->hrSWRunPath, '/' ); if (cp2) cp2++; /* Find the final component ... */ else cp2 = entry->hrSWRunPath; /* ... if any */ entry->hrSWRunName_len = sprintf(entry->hrSWRunName, "%.*s", (int)sizeof(entry->hrSWRunName) - 1, cp2); if ( cp1 ) *cp1 = '.'; /* Restore the file extension */ } /* * XXX - No information regarding process arguments * XXX - No information regarding system processes vs applications */ if (PID_STOPPED & curproc.process_state ) { entry->hrSWRunStatus = HRSWRUNSTATUS_NOTRUNNABLE; } /* else if (PID_ZOMBIE & curproc.process_state ) */ else if ( ~0xffff & curproc.exitcode ) { entry->hrSWRunStatus = HRSWRUNSTATUS_INVALID; } else { /* entry->hrSWRunStatus = HRSWRUNSTATUS_RUNNABLE; ?? */ entry->hrSWRunStatus = HRSWRUNSTATUS_RUNNING; } if (h) { if (GetProcessTimes(h, &ct, &et, &kt, &ut)) entry->hrSWRunPerfCPU = (to_msec(&kt) + to_msec(&ut)) / 10; if (myGetProcessMemoryInfo && myGetProcessMemoryInfo(h, &pmc, sizeof pmc)) entry->hrSWRunPerfMem = pmc.WorkingSetSize / 1024; CloseHandle(h); } } cygwin_internal(CW_UNLOCK_PINFO); DEBUGMSGTL(("swrun:load:arch"," loaded %d entries\n", CONTAINER_SIZE(container))); return 0; }