package com.sun.jna.examples.win32;
import com.sun.jna.examples.win32.W32API.HANDLE;
import com.sun.jna.examples.win32.W32API.SIZE_T;
import com.sun.jna.ptr.PointerByReference;
/**
*
* @author <a href="mailto:phil.kursawe@gmail.com">Philipp Kursawe</a>
*
*/
public final class Kernel32Helper {
public static void checkLastError(String message) throws RuntimeException {
int lastError = Kernel32.INSTANCE.GetLastError();
if (lastError != W32Errors.NO_ERROR) {
throw new RuntimeException(String.format("%s%s%s (%d)",
message != null ? message : "",
message != null ? ": " : "", formatSystemError(lastError),
lastError));
}
}
public static void checkLastError() throws RuntimeException {
checkLastError(null);
}
public static String formatSystemError(int code) {
Kernel32 lib = Kernel32.INSTANCE;
PointerByReference pref = new PointerByReference();
try {
lib.FormatMessage(Kernel32.FORMAT_MESSAGE_ALLOCATE_BUFFER
| Kernel32.FORMAT_MESSAGE_FROM_SYSTEM
| Kernel32.FORMAT_MESSAGE_IGNORE_INSERTS, null, code, 0,
pref, 0, null);
String s = pref.getValue().getString(0,
!Boolean.getBoolean("w32.ascii"));
s = s.replace(".\r", ".").replace(".\n", ".");
return s;
} finally {
lib.LocalFree(pref.getValue());
}
}
public interface FunctionCall<R> {
R call();
}
/**
* Runs the given runnable and then checks the the last error if the
* expected result does not match the one returned by the function call.
*
* @param call
* @throws RuntimeException
* if the last error was set after the function call did not
* returned the expected result.
*/
public static <R> void checkedCall(R expectedResult, FunctionCall<R> call) {
R result = call.call();
if (!result.equals(expectedResult)) {
checkLastError();
}
}
private static final SIZE_T zeroSize = new SIZE_T(0);
public static void checkedVirtualFreeEx(final HANDLE hProcess,
final int lpAddress, final int dwFreeType) {
checkedCall(true, new FunctionCall<Boolean>() {
public Boolean call() {
return Kernel32.INSTANCE.VirtualFreeEx(hProcess, lpAddress,
zeroSize, dwFreeType);
}
});
}
private Kernel32Helper() {
}
}