Skip to content

Commit 3c0dc33

Browse files
T-SvenssonTorbjörn Svensson
authored and
Torbjörn Svensson
committed
Add mapping for EnumProcesses to Psapi
1 parent d471b15 commit 3c0dc33

File tree

5 files changed

+178
-0
lines changed

5 files changed

+178
-0
lines changed

CHANGES.md

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Features
1919
* [#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).
2020
* [#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).
2121
* [#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).
22+
* [#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/).
2223

2324
Bug Fixes
2425
---------

contrib/platform/src/com/sun/jna/platform/win32/Psapi.java

+40
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,46 @@ public interface Psapi extends StdCallLibrary {
266266
*/
267267
boolean GetPerformanceInfo(PERFORMANCE_INFORMATION pPerformanceInformation, int cb);
268268

269+
/**
270+
* Retrieves the process identifier for each process object in the system.
271+
* <br>
272+
* It is a good idea to use a large array, because it is hard to predict
273+
* how many processes there will be at the time you call EnumProcesses.
274+
* <br>
275+
* To determine how many processes were enumerated, divide the
276+
* pBytesReturned value by sizeof(DWORD). There is no indication given
277+
* when the buffer is too small to store all process identifiers.
278+
* Therefore, if pBytesReturned equals cb, consider retrying the call
279+
* with a larger array.
280+
* <br>
281+
* To obtain process handles for the processes whose identifiers you
282+
* have just obtained, call the OpenProcess function.
283+
* <br>
284+
* Starting with Windows 7 and Windows Server 2008 R2, Psapi.h
285+
* establishes version numbers for the PSAPI functions. The PSAPI
286+
* version number affects the name used to call the function and the
287+
* library that a program must load.
288+
* <br>
289+
* If PSAPI_VERSION is 2 or greater, this function is defined as
290+
* K32EnumProcesses in Psapi.h and exported in Kernel32.lib and
291+
* Kernel32.dll. If PSAPI_VERSION is 1, this function is defined as
292+
* EnumProcesses in Psapi.h and exported in Psapi.lib and Psapi.dll as a
293+
* wrapper that calls K32EnumProcesses.
294+
*
295+
* @param lpidProcess
296+
* A pointer to an array that receives the list of process
297+
* identifiers
298+
* @param cb
299+
* The size of the pProcessIds array, in bytes.
300+
* @param lpcbNeeded
301+
* The number of bytes returned in the pProcessIds array.
302+
* @return If the function succeeds, the return value is nonzero. If the
303+
* function fails, the return value is zero. To get extended
304+
* error information, call GetLastError.
305+
* @see <a href="https://docs.microsoft.com/en-us/windows/win32/api/psapi/nf-psapi-enumprocesses">MSDN</a>
306+
*/
307+
boolean EnumProcesses(int[] lpidProcess, int cb, IntByReference lpcbNeeded);
308+
269309
@FieldOrder({"lpBaseOfDll", "SizeOfImage", "EntryPoint"})
270310
class MODULEINFO extends Structure {
271311
public Pointer EntryPoint;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/* Copyright (c) 2020 Torbjörn Svensson, All Rights Reserved
2+
*
3+
* The contents of this file is dual-licensed under 2
4+
* alternative Open Source/Free licenses: LGPL 2.1 or later and
5+
* Apache License 2.0. (starting with JNA version 4.0.0).
6+
*
7+
* You can freely decide which license you want to apply to
8+
* the project.
9+
*
10+
* You may obtain a copy of the LGPL License at:
11+
*
12+
* http://www.gnu.org/licenses/licenses.html
13+
*
14+
* A copy is also included in the downloadable source code package
15+
* containing JNA, in file "LGPL2.1".
16+
*
17+
* You may obtain a copy of the Apache License at:
18+
*
19+
* http://www.apache.org/licenses/
20+
*
21+
* A copy is also included in the downloadable source code package
22+
* containing JNA, in file "AL2.0".
23+
*/
24+
package com.sun.jna.platform.win32;
25+
26+
import com.sun.jna.Native;
27+
import com.sun.jna.platform.win32.WinDef.DWORD;
28+
import com.sun.jna.ptr.IntByReference;
29+
30+
/**
31+
* Psapi utility API.
32+
*
33+
* @author Torbj&ouml;rn Svensson, azoff[at]svenskalinuxforeninen.se
34+
*/
35+
public abstract class PsapiUtil {
36+
37+
/**
38+
* Retrieves the process identifier for each process object in the system.
39+
*
40+
* @return Array of pids
41+
*/
42+
public static int[] enumProcesses() {
43+
int size = 0;
44+
int[] lpidProcess = null;
45+
IntByReference lpcbNeeded = new IntByReference();
46+
do {
47+
size = size + 1024;
48+
lpidProcess = new int[size];
49+
if (!Psapi.INSTANCE.EnumProcesses(lpidProcess, size * DWORD.SIZE, lpcbNeeded)) {
50+
throw new Win32Exception(Native.getLastError());
51+
}
52+
} while (size == lpcbNeeded.getValue() / DWORD.SIZE);
53+
54+
int[] result = new int[lpcbNeeded.getValue() / DWORD.SIZE];
55+
System.arraycopy(lpidProcess, 0, result, 0, result.length);
56+
return result;
57+
}
58+
}

contrib/platform/test/com/sun/jna/platform/win32/PsapiTest.java

+27
Original file line numberDiff line numberDiff line change
@@ -248,4 +248,31 @@ public void testGetPerformanceInfo() {
248248
assertTrue(Psapi.INSTANCE.GetPerformanceInfo(perfInfo, perfInfo.size()));
249249
assertTrue(perfInfo.ProcessCount.intValue() > 0);
250250
}
251+
252+
@Test
253+
public void EnumProcesses() {
254+
int size = 0;
255+
int[] lpidProcess = null;
256+
IntByReference lpcbNeeded = new IntByReference();
257+
do {
258+
size = size + 1024;
259+
lpidProcess = new int[size];
260+
if (!Psapi.INSTANCE.EnumProcesses(lpidProcess, size * DWORD.SIZE, lpcbNeeded)) {
261+
throw new Win32Exception(Native.getLastError());
262+
}
263+
} while (size == lpcbNeeded.getValue());
264+
265+
assertTrue("Size of pid list in bytes should be a multiple of " + DWORD.SIZE, lpcbNeeded.getValue() % DWORD.SIZE == 0);
266+
assertTrue("List should contain atleast one pid", lpcbNeeded.getValue() > DWORD.SIZE);
267+
268+
int myPid = Kernel32.INSTANCE.GetCurrentProcessId();
269+
boolean foundMyPid = false;
270+
for (int i = 0; i < lpcbNeeded.getValue() / DWORD.SIZE; i++) {
271+
if (lpidProcess[i] == myPid) {
272+
foundMyPid = true;
273+
break;
274+
}
275+
}
276+
assertTrue("List should contain my pid", foundMyPid);
277+
}
251278
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/* Copyright (c) 2020 Torbjörn Svensson, All Rights Reserved
2+
*
3+
* The contents of this file is dual-licensed under 2
4+
* alternative Open Source/Free licenses: LGPL 2.1 or later and
5+
* Apache License 2.0. (starting with JNA version 4.0.0).
6+
*
7+
* You can freely decide which license you want to apply to
8+
* the project.
9+
*
10+
* You may obtain a copy of the LGPL License at:
11+
*
12+
* http://www.gnu.org/licenses/licenses.html
13+
*
14+
* A copy is also included in the downloadable source code package
15+
* containing JNA, in file "LGPL2.1".
16+
*
17+
* You may obtain a copy of the Apache License at:
18+
*
19+
* http://www.apache.org/licenses/
20+
*
21+
* A copy is also included in the downloadable source code package
22+
* containing JNA, in file "AL2.0".
23+
*/
24+
package com.sun.jna.platform.win32;
25+
26+
import static org.junit.Assert.assertTrue;
27+
28+
import org.junit.Test;
29+
30+
/**
31+
* Applies API tests on {@link PsapiUtil}.
32+
*
33+
* @author Torbj&ouml;rn Svensson, azoff[at]svenskalinuxforeninen.se
34+
*/
35+
public class PsapiUtilTest {
36+
@Test
37+
public void enumProcesses() {
38+
int[] pids = PsapiUtil.enumProcesses();
39+
40+
assertTrue("List should contain atleast one pid", pids.length > 0);
41+
42+
int myPid = Kernel32.INSTANCE.GetCurrentProcessId();
43+
boolean foundMyPid = false;
44+
for (int i = 0; i < pids.length; i++) {
45+
if (pids[i] == myPid) {
46+
foundMyPid = true;
47+
break;
48+
}
49+
}
50+
assertTrue("List should contain my pid", foundMyPid);
51+
}
52+
}

0 commit comments

Comments
 (0)