|
15 | 15 | import java.io.File;
|
16 | 16 | import java.io.FileNotFoundException;
|
17 | 17 | import java.nio.ByteOrder;
|
18 |
| -import java.util.ArrayList; |
19 | 18 | import java.util.List;
|
20 | 19 | import java.util.Map;
|
21 | 20 | import java.util.TreeMap;
|
@@ -136,33 +135,22 @@ public static void deleteFile(String filename) {
|
136 | 135 | /**
|
137 | 136 | * Returns valid drives in the system.
|
138 | 137 | *
|
139 |
| - * @return An array of valid drives. |
| 138 | + * @return A {@link List} of valid drives. |
140 | 139 | */
|
141 |
| - public static String[] getLogicalDriveStrings() { |
142 |
| - DWORD dwSize = Kernel32.INSTANCE.GetLogicalDriveStrings(new DWORD(0), |
143 |
| - null); |
| 140 | + public static List<String> getLogicalDriveStrings() { |
| 141 | + DWORD dwSize = Kernel32.INSTANCE.GetLogicalDriveStrings(new DWORD(0), null); |
144 | 142 | if (dwSize.intValue() <= 0) {
|
145 | 143 | throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
|
146 | 144 | }
|
147 | 145 |
|
148 | 146 | char buf[] = new char[dwSize.intValue()];
|
149 | 147 | dwSize = Kernel32.INSTANCE.GetLogicalDriveStrings(dwSize, buf);
|
150 |
| - if (dwSize.intValue() <= 0) { |
| 148 | + int bufSize = dwSize.intValue(); |
| 149 | + if (bufSize <= 0) { |
151 | 150 | throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
|
152 | 151 | }
|
153 | 152 |
|
154 |
| - List<String> drives = new ArrayList<String>(); |
155 |
| - String drive = ""; |
156 |
| - // the buffer is double-null-terminated |
157 |
| - for (int i = 0; i < buf.length - 1; i++) { |
158 |
| - if (buf[i] == 0) { |
159 |
| - drives.add(drive); |
160 |
| - drive = ""; |
161 |
| - } else { |
162 |
| - drive += buf[i]; |
163 |
| - } |
164 |
| - } |
165 |
| - return drives.toArray(new String[0]); |
| 153 | + return Native.toStringList(buf, 0, bufSize); |
166 | 154 | }
|
167 | 155 |
|
168 | 156 | /**
|
@@ -609,4 +597,76 @@ public static final void writePrivateProfileSection(final String appName, final
|
609 | 597 | throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
|
610 | 598 | }
|
611 | 599 | }
|
| 600 | + |
| 601 | + /** |
| 602 | + * Invokes the {@link Kernel32#QueryDosDevice(String, char[], int)} method |
| 603 | + * and parses the result |
| 604 | + * @param lpszDeviceName The device name |
| 605 | + * @param maxTargetSize The work buffer size to use for the query |
| 606 | + * @return The parsed result |
| 607 | + */ |
| 608 | + public static final List<String> queryDosDevice(String lpszDeviceName, int maxTargetSize) { |
| 609 | + char[] lpTargetPath = new char[maxTargetSize]; |
| 610 | + int dwSize = Kernel32.INSTANCE.QueryDosDevice(lpszDeviceName, lpTargetPath, lpTargetPath.length); |
| 611 | + if (dwSize == 0) { |
| 612 | + throw new Win32Exception(Kernel32.INSTANCE.GetLastError()); |
| 613 | + } |
| 614 | + |
| 615 | + return Native.toStringList(lpTargetPath, 0, dwSize); |
| 616 | + } |
| 617 | + |
| 618 | + /** |
| 619 | + * Invokes and parses the result of {@link Kernel32#GetVolumePathNamesForVolumeName(String, char[], int, IntByReference)} |
| 620 | + * @param lpszVolumeName The volume name |
| 621 | + * @return The parsed result |
| 622 | + * @throws Win32Exception If failed to retrieve the required information |
| 623 | + */ |
| 624 | + public static final List<String> getVolumePathNamesForVolumeName(String lpszVolumeName) { |
| 625 | + char[] lpszVolumePathNames = new char[WinDef.MAX_PATH + 1]; |
| 626 | + IntByReference lpcchReturnLength = new IntByReference(); |
| 627 | + |
| 628 | + if (!Kernel32.INSTANCE.GetVolumePathNamesForVolumeName(lpszVolumeName, lpszVolumePathNames, lpszVolumePathNames.length, lpcchReturnLength)) { |
| 629 | + int hr = Kernel32.INSTANCE.GetLastError(); |
| 630 | + if (hr != WinError.ERROR_MORE_DATA) { |
| 631 | + throw new Win32Exception(hr); |
| 632 | + } |
| 633 | + |
| 634 | + int required = lpcchReturnLength.getValue(); |
| 635 | + lpszVolumePathNames = new char[required]; |
| 636 | + // this time we MUST succeed |
| 637 | + if (!Kernel32.INSTANCE.GetVolumePathNamesForVolumeName(lpszVolumeName, lpszVolumePathNames, lpszVolumePathNames.length, lpcchReturnLength)) { |
| 638 | + throw new Win32Exception(Kernel32.INSTANCE.GetLastError()); |
| 639 | + } |
| 640 | + } |
| 641 | + |
| 642 | + int bufSize = lpcchReturnLength.getValue(); |
| 643 | + return Native.toStringList(lpszVolumePathNames, 0, bufSize); |
| 644 | + } |
| 645 | + |
| 646 | + // prefix and suffix of a volume GUID path |
| 647 | + public static final String VOLUME_GUID_PATH_PREFIX = "\\\\?\\Volume{"; |
| 648 | + public static final String VOLUME_GUID_PATH_SUFFIX = "}\\"; |
| 649 | + |
| 650 | + /** |
| 651 | + * Parses and returns the pure GUID value of a volume name obtained |
| 652 | + * from {@link Kernel32#FindFirstVolume(char[], int)} or |
| 653 | + * {@link Kernel32#FindNextVolume(HANDLE, char[], int)} calls |
| 654 | + * |
| 655 | + * @param volumeName |
| 656 | + * The volume name as returned by on of the above mentioned calls |
| 657 | + * @return The pure GUID value after stripping the "\\?\" prefix and |
| 658 | + * removing the trailing backslash. |
| 659 | + * @throws IllegalArgumentException if bad format encountered |
| 660 | + * @see <A HREF="https://msdn.microsoft.com/en-us/library/windows/desktop/aa365248(v=vs.85).aspx">Naming a Volume</A> |
| 661 | + */ |
| 662 | + public static final String extractVolumeGUID(String volumeGUIDPath) { |
| 663 | + if ((volumeGUIDPath == null) |
| 664 | + || (volumeGUIDPath.length() <= (VOLUME_GUID_PATH_PREFIX.length() + VOLUME_GUID_PATH_SUFFIX.length())) |
| 665 | + || (!volumeGUIDPath.startsWith(VOLUME_GUID_PATH_PREFIX)) |
| 666 | + || (!volumeGUIDPath.endsWith(VOLUME_GUID_PATH_SUFFIX))) { |
| 667 | + throw new IllegalArgumentException("Bad volume GUID path format: " + volumeGUIDPath); |
| 668 | + } |
| 669 | + |
| 670 | + return volumeGUIDPath.substring(VOLUME_GUID_PATH_PREFIX.length(), volumeGUIDPath.length() - VOLUME_GUID_PATH_SUFFIX.length()); |
| 671 | + } |
612 | 672 | }
|
0 commit comments