コード例 #1
0
ファイル: TemplateUserType.cs プロジェクト: heruix/WinDbgCs
        /// <summary>
        /// Gets the type tree for the specified field.
        /// </summary>
        /// <param name="field">The field.</param>
        /// <param name="factory">The user type factory.</param>
        /// <param name="extractingBaseClass">if set to <c>true</c> user type field is being generated for getting base class.</param>
        /// <param name="bitLength">Number of bits used for this symbol.</param>
        protected override TypeTree GetFieldTypeTree(SymbolField field, UserTypeFactory factory, bool extractingBaseClass, int bitLength = 0)
        {
            // Do not match specializations when getting type for base class.
            if (extractingBaseClass || NumberOfTemplateArguments == 0)
            {
                return(GetSymbolTypeTree(field.Type, factory, bitLength));
            }

            // Check field in all specializations
            var specializedFields = SpecializedTypes.Select(r => new Tuple <TemplateUserType, SymbolField>(r, r.Symbol.Fields.FirstOrDefault(q => q.Name == field.Name))).ToArray();

            if (specializedFields.Any(r => r.Item2 == null))
            {
                // TODO: Incorrect bucketization. Field does not exist in all specialization.
                return(GetSymbolTypeTree(field.Type, factory, bitLength));
            }

            if (specializedFields.All(r => r.Item2.Type.Name == field.Type.Name))
            {
                // There is no specialization, all types across the specializations are the same.
                return(GetSymbolTypeTree(field.Type, factory, bitLength));
            }

            // Try to get type tree
            TypeTree result = GetSymbolTypeTree(field.Type, factory, bitLength);

            return(FixTypeTree(result, field.Type, factory));
        }
コード例 #2
0
        /// <summary>
        /// Gets the name of the property based on the field name.
        /// </summary>
        /// <param name="field">The field.</param>
        /// <param name="userType">The user type owning the field.</param>
        /// <returns>The name of the property.</returns>
        public static string GetPropertyName(SymbolField field, UserType userType)
        {
            if (!string.IsNullOrEmpty(field.PropertyName))
            {
                return(field.PropertyName);
            }

            string fieldName = field.Name;

            // Check if field name is the same as owner type name
            if (fieldName == userType.Symbol.Name) // TODO: Check if this should be userType.ConstructorName
            {
                // Property name cannot be equal to the class name
                return(string.Format("_{0}", fieldName));
            }

            // Check if field name is the same as any inner type name
            foreach (string className in userType.InnerTypes.Select(r => r.ClassName)) // TODO: Check if this should be r.ConstructorName
            {
                if (fieldName == className)
                {
                    // Property name cannot be equal to the class name
                    return(string.Format("_{0}", fieldName));
                }
            }

            fieldName = fieldName.Replace("::", "_");

            switch (fieldName)
            {
            case "lock":
            case "base":
            case "params":
            case "enum":
            case "in":
            case "object":
            case "event":
            case "string":
            case "fixed":
            case "internal":
            case "out":
            case "override":
            case "virtual":
            case "namespace":
            case "public":
            case "private":
            case "decimal":
                return(string.Format("_{0}", fieldName));

            default:
                break;
            }

            return(fieldName);
        }
コード例 #3
0
ファイル: TemplateUserType.cs プロジェクト: leculver/WinDbgCs
        /// <summary>
        /// Gets the type tree for the specified field.
        /// </summary>
        /// <param name="field">The field.</param>
        /// <param name="factory">The user type factory.</param>
        /// <param name="extractingBaseClass">if set to <c>true</c> user type field is being generated for getting base class.</param>
        /// <param name="bitLength">Number of bits used for this symbol.</param>
        protected override TypeTree GetFieldTypeTree(SymbolField field, UserTypeFactory factory, bool extractingBaseClass, int bitLength = 0)
        {
            // Do not match specializations when getting type for base class.
            if (extractingBaseClass || NumberOfTemplateArguments == 0)
            {
                return(GetSymbolTypeTree(field.Type, factory, bitLength));
            }

            // Check field in all specializations
            var specializedFields = SpecializedTypes.Select(r => new Tuple <TemplateUserType, SymbolField>(r, r.Symbol.Fields.FirstOrDefault(q => q.Name == field.Name))).ToArray();

            if (specializedFields.Any(r => r.Item2 == null))
            {
                // TODO: Incorrect bucketization. Field does not exist in all specialization.
                return(GetSymbolTypeTree(field.Type, factory, bitLength));
            }

            if (specializedFields.All(r => r.Item2.Type.Name == field.Type.Name))
            {
                // There is no specialization, all types across the specializations are the same.
                return(GetSymbolTypeTree(field.Type, factory, bitLength));
            }

            // Try to get type tree
            TypeTree result = GetSymbolTypeTree(field.Type, factory, bitLength);

            if (result is BasicTypeTree)
            {
                // Basic type tree is not challenged against template arguments, so try to do that.
                UserType basicUserType;

                if (CreateFactory(factory).GetUserType(field.Type, out basicUserType))
                {
                    TypeTree tree = UserTypeTree.Create(basicUserType, factory);

                    if (tree != null)
                    {
                        return(tree);
                    }
                }

                // Failed to match the type
                // TODO: Look for typedeclared. Class is using different types than in template specialization. We cannot support it right now.
                return(new VariableTypeTree());
            }

            return(result);
        }
コード例 #4
0
        /// <summary>
        /// Generates user type field based on the specified symbol field and all other fields that are prepared for this function.
        /// Do not use this function directly, unless you are calling it from overridden function.
        /// </summary>
        /// <param name="field">The symbol field.</param>
        /// <param name="fieldType">The field tree type.</param>
        /// <param name="factory">The user type factory.</param>
        /// <param name="simpleFieldValue">The code foe "simple field value" used when creating transformation.</param>
        /// <param name="gettingField">The code for getting field variable.</param>
        /// <param name="isStatic">if set to <c>true</c> generated field should be static.</param>
        /// <param name="generationFlags">The user type generation flags.</param>
        /// <param name="extractingBaseClass">if set to <c>true</c> user type field is being generated for getting base class.</param>
        protected override UserTypeField ExtractFieldInternal(SymbolField field, TypeTree fieldType, UserTypeFactory factory, string simpleFieldValue, string gettingField, bool isStatic, UserTypeGenerationFlags generationFlags, bool extractingBaseClass)
        {
            // Physical code generation make sense only for non-static fields
            if (!isStatic)
            {
                bool lazyCacheUserTypeFields = generationFlags.HasFlag(UserTypeGenerationFlags.LazyCacheUserTypeFields);

                bool                   cacheUserTypeFields       = generationFlags.HasFlag(UserTypeGenerationFlags.CacheUserTypeFields);
                bool                   cacheStaticUserTypeFields = generationFlags.HasFlag(UserTypeGenerationFlags.CacheStaticUserTypeFields);
                string                 constructorText           = "";
                string                 fieldName          = field.Name;
                string                 fieldTypeString    = fieldType.GetTypeString();
                BasicTypeTree          baseType           = fieldType as BasicTypeTree;
                ArrayTypeTree          codeArrayType      = fieldType as ArrayTypeTree;
                UserTypeTree           userType           = fieldType as UserTypeTree;
                TransformationTypeTree transformationType = fieldType as TransformationTypeTree;
                bool                   isEmbedded         = field.Type.Tag != CodeTypeTag.Pointer;

                // Specialization for basic types
                if (baseType != null)
                {
                    if (baseType.BasicType == "string")
                    {
                        int charSize = field.Type.ElementType.Size;

                        constructorText = string.Format("ReadString(GetCodeType().Module.Process, ReadPointer(memoryBuffer, memoryBufferOffset + {0}, {1}), {2})", field.Offset, field.Type.Size, charSize);
                    }
                    else if (baseType.BasicType != "NakedPointer")
                    {
                        if (field.LocationType == LocationType.BitField)
                        {
                            constructorText = string.Format("Read{0}(memoryBuffer, memoryBufferOffset + {1}, {2}, {3})", baseType.GetTypeString().UppercaseFirst(), field.Offset, field.Size, field.BitPosition);
                        }
                        else
                        {
                            constructorText = string.Format("Read{0}(memoryBuffer, memoryBufferOffset + {1})", baseType.GetTypeString().UppercaseFirst(), field.Offset);
                        }
                    }
                }
                // Specialization for arrays
                else if (codeArrayType != null)
                {
                    if (codeArrayType.ElementType is BasicTypeTree)
                    {
                        baseType = (BasicTypeTree)codeArrayType.ElementType;
                        if (baseType != null && baseType.BasicType != "string" && baseType.BasicType != "NakedPointer")
                        {
                            int arraySize   = field.Type.Size;
                            int elementSize = field.Type.ElementType.Size;

                            if (baseType.BasicType == "char")
                            {
                                constructorText = string.Format("Read{0}Array(memoryBuffer, memoryBufferOffset + {1}, {2}, {3})", baseType.GetTypeString().UppercaseFirst(), field.Offset, arraySize / elementSize, elementSize);
                            }
                            else
                            {
                                constructorText = string.Format("Read{0}Array(memoryBuffer, memoryBufferOffset + {1}, {2})", baseType.GetTypeString().UppercaseFirst(), field.Offset, arraySize / elementSize);
                            }
                            fieldTypeString = baseType.GetTypeString() + "[]";
                        }
                    }
                }
                // Specialization for user types
                else if (userType != null && !extractingBaseClass)
                {
                    if (!(userType.UserType is EnumUserType))
                    {
                        string thisClassCodeType;

                        if (IsTypeUsingStaticCodeType(this))
                        {
                            thisClassCodeType = ClassCodeType;
                        }
                        else
                        {
                            thisClassCodeType = "thisClass.Value.GetCodeType()";
                            usedThisClass     = true;
                        }

                        // Check if type is embedded
                        if (!isEmbedded)
                        {
                            // If user type is not embedded, we do have pointer inside of our memory buffer that we can read directly
                            if (IsTypeUsingStaticCodeType(this))
                            {
                                constructorText = string.Format("ReadPointer<{0}>({4}, \"{1}\", memoryBuffer, memoryBufferOffset + {2}, {3})", fieldTypeString, fieldName, field.Offset, field.Type.Size, ClassCodeType);
                            }
                            else
                            {
                                constructorText = string.Format("ReadPointer<{0}>(thisClass, \"{1}\", memoryBuffer, memoryBufferOffset + {2}, {3})", fieldTypeString, fieldName, field.Offset, field.Type.Size);
                                usedThisClass   = true;
                            }

                            // Do downcasting if field has vtable
                            if (userType.UserType.Symbol.HasVTable() && userType.UserType.DerivedClasses.Count > 0)
                            {
                                constructorText += ".DowncastObject()";
                            }
                        }
                        else
                        {
                            // If user type is embedded, we can reuse memory buffer that we already have in this class
                            string fieldAddress  = string.Format("memoryBufferAddress + (ulong)(memoryBufferOffset + {0})", field.Offset);
                            string fieldCodeType = string.Format("{0}.GetClassFieldType(\"{1}\")", thisClassCodeType, fieldName);

                            if (IsTypeUsingStaticCodeType(userType.UserType))
                            {
                                fieldCodeType = string.Format("{0}.{1}", userType.UserType.FullClassName, ClassCodeType);
                            }
                            else if (IsTypeUsingStaticCodeType(this))
                            {
                                fieldCodeType = AddFieldCodeType(fieldName);
                            }

                            constructorText = string.Format("new {0}(memoryBuffer, memoryBufferOffset + {1}, memoryBufferAddress, {2}, {3}, \"{4}\")", fieldTypeString, field.Offset, fieldCodeType, fieldAddress, fieldName);
                        }
                    }
                    else
                    {
                        // TODO: This is enum. Read how much enum base type is big and just cast to enum type...
                    }
                }
                // Specialization for transformations
                else if (transformationType != null)
                {
                    if (!isEmbedded)
                    {
                        string thisClassCodeType;

                        if (IsTypeUsingStaticCodeType(this))
                        {
                            thisClassCodeType = ClassCodeType;
                        }
                        else
                        {
                            thisClassCodeType = "thisClass.Value.GetCodeType()";
                            usedThisClass     = true;
                        }

                        string fieldAddress  = string.Format("memoryBufferAddress + (ulong)(memoryBufferOffset + {0})", field.Offset);
                        string fieldVariable = string.Format("Variable.CreateNoCast({0}.GetClassFieldType(\"{1}\"), {2}, \"{1}\")", thisClassCodeType, fieldName, fieldAddress);

                        if (transformationType.Transformation.Transformation.HasPhysicalConstructor)
                        {
                            fieldVariable = string.Format("{0}, memoryBuffer, memoryBufferOffset + {1}, memoryBufferAddress", fieldVariable, field.Offset);
                        }

                        simpleFieldValue = fieldVariable;
                        constructorText  = string.Format("new {0}({1})", fieldTypeString, fieldVariable);
                    }
                }

                // If we found suitable physical representation, generate the field
                if (!string.IsNullOrEmpty(constructorText))
                {
                    return new UserTypeField()
                           {
                               ConstructorText      = constructorText,
                               FieldName            = "_" + fieldName,
                               FieldType            = fieldTypeString,
                               FieldTypeInfoComment = string.Format("// {0} {1};", field.Type.Name, fieldName),
                               PropertyName         = UserTypeField.GetPropertyName(field, this),
                               Static           = isStatic,
                               UseUserMember    = lazyCacheUserTypeFields,
                               CacheResult      = cacheUserTypeFields || (isStatic && cacheStaticUserTypeFields),
                               SimpleFieldValue = simpleFieldValue,
                           }
                }
                ;
            }

            return(base.ExtractFieldInternal(field, fieldType, factory, simpleFieldValue, gettingField, isStatic, generationFlags, extractingBaseClass));
        }
コード例 #5
0
 private void OnRequestBrowse(SymbolField sender) => ParameterSelector.ShowParameterSelector(_sym.ParameterDefinition.Parameter, sender);
コード例 #6
0
        /// <summary>
        /// Generates user type field based on the specified symbol field and all other fields that are prepared for this function.
        /// Do not use this function directly, unless you are calling it from overridden function.
        /// </summary>
        /// <param name="field">The symbol field.</param>
        /// <param name="fieldType">The field tree type.</param>
        /// <param name="factory">The user type factory.</param>
        /// <param name="simpleFieldValue">The code foe "simple field value" used when creating transformation.</param>
        /// <param name="gettingField">The code for getting field variable.</param>
        /// <param name="isStatic">if set to <c>true</c> generated field should be static.</param>
        /// <param name="generationFlags">The user type generation flags.</param>
        /// <param name="extractingBaseClass">if set to <c>true</c> user type field is being generated for getting base class.</param>
        protected override UserTypeField ExtractFieldInternal(SymbolField field, TypeTree fieldType, UserTypeFactory factory, string simpleFieldValue, string gettingField, bool isStatic, UserTypeGenerationFlags generationFlags, bool extractingBaseClass)
        {
            // Physical code generation make sense only for non-static fields
            if (!isStatic)
            {
                bool lazyCacheUserTypeFields = generationFlags.HasFlag(UserTypeGenerationFlags.LazyCacheUserTypeFields);
                bool cacheUserTypeFields = generationFlags.HasFlag(UserTypeGenerationFlags.CacheUserTypeFields);
                bool cacheStaticUserTypeFields = generationFlags.HasFlag(UserTypeGenerationFlags.CacheStaticUserTypeFields);
                string constructorText = "";
                string fieldName = field.Name;
                string fieldTypeString = fieldType.GetTypeString();
                BasicTypeTree baseType = fieldType as BasicTypeTree;
                ArrayTypeTree codeArrayType = fieldType as ArrayTypeTree;
                UserTypeTree userType = fieldType as UserTypeTree;
                TransformationTypeTree transformationType = fieldType as TransformationTypeTree;
                bool isEmbedded = field.Type.Tag != SymTagEnum.SymTagPointerType;

                // Specialization for basic types
                if (baseType != null)
                {
                    if (baseType.BasicType == "string")
                    {
                        int charSize = field.Type.ElementType.Size;

                        constructorText = string.Format("ReadString(GetCodeType().Module.Process, ReadPointer(memoryBuffer, memoryBufferOffset + {0}, {1}), {2})", field.Offset, field.Type.Size, charSize);
                    }
                    else if (baseType.BasicType != "NakedPointer")
                    {
                        if (field.LocationType == LocationType.BitField)
                            constructorText = string.Format("Read{0}(memoryBuffer, memoryBufferOffset + {1}, {2}, {3})", baseType.GetTypeString().UppercaseFirst(), field.Offset, field.Size, field.BitPosition);
                        else
                            constructorText = string.Format("Read{0}(memoryBuffer, memoryBufferOffset + {1})", baseType.GetTypeString().UppercaseFirst(), field.Offset);
                    }
                }
                // Specialization for arrays
                else if (codeArrayType != null)
                {
                    if (codeArrayType.ElementType is BasicTypeTree)
                    {
                        baseType = (BasicTypeTree)codeArrayType.ElementType;
                        if (baseType != null && baseType.BasicType != "string" && baseType.BasicType != "NakedPointer")
                        {
                            int arraySize = field.Type.Size;
                            int elementSize = field.Type.ElementType.Size;

                            if (baseType.BasicType == "char")
                                constructorText = string.Format("Read{0}Array(memoryBuffer, memoryBufferOffset + {1}, {2}, {3})", baseType.GetTypeString().UppercaseFirst(), field.Offset, arraySize / elementSize, elementSize);
                            else
                                constructorText = string.Format("Read{0}Array(memoryBuffer, memoryBufferOffset + {1}, {2})", baseType.GetTypeString().UppercaseFirst(), field.Offset, arraySize / elementSize);
                            fieldTypeString = baseType.GetTypeString() + "[]";
                        }
                    }
                }
                // Specialization for user types
                else if (userType != null && !extractingBaseClass)
                {
                    if (!(userType.UserType is EnumUserType))
                    {
                        string thisClassCodeType;

                        if (IsTypeUsingStaticCodeType(this))
                            thisClassCodeType = ClassCodeType;
                        else
                        {
                            thisClassCodeType = "thisClass.Value.GetCodeType()";
                            usedThisClass = true;
                        }

                        // Check if type is embedded
                        if (!isEmbedded)
                        {
                            // If user type is not embedded, we do have pointer inside of our memory buffer that we can read directly
                            if (IsTypeUsingStaticCodeType(this))
                                constructorText = string.Format("ReadPointer<{0}>({4}, \"{1}\", memoryBuffer, memoryBufferOffset + {2}, {3})", fieldTypeString, fieldName, field.Offset, field.Type.Size, ClassCodeType);
                            else
                            {
                                constructorText = string.Format("ReadPointer<{0}>(thisClass, \"{1}\", memoryBuffer, memoryBufferOffset + {2}, {3})", fieldTypeString, fieldName, field.Offset, field.Type.Size);
                                usedThisClass = true;
                            }

                            // Do downcasting if field has vtable
                            if (userType.UserType.Symbol.HasVTable() && userType.UserType.DerivedClasses.Count > 0)
                                constructorText += ".DowncastObject()";
                        }
                        else
                        {
                            // If user type is embedded, we can reuse memory buffer that we already have in this class
                            string fieldAddress = string.Format("memoryBufferAddress + (ulong)(memoryBufferOffset + {0})", field.Offset);
                            string fieldCodeType = string.Format("{0}.GetClassFieldType(\"{1}\")", thisClassCodeType, fieldName);

                            if (IsTypeUsingStaticCodeType(userType.UserType))
                            {
                                fieldCodeType = string.Format("{0}.{1}", userType.UserType.FullClassName, ClassCodeType);
                            }
                            else if (IsTypeUsingStaticCodeType(this))
                            {
                                fieldCodeType = AddFieldCodeType(fieldName);
                            }

                            constructorText = string.Format("new {0}(memoryBuffer, memoryBufferOffset + {1}, memoryBufferAddress, {2}, {3}, \"{4}\")", fieldTypeString, field.Offset, fieldCodeType, fieldAddress, fieldName);
                        }
                    }
                    else
                    {
                        // TODO: This is enum. Read how much enum base type is big and just cast to enum type...
                    }
                }
                // Specialization for transformations
                else if (transformationType != null)
                {
                    if (!isEmbedded)
                    {
                        string thisClassCodeType;

                        if (IsTypeUsingStaticCodeType(this))
                            thisClassCodeType = ClassCodeType;
                        else
                        {
                            thisClassCodeType = "thisClass.Value.GetCodeType()";
                            usedThisClass = true;
                        }

                        string fieldAddress = string.Format("memoryBufferAddress + (ulong)(memoryBufferOffset + {0})", field.Offset);
                        string fieldVariable = string.Format("Variable.CreateNoCast({0}.GetClassFieldType(\"{1}\"), {2}, \"{1}\")", thisClassCodeType, fieldName, fieldAddress);

                        if (transformationType.Transformation.Transformation.HasPhysicalConstructor)
                        {
                            fieldVariable = string.Format("{0}, memoryBuffer, memoryBufferOffset + {1}, memoryBufferAddress", fieldVariable, field.Offset);
                        }

                        simpleFieldValue = fieldVariable;
                        constructorText = string.Format("new {0}({1})", fieldTypeString, fieldVariable);
                    }
                }

                // If we found suitable physical representation, generate the field
                if (!string.IsNullOrEmpty(constructorText))
                    return new UserTypeField()
                    {
                        ConstructorText = constructorText,
                        FieldName = "_" + fieldName,
                        FieldType = fieldTypeString,
                        FieldTypeInfoComment = string.Format("// {0} {1};", field.Type.Name, fieldName),
                        PropertyName = UserTypeField.GetPropertyName(fieldName, this),
                        Static = isStatic,
                        UseUserMember = lazyCacheUserTypeFields,
                        CacheResult = cacheUserTypeFields || (isStatic && cacheStaticUserTypeFields),
                        SimpleFieldValue = simpleFieldValue,
                    };
            }

            return base.ExtractFieldInternal(field, fieldType, factory, simpleFieldValue, gettingField, isStatic, generationFlags, extractingBaseClass);
        }
コード例 #7
0
        /// <summary>
        /// Gets the type tree for the specified field.
        /// </summary>
        /// <param name="field">The field.</param>
        /// <param name="factory">The user type factory.</param>
        /// <param name="extractingBaseClass">if set to <c>true</c> user type field is being generated for getting base class.</param>
        /// <param name="bitLength">Number of bits used for this symbol.</param>
        protected override TypeTree GetFieldTypeTree(SymbolField field, UserTypeFactory factory, bool extractingBaseClass, int bitLength = 0)
        {
            // Do not match specializations when getting type for base class.
            if (extractingBaseClass || NumberOfTemplateArguments == 0)
                return GetSymbolTypeTree(field.Type, factory, bitLength);

            // Check field in all specializations
            var specializedFields = SpecializedTypes.Select(r => new Tuple<TemplateUserType, SymbolField>(r, r.Symbol.Fields.FirstOrDefault(q => q.Name == field.Name))).ToArray();

            if (specializedFields.Any(r => r.Item2 == null))
            {
                // TODO: Incorrect bucketization. Field does not exist in all specialization.
                return GetSymbolTypeTree(field.Type, factory, bitLength);
            }

            if (specializedFields.All(r => r.Item2.Type.Name == field.Type.Name))
            {
                // There is no specialization, all types across the specializations are the same.
                return GetSymbolTypeTree(field.Type, factory, bitLength);
            }

            // Try to get type tree
            TypeTree result = GetSymbolTypeTree(field.Type, factory, bitLength);

            if (result is BasicTypeTree)
            {
                // Basic type tree is not challenged against template arguments, so try to do that.
                UserType basicUserType;

                if (CreateFactory(factory).GetUserType(field.Type, out basicUserType))
                {
                    TypeTree tree = UserTypeTree.Create(basicUserType, factory);

                    if (tree != null)
                    {
                        return tree;
                    }
                }

                // Failed to match the type
                // TODO: Look for typedeclared. Class is using different types than in template specialization. We cannot support it right now.
                return new VariableTypeTree();
            }

            return result;
        }
コード例 #8
0
ファイル: TextDialog.cs プロジェクト: kanbang/Colt
 private void OnRequestBrowse(SymbolField sender)
 {
     ParameterSelector.ShowParameterSelector(_sym.ParameterDefinition.Parameter, sender);
 }
コード例 #9
0
        /// <summary>
        /// Try to generate fields based on the Hungarian notation used in class fields.
        /// </summary>
        /// <param name="fixName">Function that generated unique field names with desire to keep existing name.</param>
        protected virtual IEnumerable <HungarianArrayUserTypeMember> GenerateHungarianNotationFields(Func <string, string> fixName)
        {
            // TODO: Add comments to this function and expand XML documentation comment
            const string CounterPrefix = "m_c";
            const string PointerPrefix = "m_p";
            const string ArrayPrefix   = "m_rg";

            SymbolField[]                         fields          = Symbol.Fields;
            IEnumerable <SymbolField>             counterFields   = fields.Where(r => r.Name.StartsWith(CounterPrefix));
            Dictionary <SymbolField, SymbolField> userTypesArrays = new Dictionary <SymbolField, SymbolField>();

            foreach (SymbolField counterField in counterFields)
            {
                if (counterField.Type.BasicType != BasicType.UInt &&
                    counterField.Type.BasicType != BasicType.Int &&
                    counterField.Type.BasicType != BasicType.Long &&
                    counterField.Type.BasicType != BasicType.ULong)
                {
                    continue;
                }

                if (counterField.Type.Tag == CodeTypeTag.Enum)
                {
                    continue;
                }

                string counterNameSurfix = counterField.Name.Substring(CounterPrefix.Length);

                if (string.IsNullOrEmpty(counterNameSurfix))
                {
                    continue;
                }

                foreach (SymbolField pointerField in fields.Where(r => (r.Name.StartsWith(PointerPrefix) || r.Name.StartsWith(ArrayPrefix)) && r.Name.EndsWith(counterNameSurfix)))
                {
                    if ((counterField.IsStatic) != (pointerField.IsStatic))
                    {
                        continue;
                    }

                    if (pointerField.Type.Tag != CodeTypeTag.Pointer)
                    {
                        continue;
                    }

                    if (userTypesArrays.ContainsKey(pointerField))
                    {
                        if (userTypesArrays[pointerField].Name.Length > counterField.Name.Length)
                        {
                            continue;
                        }
                    }

                    userTypesArrays[pointerField] = counterField;
                }
            }

            foreach (var userTypeArray in userTypesArrays)
            {
                SymbolField  pointerField = userTypeArray.Key;
                SymbolField  counterField = userTypeArray.Value;
                TypeInstance fieldType    = Factory.GetSymbolTypeInstance(this, pointerField.Type);

                if (fieldType is ArrayTypeInstance)
                {
                    continue;
                }

                if (fieldType is PointerTypeInstance fieldTypeCodePointer)
                {
                    fieldType = fieldTypeCodePointer.ElementType;
                }

                yield return(new HungarianArrayUserTypeMember()
                {
                    AccessLevel = AccessLevel.Public,
                    Name = fixName(CodeNaming.FixUserNaming(pointerField.Name + "Array")),
                    Type = new ArrayTypeInstance(fieldType),
                    UserType = this,
                    PointerFieldName = pointerField.Name,
                    CounterFieldName = counterField.Name,
                });
            }
        }