0

I'm trying to convert this function to JNA:

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.mycode.winapi;

import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.NativeLong;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.WString;
import com.sun.jna.platform.win32.Sspi;
import com.sun.jna.platform.win32.WinDef.HBITMAP;
import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.platform.win32.WinDef.ULONG;
import com.sun.jna.platform.win32.WinDef.ULONGByReference;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.PointerByReference;
import java.util.Arrays;
import java.util.List;

/**
 * Credui
 * @author
 */
public interface Credui extends Library {

    /**
     * INSTANCE
     */
    Credui INSTANCE = (Credui) Native.loadLibrary("Credui", Credui.class);

    /**
     * CredUIPromptForWindowsCredentialsW
     * DWORD WINAPI CredUIPromptForWindowsCredentials(
     * _In_opt_    PCREDUI_INFO pUiInfo,
     * _In_        DWORD        dwAuthError,
     * _Inout_     ULONG        *pulAuthPackage,
     * _In_opt_    LPCVOID      pvInAuthBuffer,
     * _In_        ULONG        ulInAuthBufferSize,
     * _Out_       LPVOID       *ppvOutAuthBuffer,
     * _Out_       ULONG        *pulOutAuthBufferSize,
     * _Inout_opt_ BOOL         *pfSave,
     * _In_        DWORD        dwFlags
     * );
     * 
     * @return 
     */
    int CredUIPromptForWindowsCredentialsW(
        PointerByReference pUiInfo,
        int dwAuthError,
        ULONGByReference pulAuthPackage,
        Pointer pvInAuthBuffer,
        ULONG ulInAuthBufferSize,
        PointerByReference ppvOutAuthBuffer,
        ULONGByReference pulOutAuthBufferSize,
        IntByReference pfSave,
        int dwFlags
        );

    /**
     * CREDUI_INFO
     * 
     * typedef struct _CREDUI_INFO {
     * DWORD   cbSize;
     * HWND    hwndParent;
     * PCTSTR  pszMessageText;
     * PCTSTR  pszCaptionText;
     * HBITMAP hbmBanner;
     * } CREDUI_INFO, *PCREDUI_INFO;
     */
    public static class CREDUI_INFO extends Structure {

        public int cbSize;

        public HWND hwndParent;

        public WString pszMessageText;

        public WString pszCaptionText;

        public HBITMAP hbmBanner;

        /**
         * getFieldOrder
         * @return 
         */
        @Override
        protected List getFieldOrder() {
            return Arrays.asList(new String[]{
                "cbSize", 
                "hwndParent",
                "pszMessageText",
                "pszCaptionText",
                "hbmBanner",
            });
        }
    }
}

And Call:

Credui.CREDUI_INFO info = new Credui.CREDUI_INFO();

info.cbSize = info.size();
info.pszCaptionText = new WString(caption);
info.pszMessageText = new WString(message);

PointerByReference pinfo = new PointerByReference(info.getPointer());

WinDef.ULONGByReference authPackage = new WinDef.ULONGByReference();
PointerByReference outCredBuffer = new PointerByReference();
WinDef.ULONGByReference outCredSize = new WinDef.ULONGByReference();
IntByReference save = new IntByReference(0);
WinDef.ULONG ulInAuthBufferSize = new WinDef.ULONG(0);

int result = Credui.INSTANCE.CredUIPromptForWindowsCredentialsW(pinfo, 0, authPackage, 
                null, ulInAuthBufferSize, outCredBuffer, outCredSize, save, 0);

if( result == 0 ) {         
}

I tried to declare pUiInfo in CredUIPromptForWindowsCredentialsW as Pointer or PointerByReference.

Function CredUIPromptForWindowsCredentialsW returns Code 160 ("Bad parameter). What's wrong?

Toby Speight
  • 27,591
  • 48
  • 66
  • 103

1 Answers1

0

Because Java does not have a distinction between "by value" and "by reference", JNA infers which it should use for a given Structure usage based by the most common usage patterns.

In this case, the native PCREDUI_INFO means struct*, which is the more common usage of structs as function parameters. JNA will default to using the address of your Structure's allocated memory as the native argument, and will automatically sync the Structure's Java fields with native memory before and after the native call.

If you only pass Structure.getPointer(), then no sync will be performed and your native code will get a block of memory with undefined contents (thus your "bad parameter" error).

technomage
  • 9,861
  • 2
  • 26
  • 40