Skip to content

Commit

Permalink
Add mapping for EnumProcesses to Psapi
Browse files Browse the repository at this point in the history
  • Loading branch information
T-Svensson committed Jun 29, 2020
1 parent d471b15 commit 758a829
Show file tree
Hide file tree
Showing 5 changed files with 178 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGES.md
Expand Up @@ -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
---------
Expand Down
40 changes: 40 additions & 0 deletions contrib/platform/src/com/sun/jna/platform/win32/Psapi.java
Expand Up @@ -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.
* <br>
* 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.
* <br>
* 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.
* <br>
* To obtain process handles for the processes whose identifiers you
* have just obtained, call the OpenProcess function.
* <br>
* 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.
* <br>
* 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 <a href="https://docs.microsoft.com/en-us/windows/win32/api/psapi/nf-psapi-enumprocesses">MSDN</a>
*/
boolean EnumProcesses(int[] lpidProcess, int cb, IntByReference lpcbNeeded);

@FieldOrder({"lpBaseOfDll", "SizeOfImage", "EntryPoint"})
class MODULEINFO extends Structure {
public Pointer EntryPoint;
Expand Down
58 changes: 58 additions & 0 deletions 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&ouml;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;
}
}
27 changes: 27 additions & 0 deletions contrib/platform/test/com/sun/jna/platform/win32/PsapiTest.java
Expand Up @@ -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);
}
}
@@ -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&ouml;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);
}
}

0 comments on commit 758a829

Please sign in to comment.