java-native-access/jna · error · Win32Exception

Win32Exception from native GetLastError when SizeofResource

Error message

Win32Exception from native GetLastError when SizeofResource returned 0

What it means

Kernel32Util throws this Win32Exception when Kernel32.INSTANCE.SizeofResource returns 0 after the resource was found and loaded. A zero size means the resource has no data or the size could not be determined; the native GetLastError code is wrapped to expose the underlying reason.

Source

Thrown at contrib/platform/src/com/sun/jna/platform/win32/Kernel32Util.java:1022

            } catch (NumberFormatException e) {
                n = new Memory(Native.WCHAR_SIZE * (name.length() + 1));
                n.setWideString(0, name);
            }

            HRSRC hrsrc = Kernel32.INSTANCE.FindResource(target, n, t);
            if (hrsrc == null) {
                throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
            }

            // according to MSDN, on 32 bit Windows or newer, calling FreeResource() is not necessary - and in fact does nothing but return false.
            HANDLE loaded = Kernel32.INSTANCE.LoadResource(target, hrsrc);
            if (loaded == null) {
                throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
            }

            length = Kernel32.INSTANCE.SizeofResource(target, hrsrc);
            if (length == 0) {
                throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
            }

            // MSDN: It is not necessary to unlock resources because the system automatically deletes them when the process that created them terminates.
            // MSDN does not say that LockResource sets GetLastError
            start = Kernel32.INSTANCE.LockResource(loaded);
            if (start == null) {
                throw new IllegalStateException("LockResource returned null.");
            }
            // have to capture it into a byte array before you free the library, otherwise bad things happen.
            results = start.getByteArray(0, length);
        } catch (Win32Exception we) {
            err = we;
        } finally {
            // from what I can tell on MSDN, the only thing that needs cleanup on this is the HMODULE from LoadLibrary
            if (target != null) {
                if (!Kernel32.INSTANCE.FreeLibrary(target)) {
                    Win32Exception we = new Win32Exception(Kernel32.INSTANCE.GetLastError());
                    if (err != null) {

View on GitHub (pinned to d036ad9781)

Solutions

  1. Catch Win32Exception and check errorCode (e.g. ERROR_INVALID_HANDLE 6)
  2. Ensure the same HMODULE instance is used for all calls in the sequence
  3. Treat size 0 as 'empty resource' and skip/handle gracefully before copying bytes
  4. Re-extract the resource from a known-good copy of the binary

Example fix

// before
byte[] data = Kernel32Util.getResource(h, type, name); // throws on empty resource
// after
try {
    byte[] data = Kernel32Util.getResource(h, type, name);
} catch (Win32Exception e) {
    if (e.getErrorCode().intValue() == WinError.ERROR_INVALID_HANDLE) {
        throw new IllegalStateException("Resource size could not be read", e);
    }
    throw e;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-check by loading as datafile and probing size indirectly is not exposed;
// instead guard the module handle:
if (target == null) throw new IllegalArgumentException("target module handle must not be null");

Type guard

boolean canSize(HMODULE target, HRSRC hrsrc) {
    DWORD sz = Kernel32.INSTANCE.SizeofResource(target, hrsrc);
    return sz != null && sz.intValue() > 0;
}

Try / catch

try {
    byte[] data = Kernel32Util.getResource(h, type, name);
} catch (Win32Exception e) {
    // size 0 / invalid handle during SizeofResource
    log.warn("Cannot size resource " + name + " code=" + e.getErrorCode(), e);
    throw e;
}

Prevention

When it happens

Trigger: Calling Kernel32Util.getResource(...) where FindResource and LoadResource succeeded but SizeofResource(target, hrsrc) returns 0 — zero-length resources, or an hrsrc/module handle combination the OS cannot size (e.g. handle from a different module instance).

Common situations: Reading resources from a module loaded twice with different flags so the HRSRC belongs to another HMODULE; resources intentionally stored empty; maliciously or accidentally stripped resource sections.

Related errors


AI-assisted analysis of java-native-access/jna@d036ad9781 (2026-09-12). Data as JSON: /api/errors/336ded1d5dff8f97. Report an issue: GitHub.