/* Copyright (c) 2007 Timothy Wall, All Rights Reserved
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package com.sun.jna.platform.win32;
import java.io.File;
import java.util.Collection;
import java.util.List;
import org.junit.Test;
import com.sun.jna.Native;
import com.sun.jna.platform.win32.WinNT.HANDLE;
import com.sun.jna.ptr.IntByReference;
public class Kernel32VolumeManagementFunctionsTest extends AbstractWin32TestSupport {
public Kernel32VolumeManagementFunctionsTest() {
super();
}
@Test
public void testQueryDosDevice() {
Collection<String> logicalDrives = Kernel32Util.getLogicalDriveStrings();
for (String lpszDeviceName : logicalDrives) {
// the documentation states that the device name cannot have a trailing backslash
if (lpszDeviceName.charAt(lpszDeviceName.length() - 1) == File.separatorChar) {
lpszDeviceName = lpszDeviceName.substring(0, lpszDeviceName.length() - 1);
}
Collection<String> devices = Kernel32Util.queryDosDevice(lpszDeviceName, WinBase.MAX_PATH);
assertTrue("No devices for " + lpszDeviceName, devices.size() > 0);
for (String name : devices) {
assertTrue("Empty device name for " + lpszDeviceName, name.length() > 0);
// System.out.append(getCurrentTestName()).append('[').append(lpszDeviceName).append(']').append(" - ").println(name);
}
}
}
@Test
public void testGetVolumePathName() {
char[] lpszVolumePathName = new char[WinDef.MAX_PATH + 1];
for (String propName : new String[] { "java.home", "java.io.tmpdir", "user.dir", "user.home" }) {
String lpszFileName = System.getProperty(propName);
assertCallSucceeded("GetVolumePathName(" + lpszFileName + ")",
Kernel32.INSTANCE.GetVolumePathName(lpszFileName, lpszVolumePathName, lpszVolumePathName.length));
String path = Native.toString(lpszVolumePathName);
// System.out.append(getCurrentTestName()).append('[').append(lpszFileName).append(']').append(" - ").println(path);
assertTrue("No volume path for " + lpszFileName, path.length() > 0);
}
}
@Test
public void testGetVolumeNameForVolumeMountPoint() {
Collection<String> logicalDrives = Kernel32Util.getLogicalDriveStrings();
char[] lpVolumeNameBuffer = new char[WinDef.MAX_PATH + 1];
for (String lpszVolumeMountPoint : logicalDrives) {
// according to documentation path MUST end in backslash
if (lpszVolumeMountPoint.charAt(lpszVolumeMountPoint.length() - 1) != File.separatorChar) {
lpszVolumeMountPoint += File.separator;
}
int driveType = Kernel32.INSTANCE.GetDriveType(lpszVolumeMountPoint);
// network mapped drives fail GetVolumeNameForVolumeMountPoint call
if (driveType != WinBase.DRIVE_FIXED) {
// System.out.append('\t').append('[').append(lpszVolumeMountPoint).append(']').println(" - skipped: non-fixed drive");
continue;
}
if (Kernel32.INSTANCE.GetVolumeNameForVolumeMountPoint(lpszVolumeMountPoint, lpVolumeNameBuffer, lpVolumeNameBuffer.length)) {
String volumeGUID = Native.toString(lpVolumeNameBuffer);
// System.out.append(getCurrentTestName()).append('[').append(lpszVolumeMountPoint).append(']').append(" - ").println(volumeGUID);
assertTrue("Empty GUID for " + lpszVolumeMountPoint, volumeGUID.length() > 0);
} else {
int hr = Kernel32.INSTANCE.GetLastError();
if ((hr == WinError.ERROR_ACCESS_DENIED) // e.g., hidden volumes
|| (hr == WinError.ERROR_NOT_READY)) { // e.g., DVD drive
// System.out.append('\t').append('[').append(lpszVolumeMountPoint).append(']').append(" - skipped: reason=").println(hr);
continue;
}
fail("Cannot (error=" + hr + ") get volume information mount point " + lpszVolumeMountPoint);
}
}
}
@Test
public void testGetVolumeInformation() {
List<String> logicalDrives = Kernel32Util.getLogicalDriveStrings();
char[] lpVolumeNameBuffer = new char[WinDef.MAX_PATH + 1];
char[] lpFileSystemNameBuffer = new char[WinDef.MAX_PATH + 1];
IntByReference lpVolumeSerialNumber = new IntByReference();
IntByReference lpMaximumComponentLength = new IntByReference();
IntByReference lpFileSystemFlags = new IntByReference();
for (int index=(-1); index < logicalDrives.size(); index++) {
String lpRootPathName = (index < 0) ? null /* curdir */ : logicalDrives.get(index);
// according to documentation path MUST end in backslash
if ((lpRootPathName != null) && (lpRootPathName.charAt(lpRootPathName.length() - 1) != File.separatorChar)) {
lpRootPathName += File.separator;
}
if (!Kernel32.INSTANCE.GetVolumeInformation(lpRootPathName,
lpVolumeNameBuffer, lpVolumeNameBuffer.length,
lpVolumeSerialNumber, lpMaximumComponentLength, lpFileSystemFlags,
lpFileSystemNameBuffer, lpFileSystemNameBuffer.length)) {
int hr = Kernel32.INSTANCE.GetLastError();
if ((hr == WinError.ERROR_ACCESS_DENIED) // e.g., network or hidden volumes
|| (hr == WinError.ERROR_NOT_READY)) { // e.g., DVD drive
// System.out.append('\t').append('[').append(lpRootPathName).append(']').append(" - skipped: reason=").println(hr);
continue;
}
fail("Cannot (error=" + hr + ") get volume information for " + lpRootPathName);
}
// System.out.append(getCurrentTestName()).append('[').append(lpRootPathName).println(']');
// System.out.append('\t').append("Volume name: ").println(Native.toString(lpVolumeNameBuffer));
// System.out.append('\t').append("File system name: ").println(Native.toString(lpFileSystemNameBuffer));
// System.out.append('\t').append("Serial number: ").println(lpVolumeSerialNumber.getValue());
// System.out.append('\t').append("Max. component: ").println(lpMaximumComponentLength.getValue());
// System.out.append('\t').append("File system flags: 0x").println(Integer.toHexString(lpFileSystemFlags.getValue()));
}
}
@Test
public void testEnumVolumes() {
char[] lpszVolumeName = new char[WinDef.MAX_PATH + 1];
HANDLE hFindVolume = assertValidHandle("FindFirstVolume", Kernel32.INSTANCE.FindFirstVolume(lpszVolumeName, lpszVolumeName.length));
try {
int foundPaths = 0;
do {
String volumeGUID = Native.toString(lpszVolumeName);
testEnumVolumeMountMoints(volumeGUID);
foundPaths += testGetVolumePathNamesForVolumeName(volumeGUID);
} while(Kernel32.INSTANCE.FindNextVolume(hFindVolume, lpszVolumeName, lpszVolumeName.length));
assertTrue("No paths were found", foundPaths > 0);
int hr = Kernel32.INSTANCE.GetLastError();
assertEquals("Bad volumes enum termination reason", WinError.ERROR_NO_MORE_FILES, hr);
} finally {
assertCallSucceeded("FindVolumeClose", Kernel32.INSTANCE.FindVolumeClose(hFindVolume));
}
}
private int testGetVolumePathNamesForVolumeName(String lpszVolumeName) {
Collection<String> paths = Kernel32Util.getVolumePathNamesForVolumeName(lpszVolumeName);
for (String p : paths) {
// System.out.append('\t').append("testGetVolumePathNamesForVolumeName").append('[').append(lpszVolumeName).append(']').append(" - ").println(p);
assertTrue("Empty path for volume " + lpszVolumeName, p.length() > 0);
}
return paths.size();
}
private void testEnumVolumeMountMoints(String volumeGUID) {
char[] lpszVolumeMountPoint = new char[WinDef.MAX_PATH + 1];
HANDLE hFindVolumeMountPoint = Kernel32.INSTANCE.FindFirstVolumeMountPoint(volumeGUID, lpszVolumeMountPoint, lpszVolumeMountPoint.length);
if (WinNT.INVALID_HANDLE_VALUE.equals(hFindVolumeMountPoint)) {
int hr = Kernel32.INSTANCE.GetLastError();
if ((hr == WinError.ERROR_ACCESS_DENIED) // e.g., network or hidden volumes
|| (hr == WinError.ERROR_NOT_READY) // e.g., DVD drive
|| (hr == WinError.ERROR_NO_MORE_FILES) // No folders found
|| (hr == WinError.ERROR_PATH_NOT_FOUND)) {
// System.out.append('\t').append('[').append(volumeGUID).append(']').append(" - skipped: reason=").println(hr);
return;
}
fail("Cannot (error=" + hr + ") open mount point search handle for " + volumeGUID);
}
try {
do {
String name = Native.toString(lpszVolumeMountPoint);
assertTrue("Empty mount point for " + volumeGUID, name.length() > 0);
// System.out.append('\t').append("testEnumVolumeMountMoints").append('[').append(volumeGUID).append(']').append(" - ").println(name);
} while(Kernel32.INSTANCE.FindNextVolumeMountPoint(hFindVolumeMountPoint, lpszVolumeMountPoint, lpszVolumeMountPoint.length));
int hr = Kernel32.INSTANCE.GetLastError();
assertEquals("Mount points enum termination reason for " + volumeGUID, WinError.ERROR_NO_MORE_FILES, hr);
} finally {
assertCallSucceeded("FindVolumeMountPointClose(" + volumeGUID + ")", Kernel32.INSTANCE.FindVolumeMountPointClose(hFindVolumeMountPoint));
}
}
}