From 9892e491ad51e6367059ca36217a17c7169fe32c Mon Sep 17 00:00:00 2001 From: Daniel Widdis Date: Sun, 14 Jun 2020 19:51:10 -0700 Subject: [PATCH] Add mappings for Thread32First and Thread32Next to Kernel32 --- CHANGES.md | 1 + .../com/sun/jna/platform/win32/Kernel32.java | 31 ++++++++ .../com/sun/jna/platform/win32/Tlhelp32.java | 72 ++++++++++++++++++- .../sun/jna/platform/win32/Kernel32Test.java | 22 ++++++ 4 files changed, 123 insertions(+), 3 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index e948204401..3984fcf383 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -17,6 +17,7 @@ Features * [#1194](https://github.com/java-native-access/jna/pull/1194): Add `GetConsoleScreenBufferInfo`, `ReadConsoleInput` and `WriteConsole` with associated structures to `c.s.j.p.win32.Wincon` - [@rednoah](https://github.com/rednoah). * [#1198](https://github.com/java-native-access/jna/pull/1198): Add `NetSessionEnum` to `c.s.j.p.win32.Netapi32` and `WTSEnumerateSessions`, `WTSQuerySessionInformation`, and `WTSFreeMemory` to `c.s.j.p.win32.Wtsapi32` - [@dbwiddis](https://github.com/dbwiddis). * [#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). +* [#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). Bug Fixes --------- diff --git a/contrib/platform/src/com/sun/jna/platform/win32/Kernel32.java b/contrib/platform/src/com/sun/jna/platform/win32/Kernel32.java index 7795269c0d..7b0b2dcb83 100644 --- a/contrib/platform/src/com/sun/jna/platform/win32/Kernel32.java +++ b/contrib/platform/src/com/sun/jna/platform/win32/Kernel32.java @@ -2385,6 +2385,37 @@ boolean DeviceIoControl(HANDLE hDevice, int dwIoControlCode, */ boolean Process32Next(HANDLE hSnapshot, Tlhelp32.PROCESSENTRY32 lppe); + /** + * Retrieves information about the first thread of any process encountered in a + * system snapshot. + * + * @param hSnapshot + * A handle to the snapshot returned from a previous call to the + * CreateToolhelp32Snapshot function. + * @param lpte + * A pointer to a THREADENTRY32 structure. + * @return Returns TRUE if the first entry of the thread list has been copied to + * the buffer or FALSE otherwise. The ERROR_NO_MORE_FILES error value is + * returned by the GetLastError function if no threads exist or the + * snapshot does not contain thread information. + */ + boolean Thread32First(HANDLE hSnapshot, Tlhelp32.THREADENTRY32 lpte); + + /** + * Retrieves information about the next process recorded in a system snapshot. + * + * @param hSnapshot + * A handle to the snapshot returned from a previous call to the + * CreateToolhelp32Snapshot function. + * @param lpte + * A pointer to a THREADENTRY32 structure. + * @return Returns TRUE if the next entry of the thread list has been copied to + * the buffer or FALSE otherwise. The ERROR_NO_MORE_FILES error value is + * returned by the GetLastError function if no threads exist or the + * snapshot does not contain thread information. + */ + boolean Thread32Next(HANDLE hSnapshot, Tlhelp32.THREADENTRY32 lpte); + /** * The SetEnvironmentVariable function sets the contents of the specified * environment variable for the current process. diff --git a/contrib/platform/src/com/sun/jna/platform/win32/Tlhelp32.java b/contrib/platform/src/com/sun/jna/platform/win32/Tlhelp32.java index 607ddcb409..6c72b02bd6 100644 --- a/contrib/platform/src/com/sun/jna/platform/win32/Tlhelp32.java +++ b/contrib/platform/src/com/sun/jna/platform/win32/Tlhelp32.java @@ -22,9 +22,8 @@ */ package com.sun.jna.platform.win32; -import java.util.List; - import com.sun.jna.Native; +import com.sun.jna.NativeLong; import com.sun.jna.Pointer; import com.sun.jna.Structure; import com.sun.jna.Structure.FieldOrder; @@ -171,11 +170,78 @@ public PROCESSENTRY32(Pointer memory) { } } + /** + * Describes an entry from a list of the threads executing in the system when a + * snapshot was taken. + */ + @FieldOrder({ "dwSize", "cntUsage", "th32ThreadID", "th32OwnerProcessID", "tpBasePri", "tpDeltaPri", "dwFlags" }) + public static class THREADENTRY32 extends Structure { + + public static class ByReference extends THREADENTRY32 implements Structure.ByReference { + public ByReference() { + } + + public ByReference(Pointer memory) { + super(memory); + } + } + + /** + * The size of the structure, in bytes. Before calling the Thread32First + * function, set this member to sizeof(THREADENTRY32). If you do not initialize + * dwSize, Thread32First fails. + */ + int dwSize; + + /** + * This member is no longer used and is always set to zero. + */ + int cntUsage; + + /** + * The thread identifier, compatible with the thread identifier returned by the + * CreateProcess function. + */ + int th32ThreadID; + + /** + * The identifier of the process that created the thread. + */ + int th32OwnerProcessID; + + /** + * The kernel base priority level assigned to the thread. The priority is a + * number from 0 to 31, with 0 representing the lowest possible thread priority. + * For more information, see KeQueryPriorityThread. + */ + NativeLong tpBasePri; + + /** + * This member is no longer used and is always set to zero. + */ + NativeLong tpDeltaPri; + + /** + * This member is no longer used and is always set to zero. + */ + int dwFlags; + + public THREADENTRY32() { + dwSize = size(); + } + + public THREADENTRY32(Pointer memory) { + super(memory); + read(); + } + } + /** * Describes an entry from a list of the modules belonging to the specified * process. * - * @see MSDN + * @see MSDN */ @FieldOrder({"dwSize", "th32ModuleID", "th32ProcessID", "GlblcntUsage", "ProccntUsage", "modBaseAddr", "modBaseSize", "hModule", diff --git a/contrib/platform/test/com/sun/jna/platform/win32/Kernel32Test.java b/contrib/platform/test/com/sun/jna/platform/win32/Kernel32Test.java index 3c928034c9..da72a7b661 100644 --- a/contrib/platform/test/com/sun/jna/platform/win32/Kernel32Test.java +++ b/contrib/platform/test/com/sun/jna/platform/win32/Kernel32Test.java @@ -1180,6 +1180,28 @@ public void testGetProcessList() throws IOException { } } + public void testGetThreadList() throws IOException { + HANDLE threadEnumHandle = Kernel32.INSTANCE.CreateToolhelp32Snapshot(Tlhelp32.TH32CS_SNAPTHREAD, + new WinDef.DWORD(0)); + assertFalse(WinBase.INVALID_HANDLE_VALUE.equals(threadEnumHandle)); + try { + Tlhelp32.THREADENTRY32.ByReference threadEntry = new Tlhelp32.THREADENTRY32.ByReference(); + + assertTrue(Kernel32.INSTANCE.Thread32First(threadEnumHandle, threadEntry)); + + List threadIdList = new ArrayList(); + threadIdList.add(threadEntry.th32ThreadID); + + while (Kernel32.INSTANCE.Thread32Next(threadEnumHandle, threadEntry)) { + threadIdList.add(threadEntry.th32ThreadID); + } + + assertTrue(threadIdList.size() > 4); + } finally { + Kernel32Util.closeHandle(threadEnumHandle); + } + } + public final void testGetPrivateProfileInt() throws IOException { final File tmp = File.createTempFile("testGetPrivateProfileInt", "ini"); tmp.deleteOnExit();