1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4 
5 using System.Configuration.Internal;
6 using System.Diagnostics;
7 
8 namespace System.Configuration
9 {
10     public sealed class SectionInformation
11     {
12         // Flags
13         private const int FlagAttached = 0x00000001;
14         private const int FlagDeclared = 0x00000002;
15         private const int FlagDeclarationRequired = 0x00000004;
16         private const int FlagAllowLocation = 0x00000008;
17         private const int FlagRestartOnExternalChanges = 0x00000010;
18         private const int FlagRequirePermission = 0x00000020;
19         private const int FlagLocationLocked = 0x00000040;
20         private const int FlagChildrenLocked = 0x00000080;
21         private const int FlagInheritInChildApps = 0x00000100;
22         private const int FlagIsParentSection = 0x00000200;
23         private const int FlagRemoved = 0x00000400;
24         private const int FlagProtectionProviderDetermined = 0x00000800;
25         private const int FlagForceSave = 0x00001000;
26         private const int FlagIsUndeclared = 0x00002000;
27         private const int FlagChildrenLockWithoutFileInput = 0x00004000;
28 
29         private const int FlagAllowExeDefinitionModified = 0x00010000;
30         private const int FlagAllowDefinitionModified = 0x00020000;
31         private const int FlagConfigSourceModified = 0x00040000;
32         private const int FlagProtectionProviderModified = 0x00080000;
33         private const int FlagOverrideModeDefaultModified = 0x00100000;
34         private const int FlagOverrideModeModified = 0x00200000; // Used only for modified tracking
35 
36         private readonly ConfigurationSection _configurationSection;
37         private ConfigurationAllowDefinition _allowDefinition;
38         private ConfigurationAllowExeDefinition _allowExeDefinition;
39         private MgmtConfigurationRecord _configRecord;
40         private string _configSource;
41         private SafeBitVector32 _flags;
42         private SimpleBitVector32 _modifiedFlags;
43         private OverrideModeSetting _overrideMode; // The override mode at the current config path
44         private OverrideModeSetting _overrideModeDefault; // The default mode for the section in _configurationSection
45         private ProtectedConfigurationProvider _protectionProvider;
46         private string _typeName;
47 
SectionInformation(ConfigurationSection associatedConfigurationSection)48         internal SectionInformation(ConfigurationSection associatedConfigurationSection)
49         {
50             ConfigKey = string.Empty;
51             Name = string.Empty;
52 
53             _configurationSection = associatedConfigurationSection;
54             _allowDefinition = ConfigurationAllowDefinition.Everywhere;
55             _allowExeDefinition = ConfigurationAllowExeDefinition.MachineToApplication;
56             _overrideModeDefault = OverrideModeSetting.s_sectionDefault;
57             _overrideMode = OverrideModeSetting.s_locationDefault;
58 
59             _flags[FlagAllowLocation] = true;
60             _flags[FlagRestartOnExternalChanges] = true;
61             _flags[FlagRequirePermission] = true;
62             _flags[FlagInheritInChildApps] = true;
63             _flags[FlagForceSave] = false;
64 
65             _modifiedFlags = new SimpleBitVector32();
66         }
67 
68         private bool IsRuntime => _flags[FlagAttached] &&
69             (_configRecord == null);
70 
71         internal bool Attached => _flags[FlagAttached];
72 
73         internal string ConfigKey { get; private set; }
74 
75         internal bool Removed
76         {
77             get { return _flags[FlagRemoved]; }
78             set { _flags[FlagRemoved] = value; }
79         }
80 
81         public string SectionName => ConfigKey;
82 
83         public string Name { get; private set; }
84 
85         public ConfigurationAllowDefinition AllowDefinition
86         {
87             get { return _allowDefinition; }
88             set
89             {
90                 VerifyIsEditable();
91                 VerifyIsEditableFactory();
92 
93                 // allow AllowDefinition to be different from current type,
94                 // so long as it doesn't conflict with a type already defined
95                 FactoryRecord factoryRecord = FindParentFactoryRecord(false);
96                 if ((factoryRecord != null) && (factoryRecord.AllowDefinition != value))
97                     throw new ConfigurationErrorsException(string.Format(SR.Config_tag_name_already_defined, ConfigKey));
98 
99                 _allowDefinition = value;
100                 _modifiedFlags[FlagAllowDefinitionModified] = true;
101             }
102         }
103 
104         internal bool AllowDefinitionModified => _modifiedFlags[FlagAllowDefinitionModified];
105 
106         public ConfigurationAllowExeDefinition AllowExeDefinition
107         {
108             get { return _allowExeDefinition; }
109             set
110             {
111                 VerifyIsEditable();
112                 VerifyIsEditableFactory();
113 
114                 // allow AllowDefinition to be different from current type,
115                 // so long as it doesn't conflict with a type already defined
116                 FactoryRecord factoryRecord = FindParentFactoryRecord(false);
117                 if ((factoryRecord != null) && (factoryRecord.AllowExeDefinition != value))
118                     throw new ConfigurationErrorsException(string.Format(SR.Config_tag_name_already_defined, ConfigKey));
119 
120                 _allowExeDefinition = value;
121                 _modifiedFlags[FlagAllowExeDefinitionModified] = true;
122             }
123         }
124 
125         internal bool AllowExeDefinitionModified => _modifiedFlags[FlagAllowExeDefinitionModified];
126 
127         public OverrideMode OverrideModeDefault
128         {
129             get { return _overrideModeDefault.OverrideMode; }
130             set
131             {
132                 VerifyIsEditable();
133                 VerifyIsEditableFactory();
134 
135                 // allow OverrideModeDefault to be different from current value,
136                 // so long as it doesn't conflict with a type already defined
137                 FactoryRecord factoryRecord = FindParentFactoryRecord(false);
138                 if ((factoryRecord != null) && (factoryRecord.OverrideModeDefault.OverrideMode != value))
139                     throw new ConfigurationErrorsException(string.Format(SR.Config_tag_name_already_defined, ConfigKey));
140 
141                 // Threat "Inherit" as "Allow" as "Inherit" does not make sense as a default
142                 if (value == OverrideMode.Inherit) value = OverrideMode.Allow;
143 
144                 _overrideModeDefault.OverrideMode = value;
145                 _modifiedFlags[FlagOverrideModeDefaultModified] = true;
146             }
147         }
148 
149         internal OverrideModeSetting OverrideModeDefaultSetting => _overrideModeDefault;
150 
151         internal bool OverrideModeDefaultModified => _modifiedFlags[FlagOverrideModeDefaultModified];
152 
153         public bool AllowLocation
154         {
155             get { return _flags[FlagAllowLocation]; }
156             set
157             {
158                 VerifyIsEditable();
159                 VerifyIsEditableFactory();
160 
161                 // allow AllowLocation to be different from current type,
162                 // so long as it doesn't conflict with a type already defined
163                 FactoryRecord factoryRecord = FindParentFactoryRecord(false);
164                 if ((factoryRecord != null) && (factoryRecord.AllowLocation != value))
165                     throw new ConfigurationErrorsException(string.Format(SR.Config_tag_name_already_defined, ConfigKey));
166 
167                 _flags[FlagAllowLocation] = value;
168                 _modifiedFlags[FlagAllowLocation] = true;
169             }
170         }
171 
172         internal bool AllowLocationModified => _modifiedFlags[FlagAllowLocation];
173 
174         public bool AllowOverride
175         {
176             get { return _overrideMode.AllowOverride; }
177             set
178             {
179                 VerifyIsEditable();
180                 VerifySupportsLocation();
181                 _overrideMode.AllowOverride = value;
182                 _modifiedFlags[FlagOverrideModeModified] = true;
183             }
184         }
185 
186         public OverrideMode OverrideMode
187         {
188             get { return _overrideMode.OverrideMode; }
189             set
190             {
191                 VerifyIsEditable();
192                 VerifySupportsLocation();
193                 _overrideMode.OverrideMode = value;
194                 _modifiedFlags[FlagOverrideModeModified] = true;
195 
196                 // Modify the state of OverrideModeEffective according to the changes to the current mode
197                 switch (value)
198                 {
199                     case OverrideMode.Inherit:
200                         // Wehen the state is changing to inherit - apply the value from parent which does not
201                         // include the file input lock mode
202                         _flags[FlagChildrenLocked] = _flags[FlagChildrenLockWithoutFileInput];
203                         break;
204                     case OverrideMode.Allow:
205                         _flags[FlagChildrenLocked] = false;
206                         break;
207                     case OverrideMode.Deny:
208                         _flags[FlagChildrenLocked] = true;
209                         break;
210                     default:
211                         Debug.Assert(false, "Unexpected value for OverrideMode");
212                         break;
213                 }
214             }
215         }
216 
217         public OverrideMode OverrideModeEffective => _flags[FlagChildrenLocked] ? OverrideMode.Deny : OverrideMode.Allow
218             ;
219 
220         internal OverrideModeSetting OverrideModeSetting => _overrideMode;
221 
222 
223         // LocationAttributesAreDefault
224         //
225         // Are the location attributes for this section set to the
226         // default settings?
227         internal bool LocationAttributesAreDefault => _overrideMode.IsDefaultForLocationTag &&
228             _flags[FlagInheritInChildApps];
229 
230         public string ConfigSource
231         {
232             get { return _configSource ?? string.Empty; }
233             set
234             {
235                 VerifyIsEditable();
236 
237                 string configSource = !string.IsNullOrEmpty(value)
238                     ? BaseConfigurationRecord.NormalizeConfigSource(value, null)
239                     : null;
240 
241                 // return early if there is no change
242                 if (configSource == _configSource)
243                     return;
244 
245                 _configRecord?.ChangeConfigSource(this, _configSource, ConfigSourceStreamName, configSource);
246 
247                 _configSource = configSource;
248                 _modifiedFlags[FlagConfigSourceModified] = true;
249             }
250         }
251 
252         internal bool ConfigSourceModified => _modifiedFlags[FlagConfigSourceModified];
253 
254         internal string ConfigSourceStreamName { get; set; }
255 
256         public bool InheritInChildApplications
257         {
258             get { return _flags[FlagInheritInChildApps]; }
259             set
260             {
261                 VerifyIsEditable();
262                 VerifySupportsLocation();
263                 _flags[FlagInheritInChildApps] = value;
264             }
265         }
266 
267         // True if the section is declared at the current level
268         public bool IsDeclared
269         {
270             get
271             {
272                 VerifyNotParentSection();
273 
274                 return _flags[FlagDeclared];
275             }
276         }
277 
278         // Is the Declaration Required.  It is required if it is not set
279         // in a parent, or the parent entry does not have the type
280         public bool IsDeclarationRequired
281         {
282             get
283             {
284                 VerifyNotParentSection();
285 
286                 return _flags[FlagDeclarationRequired];
287             }
288         }
289 
290         // Is the Definition Allowed at this point.  This is all depending
291         // on the Definition that is allowed, and what context we are
292         // writing the file
293         private bool IsDefinitionAllowed
294             => (_configRecord == null) || _configRecord.IsDefinitionAllowed(_allowDefinition, _allowExeDefinition);
295 
296         public bool IsLocked => _flags[FlagLocationLocked] || !IsDefinitionAllowed ||
297             _configurationSection.ElementInformation.IsLocked;
298 
299         public bool IsProtected => ProtectionProvider != null;
300 
301         public ProtectedConfigurationProvider ProtectionProvider
302         {
303             get
304             {
305                 if (!_flags[FlagProtectionProviderDetermined] && (_configRecord != null))
306                 {
307                     _protectionProvider = _configRecord.GetProtectionProviderFromName(ProtectionProviderName, false);
308                     _flags[FlagProtectionProviderDetermined] = true;
309                 }
310 
311                 return _protectionProvider;
312             }
313         }
314 
315         internal string ProtectionProviderName { get; private set; }
316 
317         public bool RestartOnExternalChanges
318         {
319             get { return _flags[FlagRestartOnExternalChanges]; }
320             set
321             {
322                 VerifyIsEditable();
323                 VerifyIsEditableFactory();
324 
325                 // allow RestartOnExternalChanges to be different from current type,
326                 // so long as it doesn't conflict with a type already defined
327                 FactoryRecord factoryRecord = FindParentFactoryRecord(false);
328                 if ((factoryRecord != null) && (factoryRecord.RestartOnExternalChanges != value))
329                     throw new ConfigurationErrorsException(string.Format(SR.Config_tag_name_already_defined, ConfigKey));
330 
331                 _flags[FlagRestartOnExternalChanges] = value;
332                 _modifiedFlags[FlagRestartOnExternalChanges] = true;
333             }
334         }
335 
336         internal bool RestartOnExternalChangesModified => _modifiedFlags[FlagRestartOnExternalChanges];
337 
338         public bool RequirePermission
339         {
340             get { return _flags[FlagRequirePermission]; }
341             set
342             {
343                 VerifyIsEditable();
344                 VerifyIsEditableFactory();
345 
346                 // allow RequirePermission to be different from current type,
347                 // so long as it doesn't conflict with a type already defined
348                 FactoryRecord factoryRecord = FindParentFactoryRecord(false);
349                 if ((factoryRecord != null) && (factoryRecord.RequirePermission != value))
350                     throw new ConfigurationErrorsException(string.Format(SR.Config_tag_name_already_defined, ConfigKey));
351 
352                 _flags[FlagRequirePermission] = value;
353                 _modifiedFlags[FlagRequirePermission] = true;
354             }
355         }
356 
357         internal bool RequirePermissionModified => _modifiedFlags[FlagRequirePermission];
358 
359 
360         public string Type
361         {
362             get { return _typeName; }
363             set
364             {
365                 if (string.IsNullOrEmpty(value)) throw ExceptionUtil.PropertyNullOrEmpty(nameof(Type));
366 
367                 VerifyIsEditable();
368                 VerifyIsEditableFactory();
369 
370                 // allow type to be different from current type,
371                 // so long as it doesn't conflict with a type already defined
372                 FactoryRecord factoryRecord = FindParentFactoryRecord(false);
373                 if (factoryRecord != null)
374                 {
375                     IInternalConfigHost host = null;
376                     if (_configRecord != null) host = _configRecord.Host;
377 
378                     if (!factoryRecord.IsEquivalentType(host, value))
379                     {
380                         throw new ConfigurationErrorsException(string.Format(SR.Config_tag_name_already_defined,
381                             ConfigKey));
382                     }
383                 }
384 
385                 _typeName = value;
386             }
387         }
388 
389         internal string RawXml { get; set; }
390 
391         // True if the section will be serialized to the current hierarchy level, regardless of
392         // ConfigurationSaveMode.
393         public bool ForceSave
394         {
395             get { return _flags[FlagForceSave]; }
396             set
397             {
398                 VerifyIsEditable();
399 
400                 _flags[FlagForceSave] = value;
401             }
402         }
403 
ResetModifiedFlags()404         internal void ResetModifiedFlags()
405         {
406             _modifiedFlags = new SimpleBitVector32();
407         }
408 
IsModifiedFlags()409         internal bool IsModifiedFlags()
410         {
411             return _modifiedFlags.Data != 0;
412         }
413 
414         // for instantiation of a ConfigurationSection from GetConfig
AttachToConfigurationRecord(MgmtConfigurationRecord configRecord, FactoryRecord factoryRecord, SectionRecord sectionRecord)415         internal void AttachToConfigurationRecord(MgmtConfigurationRecord configRecord, FactoryRecord factoryRecord,
416             SectionRecord sectionRecord)
417         {
418             SetRuntimeConfigurationInformation(configRecord, factoryRecord, sectionRecord);
419             _configRecord = configRecord;
420         }
421 
SetRuntimeConfigurationInformation(BaseConfigurationRecord configRecord, FactoryRecord factoryRecord, SectionRecord sectionRecord)422         internal void SetRuntimeConfigurationInformation(BaseConfigurationRecord configRecord,
423             FactoryRecord factoryRecord, SectionRecord sectionRecord)
424         {
425             _flags[FlagAttached] = true;
426 
427             // factory info
428             ConfigKey = factoryRecord.ConfigKey;
429             Name = factoryRecord.Name;
430             _typeName = factoryRecord.FactoryTypeName;
431             _allowDefinition = factoryRecord.AllowDefinition;
432             _allowExeDefinition = factoryRecord.AllowExeDefinition;
433             _flags[FlagAllowLocation] = factoryRecord.AllowLocation;
434             _flags[FlagRestartOnExternalChanges] = factoryRecord.RestartOnExternalChanges;
435             _flags[FlagRequirePermission] = factoryRecord.RequirePermission;
436             _overrideModeDefault = factoryRecord.OverrideModeDefault;
437 
438             if (factoryRecord.IsUndeclared)
439             {
440                 _flags[FlagIsUndeclared] = true;
441                 _flags[FlagDeclared] = false;
442                 _flags[FlagDeclarationRequired] = false;
443             }
444             else
445             {
446                 _flags[FlagIsUndeclared] = false;
447                 _flags[FlagDeclared] = configRecord.GetFactoryRecord(factoryRecord.ConfigKey, false) != null;
448                 _flags[FlagDeclarationRequired] = configRecord.IsRootDeclaration(factoryRecord.ConfigKey, false);
449             }
450 
451             // section info
452             _flags[FlagLocationLocked] = sectionRecord.Locked;
453             _flags[FlagChildrenLocked] = sectionRecord.LockChildren;
454             _flags[FlagChildrenLockWithoutFileInput] = sectionRecord.LockChildrenWithoutFileInput;
455 
456             if (sectionRecord.HasFileInput)
457             {
458                 SectionInput fileInput = sectionRecord.FileInput;
459 
460                 _flags[FlagProtectionProviderDetermined] = fileInput.IsProtectionProviderDetermined;
461                 _protectionProvider = fileInput.ProtectionProvider;
462 
463                 SectionXmlInfo sectionXmlInfo = fileInput.SectionXmlInfo;
464 
465                 _configSource = sectionXmlInfo.ConfigSource;
466                 ConfigSourceStreamName = sectionXmlInfo.ConfigSourceStreamName;
467                 _overrideMode = sectionXmlInfo.OverrideModeSetting;
468                 _flags[FlagInheritInChildApps] = !sectionXmlInfo.SkipInChildApps;
469                 ProtectionProviderName = sectionXmlInfo.ProtectionProviderName;
470             }
471             else
472             {
473                 _flags[FlagProtectionProviderDetermined] = false;
474                 _protectionProvider = null;
475             }
476 
477             // element context information
478             _configurationSection.AssociateContext(configRecord);
479         }
480 
DetachFromConfigurationRecord()481         internal void DetachFromConfigurationRecord()
482         {
483             RevertToParent();
484             _flags[FlagAttached] = false;
485             _configRecord = null;
486         }
487 
VerifyDesigntime()488         private void VerifyDesigntime()
489         {
490             if (IsRuntime) throw new InvalidOperationException(SR.Config_operation_not_runtime);
491         }
492 
VerifyIsAttachedToConfigRecord()493         private void VerifyIsAttachedToConfigRecord()
494         {
495             if (_configRecord == null)
496                 throw new InvalidOperationException(SR.Config_cannot_edit_configurationsection_when_not_attached);
497         }
498 
499         // VerifyIsEditable
500         //
501         // Verify the section is Editable.
502         // It may not be editable for the following reasons:
503         //   - We are in Runtime mode, not Design time
504         //   - The section is not attached to a _configRecord.
505         //   - We are locked (ie. allowOveride = false )
506         //   - We are a parent section (ie. Retrieved from GetParentSection)
507         //
VerifyIsEditable()508         internal void VerifyIsEditable()
509         {
510             VerifyDesigntime();
511 
512             if (IsLocked)
513                 throw new InvalidOperationException(SR.Config_cannot_edit_configurationsection_when_locked);
514 
515             if (_flags[FlagIsParentSection])
516                 throw new InvalidOperationException(SR.Config_cannot_edit_configurationsection_parentsection);
517 
518             if (!_flags[FlagAllowLocation] &&
519                 (_configRecord != null) &&
520                 _configRecord.IsLocationConfig)
521                 throw new InvalidOperationException(SR.Config_cannot_edit_configurationsection_when_location_locked);
522         }
523 
VerifyNotParentSection()524         private void VerifyNotParentSection()
525         {
526             if (_flags[FlagIsParentSection])
527                 throw new InvalidOperationException(SR.Config_configsection_parentnotvalid);
528         }
529 
530         // Verify that we support the location tag.  This is true either
531         // in machine.config, or in any place for the web config system
VerifySupportsLocation()532         private void VerifySupportsLocation()
533         {
534             if ((_configRecord != null) &&
535                 !_configRecord.RecordSupportsLocation)
536                 throw new InvalidOperationException(SR.Config_cannot_edit_locationattriubtes);
537         }
538 
VerifyIsEditableFactory()539         internal void VerifyIsEditableFactory()
540         {
541             if ((_configRecord != null) && _configRecord.IsLocationConfig)
542                 throw new InvalidOperationException(SR.Config_cannot_edit_configurationsection_in_location_config);
543 
544             // Can't edit factory if the section is built-in
545             if (BaseConfigurationRecord.IsImplicitSection(ConfigKey))
546                 throw new InvalidOperationException(SR.Config_cannot_edit_configurationsection_when_it_is_implicit);
547 
548             // Can't edit undeclared section
549             if (_flags[FlagIsUndeclared])
550                 throw new InvalidOperationException(SR.Config_cannot_edit_configurationsection_when_it_is_undeclared);
551         }
552 
FindParentFactoryRecord(bool permitErrors)553         private FactoryRecord FindParentFactoryRecord(bool permitErrors)
554         {
555             FactoryRecord factoryRecord = null;
556 
557             if ((_configRecord != null) && !_configRecord.Parent.IsRootConfig)
558                 factoryRecord = _configRecord.Parent.FindFactoryRecord(ConfigKey, permitErrors);
559 
560             return factoryRecord;
561         }
562 
563         // Force the section declaration to be written out during Save.
ForceDeclaration()564         public void ForceDeclaration()
565         {
566             ForceDeclaration(true);
567         }
568 
569         // If force==false, it actually means don't declare it at
570         // the current level.
ForceDeclaration(bool force)571         public void ForceDeclaration(bool force)
572         {
573             VerifyIsEditable();
574 
575             if ((force == false) &&
576                 _flags[FlagDeclarationRequired])
577             {
578                 // Since it is required, we can not remove it
579             }
580             else
581             {
582                 // CONSIDER: There is no apriori way to determine if a section
583                 // is implicit or undeclared. Would it be better to simply
584                 // fail silently so that app code can easily loop through sections
585                 // and declare all of them?
586                 if (force && BaseConfigurationRecord.IsImplicitSection(SectionName))
587                     throw new ConfigurationErrorsException(SR.Cannot_declare_or_remove_implicit_section);
588 
589                 if (force && _flags[FlagIsUndeclared])
590                 {
591                     throw new ConfigurationErrorsException(
592                         SR.Config_cannot_edit_configurationsection_when_it_is_undeclared);
593                 }
594 
595                 _flags[FlagDeclared] = force;
596             }
597         }
598 
599         // method to cause a section to be protected using the specified provider
ProtectSection(string protectionProvider)600         public void ProtectSection(string protectionProvider)
601         {
602             ProtectedConfigurationProvider protectedConfigurationProvider;
603 
604             VerifyIsEditable();
605 
606             // Do not encrypt sections that will be read by a native reader.
607             // These sections are be marked with allowLocation=false.
608             // Also, the configProtectedData section cannot be encrypted!
609             if (!AllowLocation || (ConfigKey == BaseConfigurationRecord.ReservedSectionProtectedConfiguration))
610                 throw new InvalidOperationException(SR.Config_not_allowed_to_encrypt_this_section);
611 
612             if (_configRecord != null)
613             {
614                 if (string.IsNullOrEmpty(protectionProvider)) protectionProvider = _configRecord.DefaultProviderName;
615 
616                 protectedConfigurationProvider = _configRecord.GetProtectionProviderFromName(protectionProvider, true);
617             }
618             else throw new InvalidOperationException(SR.Must_add_to_config_before_protecting_it);
619 
620             ProtectionProviderName = protectionProvider;
621             _protectionProvider = protectedConfigurationProvider;
622 
623             _flags[FlagProtectionProviderDetermined] = true;
624             _modifiedFlags[FlagProtectionProviderModified] = true;
625         }
626 
UnprotectSection()627         public void UnprotectSection()
628         {
629             VerifyIsEditable();
630 
631             _protectionProvider = null;
632             ProtectionProviderName = null;
633             _flags[FlagProtectionProviderDetermined] = true;
634             _modifiedFlags[FlagProtectionProviderModified] = true;
635         }
636 
GetParentSection()637         public ConfigurationSection GetParentSection()
638         {
639             VerifyDesigntime();
640 
641             if (_flags[FlagIsParentSection])
642                 throw new InvalidOperationException(SR.Config_getparentconfigurationsection_first_instance);
643 
644             // if a users create a configsection with : sectionType sec  = new sectionType();
645             // the config record will be null.  Return null for the parent in this case.
646             ConfigurationSection ancestor = null;
647             if (_configRecord != null)
648             {
649                 ancestor = _configRecord.FindAndCloneImmediateParentSection(_configurationSection);
650                 if (ancestor != null)
651                 {
652                     ancestor.SectionInformation._flags[FlagIsParentSection] = true;
653                     ancestor.SetReadOnly();
654                 }
655             }
656 
657             return ancestor;
658         }
659 
GetRawXml()660         public string GetRawXml()
661         {
662             VerifyDesigntime();
663             VerifyNotParentSection();
664 
665             return RawXml ?? _configRecord?.GetRawXml(ConfigKey);
666         }
667 
SetRawXml(string rawXml)668         public void SetRawXml(string rawXml)
669         {
670             VerifyIsEditable();
671 
672             if (_configRecord != null) _configRecord.SetRawXml(_configurationSection, rawXml);
673             else RawXml = string.IsNullOrEmpty(rawXml) ? null : rawXml;
674         }
675 
RevertToParent()676         public void RevertToParent()
677         {
678             VerifyIsEditable();
679             VerifyIsAttachedToConfigRecord();
680 
681             _configRecord.RevertToParent(_configurationSection);
682         }
683     }
684 }