

![]() | Start a set with this search |
![]() | Include this search in one of my sets |
![]() | Exclude this search from one of my sets |
![]() | Permalink to these results Paste this link in email or IM: |
| Atom feed for tracking future search results Paste this URL into your reader: |
1 message in net.java.dev.jna.users[jna-users] Weird Struct/Class Behavi...| From | Sent On | Attachments |
|---|---|---|
| Croteau, Beau | Feb 24, 2009 12:22 pm |

![]() | Permalink for this message Paste this link in email or IM: |
![]() | Permalink for this thread Paste this link in email or IM: |
| Atom feed for this thread Paste this URL into your reader: |
| Subject: | [jna-users] Weird Struct/Class Behavior for JNA on Windows | Actions... |
|---|---|---|
| From: | Croteau, Beau (Beau...@ca.com) | |
| Date: | Feb 24, 2009 12:22:39 pm | |
| List: | net.java.dev.jna.users | |
All,
I've been using JNA on and off for a few months for various development tasks, but I'm currently running in to a problem that I can't quite track down.
Basically I'm attempting to call in to the Windows Version.DLL library to get the version of a requested DLL.
The code I have to support this looks like this: First, the supporting class mapping (FixedFileInfo.java): package test.fv; import com.sun.jna.*; import com.sun.jna.ptr.*; public class FixedFileInfo extends Structure { public int dwSignature; public int dwStrucVersion; public int dwFileVersionMS; public int dwFileVersionLS; public int dwProductVersionMS; public int dwProductVersionLS; public int dwFileFlagsMask; public int dwFileFlags; public int dwFileOS; public int dwFileType; public int dwFileSubtype; public int dwFileDateMS; public int dwFileDateLS; public FixedFileInfo(Pointer p) { super(); useMemory(p); read(); } private FixedFileInfo() { } }
Next, the test program(TestFV.java): package test.fv; import com.sun.jna.*; import com.sun.jna.ptr.*; public class TestFV { public static int[] getFileVersion(String filePath) { int fileVersion[] = new int[4]; fileVersion[0]=0; fileVersion[1]=0; fileVersion[2]=0; fileVersion[3]=0; /*System.out.println(filePath);*/ IntByReference useless = new IntByReference(); int fileVersionSize = com.sun.jna.NativeLibrary.getInstance("version").getFunction("GetFileVer sionInfoSizeA").invokeInt(new java.lang.Object[]{filePath, useless}); /*System.out.println(fileVersionSize);*/ if(fileVersionSize != 0) { byte buffer[] = new byte[fileVersionSize]; int fileVersionRet = com.sun.jna.NativeLibrary.getInstance("version").getFunction("GetFileVer sionInfoA").invokeInt(new java.lang.Object[]{filePath, null, fileVersionSize,buffer}); if(fileVersionRet != 0) { /*Native.setProtected(true);*/ /*System.out.println(fileVersionRet);*/ IntByReference a = new IntByReference(); PointerByReference pref = new PointerByReference(); FixedFileInfo ffi = null; int ret = com.sun.jna.NativeLibrary.getInstance("version").getFunction("VerQueryVa lueA").invokeInt(new java.lang.Object[]{buffer,"\\",pref,a}); /*System.out.println(ret);*/ if(ret != 0) { Pointer p = pref.getValue(); System.out.println(p); ffi = new FixedFileInfo(p); System.out.println(ffi); System.out.println(ffi.size()); fileVersion[0] = ffi.dwProductVersionMS>>16 & 0xFFFF; fileVersion[1] = ffi.dwProductVersionMS & 0xFFFF; fileVersion[2] = ffi.dwProductVersionLS>>16 & 0xFFFF; fileVersion[3] = ffi.dwProductVersionLS & 0xFFFF; } } } return fileVersion; } public static void main(String[] args) { int fv[] = null; fv = getFileVersion("C:\\windows\\system32\\user32.dll"); for(int i = 0 ; i < fv.length ; i++) { System.out.print(fv[i] + "."); } System.out.println(""); fv = getFileVersion("C:\\windows\\system32\\user32.dll"); for(int i = 0 ; i < fv.length ; i++) { System.out.print(fv[i] + "."); } System.out.println(""); } }
Compiled and run on Java 1.6.0_06 with JNA 3.0.9 from the website with the following command line: javac -classpath ../lib/jna.jar test/fv/*.java && java -Djna.dump_memory=true -cp "../lib/jna.jar;." test/fv/TestFV
Output that I get: native@0x2b3b048 FixedFileInfo(native@0x2b3b048) (52 bytes) { int dwSignature@0=1920300129 int dwStrucVersion@4=16777573 int dwFileVersionMS@8=234881353 int dwFileVersionLS@c=1951627108 int dwProductVersionMS@10=1449358706 int dwProductVersionLS@14=1769173605 int dwFileFlagsMask@18=93807 int dwFileFlags@1c=1182229519 int dwFileOS@20=1449487465 int dwFileType@24=1769173605 int dwFileSubtype@28=1397583471 int dwFileDateMS@2c=1678704641 int dwFileDateLS@30=1818838647 } memory dump [61747572] [65010001] [4901000e] [64775374] [72756356] [65727369] [6f6e0100] [0f647746] [696c6556] [65727369] [6f6e4d53] [01000f64] [7746696c] 52 22115.30066.26995.29285. native@0x2b382a8 FixedFileInfo(native@0x2b382a8) (52 bytes) { int dwSignature@0=-17890115 int dwStrucVersion@4=65536 int dwFileVersionMS@8=327682 int dwFileVersionLS@c=248385473 int dwProductVersionMS@10=327682 int dwProductVersionLS@14=248385473 int dwFileFlagsMask@18=63 int dwFileFlags@1c=0 int dwFileOS@20=262148 int dwFileType@24=2 int dwFileSubtype@28=0 int dwFileDateMS@2c=0 int dwFileDateLS@30=0 } memory dump [bd04effe] [00000100] [02000500] [c10fce0e] [02000500] [c10fce0e] [3f000000] [00000000] [04000400] [02000000] [00000000] [00000000] [00000000] 52 5.2.3790.4033.
Now, from this output I see that the 2nd call to getFileVersion() works correctly, but the first does not. The first seems to produce sporadic fill in values for the FixedFileInfo class. So, that's the main question. It seems that calls 2-n after the first call get the correct values, regardless of which file they are pointing at.
In my experimenting, I've replaced the useMemory/Pointer constructor, that from everything I read should work just fine, with the following code in the FixedFileInfo class: private int unsignedIntToLong(byte a,byte b, byte c, byte d) { int l = 0; l |= a & 0xFF; l <<= 8; l |= b & 0xFF; l <<= 8; l |= c & 0xFF; l <<= 8; l |= d & 0xFF; return l; } public FixedFileInfo(byte [] b) { dwSignature = unsignedIntToLong(b[3],b[2],b[1],b[0]); dwStrucVersion = unsignedIntToLong(b[7],b[6],b[5],b[4]); dwFileVersionMS = unsignedIntToLong(b[11],b[10],b[9],b[8]); dwFileVersionLS = unsignedIntToLong(b[15],b[14],b[13],b[12]); dwProductVersionMS = unsignedIntToLong(b[19],b[18],b[17],b[16]); dwProductVersionLS = unsignedIntToLong(b[23],b[22],b[21],b[20]); dwFileFlagsMask = unsignedIntToLong(b[27],b[26],b[25],b[24]); dwFileFlags = unsignedIntToLong(b[31],b[30],b[29],b[28]); dwFileOS = unsignedIntToLong(b[35],b[34],b[33],b[32]); dwFileType = unsignedIntToLong(b[39],b[38],b[37],b[36]); dwFileSubtype = unsignedIntToLong(b[43],b[42],b[41],b[40]); dwFileDateMS = unsignedIntToLong(b[47],b[46],b[45],b[44]); dwFileDateLS = unsignedIntToLong(b[51],b[50],b[49],b[48]); } And then this in the getFileVersion function: byte [] buffer1 = p.getByteArray(0,a.getValue()); FixedFileInfo ffi = new FixedFileInfo(buffer1); fileVersion[0] = ffi.dwProductVersionMS>>16 & 0xFFFF; fileVersion[1] = ffi.dwProductVersionMS & 0xFFFF; fileVersion[2] = ffi.dwProductVersionLS>>16 & 0xFFFF; fileVersion[3] = ffi.dwProductVersionLS & 0xFFFF;
And clearly that's not using the native memory pointer, but it does work on the first call and all successive calls. But, that was only done for testing to make sure the memory contents returned were correct.
So, does anybody have any suggestions or possible workarounds? Am I missing something? Do I have to initialize the JNA library or something?
From, Beau Croteau Beau...@ca.com







