File: qualifierset.cs
Project: ndp\fx\src\wmi\managed\System\Management\System.Management.csproj (System.Management)
using System;
using System.Collections;
using System.Runtime.InteropServices;
using WbemClient_v1;
 
namespace System.Management
{
	//CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC//	
	/// <summary>
	/// <para> Represents a collection of <see cref='System.Management.QualifierData'/> objects.</para>
	/// </summary>
	/// <example>
	///    <code lang='C#'>using System; 
	/// using System.Management;
	///  
	/// // This sample demonstrates how to list all qualifiers including amended 
	/// // qualifiers of a ManagementClass object. 
	/// class Sample_QualifierDataCollection 
	/// { 
	///     public static int Main(string[] args) { 
	///         ManagementClass diskClass = new ManagementClass("Win32_LogicalDisk"); 
	///         diskClass.Options.UseAmendedQualifiers = true;
	///         QualifierDataCollection qualifierCollection = diskClass.Qualifiers;
	///         foreach (QualifierData q in qualifierCollection) {
	///             Console.WriteLine(q.Name + " = " + q.Value);
	///         }
	///         return 0;
	///     }
	/// }
	///    </code>
	///    <code lang='VB'>Imports System
	///       Imports System.Management
	///       ' This sample demonstrates how to list all qualifiers including amended
	///       ' qualifiers of a ManagementClass object.
	///       Class Sample_QualifierDataCollection
	///       Overloads Public Shared Function Main(args() As String) As Integer
	///       Dim diskClass As New ManagementClass("Win32_LogicalDisk")
	///       diskClass.Options.UseAmendedQualifiers = true
	///       Dim qualifierCollection As QualifierDataCollection = diskClass.Qualifiers
	///       Dim q As QualifierData
	///       For Each q In qualifierCollection
	///       Console.WriteLine(q.Name &amp; " = " &amp; q.Value)
	///       Next q
	///       Return 0
	///       End Function
	///       End Class
	///    </code>
	/// </example>
	//CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC//
	public class QualifierDataCollection : ICollection, IEnumerable
	{
		private ManagementBaseObject parent;
		private string propertyOrMethodName;
		private QualifierType qualifierSetType;
 
		internal QualifierDataCollection(ManagementBaseObject parent) : base()
		{
			this.parent = parent;
			this.qualifierSetType = QualifierType.ObjectQualifier;
			this.propertyOrMethodName = null;
		}
 
		internal QualifierDataCollection(ManagementBaseObject parent, string propertyOrMethodName, QualifierType type) : base()
		{
			this.parent = parent;
			this.propertyOrMethodName = propertyOrMethodName;
			this.qualifierSetType = type;
		}
 
		/// <summary>
		/// Return the qualifier set associated with its type
		/// Overload with use of private data member, qualifierType
		/// </summary>
		private IWbemQualifierSetFreeThreaded GetTypeQualifierSet()
		{
			return GetTypeQualifierSet(qualifierSetType);
		}
 
		/// <summary>
		/// Return the qualifier set associated with its type
		/// </summary>
		private IWbemQualifierSetFreeThreaded GetTypeQualifierSet(QualifierType qualifierSetType)
		{
			IWbemQualifierSetFreeThreaded qualifierSet	= null;
			int status						= (int)ManagementStatus.NoError;
 
			switch (qualifierSetType) 
			{
				case QualifierType.ObjectQualifier :
					status = parent.wbemObject.GetQualifierSet_(out qualifierSet);
					break;
				case QualifierType.PropertyQualifier :
					status = parent.wbemObject.GetPropertyQualifierSet_(propertyOrMethodName, out qualifierSet);
					break;
				case QualifierType.MethodQualifier :
					status = parent.wbemObject.GetMethodQualifierSet_(propertyOrMethodName, out qualifierSet);
					break;
				default :
					throw new ManagementException(ManagementStatus.Unexpected, null, null);	// Is this the best fit error ??
			}
 
			if (status < 0)
			{
				if ((status & 0xfffff000) == 0x80041000)
					ManagementException.ThrowWithExtendedInfo((ManagementStatus)status);
				else
					Marshal.ThrowExceptionForHR(status, WmiNetUtilsHelper.GetErrorInfo_f());
			}
 
			return qualifierSet;
		}
 
		//
		//ICollection
		//
 
		/// <summary>
		/// <para>Gets or sets the number of <see cref='System.Management.QualifierData'/> objects in the <see cref='System.Management.QualifierDataCollection'/>.</para>
		/// </summary>
		/// <value>
		///    <para>The number of objects in the collection.</para>
		/// </value>
		public int Count 
		{
			get {
				string[] qualifierNames = null;
                IWbemQualifierSetFreeThreaded quals;
                try
                {
                    quals = GetTypeQualifierSet();
                }
                catch(ManagementException e)
                {
                    // If we ask for the number of qualifiers on a system property, we return '0'
                    if(qualifierSetType == QualifierType.PropertyQualifier && e.ErrorCode == ManagementStatus.SystemProperty)
                        return 0;
                    else
                        throw;
                }
				int status = quals.GetNames_(0, out qualifierNames);
				
				if (status < 0)
				{
					if ((status & 0xfffff000) == 0x80041000)
						ManagementException.ThrowWithExtendedInfo((ManagementStatus)status);
					else
						Marshal.ThrowExceptionForHR(status, WmiNetUtilsHelper.GetErrorInfo_f());
				}
 
				return qualifierNames.Length;
			}
		}
 
		/// <summary>
		///    <para>Gets or sets a value indicating whether the object is synchronized.</para>
		/// </summary>
		/// <value>
		/// <para><see langword='true'/> if the object is synchronized; 
		///    otherwise, <see langword='false'/>.</para>
		/// </value>
		public bool IsSynchronized { get { return false; } 
		}
 
		/// <summary>
		///    <para>Gets or sets the object to be used for synchronization.</para>
		/// </summary>
		/// <value>
		///    <para>The object to be used for synchronization.</para>
		/// </value>
		public object SyncRoot { get { return this; } 
		}
 
		/// <overload>
		/// <para>Copies the <see cref='System.Management.QualifierDataCollection'/> into an array.</para>
		/// </overload>
		/// <summary>
		/// <para> Copies the <see cref='System.Management.QualifierDataCollection'/> into an array.</para>
		/// </summary>
		/// <param name='array'>The array to which to copy the <see cref='System.Management.QualifierDataCollection'/>. </param>
		/// <param name='index'>The index from which to start copying. </param>
		public void CopyTo(Array array, int index)
		{
			if (null == array)
				throw new ArgumentNullException("array");
 
			if ((index < array.GetLowerBound(0)) || (index > array.GetUpperBound(0)))
				throw new ArgumentOutOfRangeException("index");
 
			// Get the names of the qualifiers
			string[] qualifierNames = null;
            IWbemQualifierSetFreeThreaded quals;
            try
            {
                quals = GetTypeQualifierSet();
            }
            catch(ManagementException e)
            {
                // There are NO qualifiers on system properties, so we just return
                if(qualifierSetType == QualifierType.PropertyQualifier && e.ErrorCode == ManagementStatus.SystemProperty)
                    return;
                else
                    throw;
            }
			int status = quals.GetNames_(0, out qualifierNames);
 
			if (status < 0)
			{
				if ((status & 0xfffff000) == 0x80041000)
					ManagementException.ThrowWithExtendedInfo((ManagementStatus)status);
				else
					Marshal.ThrowExceptionForHR(status, WmiNetUtilsHelper.GetErrorInfo_f());
			}
 
			if ((index + qualifierNames.Length) > array.Length)
				throw new ArgumentException(null, "index");
 
			foreach (string qualifierName in qualifierNames)
				array.SetValue(new QualifierData(parent, propertyOrMethodName, qualifierName, qualifierSetType), index++);
 
			return;
		}
 
		/// <summary>
		/// <para>Copies the <see cref='System.Management.QualifierDataCollection'/> into a specialized 
		/// <see cref='System.Management.QualifierData'/> 
		/// array.</para>
		/// </summary>
		/// <param name='qualifierArray'><para>The specialized array of <see cref='System.Management.QualifierData'/> objects 
		/// to which to copy the <see cref='System.Management.QualifierDataCollection'/>.</para></param>
		/// <param name=' index'>The index from which to start copying.</param>
		public void CopyTo(QualifierData[] qualifierArray, int index)
		{
			CopyTo((Array)qualifierArray, index);
		}
 
		//
		// IEnumerable
		//
		IEnumerator IEnumerable.GetEnumerator()
		{
			return (IEnumerator)(new QualifierDataEnumerator(parent, propertyOrMethodName, qualifierSetType));
		}
 
		/// <summary>
		/// <para>Returns an enumerator for the <see cref='System.Management.QualifierDataCollection'/>. This method is strongly typed.</para>
		/// </summary>
		/// <returns>
		/// <para>An <see cref='System.Collections.IEnumerator'/> that can be used to iterate through the 
		///    collection.</para>
		/// </returns>
		public QualifierDataEnumerator GetEnumerator()
		{
			return new QualifierDataEnumerator(parent, propertyOrMethodName, qualifierSetType);
		}
 
		/// <summary>
		/// <para>Represents the enumerator for <see cref='System.Management.QualifierData'/> 
		/// objects in the <see cref='System.Management.QualifierDataCollection'/>.</para>
		/// </summary>
		/// <example>
		///    <code lang='C#'>using System; 
		/// using System.Management; 
		/// 
		/// // This sample demonstrates how to enumerate qualifiers of a ManagementClass 
		/// // using QualifierDataEnumerator object. 
		/// class Sample_QualifierDataEnumerator 
		/// { 
		///     public static int Main(string[] args) { 
		///         ManagementClass diskClass = new ManagementClass("Win32_LogicalDisk"); 
		///         diskClass.Options.UseAmendedQualifiers = true; 
		///         QualifierDataCollection diskQualifier = diskClass.Qualifiers;
		///         QualifierDataCollection.QualifierDataEnumerator 
		///             qualifierEnumerator = diskQualifier.GetEnumerator();
		///         while(qualifierEnumerator.MoveNext()) {
		///             Console.WriteLine(qualifierEnumerator.Current.Name + " = " +
		///                 qualifierEnumerator.Current.Value);
		///         }
		///         return 0;
		///     }
		/// }
		///    </code>
		///    <code lang='VB'>Imports System
		/// Imports System.Management
		/// 
		/// ' This sample demonstrates how to enumerate qualifiers of a ManagementClass
		/// ' using QualifierDataEnumerator object.
		/// Class Sample_QualifierDataEnumerator
		///     Overloads Public Shared Function Main(args() As String) As Integer
		///         Dim diskClass As New ManagementClass("win32_logicaldisk")
		///         diskClass.Options.UseAmendedQualifiers = True
		///         Dim diskQualifier As QualifierDataCollection = diskClass.Qualifiers
		///         Dim qualifierEnumerator As _
		///             QualifierDataCollection.QualifierDataEnumerator = _
		///                 diskQualifier.GetEnumerator()
		///         While qualifierEnumerator.MoveNext()
		///             Console.WriteLine(qualifierEnumerator.Current.Name &amp; _
		///                 " = " &amp; qualifierEnumerator.Current.Value)
		///         End While
		///         Return 0
		///     End Function
		/// End Class
		///    </code>
		/// </example>
		public class QualifierDataEnumerator : IEnumerator
		{
			private ManagementBaseObject parent;
			private string propertyOrMethodName;
			private QualifierType qualifierType;
			private string[] qualifierNames;
			private int index = -1;
 
			//Internal constructor
			internal QualifierDataEnumerator(ManagementBaseObject parent, string propertyOrMethodName, 
														QualifierType qualifierType)
			{
				this.parent						= parent;
				this.propertyOrMethodName		= propertyOrMethodName;
				this.qualifierType				= qualifierType;
				this.qualifierNames				= null;
 
				IWbemQualifierSetFreeThreaded qualifierSet	= null;
				int status						= (int)ManagementStatus.NoError;
 
				switch (qualifierType) 
				{
					case QualifierType.ObjectQualifier :
						status = parent.wbemObject.GetQualifierSet_(out qualifierSet);
						break;
					case QualifierType.PropertyQualifier :
						status = parent.wbemObject.GetPropertyQualifierSet_(propertyOrMethodName, out qualifierSet);
						break;
					case QualifierType.MethodQualifier :
						status = parent.wbemObject.GetMethodQualifierSet_(propertyOrMethodName, out qualifierSet);
						break;
					default :
						throw new ManagementException(ManagementStatus.Unexpected, null, null);	// Is this the best fit error ??
				}
 
                // If we got an error code back, assume there are NO qualifiers for this object/property/method
                if(status < 0)
                {
                    // 
 
 
                    qualifierNames = new String[]{};
                }
                else
                {
                    status = qualifierSet.GetNames_(0, out qualifierNames);
    							
                    if (status < 0)
                    {
                        if ((status & 0xfffff000) == 0x80041000)
                            ManagementException.ThrowWithExtendedInfo((ManagementStatus)status);
                        else
                            Marshal.ThrowExceptionForHR(status, WmiNetUtilsHelper.GetErrorInfo_f());
                    }
                }
			}
		
			//Standard "Current" variant
			/// <internalonly/>
			object IEnumerator.Current { get { return (object)this.Current; } }
 
			/// <summary>
			/// <para>Gets or sets the current <see cref='System.Management.QualifierData'/> in the <see cref='System.Management.QualifierDataCollection'/> enumeration.</para>
			/// </summary>
			/// <value>
			/// <para>The current <see cref='System.Management.QualifierData'/> element in the collection.</para>
			/// </value>
			public QualifierData Current 
			{
				get {
					if ((index == -1) || (index == qualifierNames.Length))
						throw new InvalidOperationException();
					else
						return new QualifierData(parent, propertyOrMethodName, 
												qualifierNames[index], qualifierType);
				}
			}
 
			/// <summary>
			/// <para> Moves to the next element in the <see cref='System.Management.QualifierDataCollection'/> enumeration.</para>
			/// </summary>
			/// <returns>
			/// <para><see langword='true'/> if the enumerator was successfully advanced to the next 
			///    element; <see langword='false'/> if the enumerator has passed the end of the
			///    collection.</para>
			/// </returns>
			public bool MoveNext()
			{
				if (index == qualifierNames.Length) //passed the end of the array
					return false; //don't advance the index any more
 
				index++;
				return (index == qualifierNames.Length) ? false : true;
			}
 
			/// <summary>
			/// <para>Resets the enumerator to the beginning of the <see cref='System.Management.QualifierDataCollection'/> enumeration.</para>
			/// </summary>
			public void Reset()
			{
				index = -1;
			}
            
		}//QualifierDataEnumerator
 
 
		//
		//Methods
		//
 
		/// <summary>
		/// <para> Gets the specified <see cref='System.Management.QualifierData'/> from the <see cref='System.Management.QualifierDataCollection'/>.</para>
		/// </summary>
		/// <param name='qualifierName'>The name of the <see cref='System.Management.QualifierData'/> to access in the <see cref='System.Management.QualifierDataCollection'/>. </param>
		/// <value>
		/// <para>A <see cref='System.Management.QualifierData'/>, based on the name specified.</para>
		/// </value>
		public virtual QualifierData this[string qualifierName] 
		{
			get { 
				if (null == qualifierName)
					throw new ArgumentNullException("qualifierName");
 
				return new QualifierData(parent, propertyOrMethodName, qualifierName, qualifierSetType); 
			}
		}
 
		/// <summary>
		/// <para>Removes a <see cref='System.Management.QualifierData'/> from the <see cref='System.Management.QualifierDataCollection'/> by name.</para>
		/// </summary>
		/// <param name='qualifierName'>The name of the <see cref='System.Management.QualifierData'/> to remove. </param>
		public virtual void Remove(string qualifierName)
		{
			int status = GetTypeQualifierSet().Delete_(qualifierName);
		
			if (status < 0)
			{
				if ((status & 0xfffff000) == 0x80041000)
					ManagementException.ThrowWithExtendedInfo((ManagementStatus)status);
				else
					Marshal.ThrowExceptionForHR(status, WmiNetUtilsHelper.GetErrorInfo_f());
			}
		}
 
		/// <overload>
		/// <para>Adds a <see cref='System.Management.QualifierData'/> to the <see cref='System.Management.QualifierDataCollection'/>.</para>
		/// </overload>
		/// <summary>
		/// <para>Adds a <see cref='System.Management.QualifierData'/> to the <see cref='System.Management.QualifierDataCollection'/>. This overload specifies the qualifier name and value.</para>
		/// </summary>
		/// <param name='qualifierName'>The name of the <see cref='System.Management.QualifierData'/> to be added to the <see cref='System.Management.QualifierDataCollection'/>. </param>
		/// <param name='qualifierValue'>The value for the new qualifier. </param>
		public virtual void Add(string qualifierName, object qualifierValue)
		{
			Add(qualifierName, qualifierValue, false, false, false, true);
		}
 
 
 
		/// <summary>
		/// <para>Adds a <see cref='System.Management.QualifierData'/> to the <see cref='System.Management.QualifierDataCollection'/>. This overload 
		///    specifies all property values for a <see cref='System.Management.QualifierData'/> object.</para>
		/// </summary>
		/// <param name='qualifierName'>The qualifier name. </param>
		/// <param name='qualifierValue'>The qualifier value. </param>
		/// <param name='isAmended'><see langword='true'/> to specify that this qualifier is amended (flavor); otherwise, <see langword='false'/>. </param>
		/// <param name='propagatesToInstance'><see langword='true'/> to propagate this qualifier to instances; otherwise, <see langword='false'/>. </param>
		/// <param name='propagatesToSubclass'><see langword='true'/> to propagate this qualifier to subclasses; otherwise, <see langword='false'/>. </param>
		/// <param name='isOverridable'><see langword='true'/> to specify that this qualifier's value is overridable in instances of subclasses; otherwise, <see langword='false'/>. </param>
		public virtual void Add(string qualifierName, object qualifierValue, bool isAmended, bool propagatesToInstance, bool propagatesToSubclass, bool isOverridable)
		{
			
			//Build the flavors bitmask and call the internal Add that takes a bitmask
			int qualFlavor = 0;
			if (isAmended) qualFlavor = (qualFlavor | (int)tag_WBEM_FLAVOR_TYPE.WBEM_FLAVOR_AMENDED);
			if (propagatesToInstance) qualFlavor = (qualFlavor | (int)tag_WBEM_FLAVOR_TYPE.WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE);
			if (propagatesToSubclass) qualFlavor = (qualFlavor | (int)tag_WBEM_FLAVOR_TYPE.WBEM_FLAVOR_FLAG_PROPAGATE_TO_DERIVED_CLASS);
 
			// Note we use the NOT condition here since WBEM_FLAVOR_OVERRIDABLE == 0
			if (!isOverridable) qualFlavor = (qualFlavor | (int)tag_WBEM_FLAVOR_TYPE.WBEM_FLAVOR_NOT_OVERRIDABLE);
 
			//Try to add the qualifier to the WMI object
			int status = GetTypeQualifierSet().Put_(qualifierName, ref qualifierValue, qualFlavor);
						
			if (status < 0)
			{
				if ((status & 0xfffff000) == 0x80041000)
					ManagementException.ThrowWithExtendedInfo((ManagementStatus)status);
				else
					Marshal.ThrowExceptionForHR(status, WmiNetUtilsHelper.GetErrorInfo_f());
			}
		}
 
	}//QualifierDataCollection
}