From 94d25a5dcfad872c97e71b646429fc87dc66acc2 Mon Sep 17 00:00:00 2001 From: Iain Patterson Date: Wed, 27 Jul 2016 12:21:01 +0100 Subject: [PATCH] Use QueryFullProcessImageName() if available. A 32-bit process running on 64-bit Windows can't read the image name of a 64-bit process, so printing the process tree will fail. However, on Windows Vista or later we have QueryFullProcessImageName() which is able to retrieve the path. --- README.txt | 3 +++ imports.cpp | 15 ++++++++++----- imports.h | 9 +++++++++ process.cpp | 13 ++++++++++++- 4 files changed, 34 insertions(+), 6 deletions(-) diff --git a/README.txt b/README.txt index cc63c5d..e59326f 100644 --- a/README.txt +++ b/README.txt @@ -878,6 +878,9 @@ processes started by a given service: nssm processes +Note that if 32-bit NSSM is run on a 64-bit system running an older version of +Windows than Vista it will not be able to query the paths of 64-bit processes. + Exporting service configuration ------------------------------- diff --git a/imports.cpp b/imports.cpp index 230bf43..f50591c 100644 --- a/imports.cpp +++ b/imports.cpp @@ -59,14 +59,19 @@ int get_imports() { if (error != ERROR_PROC_NOT_FOUND) return 2; } + imports.QueryFullProcessImageName = (QueryFullProcessImageName_ptr) get_import(imports.kernel32, QUERYFULLPROCESSIMAGENAME_EXPORT, &error); + if (! imports.QueryFullProcessImageName) { + if (error != ERROR_PROC_NOT_FOUND) return 3; + } + imports.SleepConditionVariableCS = (SleepConditionVariableCS_ptr) get_import(imports.kernel32, "SleepConditionVariableCS", &error); if (! imports.SleepConditionVariableCS) { - if (error != ERROR_PROC_NOT_FOUND) return 3; + if (error != ERROR_PROC_NOT_FOUND) return 4; } imports.WakeConditionVariable = (WakeConditionVariable_ptr) get_import(imports.kernel32, "WakeConditionVariable", &error); if (! imports.WakeConditionVariable) { - if (error != ERROR_PROC_NOT_FOUND) return 4; + if (error != ERROR_PROC_NOT_FOUND) return 5; } } else if (error != ERROR_MOD_NOT_FOUND) return 1; @@ -75,14 +80,14 @@ int get_imports() { if (imports.advapi32) { imports.CreateWellKnownSid = (CreateWellKnownSid_ptr) get_import(imports.advapi32, "CreateWellKnownSid", &error); if (! imports.CreateWellKnownSid) { - if (error != ERROR_PROC_NOT_FOUND) return 6; + if (error != ERROR_PROC_NOT_FOUND) return 7; } imports.IsWellKnownSid = (IsWellKnownSid_ptr) get_import(imports.advapi32, "IsWellKnownSid", &error); if (! imports.IsWellKnownSid) { - if (error != ERROR_PROC_NOT_FOUND) return 7; + if (error != ERROR_PROC_NOT_FOUND) return 8; } } - else if (error != ERROR_MOD_NOT_FOUND) return 5; + else if (error != ERROR_MOD_NOT_FOUND) return 6; return 0; } diff --git a/imports.h b/imports.h index 008a702..5c79cb4 100644 --- a/imports.h +++ b/imports.h @@ -1,8 +1,16 @@ #ifndef IMPORTS_H #define IMPORTS_H +/* Some functions don't have decorated versions. */ +#ifdef UNICODE +#define QUERYFULLPROCESSIMAGENAME_EXPORT "QueryFullProcessImageNameW" +#else +#define QUERYFULLPROCESSIMAGENAME_EXPORT "QueryFullProcessImageNameA" +#endif + typedef BOOL (WINAPI *AttachConsole_ptr)(DWORD); typedef BOOL (WINAPI *SleepConditionVariableCS_ptr)(PCONDITION_VARIABLE, PCRITICAL_SECTION, DWORD); +typedef BOOL (WINAPI *QueryFullProcessImageName_ptr)(HANDLE, unsigned long, LPTSTR, unsigned long *); typedef void (WINAPI *WakeConditionVariable_ptr)(PCONDITION_VARIABLE); typedef BOOL (WINAPI *CreateWellKnownSid_ptr)(WELL_KNOWN_SID_TYPE, SID *, SID *, unsigned long *); typedef BOOL (WINAPI *IsWellKnownSid_ptr)(SID *, WELL_KNOWN_SID_TYPE); @@ -12,6 +20,7 @@ typedef struct { HMODULE advapi32; AttachConsole_ptr AttachConsole; SleepConditionVariableCS_ptr SleepConditionVariableCS; + QueryFullProcessImageName_ptr QueryFullProcessImageName; WakeConditionVariable_ptr WakeConditionVariable; CreateWellKnownSid_ptr CreateWellKnownSid; IsWellKnownSid_ptr IsWellKnownSid; diff --git a/process.cpp b/process.cpp index dc99597..e78283c 100644 --- a/process.cpp +++ b/process.cpp @@ -411,7 +411,18 @@ int print_process(nssm_service_t *service, kill_t *k) { buffer[i] = _T('\0'); } } - if (! GetModuleFileNameEx(k->process_handle, NULL, exe, _countof(exe))) _sntprintf_s(exe, _countof(exe), _TRUNCATE, _T("???")); + + unsigned long size = _countof(exe); + if (! imports.QueryFullProcessImageName || ! imports.QueryFullProcessImageName(k->process_handle, 0, exe, &size)) { + /* + Fall back to GetModuleFileNameEx(), which won't work for WOW64 processes. + */ + if (! GetModuleFileNameEx(k->process_handle, NULL, exe, _countof(exe))) { + long error = GetLastError(); + if (error == ERROR_PARTIAL_COPY) _sntprintf_s(exe, _countof(exe), _TRUNCATE, _T("[WOW64]")); + else _sntprintf_s(exe, _countof(exe), _TRUNCATE, _T("???")); + } + } _tprintf(_T("% 8lu %s%s\n"), k->pid, buffer ? buffer : _T(""), exe); -- 2.7.4