Index: AE/installer2/src/net/oni2/aeinstaller/backend/AppExecution.java
===================================================================
--- AE/installer2/src/net/oni2/aeinstaller/backend/AppExecution.java	(revision 623)
+++ AE/installer2/src/net/oni2/aeinstaller/backend/AppExecution.java	(revision 623)
@@ -0,0 +1,62 @@
+package net.oni2.aeinstaller.backend;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.List;
+import java.util.Vector;
+
+/**
+ * @author Christian Illy
+ */
+public class AppExecution {
+
+	/**
+	 * Execute a short running application and wait for termination
+	 * 
+	 * @param cmdLine
+	 *            List of command and arguments
+	 * @return List of output lines
+	 * @throws IOException
+	 *             Exc
+	 */
+	public static Vector<String> executeAndWait(List<String> cmdLine)
+			throws IOException {
+		ProcessBuilder pb = new ProcessBuilder(cmdLine);
+		pb.redirectErrorStream(true);
+		Process proc = pb.start();
+
+		InputStream is = proc.getInputStream();
+		InputStreamReader isr = new InputStreamReader(is);
+		BufferedReader br = new BufferedReader(isr);
+
+		String line;
+		Vector<String> lines = new Vector<String>();
+
+		while ((line = br.readLine()) != null) {
+			lines.add(line);
+		}
+		return lines;
+	}
+
+	/**
+	 * Execute an app without waiting
+	 * 
+	 * @param cmd
+	 *            Command and parameters
+	 * @param workingDirectory
+	 *            Working directory of app
+	 */
+	public static void execute(List<String> cmd, File workingDirectory) {
+		try {
+			ProcessBuilder pb = new ProcessBuilder(cmd);
+			pb.directory(workingDirectory);
+			pb.start();
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+	}
+
+}
Index: AE/installer2/src/net/oni2/aeinstaller/backend/QuickAppExecution.java
===================================================================
--- AE/installer2/src/net/oni2/aeinstaller/backend/QuickAppExecution.java	(revision 622)
+++ 	(revision )
@@ -1,43 +1,0 @@
-package net.oni2.aeinstaller.backend;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.util.List;
-import java.util.Vector;
-
-/**
- * @author Christian Illy
- */
-public class QuickAppExecution {
-
-	/**
-	 * Execute a short running application
-	 * 
-	 * @param cmdLine
-	 *            List of command and arguments
-	 * @return List of output lines
-	 * @throws IOException
-	 *             Exc
-	 */
-	public static Vector<String> execute(List<String> cmdLine)
-			throws IOException {
-		ProcessBuilder pb = new ProcessBuilder(cmdLine);
-		pb.redirectErrorStream(true);
-		Process proc = pb.start();
-
-		InputStream is = proc.getInputStream();
-		InputStreamReader isr = new InputStreamReader(is);
-		BufferedReader br = new BufferedReader(isr);
-
-		String line;
-		Vector<String> lines = new Vector<String>();
-
-		while ((line = br.readLine()) != null) {
-			lines.add(line);
-		}
-		return lines;
-	}
-
-}
Index: AE/installer2/src/net/oni2/aeinstaller/backend/Settings.java
===================================================================
--- AE/installer2/src/net/oni2/aeinstaller/backend/Settings.java	(revision 622)
+++ AE/installer2/src/net/oni2/aeinstaller/backend/Settings.java	(revision 623)
@@ -80,5 +80,5 @@
 		Vector<String> res = null;
 		try {
-			res = QuickAppExecution.execute(cmd);
+			res = AppExecution.executeAndWait(cmd);
 		} catch (IOException e) {
 			e.printStackTrace();
@@ -134,5 +134,5 @@
 				Vector<String> res = null;
 				try {
-					res = QuickAppExecution.execute(cmd);
+					res = AppExecution.executeAndWait(cmd);
 				} catch (IOException e) {
 					e.printStackTrace();
Index: AE/installer2/src/net/oni2/aeinstaller/backend/mods/Mod.java
===================================================================
--- AE/installer2/src/net/oni2/aeinstaller/backend/mods/Mod.java	(revision 622)
+++ AE/installer2/src/net/oni2/aeinstaller/backend/mods/Mod.java	(revision 623)
@@ -26,4 +26,5 @@
 
 	private HashSet<Type> types = new HashSet<Type>();
+	private boolean tool = false;
 	private ECompatiblePlatform platform = null;
 	private String version = "";
@@ -36,6 +37,11 @@
 	private net.oni2.aeinstaller.backend.depot.model.File file = null;
 
+	private File exeFile = null;
+	private File iconFile = null;
+	private String workingDir = "Base";
+
 	private HashSet<Integer> incompatibilities = new HashSet<Integer>();
 	private HashSet<Integer> dependencies = new HashSet<Integer>();
+	private HashSet<Integer> unlockLevel = new HashSet<Integer>();
 
 	private long localTimestamp = 0;
@@ -52,8 +58,9 @@
 		packageNumber = nm.getPackageNumber();
 		platform = nm.getPlatform();
+		tool = nm.isTool();
 		for (TaxonomyTerm tt : nm.getTypes()) {
 			Type t = ModManager.getInstance().getTypeByName(tt.getName());
 			types.add(t);
-			if (!nm.isTool() && !isMandatoryMod() && isValidOnPlatform())
+			if (!tool && !isMandatoryMod() && isValidOnPlatform())
 				t.addEntry(this);
 		}
@@ -76,4 +83,5 @@
 		File config = new File(getLocalPath(), "Mod_Info.cfg");
 		File aeicfg = new File(getLocalPath(), "aei.cfg");
+		File plain = new File(getLocalPath(), "plain");
 		if (config.exists()) {
 			try {
@@ -131,4 +139,22 @@
 							}
 						}
+					} else if (sName.equalsIgnoreCase("UnlockLevel")) {
+						String[] levelsS = sVal.split(",");
+						for (String s : levelsS) {
+							try {
+								int level = Integer.parseInt(s);
+								unlockLevel.add(level);
+							} catch (NumberFormatException e) {
+								System.err
+										.format("Mod %05d does contain a non-number UnlockLevel value: '%s'\n",
+												packageNumber, s);
+							}
+						}
+					} else if (sName.equalsIgnoreCase("ExeName")) {
+						exeFile = new File(Paths.getEditionBasePath(), sVal);
+					} else if (sName.equalsIgnoreCase("WorkingDir")) {
+						workingDir = sVal;
+					} else if (sName.equalsIgnoreCase("IconName")) {
+						iconFile = new File(Paths.getEditionBasePath(), sVal);
 					}
 				}
@@ -166,4 +192,6 @@
 			}
 		}
+		if (node == null)
+			tool = plain.exists();
 	}
 
@@ -254,4 +282,11 @@
 
 	/**
+	 * @return Is this mod actually a tool?
+	 */
+	public boolean isTool() {
+		return tool;
+	}
+
+	/**
 	 * @return Compatible platforms
 	 */
@@ -326,4 +361,39 @@
 	public HashSet<Integer> getDependencies() {
 		return dependencies;
+	}
+
+	/**
+	 * @return the levels this mod will unlock
+	 */
+	public HashSet<Integer> getUnlockLevels() {
+		return unlockLevel;
+	}
+
+	/**
+	 * @return Executable name of this tool
+	 */
+	public File getExeFile() {
+		return exeFile;
+	}
+	/**
+	 * @return Icon file of this tool
+	 */
+	public File getIconFile() {
+		return iconFile;
+	}
+
+	/**
+	 * @return Working directory of this tool
+	 */
+	public File getWorkingDir() {
+		if (workingDir.equalsIgnoreCase("Exe")) {
+			if (exeFile != null)
+				return exeFile.getParentFile();
+			else
+				return Paths.getEditionGDF();
+		} else if (workingDir.equalsIgnoreCase("GDF"))
+			return Paths.getEditionGDF();
+		else
+			return Paths.getEditionBasePath();
 	}
 
Index: AE/installer2/src/net/oni2/aeinstaller/backend/mods/ModManager.java
===================================================================
--- AE/installer2/src/net/oni2/aeinstaller/backend/mods/ModManager.java	(revision 622)
+++ AE/installer2/src/net/oni2/aeinstaller/backend/mods/ModManager.java	(revision 623)
@@ -253,15 +253,26 @@
 
 	/**
-	 * Get a mod by its package number
+	 * @return Currently installed tools
+	 */
+	public TreeSet<Mod> getInstalledTools() {
+		TreeSet<Mod> res = new TreeSet<Mod>();
+		for (int n : Installer.getInstalledTools()) {
+			res.add(getModByNumber(n));
+		}
+		return res;
+	}
+
+	/**
+	 * Get a mod/tool by its package number
 	 * 
 	 * @param number
 	 *            Package number
-	 * @return Mod or null
+	 * @return Mod/tool or null
 	 */
 	public Mod getModByNumber(int number) {
-		for (Mod m : mods.values()) {
-			if (m.getPackageNumber() == number)
-				return m;
-		}
+		if (mods.containsKey(number))
+			return mods.get(number);
+		if (tools.containsKey(number))
+			return tools.get(number);
 		return null;
 	}
