{"record":{"id":"336ded1d5dff8f97","repo":"java-native-access/jna","slug":"win32exception-from-native-getlasterror-when-sizeofresource","errorCode":null,"errorMessage":"Win32Exception from native GetLastError when SizeofResource returned 0","messagePattern":"Win32Exception from native GetLastError when SizeofResource returned 0","errorType":"error_code","errorClass":"Win32Exception","httpStatus":null,"severity":"error","filePath":"contrib/platform/src/com/sun/jna/platform/win32/Kernel32Util.java","lineNumber":1022,"sourceCode":"            } catch (NumberFormatException e) {\n                n = new Memory(Native.WCHAR_SIZE * (name.length() + 1));\n                n.setWideString(0, name);\n            }\n\n            HRSRC hrsrc = Kernel32.INSTANCE.FindResource(target, n, t);\n            if (hrsrc == null) {\n                throw new Win32Exception(Kernel32.INSTANCE.GetLastError());\n            }\n\n            // according to MSDN, on 32 bit Windows or newer, calling FreeResource() is not necessary - and in fact does nothing but return false.\n            HANDLE loaded = Kernel32.INSTANCE.LoadResource(target, hrsrc);\n            if (loaded == null) {\n                throw new Win32Exception(Kernel32.INSTANCE.GetLastError());\n            }\n\n            length = Kernel32.INSTANCE.SizeofResource(target, hrsrc);\n            if (length == 0) {\n                throw new Win32Exception(Kernel32.INSTANCE.GetLastError());\n            }\n\n            // MSDN: It is not necessary to unlock resources because the system automatically deletes them when the process that created them terminates.\n            // MSDN does not say that LockResource sets GetLastError\n            start = Kernel32.INSTANCE.LockResource(loaded);\n            if (start == null) {\n                throw new IllegalStateException(\"LockResource returned null.\");\n            }\n            // have to capture it into a byte array before you free the library, otherwise bad things happen.\n            results = start.getByteArray(0, length);\n        } catch (Win32Exception we) {\n            err = we;\n        } finally {\n            // from what I can tell on MSDN, the only thing that needs cleanup on this is the HMODULE from LoadLibrary\n            if (target != null) {\n                if (!Kernel32.INSTANCE.FreeLibrary(target)) {\n                    Win32Exception we = new Win32Exception(Kernel32.INSTANCE.GetLastError());\n                    if (err != null) {","sourceCodeStart":1004,"sourceCodeEnd":1040,"githubUrl":"https://github.com/java-native-access/jna/blob/d036ad9781adad4b66693e8fa7098e4ac665e0a3/contrib/platform/src/com/sun/jna/platform/win32/Kernel32Util.java#L1004-L1040","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Catch Win32Exception and check errorCode (e.g. ERROR_INVALID_HANDLE 6)","Ensure the same HMODULE instance is used for all calls in the sequence","Treat size 0 as 'empty resource' and skip/handle gracefully before copying bytes","Re-extract the resource from a known-good copy of the binary"],"exampleFix":"// before\nbyte[] data = Kernel32Util.getResource(h, type, name); // throws on empty resource\n// after\ntry {\n    byte[] data = Kernel32Util.getResource(h, type, name);\n} catch (Win32Exception e) {\n    if (e.getErrorCode().intValue() == WinError.ERROR_INVALID_HANDLE) {\n        throw new IllegalStateException(\"Resource size could not be read\", e);\n    }\n    throw e;\n}","handlingStrategy":"try-catch","validationCode":"// Pre-check by loading as datafile and probing size indirectly is not exposed;\n// instead guard the module handle:\nif (target == null) throw new IllegalArgumentException(\"target module handle must not be null\");","typeGuard":"boolean canSize(HMODULE target, HRSRC hrsrc) {\n    DWORD sz = Kernel32.INSTANCE.SizeofResource(target, hrsrc);\n    return sz != null && sz.intValue() > 0;\n}","tryCatchPattern":"try {\n    byte[] data = Kernel32Util.getResource(h, type, name);\n} catch (Win32Exception e) {\n    // size 0 / invalid handle during SizeofResource\n    log.warn(\"Cannot size resource \" + name + \" code=\" + e.getErrorCode(), e);\n    throw e;\n}","preventionTips":["Use the same HMODULE for the whole Find/Load/Size/Lock sequence","Treat zero-size as an 'empty resource' condition in your own pre-checks","Avoid double-loading the module with different flags","Validate downloaded/shipped binaries before reading resources"],"tags":["win32","jni","native","resources"],"backgroundTag":"api-error-response","analyzedSha":"d036ad9781adad4b66693e8fa7098e4ac665e0a3","analyzedAt":"2026-09-12T06:50:59.239Z","contentChangedAt":"2026-09-12T06:50:59.239Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}