// Decompiled with JetBrains decompiler // Type: Microsoft.InfoCards.SecondaryIndex // Assembly: infocard, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 // MVID: ADE0A079-11DB-4A46-8BDE-D2A592CA8DEA // Assembly location: C:\Users\Administrateur\Downloads\Virusshare-00000-msil\Virus.Win32.Expiro.w-67b630ead60119692b9abbdfd8717c96904ef041127c2cae033c86b718eaa61e.exe using Microsoft.InfoCards.Diagnostics; using System; using System.Collections.Generic; using System.Runtime.InteropServices; namespace Microsoft.InfoCards { internal class SecondaryIndex { private byte[] m_buffer; private int m_lastIndex; private IComparer m_searchComparer; private IComparer m_sortComparer; private SecondaryIndexDefinition m_definition; private bool m_isOpen; public SecondaryIndex( SecondaryIndexDefinition definition, IComparer search, IComparer sort) { if (definition == null) throw InfoCardTrace.ThrowHelperArgumentNull(nameof (definition)); if (search == null) throw InfoCardTrace.ThrowHelperArgumentNull(nameof (search)); if (sort == null) throw InfoCardTrace.ThrowHelperArgumentNull(nameof (sort)); this.m_definition = definition; this.m_searchComparer = search; this.m_sortComparer = sort; this.Clear(); this.m_isOpen = true; } public SecondaryIndexDefinition Definition { get { this.ThrowIfNotOpen(); return this.m_definition; } } public int LastIndex { get { this.ThrowIfNotOpen(); return this.m_lastIndex; } } public byte[] GetBuffer() { this.ThrowIfNotOpen(); return this.m_buffer; } internal void SetValuesForId(int id, DataRowIndexBuffer indexBuffer, bool remove) { this.ThrowIfNotOpen(); if (id <= 0) throw InfoCardTrace.ThrowHelperError((Exception) new ArgumentOutOfRangeException(nameof (id), SR.GetString("StoreLocalIdOutOfRange"))); IndexObject[] array = indexBuffer[this.m_definition.Name].ToArray(); if (remove) this.RemoveForIdAndShiftData(id); if (array == null || array.Length == 0) return; for (int index = 0; index < array.Length; ++index) { if (!array[index].IsCompiled) { if (!array[index].CanCompile) throw InfoCardTrace.ThrowHelperError((Exception) new InvalidOperationException(SR.GetString("StoreIndexObjectCanNotBeCompiled"))); array[index].Compile(this.m_definition); } this.ValidateIndexValue(array[index].CompiledForm); this.ShiftAndInsertValues(id, array[index].CompiledForm); } } public void RemoveAllValuesForId(int id) { this.ThrowIfNotOpen(); if (id <= 0) throw InfoCardTrace.ThrowHelperError((Exception) new ArgumentOutOfRangeException(nameof (id), SR.GetString("StoreLocalIdOutOfRange"))); this.RemoveForIdAndShiftData(id); } public unsafe void PopulateRowIndexBuffer(DataRowIndexBuffer buffer, int id) { this.ThrowIfNotOpen(); if (id <= 0) throw InfoCardTrace.ThrowHelperError((Exception) new ArgumentOutOfRangeException(nameof (id), SR.GetString("StoreLocalIdOutOfRange"))); if (-1 == this.m_lastIndex) return; List indexObjectList = new List(); fixed (byte* numPtr = &this.m_buffer[0]) { for (int index = 0; index < this.m_lastIndex + 1; ++index) { if (((SecondaryIndexItem*) numPtr)[index].LocalId == id) { byte[] numArray = new byte[60]; Marshal.Copy((IntPtr) (void*) &((SecondaryIndexItem*) numPtr)[index].HashValue, numArray, 0, 60); indexObjectList.Add(new IndexObject(numArray)); } } if (indexObjectList.Count > 0) buffer.SetIndexValues(this.m_definition.Name, indexObjectList.ToArray()); } } public void Close() { if (!this.m_isOpen) return; this.Clear(); this.m_buffer = (byte[]) null; this.m_isOpen = false; } public void ValidateIndexValue(byte[] indexValue) { if (SecondaryIndexSettings.Nullable != (this.m_definition.Settings & SecondaryIndexSettings.Nullable) && SecondaryIndex.IsBufferEmpty(indexValue)) throw InfoCardTrace.ThrowHelperError((Exception) new InvalidOperationException(SR.GetString("StoreNullIndexValueNotPermitted", (object) this.m_definition.Name))); } public void SetBuffer(byte[] buffer, int lastIndex) { this.ThrowIfNotOpen(); this.m_buffer = buffer; this.m_lastIndex = lastIndex; } public unsafe int Match(IndexObject obj, LocalIdCollection collection, int low, int high) { if (obj == null) throw InfoCardTrace.ThrowHelperArgumentNull(nameof (obj)); if (collection == null) throw InfoCardTrace.ThrowHelperArgumentNull(nameof (collection)); if ((uint) low > (uint) high) throw InfoCardTrace.ThrowHelperError((Exception) new ArgumentOutOfRangeException(nameof (low), (object) low, SR.GetString("StoreLowValueOutOfRange"))); if ((uint) high > (uint) this.m_lastIndex) throw InfoCardTrace.ThrowHelperError((Exception) new ArgumentOutOfRangeException(nameof (high), (object) high, SR.GetString("StoreHighValueOutOfRange"))); if (!obj.IsCompiled) { if (!obj.CanCompile) throw InfoCardTrace.ThrowHelperError((Exception) new InvalidOperationException(SR.GetString("StoreIndexObjectCanNotBeCompiled"))); obj.Compile(this.m_definition); } this.ValidateIndexValue(obj.CompiledForm); SecondaryIndexItem secondaryIndexItem; Marshal.Copy(obj.CompiledForm, 0, (IntPtr) (void*) &secondaryIndexItem.HashValue, 60); return this.Match(&secondaryIndexItem, collection, low, high); } public void Clear() { this.m_buffer = new byte[sizeof (SecondaryIndexItem) * this.m_definition.InitialSize]; this.m_lastIndex = -1; } private unsafe void RemoveForIdAndShiftData(int id) { if (-1 == this.m_lastIndex) return; int num1 = this.m_lastIndex + 1; int num2 = 0; int index = 0; fixed (byte* numPtr = &this.m_buffer[0]) { do { InfoCardTrace.Assert((uint) num2 < (uint) this.m_buffer.Length, "currentOffset is invalid or has been corrupted."); InfoCardTrace.Assert(0 == num2 % sizeof (SecondaryIndexItem), "currentOffset is not aligned proppertly. This can cause data corruption."); InfoCardTrace.Assert((SecondaryIndexItem*) numPtr + index - (SecondaryIndexItem*) numPtr <= (long) (num1 * sizeof (SecondaryIndexItem)), "Current IndexPointer has walked beyond the total count of valid data."); index = num2 / sizeof (SecondaryIndexItem); InfoCardTrace.Assert((SecondaryIndexItem*) numPtr + index - (SecondaryIndexItem*) numPtr < (long) this.m_buffer.Length, "Current IndexPointer has walked beyond the allocated buffer"); if (((SecondaryIndexItem*) numPtr)[index].LocalId == id) { if (num1 != index + 1) { InfoCardTrace.Assert(this.m_lastIndex >= 0, "LastIndex indicates an invalid state for the index"); Array.Copy((Array) this.m_buffer, num2 + sizeof (SecondaryIndexItem), (Array) this.m_buffer, num2, (num1 - (index + 1)) * sizeof (SecondaryIndexItem)); Array.Clear((Array) this.m_buffer, this.m_lastIndex * sizeof (SecondaryIndexItem), sizeof (SecondaryIndexItem)); } else Array.Clear((Array) this.m_buffer, num2, sizeof (SecondaryIndexItem)); --this.m_lastIndex; --num1; } else num2 += sizeof (SecondaryIndexItem); } while (num2 / sizeof (SecondaryIndexItem) < num1); } } private unsafe void ShiftAndInsertValues(int id, byte[] indexValue) { InfoCardTrace.Assert(id > 0, "Invalid LocalId"); InfoCardTrace.Assert(null != indexValue, "Null indev value passed"); InfoCardTrace.Assert(indexValue.Length == 60, "Index buffer is not correct size."); SecondaryIndexItem secondaryIndexItem; secondaryIndexItem.LocalId = id; Marshal.Copy(indexValue, 0, (IntPtr) (void*) &secondaryIndexItem.HashValue, 60); this.AddItem(&secondaryIndexItem); } private static bool IsBufferEmpty(byte[] hash) { for (int index = 0; index < hash.Length; ++index) { if (hash[index] != (byte) 0) return false; } return true; } private unsafe int BSearch( SecondaryIndexItem* pMatch, IComparer comp, int lowStart, int highStart) { int num1 = lowStart; int num2 = highStart; fixed (byte* numPtr = &this.m_buffer[0]) { while (num1 <= num2) { int num3 = (num2 + num1) / 2; int num4 = comp.Compare((IntPtr) (void*) pMatch, (IntPtr) (void*) ((SecondaryIndexItem*) numPtr + num3)); if (num4 == 0) { num2 = num3; if (num2 == num1) return num2; } else if (num4 < 0) num2 = num3 - 1; else num1 = num3 + 1; } } return ~num1; } private unsafe int Match( SecondaryIndexItem* pMatch, LocalIdCollection results, int lowStart, int highStart) { int index = this.BSearch(pMatch, this.m_searchComparer, lowStart, highStart); if (index >= 0) { fixed (byte* numPtr = &this.m_buffer[0]) { InfoCardTrace.Assert(index * sizeof (SecondaryIndexItem) < this.m_buffer.Length, "Index has moved beyond the allocated buffer."); do { results.Add(((SecondaryIndexItem*) numPtr)[index].LocalId); ++index; } while (index <= this.m_lastIndex && this.m_searchComparer.Compare((IntPtr) (void*) ((SecondaryIndexItem*) numPtr + index), (IntPtr) (void*) pMatch) == 0); } --index; } return index; } private unsafe void AddItem(SecondaryIndexItem* pMatch) { InfoCardTrace.Assert(IntPtr.Zero != (IntPtr) pMatch, "Match pointer is null"); InfoCardTrace.Assert(pMatch->LocalId > 0, "Match pointer has invalid local id"); int num1; if (SecondaryIndexSettings.Unique == (this.m_definition.Settings & SecondaryIndexSettings.Unique)) { num1 = this.BSearch(pMatch, this.m_searchComparer, 0, this.m_lastIndex); if (num1 >= 0) throw InfoCardTrace.ThrowHelperError((Exception) new InvalidOperationException(SR.GetString("StoreUniqueIndexConstraintBroken", (object) this.m_definition.Name))); } else num1 = this.BSearch(pMatch, this.m_sortComparer, 0, this.m_lastIndex); if (num1 >= 0) return; int index = ~num1; int num2 = this.m_lastIndex + 1; int num3 = this.m_buffer.Length / sizeof (SecondaryIndexItem); if (num2 + 1 >= num3) this.GrowIndex(); if (index < num2) { int num4 = num2 * sizeof (SecondaryIndexItem); int sourceIndex = index * sizeof (SecondaryIndexItem); int destinationIndex = sourceIndex + sizeof (SecondaryIndexItem); int length = num4 - sourceIndex; InfoCardTrace.Assert(length > 0, "No Bytes to copy into index."); Array.Copy((Array) this.m_buffer, sourceIndex, (Array) this.m_buffer, destinationIndex, length); } fixed (byte* numPtr = &this.m_buffer[0]) { InfoCardTrace.Assert((SecondaryIndexItem*) numPtr + index - (SecondaryIndexItem*) numPtr < (long) this.m_buffer.Length, "IndexPointer is beyond the end of the allocated buffer"); ((SecondaryIndexItem*) numPtr)[index] = *pMatch; } ++this.m_lastIndex; } private void GrowIndex() { int increaseByPercent = Utility.CalculateIncreaseByPercent(this.m_buffer.Length, sizeof (SecondaryIndexItem), 5); InfoCardTrace.Assert(increaseByPercent > this.m_buffer.Length && 0 == increaseByPercent % sizeof (SecondaryIndexItem), "New size calculated for index is invalid."); int length = (this.m_lastIndex + 1) * sizeof (SecondaryIndexItem); byte[] destinationArray = new byte[increaseByPercent]; Array.Copy((Array) this.m_buffer, 0, (Array) destinationArray, 0, length); Array.Clear((Array) this.m_buffer, 0, length); this.m_buffer = destinationArray; } private void ThrowIfNotOpen() { if (!this.m_isOpen) throw InfoCardTrace.ThrowHelperError((Exception) new ObjectDisposedException(nameof (SecondaryIndex))); } } }