Skip to content

Commit 7ab7ddc

Browse files
Merge pull request #732 from Seven10Storage/master
Added WinioctlUtil, Ntifs and modified Kernel32
2 parents b6022ce + bfd9087 commit 7ab7ddc

File tree

10 files changed

+2081
-1
lines changed

10 files changed

+2081
-1
lines changed

CHANGES.md

+4
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ Features
6363
* [#689](https://github.com/java-native-access/jna/pull/689): Add `GetProcAddress(HMODULE, int)` to `com.sun.jna.platform.win32.Kernel32` - [@matthiasblaesing](https://github.com/matthiasblaesing).
6464
* [#723](https://github.com/java-native-access/jna/pull/723): Added `com.sun.jna.platform.win32.Wevtapi` and `com.sun.jna.platform.win32.Winevt` - [@sakamotodesu](https://github.com/sakamotodesu).
6565
* [#720](https://github.com/java-native-access/jna/issues/720): Added `SetThreadExecutionState` to `com.sun.jna.platform.win32.Kernel32` - [@matthiasblaesing](https://github.com/matthiasblaesing).
66+
* [#732](https://github.com/java-native-access/jna/pull/732): Added `com.sun.jna.platform.win32.WinioctlUtil` for help in determining FSCTL_* codes - [@amarcionek](https://github.com/amarcionek).
67+
* [#732](https://github.com/java-native-access/jna/pull/732): Added `com.sun.jna.platform.win32.Ntifs` with Reparse Point structures and defines - [@amarcionek](https://github.com/amarcionek).
68+
* [#732](https://github.com/java-native-access/jna/pull/732): Added initialization of FILETIME from LARGE_INTEGER - [@amarcionek](https://github.com/amarcionek).
69+
* [#732](https://github.com/java-native-access/jna/pull/732): Added `GetFileInformationByHandleEx` and `SetFileInformationByHandle` to `com.sun.jna.platform.win32.Kernel32` - [@amarcionek](https://github.com/amarcionek).
6670

6771
Bug Fixes
6872
---------

contrib/platform/src/com/sun/jna/platform/win32/Advapi32Util.java

+206
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,15 @@
4141
import static com.sun.jna.platform.win32.WinNT.SE_DACL_PROTECTED;
4242
import static com.sun.jna.platform.win32.WinNT.SE_SACL_PROTECTED;
4343
import static com.sun.jna.platform.win32.WinNT.STANDARD_RIGHTS_READ;
44+
import static com.sun.jna.platform.win32.WinNT.TOKEN_ADJUST_PRIVILEGES;
4445
import static com.sun.jna.platform.win32.WinNT.TOKEN_DUPLICATE;
4546
import static com.sun.jna.platform.win32.WinNT.TOKEN_IMPERSONATE;
4647
import static com.sun.jna.platform.win32.WinNT.TOKEN_QUERY;
4748
import static com.sun.jna.platform.win32.WinNT.UNPROTECTED_DACL_SECURITY_INFORMATION;
4849
import static com.sun.jna.platform.win32.WinNT.UNPROTECTED_SACL_SECURITY_INFORMATION;
4950

5051
import java.io.ByteArrayOutputStream;
52+
import java.io.Closeable;
5153
import java.io.File;
5254
import java.io.IOException;
5355
import java.util.ArrayList;
@@ -81,6 +83,7 @@
8183
import com.sun.jna.platform.win32.WinNT.SECURITY_IMPERSONATION_LEVEL;
8284
import com.sun.jna.platform.win32.WinNT.SID_AND_ATTRIBUTES;
8385
import com.sun.jna.platform.win32.WinNT.SID_NAME_USE;
86+
import com.sun.jna.platform.win32.WinNT.TOKEN_TYPE;
8487
import com.sun.jna.platform.win32.WinReg.HKEY;
8588
import com.sun.jna.platform.win32.WinReg.HKEYByReference;
8689
import com.sun.jna.ptr.IntByReference;
@@ -2636,4 +2639,207 @@ public DWORD callback(Pointer pbData, Pointer pvCallbackContext,
26362639
// close
26372640
Advapi32.INSTANCE.CloseEncryptedFileRaw(pvContext.getValue());
26382641
}
2642+
2643+
/**
2644+
* Convenience class to enable certain Windows process privileges
2645+
*/
2646+
public static class Privilege implements Closeable {
2647+
/**
2648+
* If true, the thread is currently impersonating
2649+
*/
2650+
private boolean currentlyImpersonating = false;
2651+
2652+
/**
2653+
* If true, the privileges have been enabled
2654+
*/
2655+
private boolean privilegesEnabled = false;
2656+
2657+
/**
2658+
* LUID form of the privileges
2659+
*/
2660+
private final WinNT.LUID[] pLuids;
2661+
2662+
/**
2663+
* Construct and enable a set of privileges
2664+
* @param privileges the names of the privileges in the form of SE_* from Advapi32.java
2665+
* @throws IllegalArgumentException
2666+
*/
2667+
public Privilege(String... privileges) throws IllegalArgumentException, Win32Exception {
2668+
pLuids = new WinNT.LUID[privileges.length];
2669+
int i = 0;
2670+
for (String p : privileges) {
2671+
pLuids[i] = new WinNT.LUID();
2672+
if (!Advapi32.INSTANCE.LookupPrivilegeValue(null, p, pLuids[i])) {
2673+
throw new IllegalArgumentException("Failed to find privilege \"" + privileges[i] + "\" - " + Kernel32.INSTANCE.GetLastError());
2674+
}
2675+
i++;
2676+
}
2677+
}
2678+
2679+
/**
2680+
* Calls disable() to remove the privileges
2681+
* @see java.io.Closeable#close()
2682+
*/
2683+
@Override
2684+
public void close() {
2685+
this.disable();
2686+
}
2687+
2688+
/**
2689+
* Enables the given privileges. If required, it will duplicate the process token. No resources are left open when this completes. That is, it is
2690+
* NOT required to drop the privileges, although it is considered a best practice if you do not need it. This class is state full. It keeps track
2691+
* of whether it has enabled the privileges. Multiple calls to enable() without a drop() in between have no affect.
2692+
* @return pointer to self (Privilege) as a convenience for try with resources statements
2693+
* @throws Win32Exception
2694+
*/
2695+
public Privilege enable() throws Win32Exception {
2696+
// Ignore if already enabled.
2697+
if (privilegesEnabled)
2698+
return this;
2699+
2700+
// Get thread token
2701+
final HANDLEByReference phThreadToken = new HANDLEByReference();
2702+
2703+
try {
2704+
phThreadToken.setValue(getThreadToken());
2705+
WinNT.TOKEN_PRIVILEGES tp = new WinNT.TOKEN_PRIVILEGES(pLuids.length);
2706+
for (int i = 0; i < pLuids.length; i++) {
2707+
tp.Privileges[i] = new WinNT.LUID_AND_ATTRIBUTES(pLuids[i], new DWORD(WinNT.SE_PRIVILEGE_ENABLED));
2708+
}
2709+
if (!Advapi32.INSTANCE.AdjustTokenPrivileges(phThreadToken.getValue(), false, tp, 0, null, null)) {
2710+
throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
2711+
}
2712+
privilegesEnabled = true;
2713+
}
2714+
catch (Win32Exception ex) {
2715+
// If fails, clean up
2716+
if (currentlyImpersonating) {
2717+
Advapi32.INSTANCE.SetThreadToken(null, null);
2718+
currentlyImpersonating = false;
2719+
}
2720+
else {
2721+
if (privilegesEnabled) {
2722+
WinNT.TOKEN_PRIVILEGES tp = new WinNT.TOKEN_PRIVILEGES(pLuids.length);
2723+
for (int i = 0; i < pLuids.length; i++) {
2724+
tp.Privileges[i] = new WinNT.LUID_AND_ATTRIBUTES(pLuids[i], new DWORD(0));
2725+
}
2726+
Advapi32.INSTANCE.AdjustTokenPrivileges(phThreadToken.getValue(), false, tp, 0, null, null);
2727+
privilegesEnabled = false;
2728+
}
2729+
}
2730+
throw ex;
2731+
}
2732+
finally {
2733+
// Always close the thread token
2734+
if ((phThreadToken.getValue() != WinBase.INVALID_HANDLE_VALUE)
2735+
&& (phThreadToken.getValue() != null)) {
2736+
Kernel32.INSTANCE.CloseHandle(phThreadToken.getValue());
2737+
phThreadToken.setValue(null);
2738+
}
2739+
}
2740+
return this;
2741+
}
2742+
2743+
/**
2744+
* Disabled the prior enabled privilege
2745+
* @throws Win32Exception
2746+
*/
2747+
public void disable() throws Win32Exception {
2748+
// Get thread token
2749+
final HANDLEByReference phThreadToken = new HANDLEByReference();
2750+
2751+
try {
2752+
phThreadToken.setValue(getThreadToken());
2753+
if (currentlyImpersonating) {
2754+
Advapi32.INSTANCE.SetThreadToken(null, null);
2755+
}
2756+
else
2757+
{
2758+
if (privilegesEnabled) {
2759+
WinNT.TOKEN_PRIVILEGES tp = new WinNT.TOKEN_PRIVILEGES(pLuids.length);
2760+
for (int i = 0; i < pLuids.length; i++) {
2761+
tp.Privileges[i] = new WinNT.LUID_AND_ATTRIBUTES(pLuids[i], new DWORD(0));
2762+
}
2763+
Advapi32.INSTANCE.AdjustTokenPrivileges(phThreadToken.getValue(), false, tp, 0, null, null);
2764+
privilegesEnabled = false;
2765+
}
2766+
}
2767+
}
2768+
finally {
2769+
// Close the thread token
2770+
if ((phThreadToken.getValue() != WinBase.INVALID_HANDLE_VALUE)
2771+
&& (phThreadToken.getValue() != null)) {
2772+
Kernel32.INSTANCE.CloseHandle(phThreadToken.getValue());
2773+
phThreadToken.setValue(null);
2774+
}
2775+
}
2776+
}
2777+
2778+
/**
2779+
* Get a handle to the thread token. May duplicate the process token
2780+
* and set as the thread token if ther thread has no token.
2781+
* @return HANDLE to the thread token
2782+
* @throws Win32Exception
2783+
*/
2784+
private HANDLE getThreadToken() throws Win32Exception {
2785+
// we need to create a new token here for the duplicate
2786+
final HANDLEByReference phThreadToken = new HANDLEByReference();
2787+
final HANDLEByReference phProcessToken = new HANDLEByReference();
2788+
2789+
try {
2790+
// open thread token
2791+
if (!Advapi32.INSTANCE.OpenThreadToken(Kernel32.INSTANCE.GetCurrentThread(),
2792+
TOKEN_ADJUST_PRIVILEGES,
2793+
false,
2794+
phThreadToken)) {
2795+
// OpenThreadToken may fail with W32Errors.ERROR_NO_TOKEN if current thread is anonymous. Check for that condition here. If not, throw an error.
2796+
int lastError = Kernel32.INSTANCE.GetLastError();
2797+
if (W32Errors.ERROR_NO_TOKEN != lastError) {
2798+
throw new Win32Exception(lastError);
2799+
}
2800+
2801+
// Due to ERROR_NO_TOKEN, we need to open the process token to duplicate it, then set our thread token.
2802+
if (!Advapi32.INSTANCE.OpenProcessToken(Kernel32.INSTANCE.GetCurrentProcess(), TOKEN_DUPLICATE, phProcessToken)) {
2803+
throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
2804+
}
2805+
2806+
// Process token opened, now duplicate
2807+
if (!Advapi32.INSTANCE.DuplicateTokenEx(phProcessToken.getValue(),
2808+
TOKEN_ADJUST_PRIVILEGES | TOKEN_IMPERSONATE,
2809+
null,
2810+
SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation,
2811+
TOKEN_TYPE.TokenImpersonation,
2812+
phThreadToken)) {
2813+
throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
2814+
}
2815+
2816+
// And set thread token.
2817+
if (!Advapi32.INSTANCE.SetThreadToken(null, phThreadToken.getValue())) {
2818+
throw new Win32Exception(Kernel32.INSTANCE.GetLastError());
2819+
}
2820+
currentlyImpersonating = true;
2821+
}
2822+
}
2823+
catch (Win32Exception ex) {
2824+
// Close the thread token
2825+
if ((phThreadToken.getValue() != WinBase.INVALID_HANDLE_VALUE)
2826+
&& (phThreadToken.getValue() != null)) {
2827+
Kernel32.INSTANCE.CloseHandle(phThreadToken.getValue());
2828+
phThreadToken.setValue(null);
2829+
}
2830+
throw ex;
2831+
}
2832+
finally
2833+
{
2834+
// Always close the process token
2835+
if ((phProcessToken.getValue() != WinBase.INVALID_HANDLE_VALUE)
2836+
&& (phProcessToken.getValue() != null)) {
2837+
Kernel32.INSTANCE.CloseHandle(phProcessToken.getValue());
2838+
phProcessToken.setValue(null);
2839+
}
2840+
}
2841+
2842+
return phThreadToken.getValue();
2843+
}
2844+
}
26392845
}

0 commit comments

Comments
 (0)