The Labs \ Source Viewer \ SSCLI \ System.Security.Policy \ IUnionSemanticCodeGroup

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. // CodeGroup.cs
  16. //
  17. // Representation for code groups used for the policy mechanism
  18. //
  19. namespace System.Security.Policy
  20. {
  21.    
  22.     using System;
  23.     using System.Security.Util;
  24.     using System.Security;
  25.     using System.Collections;
  26.     using System.Globalization;
  27.    
  28.     internal interface IUnionSemanticCodeGroup
  29.     {
  30.         PolicyStatement InternalResolve(Evidence evidence);
  31.     }
  32.    
  33.     [Serializable()]
  34.     [System.Runtime.InteropServices.ComVisible(true)]
  35.     public abstract class CodeGroup
  36.     {
  37.         private IMembershipCondition m_membershipCondition;
  38.         private IList m_children;
  39.         private PolicyStatement m_policy;
  40.         private SecurityElement m_element;
  41.         private PolicyLevel m_parentLevel;
  42.         private string m_name;
  43.         private string m_description;
  44.        
  45.         internal CodeGroup()
  46.         {
  47.             m_membershipCondition = null;
  48.             m_children = null;
  49.             m_policy = null;
  50.             m_element = null;
  51.             m_parentLevel = null;
  52.         }
  53.        
  54.         internal CodeGroup(IMembershipCondition membershipCondition, PermissionSet permSet)
  55.         {
  56.             BCLDebug.Assert(membershipCondition != null, "membershipCondition != null");
  57.             BCLDebug.Assert(permSet != null, "permSet != null");
  58.            
  59.             m_membershipCondition = membershipCondition;
  60.             m_policy = new PolicyStatement();
  61.             m_policy.SetPermissionSetNoCopy(permSet);
  62.             m_children = ArrayList.Synchronized(new ArrayList());
  63.             m_element = null;
  64.             m_parentLevel = null;
  65.         }
  66.        
  67.         protected CodeGroup(IMembershipCondition membershipCondition, PolicyStatement policy)
  68.         {
  69.             if (membershipCondition == null)
  70.                 throw new ArgumentNullException("membershipCondition");
  71.            
  72.             if (policy == null)
  73.                 m_policy = null;
  74.             else
  75.                 m_policy = policy.Copy();
  76.            
  77.             m_membershipCondition = membershipCondition.Copy();
  78.             m_children = ArrayList.Synchronized(new ArrayList());
  79.             m_element = null;
  80.             m_parentLevel = null;
  81.         }
  82.        
  83.         public void AddChild(CodeGroup group)
  84.         {
  85.             if (group == null)
  86.                 throw new ArgumentNullException("group");
  87.            
  88.             if (m_children == null)
  89.                 ParseChildren();
  90.            
  91.             lock (this) {
  92.                 m_children.Add(group.Copy());
  93.             }
  94.         }
  95.        
  96.         internal void AddChildInternal(CodeGroup group)
  97.         {
  98.             if (group == null)
  99.                 throw new ArgumentNullException("group");
  100.            
  101.             if (m_children == null)
  102.                 ParseChildren();
  103.            
  104.             lock (this) {
  105.                 m_children.Add(group);
  106.             }
  107.         }
  108.        
  109.         public void RemoveChild(CodeGroup group)
  110.         {
  111.             if (group == null)
  112.                 return;
  113.            
  114.             if (m_children == null)
  115.                 ParseChildren();
  116.            
  117.             lock (this) {
  118.                 int index = m_children.IndexOf(group);
  119.                
  120.                 if (index != -1) {
  121.                     m_children.RemoveAt(index);
  122.                 }
  123.             }
  124.         }
  125.        
  126.         public IList Children {
  127.             get {
  128.                 if (m_children == null)
  129.                     ParseChildren();
  130.                
  131.                 lock (this) {
  132.                     IList newList = new ArrayList(m_children.Count);
  133.                    
  134.                     IEnumerator enumerator = m_children.GetEnumerator();
  135.                    
  136.                     while (enumerator.MoveNext()) {
  137.                         newList.Add(((CodeGroup)enumerator.Current).Copy());
  138.                     }
  139.                    
  140.                     return newList;
  141.                 }
  142.             }
  143.            
  144.             set {
  145.                 if (value == null)
  146.                     throw new ArgumentNullException("Children");
  147.                
  148.                 ArrayList children = ArrayList.Synchronized(new ArrayList(value.Count));
  149.                
  150.                 IEnumerator enumerator = value.GetEnumerator();
  151.                
  152.                 while (enumerator.MoveNext()) {
  153.                     CodeGroup group = enumerator.Current as CodeGroup;
  154.                    
  155.                     if (group == null)
  156.                         throw new ArgumentException(Environment.GetResourceString("Argument_CodeGroupChildrenMustBeCodeGroups"));
  157.                    
  158.                     children.Add(group.Copy());
  159.                 }
  160.                
  161.                 m_children = children;
  162.             }
  163.         }
  164.        
  165.         internal IList GetChildrenInternal()
  166.         {
  167.             if (m_children == null)
  168.                 ParseChildren();
  169.            
  170.             return m_children;
  171.         }
  172.        
  173.         public IMembershipCondition MembershipCondition {
  174.             get {
  175.                 if (m_membershipCondition == null && m_element != null)
  176.                     ParseMembershipCondition();
  177.                
  178.                 return m_membershipCondition.Copy();
  179.             }
  180.            
  181.             set {
  182.                 if (value == null)
  183.                     throw new ArgumentNullException("MembershipCondition");
  184.                
  185.                 m_membershipCondition = value.Copy();
  186.             }
  187.         }
  188.        
  189.         public PolicyStatement PolicyStatement {
  190.             get {
  191.                 if (m_policy == null && m_element != null)
  192.                     ParsePolicy();
  193.                
  194.                 if (m_policy != null)
  195.                     return m_policy.Copy();
  196.                 else
  197.                     return null;
  198.             }
  199.            
  200.             set {
  201.                 if (value != null)
  202.                     m_policy = value.Copy();
  203.                 else
  204.                     m_policy = null;
  205.             }
  206.         }
  207.        
  208.         public string Name {
  209.             get { return m_name; }
  210.            
  211.             set { m_name = value; }
  212.         }
  213.        
  214.         public string Description {
  215.             get { return m_description; }
  216.            
  217.             set { m_description = value; }
  218.         }
  219.        
  220.         public abstract PolicyStatement Resolve(Evidence evidence);
  221.        
  222.         public abstract CodeGroup ResolveMatchingCodeGroups(Evidence evidence);
  223.        
  224.         public abstract CodeGroup Copy();
  225.        
  226.         public virtual string PermissionSetName {
  227.             get {
  228.                 if (m_policy == null && m_element != null)
  229.                     ParsePolicy();
  230.                
  231.                 if (m_policy == null)
  232.                     return null;
  233.                
  234.                 NamedPermissionSet permSet = m_policy.GetPermissionSetNoCopy() as NamedPermissionSet;
  235.                
  236.                 if (permSet != null) {
  237.                     return permSet.Name;
  238.                 }
  239.                 else {
  240.                     return null;
  241.                 }
  242.             }
  243.         }
  244.        
  245.         public virtual string AttributeString {
  246.             get {
  247.                 if (m_policy == null && m_element != null)
  248.                     ParsePolicy();
  249.                
  250.                 if (m_policy != null)
  251.                     return m_policy.AttributeString;
  252.                 else
  253.                     return null;
  254.             }
  255.         }
  256.        
  257.         public abstract string MergeLogic {
  258.             get;
  259.         }
  260.        
  261.         public SecurityElement ToXml()
  262.         {
  263.             return ToXml(null);
  264.         }
  265.        
  266.         public void FromXml(SecurityElement e)
  267.         {
  268.             FromXml(e, null);
  269.         }
  270.        
  271.         public SecurityElement ToXml(PolicyLevel level)
  272.         {
  273.             return ToXml(level, GetTypeName());
  274.         }
  275.        
  276.         internal virtual string GetTypeName()
  277.         {
  278.             return this.GetType().FullName;
  279.         }
  280.        
  281.         internal SecurityElement ToXml(PolicyLevel level, string policyClassName)
  282.         {
  283.             if (m_membershipCondition == null && m_element != null)
  284.                 ParseMembershipCondition();
  285.            
  286.             if (m_children == null)
  287.                 ParseChildren();
  288.            
  289.             if (m_policy == null && m_element != null)
  290.                 ParsePolicy();
  291.            
  292.             SecurityElement e = new SecurityElement("CodeGroup");
  293.             System.Security.Util.XMLUtil.AddClassAttribute(e, this.GetType(), policyClassName);
  294.             // If you hit this assert then most likely you are trying to change the name of this class.
  295.             // This is ok as long as you change the hard coded string above and change the assert below.
  296.             BCLDebug.Assert(this.GetType().FullName.Equals(policyClassName), "Incorrect class name passed in! Was: " + policyClassName + " Should be " + this.GetType().FullName);
  297.            
  298.             e.AddAttribute("version", "1");
  299.            
  300.             e.AddChild(m_membershipCondition.ToXml(level));
  301.            
  302.             // Grab the inerts of the policy statement's xml and just stick it
  303.             // into the code group xml directly. We do this to hide the policy statement from
  304.             // users in the config file.
  305.            
  306.             if (m_policy != null) {
  307.                 PermissionSet permSet = m_policy.GetPermissionSetNoCopy();
  308.                 NamedPermissionSet namedPermSet = permSet as NamedPermissionSet;
  309.                
  310.                 if (namedPermSet != null && level != null && level.GetNamedPermissionSetInternal(namedPermSet.Name) != null) {
  311.                     e.AddAttribute("PermissionSetName", namedPermSet.Name);
  312.                 }
  313.                 else {
  314.                     if (!permSet.IsEmpty())
  315.                         e.AddChild(permSet.ToXml());
  316.                 }
  317.                
  318.                 if (m_policy.Attributes != PolicyStatementAttribute.Nothing)
  319.                     e.AddAttribute("Attributes", XMLUtil.BitFieldEnumToString(typeof(PolicyStatementAttribute), m_policy.Attributes));
  320.             }
  321.            
  322.             if (m_children.Count > 0) {
  323.                 lock (this) {
  324.                     IEnumerator enumerator = m_children.GetEnumerator();
  325.                    
  326.                     while (enumerator.MoveNext()) {
  327.                         e.AddChild(((CodeGroup)enumerator.Current).ToXml(level));
  328.                     }
  329.                 }
  330.             }
  331.            
  332.             if (m_name != null) {
  333.                 e.AddAttribute("Name", SecurityElement.Escape(m_name));
  334.             }
  335.            
  336.             if (m_description != null) {
  337.                 e.AddAttribute("Description", SecurityElement.Escape(m_description));
  338.             }
  339.            
  340.             CreateXml(e, level);
  341.            
  342.             return e;
  343.         }
  344.        
  345.         protected virtual void CreateXml(SecurityElement element, PolicyLevel level)
  346.         {
  347.         }
  348.        
  349.         public void FromXml(SecurityElement e, PolicyLevel level)
  350.         {
  351.             if (e == null)
  352.                 throw new ArgumentNullException("e");
  353.            
  354.             lock (this) {
  355.                 m_element = e;
  356.                 m_parentLevel = level;
  357.                 m_children = null;
  358.                 m_membershipCondition = null;
  359.                 m_policy = null;
  360.                
  361.                 m_name = e.Attribute("Name");
  362.                 m_description = e.Attribute("Description");
  363.                
  364.                 ParseXml(e, level);
  365.             }
  366.         }
  367.        
  368.         protected virtual void ParseXml(SecurityElement e, PolicyLevel level)
  369.         {
  370.         }
  371.        
  372.         private bool ParseMembershipCondition(bool safeLoad)
  373.         {
  374.             lock (this) {
  375.                 IMembershipCondition membershipCondition = null;
  376.                 SecurityElement elMembershipCondition = m_element.SearchForChildByTag("IMembershipCondition");
  377.                 if (elMembershipCondition != null) {
  378.                     try {
  379.                         membershipCondition = System.Security.Util.XMLUtil.CreateMembershipCondition(elMembershipCondition);
  380.                        
  381.                         if (membershipCondition == null)
  382.                             return false;
  383.                     }
  384.                     catch (Exception ex) {
  385.                         throw new ArgumentException(Environment.GetResourceString("Argument_MembershipConditionElement"), ex);
  386.                     }
  387.                     // catch
  388.                     // {
  389.                     // throw new ArgumentException( Environment.GetResourceString( "Argument_MembershipConditionElement" ) );
  390.                     // }
  391.                     membershipCondition.FromXml(elMembershipCondition, m_parentLevel);
  392.                 }
  393.                 else {
  394.                     throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_InvalidXMLElement"), "IMembershipCondition", this.GetType().FullName));
  395.                 }
  396.                
  397.                 m_membershipCondition = membershipCondition;
  398.                 return true;
  399.             }
  400.         }
  401.        
  402.         private void ParseMembershipCondition()
  403.         {
  404.             ParseMembershipCondition(false);
  405.         }
  406.        
  407.         internal void ParseChildren()
  408.         {
  409.             lock (this) {
  410.                 ArrayList childrenList = ArrayList.Synchronized(new ArrayList());
  411.                
  412.                 if (m_element != null && m_element.InternalChildren != null) {
  413.                     // We set the elements childrenList to a list that contains no code groups that are in
  414.                     // assemblies that have not yet been loaded. This guarantees that if
  415.                     // we recurse while loading the child code groups or their membership conditions
  416.                     // that we won't get back to this point to create an infinite recursion.
  417.                    
  418.                     m_element.Children = (ArrayList)m_element.InternalChildren.Clone();
  419.                    
  420.                     // We need to keep track of which children are not parsed and created in our
  421.                     // first pass through the list of children, including what position they were
  422.                     // at originally so that we can add them back in as we do parse them.
  423.                    
  424.                     ArrayList unparsedChildren = ArrayList.Synchronized(new ArrayList());
  425.                    
  426.                     Evidence evidence = new Evidence();
  427.                    
  428.                     int childCount = m_element.InternalChildren.Count;
  429.                     int i = 0;
  430.                     while (i < childCount) {
  431.                         SecurityElement elGroup = (SecurityElement)m_element.Children[i];
  432.                        
  433.                         if (elGroup.Tag.Equals("CodeGroup")) {
  434.                             // Using safe load here to guarantee that we don't load any assemblies that aren't
  435.                             // already loaded. If we find a code group or membership condition that is defined
  436.                             // in an assembly that is not yet loaded, we will remove the corresponding element
  437.                             // from the list of child elements as to avoid the infinite recursion, and then
  438.                             // add them back in later.
  439.                            
  440.                             CodeGroup group = System.Security.Util.XMLUtil.CreateCodeGroup(elGroup);
  441.                            
  442.                             if (group != null) {
  443.                                 group.FromXml(elGroup, m_parentLevel);
  444.                                
  445.                                 // We want to touch the membership condition to make sure it is loaded
  446.                                 // before we put the code group in a place where Resolve will touch it.
  447.                                 // This is critical in negotiating our recursive resolve scenario.
  448.                                
  449.                                 if (ParseMembershipCondition(true)) {
  450.                                     // In addition, we need to touch several methods to make sure they are jitted previous
  451.                                     // to a Resolve happening with this code gropu in the hierarchy. We can run into
  452.                                     // recursive cases where if you have a method that touchs an assembly that does
  453.                                     // a resolve at load time (permission request, execution checking) that you recurse around
  454.                                     // and end up trying to jit the same method again.
  455.                                    
  456.                                     group.Resolve(evidence);
  457.                                     group.MembershipCondition.Check(evidence);
  458.                                    
  459.                                     // Now it should be ok to add the group to the hierarchy.
  460.                                    
  461.                                     childrenList.Add(group);
  462.                                    
  463.                                     // Increment the count since we are done with this child
  464.                                    
  465.                                     ++i;
  466.                                 }
  467.                                 else {
  468.                                     // Assembly that holds the membership condition is not loaded, remove
  469.                                     // the child from the list.
  470.                                    
  471.                                     m_element.InternalChildren.RemoveAt(i);
  472.                                    
  473.                                     // Note: we do not increment the counter since the value at 'i' should
  474.                                     // now be what was at 'i+1' previous to the RemoveAt( i ) above. However,
  475.                                     // we do need to update the count of children in the list
  476.                                    
  477.                                     childCount = m_element.InternalChildren.Count;
  478.                                    
  479.                                     // Add this child to the unparsed child list.
  480.                                    
  481.                                     unparsedChildren.Add(new CodeGroupPositionMarker(i, childrenList.Count, elGroup));
  482.                                 }
  483.                             }
  484.                             else {
  485.                                 // Assembly that holds the code group is not loaded, remove
  486.                                 // the child from the list.
  487.                                
  488.                                 m_element.InternalChildren.RemoveAt(i);
  489.                                
  490.                                 // Note: we do not increment the counter since the value at 'i' should
  491.                                 // now be what was at 'i+1' previous to the RemoveAt( i ) above. However,
  492.                                 // we do need to update the count of children in the list
  493.                                
  494.                                 childCount = m_element.InternalChildren.Count;
  495.                                
  496.                                 // Add this child to the unparsed child list.
  497.                                
  498.                                 unparsedChildren.Add(new CodeGroupPositionMarker(i, childrenList.Count, elGroup));
  499.                             }
  500.                         }
  501.                         else {
  502.                             // The current tag is not an <CodeGroup> tag, so we just skip it.
  503.                            
  504.                             ++i;
  505.                         }
  506.                     }
  507.                    
  508.                     // Now we have parsed all the children that only use classes in already loaded
  509.                     // assemblies. Now go through the process of loading the needed classes (and
  510.                     // therefore assemblies) and building the objects in the order that they
  511.                     // appear in the list of children (which is the same as they now appear in the
  512.                     // list of unparsed children since we always added to the back of the list).
  513.                     // As each is parsed, add that child back into the list of children since they
  514.                     // can now be parsed without loading any additional assemblies.
  515.                    
  516.                     IEnumerator enumerator = unparsedChildren.GetEnumerator();
  517.                    
  518.                     while (enumerator.MoveNext()) {
  519.                         CodeGroupPositionMarker marker = (CodeGroupPositionMarker)enumerator.Current;
  520.                        
  521.                         CodeGroup group = System.Security.Util.XMLUtil.CreateCodeGroup(marker.element);
  522.                        
  523.                         if (group != null) {
  524.                             group.FromXml(marker.element, m_parentLevel);
  525.                            
  526.                             // We want to touch the membership condition to make sure it is loaded
  527.                             // before we put the code group in a place where Resolve will touch it.
  528.                             // This is critical in negotiating our recursive resolve scenario.
  529.                            
  530.                             group.Resolve(evidence);
  531.                             group.MembershipCondition.Check(evidence);
  532.                            
  533.                             // Now it should be ok to add the group to the hierarchy.
  534.                            
  535.                             childrenList.Insert(marker.groupIndex, group);
  536.                            
  537.                             // Add the element back into the child list in the proper spot.
  538.                            
  539.                             m_element.InternalChildren.Insert(marker.elementIndex, marker.element);
  540.                         }
  541.                         else {
  542.                             throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_FailedCodeGroup"), marker.element.Attribute("class")));
  543.                         }
  544.                     }
  545.                    
  546.                 }
  547.                 m_children = childrenList;
  548.             }
  549.            
  550.         }
  551.        
  552.         private void ParsePolicy()
  553.         {
  554.             // There is a potential deadlock situation here
  555.             // since the PolicyStatement.FromXml method calls
  556.             // into PolicyLevel and we are holding this CodeGroup's lock.
  557.             // We solve this by releasing the lock for the duration of
  558.             // the FromXml call, but this leads us into some race conditions
  559.             // with other threads trying to alter the state of this object.
  560.             // The trickiest of these is the case from FromXml gets called on
  561.             // this object, in which case we will loop and try the decode again.
  562.            
  563.             while (true) {
  564.                 PolicyStatement policy = new PolicyStatement();
  565.                 bool needToParse = false;
  566.                
  567.                 SecurityElement elPolicy = new SecurityElement("PolicyStatement");
  568.                 elPolicy.AddAttribute("version", "1");
  569.                
  570.                 SecurityElement localRef = m_element;
  571.                
  572.                 lock (this) {
  573.                    
  574.                     // We create an xml representation of a policy statement from the
  575.                     // xml for a code group. We do this to hide the policy statement from
  576.                     // users in the config file.
  577.                    
  578.                     if (m_element != null) {
  579.                         string permSetName = m_element.Attribute("PermissionSetName");
  580.                        
  581.                         if (permSetName != null) {
  582.                             elPolicy.AddAttribute("PermissionSetName", permSetName);
  583.                             needToParse = true;
  584.                         }
  585.                         else {
  586.                             SecurityElement elPermSet = m_element.SearchForChildByTag("PermissionSet");
  587.                            
  588.                             if (elPermSet != null) {
  589.                                 elPolicy.AddChild(elPermSet);
  590.                                 needToParse = true;
  591.                             }
  592.                             else {
  593.                                 elPolicy.AddChild(new PermissionSet(false).ToXml());
  594.                                 needToParse = true;
  595.                             }
  596.                         }
  597.                        
  598.                         string attributes = m_element.Attribute("Attributes");
  599.                        
  600.                         if (attributes != null) {
  601.                             elPolicy.AddAttribute("Attributes", attributes);
  602.                             needToParse = true;
  603.                         }
  604.                     }
  605.                 }
  606.                
  607.                 if (needToParse)
  608.                     policy.FromXml(elPolicy, m_parentLevel);
  609.                 else
  610.                     policy.PermissionSet = null;
  611.                
  612.                 lock (this) {
  613.                     if (localRef == m_element && m_policy == null) {
  614.                         m_policy = policy;
  615.                         break;
  616.                     }
  617.                     else if (m_policy != null) {
  618.                         break;
  619.                     }
  620.                 }
  621.             }
  622.            
  623.             if (m_policy != null && m_children != null && m_membershipCondition != null) {
  624.                 //m_element = null;
  625.                 //m_parentLevel = null;
  626.             }
  627.            
  628.         }
  629.        
  630.         public override bool Equals(object o)
  631.         {
  632.             CodeGroup that = (o as CodeGroup);
  633.            
  634.             if (that != null && this.GetType().Equals(that.GetType())) {
  635.                 if (Equals(this.m_name, that.m_name) && Equals(this.m_description, that.m_description)) {
  636.                     if (this.m_membershipCondition == null && this.m_element != null)
  637.                         this.ParseMembershipCondition();
  638.                     if (that.m_membershipCondition == null && that.m_element != null)
  639.                         that.ParseMembershipCondition();
  640.                    
  641.                     if (Equals(this.m_membershipCondition, that.m_membershipCondition)) {
  642.                         return true;
  643.                     }
  644.                 }
  645.             }
  646.             return false;
  647.         }
  648.        
  649.         public bool Equals(CodeGroup cg, bool compareChildren)
  650.         {
  651.             if (!this.Equals(cg))
  652.                 return false;
  653.            
  654.             if (compareChildren) {
  655.                 if (this.m_children == null)
  656.                     this.ParseChildren();
  657.                 if (cg.m_children == null)
  658.                     cg.ParseChildren();
  659.                
  660.                 ArrayList list1 = new ArrayList(this.m_children);
  661.                 ArrayList list2 = new ArrayList(cg.m_children);
  662.                
  663.                 if (list1.Count != list2.Count)
  664.                     return false;
  665.                
  666.                 for (int i = 0; i < list1.Count; i++) {
  667.                     if (!((CodeGroup)list1[i]).Equals((CodeGroup)list2[i], true)) {
  668.                         return false;
  669.                     }
  670.                 }
  671.             }
  672.            
  673.             return true;
  674.         }
  675.        
  676.         public override int GetHashCode()
  677.         {
  678.             if (m_membershipCondition == null && m_element != null)
  679.                 ParseMembershipCondition();
  680.            
  681.             if (m_name != null || m_membershipCondition != null) {
  682.                 return (m_name == null ? 0 : m_name.GetHashCode()) + (m_membershipCondition == null ? 0 : m_membershipCondition.GetHashCode());
  683.             }
  684.             else {
  685.                 return GetType().GetHashCode();
  686.             }
  687.         }
  688.     }
  689.    
  690.     internal class CodeGroupPositionMarker
  691.     {
  692.         internal int elementIndex;
  693.         internal int groupIndex;
  694.         internal SecurityElement element;
  695.        
  696.         internal CodeGroupPositionMarker(int elementIndex, int groupIndex, SecurityElement element)
  697.         {
  698.             this.elementIndex = elementIndex;
  699.             this.groupIndex = groupIndex;
  700.             this.element = element;
  701.         }
  702.     }
  703. }

Developer Fusion