2021-11-27

Can JNA be used for a complex Windows DLL like IMAPI

I've managed to get COM4J to use some functionality in the windows IMAPI (CD writing).

However I've failed to get any of the calls that return SAFEARRAYs working, but this project doesn't appear to be currently active ...

The DLL is usually in C:\Windows\System32\imapi2.dll, and using it also requires using C:\Windows\System32\imapi2fs.dll

Looking around for a JAVA-COM bridge project that is active led me to JNA.

The remit of the project to simplify JAVA-COM bridging intrigued me .... however I fell at the first hurdle, and am hoping someone can help.

So far I've taken the Microsoft IMAPI examples and written a Powershell application, from which I have the series of calls I need to make to the API.[CDInterface][1]

The first thing you need to do with IMAPI is create an Instance of IDiskMaster2, so I've declared that via an Imapi2 interface, like so

public interface Imapi2 extends Library {
        Imapi2 INSTANCE = (Imapi2)
                Native.load("C:/Windows/System32/imapi2.dll" , Imapi2.class);

        public static class IDiscMaster2 extends Structure {
            int getCount;

            public int getCount() {
                return getCount;
            }
        }
        IDiscMaster2 createMsftDiscMaster2();
    }

Then in the main code

 Imapi2.IDiscMaster2 recorderList = Imapi2.INSTANCE.createMsftDiscMaster2();
        System.out.println("Found " + recorderList.getCount() + " Recorders");

Just putting 'imapi2' in the call to Native.load() didn't work either.

I'm guessing I'm doing something fundamentally wrong, but it's not clear how you get JNA to 'see' a new dll you want to interface to ..... and also I am kind of afraid there is something very different about this API from the othe APIs that people are using JNA to talk to, so may not be worth trying!

public interface Imapi2 extends Library {
        Imapi2 INSTANCE = (Imapi2)
                Native.load("C:/Windows/System32/imapi2.dll" , Imapi2.class);

        public class IDiscMaster2 extends Dispatch {

            public static final CLSID CLSID_MsftDiscMaster2 = new CLSID("2735412F-7F64-5B0F-8F00-5D77AFBE261E");

            public IDiscMaster2() {
            }

            private IDiscMaster2(Pointer pvInstance) {
                super(pvInstance);
            }

            public static IDiscMaster2 create() {
                PointerByReference pbr = new PointerByReference();

                WinNT.HRESULT hres = Ole32.INSTANCE.CoCreateInstance(CLSID_MsftDiscMaster2, null, WTypes.CLSCTX_ALL, null, pbr);
                if (COMUtils.FAILED(hres)) {
                    System.out.println("ERROR: Failed to create instance");
                    return null;
                }

                return new IDiscMaster2(pbr.getValue());
            }

            public WinNT.HRESULT _getCount(Pointer count ){
                return (WinNT.HRESULT) _invokeNativeObject(2, new Object[]{count}, WinNT.HRESULT.class);
            }

            public long getCount() {
                try {
                    long count = -1;
                    Pointer ptr = new Pointer(count);
                    WinNT.HRESULT result = _getCount(ptr);

                    COMUtils.checkRC(result);

                    return count;
                } catch ( Exception e ) {
                    System.out.println("Error : " + e.getMessage());
                }
                return -1;
            }
} 

Then invocation in main changed to

Imapi2 imapi2Lib = Imapi2.INSTANCE;
        Imapi2.IDiscMaster2 recorderList = new Imapi2.IDiscMaster2();

        System.out.println("Found " + recorderList.getCount() + " Recorders");

IntelliJ shows up uninvoked methods, so it doesn't look like create() is getting called. Not sure if this is because I need to call it, or down to the function implementing IDispatch not IUnknown. [1]: https://github.com/nosdod/CDInterface



from Recent Questions - Stack Overflow https://ift.tt/3DUEZ1C
https://ift.tt/eA8V8J

No comments:

Post a Comment