/// <summary> /// Creates a new (empty) registry hive. /// </summary> /// <param name="stream">The stream to contain the new hive.</param> /// <param name="ownership">Whether the returned object owns the stream.</param> /// <returns>The new hive.</returns> public static RegistryHive Create(Stream stream, Ownership ownership) { if (stream == null) { throw new ArgumentNullException("stream", "Attempt to create registry hive in null stream"); } // Construct a file with minimal structure - hive header, plus one (empty) bin BinHeader binHeader = new BinHeader(); binHeader.FileOffset = 0; binHeader.BinSize = (int)(4 * Sizes.OneKiB); HiveHeader hiveHeader = new HiveHeader(); hiveHeader.Length = binHeader.BinSize; stream.Position = 0; byte[] buffer = new byte[hiveHeader.Size]; hiveHeader.WriteTo(buffer, 0); stream.Write(buffer, 0, buffer.Length); buffer = new byte[binHeader.Size]; binHeader.WriteTo(buffer, 0); stream.Position = BinStart; stream.Write(buffer, 0, buffer.Length); buffer = new byte[4]; Utilities.WriteBytesLittleEndian(binHeader.BinSize - binHeader.Size, buffer, 0); stream.Write(buffer, 0, buffer.Length); // Make sure the file is initialized out to the end of the firs bin stream.Position = BinStart + binHeader.BinSize - 1; stream.WriteByte(0); // Temporary hive to perform construction of higher-level structures RegistryHive newHive = new RegistryHive(stream); KeyNodeCell rootCell = new KeyNodeCell("root", -1); rootCell.Flags = RegistryKeyFlags.Normal | RegistryKeyFlags.Root; newHive.UpdateCell(rootCell, true); RegistrySecurity sd = new RegistrySecurity(); sd.SetSecurityDescriptorSddlForm("O:BAG:BAD:PAI(A;;KA;;;SY)(A;CI;KA;;;BA)", AccessControlSections.All); SecurityCell secCell = new SecurityCell(sd); newHive.UpdateCell(secCell, true); secCell.NextIndex = secCell.Index; secCell.PreviousIndex = secCell.Index; newHive.UpdateCell(secCell, false); rootCell.SecurityIndex = secCell.Index; newHive.UpdateCell(rootCell, false); // Ref the root cell from the hive header hiveHeader.RootCell = rootCell.Index; buffer = new byte[hiveHeader.Size]; hiveHeader.WriteTo(buffer, 0); stream.Position = 0; stream.Write(buffer, 0, buffer.Length); // Finally, return the new hive return(new RegistryHive(stream, ownership)); }
/// <summary> /// Deletes a named value stored within this key. /// </summary> /// <param name="name">The name of the value to delete.</param> /// <param name="throwOnMissingValue">Throws ArgumentException if <c>name</c> doesn't exist.</param> public void DeleteValue(string name, bool throwOnMissingValue) { bool foundValue = false; if (_cell.NumValues != 0) { byte[] valueList = _hive.RawCellData(_cell.ValueListIndex, _cell.NumValues * 4); int i = 0; while (i < _cell.NumValues) { int valueIndex = Utilities.ToInt32LittleEndian(valueList, i * 4); ValueCell valueCell = _hive.GetCell <ValueCell>(valueIndex); if (string.Compare(valueCell.Name, name, StringComparison.OrdinalIgnoreCase) == 0) { foundValue = true; _hive.FreeCell(valueIndex); _cell.NumValues--; _hive.UpdateCell(_cell, false); break; } ++i; } // Move following value's to fill gap if (i < _cell.NumValues) { while (i < _cell.NumValues) { int valueIndex = Utilities.ToInt32LittleEndian(valueList, (i + 1) * 4); Utilities.WriteBytesLittleEndian(valueIndex, valueList, i * 4); ++i; } _hive.WriteRawCellData(_cell.ValueListIndex, valueList, 0, _cell.NumValues * 4); } // TODO: Update maxbytes for value name and value content if this was the largest value for either. // Windows seems to repair this info, if not accurate, though. } if (throwOnMissingValue && !foundValue) { throw new ArgumentException("No such value: " + name, "name"); } }