public uint AddDescriptor(RawSecurityDescriptor newDescriptor) { // Search to see if this is a known descriptor SecurityDescriptor newDescObj = new SecurityDescriptor(newDescriptor); uint newHash = newDescObj.CalcHash(); byte[] newByteForm = new byte[newDescObj.Size]; newDescObj.WriteTo(newByteForm, 0); foreach (KeyValuePair <HashIndexKey, HashIndexData> entry in _hashIndex.FindAll(new HashFinder(newHash))) { SecurityDescriptor stored = ReadDescriptor(entry.Value); byte[] storedByteForm = new byte[stored.Size]; stored.WriteTo(storedByteForm, 0); if (Utilities.AreEqual(newByteForm, storedByteForm)) { return(entry.Value.Id); } } long offset = _nextSpace; // Write the new descriptor to the end of the existing descriptors SecurityDescriptorRecord record = new SecurityDescriptorRecord(); record.SecurityDescriptor = newByteForm; record.Hash = newHash; record.Id = _nextId; // If we'd overflow into our duplicate block, skip over it to the // start of the next block if ((offset + record.Size) / BlockSize % 2 == 1) { _nextSpace = Utilities.RoundUp(offset, BlockSize * 2); offset = _nextSpace; } record.OffsetInFile = offset; byte[] buffer = new byte[record.Size]; record.WriteTo(buffer, 0); using (Stream s = _file.OpenStream(AttributeType.Data, "$SDS", FileAccess.ReadWrite)) { s.Position = _nextSpace; s.Write(buffer, 0, buffer.Length); s.Position = BlockSize + _nextSpace; s.Write(buffer, 0, buffer.Length); } // Make the next descriptor land at the end of this one _nextSpace = Utilities.RoundUp(_nextSpace + buffer.Length, 16); _nextId++; // Update the indexes HashIndexData hashIndexData = new HashIndexData(); hashIndexData.Hash = record.Hash; hashIndexData.Id = record.Id; hashIndexData.SdsOffset = record.OffsetInFile; hashIndexData.SdsLength = (int)record.EntrySize; HashIndexKey hashIndexKey = new HashIndexKey(); hashIndexKey.Hash = record.Hash; hashIndexKey.Id = record.Id; _hashIndex[hashIndexKey] = hashIndexData; IdIndexData idIndexData = new IdIndexData(); idIndexData.Hash = record.Hash; idIndexData.Id = record.Id; idIndexData.SdsOffset = record.OffsetInFile; idIndexData.SdsLength = (int)record.EntrySize; IdIndexKey idIndexKey = new IdIndexKey(); idIndexKey.Id = record.Id; _idIndex[idIndexKey] = idIndexData; _file.UpdateRecordInMft(); return(record.Id); }
public uint AddDescriptor(RawSecurityDescriptor newDescriptor) { // Search to see if this is a known descriptor SecurityDescriptor newDescObj = new SecurityDescriptor(newDescriptor); uint newHash = newDescObj.CalcHash(); byte[] newByteForm = new byte[newDescObj.Size]; newDescObj.WriteTo(newByteForm, 0); foreach (var entry in _hashIndex.FindAll(new HashFinder(newHash))) { SecurityDescriptor stored = ReadDescriptor(entry.Value); byte[] storedByteForm = new byte[stored.Size]; stored.WriteTo(storedByteForm, 0); if (Utilities.AreEqual(newByteForm, storedByteForm)) { return(entry.Value.Id); } } long offset = _nextSpace; // Write the new descriptor to the end of the existing descriptors SecurityDescriptorRecord record = new SecurityDescriptorRecord(); record.SecurityDescriptor = newByteForm; record.Hash = newHash; record.Id = _nextId; record.OffsetInFile = offset; byte[] buffer = new byte[record.Size]; record.WriteTo(buffer, 0); if (offset + buffer.Length > 0x40000) { throw new NotImplementedException("Excessive number of security descriptors - running into redundant storage area"); } using (Stream s = _file.OpenStream(AttributeType.Data, "$SDS", FileAccess.ReadWrite)) { s.Position = _nextSpace; s.Write(buffer, 0, buffer.Length); s.Position = 0x40000 + _nextSpace; s.Write(buffer, 0, buffer.Length); } // Make the next descriptor land at the end of this one _nextSpace = Utilities.RoundUp(_nextSpace + buffer.Length, 16); _nextId++; // Update the indexes HashIndexData hashIndexData = new HashIndexData(); hashIndexData.Hash = record.Hash; hashIndexData.Id = record.Id; hashIndexData.SdsOffset = record.OffsetInFile; hashIndexData.SdsLength = (int)record.EntrySize; HashIndexKey hashIndexKey = new HashIndexKey(); hashIndexKey.Hash = record.Hash; hashIndexKey.Id = record.Id; _hashIndex[hashIndexKey] = hashIndexData; IdIndexData idIndexData = new IdIndexData(); idIndexData.Hash = record.Hash; idIndexData.Id = record.Id; idIndexData.SdsOffset = record.OffsetInFile; idIndexData.SdsLength = (int)record.EntrySize; IdIndexKey idIndexKey = new IdIndexKey(); idIndexKey.Id = record.Id; _idIndex[idIndexKey] = idIndexData; _file.UpdateRecordInMft(); return(record.Id); }