File: propertyset.cs
Project: ndp\fx\src\wmi\managed\System\Management\System.Management.csproj (System.Management)
using System.Collections;
using System.Diagnostics;
using System.Runtime.InteropServices;
using WbemClient_v1;
using System.ComponentModel;
 
namespace System.Management
{
	//CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC//	
	/// <summary>
	///    <para> Represents the set of properties of a WMI object.</para>
	/// </summary>
	/// <example>
	///    <code lang='C#'>using System; 
	/// using System.Management; 
	/// 
	/// // This sample demonstrates how to enumerate properties 
	/// // in a ManagementObject object.
	/// class Sample_PropertyDataCollection 
	/// { 
	///     public static int Main(string[] args) {
	///         ManagementObject disk = new ManagementObject("win32_logicaldisk.deviceid = \"c:\""); 
	///         PropertyDataCollection diskProperties = disk.Properties;
	///         foreach (PropertyData diskProperty in diskProperties) {
	///             Console.WriteLine("Property = " + diskProperty.Name);
	///         }
	///         return 0;
	///     }
	/// }
	///    </code>
	///    <code lang='VB'>Imports System
	/// Imports System.Management
	/// 
	/// ' This sample demonstrates how to enumerate properties
	/// ' in a ManagementObject object.
	/// Class Sample_PropertyDataCollection
	///     Overloads Public Shared Function Main(args() As String) As Integer
	///         Dim disk As New ManagementObject("win32_logicaldisk.deviceid=""c:""")
	///         Dim diskProperties As PropertyDataCollection = disk.Properties
	///         Dim diskProperty As PropertyData
	///         For Each diskProperty In diskProperties
	///             Console.WriteLine("Property = " &amp; diskProperty.Name)
	///         Next diskProperty
	///         Return 0
	///     End Function
	/// End Class
	///    </code>
	/// </example>
	//CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC//
	public class PropertyDataCollection : ICollection, IEnumerable
	{
		private ManagementBaseObject parent;
		bool isSystem;
 
		internal PropertyDataCollection(ManagementBaseObject parent, bool isSystem) : base()
		{
			this.parent = parent;
			this.isSystem = isSystem;
		}
 
		//
		//ICollection
		//
 
		/// <summary>
		/// <para>Gets or sets the number of objects in the <see cref='System.Management.PropertyDataCollection'/>.</para>
		/// </summary>
		/// <value>
		///    <para>The number of objects in the collection.</para>
		/// </value>
		public int Count 
		{
			get {
				string[] propertyNames = null; object qualVal = null;
				int flag;
				if (isSystem)
					flag = (int)tag_WBEM_CONDITION_FLAG_TYPE.WBEM_FLAG_SYSTEM_ONLY;
				else
					flag = (int)tag_WBEM_CONDITION_FLAG_TYPE.WBEM_FLAG_NONSYSTEM_ONLY;
 
				flag |= (int)tag_WBEM_CONDITION_FLAG_TYPE.WBEM_FLAG_ALWAYS;
 
				int status = parent.wbemObject.GetNames_(null, flag, ref qualVal, out propertyNames);
 
				if (status < 0)
				{
					if ((status & 0xfffff000) == 0x80041000)
						ManagementException.ThrowWithExtendedInfo((ManagementStatus)status);
					else
						Marshal.ThrowExceptionForHR(status, WmiNetUtilsHelper.GetErrorInfo_f());
				}
 
				return propertyNames.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.PropertyDataCollection'/> into an array.</para>
		/// </overload>
		/// <summary>
		/// <para>Copies the <see cref='System.Management.PropertyDataCollection'/> into an array.</para>
		/// </summary>
		/// <param name='array'>The array to which to copy the <see cref='System.Management.PropertyDataCollection'/>. </param>
		/// <param name='index'>The index from which to start copying. </param>
		public void CopyTo(Array array, Int32 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 properties 
			string[] nameArray = null;
			object dummy = null;
			int flag = 0;
 
			if (isSystem)
				flag |= (int)tag_WBEM_CONDITION_FLAG_TYPE.WBEM_FLAG_SYSTEM_ONLY;
			else
				flag |= (int)tag_WBEM_CONDITION_FLAG_TYPE.WBEM_FLAG_NONSYSTEM_ONLY;
				
			flag |= (int)tag_WBEM_CONDITION_FLAG_TYPE.WBEM_FLAG_ALWAYS;
				
			int status = this.parent.wbemObject.GetNames_(null, flag, ref dummy, out nameArray);
 
			if (status >= 0)
			{
				if ((index + nameArray.Length) > array.Length)
					throw new ArgumentException(null,"index");
 
				foreach (string propertyName in nameArray)
					array.SetValue(new PropertyData(parent, propertyName), index++);
			}
 
			if (status < 0)
			{
				if ((status & 0xfffff000) == 0x80041000)
					ManagementException.ThrowWithExtendedInfo((ManagementStatus)status);
				else
					Marshal.ThrowExceptionForHR(status, WmiNetUtilsHelper.GetErrorInfo_f());
			}
 
			return;
		}
 
		/// <summary>
		/// <para>Copies the <see cref='System.Management.PropertyDataCollection'/> to a specialized <see cref='System.Management.PropertyData'/> object
		///    array.</para>
		/// </summary>
		/// <param name='propertyArray'>The destination array to contain the copied <see cref='System.Management.PropertyDataCollection'/>.</param>
		/// <param name=' index'>The index in the destination array from which to start copying.</param>
		public void CopyTo(PropertyData[] propertyArray, Int32 index)
		{
			CopyTo((Array)propertyArray, index);	
		}
		//
		// IEnumerable
		//
		IEnumerator IEnumerable.GetEnumerator()
		{
			return (IEnumerator)(new PropertyDataEnumerator(parent, isSystem));
		}
 
		/// <summary>
		/// <para>Returns the enumerator for this <see cref='System.Management.PropertyDataCollection'/>.</para>
		/// </summary>
		/// <returns>
		/// <para>An <see cref='System.Collections.IEnumerator'/> 
		/// that can be used to iterate through the collection.</para>
		/// </returns>
		public PropertyDataEnumerator GetEnumerator()
		{
			return new PropertyDataEnumerator(parent, isSystem);
		}
 
		//Enumerator class
		/// <summary>
		/// <para>Represents the enumerator for <see cref='System.Management.PropertyData'/> 
		/// objects in the <see cref='System.Management.PropertyDataCollection'/>.</para>
		/// </summary>
		/// <example>
		///    <code lang='C#'>using System; 
		/// using System.Management; 
		/// 
		/// // This sample demonstrates how to enumerate all properties in a 
		/// // ManagementObject using the PropertyDataEnumerator object. 
		/// class Sample_PropertyDataEnumerator 
		/// {
		///     public static int Main(string[] args) { 
		///         ManagementObject disk = new ManagementObject("Win32_LogicalDisk.DeviceID='C:'");
		///         PropertyDataCollection.PropertyDataEnumerator propertyEnumerator = disk.Properties.GetEnumerator();
		///         while(propertyEnumerator.MoveNext()) {
		///             PropertyData p = (PropertyData)propertyEnumerator.Current;
		///             Console.WriteLine("Property found: " + p.Name);
		///         }
		///         return 0;
		///     }
		/// }
		///    </code>
		///    <code lang='VB'>Imports System
		/// Imports System.Management
		/// 
		/// ' This sample demonstrates how to enumerate all properties in a
		/// ' ManagementObject using PropertyDataEnumerator object.
		/// Class Sample_PropertyDataEnumerator
		///     Overloads Public Shared Function Main(args() As String) As Integer
		///         Dim disk As New ManagementObject("Win32_LogicalDisk.DeviceID='C:'")
		///         Dim propertyEnumerator As _
		///           PropertyDataCollection.PropertyDataEnumerator = disk.Properties.GetEnumerator()
		///         While propertyEnumerator.MoveNext()
		///             Dim p As PropertyData = _
		///                 CType(propertyEnumerator.Current, PropertyData)
		///             Console.WriteLine("Property found: " &amp; p.Name)
		///          End While
		///          Return 0
		///      End Function
		/// End Class
		///    </code>
		/// </example>
		public class PropertyDataEnumerator : IEnumerator
		{
			private ManagementBaseObject parent;
			private string[] propertyNames;
			private int index;
 
			internal PropertyDataEnumerator(ManagementBaseObject parent, bool isSystem)
			{
				this.parent = parent;
				propertyNames = null; index = -1;
				int flag; object qualVal = null;
 
				if (isSystem)
					flag = (int)tag_WBEM_CONDITION_FLAG_TYPE.WBEM_FLAG_SYSTEM_ONLY;
				else
					flag = (int)tag_WBEM_CONDITION_FLAG_TYPE.WBEM_FLAG_NONSYSTEM_ONLY;
 
				flag |= (int)tag_WBEM_CONDITION_FLAG_TYPE.WBEM_FLAG_ALWAYS;
 
				int status = parent.wbemObject.GetNames_(null, flag, ref qualVal, out propertyNames);
 
				if (status < 0)
				{
					if ((status & 0xfffff000) == 0x80041000)
						ManagementException.ThrowWithExtendedInfo((ManagementStatus)status);
					else
						Marshal.ThrowExceptionForHR(status, WmiNetUtilsHelper.GetErrorInfo_f());
				}
			}
		
			/// <internalonly/>
			object IEnumerator.Current { get { return (object)this.Current; } }
 
			/// <summary>
			/// <para>Gets the current <see cref='System.Management.PropertyData'/> in the <see cref='System.Management.PropertyDataCollection'/> enumeration.</para>
			/// </summary>
			/// <value>
			///    The current <see cref='System.Management.PropertyData'/>
			///    element in the collection.
			/// </value>
			public PropertyData Current 
			{
				get {
					if ((index == -1) || (index == propertyNames.Length))
						throw new InvalidOperationException();
					else
						return new PropertyData(parent, propertyNames[index]);
				}
			}
 
			/// <summary>
			/// <para> Moves to the next element in the <see cref='System.Management.PropertyDataCollection'/> 
			/// 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 == propertyNames.Length) //passed the end of the array
					return false; //don't advance the index any more
 
				index++;
				return (index == propertyNames.Length) ? false : true;
			}
 
			/// <summary>
			/// <para>Resets the enumerator to the beginning of the <see cref='System.Management.PropertyDataCollection'/> 
			/// enumeration.</para>
			/// </summary>
			public void Reset()
			{
				index = -1;
			}
            
		}//PropertyDataEnumerator
 
 
 
		//
		// Methods
		//
 
		/// <summary>
		/// <para> Returns the specified property from the <see cref='System.Management.PropertyDataCollection'/>, using [] syntax.</para>
		/// </summary>
		/// <param name='propertyName'>The name of the property to retrieve.</param>
		/// <value>
		/// <para> A <see cref='System.Management.PropertyData'/>, based on
		///    the name specified.</para>
		/// </value>
		/// <example>
		///    <code lang='C#'>ManagementObject o = new ManagementObject("Win32_LogicalDisk.Name = 'C:'");
		/// Console.WriteLine("Free space on C: drive is: ", c.Properties["FreeSpace"].Value);
		///    </code>
		///    <code lang='VB'>Dim o As New ManagementObject("Win32_LogicalDisk.Name=""C:""")
		/// Console.WriteLine("Free space on C: drive is: " &amp; c.Properties("FreeSpace").Value)
		///    </code>
		/// </example>
		public virtual PropertyData this[string propertyName] 
		{
			get { 
				if (null == propertyName)
					throw new ArgumentNullException("propertyName");
 
				return new PropertyData(parent, propertyName);
            }
		}
 
		/// <summary>
		/// <para>Removes a <see cref='System.Management.PropertyData'/> from the <see cref='System.Management.PropertyDataCollection'/>.</para>
		/// </summary>
		/// <param name='propertyName'>The name of the property to be removed.</param>
		/// <remarks>
		///    <para> Properties can only be removed from class definitions, 
		///       not from instances. This method is only valid when invoked on a property
		///       collection in a <see cref='System.Management.ManagementClass'/>.</para>
		/// </remarks>
		/// <example>
		///    <code lang='C#'>ManagementClass c = new ManagementClass("MyClass");
		/// c.Properties.Remove("PropThatIDontWantOnThisClass");
		///    </code>
		///    <code lang='VB'>Dim c As New ManagementClass("MyClass")
		/// c.Properties.Remove("PropThatIDontWantOnThisClass")
		///    </code>
		/// </example>
		public virtual void Remove(string propertyName)
		{
			// On instances, reset the property to the default value for the class.
			if (parent.GetType() == typeof(ManagementObject))
			{
				ManagementClass cls = new ManagementClass(parent.ClassPath);
				parent.SetPropertyValue(propertyName, cls.GetPropertyValue(propertyName));
			}
			else
			{
				int status = parent.wbemObject.Delete_(propertyName);
 
				if (status < 0)
				{
					if ((status & 0xfffff000) == 0x80041000)
						ManagementException.ThrowWithExtendedInfo((ManagementStatus)status);
					else
						Marshal.ThrowExceptionForHR(status, WmiNetUtilsHelper.GetErrorInfo_f());
				}
			}
		}
 
		/// <overload>
		/// <para>Adds a new <see cref='System.Management.PropertyData'/> with the specified value.</para>
		/// </overload>
		/// <summary>
		/// <para>Adds a new <see cref='System.Management.PropertyData'/> with the specified value. The value cannot
		///    be null and must be convertable to a CIM type.</para>
		/// </summary>
		/// <param name='propertyName'>The name of the new property.</param>
		/// <param name='propertyValue'>The value of the property (cannot be null).</param>
		/// <remarks>
		///    <para> Properties can only be added to class definitions, not 
		///       to instances. This method is only valid when invoked on a <see cref='System.Management.PropertyDataCollection'/>
		///       in
		///       a <see cref='System.Management.ManagementClass'/>.</para>
		/// </remarks>
		public virtual void Add(string propertyName, Object propertyValue)
		{
			if (null == propertyValue)
				throw new ArgumentNullException("propertyValue");
 
			if (parent.GetType() == typeof(ManagementObject)) //can't add properties to instance
				throw new InvalidOperationException();
 
			CimType cimType = 0;
			bool isArray = false;
			object wmiValue = PropertyData.MapValueToWmiValue(propertyValue, out isArray, out cimType);
			int wmiCimType = (int)cimType;
 
			if (isArray)
				wmiCimType |= (int)tag_CIMTYPE_ENUMERATION.CIM_FLAG_ARRAY;
 
			int status = parent.wbemObject.Put_(propertyName, 0, ref wmiValue, wmiCimType);
 
			if (status < 0)
			{
				if ((status & 0xfffff000) == 0x80041000)
					ManagementException.ThrowWithExtendedInfo((ManagementStatus)status);
				else
					Marshal.ThrowExceptionForHR(status, WmiNetUtilsHelper.GetErrorInfo_f());
			}
		}
 
		/// <summary>
		/// <para>Adds a new <see cref='System.Management.PropertyData'/> with the specified value and CIM type.</para>
		/// </summary>
		/// <param name='propertyName'>The name of the property.</param>
		/// <param name='propertyValue'>The value of the property (which can be null).</param>
		/// <param name='propertyType'>The CIM type of the property.</param>
		/// <remarks>
		///    <para> Properties can only be added to class definitions, not 
		///       to instances. This method is only valid when invoked on a <see cref='System.Management.PropertyDataCollection'/>
		///       in
		///       a <see cref='System.Management.ManagementClass'/>.</para>
		/// </remarks>
		public void Add(string propertyName, Object propertyValue, CimType propertyType)
		{
			if (null == propertyName)
				throw new ArgumentNullException("propertyName");
 
			if (parent.GetType() == typeof(ManagementObject)) //can't add properties to instance
				throw new InvalidOperationException();
 
			int wmiCimType = (int)propertyType;
			bool isArray = false;
 
			if ((null != propertyValue) && propertyValue.GetType().IsArray)
			{
				isArray = true;
				wmiCimType = (wmiCimType | (int)tag_CIMTYPE_ENUMERATION.CIM_FLAG_ARRAY);
			}
 
			object wmiValue = PropertyData.MapValueToWmiValue(propertyValue, propertyType, isArray);
 
			int status = parent.wbemObject.Put_(propertyName, 0, ref wmiValue, wmiCimType);
 
			if (status < 0)
			{
				if ((status & 0xfffff000) == 0x80041000)
					ManagementException.ThrowWithExtendedInfo((ManagementStatus)status);
				else
					Marshal.ThrowExceptionForHR(status, WmiNetUtilsHelper.GetErrorInfo_f());
			}
		}
		
		/// <summary>
		/// <para>Adds a new <see cref='System.Management.PropertyData'/> with no assigned value.</para>
		/// </summary>
		/// <param name='propertyName'>The name of the property.</param>
		/// <param name='propertyType'>The CIM type of the property.</param>
		/// <param name='isArray'><see langword='true'/> to specify that the property is an array type; otherwise, <see langword='false'/>.</param>
		/// <remarks>
		///    <para> Properties can only be added to class definitions, not 
		///       to instances. This method is only valid when invoked on a <see cref='System.Management.PropertyDataCollection'/>
		///       in
		///       a <see cref='System.Management.ManagementClass'/>.</para>
		/// </remarks>
		public void Add(string propertyName, CimType propertyType, bool isArray)
		{
			if (null == propertyName)
				throw new ArgumentNullException(propertyName);
 
			if (parent.GetType() == typeof(ManagementObject)) //can't add properties to instance
				throw new InvalidOperationException();
 
			int wmiCimType = (int)propertyType;  
			
			if (isArray)
				wmiCimType = (wmiCimType | (int)tag_CIMTYPE_ENUMERATION.CIM_FLAG_ARRAY);
 
			object dummyObj = System.DBNull.Value;
 
			int status = parent.wbemObject.Put_(propertyName, 0, ref dummyObj, wmiCimType);
 
			if (status < 0)
			{
				if ((status & 0xfffff000) == 0x80041000)
					ManagementException.ThrowWithExtendedInfo((ManagementStatus)status);
				else
					Marshal.ThrowExceptionForHR(status, WmiNetUtilsHelper.GetErrorInfo_f());
			}
		}
		
	}//PropertyDataCollection
}