|
1 | 1 | package dev.dokan.dokan_java; |
2 | 2 |
|
3 | 3 | import com.sun.jna.platform.win32.WinBase.FILETIME; |
| 4 | +import com.sun.jna.platform.win32.WinNT; |
| 5 | +import dev.dokan.dokan_java.constants.microsoft.CreationDisposition; |
4 | 6 |
|
5 | 7 | import java.util.Date; |
6 | 8 |
|
7 | 9 | import static com.sun.jna.platform.win32.WinError.*; |
| 10 | +import static dev.dokan.dokan_java.constants.microsoft.CreateDispositions.*; |
| 11 | +import static dev.dokan.dokan_java.constants.microsoft.CreateOptions.*; |
| 12 | +import static dev.dokan.dokan_java.constants.microsoft.CreationDisposition.*; |
8 | 13 | import static dev.dokan.dokan_java.constants.microsoft.NtStatuses.*; |
9 | 14 | import static dev.dokan.dokan_java.constants.microsoft.Win32ErrorCodes.ERROR_CTX_WINSTATION_ACCESS_DENIED; |
10 | 15 | import static dev.dokan.dokan_java.constants.microsoft.Win32ErrorCodes.ERROR_CTX_WINSTATION_ALREADY_EXISTS; |
|
22 | 27 | */ |
23 | 28 | public class DokanyUtils { |
24 | 29 |
|
| 30 | + private static final boolean winVersionAtLeast8; |
| 31 | + |
| 32 | + static { |
| 33 | + boolean tmp = false; |
| 34 | + try { |
| 35 | + String s = System.getProperty("os.version"); |
| 36 | + if (s.startsWith("10") || s.startsWith("8")) { |
| 37 | + tmp = true; |
| 38 | + } |
| 39 | + } catch (Exception e) { |
| 40 | + //NO-OP |
| 41 | + } |
| 42 | + winVersionAtLeast8 = tmp; |
| 43 | + } |
| 44 | + |
25 | 45 | private DokanyUtils() { |
26 | 46 |
|
27 | 47 | } |
@@ -51,6 +71,105 @@ public static boolean canHandleShutdownHooks() { |
51 | 71 | } |
52 | 72 | } |
53 | 73 |
|
| 74 | + /** |
| 75 | + * Extends the file attributes number with the file flags given in the createOptions. |
| 76 | + * |
| 77 | + * @param fileAttributes |
| 78 | + * @param createOptions |
| 79 | + * @return fileAttributes extended with the file flags |
| 80 | + */ |
| 81 | + public static int addFileFlagsToFileAttributes(int fileAttributes, int createOptions) { |
| 82 | + int outFileAttributesAndFlags = fileAttributes; |
| 83 | + outFileAttributesAndFlags = DokanMapKernelBit(outFileAttributesAndFlags, createOptions, WinNT.FILE_FLAG_WRITE_THROUGH, FILE_WRITE_THROUGH); |
| 84 | + outFileAttributesAndFlags = DokanMapKernelBit(outFileAttributesAndFlags, createOptions, WinNT.FILE_FLAG_SEQUENTIAL_SCAN, FILE_SEQUENTIAL_ONLY); |
| 85 | + outFileAttributesAndFlags = DokanMapKernelBit(outFileAttributesAndFlags, createOptions, WinNT.FILE_FLAG_RANDOM_ACCESS, FILE_RANDOM_ACCESS); |
| 86 | + outFileAttributesAndFlags = DokanMapKernelBit(outFileAttributesAndFlags, createOptions, WinNT.FILE_FLAG_NO_BUFFERING, FILE_NO_INTERMEDIATE_BUFFERING); |
| 87 | + outFileAttributesAndFlags = DokanMapKernelBit(outFileAttributesAndFlags, createOptions, WinNT.FILE_FLAG_OPEN_REPARSE_POINT, FILE_OPEN_REPARSE_POINT); |
| 88 | + outFileAttributesAndFlags = DokanMapKernelBit(outFileAttributesAndFlags, createOptions, WinNT.FILE_FLAG_DELETE_ON_CLOSE, FILE_DELETE_ON_CLOSE); |
| 89 | + outFileAttributesAndFlags = DokanMapKernelBit(outFileAttributesAndFlags, createOptions, WinNT.FILE_FLAG_BACKUP_SEMANTICS, FILE_OPEN_FOR_BACKUP_INTENT); |
| 90 | + |
| 91 | + if (winVersionAtLeast8) { |
| 92 | + outFileAttributesAndFlags = DokanMapKernelBit(outFileAttributesAndFlags, createOptions, 0x00800000, FILE_SESSION_AWARE); //FILE_FLAG_SESSION_AWARE == 0x00800000 |
| 93 | + } |
| 94 | + |
| 95 | + return outFileAttributesAndFlags; |
| 96 | + } |
| 97 | + |
| 98 | + private static int DokanMapKernelBit(int dest, int src, int userBit, int kernelBit) { |
| 99 | + if (((src) & (kernelBit)) == (kernelBit)) |
| 100 | + return (dest |= userBit); |
| 101 | + else |
| 102 | + return dest; |
| 103 | + } |
| 104 | + |
| 105 | + /** |
| 106 | + * Maps the generic file accesses specific to files and directories to the general generic accesses. |
| 107 | + * Copied from dokan.c. |
| 108 | + * |
| 109 | + * @param fileAccess the |
| 110 | + * @return |
| 111 | + */ |
| 112 | + public static int mapFileGenericAccessToGenericAccess(int fileAccess) { |
| 113 | + boolean genericRead = false, genericWrite = false, genericExecute = false, genericAll = false; |
| 114 | + int outDesiredAccess = fileAccess; |
| 115 | + |
| 116 | + if ((outDesiredAccess & WinNT.FILE_GENERIC_READ) == WinNT.FILE_GENERIC_READ) { |
| 117 | + outDesiredAccess |= WinNT.GENERIC_READ; |
| 118 | + genericRead = true; |
| 119 | + } |
| 120 | + if ((outDesiredAccess & WinNT.FILE_GENERIC_WRITE) == WinNT.FILE_GENERIC_WRITE) { |
| 121 | + outDesiredAccess |= WinNT.GENERIC_WRITE; |
| 122 | + genericWrite = true; |
| 123 | + } |
| 124 | + if ((outDesiredAccess & WinNT.FILE_GENERIC_EXECUTE) == WinNT.FILE_GENERIC_EXECUTE) { |
| 125 | + outDesiredAccess |= WinNT.GENERIC_EXECUTE; |
| 126 | + genericExecute = true; |
| 127 | + } |
| 128 | + if ((outDesiredAccess & WinNT.FILE_ALL_ACCESS) == WinNT.FILE_ALL_ACCESS) { |
| 129 | + outDesiredAccess |= WinNT.GENERIC_ALL; |
| 130 | + genericAll = true; |
| 131 | + } |
| 132 | + |
| 133 | + if (genericRead) |
| 134 | + outDesiredAccess &= ~WinNT.FILE_GENERIC_READ; |
| 135 | + if (genericWrite) |
| 136 | + outDesiredAccess &= ~WinNT.FILE_GENERIC_WRITE; |
| 137 | + if (genericExecute) |
| 138 | + outDesiredAccess &= ~WinNT.FILE_GENERIC_EXECUTE; |
| 139 | + if (genericAll) |
| 140 | + outDesiredAccess &= ~WinNT.FILE_ALL_ACCESS; |
| 141 | + |
| 142 | + return outDesiredAccess; |
| 143 | + } |
| 144 | + |
| 145 | + /** |
| 146 | + * Converts the kernel file creation flags to the win32 flags. |
| 147 | + * Copied from dokan.c. |
| 148 | + * |
| 149 | + * @param createDisposition |
| 150 | + * @return integer corresponding to an enum in {@link CreationDisposition} |
| 151 | + */ |
| 152 | + public static int convertCreateDispositionToCreationDispostion(int createDisposition) { |
| 153 | + switch (createDisposition) { |
| 154 | + case FILE_CREATE: |
| 155 | + return CREATE_NEW.getMask(); |
| 156 | + case FILE_OPEN: |
| 157 | + return OPEN_EXISTING.getMask(); |
| 158 | + case FILE_OPEN_IF: |
| 159 | + return OPEN_ALWAYS.getMask(); |
| 160 | + case FILE_OVERWRITE: |
| 161 | + return TRUNCATE_EXISTING.getMask(); |
| 162 | + case FILE_SUPERSEDE: |
| 163 | + // The documentation isn't clear on the difference between replacing a file |
| 164 | + // and truncating it. |
| 165 | + // For now we just map it to create/truncate |
| 166 | + case FILE_OVERWRITE_IF: |
| 167 | + return CREATE_ALWAYS.getMask(); |
| 168 | + default: |
| 169 | + //TODO: maybe throw an exception |
| 170 | + return 0; |
| 171 | + } |
| 172 | + } |
54 | 173 |
|
55 | 174 | /** |
56 | 175 | * Maps Win32 error codes to their respective NTStatus accordingly to ntstatus.i |
|
0 commit comments