singrdk/base/Windows/AppReader/INFSection.cs

322 lines
8.0 KiB
C#
Raw Normal View History

2008-03-05 09:52:00 -05:00
///////////////////////////////////////////////////////////////////////////////
//
// Microsoft Research Singularity
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
///////////////////////////////////////////////////////////////////////////////
namespace ManifestReader
{
using System;
using System.IO;
using System.Collections;
using System.Xml;
using System.Diagnostics;
public class INFSection
{
string version;
public string Version
{
get
{
return version;
}
}
string name;
public string Name
{
get
{
return name;
}
}
ArrayList lines;
public ArrayList Lines
{
get
{
// return a copy so it can be modified
return new ArrayList(lines);
}
}
ArrayList addRegSectionNames;
ArrayList delRegSectionNames;
public INFSection(string line)
{
string temp;
version = null;
// you can't just throw away all the characters to the right of the
// first ';', 'cause apparently this is a valid character in section identifiers
// Instead, we will find the '[' ']' and make sure there're only comment
// strings after it
int leftBracket = -1;
int rightBracket = -1;
for(int i = 0; i < line.Length; i++)
{
if (line[i] == '[') leftBracket = i;
if (line[i] == ']')
{
if (leftBracket < 0)
{
throw new Exception("Could not find a left bracket");
}
rightBracket = i;
break;
}
}
temp = line.Substring(leftBracket, rightBracket-leftBracket+1);
//Console.WriteLine("Got section title " + temp);
temp = temp.Trim();
if (!temp.StartsWith("[") ||
!temp.EndsWith("]"))
{
throw new Exception("The line is not properly bracketed");
}
temp = temp.TrimEnd(new char[] {']'});
temp = temp.TrimStart(new char[] {'['});
this.name = temp;
lines = new ArrayList();
addRegSectionNames = new ArrayList();
delRegSectionNames = new ArrayList();
}
public void GetAddRegSections(Hashtable h)
{
for(int i = 0; i < addRegSectionNames.Count; i++)
{
h[(string)addRegSectionNames[i]] = null;
}
return;
}
public void GetDelRegSections(Hashtable h)
{
for(int i = 0; i < delRegSectionNames.Count; i++)
{
h[(string)delRegSectionNames[i]] = null;
}
return;
}
public void DiscoverRegistryLines()
{
for(int i = 0; i < lines.Count; i++)
{
string line = (string)lines[i];
if (line.ToLower().StartsWith("addreg"))
{
parseRegLine(line, addRegSectionNames);
}
else if (line.ToLower().StartsWith("delreg"))
{
parseRegLine(line, delRegSectionNames);
}
}
}
public virtual void AddLine(string line)
{
// throw away any comments
string[] parsedLine = line.Split(new char[] {';'}, 20);
// if this is the Version section, record the ClassID
if (this is INFVersionSection)
{
if (line.ToLower().StartsWith("classguid"))
{
string[] components = parsedLine[0].Split(new char[] {'='}, 2);
components[1] = components[1].Trim();
((INFVersionSection)this).Guid = components[1];
}
}
lines.Add(parsedLine[0]);
return;
}
protected void parseRegLine(string line, ArrayList regSectionNames)
{
// split on '=' and then on ',' and walk through and add the entries
string[] twoHalves = line.Split(new char[] {'='}, 2);
if (twoHalves.Length != 2)
{
throw new Exception(line + " is not a valid registry line");
}
// 40 is a magic number. I have no idea how many there may be,
// but I can't imagine there being more than 40 on a single line
string[] regSections = twoHalves[1].Split(new char[] {','}, 40);
for(int i = 0; i < regSections.Length; i++)
{
string rSec = regSections[i];
rSec = rSec.Trim();
regSectionNames.Add(rSec);
}
return;
}
public void UpdateStrings(INFStringSection strSec)
{
// walk through each line and replace its '%'-quoted strings
for(int i = 0; i < lines.Count; i++)
{
string curLine = (string)lines[i];
string replacementLine = curLine;
bool insideReplacement = false;
string curReplace = "";
int percentCount = 0;
for(int j = 0; j < curLine.Length; j++)
{
if (insideReplacement)
{
curReplace += curLine[j];
}
if (curLine[j] == '%')
{
percentCount++;
// if we have seen an odd number of '%' and the next character is not a '%'
if (percentCount % 2 == 1 &&
!(j < curLine.Length - 1 && curLine[j + 1] == '%'))
{
if (insideReplacement)
{
// try to replace the string
if (strSec.hasString(curReplace))
{
replacementLine = replacementLine.Replace(curReplace, strSec[curReplace]);
}
curReplace = "";
percentCount = 0;
}
insideReplacement = !insideReplacement;
if (insideReplacement)
{
curReplace += curLine[j];
}
}
}
else
{
percentCount = 0;
}
}
lines[i] = replacementLine;
}
}
public static bool IsStringSection(string line)
{
return line.ToLower().StartsWith("[strings]");
}
public static bool IsVersionSection(string line)
{
return line.ToLower().StartsWith("[version]");
}
public static bool IsSection(string line)
{
return line.ToLower().StartsWith("[");
}
public static bool IsComment(string line)
{
return line.ToLower().StartsWith(";");
}
// according to ChkINF: # HKR = HKLM,System\CurrentControlSet\Control\Class\{SetupClassGUID}
public static string GetRegKey(string line, string guid)
{
if (!line.StartsWith("HK"))
{
return null;
}
// if we're not referenced from one of the magic sections, this is easy
string[] valStr = line.Split(new char[] {','}, 5);
// the first three entries are the components of the key
string root = valStr[0];
root = root.Trim();
string subkey = "";
string name = "";
if (valStr.Length > 1)
{
subkey = valStr[1];
subkey = subkey.Trim();
name = "";
}
if (root.Equals("HKR"))
{
if (guid == null)
{
guid = "EVIL_INF";
//throw new Exception("We have an HKR string, but no version section!");
}
root = "HKLM";
subkey = "System\\CurrentControlSet\\Control\\Class\\" + guid + "\\" + subkey;
if (valStr.Length > 2)
{
name = valStr[2];
}
}
else
{
// trim any outside quotation marks
subkey = subkey.TrimEnd(new char[] {'"'});
subkey = subkey.TrimStart(new char[] {'"'});
if (valStr.Length > 2)
{
name = valStr[2];
name = name.Trim();
name = name.TrimEnd(new char[] {'"'});
name = name.TrimStart(new char[] {'"'});
}
}
// we ignore registry types for now, although this could in theory bite us,
// since we could get a false negative
string toReturn = root;
if (!subkey.Equals(""))
{
toReturn += "\\" + subkey;
}
if (!name.Equals(""))
{
toReturn += "\\" + name;
}
return toReturn;
}
public static string GetRegValue(string line)
{
// this is pretty much always easy, although it can be complicated
// to tell what type of value this is
string[] valStr = line.Split(new char[] {','}, 5);
if (valStr.Length < 5)
{
return "";
}
// the last entry is the value
string val = valStr[4];
val = val.Trim();
return valStr[4];
}
}
}