Skip to content

Commit

Permalink
Code Review and Build Errors Fix.
Browse files Browse the repository at this point in the history
  • Loading branch information
Crain-32 committed Aug 6, 2022
1 parent 999c60a commit 3084361
Show file tree
Hide file tree
Showing 2 changed files with 149 additions and 0 deletions.
107 changes: 107 additions & 0 deletions contrib/platform/src/com/sun/jna/platform/win32/Psapi.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
import com.sun.jna.Structure;
import com.sun.jna.Structure.FieldOrder;
import com.sun.jna.platform.win32.BaseTSD.SIZE_T;
import com.sun.jna.platform.win32.BaseTSD.ULONG_PTR;
import com.sun.jna.platform.win32.WinDef.ULONG;
import com.sun.jna.platform.win32.WinDef.DWORD;
import com.sun.jna.platform.win32.WinDef.HMODULE;
import com.sun.jna.platform.win32.WinNT.HANDLE;
Expand Down Expand Up @@ -292,6 +294,18 @@ public interface Psapi extends StdCallLibrary {
*/
boolean EnumProcesses(int[] lpidProcess, int cb, IntByReference lpcbNeeded);

/**
* Retrieves extended information about the pages at specific
* virtual addresses in the address space of the specified process.
*
* @param hProcess A Handle to the Process
* @param pv A pointer to an array of PSAPI_WORKING_SET_EX_INFORMATION structures
* @param cb The size of the pv buffer, in bytes.
* @return If the function succeeds, the return value is nonzero.
* @see <a href="https://docs.microsoft.com/en-us/windows/win32/api/psapi/nf-psapi-queryworkingsetex">MSDN</a>
*/
boolean QueryWorkingSetEx(HANDLE hProcess, PSAPI_WORKING_SET_EX_INFORMATION pv, DWORD cb);

@FieldOrder({"lpBaseOfDll", "SizeOfImage", "EntryPoint"})
class MODULEINFO extends Structure {
public Pointer EntryPoint;
Expand Down Expand Up @@ -320,4 +334,97 @@ class PERFORMANCE_INFORMATION extends Structure {
public DWORD ProcessCount;
public DWORD ThreadCount;
}

@FieldOrder({"Flags", "Data"})
class PSAPI_WORKING_SET_EX_BLOCK extends Structure {
public ULONG_PTR Flags;
public ULONG[] Data = new ULONG[Native.POINTER_SIZE == 8 ? 1 : 2];
private long innerValue;

@Override
public void read() {
super.read();
innerValue = this.Data[0].longValue();
}

/**
* If this bit is 1, the subsequent members are valid; otherwise they should be ignored.
*/
public boolean Valid() {
return getBitFieldValue(1, 0) == 1;
}

/**
* The number of processes that share this page. The maximum value of this member is 7.
*/
public int ShareCount() {
return getBitFieldValue(3, 1);
}

/**
* The memory protection attributes of the page. For a list of values see below.
* @see <a href="https://docs.microsoft.com/en-us/windows/desktop/Memory/memory-protection-constants">Memory Protection Constants</a>.
*/
public int Win32Protection() {
return getBitFieldValue(11, 3 + 1);
}

/**
* If this bit is 1, the page can be shared.
*/
public boolean Shared() {
return getBitFieldValue(1, 11 + 3 + 1) == 1;
}

/**
* The NUMA node. The maximum value of this member is 63.
*/
public int Node() {
return getBitFieldValue(6, 1 + 11 + 3 + 1);
}

/**
* If this bit is 1, the virtual page is locked in physical memory.
*/
public boolean Locked() {
return getBitFieldValue(1, 6 + 1 + 11 + 3 + 1) == 1;
}

/**
* If this bit is 1, the page is a large page.
*/
public boolean LargePage() {
return getBitFieldValue(1, 1 + 6 + 1 + 11 + 3 + 1) == 1;
}

/**
* If this bit is 1, the page is has been reported as bad.
*/
public boolean Bad() {
return getBitFieldValue(1,1 + 1 + 1 + 6 + 1 + 11 + 3 + 1) == 1;
}

/**
* Returns innerValue after shifting the value rightShiftAmount, and applying a Bit Mask of size maskLength. Example, <br/>
* innerValue = 0011<br/> getBitFieldValue(2, 1) = 0011 >> 1 & 11 = 01
* @param maskLength Size of the Bit Mask
* @param rightShiftAmount Amount to Shift innerValue to the right by
* @return innerValue with the mask and shift applied.
*/
private int getBitFieldValue(final int maskLength, final int rightShiftAmount) {
long bitMask = 0;

for (int l = 0; l <= maskLength - rightShiftAmount; l++) {
bitMask |= 1 << l;
}
return (int) ((innerValue >> rightShiftAmount) & bitMask);
}
}


@FieldOrder({"VirtualAddress", "VirtualAttributes"})
class PSAPI_WORKING_SET_EX_INFORMATION extends Structure {
public Pointer VirtualAddress;
public PSAPI_WORKING_SET_EX_BLOCK VirtualAttributes;
}
}
42 changes: 42 additions & 0 deletions contrib/platform/test/com/sun/jna/platform/win32/PsapiTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
package com.sun.jna.platform.win32;

import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertFalse;

import java.util.LinkedList;
import java.util.List;
Expand All @@ -34,12 +35,15 @@

import com.sun.jna.Memory;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.Psapi.MODULEINFO;
import com.sun.jna.platform.win32.Psapi.PERFORMANCE_INFORMATION;
import com.sun.jna.platform.win32.WinDef.DWORD;
import com.sun.jna.platform.win32.WinDef.HMODULE;
import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.platform.win32.WinNT.HANDLE;
import com.sun.jna.platform.win32.WinNT.MEMORY_BASIC_INFORMATION;
import com.sun.jna.platform.win32.BaseTSD.SIZE_T;
import com.sun.jna.ptr.IntByReference;

/**
Expand Down Expand Up @@ -273,4 +277,42 @@ public void testEnumProcesses() {
}
assertTrue("List should contain my pid", foundMyPid);
}

@Test
public void testQueryWorkingSetEx() {
Win32Exception we = null;
HANDLE selfHandle = Kernel32.INSTANCE.GetCurrentProcess();
MEMORY_BASIC_INFORMATION mbi = new MEMORY_BASIC_INFORMATION();
try {
SIZE_T bytesRead = Kernel32.INSTANCE.VirtualQueryEx(selfHandle, Pointer.NULL, mbi, new SIZE_T(mbi.size()));
assertTrue("It should read correctly", bytesRead.intValue() != 0);
Psapi.PSAPI_WORKING_SET_EX_INFORMATION pswsi = new Psapi.PSAPI_WORKING_SET_EX_INFORMATION();
pswsi.VirtualAddress = mbi.baseAddress;
if (!Psapi.INSTANCE.QueryWorkingSetEx(selfHandle, pswsi, new DWORD(pswsi.size()))) {
throw new Win32Exception(Native.getLastError());
}
assertTrue("Virual Attributes should not be null", pswsi.VirtualAttributes != null);
if (Psapi.INSTANCE.QueryWorkingSetEx(new HANDLE(), pswsi, new DWORD(pswsi.size()))) {
throw new Win32Exception(Native.getLastError());
}
assertFalse("This line should never be called", true);
} catch (Win32Exception e) {
we = e;
throw we; // re-throw to invoke finally block
} finally {
try {
Kernel32Util.closeHandle(selfHandle);
} catch (Win32Exception e) {
if (we == null) {
we = e;
} else {
we.addSuppressedReflected(e);
}
}
if (we != null) {
throw we;
}
}
}
}

0 comments on commit 3084361

Please sign in to comment.