format everything for readability and so the brackets all line up again. All whitespace changes.

This commit is contained in:
idk
2022-09-03 21:17:44 -04:00
parent 079ef87c8f
commit a230a49af7
4 changed files with 270 additions and 249 deletions

View File

@ -5,29 +5,31 @@ import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.Kernel32Util; import com.sun.jna.platform.win32.Kernel32Util;
public class Elevator { public class Elevator {
public static void main(String... args) { public static void main(String... args) {
executeAsAdministrator("c:\\windows\\system32\\notepad.exe", ""); executeAsAdministrator("c:\\windows\\system32\\notepad.exe", "");
} }
public static void executeAsAdministrator(String command, String args) { public static void executeAsAdministrator(String command, String args) {
if (command == "" || command == null) { if (command == "" || command == null) {
System.out.println("No command specified"); System.out.println("No command specified");
return; return;
}
Shell32X.SHELLEXECUTEINFO execInfo = new Shell32X.SHELLEXECUTEINFO();
execInfo.lpFile = new WString(command);
if (args != null)
execInfo.lpParameters = new WString(args);
execInfo.nShow = Shell32X.SW_SHOWDEFAULT;
execInfo.fMask = Shell32X.SEE_MASK_NOCLOSEPROCESS;
execInfo.lpVerb = new WString("runas");
boolean result = Shell32X.INSTANCE.ShellExecuteEx(execInfo);
if (!result) {
int lastError = Kernel32.INSTANCE.GetLastError();
String errorMessage = Kernel32Util.formatMessageFromLastErrorCode(lastError);
throw new RuntimeException("Error performing elevation: " + lastError + ": " + errorMessage + " (apperror="
+ execInfo.hInstApp + ")");
}
} }
Shell32X.SHELLEXECUTEINFO execInfo = new Shell32X.SHELLEXECUTEINFO();
execInfo.lpFile = new WString(command);
if (args != null)
execInfo.lpParameters = new WString(args);
execInfo.nShow = Shell32X.SW_SHOWDEFAULT;
execInfo.fMask = Shell32X.SEE_MASK_NOCLOSEPROCESS;
execInfo.lpVerb = new WString("runas");
boolean result = Shell32X.INSTANCE.ShellExecuteEx(execInfo);
if (!result) {
int lastError = Kernel32.INSTANCE.GetLastError();
String errorMessage =
Kernel32Util.formatMessageFromLastErrorCode(lastError);
throw new RuntimeException("Error performing elevation: " + lastError +
": " + errorMessage +
" (apperror=" + execInfo.hInstApp + ")");
}
}
} }

View File

@ -1,7 +1,5 @@
package net.i2p.router; package net.i2p.router;
import java.util.*;
import com.sun.jna.Native; import com.sun.jna.Native;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;
import com.sun.jna.Structure; import com.sun.jna.Structure;
@ -12,100 +10,114 @@ import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.platform.win32.WinNT.HANDLE; import com.sun.jna.platform.win32.WinNT.HANDLE;
import com.sun.jna.platform.win32.WinReg.HKEY; import com.sun.jna.platform.win32.WinReg.HKEY;
import com.sun.jna.win32.W32APIOptions; import com.sun.jna.win32.W32APIOptions;
import java.util.*;
public interface Shell32X extends Shell32 { public interface Shell32X extends Shell32 {
Shell32X INSTANCE = (Shell32X) Native.loadLibrary("shell32", Shell32X.class, W32APIOptions.UNICODE_OPTIONS); Shell32X INSTANCE = (Shell32X)Native.loadLibrary(
"shell32", Shell32X.class, W32APIOptions.UNICODE_OPTIONS);
int SW_HIDE = 0; int SW_HIDE = 0;
int SW_MAXIMIZE = 3; int SW_MAXIMIZE = 3;
int SW_MINIMIZE = 6; int SW_MINIMIZE = 6;
int SW_RESTORE = 9; int SW_RESTORE = 9;
int SW_SHOW = 5; int SW_SHOW = 5;
int SW_SHOWDEFAULT = 10; int SW_SHOWDEFAULT = 10;
int SW_SHOWMAXIMIZED = 3; int SW_SHOWMAXIMIZED = 3;
int SW_SHOWMINIMIZED = 2; int SW_SHOWMINIMIZED = 2;
int SW_SHOWMINNOACTIVE = 7; int SW_SHOWMINNOACTIVE = 7;
int SW_SHOWNA = 8; int SW_SHOWNA = 8;
int SW_SHOWNOACTIVATE = 4; int SW_SHOWNOACTIVATE = 4;
int SW_SHOWNORMAL = 1; int SW_SHOWNORMAL = 1;
/** File not found. */ /** File not found. */
int SE_ERR_FNF = 2; int SE_ERR_FNF = 2;
/** Path not found. */ /** Path not found. */
int SE_ERR_PNF = 3; int SE_ERR_PNF = 3;
/** Access denied. */ /** Access denied. */
int SE_ERR_ACCESSDENIED = 5; int SE_ERR_ACCESSDENIED = 5;
/** Out of memory. */ /** Out of memory. */
int SE_ERR_OOM = 8; int SE_ERR_OOM = 8;
/** DLL not found. */ /** DLL not found. */
int SE_ERR_DLLNOTFOUND = 32; int SE_ERR_DLLNOTFOUND = 32;
/** Cannot share an open file. */ /** Cannot share an open file. */
int SE_ERR_SHARE = 26; int SE_ERR_SHARE = 26;
int SEE_MASK_NOCLOSEPROCESS = 0x00000040; int SEE_MASK_NOCLOSEPROCESS = 0x00000040;
int ShellExecute(int i, String lpVerb, String lpFile, String lpParameters, String lpDirectory, int nShow); int ShellExecute(int i, String lpVerb, String lpFile, String lpParameters,
String lpDirectory, int nShow);
boolean ShellExecuteEx(SHELLEXECUTEINFO lpExecInfo); boolean ShellExecuteEx(SHELLEXECUTEINFO lpExecInfo);
public static class SHELLEXECUTEINFO extends Structure { public static class SHELLEXECUTEINFO extends Structure {
/* /*
* DWORD cbSize; * DWORD cbSize;
* ULONG fMask; * ULONG fMask;
* HWND hwnd; * HWND hwnd;
* LPCTSTR lpVerb; * LPCTSTR lpVerb;
* LPCTSTR lpFile; * LPCTSTR lpFile;
* LPCTSTR lpParameters; * LPCTSTR lpParameters;
* LPCTSTR lpDirectory; * LPCTSTR lpDirectory;
* int nShow; * int nShow;
* HINSTANCE hInstApp; * HINSTANCE hInstApp;
* LPVOID lpIDList; * LPVOID lpIDList;
* LPCTSTR lpClass; * LPCTSTR lpClass;
* HKEY hkeyClass; * HKEY hkeyClass;
* DWORD dwHotKey; * DWORD dwHotKey;
* union { * union {
* HANDLE hIcon; * HANDLE hIcon;
* HANDLE hMonitor; * HANDLE hMonitor;
* } DUMMYUNIONNAME; * } DUMMYUNIONNAME;
* HANDLE hProcess; * HANDLE hProcess;
*/ */
public int cbSize = size(); public int cbSize = size();
public int fMask; public int fMask;
public HWND hwnd; public HWND hwnd;
public WString lpVerb; public WString lpVerb;
public WString lpFile; public WString lpFile;
public WString lpParameters; public WString lpParameters;
public WString lpDirectory; public WString lpDirectory;
public int nShow; public int nShow;
public HINSTANCE hInstApp; public HINSTANCE hInstApp;
public Pointer lpIDList; public Pointer lpIDList;
public WString lpClass; public WString lpClass;
public HKEY hKeyClass; public HKEY hKeyClass;
public int dwHotKey; public int dwHotKey;
/* /*
* Actually: * Actually:
* union { * union {
* HANDLE hIcon; * HANDLE hIcon;
* HANDLE hMonitor; * HANDLE hMonitor;
* } DUMMYUNIONNAME; * } DUMMYUNIONNAME;
*/ */
public HANDLE hMonitor; public HANDLE hMonitor;
public HANDLE hProcess; public HANDLE hProcess;
protected List getFieldOrder() { protected List getFieldOrder() {
return Arrays.asList(new String[] { return Arrays.asList(new String[] {
"cbSize", "fMask", "hwnd", "lpVerb", "lpFile", "lpParameters", "cbSize",
"lpDirectory", "nShow", "hInstApp", "lpIDList", "lpClass", "fMask",
"hKeyClass", "dwHotKey", "hMonitor", "hProcess", "hwnd",
}); "lpVerb",
} "lpFile",
"lpParameters",
"lpDirectory",
"nShow",
"hInstApp",
"lpIDList",
"lpClass",
"hKeyClass",
"dwHotKey",
"hMonitor",
"hProcess",
});
} }
}
} }

View File

@ -1,80 +1,88 @@
package net.i2p.router; package net.i2p.router;
import net.i2p.router.*;
import net.i2p.I2PAppContext;
import java.util.function.*;
import java.io.*; import java.io.*;
import java.util.function.*;
import net.i2p.I2PAppContext;
import net.i2p.router.*;
import net.i2p.util.Log; import net.i2p.util.Log;
class WinUpdateProcess implements Runnable { class WinUpdateProcess implements Runnable {
private final RouterContext ctx; private final RouterContext ctx;
private final Supplier<String> versionSupplier; private final Supplier<String> versionSupplier;
private final Supplier<File> fileSupplier; private final Supplier<File> fileSupplier;
private final Log _log; private final Log _log;
WinUpdateProcess(RouterContext ctx, Supplier<String> versionSupplier, Supplier<File> fileSupplier) { WinUpdateProcess(RouterContext ctx, Supplier<String> versionSupplier,
this.ctx = ctx; Supplier<File> fileSupplier) {
this.versionSupplier = versionSupplier; this.ctx = ctx;
this.fileSupplier = fileSupplier; this.versionSupplier = versionSupplier;
this._log = ctx.logManager().getLog(WinUpdateProcess.class); this.fileSupplier = fileSupplier;
this._log = ctx.logManager().getLog(WinUpdateProcess.class);
}
private File workDir() throws IOException {
if (ctx != null) {
File workDir =
new File(ctx.getConfigDir().getAbsolutePath(), "i2p_update_win");
if (workDir.exists()) {
if (workDir.isFile())
throw new IOException(workDir +
" exists but is a file, get it out of the way");
return workDir;
} else {
workDir.mkdirs();
}
return workDir;
} }
return null;
}
private File workDir() throws IOException { private void runUpdateInstaller() throws IOException {
if (ctx != null) { String version = versionSupplier.get();
File workDir = new File(ctx.getConfigDir().getAbsolutePath(), "i2p_update_win"); File file = fileSupplier.get();
if (workDir.exists()) { if (file == null)
if (workDir.isFile()) return;
throw new IOException(workDir + " exists but is a file, get it out of the way");
return workDir; var workingDir = workDir();
} else { var logFile = new File(workingDir, "log-" + version + ".txt");
workDir.mkdirs();
} if (logFile.canWrite()) {
return workDir; // check if we can write to the log file. If we can, use the
} // ProcessBuilder to run the installer.
return null; ProcessBuilder pb = new ProcessBuilder(
file.getAbsolutePath(), "/S", "/D=" + workingDir.getAbsolutePath());
var env = pb.environment();
env.put("OLD_I2P_VERSION", version);
env.remove("RESTART_I2P");
int exitCode = ctx.router().scheduledGracefulExitCode();
if (exitCode == Router.EXIT_HARD_RESTART ||
exitCode == Router.EXIT_GRACEFUL_RESTART)
env.put("RESTART_I2P", "true");
try {
pb.directory(workingDir)
.redirectErrorStream(true)
.redirectOutput(logFile)
.start();
} catch (IOException ex) {
_log.error(
"Unable to run update-program in background. Update will fail.");
}
} else {
// If we cant write to the log file and we're on Windows, use the elevator
// to execute the installer instead of the ProcessBuilder.
Elevator.executeAsAdministrator(file.getAbsolutePath(),
" /S /D=" + workingDir.getAbsolutePath());
} }
}
private void runUpdateInstaller() throws IOException { @Override
String version = versionSupplier.get(); public void run() {
File file = fileSupplier.get(); try {
if (file == null) runUpdateInstaller();
return; } catch (IOException ioe) {
_log.error("Error running updater, update may fail." + ioe);
var workingDir = workDir();
var logFile = new File(workingDir, "log-" + version + ".txt");
if (logFile.canWrite()) {
// check if we can write to the log file. If we can, use the ProcessBuilder to
// run the installer.
ProcessBuilder pb = new ProcessBuilder(file.getAbsolutePath(), "/S", "/D=" + workingDir.getAbsolutePath());
var env = pb.environment();
env.put("OLD_I2P_VERSION", version);
env.remove("RESTART_I2P");
int exitCode = ctx.router().scheduledGracefulExitCode();
if (exitCode == Router.EXIT_HARD_RESTART || exitCode == Router.EXIT_GRACEFUL_RESTART)
env.put("RESTART_I2P", "true");
try {
pb.directory(workingDir).redirectErrorStream(true).redirectOutput(logFile).start();
} catch (IOException ex) {
_log.error("Unable to run update-program in background. Update will fail.");
}
} else {
// If we cant write to the log file and we're on Windows, use the elevator to
// execute the installer instead of the ProcessBuilder.
Elevator.executeAsAdministrator(file.getAbsolutePath(), " /S /D=" + workingDir.getAbsolutePath());
}
}
@Override
public void run() {
try {
runUpdateInstaller();
} catch (IOException ioe) {
_log.error("Error running updater, update may fail." + ioe);
}
} }
}
} }

View File

@ -1,101 +1,100 @@
package net.i2p.router; package net.i2p.router;
import static net.i2p.update.UpdateType.*;
import java.io.*; import java.io.*;
import java.lang.InterruptedException;
import java.lang.Process;
import java.lang.ProcessBuilder;
import java.util.*; import java.util.*;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.*; import java.util.concurrent.atomic.*;
import net.i2p.crypto.*;
import static net.i2p.update.UpdateType.*;
import net.i2p.I2PAppContext; import net.i2p.I2PAppContext;
import net.i2p.update.UpdateType; import net.i2p.crypto.*;
import net.i2p.update.UpdatePostProcessor; import net.i2p.update.UpdatePostProcessor;
import net.i2p.update.UpdateType;
import net.i2p.util.Log; import net.i2p.util.Log;
import net.i2p.util.SystemVersion; import net.i2p.util.SystemVersion;
import java.lang.ProcessBuilder;
import java.lang.Process;
import java.lang.InterruptedException;
public class WindowsUpdatePostProcessor implements UpdatePostProcessor { public class WindowsUpdatePostProcessor implements UpdatePostProcessor {
private final Log _log; private final Log _log;
private final RouterContext ctx; private final RouterContext ctx;
private final AtomicBoolean hook = new AtomicBoolean(); private final AtomicBoolean hook = new AtomicBoolean();
private final String fileName = "i2p-jpackage-update.exe"; private final String fileName = "i2p-jpackage-update.exe";
private volatile String version; private volatile String version;
private volatile File positionedFile = null; private volatile File positionedFile = null;
WindowsUpdatePostProcessor(RouterContext ctx) { WindowsUpdatePostProcessor(RouterContext ctx) {
this.ctx = ctx; this.ctx = ctx;
this._log = ctx.logManager().getLog(WindowsUpdatePostProcessor.class); this._log = ctx.logManager().getLog(WindowsUpdatePostProcessor.class);
}
public String getVersion() { return version; }
public File getFile() { return positionedFile; }
public void updateDownloadedandVerified(UpdateType type, int fileType,
String version, File file)
throws IOException {
_log.info("Got an update to post-process");
if (SystemVersion.isWindows()) {
if (type != UpdateType.ROUTER_SIGNED_SU3 &&
type != UpdateType.ROUTER_DEV_SU3) {
_log.warn("Unsupported update type " + type);
return;
}
if (fileType != SU3File.TYPE_EXE) {
_log.warn("Unsupported file type " + fileType);
return;
}
this.positionedFile = moveUpdateInstaller(file);
this.version = version;
if (!hook.compareAndSet(false, true)) {
_log.info("shutdown hook was already set");
return;
}
_log.info("adding shutdown hook");
ctx.addFinalShutdownTask(
new WinUpdateProcess(ctx, this::getVersion, this::getFile));
} }
}
public String getVersion() { private File moveUpdateInstaller(File file) throws IOException {
return version; if (this.ctx != null) {
} File newFile = new File(workDir(), fileName);
boolean renamedStatus = file.renameTo(newFile);
public File getFile() { if (renamedStatus)
return positionedFile; return newFile;
} else
public void updateDownloadedandVerified(UpdateType type, int fileType, String version, File file)
throws IOException {
_log.info("Got an update to post-process");
if (SystemVersion.isWindows()) {
if (type != UpdateType.ROUTER_SIGNED_SU3 && type != UpdateType.ROUTER_DEV_SU3) {
_log.warn("Unsupported update type " + type);
return;
}
if (fileType != SU3File.TYPE_EXE) {
_log.warn("Unsupported file type " + fileType);
return;
}
this.positionedFile = moveUpdateInstaller(file);
this.version = version;
if (!hook.compareAndSet(false, true)) {
_log.info("shutdown hook was already set");
return;
}
_log.info("adding shutdown hook");
ctx.addFinalShutdownTask(new WinUpdateProcess(ctx, this::getVersion, this::getFile));
}
}
private File moveUpdateInstaller(File file) throws IOException {
if (this.ctx != null) {
File newFile = new File(workDir(), fileName);
boolean renamedStatus = file.renameTo(newFile);
if (renamedStatus)
return newFile;
else
throw new IOException(
"WindowsUpdatePostProcesssor unable to move file to working directory, update will fail");
}
throw new IOException( throw new IOException(
"Router context not available to WindowsUpdatePostProcesssor, unable to find working directory, update will fail"); "WindowsUpdatePostProcesssor unable to move file to working directory, update will fail");
} }
throw new IOException(
"Router context not available to WindowsUpdatePostProcesssor, unable to find working directory, update will fail");
}
private File workDir() throws IOException { private File workDir() throws IOException {
if (this.ctx != null) { if (this.ctx != null) {
File workDir = new File(this.ctx.getConfigDir().getAbsolutePath(), "i2p_update_win"); File workDir =
if (workDir.exists()) { new File(this.ctx.getConfigDir().getAbsolutePath(), "i2p_update_win");
if (workDir.isFile()) if (workDir.exists()) {
throw new IOException(workDir + " exists but is a file, get it out of the way"); if (workDir.isFile())
return null; throw new IOException(workDir +
} else { " exists but is a file, get it out of the way");
workDir.mkdirs();
}
return workDir;
}
return null; return null;
} else {
workDir.mkdirs();
}
return workDir;
} }
return null;
}
} }