Don't leave Windows 2000 behind.

* Makefile.in (ps.exe): Revert previous change.
	* ps.cc: Include psapi.h again.
	(main): In CW_GETPINFO_FULL case.  Evaluate minimal process access mask
	required per OS and use that in OpenProcess call.  Use
	GetModuleFileNameExW on Windows 2000 or if fetching the drive mapping
	failed.  Handle empty process name.
This commit is contained in:
Corinna Vinschen 2011-12-22 13:48:05 +00:00
parent a6ae9400a7
commit 185ad82d2d
3 changed files with 72 additions and 22 deletions

View File

@ -1,3 +1,12 @@
2011-12-22 Corinna Vinschen <corinna@vinschen.de>
* Makefile.in (ps.exe): Revert previous change.
* ps.cc: Include psapi.h again.
(main): In CW_GETPINFO_FULL case. Evaluate minimal process access mask
required per OS and use that in OpenProcess call. Use
GetModuleFileNameExW on Windows 2000 or if fetching the drive mapping
failed. Handle empty process name.
2011-12-22 Corinna Vinschen <corinna@vinschen.de> 2011-12-22 Corinna Vinschen <corinna@vinschen.de>
* Makefile.in (ps.exe): Drop -lpsapi from ALL_LDFLAGS. * Makefile.in (ps.exe): Drop -lpsapi from ALL_LDFLAGS.

View File

@ -77,7 +77,7 @@ mount.exe: path-mount.o
cygcheck.exe: MINGW_LDFLAGS += -lntdll cygcheck.exe: MINGW_LDFLAGS += -lntdll
cygpath.exe: ALL_LDFLAGS += -lcygwin -luserenv -lntdll cygpath.exe: ALL_LDFLAGS += -lcygwin -luserenv -lntdll
cygpath.exe: CXXFLAGS += -fno-threadsafe-statics cygpath.exe: CXXFLAGS += -fno-threadsafe-statics
ps.exe: ALL_LDFLAGS += -lcygwin -lntdll ps.exe: ALL_LDFLAGS += -lcygwin -lpsapi -lntdll
strace.exe: MINGW_LDFLAGS += -lntdll strace.exe: MINGW_LDFLAGS += -lntdll
ldd.exe: ALL_LDFLAGS += -lpsapi ldd.exe: ALL_LDFLAGS += -lpsapi

View File

@ -22,6 +22,7 @@ details. */
#include <limits.h> #include <limits.h>
#include <sys/cygwin.h> #include <sys/cygwin.h>
#include <cygwin/version.h> #include <cygwin/version.h>
#include <psapi.h>
#include <ddk/ntapi.h> #include <ddk/ntapi.h>
#include <ddk/winddk.h> #include <ddk/winddk.h>
#include "loadlib.h" #include "loadlib.h"
@ -150,6 +151,7 @@ main (int argc, char *argv[])
external_pinfo *p; external_pinfo *p;
int aflag, lflag, fflag, sflag, uid, proc_id; int aflag, lflag, fflag, sflag, uid, proc_id;
bool found_proc_id = true; bool found_proc_id = true;
DWORD proc_access = PROCESS_QUERY_LIMITED_INFORMATION;
cygwin_getinfo_types query = CW_GETPINFO; cygwin_getinfo_types query = CW_GETPINFO;
const char *dtitle = " PID TTY STIME COMMAND\n"; const char *dtitle = " PID TTY STIME COMMAND\n";
const char *dfmt = "%7d%4s%10s %s\n"; const char *dfmt = "%7d%4s%10s %s\n";
@ -250,12 +252,33 @@ main (int argc, char *argv[])
AdjustTokenPrivileges (tok, FALSE, &priv, 0, NULL, NULL); AdjustTokenPrivileges (tok, FALSE, &priv, 0, NULL, NULL);
} }
} }
/* Fetch an opaque drive mapping object from the Cygwin DLL.
This is used to map NT device paths to Win32 paths. */ /* Check process query capabilities. */
drive_map = (void *) cygwin_internal (CW_ALLOC_DRIVE_MAP); OSVERSIONINFO version;
/* Check old Cygwin version. */ version.dwOSVersionInfoSize = sizeof version;
if (drive_map == (void *) -1) GetVersionEx (&version);
drive_map = NULL; if (version.dwMajorVersion <= 5) /* pre-Vista */
{
proc_access = PROCESS_QUERY_INFORMATION;
if (version.dwMinorVersion < 1) /* Windows 2000 */
proc_access |= PROCESS_VM_READ;
else
{
}
}
/* Except on Windows 2000, fetch an opaque drive mapping object from the
Cygwin DLL. This is used to map NT device paths to Win32 paths. */
if (!(proc_access & PROCESS_VM_READ))
{
drive_map = (void *) cygwin_internal (CW_ALLOC_DRIVE_MAP);
/* Check old Cygwin version. */
if (drive_map == (void *) -1)
drive_map = NULL;
/* Allow fallback to GetModuleFileNameEx for post-W2K. */
if (!drive_map)
proc_access = PROCESS_QUERY_INFORMATION | PROCESS_VM_READ;
}
} }
for (int pid = 0; for (int pid = 0;
@ -298,29 +321,47 @@ main (int argc, char *argv[])
if (p->process_state & PID_EXITED || (p->exitcode & ~0xffff)) if (p->process_state & PID_EXITED || (p->exitcode & ~0xffff))
strcat (pname, " <defunct>"); strcat (pname, " <defunct>");
} }
else if (query == CW_GETPINFO_FULL && drive_map) else if (query == CW_GETPINFO_FULL)
{ {
HANDLE h; HANDLE h;
NTSTATUS status; NTSTATUS status;
wchar_t *win32path = NULL; wchar_t *win32path = NULL;
h = OpenProcess (PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, h = OpenProcess (proc_access, FALSE, p->dwProcessId);
FALSE, p->dwProcessId);
if (!h) if (!h)
continue; continue;
status = NtQueryInformationProcess (h, ProcessImageFileName, uni, /* We use NtQueryInformationProcess in the first place, because
sizeof unicode_buf, NULL); GetModuleFileNameEx does not work on 64 bit systems when trying
if (NT_SUCCESS (status)) to fetch module names of 64 bit processes. */
if (!(proc_access & PROCESS_VM_READ)) /* Windows 2000 */
{ {
/* NtQueryInformationProcess returns a native NT device path. status = NtQueryInformationProcess (h, ProcessImageFileName, uni,
Call CW_MAP_DRIVE_MAP to convert the path to an ordinary sizeof unicode_buf, NULL);
Win32 path. The returned pointer is a pointer into the if (NT_SUCCESS (status))
incoming buffer given as third argument. It's expected {
to be big enough, which we made sure by defining unicode_buf /* NtQueryInformationProcess returns a native NT device path.
to have enough space for a maximum sized UNICODE_STRING. */ Call CW_MAP_DRIVE_MAP to convert the path to an ordinary
uni->Buffer[uni->Length / sizeof (WCHAR)] = L'\0'; Win32 path. The returned pointer is a pointer into the
win32path = (wchar_t *) cygwin_internal (CW_MAP_DRIVE_MAP, incoming buffer given as third argument. It's expected
drive_map, uni->Buffer); to be big enough, which we made sure by defining
unicode_buf to have enough space for a maximum sized
UNICODE_STRING. */
if (uni->Length == 0) /* System process */
win32path = L"System";
else
{
uni->Buffer[uni->Length / sizeof (WCHAR)] = L'\0';
win32path = (wchar_t *) cygwin_internal (CW_MAP_DRIVE_MAP,
drive_map,
uni->Buffer);
}
}
}
else
{
if (GetModuleFileNameExW (h, NULL, (PWCHAR) unicode_buf,
NT_MAX_PATH))
win32path = (wchar_t *) unicode_buf;
} }
if (win32path) if (win32path)
wcstombs (pname, win32path, sizeof pname); wcstombs (pname, win32path, sizeof pname);