<div dir="ltr">Thanks for the work on project Panama. It's an exciting technology. I'm using it to make native operating system services available to Java.<div><br></div><div>On Windows I've run into an issue. This C/C++ Windows code:<div><div><br></div><div>    BOOL res = WriteFile(INVALID_HANDLE_VALUE, NULL, 0, NULL, NULL);<br>    DWORD err = GetLastError();<br></div></div><div>    printf("WriteFile result: %d, GetLastError result: %d\n", res, err);<br></div><div><br></div><div>prints (as expected):</div><div><br></div><div>    WriteFile result: 0, GetLastError result: 6<br></div><div><br></div><div>6 is the value of the constant ERROR_INVALID_HANDLE.</div><div><br></div><div>Using panama, I've translated the code to Java. The result is:</div><div><br></div><div>Without debugger, the output is the same. Everything is ok.</div><div><br></div><div>With the debugger, the result is incorrect:</div><div><br></div><div><div>    WriteFile result: 0, GetLastError result: 0<br></div><div><br></div><div>This is incorrect. WriteFile() indicates an error, but GetLastError() returns 0 (= NO_ERROR). Could it be that the debugger calls another Windows API function between those two functions, resetting the last error?</div><div><br></div><div>In my project that's a major issue. Since the software behaves incorrectly with the debugger, the software can no longer be debugged. This doesn't just affect it when debugging this particular piece of code but anytime this code is run in a debugging session.</div><div><br></div><div>Is there something I'm not doing incorrectly? Or is there a fix or workaround?</div><div><br></div><div>Here's the Java code:</div><div><br></div><div><pre style="background-color:rgb(43,43,43);color:rgb(169,183,198);font-family:"JetBrains Mono",monospace;font-size:9.8pt"><span style="color:rgb(204,120,50)">import </span>java.lang.foreign.*<span style="color:rgb(204,120,50)">;<br></span><span style="color:rgb(204,120,50)">import </span>java.lang.invoke.MethodHandle<span style="color:rgb(204,120,50)">;<br></span><span style="color:rgb(204,120,50)"><br></span><span style="color:rgb(204,120,50)">import static </span>java.lang.foreign.MemoryAddress.<span style="color:rgb(152,118,170);font-style:italic">NULL</span><span style="color:rgb(204,120,50)">;<br></span><span style="color:rgb(204,120,50)">import static </span>java.lang.foreign.ValueLayout.<span style="color:rgb(152,118,170);font-style:italic">ADDRESS</span><span style="color:rgb(204,120,50)">;<br></span><span style="color:rgb(204,120,50)">import static </span>java.lang.foreign.ValueLayout.<span style="color:rgb(152,118,170);font-style:italic">JAVA_INT</span><span style="color:rgb(204,120,50)">;<br></span><span style="color:rgb(204,120,50)"><br></span><span style="color:rgb(204,120,50)">public class </span>WinApi {<br>    <span style="color:rgb(204,120,50)">static final </span>MethodHandle <span style="color:rgb(152,118,170);font-style:italic">WriteFile$Func</span><span style="color:rgb(204,120,50)">;<br></span><span style="color:rgb(204,120,50)">    static final </span>MethodHandle <span style="color:rgb(152,118,170);font-style:italic">GetLastError$Func</span><span style="color:rgb(204,120,50)">;<br></span><span style="color:rgb(204,120,50)">    static final </span>MemoryAddress <span style="color:rgb(152,118,170);font-style:italic">INVALID_HANDLE_VALUE </span>= MemoryAddress.<span style="font-style:italic">ofLong</span>(-<span style="color:rgb(104,151,187)">1</span>)<span style="color:rgb(204,120,50)">;<br></span><span style="color:rgb(204,120,50)"><br></span><span style="color:rgb(204,120,50)">    static </span>{<br>        <span style="color:rgb(204,120,50)">var </span>linker = Linker.<span style="font-style:italic">nativeLinker</span>()<span style="color:rgb(204,120,50)">;<br></span><span style="color:rgb(204,120,50)">        var </span>lookup = SymbolLookup.<span style="font-style:italic">libraryLookup</span>(<span style="color:rgb(106,135,89)">"Kernel32"</span><span style="color:rgb(204,120,50)">, </span>MemorySession.<span style="font-style:italic">global</span>())<span style="color:rgb(204,120,50)">;<br></span><span style="color:rgb(204,120,50)"><br></span><span style="color:rgb(204,120,50)">        </span><span style="color:rgb(152,118,170);font-style:italic">WriteFile$Func </span>= linker.downcallHandle(<br>                lookup.lookup(<span style="color:rgb(106,135,89)">"WriteFile"</span>).get()<span style="color:rgb(204,120,50)">,<br></span><span style="color:rgb(204,120,50)">                </span>FunctionDescriptor.<span style="font-style:italic">of</span>(<span style="color:rgb(152,118,170);font-style:italic">JAVA_INT</span><span style="color:rgb(204,120,50)">, </span><span style="color:rgb(152,118,170);font-style:italic">ADDRESS</span><span style="color:rgb(204,120,50)">, </span><span style="color:rgb(152,118,170);font-style:italic">ADDRESS</span><span style="color:rgb(204,120,50)">, </span><span style="color:rgb(152,118,170);font-style:italic">JAVA_INT</span><span style="color:rgb(204,120,50)">, </span><span style="color:rgb(152,118,170);font-style:italic">ADDRESS</span><span style="color:rgb(204,120,50)">, </span><span style="color:rgb(152,118,170);font-style:italic">ADDRESS</span>)<br>        )<span style="color:rgb(204,120,50)">;<br></span><span style="color:rgb(204,120,50)">        </span><span style="color:rgb(152,118,170);font-style:italic">GetLastError$Func </span>= linker.downcallHandle(<br>                lookup.lookup(<span style="color:rgb(106,135,89)">"GetLastError"</span>).get()<span style="color:rgb(204,120,50)">,<br></span><span style="color:rgb(204,120,50)">                </span>FunctionDescriptor.<span style="font-style:italic">of</span>(<span style="color:rgb(152,118,170);font-style:italic">JAVA_INT</span>)<br>        )<span style="color:rgb(204,120,50)">;<br></span><span style="color:rgb(204,120,50)">    </span>}<br><br>    <span style="color:rgb(204,120,50)">public static void </span><span style="color:rgb(255,198,109)">main</span>(String[] args) {<br>        <span style="color:rgb(204,120,50)">var </span>res = <span style="font-style:italic">WriteFile</span>(<span style="color:rgb(152,118,170);font-style:italic">INVALID_HANDLE_VALUE</span><span style="color:rgb(204,120,50)">, </span><span style="color:rgb(152,118,170);font-style:italic">NULL</span><span style="color:rgb(204,120,50)">, </span><span style="color:rgb(104,151,187)">0</span><span style="color:rgb(204,120,50)">, </span><span style="color:rgb(152,118,170);font-style:italic">NULL</span><span style="color:rgb(204,120,50)">, </span><span style="color:rgb(152,118,170);font-style:italic">NULL</span>)<span style="color:rgb(204,120,50)">;<br></span><span style="color:rgb(204,120,50)">        var </span>err = <span style="font-style:italic">GetLastError</span>()<span style="color:rgb(204,120,50)">;<br></span><span style="color:rgb(204,120,50)">        </span>System.<span style="color:rgb(152,118,170);font-style:italic">out</span>.printf(<span style="color:rgb(106,135,89)">"WriteFile result: %d, GetLastError result: %d</span><span style="color:rgb(204,120,50)">\n</span><span style="color:rgb(106,135,89)">"</span><span style="color:rgb(204,120,50)">, </span>res<span style="color:rgb(204,120,50)">, </span>err)<span style="color:rgb(204,120,50)">;<br></span><span style="color:rgb(204,120,50)">    </span>}<br><br>    <span style="color:rgb(204,120,50)">static int </span><span style="color:rgb(255,198,109)">WriteFile</span>(MemoryAddress hFile<span style="color:rgb(204,120,50)">, </span>MemoryAddress lpBuffer<span style="color:rgb(204,120,50)">, int </span>nNumberOfBytesToWrite<span style="color:rgb(204,120,50)">,<br></span><span style="color:rgb(204,120,50)">                         </span>MemoryAddress lpNumberOfBytesWritten<span style="color:rgb(204,120,50)">, </span>MemoryAddress lpOverlapped) {<br>        <span style="color:rgb(204,120,50)">try </span>{<br>            <span style="color:rgb(204,120,50)">return </span>(<span style="color:rgb(204,120,50)">int</span>) <span style="color:rgb(152,118,170);font-style:italic">WriteFile$Func</span>.invokeExact((Addressable)hFile<span style="color:rgb(204,120,50)">, </span>(Addressable)lpBuffer<span style="color:rgb(204,120,50)">, </span>nNumberOfBytesToWrite<span style="color:rgb(204,120,50)">,<br></span><span style="color:rgb(204,120,50)">                    </span>(Addressable)lpNumberOfBytesWritten<span style="color:rgb(204,120,50)">, </span>(Addressable)lpOverlapped)<span style="color:rgb(204,120,50)">;<br></span><span style="color:rgb(204,120,50)">        </span>} <span style="color:rgb(204,120,50)">catch </span>(Throwable e) {<br>            <span style="color:rgb(204,120,50)">throw new </span>RuntimeException(e)<span style="color:rgb(204,120,50)">;<br></span><span style="color:rgb(204,120,50)">        </span>}<br>    }<br><br>    <span style="color:rgb(204,120,50)">static int </span><span style="color:rgb(255,198,109)">GetLastError</span>() {<br>        <span style="color:rgb(204,120,50)">try </span>{<br>            <span style="color:rgb(204,120,50)">return </span>(<span style="color:rgb(204,120,50)">int</span>) <span style="color:rgb(152,118,170);font-style:italic">GetLastError$Func</span>.invokeExact()<span style="color:rgb(204,120,50)">;<br></span><span style="color:rgb(204,120,50)">        </span>} <span style="color:rgb(204,120,50)">catch </span>(Throwable e) {<br>            <span style="color:rgb(204,120,50)">throw new </span>RuntimeException(e)<span style="color:rgb(204,120,50)">;<br></span><span style="color:rgb(204,120,50)">        </span>}<br>    }<br>}</pre></div><div><br></div></div><div>Cheers</div><div>Manuel</div><div><br></div></div></div>