Ciao a tutti! Sto realizzando una piccola applicazione che recupera le informazioni delle cartelle speciali tanto in linux quanto in windows usando Java. L'API JNA (Java Native Application) mi fornisce un layer semplificato per acedere alle API scritte in C. Quando cerco però di usare l'API di Windows SHGetFileInfo per recuperare il nome localizzato della cartella, il programma Java va in crash sulla chiamata esterna.
Questi sono i listati del programma:
codice:
import com.sun.jna.platform.win32.ShlObj;
import com.sun.jna.platform.win32.Win32Exception;
import com.sun.jna.platform.win32.WinNT;
import com.sun.jna.platform.win32.WinNT.HRESULT;


public class ElencoSpecialFolder {
	private static class EnumCSIDL implements Iterable<Integer> {
		public static final int CSIDL_COMMON_APPDATA = (int)35;
		public static final int CSIDL_COMMON_PICTURES = (int)54;
		public static final int CSIDL_STARTUP = (int)7;
		public static final int CSIDL_FONTS = (int)20;
		public static final int CSIDL_CDBURN_AREA = (int)59;
		public static final int CSIDL_PROFILE = (int)40;
		public static final int CSIDL_DESKTOP = (int)0;
		public static final int CSIDL_INTERNET_CACHE = (int)32;
		public static final int CSIDL_COMMON_DESKTOPDIRECTORY = (int)25;
		public static final int CSIDL_COMMON_FAVORITES = (int)31;
		public static final int CSIDL_FLAG_CREATE = (int)32768;
		public static final int CSIDL_PROGRAM_FILES_COMMON = (int)43;
		public static final int CSIDL_MYPICTURES = (int)39;
		public static final int CSIDL_NETHOOD = (int)19;
		public static final int CSIDL_BITBUCKET = (int)10;
		public static final int CSIDL_COMMON_MUSIC = (int)53;
		public static final int CSIDL_PERSONAL = (int)5;
		public static final int CSIDL_HISTORY = (int)34;
		public static final int CSIDL_FAVORITES = (int)6;
		public static final int CSIDL_LOCAL_APPDATA = (int)28;
		public static final int CSIDL_SYSTEM = (int)37;
		public static final int CSIDL_SYSTEMX86 = (int)41;
		public static final int CSIDL_RESOURCES_LOCALIZED = (int)57;
		public static final int CSIDL_COMMON_ALTSTARTUP = (int)30;
		public static final int CSIDL_COMMON_DOCUMENTS = (int)46;
		public static final int CSIDL_APPDATA = (int)26;
		public static final int CSIDL_SENDTO = (int)9;
		public static final int CSIDL_RECENT = (int)8;
		public static final int CSIDL_COMMON_VIDEO = (int)55;
		public static final int CSIDL_PROGRAM_FILESX86 = (int)42;
		public static final int CSIDL_DESKTOPDIRECTORY = (int)16;
		public static final int CSIDL_FLAG_MASK = (int)65280;
		public static final int CSIDL_COMMON_STARTUP = (int)24;
		public static final int CSIDL_CONNECTIONS = (int)49;
		public static final int CSIDL_PRINTERS = (int)4;
		public static final int CSIDL_FLAG_DONT_VERIFY = (int)16384;
		public static final int CSIDL_COMMON_TEMPLATES = (int)45;
		public static final int CSIDL_PROGRAM_FILES = (int)38;
		public static final int CSIDL_PROGRAMS = (int)2;
		public static final int CSIDL_COMMON_OEM_LINKS = (int)58;
		public static final int CSIDL_COMPUTERSNEARME = (int)61;
		public static final int CSIDL_COMMON_ADMINTOOLS = (int)47;
		public static final int CSIDL_CONTROLS = (int)3;
		public static final int CSIDL_DRIVES = (int)17;
		public static final int CSIDL_TEMPLATES = (int)21;
		public static final int CSIDL_WINDOWS = (int)36;
		public static final int CSIDL_PROGRAM_FILES_COMMONX86 = (int)44;
		public static final int CSIDL_COMMON_PROGRAMS = (int)23;
		public static final int CSIDL_ALTSTARTUP = (int)29;
		public static final int CSIDL_PRINTHOOD = (int)27;
		public static final int CSIDL_INTERNET = (int)1;
		public static final int CSIDL_COMMON_STARTMENU = (int)22;
		public static final int CSIDL_RESOURCES = (int)56;
		public static final int CSIDL_STARTMENU = (int)11;
		public static final int CSIDL_COOKIES = (int)33;
		private List<Integer> listCSIDL=new ArrayList<Integer>();
		
		public EnumCSIDL() {
			listCSIDL.add(CSIDL_ADMINTOOLS);
			listCSIDL.add(CSIDL_NETWORK);
			listCSIDL.add(CSIDL_COMMON_APPDATA);
			listCSIDL.add(CSIDL_COMMON_PICTURES);
			listCSIDL.add(CSIDL_STARTUP);
			listCSIDL.add(CSIDL_FONTS);
			listCSIDL.add(CSIDL_CDBURN_AREA);
			listCSIDL.add(CSIDL_PROFILE);
			listCSIDL.add(CSIDL_DESKTOP);
			listCSIDL.add(CSIDL_INTERNET_CACHE);
			listCSIDL.add(CSIDL_COMMON_DESKTOPDIRECTORY);
			listCSIDL.add(CSIDL_COMMON_FAVORITES);
			listCSIDL.add(CSIDL_PROGRAM_FILES_COMMON);
			listCSIDL.add(CSIDL_MYPICTURES);
			listCSIDL.add(CSIDL_NETHOOD);
			listCSIDL.add(CSIDL_BITBUCKET);
			listCSIDL.add(CSIDL_COMMON_MUSIC);
			listCSIDL.add(CSIDL_PERSONAL);
			listCSIDL.add(CSIDL_HISTORY);
			listCSIDL.add(CSIDL_FAVORITES);
			listCSIDL.add(CSIDL_LOCAL_APPDATA);
			listCSIDL.add(CSIDL_SYSTEM);
			listCSIDL.add(CSIDL_SYSTEMX86);
			listCSIDL.add(CSIDL_RESOURCES_LOCALIZED);
			listCSIDL.add(CSIDL_COMMON_ALTSTARTUP);
			listCSIDL.add(CSIDL_COMMON_DOCUMENTS);
			listCSIDL.add(CSIDL_APPDATA);
			listCSIDL.add(CSIDL_SENDTO);
			listCSIDL.add(CSIDL_RECENT);
			listCSIDL.add(CSIDL_COMMON_VIDEO);
			listCSIDL.add(CSIDL_PROGRAM_FILESX86);
			listCSIDL.add(CSIDL_DESKTOPDIRECTORY);
			listCSIDL.add(CSIDL_COMMON_STARTUP);
			listCSIDL.add(CSIDL_CONNECTIONS);
			listCSIDL.add(CSIDL_PRINTERS);
			listCSIDL.add(CSIDL_COMMON_TEMPLATES);
			listCSIDL.add(CSIDL_PROGRAM_FILES);
			listCSIDL.add(CSIDL_PROGRAMS);
			listCSIDL.add(CSIDL_COMMON_OEM_LINKS);
			listCSIDL.add(CSIDL_COMPUTERSNEARME);
			listCSIDL.add(CSIDL_COMMON_ADMINTOOLS);
			listCSIDL.add(CSIDL_CONTROLS);
			listCSIDL.add(CSIDL_DRIVES);
			listCSIDL.add(CSIDL_TEMPLATES);
			listCSIDL.add(CSIDL_WINDOWS);
			listCSIDL.add(CSIDL_PROGRAM_FILES_COMMONX86);
			listCSIDL.add(CSIDL_COMMON_PROGRAMS);
			listCSIDL.add(CSIDL_ALTSTARTUP);
			listCSIDL.add(CSIDL_PRINTHOOD);
			listCSIDL.add(CSIDL_INTERNET);
			listCSIDL.add(CSIDL_COMMON_STARTMENU);
			listCSIDL.add(CSIDL_RESOURCES);
			listCSIDL.add(CSIDL_STARTMENU);
			listCSIDL.add(CSIDL_COOKIES);
		}
		@Override
		public Iterator<Integer> iterator() {
			return listCSIDL.iterator();
		}
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		EnumCSIDL cs=new EnumCSIDL();
		for (int i : cs) {
			try {
				String percorso=Shell32Util.getFolderPath(i);
				ITEMIDLIST.ByReference ppidl=new ITEMIDLIST.ByReference();
				String nome="";
				try {
					WString p=new WString(percorso);
					SHFILEINFO shfi=new SHFILEINFO();
				 	NativeLong result1=Shell32Library.SHGetFileInfo(p, 
					   WinNT.FILE_ATTRIBUTE_NORMAL,
					   shfi,
					   shfi.size(),
					   Shell32Library.SHGFI_PIDL | Shell32Library.SHGFI_DISPLAYNAME);
					System.out.println("result="+result1);
					if (result1.intValue()!=0) {
						nome="NoName";
					} else {
					    nome = new String(shfi.szDisplayName);
					} //endif
				} catch (LastErrorException e) {
					nome="SHFILEINFO Error:" + e.getLocalizedMessage();
				}
								
				System.out.println("nome="+nome+"; percorso="+percorso);
			} catch (Win32Exception e) {
				System.out.println("CSIDL="+i+" Errore: "+e.getLocalizedMessage());
			} 
		}
	}

}
codice:
import com.sun.jna.LastErrorException;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.NativeLong;
import com.sun.jna.WString;
import com.sun.jna.platform.win32.WinDef;
import com.sun.jna.platform.win32.WinNT;
import com.sun.jna.ptr.ShortByReference;


public class Shell32Library implements Library {
	
	public static int SHGFI_DISPLAYNAME = 0x000000200;
	public static int SHGFI_PIDL = 0x000000008;
	/**
	 * JNA Wrapper for library shell32

	 * This file was autogenerated by JNAerator,

	 * a tool written by Olivier Chafik that uses a few opensource projects..

	 * For help, please visit NativeLibs4Java , Rococoa, or JNA.
	 */
	static {
		Native.register("shell32");
	}
	/**
	 * Original signature : <code>DWORD_PTR SHGetFileInfo(__in LPCTSTR, DWORD, __inout SHFILEINFO*, UINT, UINT)</code>

	 * native declaration : line 34

	 * @deprecated use the safer methods {@link #SHGetFileInfo(short[], int, shell32.SHFILEINFO, int, int)} and {@link #SHGetFileInfo(com.sun.jna.ptr.ShortByReference, int, shell32.SHFILEINFO, int, int)} instead
	 */
	@Deprecated 
	public static native NativeLong SHGetFileInfo(ShortByReference pszPath, int dwFileAttributes, SHFILEINFO psfi, int cbFileInfo, int uFlags);
	/**
	 * Original signature : <code>DWORD_PTR SHGetFileInfo(__in LPCTSTR, DWORD, __inout SHFILEINFO*, UINT, UINT)</code>

	 * native declaration : line 34
	 */
	public static native NativeLong SHGetFileInfo(WString pszPath, int dwFileAttributes, SHFILEINFO psfi, int cbFileInfo, int uFlags) throws LastErrorException;
	public static native NativeLong SHGetFileInfo(ITEMIDLIST.ByReference pszPath, int dwFileAttributes, SHFILEINFO.ByReference psfi, int cbFileInfo, int uFlags) throws LastErrorException;
	
	/**
	 * Original signature : <code>HRESULT SHGetSpecialFolderLocation(__in HWND, __in int, __out ITEMIDLIST*)</code>

	 * native declaration : line 15
	 */
	public static native WinNT.HRESULT SHGetSpecialFolderLocation(WinDef.HWND hwndOwner, int nFolder, ITEMIDLIST.ByReference ppidl) throws LastErrorException;
	
}
codice:
import com.sun.jna.Structure;
import com.sun.jna.platform.win32.WinDef;
import com.sun.jna.platform.win32.WinNT.HANDLE;

public class SHFILEINFO extends Structure {
	/// C type : HICON
	public HANDLE hIcon;
	public int iIcon;
	public int dwAttributes;
	/// C type : TCHAR[MAX_PATH]
	public char[] szDisplayName = new char[(WinDef.MAX_PATH)];
	/// C type : TCHAR[80]
	public char[] szTypeName = new char[(80)];
	public SHFILEINFO() {
		super();
		initFieldOrder();
	}
	protected void initFieldOrder() {
		setFieldOrder(new java.lang.String[]{"hIcon", "iIcon", "dwAttributes", "szDisplayName", "szTypeName"});
	}
	/**
	 * @param hIcon C type : HICON

	 * @param szDisplayName C type : TCHAR[MAX_PATH]

	 * @param szTypeName C type : TCHAR[80]
	 */
	public SHFILEINFO(HANDLE hIcon, int iIcon, int dwAttributes, char[] szDisplayName, char[] szTypeName) {
		super();
		this.hIcon = hIcon;
		this.iIcon = iIcon;
		this.dwAttributes = dwAttributes;
		if (szDisplayName.length != this.szDisplayName.length) 
			throw new IllegalArgumentException("Wrong array size !");
		this.szDisplayName = szDisplayName;
		if (szTypeName.length != this.szTypeName.length) 
			throw new IllegalArgumentException("Wrong array size !");
		this.szTypeName = szTypeName;
		initFieldOrder();
	}
	public static class ByReference extends SHFILEINFO implements Structure.ByReference {
		
	};
	public static class ByValue extends SHFILEINFO implements Structure.ByValue {
		
	};
}
Durante l'esecuzione va subito in crash lamentando un errore nella chiamata nativa.

Qualcuno conosce JNA per aiutarmi?

Ciao