Моя версия \\?\Volume{5b57f944-8d60-11de-8b2a-806d6172696f}\
должна получить C:\
Интерфейс Kernel32:
import com.sun.jna.WString;
import com.sun.jna.platform.win32.WinDef.DWORD;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.win32.StdCallLibrary;
public interface Kernel32 extends StdCallLibrary {
public boolean GetVolumePathNamesForVolumeNameW(
WString lpszVolumeName,
char[] lpszVolumePathNames,
DWORD cchBufferLength,
IntByReference lpcchReturnLength
);
public int GetLastError();
}
Тестовое приложение:
import java.util.Arrays;
import com.sun.jna.Native;
import com.sun.jna.WString;
import com.sun.jna.platform.win32.Win32Exception;
import com.sun.jna.platform.win32.WinDef.DWORD;
import com.sun.jna.ptr.IntByReference;
public class TestJNA {
static Kernel32 kernel32 = (Kernel32) Native.loadLibrary("kernel32.dll", Kernel32.class);
/**
* @param args
*/
public static void main(String[] args) {
try {
System.out.println(getPathNames());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static String getPathNames() throws Win32Exception {
DWORD value = new DWORD(100);
char[] pathNames = new char[100];
IntByReference len = new IntByReference();
if (kernel32.GetVolumePathNamesForVolumeNameW(getGuidPath(), pathNames, value, len)) {
if (kernel32.GetLastError() == WindowsConstants.ERROR_MORE_DATA) {
pathNames = new char[len.getValue()];
DWORD sz = new DWORD(len.getValue());
if (!kernel32.GetVolumePathNamesForVolumeNameW(getGuidPath(), pathNames, sz, len)) {
throw new Win32Exception(kernel32.GetLastError());
}
}
else
throw new Win32Exception(kernel32.GetLastError());
}
return Arrays.toString(pathNames);
}
private static WString getGuidPath() {
final WString str = new WString("\\\\?\\Volume{5b57f944-8d60-11de-8b2a-806d6172696f}\\");
return str;
}
}
Результат:
[C, :, \, , ]
Чтобы перепроверить его, я набираю в командной строке DOS: mountvol
Отредактировано: Для улучшения значения результата ...
Изменитьвозвращаемое значение метода getPathNames()
, от:
return Arrays.toString(pathNames);
до
return new String(pathNames);
В моем тестовом приложении вы можете просто:
String[] points = getPathNames().split("\u0000"); //split by Unicode NULL
for(String s: points) System.out.println("mount: " + s);
My onlyпроблема заключается в том, как JNA обрабатывает строки Юникода с нулевым символом в конце из параметра lpszVolumePathNames
в методе Kernel32 GetVolumePathNamesForVolumeNameW()
:список букв дисков и томов GUID путей.Список представляет собой массив строк с нулевым символом в конце, оканчивающихся на дополнительный символ NULL.Если буфер недостаточно велик для размещения полного списка, буфер содержит как можно большую часть списка.
Хотя спецификация JNI гласит (я не уверен в части JNA):
10.8 Завершение строк Unicode
Строки Unicode, полученные из GetStringChars или GetStringCritical, не заканчиваются NULL.Вызовите GetStringLength, чтобы узнать количество 16-битных символов Unicode в строке.Некоторые операционные системы, такие как Windows NT, ожидают, что два завершающих нулевых байта завершают строки Unicode.Вы не можете передать результат GetStringChars в API-интерфейсы Windows NT, которые ожидают строку Unicode.Вы должны сделать еще одну копию строки и вставить два завершающих нулевых байтовых значения.
http://java.sun.com/docs/books/jni/html/pitfalls.html
Отредактировано:
Itкажется, что мой код в порядке, так как параметр lpszVolumePathNames
возвращает строки с нулевым символом в Юникоде, проверяя наличие в нем строк "\ u0000":
String point = getPathNames().replaceAll("\u0000", "-");