From 758a8297333980e33f392ac61884b418bc849b38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torbj=C3=B6rn=20Svensson?= Date: Fri, 26 Jun 2020 21:37:57 +0200 Subject: [PATCH] Add mapping for EnumProcesses to Psapi --- CHANGES.md | 1 + .../src/com/sun/jna/platform/win32/Psapi.java | 40 +++++++++++++ .../com/sun/jna/platform/win32/PsapiUtil.java | 58 +++++++++++++++++++ .../com/sun/jna/platform/win32/PsapiTest.java | 27 +++++++++ .../sun/jna/platform/win32/PsapiUtilTest.java | 52 +++++++++++++++++ 5 files changed, 178 insertions(+) create mode 100644 contrib/platform/src/com/sun/jna/platform/win32/PsapiUtil.java create mode 100644 contrib/platform/test/com/sun/jna/platform/win32/PsapiUtilTest.java diff --git a/CHANGES.md b/CHANGES.md index 09ebd6b588..8f6cc65afb 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -19,6 +19,7 @@ Features * [#1200](https://github.com/java-native-access/jna/pull/1200): Add mappings for `libudev` to `c.s.j.p.linux.Udev` - [@dbwiddis](https://github.com/dbwiddis). * [#1202](https://github.com/java-native-access/jna/pull/1202): Add mappings supporting shared memory including `c.s.j.p.unix.LibCAPI` types `size_t` and `ssize_t`, `c.s.j.p.linux.LibC` methods `munmap()`, `msync()`, and `close()`, `c.s.j.p.unix.LibCUtil` mapping `mmap()` and `ftruncate()`, and `c.s.j.p.linux.LibRT` methods `shm_open()` and `shm_unlink()` - [@dbwiddis](https://github.com/dbwiddis). * [#1209](https://github.com/java-native-access/jna/pull/1209): Add mappings for `Thread32First` and `Thread32Next` to `c.s.j.p.win32.Kernel32` - [@dbwiddis](https://github.com/dbwiddis). +* [#1214](https://github.com/java-native-access/jna/pull/1214): Add mapping for EnumProcesses to `c.s.j.p.win32.Psapi` - [@T-Svensson](https://github.com/T-Svensson/). Bug Fixes --------- diff --git a/contrib/platform/src/com/sun/jna/platform/win32/Psapi.java b/contrib/platform/src/com/sun/jna/platform/win32/Psapi.java index c6c89c5180..b071617531 100644 --- a/contrib/platform/src/com/sun/jna/platform/win32/Psapi.java +++ b/contrib/platform/src/com/sun/jna/platform/win32/Psapi.java @@ -266,6 +266,46 @@ public interface Psapi extends StdCallLibrary { */ boolean GetPerformanceInfo(PERFORMANCE_INFORMATION pPerformanceInformation, int cb); + /** + * Retrieves the process identifier for each process object in the system. + *
+ * It is a good idea to use a large array, because it is hard to predict + * how many processes there will be at the time you call EnumProcesses. + *
+ * To determine how many processes were enumerated, divide the + * pBytesReturned value by sizeof(DWORD). There is no indication given + * when the buffer is too small to store all process identifiers. + * Therefore, if pBytesReturned equals cb, consider retrying the call + * with a larger array. + *
+ * To obtain process handles for the processes whose identifiers you + * have just obtained, call the OpenProcess function. + *
+ * Starting with Windows 7 and Windows Server 2008 R2, Psapi.h + * establishes version numbers for the PSAPI functions. The PSAPI + * version number affects the name used to call the function and the + * library that a program must load. + *
+ * If PSAPI_VERSION is 2 or greater, this function is defined as + * K32EnumProcesses in Psapi.h and exported in Kernel32.lib and + * Kernel32.dll. If PSAPI_VERSION is 1, this function is defined as + * EnumProcesses in Psapi.h and exported in Psapi.lib and Psapi.dll as a + * wrapper that calls K32EnumProcesses. + * + * @param lpidProcess + * A pointer to an array that receives the list of process + * identifiers + * @param cb + * The size of the pProcessIds array, in bytes. + * @param lpcbNeeded + * The number of bytes returned in the pProcessIds array. + * @return If the function succeeds, the return value is nonzero. If the + * function fails, the return value is zero. To get extended + * error information, call GetLastError. + * @see MSDN + */ + boolean EnumProcesses(int[] lpidProcess, int cb, IntByReference lpcbNeeded); + @FieldOrder({"lpBaseOfDll", "SizeOfImage", "EntryPoint"}) class MODULEINFO extends Structure { public Pointer EntryPoint; diff --git a/contrib/platform/src/com/sun/jna/platform/win32/PsapiUtil.java b/contrib/platform/src/com/sun/jna/platform/win32/PsapiUtil.java new file mode 100644 index 0000000000..0ec32cb191 --- /dev/null +++ b/contrib/platform/src/com/sun/jna/platform/win32/PsapiUtil.java @@ -0,0 +1,58 @@ +/* Copyright (c) 2020 Torbjörn Svensson, All Rights Reserved + * + * The contents of this file is dual-licensed under 2 + * alternative Open Source/Free licenses: LGPL 2.1 or later and + * Apache License 2.0. (starting with JNA version 4.0.0). + * + * You can freely decide which license you want to apply to + * the project. + * + * You may obtain a copy of the LGPL License at: + * + * http://www.gnu.org/licenses/licenses.html + * + * A copy is also included in the downloadable source code package + * containing JNA, in file "LGPL2.1". + * + * You may obtain a copy of the Apache License at: + * + * http://www.apache.org/licenses/ + * + * A copy is also included in the downloadable source code package + * containing JNA, in file "AL2.0". + */ +package com.sun.jna.platform.win32; + +import com.sun.jna.Native; +import com.sun.jna.platform.win32.WinDef.DWORD; +import com.sun.jna.ptr.IntByReference; + +/** + * Psapi utility API. + * + * @author Torbjörn Svensson, azoff[at]svenskalinuxforeninen.se + */ +public abstract class PsapiUtil { + + /** + * Retrieves the process identifier for each process object in the system. + * + * @return Array of pids + */ + public static int[] enumProcesses() { + int size = 0; + int[] lpidProcess = null; + IntByReference lpcbNeeded = new IntByReference(); + do { + size = size + 1024; + lpidProcess = new int[size]; + if (!Psapi.INSTANCE.EnumProcesses(lpidProcess, size * DWORD.SIZE, lpcbNeeded)) { + throw new Win32Exception(Native.getLastError()); + } + } while (size == lpcbNeeded.getValue() / DWORD.SIZE); + + int[] result = new int[lpcbNeeded.getValue() / DWORD.SIZE]; + System.arraycopy(lpidProcess, 0, result, 0, result.length); + return result; + } +} diff --git a/contrib/platform/test/com/sun/jna/platform/win32/PsapiTest.java b/contrib/platform/test/com/sun/jna/platform/win32/PsapiTest.java index 44404e896b..dcf30830d7 100644 --- a/contrib/platform/test/com/sun/jna/platform/win32/PsapiTest.java +++ b/contrib/platform/test/com/sun/jna/platform/win32/PsapiTest.java @@ -248,4 +248,31 @@ public void testGetPerformanceInfo() { assertTrue(Psapi.INSTANCE.GetPerformanceInfo(perfInfo, perfInfo.size())); assertTrue(perfInfo.ProcessCount.intValue() > 0); } + + @Test + public void EnumProcesses() { + int size = 0; + int[] lpidProcess = null; + IntByReference lpcbNeeded = new IntByReference(); + do { + size = size + 1024; + lpidProcess = new int[size]; + if (!Psapi.INSTANCE.EnumProcesses(lpidProcess, size * DWORD.SIZE, lpcbNeeded)) { + throw new Win32Exception(Native.getLastError()); + } + } while (size == lpcbNeeded.getValue()); + + assertTrue("Size of pid list in bytes should be a multiple of " + DWORD.SIZE, lpcbNeeded.getValue() % DWORD.SIZE == 0); + assertTrue("List should contain atleast one pid", lpcbNeeded.getValue() > DWORD.SIZE); + + int myPid = Kernel32.INSTANCE.GetCurrentProcessId(); + boolean foundMyPid = false; + for (int i = 0; i < lpcbNeeded.getValue() / DWORD.SIZE; i++) { + if (lpidProcess[i] == myPid) { + foundMyPid = true; + break; + } + } + assertTrue("List should contain my pid", foundMyPid); + } } diff --git a/contrib/platform/test/com/sun/jna/platform/win32/PsapiUtilTest.java b/contrib/platform/test/com/sun/jna/platform/win32/PsapiUtilTest.java new file mode 100644 index 0000000000..62ff5fc627 --- /dev/null +++ b/contrib/platform/test/com/sun/jna/platform/win32/PsapiUtilTest.java @@ -0,0 +1,52 @@ +/* Copyright (c) 2020 Torbjörn Svensson, All Rights Reserved + * + * The contents of this file is dual-licensed under 2 + * alternative Open Source/Free licenses: LGPL 2.1 or later and + * Apache License 2.0. (starting with JNA version 4.0.0). + * + * You can freely decide which license you want to apply to + * the project. + * + * You may obtain a copy of the LGPL License at: + * + * http://www.gnu.org/licenses/licenses.html + * + * A copy is also included in the downloadable source code package + * containing JNA, in file "LGPL2.1". + * + * You may obtain a copy of the Apache License at: + * + * http://www.apache.org/licenses/ + * + * A copy is also included in the downloadable source code package + * containing JNA, in file "AL2.0". + */ +package com.sun.jna.platform.win32; + +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +/** + * Applies API tests on {@link PsapiUtil}. + * + * @author Torbjörn Svensson, azoff[at]svenskalinuxforeninen.se + */ +public class PsapiUtilTest { + @Test + public void enumProcesses() { + int[] pids = PsapiUtil.enumProcesses(); + + assertTrue("List should contain atleast one pid", pids.length > 0); + + int myPid = Kernel32.INSTANCE.GetCurrentProcessId(); + boolean foundMyPid = false; + for (int i = 0; i < pids.length; i++) { + if (pids[i] == myPid) { + foundMyPid = true; + break; + } + } + assertTrue("List should contain my pid", foundMyPid); + } +}