/// <summary>
 /// AppendStructParameters - Helper routine to append parameters to a param list.
 /// </summary>
 internal static int AppendStructParameters(
     DelimitedList parameterList,
     PaddedStructData paddedFields,
     int initialPosition,
     bool unmanagedStruct)
 {
     return(AppendStructParameters(
                parameterList,
                paddedFields,
                initialPosition,
                unmanagedStruct,
                false
                ));
 }
        internal static int AppendStructParameters(
            DelimitedList parameterList,
            PaddedStructData paddedFields,
            int initialPosition,
            bool unmanagedStruct,
            bool kernelAccessibleStruct
            )
        {
            int padSuffix = 0;

            Helpers.CodeGenHelpers.AlignedFieldOffsetHelper alignedFieldHelper = new Helpers.CodeGenHelpers.AlignedFieldOffsetHelper(4, 4);

            foreach (AlignmentEntry alignmentEntry in paddedFields.AlignmentEntries)
            {
                McgField field    = alignmentEntry.Field;
                int      position = initialPosition + alignmentEntry.Offset;

                alignedFieldHelper.MoveToNextEntry(position, alignmentEntry.Size);
                int alignedFieldOffset = alignedFieldHelper.AlignedFieldOffset;

                if (unmanagedStruct)
                {
                    // Insert enough padding to ensure the field is properly aligned
                    foreach (string alignmentField in alignedFieldHelper.AlignmentFields)
                    {
                        parameterList.Append(alignmentField);
                    }
                }

                // This primary if else else block switches between the tree types of entries in the
                // paddedFields alignment list: padding, animation and normal field entries.
                // The offset of each field is stored in "position", which is the padding offset of the
                // entry + the initial position.
                if (field == null)
                {
                    Debug.Assert(alignmentEntry.IsPad);

                    string padIdentifier = "padQuadAlignment" + padSuffix;

                    if (unmanagedStruct)
                    {
                        parameterList.Append("UINT32 " + padIdentifier + ";");
                    }
                    else
                    {
                        parameterList.Append("[FieldOffset(" + alignedFieldOffset + ")] private UInt32 " + padIdentifier);
                    }
                    ++padSuffix;
                }
                else if (alignmentEntry.IsAnimation)
                {
                    if (unmanagedStruct)
                    {
                        parameterList.Append("HMIL_RESOURCE " + "h" + field.PropertyName + "Animations;");
                    }
                    else
                    {
                        parameterList.Append("[FieldOffset(" + alignedFieldOffset + ")] internal DUCE.ResourceHandle h" + field.PropertyName + "Animations");
                    }
                }
                else
                {
                    // This case is a boring, non animate field.

                    bool        constructedParam = false;
                    McgType     type             = field.Type;
                    McgResource resourceType     = type as McgResource;

                    // If it's an McgResource, we have to handle reference types and collections
                    if (resourceType != null)
                    {
                        // Currently, collections are accounted for by storing just their size inline
                        if (resourceType.IsCollection)
                        {
                            if (unmanagedStruct)
                            {
                                parameterList.Append("UINT32 " + field.Name + "Size;");
                            }
                            else
                            {
                                parameterList.Append("[FieldOffset(" + alignedFieldOffset + ")] internal UInt32 " + field.Name + "Size");
                            }
                            constructedParam = true;
                        }
                        // If it's not a collection, is it a reference type?  If so, it's passed by handle.
                        else if (!resourceType.IsValueType)
                        {
                            if (unmanagedStruct)
                            {
                                parameterList.Append("HMIL_RESOURCE " + "h" + field.Name + ";");
                            }
                            else
                            {
                                parameterList.Append("[FieldOffset(" + alignedFieldOffset + ")] internal DUCE.ResourceHandle h" + field.Name);
                            }

                            constructedParam = true;
                        }
                    }

                    // If we haven't yet handled this parameter, we're left with a primitive type,
                    // like a struct or an enum.  At this point, the value will be stored inline.
                    // The only real question left is whether the unmanaged struct matches the managed struct.
                    // If so, the struct is simply stored.  If not, then .NeedsConvert is true, and
                    // the record is of the unmanaged type, even on the managed side of things.
                    if (!constructedParam)
                    {
                        if (type.NeedsConvert)
                        {
                            if (unmanagedStruct)
                            {
                                parameterList.Append(type.BaseUnmanagedType + " " + field.Name + ";");
                            }
                            else
                            {
                                parameterList.Append("[FieldOffset(" + alignedFieldOffset + ")] internal " + type.MarshalUnmanagedType + " " + field.Name);
                            }
                        }
                        else
                        {
                            if (unmanagedStruct)
                            {
                                if (kernelAccessibleStruct)
                                {
                                    McgEnum enumType = type as McgEnum;

                                    if (enumType != null)
                                    {
                                        parameterList.Append(enumType.KernelAccessibleType + " " + field.Name + ";");
                                        constructedParam = true;
                                    }
                                }

                                if (!constructedParam)
                                {
                                    parameterList.Append(type.BaseUnmanagedType + " " + field.Name + ";");
                                }
                            }
                            else
                            {
                                parameterList.Append("[FieldOffset(" + alignedFieldOffset + ")] internal " + type.ManagedName + " " + field.Name);
                            }
                        }
                    }
                }
            }

            if (unmanagedStruct)
            {
                // Insert enough padding to ensure the struct's size falls on a packing boundary
                foreach (string packingField in alignedFieldHelper.NativePackingFields)
                {
                    parameterList.Append(packingField);
                }
            }
            else
            {
                // Insert enough padding to ensure the struct's size falls on a packing boundary
                foreach (string packingField in alignedFieldHelper.ManagedPackingFields)
                {
                    parameterList.Append(packingField);
                }
            }

            return(initialPosition + paddedFields.PaddedSize);
        }