Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix unittests for windows 32bit intel #1278

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Bug Fixes
* [#1252](https://github.com/java-native-access/jna/issues/1252): - Fix bindings of `CTL_ENTRY#getRgAttribute`, `CTL_INFO#getRgCTLEntry`, `CTL_INFO#getRgExtension`, `CERT_EXTENSIONS#getRgExtension`, `CERT_INFO#getRgExtension`, `CRL_INFO#getRgCRLEntry`, `CRL_INFO#getRgExtension`, `CRL_ENTRY#getRgExtension`. Add bindings for `CertEnumCertificatesInStore`, `CertEnumCTLsInStore`, `CertEnumCRLsInStore` and `CryptQueryObject` in `c.s.j.p.win32.Crypt32`.<br> *WARNING:* The signatures for `CTL_INFO#getRgCTLEntry` and `CTL_INFO#getRgExtension` were changed - as the original signatures were obviously wrong and read the wrong attributes, it is not considered an API break - [@matthiasblaesing](https://github.com/matthiasblaesing).
* [#1275](https://github.com/java-native-access/jna/issues/1275): Fix `CFStringRef#stringValue` for empty Strings - [@dyorgio](https://github.com/dyorgio).
* [#1279](https://github.com/java-native-access/jna/issues/1279): Remove `DLLCallback` import from `CallbackReference` - [@dyorgio](https://github.com/dyorgio).
* [#1278](https://github.com/java-native-access/jna/pull/1278): Improve compatibility of `c.s.j.p.WindowUtils#getProcessFilePath` and fix unittests for windows 32bit intel - [@matthiasblaesing](https://github.com/matthiasblaesing).

Release 5.6.0
=============
Expand Down
80 changes: 66 additions & 14 deletions contrib/platform/src/com/sun/jna/platform/WindowUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,12 @@
import com.sun.jna.platform.unix.X11.Xrender.XRenderPictFormat;
import com.sun.jna.platform.win32.GDI32;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.Kernel32Util;
import com.sun.jna.platform.win32.Psapi;
import com.sun.jna.platform.win32.PsapiUtil;
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.Win32Exception;
import com.sun.jna.platform.win32.WinBase;
import com.sun.jna.platform.win32.WinDef.DWORDByReference;
import com.sun.jna.platform.win32.WinDef.HBITMAP;
import com.sun.jna.platform.win32.WinDef.HDC;
Expand All @@ -99,6 +102,7 @@
import com.sun.jna.platform.win32.WinDef.POINT;
import com.sun.jna.platform.win32.WinDef.RECT;
import com.sun.jna.platform.win32.WinDef.WPARAM;
import com.sun.jna.platform.win32.WinError;
import com.sun.jna.platform.win32.WinGDI;
import com.sun.jna.platform.win32.WinGDI.BITMAP;
import com.sun.jna.platform.win32.WinGDI.BITMAPINFO;
Expand Down Expand Up @@ -1278,33 +1282,81 @@ public String getWindowTitle(final HWND hwnd) {

@Override
public String getProcessFilePath(final HWND hwnd) {
final char[] filePath = new char[2048];
final IntByReference pid = new IntByReference();
User32.INSTANCE.GetWindowThreadProcessId(hwnd, pid);

final HANDLE process = Kernel32.INSTANCE.OpenProcess(WinNT.PROCESS_QUERY_INFORMATION | WinNT.PROCESS_VM_READ,
false, pid.getValue());
// GetProcessImageFileName requires PROCESS_QUERY_INFORMATION on
// older windows versions so try that first. If we fail to get
// access to that information fallback to
// PROCESS_QUERY_LIMITED_INFORMATION. This allows reading image
// paths from processes running with elevated privileges (at least
// worked successfully for a setup program started from a network
// share)
HANDLE process = Kernel32.INSTANCE.OpenProcess(
WinNT.PROCESS_QUERY_INFORMATION,
false,
pid.getValue());

if (process == null) {
if(Kernel32.INSTANCE.GetLastError() != WinNT.ERROR_ACCESS_DENIED) {
throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
} else {
// Ignore windows, that can't be accessed
return "";
process = Kernel32.INSTANCE.OpenProcess(
WinNT.PROCESS_QUERY_LIMITED_INFORMATION,
false,
pid.getValue());

if (process == null) {
if (Kernel32.INSTANCE.GetLastError() != WinNT.ERROR_ACCESS_DENIED) {
throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
} else {
// Ignore windows, that can't be accessed
return "";
}
}
}
}

try {
final int length = Psapi.INSTANCE.GetModuleFileNameExW(process,
null, filePath, filePath.length);
if (length == 0) {
if(Kernel32.INSTANCE.GetLastError() != WinNT.ERROR_INVALID_HANDLE) {
throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
} else {
// ignore invalid handles
return "";
String processImagePath = PsapiUtil.GetProcessImageFileName(process);

// GetProcessImageFileName returns the file name as a device
// filename in the form \Device\Harddisk5\. To make this more
// familiar and keep compatibility with QueryModuleName try to
// map back to known path (DOS path or UNC path)

// Map Mup to UNC path
if(processImagePath.startsWith("\\Device\\Mup\\")) {
return "\\" + processImagePath.substring(11);
}

// Format of FindFirstVolume is
// \\?\Volume{00000000-0000-0000-0000-000000000000}\
char[] volumeUUID = new char[50];
HANDLE h = Kernel32.INSTANCE.FindFirstVolume(volumeUUID, 50);
if (h == null || h.equals(WinBase.INVALID_HANDLE_VALUE)) {
throw new Win32Exception(Native.getLastError());
}
try {
do {
String volumePath = Native.toString(volumeUUID);
for (String s : Kernel32Util.getVolumePathNamesForVolumeName(volumePath)) {
if (s.matches("[a-zA-Z]:\\\\")) {
for (String path : Kernel32Util.queryDosDevice(s.substring(0, 2), 1024)) {
if(processImagePath.startsWith(path)) {
return s + processImagePath.substring(path.length() + 1);
}
}
}
}
} while (Kernel32.INSTANCE.FindNextVolume(h, volumeUUID, 50));
if (Native.getLastError() != WinError.ERROR_NO_MORE_FILES) {
throw new Win32Exception(Native.getLastError());
}
} finally {
Kernel32.INSTANCE.FindVolumeClose(h);
}
return Native.toString(filePath).trim();
return processImagePath;
} finally {
Kernel32.INSTANCE.CloseHandle(process);
}
Expand Down
2 changes: 2 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 @@ -226,6 +226,8 @@ public interface Psapi extends StdCallLibrary {
boolean GetModuleInformation(HANDLE hProcess, HMODULE hModule, MODULEINFO lpmodinfo, int cb);

/**
* Retrieves the name of the executable file for the specified process.
*
* @param hProcess
* A handle to the process. The handle must have the
* PROCESS_QUERY_INFORMATION or PROCESS_QUERY_LIMITED_INFORMATION
Expand Down
33 changes: 33 additions & 0 deletions contrib/platform/src/com/sun/jna/platform/win32/PsapiUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@
*/
package com.sun.jna.platform.win32;

import com.sun.jna.Native;
import java.util.Arrays;

import com.sun.jna.platform.win32.WinDef.DWORD;
import com.sun.jna.platform.win32.WinNT.HANDLE;
import com.sun.jna.ptr.IntByReference;

/**
Expand Down Expand Up @@ -54,4 +56,35 @@ public static int[] enumProcesses() {

return Arrays.copyOf(lpidProcess, lpcbNeeded.getValue() / DWORD.SIZE);
}

/**
* Retrieves the name of the executable file for the specified process.
*
* @param hProcess
* A handle to the process. The handle must have the
* PROCESS_QUERY_INFORMATION or PROCESS_QUERY_LIMITED_INFORMATION
* access right. For more information, see Process Security and
* Access Rights. <br>
* Windows Server 2003 and Windows XP: The handle must have the
* PROCESS_QUERY_INFORMATION access right.
* @return ame of the executable file for the specified process.
* @throws Win32Exception in case an error occurs
* @see <a href="http://msdn.microsoft.com/en-us/library/ms683217(VS.85).aspx">MSDN</a>
*/
public static String GetProcessImageFileName(HANDLE process) {
int size = 2048;
while (true) {
final char[] filePath = new char[size];
int length = Psapi.INSTANCE.GetProcessImageFileName(process,
filePath, filePath.length);
if(length == 0) {
if(Native.getLastError() != WinError.ERROR_INSUFFICIENT_BUFFER) {
throw new Win32Exception(Native.getLastError());
}
size += 2048;
} else {
return Native.toString(filePath);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ public void testReadAlignedCliTool() throws IOException {

public void testWriteAlignedCliTool() throws IOException, InterruptedException {
Process p = Runtime.getRuntime().exec(new String[] {"xattr", "-w", "JNA", "Java Native Access", testPath});
assertTrue(p.waitFor(10, TimeUnit.SECONDS));
assertTrue(p.waitFor(30, TimeUnit.SECONDS));
String resultString = XAttrUtil.getXAttr(testPath, "JNA");
assertEquals("Java Native Access", resultString);
}
Expand Down
23 changes: 21 additions & 2 deletions contrib/platform/test/com/sun/jna/platform/win32/Kernel32Test.java
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@
import com.sun.jna.ptr.ShortByReference;

import junit.framework.TestCase;
import org.junit.Assume;

public class Kernel32Test extends TestCase {

Expand Down Expand Up @@ -1381,13 +1382,31 @@ public final void testCreateRemoteThreadInvalid() throws IOException {

@Test
public void testCreateRemoteThread() {
Assume.assumeTrue("testCreateRemoteThread is only implemented for x86 + x86-64", Platform.isIntel());

Pointer addr = Kernel32.INSTANCE.VirtualAllocEx(
Kernel32.INSTANCE.GetCurrentProcess(), null, new SIZE_T(4096),
MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);

// mov eax, ecx; ret; int3
Memory localBuffer = new Memory(4096);
localBuffer.setInt(0, 0xccc3c18b);
localBuffer.clear();

if (Platform.is64Bit()) {
// mov eax, ecx; ret; int3
localBuffer.setByte(0, (byte) 0x8b); // MOV
localBuffer.setByte(1, (byte) 0xc1); // ECX -> EAX
localBuffer.setByte(2, (byte) 0xc3); // RET
localBuffer.setByte(3, (byte) 0xcc); // INT3
} else {
// mov eax, esp + 4; ret; int3
localBuffer.setByte(0, (byte) 0x8b); // MOV
localBuffer.setByte(1, (byte) 0x44); // ESP + 4bytes-> EAX
localBuffer.setByte(2, (byte) 0x24); //
localBuffer.setByte(3, (byte) 0x04); //
localBuffer.setByte(4, (byte) 0xc3); // RET
localBuffer.setByte(5, (byte) 0xcc); // INT3
}

IntByReference bytesWritten = new IntByReference();
Kernel32.INSTANCE.WriteProcessMemory(Kernel32.INSTANCE.GetCurrentProcess(),
addr, localBuffer, 4096, bytesWritten);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@

import com.sun.jna.CallbackReference;
import com.sun.jna.Native;
import com.sun.jna.Platform;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.platform.win32.BaseTSD.ULONG_PTR;
Expand Down Expand Up @@ -442,8 +443,14 @@ public LRESULT callback(HWND hwnd, int uMsg, WPARAM wParam, LPARAM lParam) {
}

SubClassedWindowProc subclass = new SubClassedWindowProc();
subclass.oldWindowProc = User32.INSTANCE.SetWindowLongPtr(hwndToSubclass, WinUser.GWL_WNDPROC,
CallbackReference.getFunctionPointer(subclass));
if(Platform.is64Bit()) {
subclass.oldWindowProc = User32.INSTANCE.SetWindowLongPtr(hwndToSubclass, WinUser.GWL_WNDPROC,
CallbackReference.getFunctionPointer(subclass));
} else {
// From MSDN: When compiling for 32-bit Windows, SetWindowLongPtr is defined as a call to the SetWindowLong function.
User32.INSTANCE.SetWindowLong(hwndToSubclass, WinUser.GWL_WNDPROC,
(int) Pointer.nativeValue(CallbackReference.getFunctionPointer(subclass)));
}
}

/**
Expand Down