using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.IO;
using Microsoft.Win32;
namespace Autorunner
{
public class RegKeysAndDrives
{
public RegistryKey basekey;
public String subkey;
public String driveLetter;
public RegKeysAndDrives(RegistryKey _basekey, String _subkey, String _driveLetter)
{
basekey = _basekey;
subkey = _subkey;
driveLetter = _driveLetter;
}
}
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
///
public static List<RegKeysAndDrives> toDelete;
[STAThread]
static void Main()
{
//keep track of drives we've already ran, Must compare strings, DriveInfo only compares using the Object
List<String> haveRun = new List<String>();
toDelete = new List<RegKeysAndDrives>();
while (true)
{
//let's check every 2 seconds... We don't want to slow down the machine!
System.Threading.Thread.Sleep(2000);
try
{
//Get current drives
DriveInfo[] drives = DriveInfo.GetDrives();
List<DriveInfo> curDrives = new List<DriveInfo>(drives);
//remove any drives from haverun that don't exist anymore
for (int i = 0; i < haveRun.Count; i++)
{
if (DriveInfoContains(curDrives, haveRun[i]) == false)
{
for (int j = 0; j < toDelete.Count; j++)
{
if (toDelete[j].driveLetter == haveRun[i])
{
try
{
toDelete[j].basekey.DeleteSubKeyTree(toDelete[j].subkey);
}
catch (Exception ex)
{
//subkey doesn't exist anymore :P
}
toDelete.RemoveAt(j);
j--;
}
}
haveRun.RemoveAt(i);
i--;
}
}
//let's remove our haveRuns from drives, no point in checking them again...
for (int i = 0; i < curDrives.Count; i++)
{
if (haveRun.Contains(curDrives[i].RootDirectory.Name) == true)
{
curDrives.RemoveAt(i);
i--;
}
}
//Check any new Removable type drives, and run them...
foreach (DriveInfo drive in curDrives)
{
if (drive.DriveType != DriveType.CDRom)
{
if (drive.IsReady)
{
try
{
AutoRunDrive(drive);
}
catch (Exception ex)
{
//I don't care if it crashes trying to launch it, let's just let it go...
}
haveRun.Add(drive.RootDirectory.Name);
}
}
}
}
catch (Exception ex)
{
//Let's not crash if something gets unplugged while we're accessing it...
}
}
}
private static bool DriveInfoContains(List<DriveInfo> curDrives, string haveRunDriveName)
{
foreach (DriveInfo di in curDrives)
{
if (di.RootDirectory.Name == haveRunDriveName)
return true;
}
return false;
}
private static void AutoRunDrive(DriveInfo drive)
{
bool doAutoRun = false;
String root = drive.RootDirectory.Name;
String autorun = root + "autorun.inf";
if (File.Exists(autorun))
{
StreamReader sr = new StreamReader(autorun);
while (!sr.EndOfStream)
{
String line = sr.ReadLine();
if (line.ToLower().StartsWith("open"))
{
int idxEquals = line.IndexOf('=');
String toRun = root + line.Substring(idxEquals + 1);
//This isn't a good guess of where the args should be, but I don't care
int spaceArgs = toRun.IndexOf(' ');
String args = toRun.Substring(spaceArgs + 1);
args = FixArgs(args, root, toRun.ToLower().Contains("truecrypt"));
toRun = toRun.Substring(0, spaceArgs);
if (MessageBox.Show("Would you like to Autorun '" + toRun + " " + args + "'?", "Autorunner", MessageBoxButtons.YesNo) == DialogResult.Yes)
{
System.Diagnostics.Process.Start(toRun, args);
doAutoRun = true;
}
}
else if (doAutoRun && line.ToLower().StartsWith("shell"))
{
int equalidx = line.IndexOf("=");
String keyName;
String subkey;
String value;
if (equalidx == -1)
continue;
keyName = line.Substring(5, equalidx - 5);
value = line.Substring(equalidx + 1);
if (keyName.Contains("command"))
{
value = root + value;
}
RegistryKey baseKey = Registry.CurrentUser;
subkey = "Software\\Classes\\Drive\\shell" + keyName;
RegistryKey key = baseKey.CreateSubKey(subkey);
key.SetValue("", value);
toDelete.Add(new RegKeysAndDrives(baseKey, subkey, root));
}
}
sr.Close();
}
}
private static string FixArgs(string args, string root, bool isTrueCrypt)
{
if (isTrueCrypt)
{
int idxv = args.IndexOf("/v");
int idxfile = args.IndexOf("\"", idxv);
return args.Substring(0, idxfile + 1) + root + args.Substring(idxfile + 1);
}
return args;
}
}
}