Cygwin: pipe: Use NtQuerySystemInformation() instead of EnumProcesses().

- Using EnumProcess() breaks Windows Vista compatibility. This patch
  replaces EnumProcesses() with NtQuerySystemInformation().

Addresses:
https://cygwin.com/pipermail/cygwin-developers/2021-October/012422.html
This commit is contained in:
Takashi Yano 2021-10-19 17:40:19 +09:00 committed by Corinna Vinschen
parent c51f05c597
commit 745b547ebd
1 changed files with 34 additions and 16 deletions

View File

@ -20,7 +20,6 @@ details. */
#include "pinfo.h" #include "pinfo.h"
#include "shared_info.h" #include "shared_info.h"
#include "tls_pbuf.h" #include "tls_pbuf.h"
#include <psapi.h>
/* This is only to be used for writing. When reading, /* This is only to be used for writing. When reading,
STATUS_PIPE_EMPTY simply means there's no data to be read. */ STATUS_PIPE_EMPTY simply means there's no data to be read. */
@ -1190,27 +1189,47 @@ HANDLE
fhandler_pipe::get_query_hdl_per_process (WCHAR *name, fhandler_pipe::get_query_hdl_per_process (WCHAR *name,
OBJECT_NAME_INFORMATION *ntfn) OBJECT_NAME_INFORMATION *ntfn)
{ {
NTSTATUS status;
ULONG len; ULONG len;
BOOL res;
DWORD n_process = 256; DWORD n_process = 256;
DWORD *proc_pids; PSYSTEM_PROCESS_INFORMATION spi;
do do
{ /* Enumerate processes */ { /* Enumerate processes */
DWORD nbytes = n_process * sizeof (DWORD); DWORD nbytes = n_process * sizeof (SYSTEM_PROCESS_INFORMATION);
proc_pids = (DWORD *) HeapAlloc (GetProcessHeap (), 0, nbytes); spi = (PSYSTEM_PROCESS_INFORMATION) HeapAlloc (GetProcessHeap (),
if (!proc_pids) 0, nbytes);
if (!spi)
return NULL; return NULL;
res = EnumProcesses (proc_pids, nbytes, &len); status = NtQuerySystemInformation (SystemProcessInformation,
if (res && len < nbytes) spi, nbytes, &len);
if (NT_SUCCESS (status))
break; break;
res = FALSE; HeapFree (GetProcessHeap (), 0, spi);
HeapFree (GetProcessHeap (), 0, proc_pids);
n_process *= 2; n_process *= 2;
} }
while (n_process < (1L<<20)); while (n_process < (1L<<20) && status == STATUS_INFO_LENGTH_MISMATCH);
if (!res) if (!NT_SUCCESS (status))
return NULL; return NULL;
n_process = len / sizeof (DWORD);
/* In most cases, it is faster to check the processes in reverse order.
To do this, store PIDs into an array. */
DWORD *proc_pids = (DWORD *) HeapAlloc (GetProcessHeap (), 0,
n_process * sizeof (DWORD));
if (!proc_pids)
{
HeapFree (GetProcessHeap (), 0, spi);
return NULL;
}
PSYSTEM_PROCESS_INFORMATION p = spi;
n_process = 0;
while (true)
{
proc_pids[n_process++] = (DWORD)(intptr_t) p->UniqueProcessId;
if (!p->NextEntryOffset)
break;
p = (PSYSTEM_PROCESS_INFORMATION) ((char *) p + p->NextEntryOffset);
}
HeapFree (GetProcessHeap (), 0, spi);
for (LONG i = (LONG) n_process - 1; i >= 0; i--) for (LONG i = (LONG) n_process - 1; i >= 0; i--)
{ {
@ -1221,7 +1240,6 @@ fhandler_pipe::get_query_hdl_per_process (WCHAR *name,
continue; continue;
/* Retrieve process handles */ /* Retrieve process handles */
NTSTATUS status;
DWORD n_handle = 256; DWORD n_handle = 256;
PPROCESS_HANDLE_SNAPSHOT_INFORMATION phi; PPROCESS_HANDLE_SNAPSHOT_INFORMATION phi;
do do
@ -1255,7 +1273,7 @@ fhandler_pipe::get_query_hdl_per_process (WCHAR *name,
/* Retrieve handle */ /* Retrieve handle */
HANDLE h = (HANDLE)(intptr_t) phi->Handles[j].HandleValue; HANDLE h = (HANDLE)(intptr_t) phi->Handles[j].HandleValue;
res = DuplicateHandle (proc, h, GetCurrentProcess (), &h, BOOL res = DuplicateHandle (proc, h, GetCurrentProcess (), &h,
FILE_READ_DATA, 0, 0); FILE_READ_DATA, 0, 0);
if (!res) if (!res)
continue; continue;