Windows DXGI Experiment
Daniel Jarabek
jarabekit at gmail.com
Mon Feb 24 21:21:37 UTC 2025
Because of how Microsoft lays out the IID struct (int, short, short,
byte[8]), shouldn't the UUID be this?
buffer.
putInt(0x770aae78).
putInt(0x4dbaf26f).
putInt(0x3c2529a8).
putInt(0x87b3d183);
Running this in a Windows 11 VM, I get "Invocation result: 00000000"
(which I assume is a success).
However, looking at the code, I don't see why the ByteBuffer is needed
at all. Also, the IID/UUID struct can be represented using the panama
API as a StructLayout:
MemoryLayout.structLayout(
ValueLayout.JAVA_INT.withName("data1"),
ValueLayout.JAVA_SHORT.withName("data2"),
ValueLayout.JAVA_SHORT.withName("data3"),
MemoryLayout.sequenceLayout(8,
ValueLayout.JAVA_BYTE).withName("data4")
);
-DJ
On 2/24/25 13:58, Hugo De Vaan wrote:
> Greetings fellow developers,
>
> I've been trying to create a Java layer atop Microsoft's DXGI library
> in an attempt to get Java to work with Desktop Duplication.
> Unfortunately, I can't seem to create a DXGI factory. I can locate the
> symbol just fine, and I've double checked the UUID value for the type
> (using an earlier message in this mailing list, dating back to
> September 2020). When invoking the method handle, I get the 0x80004002
> HRESULT, which translates to "No such interface supported". I'm not
> sure what I'm doing wrong here, so I would appreciate any help.
>
> [code]
> import java.lang.foreign.Arena;
> import java.lang.foreign.FunctionDescriptor;
> import java.lang.foreign.Linker;
> import java.lang.foreign.MemorySegment;
> import java.lang.foreign.SymbolLookup;
> import java.lang.foreign.ValueLayout;
> import java.lang.invoke.MethodHandle;
> import java.nio.ByteBuffer;
> import java.nio.ByteOrder;
> import java.util.HexFormat;
>
> public final class DXGIExperiment {
> public static final void main(String[] args) {
> try {
> System.load("C:\\Windows\\System32\\dxgi.dll");
>
> Linker linker = Linker.nativeLinker();
>
> SymbolLookup symbols = SymbolLookup.libraryLookup(
> "C:\\Windows\\System32\\dxgi.dll", Arena.global());
>
> /* MemoryLayout BIT128 = MemoryLayout.
> sequenceLayout(16, ValueLayout.JAVA_BYTE); */
>
> /* Giving the 128bit UUID directly to the function doesn't
> * work - the layout is not supported:
> *
> * FunctionDescriptor descriptor = FunctionDescriptor.of(
> * ValueLayout.JAVA_INT, BIT128, ValueLayout.ADDRESS);
> */
>
> FunctionDescriptor descriptor = FunctionDescriptor.of(
> ValueLayout.JAVA_INT, ValueLayout.ADDRESS,
> ValueLayout.ADDRESS);
>
> MemorySegment createFactory =
> symbols.find("CreateDXGIFactory1").get();
>
> MethodHandle handle = linker.
> downcallHandle(createFactory, descriptor);
>
> System.out.println("Handle to CreateDXGIFactory1 created.");
>
> byte[] uuidArray = new byte[16];
> ByteBuffer buffer = ByteBuffer.wrap(uuidArray);
> buffer.order(ByteOrder.LITTLE_ENDIAN);
>
> buffer.
> putInt(0x770aae78).
> putInt(0xf26f4dba).
> putInt(0xa829253c).
> putInt(0x83d1b387);
>
> MemorySegment factoryPointer =
> Arena.global().allocate(ValueLayout.ADDRESS);
>
> MemorySegment uuidValue =
> Arena.global().allocate(16);
>
> uuidValue.setAtIndex(ValueLayout.JAVA_INT, 0,
> buffer.getInt(0));
> uuidValue.setAtIndex(ValueLayout.JAVA_INT, 1,
> buffer.getInt(4));
> uuidValue.setAtIndex(ValueLayout.JAVA_INT, 2,
> buffer.getInt(8));
> uuidValue.setAtIndex(ValueLayout.JAVA_INT, 3,
> buffer.getInt(12));
>
> int hresult = (int) handle.
> invokeExact(uuidValue, factoryPointer);
>
> System.out.println(
> "Invocation result: " +
> HexFormat.of().toHexDigits(hresult));
> } catch (Throwable t) {
> t.printStackTrace();
> }
> }
> }
> [/code]
>
> PS: This was tried on Windows 10 Pro, 64 bit, build 19045 and running
> GraalVM 21+35.1
>
> Regards,
> Hugo
More information about the panama-dev
mailing list