Search code examples
javajna

JNA allocate buffer FIXED_INFO throws Invalid memory access


I have a simple call to new FIXED_INFO(buffer) that is resulting in java.lang.Error: Invalid memory access. I can't for the life of me figure out why this is failing:

import com.sun.jna.platform.win32.IPHlpAPI;
import com.sun.jna.platform.win32.IPHlpAPI.FIXED_INFO;

public void fixedInfoTest() {
  int bufferSize = 648;
  Memory buffer = new Memory(bufferSize);
  FIXED_INFO fixedInfo = new FIXED_INFO(buffer);
}

The exception is thrown on the "new FIXED_INFO(buffer)" call.

java.lang.Error: Invalid memory access
    at com.sun.jna.Native._getPointer(Native Method)
    at com.sun.jna.Native.getPointer(Native.java:2211)
    at com.sun.jna.Pointer.getPointer(Pointer.java:642)
    at com.sun.jna.Pointer.getValue(Pointer.java:367)
    at com.sun.jna.Structure.readField(Structure.java:732)
    at com.sun.jna.Structure.read(Structure.java:591)
    at com.sun.jna.Structure.autoRead(Structure.java:2141)
    at com.sun.jna.Structure.conditionalAutoRead(Structure.java:561)
    at com.sun.jna.Structure.updateStructureByReference(Structure.java:690)
    at com.sun.jna.Pointer.getValue(Pointer.java:367)
    at com.sun.jna.Structure.readField(Structure.java:732)
    at com.sun.jna.Structure.read(Structure.java:591)
    at com.sun.jna.platform.win32.IPHlpAPI$FIXED_INFO.<init>(IPHlpAPI.java:208)
    at com.magnicomp.test.unit.WindowsNativeTest.fixedInfoTest(WindowsNativeTest.java:43)

The above test does work sometimes but fails frequently. Test systems are Win 10, Win Server 2016. JNA version 5.4.0

In my production code the fixedInfo is used for:

IntByReference bufferSize = new IntByReference();
int result = IPHlpAPI.INSTANCE.GetNetworkParams(Pointer.NULL, bufferSize);
Validate.isTrue(result == WinNT.ERROR_BUFFER_OVERFLOW, 
                "GetNetworkParams buffer size failed: " + Win32Error.getErrorMessage(result));      

Memory buffer = new Memory(bufferSize.getValue());
FIXED_INFO fixedInfo = new FIXED_INFO(buffer);

result = IPHlpAPI.INSTANCE.GetNetworkParams(fixedInfo.getPointer(), bufferSize);
if (result != WinNT.ERROR_SUCCESS) {
    log.error("GetNetworkParams failed: %s", Win32Error.getErrorMessage(result));
    return;
}
String domain = new String(fixedInfo.DomainName).trim(); 

log.info("GetNetworkParams gave domain=\"%s\"", domain);

Here are some examples I've found:

https://www.javatips.net/api/oshi-master/oshi-core/src/main/java/oshi/software/os/windows/WindowsNetworkParams.java


Solution

  • I figured it out. This code works:

    IntByReference bufferSize = new IntByReference();
    int result = IPHlpAPI.INSTANCE.GetNetworkParams(Pointer.NULL, bufferSize);
    Validate.isTrue(result == WinNT.ERROR_BUFFER_OVERFLOW, 
            "GetNetworkParams buffer size failed: " + Win32Error.getErrorMessage(result));
    log.info("BufferSize=%d", bufferSize.getValue());
    
    Memory buffer = new Memory(bufferSize.getValue());
    
    // Now retrieve the actual FIXED_INFO
    result = IPHlpAPI.INSTANCE.GetNetworkParams(buffer, bufferSize);
    if (result != WinNT.ERROR_SUCCESS) {
        log.error("GetNetworkParams failed: %s", Win32Error.getErrorMessage(result));
        return;
    }
    FIXED_INFO fixedInfo = new FIXED_INFO(buffer);
    
    String domain = new String(fixedInfo.DomainName).trim(); 
    
    log.info("GetNetworkParams gave domain=\"%s\"", domain);