Win a copy of Murach's Python Programming this week in the Jython/Python forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

JNA call to kernel32.dll  RSS feed

 
billo bailey
Ranch Hand
Posts: 50
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Howdy,

I'm trying to make a function call using JNA to GetVolumeInformation as described here, http://msdn2.microsoft.com/en-us/library/aa364993.aspx. I've been able to successfully call other functions already, GetSystemTime & GetLogicalDrives, so my setup seems to be in order.

The example calls to GetVolumeInformation I've found online are all in other languages, so I think my problem is that my method signature is wrong and hence the function is not found.

Here's one example I found and tried to adapt as Java:



I changed the uint to be int and tried returning a long as opposed to a Boolean, but no joy.

Can anyone suggest how to construct a valid java method to make a call to this function?

I know I could use JNI for this but have no c++ experience and found the various tutorials fall short at the compilation stage, for me.

Thanks
 
billo bailey
Ranch Hand
Posts: 50
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
hooray progress, boooo more problems

So it seems the call is now working, however it results in a access violation problem, here's the method sig:



and here's the error:





Anyone any suggestions?

Thanks
 
Timothy Wall
Greenhorn
Posts: 14
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Use char[] or byte[] for character buffers, not StringBuilder. Follow the recommended type mappings given in http://jna.dev.java.net and the JNA JavaDoc overview.
 
david lastovicka
Greenhorn
Posts: 3
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
This worked for me, sorry the code is not very clean, but it works :-)

SAMPLE USAGE:
VolumeInformation info = VolumeInformation.createVolumeInformation("c:\\");
System.out.println(info.getDiskLabel());
System.out.println(info.getDiskSerial());
System.out.println(info.getFileSystem());

FILE VolumeInformation.java

import java.io.File;

public abstract class VolumeInformation {


public static VolumeInformation createVolumeInformation(String path) {
File pathFile = new File(path);
return createVolumeInformation(pathFile);
}

public static VolumeInformation createVolumeInformation(File pathFile) {
//return new VolumeInformation_win_cmdVol(pathFile);
return new VolumeInformation_win_jni(pathFile);
}

/**
* Returns the serial id of the disk containing
* the specified path
* @return
*/
public abstract String getDiskSerial();

/**
* Returns the label of the disk containing
* the specified path
* @return
*/
public abstract String getDiskLabel();

public abstract String getFileSystem();

}

FILE VolumeInformation_win_jni.java

import java.io.File;
import java.io.IOException;
import java.nio.CharBuffer;
import com.sun.jna.ptr.LongByReference;

class VolumeInformation_win_jni extends VolumeInformation {

private String diskSerial;
private String diskLabel;
private String fileSystem;

public VolumeInformation_win_jni(String path) {
this(new File(path));
}


/**
* @param pathFile
*/
public VolumeInformation_win_jni(File pathFile) {
String driveName;
try {
driveName = pathFile.getCanonicalPath().substring(0, 2) + "\\";
} catch(IOException e) {
throw new RuntimeException(e);
}

//byte[] lpRootPathName = new byte[4];
//for (int i=0; i<3; i++) {
//lpRootPathName[i] = (byte)(((byte)driveName.charAt(i)));
//}
//lpRootPathName[3] = '\0';
//char[] lpRootPathName_chars0 = driveName.toCharArray();
char[] lpRootPathName_chars = new char[4];
for (int i=0; i<3; i++) {
lpRootPathName_chars[i] = driveName.charAt(i);
}
lpRootPathName_chars[3] = '\0';
int nVolumeNameSize = 256;
//String lpRootPathName_string = driveName;
//ByteBuffer lpVolumeNameBuffer_byte = ByteBuffer.allocate(nVolumeNameSize);
CharBuffer lpVolumeNameBuffer_char = CharBuffer.allocate(nVolumeNameSize);
LongByReference lpVolumeSerialNumber = new LongByReference();
LongByReference lpMaximumComponentLength = new LongByReference();
LongByReference lpFileSystemFlags = new LongByReference();
int nFileSystemNameSize = 256;
//ByteBuffer lpFileSystemNameBuffer_byte = ByteBuffer.allocate(nFileSystemNameSize);
CharBuffer lpFileSystemNameBuffer_char = CharBuffer.allocate(nFileSystemNameSize);

//boolean result = MyKernel32.INSTANCE.GetVolumeInformationA(
//lpRootPathName_string,
//lpVolumeNameBuffer_byte,
//nVolumeNameSize,
//lpVolumeSerialNumber,
//lpMaximumComponentLength,
//lpFileSystemFlags,
//lpFileSystemNameBuffer_byte,
//nFileSystemNameSize);
//int err = MyKernel32.INSTANCE.GetLastError();
//this.diskLabel = lpVolumeNameBuffer_byte.toString();
//this.diskSerial = Long.toHexString(lpVolumeSerialNumber.getValue());
//this.fileSystem = lpFileSystemNameBuffer_byte.toString();

boolean result2 = MyKernel32.INSTANCE.GetVolumeInformationW(
lpRootPathName_chars,
lpVolumeNameBuffer_char,
nVolumeNameSize,
lpVolumeSerialNumber,
lpMaximumComponentLength,
lpFileSystemFlags,
lpFileSystemNameBuffer_char,
nFileSystemNameSize);
if (!result2) {
int err2 = MyKernel32.INSTANCE.GetLastError();
throw new RuntimeException("W32Api call to GetVolumeInformationW returned err code " + err2);
}
this.diskLabel = charString2String(lpVolumeNameBuffer_char);
this.fileSystem = charString2String(lpFileSystemNameBuffer_char);
this.diskSerial = Long.toHexString(lpVolumeSerialNumber.getValue());

}

/**
* Returns the serial id of the disk containing
* the specified path
* @return
*/
@Override
public String getDiskSerial() {
return diskSerial;
}

/**
* Returns the label of the disk containing
* the specified path
* @return
*/
@Override
public String getDiskLabel() {
return diskLabel;
}

@Override
public String getFileSystem() {
return fileSystem;
}

private String charString2String(CharBuffer buf) {
char[] chars = buf.array();
int i;
for (i=0; i<chars.length; i++) {
if (chars[i]=='\0') break;
}
return new String(chars,0,i);
}
}
 
david lastovicka
Greenhorn
Posts: 3
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The code above requires jna.jar as well as examples.jar to be included in the project
 
david lastovicka
Greenhorn
Posts: 3
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I forgot one class:

FILE MyKernel32.java

import java.nio.ByteBuffer;
import java.nio.CharBuffer;

import com.sun.jna.Native;
import com.sun.jna.examples.win32.Kernel32;
import com.sun.jna.ptr.LongByReference;

interface MyKernel32 extends Kernel32 {

boolean GetVolumeInformationW(
char[] lpRootPathName,
CharBuffer lpVolumeNameBuffer,
int nVolumeNameSize,
LongByReference lpVolumeSerialNumber,
LongByReference lpMaximumComponentLength,
LongByReference lpFileSystemFlags,
CharBuffer lpFileSystemNameBuffer,
int nFileSystemNameSize
);

boolean GetVolumeInformationA(
String lpRootPathName,
ByteBuffer lpVolumeNameBuffer,
int nVolumeNameSize,
LongByReference lpVolumeSerialNumber,
LongByReference lpMaximumComponentLength,
LongByReference lpFileSystemFlags,
ByteBuffer lpFileSystemNameBuffer,
int nFileSystemNameSize
);

MyKernel32 INSTANCE = (MyKernel32)Native.loadLibrary("kernel32", MyKernel32.class);

}
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!