/// <summary>
        /// Finds all rows owned by <paramref name="key"/> in table <paramref name="tableSource"/>
        /// whose index is <paramref name="keyColIndex"/>
        /// </summary>
        /// <param name="tableSource">Table to search</param>
        /// <param name="keyColIndex">Key column index</param>
        /// <param name="key">Key</param>
        /// <returns>A <see cref="RidList"/> instance</returns>
        protected RidList FindAllRows(MDTable tableSource, int keyColIndex, uint key)
        {
            uint startRid = BinarySearch(tableSource, keyColIndex, key);

            if (tableSource.IsInvalidRID(startRid))
            {
                return(RidList.Empty);
            }
            uint endRid = startRid + 1;
            var  column = tableSource.TableInfo.Columns[keyColIndex];

            for (; startRid > 1; startRid--)
            {
                if (!tablesStream.TryReadColumn24(tableSource, startRid - 1, column, out uint key2))
                {
                    break;                      // Should never happen since startRid is valid
                }
                if (key != key2)
                {
                    break;
                }
            }
            for (; endRid <= tableSource.Rows; endRid++)
            {
                if (!tablesStream.TryReadColumn24(tableSource, endRid, column, out uint key2))
                {
                    break;                      // Should never happen since endRid is valid
                }
                if (key != key2)
                {
                    break;
                }
            }
            return(RidList.Create(startRid, endRid - startRid));
        }
        /// <summary>
        /// Gets a rid list (eg. field list)
        /// </summary>
        /// <param name="tableSource">Source table, eg. <c>TypeDef</c></param>
        /// <param name="tableSourceRid">Row ID in <paramref name="tableSource"/></param>
        /// <param name="colIndex">Column index in <paramref name="tableSource"/>, eg. 4 for <c>TypeDef.FieldList</c></param>
        /// <param name="tableDest">Destination table, eg. <c>Field</c></param>
        /// <returns>A new <see cref="RidList"/> instance</returns>
        RidList GetRidList(MDTable tableSource, uint tableSourceRid, int colIndex, MDTable tableDest)
        {
            var column = tableSource.TableInfo.Columns[colIndex];

            if (!tablesStream.TryReadColumn24(tableSource, tableSourceRid, column, out uint startRid))
            {
                return(RidList.Empty);
            }
            bool hasNext = tablesStream.TryReadColumn24(tableSource, tableSourceRid + 1, column, out uint nextListRid);
            uint lastRid = tableDest.Rows + 1;

            if (startRid == 0 || startRid >= lastRid)
            {
                return(RidList.Empty);
            }
            uint endRid = !hasNext || (nextListRid == 0 && tableSourceRid + 1 == tableSource.Rows && tableDest.Rows == 0xFFFF) ? lastRid : nextListRid;

            if (endRid < startRid)
            {
                endRid = startRid;
            }
            if (endRid > lastRid)
            {
                endRid = lastRid;
            }
            return(RidList.Create(startRid, endRid - startRid));
        }
Beispiel #3
0
        /// <inheritdoc/>
        public override RidList GetExportedTypeRidList()
        {
            if (!hasDeletedNonFields)
            {
                return(base.GetExportedTypeRidList());
            }
            uint rows = tablesStream.ExportedTypeTable.Rows;
            var  list = new List <uint>((int)rows);

            for (uint rid = 1; rid <= rows; rid++)
            {
                if (!tablesStream.TryReadExportedTypeRow(rid, out var row))
                {
                    continue;                           // Should never happen since rid is valid
                }
                // RTSpecialName is ignored by the CLR. It's only the name that indicates
                // whether it's been deleted.
                if (stringsStream.ReadNoNull(row.TypeName).StartsWith(DeletedName))
                {
                    continue;                           // ignore this deleted row
                }
                list.Add(rid);
            }
            return(RidList.Create(list));
        }
            /// <summary>
            /// Find all rids that contain <paramref name="key"/>
            /// </summary>
            /// <param name="key">The key</param>
            /// <returns>A new <see cref="RidList"/> instance</returns>
            public RidList FindAllRows(uint key)
            {
                int startIndex = BinarySearch(key);

                if (startIndex == 0)
                {
                    return(RidList.Empty);
                }
                int endIndex = startIndex + 1;

                for (; startIndex > 1; startIndex--)
                {
                    if (key != rows[startIndex - 1].key)
                    {
                        break;
                    }
                }
                for (; endIndex < rows.Length; endIndex++)
                {
                    if (key != rows[endIndex].key)
                    {
                        break;
                    }
                }
                var list = new List <uint>(endIndex - startIndex);

                for (int i = startIndex; i < endIndex; i++)
                {
                    list.Add(rows[i].rid);
                }
                return(RidList.Create(list));
            }
 public override RidList GetNestedClassRidList(uint typeDefRid)
 {
     if (typeDefRidToNestedClasses is null)
     {
         InitializeNestedClassesDictionary();
     }
     if (typeDefRidToNestedClasses.TryGetValue(typeDefRid, out var ridList))
     {
         return(RidList.Create(ridList));
     }
     return(RidList.Empty);
 }
Beispiel #6
0
        /// <inheritdoc/>
        public override RidList GetFieldRidList(uint typeDefRid)
        {
            var list = GetRidList(tablesStream.TypeDefTable, typeDefRid, 4, tablesStream.FieldTable);

            if (list.Count == 0 || (!hasFieldPtr && !hasDeletedFields))
            {
                return(list);
            }

            var destTable = tablesStream.FieldTable;
            var newList   = new List <uint>(list.Count);

            for (int i = 0; i < list.Count; i++)
            {
                var rid = ToFieldRid(list[i]);
                if (destTable.IsInvalidRID(rid))
                {
                    continue;
                }
                if (hasDeletedFields)
                {
                    // It's a deleted row if RTSpecialName is set and name is "_Deleted"
                    if (!tablesStream.TryReadFieldRow(rid, out var row))
                    {
                        continue;                               // Should never happen since rid is valid
                    }
                    if (runtime == CLRRuntimeReaderKind.CLR)
                    {
                        if ((row.Flags & (uint)FieldAttributes.RTSpecialName) != 0)
                        {
                            if (stringsStream.ReadNoNull(row.Name).StartsWith(DeletedName))
                            {
                                continue;                                       // ignore this deleted row
                            }
                        }
                    }
                    else
                    {
                        if ((row.Flags & (uint)(FieldAttributes.SpecialName | FieldAttributes.RTSpecialName)) == (uint)(FieldAttributes.SpecialName | FieldAttributes.RTSpecialName))
                        {
                            if (stringsStream.ReadNoNull(row.Name) == DeletedName)
                            {
                                continue;                                       // ignore this deleted row
                            }
                        }
                    }
                }
                // It's a valid non-deleted rid so add it
                newList.Add(rid);
            }
            return(RidList.Create(newList));
        }
Beispiel #7
0
        /// <inheritdoc/>
        public override RidList GetPropertyRidList(uint propertyMapRid)
        {
            var list = GetRidList(tablesStream.PropertyMapTable, propertyMapRid, 1, tablesStream.PropertyTable);

            if (list.Count == 0 || (!hasPropertyPtr && !hasDeletedNonFields))
            {
                return(list);
            }

            var destTable = tablesStream.PropertyTable;
            var newList   = new List <uint>(list.Count);

            for (int i = 0; i < list.Count; i++)
            {
                var rid = ToPropertyRid(list[i]);
                if (destTable.IsInvalidRID(rid))
                {
                    continue;
                }
                if (hasDeletedNonFields)
                {
                    // It's a deleted row if RTSpecialName is set and name is "_Deleted"
                    if (!tablesStream.TryReadPropertyRow(rid, out var row))
                    {
                        continue;                               // Should never happen since rid is valid
                    }
                    if ((row.PropFlags & (uint)PropertyAttributes.RTSpecialName) != 0)
                    {
                        if (stringsStream.ReadNoNull(row.Name).StartsWith(DeletedName))
                        {
                            continue;                                   // ignore this deleted row
                        }
                    }
                }
                // It's a valid non-deleted rid so add it
                newList.Add(rid);
            }
            return(RidList.Create(newList));
        }
Beispiel #8
0
        /// <inheritdoc/>
        public override RidList GetParamRidList(uint methodRid)
        {
            var list = GetRidList(tablesStream.MethodTable, methodRid, 5, tablesStream.ParamTable);

            if (list.Count == 0 || !hasParamPtr)
            {
                return(list);
            }

            var destTable = tablesStream.ParamTable;
            var newList   = new List <uint>(list.Count);

            for (int i = 0; i < list.Count; i++)
            {
                var rid = ToParamRid(list[i]);
                if (destTable.IsInvalidRID(rid))
                {
                    continue;
                }
                newList.Add(rid);
            }
            return(RidList.Create(newList));
        }
        void InitializeNestedClassesDictionary()
        {
            var table     = tablesStream.NestedClassTable;
            var destTable = tablesStream.TypeDefTable;

            Dictionary <uint, bool> validTypeDefRids = null;
            var typeDefRidList = GetTypeDefRidList();

            if ((uint)typeDefRidList.Count != destTable.Rows)
            {
                validTypeDefRids = new Dictionary <uint, bool>(typeDefRidList.Count);
                for (int i = 0; i < typeDefRidList.Count; i++)
                {
                    validTypeDefRids[typeDefRidList[i]] = true;
                }
            }

            var nestedRidsDict = new Dictionary <uint, bool>((int)table.Rows);
            var nestedRids     = new List <uint>((int)table.Rows);              // Need it so we add the rids in correct order

            for (uint rid = 1; rid <= table.Rows; rid++)
            {
                if (validTypeDefRids is not null && !validTypeDefRids.ContainsKey(rid))
                {
                    continue;
                }
                if (!tablesStream.TryReadNestedClassRow(rid, out var row))
                {
                    continue;                           // Should never happen since rid is valid
                }
                if (!destTable.IsValidRID(row.NestedClass) || !destTable.IsValidRID(row.EnclosingClass))
                {
                    continue;
                }
                if (nestedRidsDict.ContainsKey(row.NestedClass))
                {
                    continue;
                }
                nestedRidsDict[row.NestedClass] = true;
                nestedRids.Add(row.NestedClass);
            }

            var newTypeDefRidToNestedClasses = new Dictionary <uint, List <uint> >();
            int count = nestedRids.Count;

            for (int i = 0; i < count; i++)
            {
                var nestedRid = nestedRids[i];
                if (!tablesStream.TryReadNestedClassRow(GetNestedClassRid(nestedRid), out var row))
                {
                    continue;
                }
                if (!newTypeDefRidToNestedClasses.TryGetValue(row.EnclosingClass, out var ridList))
                {
                    newTypeDefRidToNestedClasses[row.EnclosingClass] = ridList = new List <uint>();
                }
                ridList.Add(nestedRid);
            }

            var newNonNestedTypes = new List <uint>((int)(destTable.Rows - nestedRidsDict.Count));

            for (uint rid = 1; rid <= destTable.Rows; rid++)
            {
                if (validTypeDefRids is not null && !validTypeDefRids.ContainsKey(rid))
                {
                    continue;
                }
                if (nestedRidsDict.ContainsKey(rid))
                {
                    continue;
                }
                newNonNestedTypes.Add(rid);
            }

            Interlocked.CompareExchange(ref nonNestedTypes, new StrongBox <RidList>(RidList.Create(newNonNestedTypes)), null);

            // Initialize this one last since it's tested by the callers of this method
            Interlocked.CompareExchange(ref typeDefRidToNestedClasses, newTypeDefRidToNestedClasses, null);
        }
 public override RidList GetExportedTypeRidList() => RidList.Create(1, tablesStream.ExportedTypeTable.Rows);
 public override RidList GetTypeDefRidList() => RidList.Create(1, tablesStream.TypeDefTable.Rows);