public inbox for cygwin-patches@cygwin.com
 help / color / mirror / Atom feed
From: Takashi Yano <takashi.yano@nifty.ne.jp>
To: cygwin-patches@cygwin.com
Subject: [PATCH] Cygwin: pipe: Use NtQuerySystemInformation() instead of EnumProcesses().
Date: Tue, 19 Oct 2021 17:40:19 +0900	[thread overview]
Message-ID: <20211019084019.1660-1-takashi.yano@nifty.ne.jp> (raw)

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

Addresses:
https://cygwin.com/pipermail/cygwin-developers/2021-October/012422.html
---
 winsup/cygwin/fhandler_pipe.cc | 50 +++++++++++++++++++++++-----------
 1 file changed, 34 insertions(+), 16 deletions(-)

diff --git a/winsup/cygwin/fhandler_pipe.cc b/winsup/cygwin/fhandler_pipe.cc
index dd8b4f317..63e432160 100644
--- a/winsup/cygwin/fhandler_pipe.cc
+++ b/winsup/cygwin/fhandler_pipe.cc
@@ -20,7 +20,6 @@ details. */
 #include "pinfo.h"
 #include "shared_info.h"
 #include "tls_pbuf.h"
-#include <psapi.h>
 
 /* This is only to be used for writing.  When reading,
 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,
 					  OBJECT_NAME_INFORMATION *ntfn)
 {
+  NTSTATUS status;
   ULONG len;
-  BOOL res;
   DWORD n_process = 256;
-  DWORD *proc_pids;
+  PSYSTEM_PROCESS_INFORMATION spi;
   do
     { /* Enumerate processes */
-      DWORD nbytes = n_process * sizeof (DWORD);
-      proc_pids = (DWORD *) HeapAlloc (GetProcessHeap (), 0, nbytes);
-      if (!proc_pids)
+      DWORD nbytes = n_process * sizeof (SYSTEM_PROCESS_INFORMATION);
+      spi = (PSYSTEM_PROCESS_INFORMATION) HeapAlloc (GetProcessHeap (),
+						     0, nbytes);
+      if (!spi)
 	return NULL;
-      res = EnumProcesses (proc_pids, nbytes, &len);
-      if (res && len < nbytes)
+      status = NtQuerySystemInformation (SystemProcessInformation,
+					 spi, nbytes, &len);
+      if (NT_SUCCESS (status))
 	break;
-      res = FALSE;
-      HeapFree (GetProcessHeap (), 0, proc_pids);
+      HeapFree (GetProcessHeap (), 0, spi);
       n_process *= 2;
     }
-  while (n_process < (1L<<20));
-  if (!res)
+  while (n_process < (1L<<20) && status == STATUS_INFO_LENGTH_MISMATCH);
+  if (!NT_SUCCESS (status))
     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--)
     {
@@ -1221,7 +1240,6 @@ fhandler_pipe::get_query_hdl_per_process (WCHAR *name,
 	continue;
 
       /* Retrieve process handles */
-      NTSTATUS status;
       DWORD n_handle = 256;
       PPROCESS_HANDLE_SNAPSHOT_INFORMATION phi;
       do
@@ -1255,8 +1273,8 @@ fhandler_pipe::get_query_hdl_per_process (WCHAR *name,
 
 	  /* Retrieve handle */
 	  HANDLE h = (HANDLE)(intptr_t) phi->Handles[j].HandleValue;
-	  res = DuplicateHandle (proc, h, GetCurrentProcess (), &h,
-				 FILE_READ_DATA, 0, 0);
+	  BOOL res = DuplicateHandle (proc, h, GetCurrentProcess (), &h,
+				      FILE_READ_DATA, 0, 0);
 	  if (!res)
 	    continue;
 
-- 
2.33.0


             reply	other threads:[~2021-10-19  8:40 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-10-19  8:40 Takashi Yano [this message]
2021-10-19 11:07 ` Corinna Vinschen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20211019084019.1660-1-takashi.yano@nifty.ne.jp \
    --to=takashi.yano@nifty.ne.jp \
    --cc=cygwin-patches@cygwin.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).