Skip to content

Commit

Permalink
Bind VirtualLock and VirtualUnlock in c.s.j.p.win32.Kernel32
Browse files Browse the repository at this point in the history
  • Loading branch information
matthiasblaesing committed Aug 11, 2022
1 parent dbf8751 commit 04ae48f
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 1 deletion.
3 changes: 2 additions & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ Next Release (5.13.0)

Features
--------
* [#1454](https://github.com/java-native-access/jna/pull/1454): Add `c.s.j.p.win32.Psapi.QueryWorkingSetEx` and associated Types = [@crain-32](https://github.com/Crain-32).
* [#1454](https://github.com/java-native-access/jna/pull/1454): Add `c.s.j.p.win32.Psapi.QueryWorkingSetEx` and associated Types - [@crain-32](https://github.com/Crain-32).
* [#1459](https://github.com/java-native-access/jna/pull/1459): Add `VirtualLock` and `VirtualUnlock` in `c.s.j.p.win32.Kernel32` - [@matthiasblaesing](https://github.com/matthiasblaesing).

Bug Fixes
---------
Expand Down
80 changes: 80 additions & 0 deletions contrib/platform/src/com/sun/jna/platform/win32/Kernel32.java
Original file line number Diff line number Diff line change
Expand Up @@ -4307,4 +4307,84 @@ Pointer VirtualAllocEx(HANDLE hProcess, Pointer lpAddress, SIZE_T dwSize,
* @see <A HREF="https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-getapplicationrestartsettings">MSDN Entry</A>
*/
HRESULT GetApplicationRestartSettings(HANDLE hProcess, char[] pwzCommandline, IntByReference pcchSize, IntByReference pdwFlags);

/**
* Locks the specified region of the process's virtual address space into
* physical memory, ensuring that subsequent access to the region will not
* incur a page fault.
*
* @param lpAddress A pointer to the base address of the region of pages to
* be locked.
* @param dwSize The size of the region to be locked, in bytes. The
* region of affected pages includes all pages that contain
* one or more bytes in the range from the lpAddress
* parameter to (lpAddress+dwSize). This means that a
* 2-byte range straddling a page boundary causes both
* pages to be locked.
*
* @return {@code true} if locking succeeded.
*
* <p>
* All pages in the specified region must be committed. Memory protected
* with {@code PAGE_NOACCESS} cannot be locked.
* </p>
* <p>
* Locking pages into memory may degrade the performance of the system by
* reducing the available RAM and forcing the system to swap out other
* critical pages to the paging file. Each version of Windows has a limit on
* the maximum number of pages a process can lock. This limit is
* intentionally small to avoid severe performance degradation. Applications
* that need to lock larger numbers of pages must first call the
* SetProcessWorkingSetSize function to increase their minimum and maximum
* working set sizes. The maximum number of pages that a process can lock is
* equal to the number of pages in its minimum working set minus a small
* overhead.
* </p>
* <p>
* Pages that a process has locked remain in physical memory until the
* process unlocks them or terminates. These pages are guaranteed not to be
* written to the pagefile while they are locked.
* </p>
* <p>
* To unlock a region of locked pages, use the VirtualUnlock function.
* Locked pages are automatically unlocked when the process terminates.
* </p>
* <p>
* This function is not like the GlobalLock or LocalLock function in that it
* does not increment a lock count and translate a handle into a pointer.
* There is no lock count for virtual pages, so multiple calls to the
* VirtualUnlock function are never required to unlock a region of pages.
* </p>
*/
boolean VirtualLock(Pointer lpAddress, SIZE_T dwSize);

/**
* Unlocks a specified range of pages in the virtual address space of a
* process, enabling the system to swap the pages out to the paging file if
* necessary.
*
* @param lpAddress A pointer to the base address of the region of pages to
* be unlocked.
* @param dwSize The size of the region being unlocked, in bytes. The
* region of affected pages includes all pages containing
* one or more bytes in the range from the lpAddress
* parameter to (lpAddress+dwSize). This means that a
* 2-byte range straddling a page boundary causes both
* pages to be unlocked.
*
* @return {@code true} if unlocking succeeded.
*
* <p>
* For the function to succeed, the range specified need not match a range
* passed to a previous call to the VirtualLock function, but all pages in
* the range must be locked. If any of the pages in the specified range are
* not locked, VirtualUnlock removes such pages from the working set, sets
* last error to ERROR_NOT_LOCKED, and returns FALSE.
* </p>
* <p>
* Calling VirtualUnlock on a range of memory that is not locked releases
* the pages from the process's working set.
* </p>
*/
boolean VirtualUnlock(Pointer lpAddress, SIZE_T dwSize);
}
11 changes: 11 additions & 0 deletions contrib/platform/test/com/sun/jna/platform/win32/Kernel32Test.java
Original file line number Diff line number Diff line change
Expand Up @@ -2088,4 +2088,15 @@ public void testOpenFileMapping() throws IOException {

}

public void testVirtualLockUnlock() {
Memory mem = new Memory(4096);
// Test that locking works
assertTrue(Kernel32.INSTANCE.VirtualLock(mem, new SIZE_T(4096)));
// Test that unlocked region can be unlocked
assertTrue(Kernel32.INSTANCE.VirtualUnlock(mem, new SIZE_T(4096)));
// Locking a region we don't have access to should fail
assertFalse(Kernel32.INSTANCE.VirtualLock(null, new SIZE_T(4096)));
// Unlocking an unlocked region should fail
assertFalse(Kernel32.INSTANCE.VirtualUnlock(mem, new SIZE_T(4096)));
}
}

0 comments on commit 04ae48f

Please sign in to comment.