public override void Write(long pos, byte[] buffer, int offset, int count) { var record = _attribute.Record; if (!CanWrite) { throw new IOException("Attempt to write to file not opened for write"); } if (record.Flags != AttributeFlags.None) { throw new NotImplementedException("Writing to compressed / sparse attributes"); } if (count == 0) { return; } if (!record.IsNonResident) { record.GetDataBuffer(_file).Write(pos, buffer, offset, count); _file.MarkMftRecordDirty(); } else { NonResidentAttributeRecord lastExtent = (NonResidentAttributeRecord)_attribute.LastExtent; IBuffer lastExtentBuffer = lastExtent.GetDataBuffer(_file); long bytesPerCluster = _file.Context.BiosParameterBlock.BytesPerCluster; if (pos + count > record.AllocatedLength) { _file.MarkMftRecordDirty(); long clusterLength = Utilities.RoundUp(pos + count, bytesPerCluster); lastExtentBuffer.SetCapacity(clusterLength - (lastExtent.StartVcn * bytesPerCluster)); record.AllocatedLength = clusterLength; } // Write zeros from end of current initialized data to the start of the new write if (pos > record.InitializedDataLength + 1) { _file.MarkMftRecordDirty(); byte[] wipeBuffer = new byte[bytesPerCluster * 4]; long wipePos = record.InitializedDataLength; while (wipePos < pos) { long extentStartPos; IBuffer extentBuffer = GetExtentBuffer(wipePos, out extentStartPos); long writePos = wipePos - extentStartPos; int numToWrite = (int)Math.Min(Math.Min(extentBuffer.Capacity - writePos, pos - wipePos), wipeBuffer.Length); extentBuffer.Write(writePos, wipeBuffer, 0, numToWrite); wipePos += numToWrite; } } long focusPos = pos; int bytesWritten = 0; while (bytesWritten < count) { long extentStartPos; IBuffer extentBuffer = GetExtentBuffer(focusPos, out extentStartPos); long writePos = focusPos - extentStartPos; int numToWrite = (int)Math.Min(extentBuffer.Capacity - writePos, count - bytesWritten); extentBuffer.Write(writePos, buffer, offset + bytesWritten, numToWrite); focusPos += numToWrite; bytesWritten += numToWrite; } if (pos + count > record.InitializedDataLength) { _file.MarkMftRecordDirty(); record.InitializedDataLength = pos + count; } if (pos + count > record.DataLength) { _file.MarkMftRecordDirty(); record.DataLength = pos + count; } } }