///
/// Copyright © 2003-2008 JetBrains s.r.o.
/// You may distribute under the terms of the GNU General Public License, as published by the Free Software Foundation, version 2 (see License.txt in the repository root folder).
///
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using JetBrains.Build.Omea.Infra;
using JetBrains.Build.Omea.Resolved.Infra;
using Microsoft.Tools.WindowsInstallerXml.Serialize;
using Directory=Microsoft.Tools.WindowsInstallerXml.Serialize.Directory;
namespace JetBrains.Build.Omea.Resolved.Tasks
{
///
/// Converts a .reg file into a .wxs file with Registry entries and a dummy structure around them to provide for an XSD-valid file.
///
public class Reg2WxsResolved : TaskResolved
{
#region Implementation
private static void ParseRegFile(string sRegFile, List wixKeys, List wixValues)
{
using(var reader = new StreamReader(sRegFile, true))
{
string line;
RegistryRootType rootCurrent = RegistryRootType.HKMU; // The current registry Root to read the values into
string sCurrentKey = ""; // The current key path under the current root to read the values into
var regexJustRoot = new Regex(@"^HKEY_[^\\]+$", RegexOptions.IgnoreCase | RegexOptions.Singleline);
var regexRootAndKey = new Regex(@"^(?HKEY_.+?)\\(?.*)$", RegexOptions.IgnoreCase | RegexOptions.Singleline);
var regexValueQuotedQuoted = new Regex("^\"(?.+?)(?.+)\"$", RegexOptions.IgnoreCase | RegexOptions.Singleline);
var regexDefaultValueQuoted = new Regex("^@=\"(?.+)\"$", RegexOptions.IgnoreCase | RegexOptions.Singleline);
while((line = reader.ReadLine()) != null)
{
line = line.Trim();
if(string.IsNullOrEmpty(line))
continue;
// A key?
Match match;
if(line[0] == '[')
{
if(line[line.Length - 1] != ']')
throw new InvalidOperationException(string.Format("There's a key opening bracket, but no closing one."));
string key = line.Substring(1, line.Length - 2);
// Only HKEY_SMTH? Not interested
if(regexJustRoot.IsMatch(key))
continue;
// Break into the root and the key
match = regexRootAndKey.Match(key);
if(!match.Success)
throw new InvalidOperationException(string.Format("Failed to parse the key “{0}”.", key));
string sKeyPrefix = "";
string sRootValue = match.Groups["Root"].Value.ToUpperInvariant();
switch(sRootValue)
{
case "HKEY_CLASSES_ROOT":
rootCurrent = RegistryRootType.HKMU;
sKeyPrefix = "Software\\Classes\\";
break;
case "HKEY_LOCAL_MACHINE":
rootCurrent = RegistryRootType.HKLM;
break;
case "HKEY_CURRENT_USER":
rootCurrent = RegistryRootType.HKCU;
break;
case "HKEY_USERS":
rootCurrent = RegistryRootType.HKU;
break;
default:
throw new InvalidOperationException(string.Format("Unsupported registry root “{0}”.", sRootValue));
}
sCurrentKey = sKeyPrefix + match.Groups["Key"].Value;
// List the key
var wixKey = new RegistryKey();
wixKey.Root = rootCurrent;
wixKey.Key = sCurrentKey;
wixKey.Action = RegistryKey.ActionType.createAndRemoveOnUninstall;
if(wixKey.Root != RegistryRootType.HKU)
wixKeys.Add(wixKey);
continue;
}
// A value, otherwise
// Parse the value
string sValueName = null;
object oValueValue = null;
match = null;
foreach(Regex regex in new[] {regexValueQuotedQuoted, regexDefaultValueQuoted,})
{
match = regex.Match(line);
if(!match.Success)
continue;
if(match.Groups["Name"] != null)
sValueName = match.Groups["Name"].Value;
if(match.Groups["Value"] != null)
oValueValue = match.Groups["Value"].Value;
break;
}
if((match == null) || (!match.Success))
throw new InvalidOperationException(string.Format("Could not parse the Registry value “{0}”.", line));
// Create the value
var wixValue = new RegistryValue();
wixValue.Root = rootCurrent;
wixValue.Key = sCurrentKey;
if(!string.IsNullOrEmpty(sValueName))
wixValue.Name = sValueName;
wixValue.Value = oValueValue != null ? oValueValue.ToString() : null;
wixValue.Type = RegistryValue.TypeType.@string;
wixValue.Action = RegistryValue.ActionType.write;
if(wixValue.Root != RegistryRootType.HKU)
wixValues.Add(wixValue);
}
}
}
private static void WriteWxsFile(string sOutputWxs, List wixKeys, List wixValues)
{
var wix = new Wix();
var wixFragment = new Fragment();
wix.AddChild(wixFragment);
var wixDirectory = new Directory();
wixFragment.AddChild(wixDirectory);
wixDirectory.Id = "";
var wixComponent = new Component();
wixDirectory.AddChild(wixComponent);
wixComponent.Id = "";
wixComponent.Guid = "*";
foreach(RegistryKey wixKey in wixKeys)
wixComponent.AddChild(wixKey);
foreach(RegistryValue wixValue in wixValues)
wixComponent.AddChild(wixValue);
// Save to the output file
using(var xw = new XmlTextWriter(new FileStream(sOutputWxs, FileMode.Create, FileAccess.Write, FileShare.Read), Encoding.UTF8))
{
xw.Formatting = Formatting.Indented;
wix.OutputXml(xw);
}
}
#endregion
#region Overrides
///
/// Actions under the resolver.
///
protected override void ExecuteTaskResolved()
{
string sInputReg = Bag.GetString(AttributeName.InputFile);
string sOutputWxs = Bag.GetString(AttributeName.OutputFile);
var wixKeys = new List();
var wixValues = new List();
ParseRegFile(sInputReg, wixKeys, wixValues);
WriteWxsFile(sOutputWxs, wixKeys, wixValues);
}
#endregion
}
}