Skip to content

Commit d5d912c

Browse files
author
infeo
committed
implemented DokanMapKernelToUserFlags to reduce JNI calls
1 parent ff2c493 commit d5d912c

File tree

2 files changed

+123
-5
lines changed

2 files changed

+123
-5
lines changed

src/main/java/dev/dokan/dokan_java/AbstractDokanyFileSystem.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -135,11 +135,10 @@ private void init(DokanyOperations dokanyOperations) {
135135
} else {
136136
if (isImplemented("zwCreateFile")) {
137137
dokanyOperations.setZwCreateFile((rawPath, securityContext, rawDesiredAccess, rawFileAttributes, rawShareAccess, rawCreateDisposition, rawCreateOptions, dokanFileInfo) -> {
138-
IntByReference createDisposition = new IntByReference();
139-
IntByReference desiredAccess = new IntByReference();
140-
IntByReference fileAttributeFlags = new IntByReference();
141-
NativeMethods.DokanMapKernelToUserCreateFileFlags(rawDesiredAccess, rawFileAttributes, rawCreateOptions, rawCreateDisposition, desiredAccess, fileAttributeFlags, createDisposition);
142-
return DokanyUtils.ntStatusFromWin32ErrorCode(this.zwCreateFile(rawPath, securityContext, desiredAccess.getValue(), fileAttributeFlags.getValue(), rawShareAccess, createDisposition.getValue(), rawCreateOptions, dokanFileInfo));
138+
int creationDisposition = DokanyUtils.convertCreateDispositionToCreationDispostion(rawCreateDisposition);
139+
int desiredAccessGeneric = DokanyUtils.mapFileGenericAccessToGenericAccess(rawDesiredAccess);
140+
int fileAttributesAndFlags = DokanyUtils.addFileFlagsToFileAttributes(rawFileAttributes, rawCreateOptions);
141+
return DokanyUtils.ntStatusFromWin32ErrorCode(this.zwCreateFile(rawPath, securityContext, desiredAccessGeneric, fileAttributesAndFlags, rawShareAccess, creationDisposition, rawCreateOptions, dokanFileInfo));
143142
});
144143
}
145144
if (isImplemented("cleanup")) {

src/main/java/dev/dokan/dokan_java/DokanyUtils.java

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
package dev.dokan.dokan_java;
22

33
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;
46

57
import java.util.Date;
68

79
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.*;
813
import static dev.dokan.dokan_java.constants.microsoft.NtStatuses.*;
914
import static dev.dokan.dokan_java.constants.microsoft.Win32ErrorCodes.ERROR_CTX_WINSTATION_ACCESS_DENIED;
1015
import static dev.dokan.dokan_java.constants.microsoft.Win32ErrorCodes.ERROR_CTX_WINSTATION_ALREADY_EXISTS;
@@ -22,6 +27,21 @@
2227
*/
2328
public class DokanyUtils {
2429

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+
2545
private DokanyUtils() {
2646

2747
}
@@ -51,6 +71,105 @@ public static boolean canHandleShutdownHooks() {
5171
}
5272
}
5373

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+
}
54173

55174
/**
56175
* Maps Win32 error codes to their respective NTStatus accordingly to ntstatus.i

0 commit comments

Comments
 (0)