diff --git a/SafeExamBrowser.ResetUtility/App.config b/SafeExamBrowser.ResetUtility/App.config
new file mode 100644
index 00000000..56efbc7b
--- /dev/null
+++ b/SafeExamBrowser.ResetUtility/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/SafeExamBrowser.ResetUtility/CompositionRoot.cs b/SafeExamBrowser.ResetUtility/CompositionRoot.cs
new file mode 100644
index 00000000..9dd21e7d
--- /dev/null
+++ b/SafeExamBrowser.ResetUtility/CompositionRoot.cs
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+using System;
+using System.IO;
+using SafeExamBrowser.Contracts.Logging;
+using SafeExamBrowser.Logging;
+using SafeExamBrowser.ResetUtility.Procedure;
+
+namespace SafeExamBrowser.ResetUtility
+{
+ internal class CompositionRoot
+ {
+ private ILogger logger;
+
+ internal ProcedureStep InitialStep { get; private set; }
+ internal NativeMethods NativeMethods { get; private set; }
+
+ internal void BuildObjectGraph()
+ {
+ InitializeLogging();
+
+ var context = new Context
+ {
+ Logger = logger,
+ };
+
+ InitialStep = new Initialization(context);
+ NativeMethods = new NativeMethods();
+ }
+
+ internal void LogStartupInformation()
+ {
+ logger.Log($"# Application started at {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}");
+ logger.Log(string.Empty);
+ }
+
+ internal void LogShutdownInformation()
+ {
+ logger.Log(string.Empty);
+ logger?.Log($"# Application terminated at {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}");
+ }
+
+ private void InitializeLogging()
+ {
+ var appDataFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), nameof(SafeExamBrowser));
+ var logFolder = Path.Combine(appDataFolder, "Logs");
+ var logFilePrefix = DateTime.Now.ToString("yyyy-MM-dd\\_HH\\hmm\\mss\\s");
+ var logFilePath = Path.Combine(logFolder, $"{logFilePrefix}_{nameof(ResetUtility)}.log");
+ var logFileWriter = new LogFileWriter(new DefaultLogFormatter(), logFilePath);
+
+ logger = new Logger();
+ logger.LogLevel = LogLevel.Debug;
+ logger.Subscribe(logFileWriter);
+ logFileWriter.Initialize();
+ }
+ }
+}
diff --git a/SafeExamBrowser.ResetUtility/Context.cs b/SafeExamBrowser.ResetUtility/Context.cs
new file mode 100644
index 00000000..d472de97
--- /dev/null
+++ b/SafeExamBrowser.ResetUtility/Context.cs
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+using SafeExamBrowser.Contracts.Logging;
+
+namespace SafeExamBrowser.ResetUtility
+{
+ internal class Context
+ {
+ internal ILogger Logger { get; set; }
+ }
+}
diff --git a/SafeExamBrowser.ResetUtility/NativeMethods.cs b/SafeExamBrowser.ResetUtility/NativeMethods.cs
new file mode 100644
index 00000000..5d9e30b8
--- /dev/null
+++ b/SafeExamBrowser.ResetUtility/NativeMethods.cs
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace SafeExamBrowser.ResetUtility
+{
+ internal class NativeMethods
+ {
+ private const int GWL_STYLE = -16;
+ private const int MF_BYCOMMAND = 0x0;
+ private const int SC_MAXIMIZE = 0xF030;
+ private const int SC_MINIMIZE = 0xF020;
+ private const int SC_SIZE = 0xF000;
+ private const int WS_MAXIMIZEBOX = 0x10000;
+ private const int WS_MINIMIZEBOX = 0x20000;
+
+ internal void TryDisableSystemMenu()
+ {
+ try
+ {
+ // DeleteMenu(GetSystemMenu(GetConsoleWindow(), false), SC_MINIMIZE, MF_BYCOMMAND);
+ DeleteMenu(GetSystemMenu(GetConsoleWindow(), false), SC_MAXIMIZE, MF_BYCOMMAND);
+ DeleteMenu(GetSystemMenu(GetConsoleWindow(), false), SC_SIZE, MF_BYCOMMAND);
+ // SetWindowLong(GetConsoleWindow(), GWL_STYLE, GetWindowLong(GetConsoleWindow(), GWL_STYLE) & ~WS_MINIMIZEBOX);
+ SetWindowLong(GetConsoleWindow(), GWL_STYLE, GetWindowLong(GetConsoleWindow(), GWL_STYLE) & ~WS_MAXIMIZEBOX);
+ }
+ catch(Exception) { }
+ }
+
+ [DllImport("user32.dll")]
+ private static extern int DeleteMenu(IntPtr hMenu, int nPosition, int wFlags);
+
+ [DllImport("kernel32.dll")]
+ private static extern IntPtr GetConsoleWindow();
+
+ [DllImport("user32.dll")]
+ private static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);
+
+ [DllImport("user32.dll")]
+ private static extern int GetWindowLong(IntPtr hWnd, int nIndex);
+
+ [DllImport("user32.dll")]
+ private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
+ }
+}
diff --git a/SafeExamBrowser.ResetUtility/Procedure/Initialization.cs b/SafeExamBrowser.ResetUtility/Procedure/Initialization.cs
new file mode 100644
index 00000000..0cbf5a99
--- /dev/null
+++ b/SafeExamBrowser.ResetUtility/Procedure/Initialization.cs
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+using System;
+using System.Security.Principal;
+using System.Threading;
+
+namespace SafeExamBrowser.ResetUtility.Procedure
+{
+ internal class Initialization : ProcedureStep
+ {
+ private static readonly Mutex mutex = new Mutex(true, "safe_exam_browser_reset_mutex");
+
+ public Initialization(Context context) : base(context)
+ {
+ }
+
+ internal override ProcedureStepResult Execute()
+ {
+ Initialize();
+
+ if (IsSingleInstance() && HasAdminPrivileges() && SebNotRunning())
+ {
+ return ProcedureStepResult.Continue;
+ }
+ else
+ {
+ return ProcedureStepResult.Terminate;
+ }
+ }
+
+ internal override ProcedureStep GetNextStep()
+ {
+ return new MainMenu(Context);
+ }
+
+ private bool IsSingleInstance()
+ {
+ var isSingle = mutex.WaitOne(TimeSpan.Zero, true);
+
+ if (isSingle)
+ {
+ Logger.Info("There is currently no other instance running.");
+ }
+ else
+ {
+ Logger.Error("There is currently another instance running! Terminating...");
+ ShowError("You can only run one instance of the Reset Utility at a time! Press any key to exit...");
+ }
+
+ return isSingle;
+ }
+
+ private bool HasAdminPrivileges()
+ {
+ var identity = WindowsIdentity.GetCurrent();
+ var principal = new WindowsPrincipal(identity);
+ var isAdmin = principal.IsInRole(WindowsBuiltInRole.Administrator);
+
+ if (isAdmin)
+ {
+ Logger.Info($"User '{identity.Name}' is running the application with administrator privileges.");
+ }
+ else
+ {
+ Logger.Error($"User '{identity.Name}' is running the application without administrator privileges! Terminating...");
+ ShowError("This application must be run with administrator privileges! Press any key to exit...");
+ }
+
+ return isAdmin;
+ }
+
+ private bool SebNotRunning()
+ {
+ var isRunning = Mutex.TryOpenExisting("safe_exam_browser_runtime_mutex", out _);
+
+ if (isRunning)
+ {
+ Logger.Error("SEB is currently running! Terminating...");
+ ShowError("This application must not be run while SEB is running! Press any key to exit...");
+ }
+ else
+ {
+ Logger.Info("SEB is currently not running.");
+ }
+
+ return !isRunning;
+ }
+ }
+}
diff --git a/SafeExamBrowser.ResetUtility/Procedure/MainMenu.cs b/SafeExamBrowser.ResetUtility/Procedure/MainMenu.cs
new file mode 100644
index 00000000..b742e16f
--- /dev/null
+++ b/SafeExamBrowser.ResetUtility/Procedure/MainMenu.cs
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace SafeExamBrowser.ResetUtility.Procedure
+{
+ internal class MainMenu : ProcedureStep
+ {
+ private IList