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();