309 lines
7.9 KiB
C#
309 lines
7.9 KiB
C#
// ----------------------------------------------------------------------------
|
|
//
|
|
// 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];
|
|
|
|
}
|
|
}
|
|
}
|