简体   繁体   中英

Java JNA Write Custom COM Interface of win32 API

I need write custom IShellFolder interface of win32 API. But I have a problem with calling method ParseDisplayName. Original of jna has a bug where pszDisplayName parameter of this method is String but win32 api has wstring as the parameter.

This is my code

String file = "c:\\Users\\Duchon\\Downloads\\Baumüller Brno, s.r.o.PS43668.prpkg";
PointerByReference psfDesktopPTR = new PointerByReference();
WinNT.HRESULT hResult = Shell32.INSTANCE.SHGetDesktopFolder(psfDesktopPTR);
   if (COMUtils.SUCCEEDED(hResult)) {
      IntByReference pcheaten = new IntByReference();
      PointerByReference ppidl = new PointerByReference();
      IntByReference pdwAttributes = new IntByReference();
      IShellFolder psfDesktop = IShellFolder.Converter.PointerToIShellFolder(psfDesktopPTR);
      hResult = psfDesktop.ParseDisplayName(null, null, new WString(file), pcheaten, ppidl, pdwAttributes);
      if (COMUtils.SUCCEEDED(hResult)) {
      }
}

This is my IShellFolder interface:

public interface IShellFolder {
   WinNT.HRESULT ParseDisplayName(WinDef.HWND hwnd, Pointer pbc, WString pszDisplayName, IntByReference pchEaten, PointerByReference ppidl, IntByReference pdwAttributes);

   public static class Converter {
      public static IShellFolder PointerToIShellFolder(final PointerByReference ptr) {
         final Pointer interfacePointer = ptr.getValue();
        final Pointer vTablePointer = interfacePointer.getPointer(0);
        final Pointer[] vTable = new Pointer[1];
        vTablePointer.read(0, vTable, 0, 1);
        return new IShellFolder() {
            @Override
            public WinNT.HRESULT ParseDisplayName(WinDef.HWND hwnd, Pointer pbc, WString pszDisplayName, IntByReference pchEaten, PointerByReference ppidl, IntByReference pdwAttributes) {
                Function f = Function.getFunction(vTable[0], Function.ALT_CONVENTION);
                return new WinNT.HRESULT(f.invokeInt(new Object[] {interfacePointer, hwnd, pbc, pszDisplayName, pchEaten, ppidl, pdwAttributes }));
            }
        };
      }
   }
}

And calling the method ParseDisplay throw exception java.lang.Error: Invalid memory access.

Can you help me when I have error.

Thank you very much.

You're almost there. Generally the way to customize an existing JNA interface is to define your own interface which extends it, and then write your own methods. For just the single method you're basically done, but the Converter class generates an anonymous class that you'll need to replicate entirely. This should work.

public interface MyIShellFolder extends com.sun.jna.platform.win32.COM.IShellFolder {

    // Define your own function invocation.
    // Since your argument signature includes a WString
    // it will be an overloaded version selected when you use the
    // WString argument.
    WinNT.HRESULT ParseDisplayName(WinDef.HWND hwnd, Pointer pbc, WString pszDisplayName, IntByReference pchEaten,
            PointerByReference ppidl, IntByReference pdwAttributes);

    // Do the same extending the inner class
    public static class Converter extends com.sun.jna.platform.win32.COM.IShellFolder.Converter {
        // You are overriding the superclass version of this so you have
        // to define the entire method
        public static MyIShellFolder PointerToIShellFolder(final PointerByReference ptr) {
            final Pointer interfacePointer = ptr.getValue();
            final Pointer vTablePointer = interfacePointer.getPointer(0);
            final Pointer[] vTable = new Pointer[13];
            vTablePointer.read(0, vTable, 0, 13);
            return new MyIShellFolder() {

                @Override
                public WinNT.HRESULT QueryInterface(REFIID byValue, PointerByReference pointerByReference) {
                    Function f = Function.getFunction(vTable[0], Function.ALT_CONVENTION);
                    return new WinNT.HRESULT(
                            f.invokeInt(new Object[] { interfacePointer, byValue, pointerByReference }));
                }

                @Override
                public int AddRef() {
                    Function f = Function.getFunction(vTable[1], Function.ALT_CONVENTION);
                    return f.invokeInt(new Object[] { interfacePointer });
                }

                public int Release() {
                    Function f = Function.getFunction(vTable[2], Function.ALT_CONVENTION);
                    return f.invokeInt(new Object[] { interfacePointer });
                }

                @Override
                public WinNT.HRESULT ParseDisplayName(WinDef.HWND hwnd, Pointer pbc, WString pszDisplayName,
                        IntByReference pchEaten, PointerByReference ppidl, IntByReference pdwAttributes) {
                    Function f = Function.getFunction(vTable[3], Function.ALT_CONVENTION);
                    return new WinNT.HRESULT(f.invokeInt(new Object[] { interfacePointer, hwnd, pbc, pszDisplayName,
                            pchEaten, ppidl, pdwAttributes }));
                }

                @Override
                public WinNT.HRESULT EnumObjects(WinDef.HWND hwnd, int grfFlags, PointerByReference ppenumIDList) {
                    Function f = Function.getFunction(vTable[4], Function.ALT_CONVENTION);
                    return new WinNT.HRESULT(
                            f.invokeInt(new Object[] { interfacePointer, hwnd, grfFlags, ppenumIDList }));
                }

                public WinNT.HRESULT BindToObject(Pointer pidl, Pointer pbc, REFIID riid, PointerByReference ppv) {
                    Function f = Function.getFunction(vTable[5], Function.ALT_CONVENTION);
                    return new WinNT.HRESULT(f.invokeInt(new Object[] { interfacePointer, pidl, pbc, riid, ppv }));
                }

                @Override
                public HRESULT BindToStorage(Pointer pidl, Pointer pbc, REFIID riid, PointerByReference ppv) {
                    Function f = Function.getFunction(vTable[6], Function.ALT_CONVENTION);
                    return new WinNT.HRESULT(f.invokeInt(new Object[] { interfacePointer, pidl, pbc, riid, ppv }));
                }

                @Override
                public HRESULT CompareIDs(WinDef.LPARAM lParam, Pointer pidl1, Pointer pidl2) {
                    Function f = Function.getFunction(vTable[7], Function.ALT_CONVENTION);
                    return new WinNT.HRESULT(f.invokeInt(new Object[] { interfacePointer, lParam, pidl1, pidl2 }));
                }

                @Override
                public HRESULT CreateViewObject(WinDef.HWND hwndOwner, REFIID riid, PointerByReference ppv) {
                    Function f = Function.getFunction(vTable[8], Function.ALT_CONVENTION);
                    return new WinNT.HRESULT(f.invokeInt(new Object[] { interfacePointer, hwndOwner, riid, ppv }));
                }

                @Override
                public HRESULT GetAttributesOf(int cidl, Pointer apidl, IntByReference rgfInOut) {
                    Function f = Function.getFunction(vTable[9], Function.ALT_CONVENTION);
                    return new WinNT.HRESULT(f.invokeInt(new Object[] { interfacePointer, cidl, apidl, rgfInOut }));
                }

                @Override
                public HRESULT GetUIObjectOf(WinDef.HWND hwndOwner, int cidl, Pointer apidl, REFIID riid,
                        IntByReference rgfReserved, PointerByReference ppv) {
                    Function f = Function.getFunction(vTable[10], Function.ALT_CONVENTION);
                    return new WinNT.HRESULT(f.invokeInt(
                            new Object[] { interfacePointer, hwndOwner, cidl, apidl, riid, rgfReserved, ppv }));
                }

                public WinNT.HRESULT GetDisplayNameOf(Pointer pidl, int flags, STRRET pName) {
                    Function f = Function.getFunction(vTable[11], Function.ALT_CONVENTION);
                    return new WinNT.HRESULT(f.invokeInt(new Object[] { interfacePointer, pidl, flags, pName }));
                }

                @Override
                public HRESULT SetNameOf(WinDef.HWND hwnd, Pointer pidl, String pszName, int uFlags,
                        PointerByReference ppidlOut) {
                    Function f = Function.getFunction(vTable[12], Function.ALT_CONVENTION);
                    return new WinNT.HRESULT(
                            f.invokeInt(new Object[] { interfacePointer, hwnd, pidl, pszName, uFlags, ppidlOut }));
                }

                // OLD VERSION THAT YOU WANT TO IGNORE BUT MUST DECLARE
                @Override
                public HRESULT ParseDisplayName(HWND hwnd, Pointer pbc, String pszDisplayName, IntByReference pchEaten,
                        PointerByReference ppidl, IntByReference pdwAttributes) {
                    return null;
                }
            };
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM