ManagementObject.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Wmi / managed / System / Management / ManagementObject.cs / 1305376 / ManagementObject.cs

                            using System.Collections; 
using System.Runtime.InteropServices;
using WbemClient_v1;
using System.ComponentModel;
using System.Runtime.Serialization; 
using System.Globalization;
 
namespace System.Management 
{
    ///  
    /// Delegate definition for the IdentifierChanged event.
    /// This event is used to signal the ManagementObject that an identifying property
    /// has been changed. Identifying properties are the ones that identify the object,
    /// namely the scope, path and options. 
    /// 
    internal delegate void IdentifierChangedEventHandler(object sender, 
                    IdentifierChangedEventArgs e); 

    ///  
    /// Delegate definition for InternalObjectPut event. This is used so that
    /// the WmiEventSink can signal to this object that the async Put call has
    /// completed.
    ///  
    internal delegate void InternalObjectPutEventHandler(object sender,
        InternalObjectPutEventArgs e); 
 

    //CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC// 
    /// 
    ///     Represents a data management object.
    /// 
    ///  
    ///    using System;
    /// using System.Management; 
    /// 
    /// // This example demonstrates reading a property of a ManagementObject.
    /// class Sample_ManagementObject 
    /// {
    ///     public static int Main(string[] args) {
    ///         ManagementObject disk = new ManagementObject(
    ///             "win32_logicaldisk.deviceid=\"c:\""); 
    ///         disk.Get();
    ///         Console.WriteLine("Logical Disk Size = " + disk["Size"] + " bytes"); 
    ///         return 0; 
    ///     }
    /// } 
    ///    
    ///    Imports System
    /// Imports System.Management
    /// 
    /// ' This example demonstrates reading a property of a ManagementObject.
    /// Class Sample_ManagementObject 
    ///     Overloads Public Shared Function Main(args() As String) As Integer 
    ///         Dim disk As New ManagementObject("win32_logicaldisk.deviceid=""c:""")
    ///         disk.Get() 
    ///         Console.WriteLine(("Logical Disk Size = " & disk("Size").ToString() _
    ///             & " bytes"))
    ///         Return 0
    ///     End Function 
    /// End Class
    ///     
    ///  
    //CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC//
    [Serializable] 
    public class ManagementObject : ManagementBaseObject, ICloneable
    {
        // constants
        internal const string ID = "ID"; 
        internal const string RETURNVALUE = "RETURNVALUE";
 
        //Fields 

        private    IWbemClassObjectFreeThreaded    wmiClass; 
        internal ManagementScope                scope;
        internal ManagementPath                    path;
        internal ObjectGetOptions                options;
 
        //Used to represent whether this managementObject is currently bound to a wbemObject
        //or not - whenever an "identifying" property is changed (Path, Scope...) the object 
        //is "detached" (isBound becomes false) so that we refresh the wbemObject next time 
        //it's used, in conformance with the new property values.
        // 
        // ***
        // *    Changed isBound flag to wbemObject==null check.
        // *    private bool isBound;
        // *** 

        //This is used to identify a state in which a Put() operation was performed, but the 
        //object was not retrieved again, so the WMI object that's available at this point 
        //cannot be used for certain operations, namely CreateInstance, GetSubclasses, Derive,
        //Clone & ClassPath. 
        //When these operations are invoked, if we are in this state we need to implicitly
        //get the object...
        private bool putButNotGot;
 
        //Event fired when any "identifying" property changes.
        internal event IdentifierChangedEventHandler IdentifierChanged; 
 
        protected override void GetObjectData(SerializationInfo info, StreamingContext context)
        { 
            base.GetObjectData ( info, context ) ;
        }

        public new void Dispose() 
        {
            if (wmiClass != null) 
            { 
                wmiClass.Dispose();
                wmiClass = null; 
            }
            base.Dispose();
            GC.SuppressFinalize(this);
        } 

        //Fires IdentifierChanged event 
 
        internal void FireIdentifierChanged()
        { 
            if (IdentifierChanged != null)
                IdentifierChanged(this, null);
        }
 
        internal bool PutButNotGot
        { 
            get 
            { return putButNotGot; }
            set 
            { putButNotGot = value; }
        }

        //Called when IdentifierChanged() event fires 
        private void HandleIdentifierChange(object sender,
            IdentifierChangedEventArgs e) 
        { 
            // Detach the object from the WMI object underneath
            // 
            // ***
            // *    Changed isBound flag to wbemObject==null check.
            // *    isBound = false;
            // *** 
            wbemObject = null;
        } 
 
        internal bool IsBound
        { 
            get
            { return _wbemObject != null; }
        }
 
        //internal constructor
        internal static ManagementObject GetManagementObject( 
            IWbemClassObjectFreeThreaded wbemObject, 
            ManagementObject mgObj)
        { 
            ManagementObject newObject = new ManagementObject();
            newObject.wbemObject = wbemObject;

            if (null != mgObj) 
            {
                newObject.scope = ManagementScope._Clone(mgObj.scope); 
 
                if (null != mgObj.path)
                    newObject.path = ManagementPath._Clone(mgObj.path); 

                if (null != mgObj.options)
                    newObject.options = ObjectGetOptions._Clone(mgObj.options);
 
                // We set isBound last since assigning to Scope, Path
                // or Options can trigger isBound to be set false. 
                // 
                // ***
                // *    Changed isBound flag to wbemObject==null check. 
                // *    newObject.isBound = mgObj.isBound;
                // ***
            }
 
            return newObject;
        } 
 
        internal static ManagementObject GetManagementObject(
            IWbemClassObjectFreeThreaded wbemObject, 
            ManagementScope scope)
        {
            ManagementObject newObject = new ManagementObject();
            newObject.wbemObject = wbemObject; 

            newObject.path = new ManagementPath(ManagementPath.GetManagementPath(wbemObject)); 
            newObject.path.IdentifierChanged += new IdentifierChangedEventHandler(newObject.HandleIdentifierChange); 

            newObject.scope = ManagementScope._Clone(scope, new IdentifierChangedEventHandler(newObject.HandleIdentifierChange)); 

            // Since we have an object, we should mark it as bound. Note
            // that we do this AFTER setting Scope and Path, since those
            // have side-effects of setting isBound=false. 
            //
            // *** 
            // *    Changed isBound flag to wbemObject==null check. 
            // *    newObject.isBound = true;
            // *** 

            return newObject;
        }
 
        //default constructor
        ///  
        ///    Initializes a new instance of the  class. 
        /// 
        ///  
        /// Initializes a new instance of the  class. This is the
        ///    default constructor.
        /// 
        ///  
        ///    ManagementObject o = new ManagementObject();
        /// 
        /// //Now set the path on this object to bind it to a 'real' manageable entity 
        /// o.Path = new ManagementPath("Win32_LogicalDisk='c:'");
        /// 
        /// //Now it can be used
        /// Console.WriteLine(o["FreeSpace"]);
        ///    
        ///    Dim o As New ManagementObject() 
        /// Dim mp As New ManagementPath("Win32_LogicalDisk='c:'")
        /// 
        /// 'Now set the path on this object to bind it to a 'real' manageable entity 
        /// o.Path = mp
        /// 
        /// 'Now it can be used
        /// Console.WriteLine(o("FreeSpace"))
        ///    
        ///  
        public ManagementObject() : this ((ManagementScope)null, null, null) {}
 
        //parameterized constructors 
        /// 
        /// Initializes a new instance of the  class for the specified WMI 
        ///    object path. The path is provided as a .
        /// 
        /// A  that contains a path to a WMI object.
        ///  
        ///    ManagementPath p = new ManagementPath("Win32_Service.Name='Alerter'");
        /// ManagementObject o = new ManagementObject(p); 
        ///     
        ///    Dim p As New ManagementPath("Win32_Service.Name=""Alerter""")
        /// Dim o As New ManagementObject(p) 
        ///    
        /// 
        public ManagementObject(ManagementPath path) : this(null, path, null) {}
 
        /// 
        /// Initializes a new instance of the  class for the specified WMI object path. The path 
        ///    is provided as a string. 
        /// 
        /// A WMI path. 
        /// 
        ///    If the specified path is a relative path only (a server
        ///       or namespace is not specified), the default path is the local machine, and the
        ///       default namespace is the  
        ///       path (by default, root\cimv2). If the user specifies a
        ///       full path, the default settings are overridden. 
        ///  
        /// 
        ///    ManagementObject o = new ManagementObject("Win32_Service.Name='Alerter'"); 
        ///
        /// //or with a full path :
        ///
        /// ManagementObject o = new ManagementObject("\\\\MyServer\\root\\MyApp:MyClass.Key='abc'"); 
        ///    
        ///    Dim o As New ManagementObject("Win32_Service.Name=""Alerter""") 
        /// 
        /// //or with a full path :
        /// 
        /// Dim o As New ManagementObject("\\\\MyServer\\root\\MyApp:MyClass.Key=""abc""");
        ///    
        /// 
        public ManagementObject(string path) : this(null, new ManagementPath(path), null) {} 

        ///  
        /// Initializes a new instance of the  class bound to the specified 
        ///    WMI path, including the specified additional options.
        ///  
        /// A  containing the WMI path.
        /// An  containing additional options for binding to the WMI object. This parameter could be null if default options are to be used.
        /// 
        ///    ManagementPath p = new ManagementPath("Win32_ComputerSystem.Name='MyMachine'"); 
        ///
        /// //Set options for no context info, but requests amended qualifiers 
        /// //to be contained in the object 
        /// ObjectGetOptions opt = new ObjectGetOptions(null, true);
        /// 
        /// ManagementObject o = new ManagementObject(p, opt);
        ///
        /// Console.WriteLine(o.GetQualifierValue("Description"));
        ///     
        ///    Dim p As New ManagementPath("Win32_ComputerSystem.Name=""MyMachine""")
        /// 
        /// 'Set options for no context info, but requests amended qualifiers 
        /// 'to be contained in the object
        /// Dim opt As New ObjectGetOptions(null, true) 
        ///
        /// Dim o As New ManagementObject(p, opt)
        ///
        /// Console.WriteLine(o.GetQualifierValue("Description")); 
        ///    
        ///  
        public ManagementObject(ManagementPath path, ObjectGetOptions options) : this(null, path, options) {} 

        ///  
        /// Initializes a new instance of the  class bound to the specified WMI path, including the
        ///    specified additional options. In this variant, the path can be specified as a
        ///    string.
        ///  
        /// The WMI path to the object.
        /// An  representing options to get the specified WMI object. 
        ///  
        ///    //Set options for no context info,
        /// //but requests amended qualifiers to be contained in the object 
        /// ObjectGetOptions opt = new ObjectGetOptions(null, true);
        ///
        /// ManagementObject o = new ManagementObject("Win32_ComputerSystem.Name='MyMachine'", opt);
        /// 
        /// Console.WriteLine(o.GetQualifierValue("Description"));
        ///     
        ///    'Set options for no context info, 
        /// 'but requests amended qualifiers to be contained in the object
        /// Dim opt As New ObjectGetOptions(null, true) 
        ///
        /// Dim o As New ManagementObject("Win32_ComputerSystem.Name=""MyMachine""", opt);
        ///
        /// Console.WriteLine(o.GetQualifierValue("Description")) 
        ///    
        ///  
        public ManagementObject(string path, ObjectGetOptions options) : 
            this(new ManagementPath(path), options) {}
 
        /// 
        ///  Initializes a new instance of the 
        /// class bound to the specified WMI path that includes the specified options.
        ///  
        /// A  representing the scope in which the WMI object resides. In this version, scopes can only be WMI namespaces.
        /// A  representing the WMI path to the manageable object. 
        /// An  specifying additional options for getting the object. 
        /// 
        ///     Because WMI paths can be relative or full, a conflict between the scope and the path 
        ///       specified may arise. However, if a scope is specified and
        ///       a relative WMI path is specified, then there is no conflict. The
        ///       following are some possible conflicts: 
        ///     If a scope is not specified and a relative WMI 
        ///       path is specified, then the scope will default to the local machine's . 
        ///     If a scope is not specified and a full WMI path is 
        ///       specified, then the scope will be inferred from the scope portion of the full 
        ///       path. For example, the full WMI path: \\MyMachine\root\MyNamespace:MyClass.Name='abc' will
        ///    represent the WMI object 'MyClass.Name='abc'" in the scope 
        ///    '\\MyMachine\root\MyNamespace'. 
        /// If a scope is specified and a full WMI path is specified, then the scope
        /// will override the scope portion of the full path. For example, if the following
        /// scope was specified: \\MyMachine\root\MyScope, and the following full path was 
        /// specified: \\MyMachine\root\MyNamespace:MyClass.Name='abc', then look for the
        /// following object: 
        /// \\MyMachine\root\MyScope:MyClass.Name= 
        /// 'abc'
        /// (the scope part of the full path is ignored). 
        /// 
        /// 
        ///    ManagementScope s = new ManagementScope("\\\\MyMachine\\root\\cimv2");
        /// ManagementPath p = new ManagementPath("Win32_LogicalDisk.Name='c:'"); 
        /// ManagementObject o = new ManagementObject(s,p);
        ///     
        ///    Dim s As New ManagementScope("\\MyMachine\root\cimv2"); 
        /// Dim p As New ManagementPath("Win32_LogicalDisk.Name=""c:""");
        /// Dim o As New ManagementObject(s,p); 
        ///    
        /// 
        public ManagementObject(ManagementScope scope, ManagementPath path, ObjectGetOptions options)
            : base (null) 
        {
            ManagementObjectCTOR(scope, path, options); 
        } 

        void ManagementObjectCTOR(ManagementScope scope, ManagementPath path, ObjectGetOptions options) 
        {
            // We may use this to set the scope path
            string nsPath = String.Empty;
 
            if ((null != path) && !path.IsEmpty)
            { 
                //If this is a ManagementObject then the path has to be an instance, 
                // and if this is a ManagementClass the path has to be a class.
                if (GetType() == typeof(ManagementObject) && path.IsClass) 
                    throw new ArgumentOutOfRangeException("path");
                else if (GetType() == typeof(ManagementClass) && path.IsInstance)
                    throw new ArgumentOutOfRangeException("path");
 
                // Save the namespace path portion of the path (if any) in case
                // we don't have a scope 
                nsPath = path.GetNamespacePath((int)tag_WBEM_GET_TEXT_FLAGS.WBEMPATH_GET_SERVER_AND_NAMESPACE_ONLY); 

                if ((null != scope) && (scope.Path.NamespacePath.Length>0)) 
                {
                    // If the scope has a path too, the namespace portion of
                    // scope.path takes precedence over what is specified in path
                    path = new ManagementPath(path.RelativePath); 
                    path.NamespacePath = scope.Path.GetNamespacePath((int)tag_WBEM_GET_TEXT_FLAGS.WBEMPATH_GET_SERVER_AND_NAMESPACE_ONLY);
                } 
 
                // If the supplied path is a class or instance use it, otherwise
                // leave it empty 
                if (path.IsClass || path.IsInstance)
                    this.path = ManagementPath._Clone(path, new IdentifierChangedEventHandler(HandleIdentifierChange));

                else 
                    this.path = ManagementPath._Clone(null, new IdentifierChangedEventHandler(HandleIdentifierChange));
            } 
 
            if (null != options)
                this.options = ObjectGetOptions._Clone(options, new IdentifierChangedEventHandler(HandleIdentifierChange)); 

            if (null != scope)
                this.scope = ManagementScope._Clone(scope, new IdentifierChangedEventHandler(HandleIdentifierChange));
            else 
            {
                // Use the path if possible, otherwise let it default 
                if (nsPath.Length>0) 
                {
                    this.scope = new ManagementScope(nsPath); 
                    this.scope.IdentifierChanged += new IdentifierChangedEventHandler(HandleIdentifierChange);
                }
            }
 
            //register for identifier change events
            IdentifierChanged += new IdentifierChangedEventHandler(HandleIdentifierChange); 
            // *** 
            // *    Changed isBound flag to wbemObject==null check.
            // *    isBound = false; 
            // ***
            putButNotGot = false;

        } 

        ///  
        ///  Initializes a new instance of the  class 
        ///    bound to the specified WMI path, and includes the specified options. The scope and
        ///    the path are specified as strings. 
        /// 
        /// The scope for the WMI object.
        /// The WMI object path.
        /// An  representing additional options for getting the WMI object. 
        /// 
        ///    See the equivalent overload for details. 
        ///  
        /// 
        ///    GetObjectOptions opt = new GetObjectOptions(null, true); 
        /// ManagementObject o = new ManagementObject("root\\MyNamespace", "MyClass.Name='abc'", opt);
        ///    
        ///    Dim opt As New GetObjectOptions(null, true)
        /// Dim o As New ManagementObject("root\MyNamespace", "MyClass.Name=""abc""", opt); 
        ///    
        ///  
        public ManagementObject(string scopeString, string pathString, ObjectGetOptions options) 
            : this(new ManagementScope(scopeString), new ManagementPath(pathString), options) {}
 
        /// 
        /// Initializes a new instance of the  class that is serializable.
        /// 
        /// The  to populate with data. 
    /// The destination (see  ) for this serialization.
        protected ManagementObject(SerializationInfo info, StreamingContext context) : base(info, context) 
        { 
            ManagementObjectCTOR(null, null, null);
        } 

        /// 
        ///     Gets or sets the scope in which this object resides.
        ///  
        /// 
        ///  A . 
        ///  
        /// 
        ///     
        ///       Changing
        ///       this property after the management object has been bound to a WMI object in
        ///       a particular namespace results in releasing the original WMI object. This causes the management object to
        ///       be rebound to the new object specified by the new path properties and scope 
        ///       values. 
        ///    The rebinding is performed in a "lazy" manner, that is, only when a requested 
        ///       value requires the management object to be bound to the WMI object. Changes can 
        ///       be made to more than just this property before attempting to rebind (for example, modifying the scope
        ///       and path properties simultaneously). 
        /// 
        /// 
        ///    //Create the object with the default namespace (root\cimv2)
        /// ManagementObject o = new ManagementObject(); 
        ///
        /// //Change the scope (=namespace) of this object to the one specified. 
        /// o.Scope = new ManagementScope("root\\MyAppNamespace"); 
        ///    
        ///    'Create the object with the default namespace (root\cimv2) 
        /// Dim o As New ManagementObject()
        ///
        /// 'Change the scope (=namespace) of this object to the one specified.
        /// o.Scope = New ManagementScope("root\MyAppNamespace") 
        ///    
        ///  
        public ManagementScope Scope 
        {
            get 
            {
                if (scope == null)
                    return scope = ManagementScope._Clone(null);
                else 
                    return scope;
            } 
            set 
            {
                if (null != value) 
                {
                    if (null != scope)
                        scope.IdentifierChanged -= new IdentifierChangedEventHandler(HandleIdentifierChange);
 
                    scope = ManagementScope._Clone((ManagementScope)value, new IdentifierChangedEventHandler(HandleIdentifierChange));
 
                    //the scope property has changed so fire event 
                    FireIdentifierChanged();
                } 
                else
                    throw new ArgumentNullException("value");
            }
        } 

        ///  
        ///     Gets or sets the object's WMI path. 
        /// 
        ///  
        /// A  representing the object's path.
        /// 
        /// 
        ///     
        ///       Changing the property after the management
        ///       object has been bound to a WMI object in a particular namespace results in releasing 
        ///       the original WMI object. This causes the management object to be rebound to 
        ///       the new object specified by the new path properties and scope values.
        ///    The rebinding is performed in a "lazy" manner, that is, only when a requested 
        ///       value requires the management object to be bound to the WMI object. Changes can
        ///       be made to more than just the property before attempting to rebind (for example,
        ///       modifying the scope and path properties simultaneously).
        ///  
        /// 
        ///    ManagementObject o = new ManagementObject(); 
        /// 
        /// //Specify the WMI path to which this object should be bound to
        /// o.Path = new ManagementPath("MyClass.Name='MyName'"); 
        ///    
        ///    Dim o As New ManagementObject()
        ///
        /// 'Specify the WMI path to which this object should be bound to 
        /// o.Path = New ManagementPath("MyClass.Name=""MyName""");
        ///     
        ///  
        public virtual ManagementPath Path
        { 
            get
            {
                if (path == null)
                    return path = ManagementPath._Clone(null); 
                else
                    return path; 
            } 
            set
            { 
                ManagementPath newPath = (null != value) ? value : new ManagementPath();

                //If the new path contains a namespace path and the scope is currently defaulted,
                //we want to set the scope to the new namespace path provided 
                string nsPath = newPath.GetNamespacePath((int)tag_WBEM_GET_TEXT_FLAGS.WBEMPATH_GET_SERVER_AND_NAMESPACE_ONLY);
                if ((nsPath.Length > 0) && (scope != null) && (scope.IsDefaulted)) 
                    Scope = new ManagementScope(nsPath); 

                // This must be a class for a ManagementClass object or an instance for a ManagementObject, or empty 
                if ((GetType() == typeof(ManagementObject) && newPath.IsInstance) ||
                    (GetType() == typeof(ManagementClass) && newPath.IsClass) ||
                    newPath.IsEmpty)
                { 
                    if (null != path)
                        path.IdentifierChanged -=  new IdentifierChangedEventHandler(HandleIdentifierChange); 
 
                    path = ManagementPath._Clone((ManagementPath)value, new IdentifierChangedEventHandler(HandleIdentifierChange));
 
                    //the path property has changed so fire event
                    FireIdentifierChanged();
                }
                else 
                    throw new ArgumentOutOfRangeException("value");
            } 
        } 

        ///  
        ///    
        ///       Gets or
        ///       sets additional information to use when retrieving the object.
        ///  
        /// 
        /// An  to use when retrieving the object. 
        ///  
        /// 
        ///     When the property is 
        ///       changed after the management object has been bound to a WMI object, the management object
        ///       is disconnected from the original WMI object and later rebound using the new
        ///       options.
        ///  
        /// 
        ///    //Contains default options 
        /// ManagementObject o = new ManagementObject("MyClass.Name='abc'"); 
        ///
        /// //Replace default options, in this case requesting retrieval of 
        /// //amended qualifiers along with the WMI object.
        /// o.Options = new ObjectGetOptions(null, true);
        ///    
        ///    'Contains default options 
        /// Dim o As New ManagementObject("MyClass.Name=""abc""")
        /// 
        /// 'Replace default options, in this case requesting retrieval of 
        /// 'amended qualifiers along with the WMI object.
        /// o.Options = New ObjectGetOptions(null, true) 
        ///    
        /// 
        public ObjectGetOptions Options
        { 
            get
            { 
                if (options == null) 
                    return options = ObjectGetOptions._Clone(null);
                else 
                    return options;
            }
            set
            { 
                if (null != value)
                { 
                    if (null != options) 
                        options.IdentifierChanged -= new IdentifierChangedEventHandler(HandleIdentifierChange);
 
                    options = ObjectGetOptions._Clone((ObjectGetOptions)value, new IdentifierChangedEventHandler(HandleIdentifierChange));

                    //the options property has changed so fire event
                    FireIdentifierChanged(); 
                }
                else 
                    throw new ArgumentNullException("value"); 
            }
        } 

        /// 
        ///    Gets or sets the path to the object's class.
        ///  
        /// 
        /// A  representing the path to the object's 
        ///    class. 
        /// 
        ///  
        ///    This property is read-only.
        /// 
        /// 
        ///    ManagementObject o = new ManagementObject("MyClass.Name='abc'"); 
        ///
        /// //Get the class definition for the object above. 
        /// ManagementClass c = new ManagementClass(o.ClassPath); 
        ///    
        ///    Dim o As New ManagementObject("MyClass.Name=""abc""") 
        ///
        /// 'Get the class definition for the object above.
        /// Dim c As New ManagementClass(o.ClassPath);
        ///     
        /// 
        public override ManagementPath ClassPath 
        { 
            get
            { 
                Object serverName = null;
                Object scopeName = null;
                Object className = null;
                int propertyType = 0; 
                int propertyFlavor = 0;
 
                if (PutButNotGot) 
                {
                    Get(); 
                    PutButNotGot = false;
                }

                // 
                // Removed Initialize call since wbemObject is a property that will call Initialize ( true ) on
                // its getter. 
                // 
                // Initialize ( ) ;
 
                int status = wbemObject.Get_("__SERVER", 0, ref serverName, ref propertyType, ref propertyFlavor);

                if (status >= 0)
                { 
                    status = wbemObject.Get_("__NAMESPACE", 0, ref scopeName, ref propertyType, ref propertyFlavor);
 
                    if (status >= 0) 
                    {
                        status = wbemObject.Get_("__CLASS", 0, ref className, ref propertyType, ref propertyFlavor); 
                    }
                }

                if (status < 0) 
                {
                    if ((status & 0xfffff000) == 0x80041000) 
                        ManagementException.ThrowWithExtendedInfo((ManagementStatus)status); 
                    else
                        Marshal.ThrowExceptionForHR(status); 
                }

                ManagementPath classPath = new ManagementPath();
 
                // initialize in case of throw
                classPath.Server = String.Empty; 
                classPath.NamespacePath = String.Empty; 
                classPath.ClassName = String.Empty;
 				 
                // Some of these may throw if they are NULL
                try
                {
                    classPath.Server = (string)(serverName is System.DBNull ? "" : serverName); 
                    classPath.NamespacePath = (string)(scopeName is System.DBNull ? "" : scopeName);
                    classPath.ClassName = (string)(className is System.DBNull ? "" : className); 
                } 
                catch
                { 
                }

                return classPath;
            } 
        }
 
        // 
        //Methods
        // 

        //******************************************************
        //Get
        //***************************************************** 
        /// 
        ///    Binds to the management object. 
        ///  
        /// 
        ///     Binds to the management object. 
        /// 
        /// 
        ///     The method is implicitly
        ///       invoked at the first attempt to get or set information to the WMI object. It 
        ///       can also be explicitly invoked at the user's discretion, to better control the
        ///       timing and manner of retrieval. 
        ///  
        /// 
        ///    ManagementObject o = new ManagementObject("MyClass.Name='abc'"); 
        /// string s = o["SomeProperty"]; //this causes an implicit Get().
        ///
        /// //or :
        /// 
        /// ManagementObject o= new ManagementObject("MyClass.Name= 'abc'");
        /// o.Get(); //explicitly 
        /// //Now it's faster because the object has already been retrieved. 
        /// string s = o["SomeProperty"];
        ///     
        ///    Dim o As New ManagementObject("MyClass.Name=""abc""")
        /// string s = o("SomeProperty") 'this causes an implicit Get().
        ///
        /// 'or : 
        ///
        /// Dim o As New ManagementObject("MyClass.Name= ""abc""") 
        /// o.Get()  'explicitly 
        /// 'Now it's faster because the object has already been retrieved.
        /// string s = o("SomeProperty"); 
        ///    
        /// 
        public void Get()
        { 
            IWbemClassObjectFreeThreaded tempObj = null;
 
            Initialize ( false ) ; // this may throw 

            if ((null == path) || (path.Path.Length==0)) 
                throw new InvalidOperationException();
            else
            {
                ObjectGetOptions gOptions = 
                    (null == options) ? new ObjectGetOptions() : options;
 
                SecurityHandler securityHandler = null; 
                int status                        = (int)ManagementStatus.NoError;
 
                try
                {
                    securityHandler = scope.GetSecurityHandler();
 
                    status = scope.GetSecuredIWbemServicesHandler( scope.GetIWbemServices() ).GetObject_(path.RelativePath,
                                                            gOptions.Flags, 
                                                            gOptions.GetContext(), 
                                                            ref tempObj,
                                                            IntPtr.Zero ); 

                    if (status < 0)
                    {
                        if ((status & 0xfffff000) == 0x80041000) 
                            ManagementException.ThrowWithExtendedInfo((ManagementStatus)status);
                        else 
                            Marshal.ThrowExceptionForHR(status); 
                    }
 
                    wbemObject = tempObj;
                }
                finally
                { 
                    if (securityHandler != null)
                        securityHandler.Reset(); 
                } 
            }
        } 

        //*****************************************************
        //Get
        //***************************************************** 
        /// 
        ///     Binds to the management object asynchronously. 
        ///  
        /// The object to receive the results of the operation as events.
        ///  
        ///    The method will issue the request to get the object
        ///       and then will immediately return. The results of the operation will then be
        ///       delivered through events being fired on the watcher object provided.
        ///  
        /// 
        ///    ManagementObject o = new ManagementObject("MyClass.Name='abc'"); 
        /// 
        /// //Set up handlers for asynchronous get
        /// MyHandler h = new MyHandler(); 
        /// ManagementOperationObserver ob = new ManagementOperationObserver();
        /// ob.Completed += new CompletedEventHandler(h.Done);
        ///
        /// //Get the object asynchronously 
        /// o.Get(ob);
        /// 
        /// //Wait until operation is completed 
        /// while (!h.Completed)
        ///     System.Threading.Thread.Sleep (1000); 
        ///
        /// //Here we can use the object
        /// Console.WriteLine(o["SomeProperty"]);
        /// 
        /// public class MyHandler
        /// { 
        ///     private bool completed = false; 
        ///
        ///     public void Done(object sender, CompletedEventArgs e) { 
        ///         Console.WriteLine("async Get completed !");
        ///         completed = true;
        ///     }
        /// 
        ///     public bool Completed {
        ///         get { 
        ///             return completed; 
        ///         }
        ///     } 
        /// }
        ///    
        ///    Dim o As New ManagementObject("MyClass.Name=""abc""")
        /// 
        /// 'Set up handlers for asynchronous get
        /// Dim h As New MyHandler() 
        /// Dim ob As New ManagementOperationObserver() 
        /// ob.Completed += New CompletedEventHandler(h.Done)
        /// 
        /// 'Get the object asynchronously
        /// o.Get(ob)
        ///
        /// 'Wait until operation is completed 
        /// While Not h.Completed
        ///     System.Threading.Thread.Sleep(1000) 
        /// End While 
        ///
        /// 'Here we can use the object 
        /// Console.WriteLine(o("SomeProperty"))
        ///
        /// Public Class MyHandler
        ///     Private _completed As Boolean = false; 
        ///
        ///     Public Sub Done(sender As Object, e As EventArrivedEventArgs) 
        ///         Console.WriteLine("async Get completed !") 
        ///         _completed = True
        ///     End Sub 
        ///
        ///     Public ReadOnly Property Completed() As Boolean
        ///        Get
        ///            Return _completed 
        ///        End Get
        ///     End Property 
        /// End Class 
        ///    
        ///  
        public void Get(ManagementOperationObserver watcher)
        {
            Initialize ( false ) ;
 
            if ((null == path) || (path.Path.Length==0))
                throw new InvalidOperationException(); 
            else if (null == watcher) 
                throw new ArgumentNullException("watcher");
            else 
            {
                IWbemServices wbemServices = scope.GetIWbemServices();

                ObjectGetOptions o = ObjectGetOptions._Clone(options); 

                WmiGetEventSink sink = watcher.GetNewGetSink( 
                    scope, 
                    o.Context,
                    this); 

                // If someone has registered for progress, make sure we flag it
                if (watcher.HaveListenersForProgress)
                    o.SendStatus = true; 

                SecurityHandler securityHandler = null; 
                int status                        = (int)ManagementStatus.NoError; 

                securityHandler = scope.GetSecurityHandler(); 

                status = scope.GetSecuredIWbemServicesHandler(wbemServices).GetObjectAsync_(path.RelativePath,
                                            o.Flags,
                                            o.GetContext(), 
                                            sink.Stub);
 
 
                if (securityHandler != null)
                    securityHandler.Reset(); 

                if (status < 0)
                {
                    watcher.RemoveSink(sink); 
                    if ((status & 0xfffff000) == 0x80041000)
                        ManagementException.ThrowWithExtendedInfo((ManagementStatus)status); 
                    else 
                        Marshal.ThrowExceptionForHR(status);
                } 
            }
        }

        //****************************************************** 
        //GetRelated
        //*************************************************** 
        ///  
        ///    Gets a collection of objects related to the object (associators).
        ///  
        /// 
        ///    Gets a collection of objects related to the object (associators).
        /// 
        ///  
        /// A  containing the
        ///    related objects. 
        ///  
        /// 
        ///     The operation is equivalent to an ASSOCIATORS OF query where ResultClass = relatedClass. 
        /// 
        /// 
        ///    ManagementObject o = new ManagementObject("Win32_Service='Alerter'");
        /// foreach(ManagementBaseObject b in o.GetRelated()) 
        ///     Console.WriteLine("Object related to Alerter service : ", b.Path);
        ///     
        ///    Dim o As New ManagementObject("Win32_Service=""Alerter""") 
        /// Dim b As ManagementBaseObject
        /// For Each b In o.GetRelated() 
        ///     Console.WriteLine("Object related to Alerter service : ", b.Path)
        /// Next b
        ///    
        ///  
        public ManagementObjectCollection GetRelated()
        { 
            return GetRelated((string)null); 
        }
 
        //******************************************************
        //GetRelated
        //****************************************************
        ///  
        ///    Gets a collection of objects related to the object (associators).
        ///  
        /// A class of related objects.  
        /// 
        ///    A  containing the related objects. 
        /// 
        /// 
        ///    ManagementObject o = new ManagementObject("Win32_Service='Alerter'");
        /// foreach (ManagementBaseObject b in o.GetRelated("Win32_Service") 
        ///     Console.WriteLine("Service related to the Alerter service {0} is {1}", b["Name"], b["State"]);
        ///     
        ///    Dim o As New ManagementObject("Win32_Service=""Alerter"""); 
        /// Dim b As ManagementBaseObject
        /// For Each b in o.GetRelated("Win32_Service") 
        ///     Console.WriteLine("Service related to the Alerter service {0} is {1}", b("Name"), b("State"))
        /// Next b
        ///    
        ///  
        public ManagementObjectCollection GetRelated(
            string relatedClass) 
        { 
            return GetRelated(relatedClass, null, null, null, null, null, false, null);
        } 


        //*****************************************************
        //GetRelated 
        //****************************************************
        ///  
        ///    Gets a collection of objects related to the object (associators). 
        /// 
        /// The class of the related objects.  
        /// The relationship class of interest. 
        /// The qualifier required to be present on the relationship class. 
        /// The qualifier required to be present on the related class. 
        /// The role that the related class is playing in the relationship.  
        /// The role that this class is playing in the relationship. 
        /// When this method returns, it contains only class definitions for the instances that match the query.  
        /// Extended options for how to execute the query.  
        /// 
        ///    A  containing the related objects. 
        /// 
        /// 
        ///    This operation is equivalent to an ASSOCIATORS OF query where ResultClass = <relatedClass>.
        ///  
        public ManagementObjectCollection GetRelated(
            string relatedClass, 
            string relationshipClass, 
            string relationshipQualifier,
            string relatedQualifier, 
            string relatedRole,
            string thisRole,
            bool classDefinitionsOnly,
            EnumerationOptions options) 
        {
            if ((null == path) || (path.Path.Length==0)) 
                throw new InvalidOperationException(); 

            Initialize ( false ) ; 

            IEnumWbemClassObject enumWbem = null;
            EnumerationOptions o = (null != options) ? options : new EnumerationOptions();
            RelatedObjectQuery q = new RelatedObjectQuery( 
                path.Path,
                relatedClass, 
                relationshipClass, 
                relationshipQualifier,
                relatedQualifier, relatedRole, 
                thisRole, classDefinitionsOnly);


            //Make sure the EnumerateDeep flag bit is turned off because it's invalid for queries 
            o.EnumerateDeep = true; //note this turns the FLAG to 0 !!
 
            SecurityHandler securityHandler = null; 
            int status                        = (int)ManagementStatus.NoError;
 
            try
            {
                securityHandler = scope.GetSecurityHandler();
 
                status = scope.GetSecuredIWbemServicesHandler(scope.GetIWbemServices() ).ExecQuery_(
                                                        q.QueryLanguage, 
                                                        q.QueryString, 
                                                        o.Flags,
                                                        o.GetContext(), 
                                                        ref enumWbem);


                if (status < 0) 
                {
                    if ((status & 0xfffff000) == 0x80041000) 
                        ManagementException.ThrowWithExtendedInfo((ManagementStatus)status); 
                    else
                        Marshal.ThrowExceptionForHR(status); 
                }

            }
            finally 
            {
                if (securityHandler != null) 
                    securityHandler.Reset(); 
            }
 
            //Create collection object
            return new ManagementObjectCollection(scope, o, enumWbem);
        }
 

        //***************************************************** 
        //GetRelated 
        //***************************************************
        ///  
        ///     Gets a collection of objects
        ///       related to the object (associators) asynchronously. This call returns immediately, and a
        ///       delegate is called when the results are available.
        ///  
        /// The object to use to return results. 
        public void GetRelated( 
            ManagementOperationObserver watcher) 
        {
            GetRelated(watcher, (string)null); 
        }

        //*****************************************************
        //GetRelated 
        //****************************************************
        ///  
        ///    Gets a collection of objects related to the object (associators). 
        /// 
        /// The object to use to return results.  
        /// The class of related objects. 
        /// 
        ///    This operation is equivalent to an ASSOCIATORS OF query where ResultClass = <relatedClass>.
        ///  
        public void GetRelated(
            ManagementOperationObserver watcher, 
            string relatedClass) 
        {
            GetRelated(watcher, relatedClass, null, null, null, null, null, false, null); 
        }


        //***************************************************** 
        //GetRelated
        //**************************************************** 
        ///  
        ///    Gets a collection of objects related to the object (associators).
        ///  
        /// The object to use to return results. 
        /// The class of the related objects. 
        /// The relationship class of interest. 
        /// The qualifier required to be present on the relationship class.  
        /// The qualifier required to be present on the related class. 
        /// The role that the related class is playing in the relationship.  
        /// The role that this class is playing in the relationship.  
        /// Return only class definitions for the instances that match the query. 
        /// Extended options for how to execute the query. 
        /// 
        ///    This operation is equivalent to an ASSOCIATORS OF query where ResultClass = <relatedClass>.
        /// 
        public void GetRelated( 
            ManagementOperationObserver watcher,
            string relatedClass, 
            string relationshipClass, 
            string relationshipQualifier,
            string relatedQualifier, 
            string relatedRole,
            string thisRole,
            bool classDefinitionsOnly,
            EnumerationOptions options) 
        {
            if ((null == path) || (path.Path.Length==0)) 
                throw new InvalidOperationException(); 

            Initialize ( true ) ; 

            if (null == watcher)
                throw new ArgumentNullException("watcher");
            else 
            {
                // Ensure we switch off ReturnImmediately as this is invalid for async calls 
                EnumerationOptions o = (null != options) 
                    ? (EnumerationOptions)options.Clone() : new EnumerationOptions();
                o.ReturnImmediately = false; 

                // If someone has registered for progress, make sure we flag it
                if (watcher.HaveListenersForProgress)
                    o.SendStatus = true; 

                WmiEventSink sink = watcher.GetNewSink( 
                    scope, 
                    o.Context);
 
                RelatedObjectQuery q = new RelatedObjectQuery(path.Path, relatedClass,
                    relationshipClass, relationshipQualifier,
                    relatedQualifier, relatedRole,
                    thisRole, classDefinitionsOnly); 

 
                //Make sure the EnumerateDeep flag bit is turned off because it's invalid for queries 
                o.EnumerateDeep = true; //note this turns the FLAG to 0 !!
 
                SecurityHandler securityHandler    = null;
                int status                        = (int)ManagementStatus.NoError;

                securityHandler = scope.GetSecurityHandler(); 

                status = scope.GetSecuredIWbemServicesHandler( scope.GetIWbemServices() ).ExecQueryAsync_( 
                                                        q.QueryLanguage, 
                                                        q.QueryString,
                                                        o.Flags, 
                                                        o.GetContext(),
                                                        sink.Stub);

 
                securityHandler.Reset();
 
                if (status < 0) 
                {
                    watcher.RemoveSink(sink); 
                    if ((status & 0xfffff000) == 0x80041000)
                        ManagementException.ThrowWithExtendedInfo((ManagementStatus)status);
                    else
                        Marshal.ThrowExceptionForHR(status); 
                }
            } 
        } 

        //******************************************************************** 
        //GetRelationships
        //*******************************************************************
        /// 
        ///    Gets a collection of associations to the object. 
        /// 
        ///  
        ///    Gets a collection of associations to the object. 
        /// 
        ///  
        /// A  containing the association objects.
        /// 
        /// 
        ///     The operation is equivalent to a REFERENCES OF query. 
        /// 
        public ManagementObjectCollection GetRelationships() 
        { 
            return GetRelationships((string)null);
        } 

        //********************************************************************
        //GetRelationships
        //******************************************************************* 
        /// 
        ///    Gets a collection of associations to the object. 
        ///  
        /// The associations to include. 
        ///  
        ///    A  containing the association objects.
        /// 
        /// 
        ///    This operation is equivalent to a REFERENCES OF query where the AssocClass = <relationshipClass>. 
        /// 
        public ManagementObjectCollection GetRelationships( 
            string relationshipClass) 
        {
            return GetRelationships(relationshipClass, null, null, false, null); 
        }


        //******************************************************************* 
        //GetRelationships
        //******************************************************************* 
        ///  
        ///    Gets a collection of associations to the object.
        ///  
        /// The type of relationship of interest. 
        /// The qualifier to be present on the relationship. 
        /// The role of this object in the relationship. 
        /// When this method returns, it contains only the class definitions for the result set.  
        /// The extended options for the query execution. 
        ///  
        ///    A  containing the association objects. 
        /// 
        ///  
        ///    This operation is equivalent to a REFERENCES OF query with possibly all the extensions.
        /// 
        public ManagementObjectCollection GetRelationships(
            string relationshipClass, 
            string relationshipQualifier,
            string thisRole, 
            bool classDefinitionsOnly, 
            EnumerationOptions options)
        { 
            if ((null == path) || (path.Path.Length==0))
                throw new InvalidOperationException();

            Initialize ( false ) ; 

            IEnumWbemClassObject enumWbem = null; 
            EnumerationOptions o = 
                (null != options) ? options : new EnumerationOptions();
            RelationshipQuery q = new RelationshipQuery(path.Path, relationshipClass, 
                relationshipQualifier, thisRole, classDefinitionsOnly);


            //Make sure the EnumerateDeep flag bit is turned off because it's invalid for queries 
            o.EnumerateDeep = true; //note this turns the FLAG to 0 !!
 
            SecurityHandler securityHandler = null; 
            int status                        = (int)ManagementStatus.NoError;
 
            try
            {
                securityHandler = scope.GetSecurityHandler();
 
                status = scope.GetSecuredIWbemServicesHandler(scope.GetIWbemServices()).ExecQuery_(
                                                    q.QueryLanguage, 
                                                    q.QueryString, 
                                                    o.Flags,
                                                    o.GetContext(), 
                                                    ref enumWbem );


                if (status < 0) 
                {
                    if ((status & 0xfffff000) == 0x80041000) 
                        ManagementException.ThrowWithExtendedInfo((ManagementStatus)status); 
                    else
                        Marshal.ThrowExceptionForHR(status); 
                }

            }
            finally 
            {
                if (securityHandler != null) 
                    securityHandler.Reset(); 
            }
 
            //Create collection object
            return new ManagementObjectCollection(scope, o, enumWbem);
        }
 

        //******************************************************************** 
        //GetRelationships 
        //*******************************************************************
        ///  
        ///    Gets a collection of associations to the object.
        /// 
        /// The object to use to return results. 
        ///  
        /// This operation is equivalent to a REFERENCES OF query
        ///  
        public void GetRelationships( 
            ManagementOperationObserver watcher)
        { 
            GetRelationships(watcher, (string)null);
        }

        //******************************************************************** 
        //GetRelationships
        //******************************************************************** 
        ///  
        ///    Gets a collection of associations to the object.
        ///  
        /// The object to use to return results. 
        /// The associations to include. 
        /// 
        ///    This operation is equivalent to a REFERENCES OF query where the AssocClass = <relationshipClass>. 
        /// 
        public void GetRelationships( 
            ManagementOperationObserver watcher, 
            string relationshipClass)
        { 
            GetRelationships(watcher, relationshipClass, null, null, false, null);
        }

 
        //*******************************************************************
        //GetRelationships 
        //******************************************************************** 
        /// 
        ///    Gets a collection of associations to the object. 
        /// 
        /// The object to use to return results. 
        /// The type of relationship of interest. 
        /// The qualifier to be present on the relationship.  
        /// The role of this object in the relationship. 
        /// When this method returns, it contains only the class definitions for the result set.  
        /// The extended options for the query execution.  
        /// 
        ///    This operation is equivalent to a REFERENCES OF query with possibly all the extensions. 
        /// 
        public void GetRelationships(
            ManagementOperationObserver watcher,
            string relationshipClass, 
            string relationshipQualifier,
            string thisRole, 
            bool classDefinitionsOnly, 
            EnumerationOptions options)
        { 
            if ((null == path)  || (path.Path.Length==0))
                throw new InvalidOperationException();
            if (null == watcher)
                throw new ArgumentNullException("watcher"); 
            else
            { 
                Initialize ( false ) ; 

                // Ensure we switch off ReturnImmediately as this is invalid for async calls 
                EnumerationOptions o =
                    (null != options) ? (EnumerationOptions)options.Clone() :
                    new EnumerationOptions();
                o.ReturnImmediately = false; 

                // If someone has registered for progress, make sure we flag it 
                if (watcher.HaveListenersForProgress) 
                    o.SendStatus = true;
 
                WmiEventSink sink = watcher.GetNewSink(scope, o.Context);

                RelationshipQuery q = new RelationshipQuery(path.Path, relationshipClass,
                    relationshipQualifier, thisRole, classDefinitionsOnly); 

 
                //Make sure the EnumerateDeep flag bit is turned off because it's invalid for queries 
                o.EnumerateDeep = true; //note this turns the FLAG to 0 !!
 
                SecurityHandler securityHandler = null;
                int status                        = (int)ManagementStatus.NoError;

                securityHandler = scope.GetSecurityHandler(); 

                status = scope.GetSecuredIWbemServicesHandler( scope.GetIWbemServices() ).ExecQueryAsync_( 
                                                        q.QueryLanguage, 
                                                        q.QueryString,
                                                        o.Flags, 
                                                        o.GetContext(),
                                                        sink.Stub );

 
                if (securityHandler != null)
                    securityHandler.Reset(); 
 
                if (status < 0)
                { 
                    watcher.RemoveSink(sink);
                    if ((status & 0xfffff000) == 0x80041000)
                        ManagementException.ThrowWithExtendedInfo((ManagementStatus)status);
                    else 
                        Marshal.ThrowExceptionForHR(status);
                } 
            } 
        }
 
        //*****************************************************
        //Put
        //*****************************************************
        ///  
        ///    Commits the changes to the object.
        ///  
        ///  
        ///    Commits the changes to the object.
        ///  
        /// 
        /// A  containing the path to the committed
        ///    object.
        ///  
        public ManagementPath Put()
        { 
            return Put((PutOptions) null); 
        }
 

        //*****************************************************
        //Put
        //****************************************************** 
        /// 
        ///    Commits the changes to the object. 
        ///  
        /// The options for how to commit the changes. 
        ///  
        ///    A  containing the path to the committed object.
        /// 
        public ManagementPath Put(PutOptions options)
        { 
            ManagementPath newPath = null;
            Initialize ( true ) ; 
            PutOptions o = (null != options) ? options : new PutOptions(); 

            IWbemServices wbemServices = scope.GetIWbemServices(); 

            //
            // Must do this convoluted allocation since the IWbemServices ref IWbemCallResult
            // has been redefined to be an IntPtr.  Due to the fact that it wasn't possible to 
            // pass NULL for the optional argument.
            // 
            IntPtr ppwbemCallResult            = IntPtr.Zero; 
            IntPtr pwbemCallResult            = IntPtr.Zero;
            IWbemCallResult wbemCallResult    = null; 
            SecurityHandler securityHandler    = null;
            int status                        = (int)ManagementStatus.NoError;

            try 
            {
                securityHandler = scope.GetSecurityHandler(); 
 
                ppwbemCallResult = Marshal.AllocHGlobal(IntPtr.Size);
                Marshal.WriteIntPtr(ppwbemCallResult, IntPtr.Zero);        // Init to NULL. 

                if (IsClass)
                {
                    status = scope.GetSecuredIWbemServicesHandler(wbemServices).PutClass_( wbemObject, 
                        o.Flags | (int)tag_WBEM_GENERIC_FLAG_TYPE.WBEM_FLAG_RETURN_IMMEDIATELY,
                        o.GetContext(), 
                        ppwbemCallResult ); 
                }
                else 
                {
                    status = scope.GetSecuredIWbemServicesHandler(wbemServices).PutInstance_(wbemObject,
                        o.Flags | (int)tag_WBEM_GENERIC_FLAG_TYPE.WBEM_FLAG_RETURN_IMMEDIATELY,
                        o.GetContext(), 
                        ppwbemCallResult);
                } 
 

                // Keep this statement here; otherwise, there'll be a leak in error cases. 
                pwbemCallResult = Marshal.ReadIntPtr(ppwbemCallResult);

                wbemCallResult = (IWbemCallResult)Marshal.GetObjectForIUnknown(pwbemCallResult);
 
                int hr;
                status = wbemCallResult.GetCallStatus_((int)tag_WBEM_TIMEOUT_TYPE.WBEM_INFINITE, out hr); 
 
                if (status >= 0)
                    status = hr; 

                if (status < 0)
                {
                    if ((status & 0xfffff000) == 0x80041000) 
                        ManagementException.ThrowWithExtendedInfo((ManagementStatus)status);
                    else 
                        Marshal.ThrowExceptionForHR(status); 
                }
 
                newPath = GetPath(wbemCallResult);

//                if (IsClass)
//                    newPath.RelativePath = ClassName; 
            }
            finally 
            { 
                if (securityHandler != null)
                    securityHandler.Reset(); 

                if (ppwbemCallResult != IntPtr.Zero)                    // Cleanup from allocations above.
                    Marshal.FreeHGlobal(ppwbemCallResult);
 
                if (pwbemCallResult != IntPtr.Zero)
                    Marshal.Release(pwbemCallResult); 
 
                if (wbemCallResult != null)
                    Marshal.ReleaseComObject(wbemCallResult); 
            }

            //Set the flag that tells the object that we've put it, so that a refresh is
            //triggered when an operation that needs this is invoked (CreateInstance, Derive). 
            putButNotGot = true;
 
            // Update our path to address the object just put. Note that 
            // we do this in such a way as to NOT trigger the setting of this
            // ManagementObject into an unbound state 
            path.SetRelativePath(newPath.RelativePath);

            return newPath;
        } 

        private ManagementPath GetPath(IWbemCallResult callResult) 
        { 
            ManagementPath newPath = null;
            int status = (int)ManagementStatus.NoError; 

            try
            {
                // 
                // Obtain the path from the call result.
                // Note this will return the relative path at best. 
                // 
                string resultPath = null;
 
                status = callResult.GetResultString_(
                    (int)tag_WBEM_TIMEOUT_TYPE.WBEM_INFINITE,
                    out resultPath);
 
                if (status >= 0)
                { 
                    newPath = new ManagementPath(scope.Path.Path); 
                    newPath.RelativePath = resultPath;
                } 
                else
                {
                    //
                    // That didn't work. Use the path in the object instead. 
                    //
                    object pathValue = GetPropertyValue("__PATH"); 
 
                    // No path? Try Relpath?
                    if (pathValue != null) 
                        newPath = new ManagementPath((string)pathValue);
                    else
                    {
                        pathValue = GetPropertyValue("__RELPATH"); 

                        if (pathValue != null) 
                        { 
                            newPath = new ManagementPath(scope.Path.Path);
                            newPath.RelativePath = (string)pathValue; 
                        }
                    }
                }
 
            }
            catch 
           { 
           }
 
            if (newPath == null)
                newPath = new ManagementPath();

            return newPath; 
        }
 
        ///  
        ///    Commits the changes to the object, asynchronously.
        ///  
        /// A  used to handle the progress and results of the asynchronous operation.
        public void Put(ManagementOperationObserver watcher)
        {
            Put(watcher, null); 
        }
 
        ///  
        ///    Commits the changes to the object asynchronously and
        ///       using the specified options. 
        /// 
        /// A  used to handle the progress and results of the asynchronous operation.
        /// A  used to specify additional options for the commit operation.
        public void Put(ManagementOperationObserver watcher, PutOptions options) 
        {
            if (null == watcher) 
                throw new ArgumentNullException("watcher"); 
            else
            { 
                Initialize ( false ) ;

                PutOptions o = (null == options) ?
                    new PutOptions() : (PutOptions)options.Clone(); 

                // If someone has registered for progress, make sure we flag it 
                if (watcher.HaveListenersForProgress) 
                    o.SendStatus = true;
 
                IWbemServices wbemServices = scope.GetIWbemServices();
                WmiEventSink sink = watcher.GetNewPutSink(scope,
                    o.Context, scope.Path.GetNamespacePath((int)tag_WBEM_GET_TEXT_FLAGS.WBEMPATH_GET_SERVER_AND_NAMESPACE_ONLY), ClassName);
 
                // Add ourselves to the watcher so we can update our state
                sink.InternalObjectPut += 
                    new InternalObjectPutEventHandler(this.HandleObjectPut); 

                SecurityHandler securityHandler    = null; 
                // Assign to error initially to insure internal event handler cleanup
                // on non-management exception.
                int status                        = (int)ManagementStatus.Failed;
 
                securityHandler = scope.GetSecurityHandler();
 
                if (IsClass) 
                {
                    status = scope.GetSecuredIWbemServicesHandler( wbemServices ).PutClassAsync_( 
                        wbemObject,
                        o.Flags,
                        o.GetContext(),
                        sink.Stub); 
                }
                else 
                { 
                    status = scope.GetSecuredIWbemServicesHandler( wbemServices ).PutInstanceAsync_(
                        wbemObject, 
                        o.Flags,
                        o.GetContext(),
                        sink.Stub);
                } 

 
                if (securityHandler != null) 
                    securityHandler.Reset();
 
                if (status < 0)
                {
                    sink.InternalObjectPut -= new InternalObjectPutEventHandler(this.HandleObjectPut);
                    watcher.RemoveSink(sink); 
                    if ((status & 0xfffff000) == 0x80041000)
                        ManagementException.ThrowWithExtendedInfo((ManagementStatus)status); 
                    else 
                        Marshal.ThrowExceptionForHR(status);
                } 
            }
        }

        internal void HandleObjectPut(object sender, InternalObjectPutEventArgs e) 
        {
            try 
            { 
                if (sender is WmiEventSink)
                { 
                    ((WmiEventSink)sender).InternalObjectPut -= new InternalObjectPutEventHandler(this.HandleObjectPut);
                    putButNotGot = true;
                    path.SetRelativePath(e.Path.RelativePath);
                } 
            }
            catch 
            { 
            }
        } 

        //*****************************************************
        //CopyTo
        //****************************************************** 
        /// 
        ///    Copies the object to a different location. 
        ///  
        /// 
        ///    Copies the object to a different location. 
        /// 
        /// The  to which the object should be copied. 
        /// 
        ///    The new path of the copied object. 
        /// 
        public ManagementPath CopyTo(ManagementPath path) 
        { 
            return CopyTo(path,(PutOptions)null);
        } 

        /// 
        ///    Copies the object to a different location.
        ///  
        /// The path to which the object should be copied. 
        ///  
        ///    The new path of the copied object. 
        /// 
        public ManagementPath CopyTo(string path) 
        {
            return CopyTo(new ManagementPath(path), (PutOptions)null);
        }
 
        /// 
        ///    Copies the object to a different location. 
        ///  
        /// The path to which the object should be copied.
        /// The options for how the object should be put. 
        /// 
        ///    The new path of the copied object.
        /// 
        public ManagementPath CopyTo(string path, PutOptions options) 
        {
            return CopyTo(new ManagementPath(path), options); 
        } 

        ///  
        ///    Copies the object to a different location.
        /// 
        /// The  to which the object should be copied.
        /// The options for how the object should be put. 
        /// 
        ///    The new path of the copied object. 
        ///  
        public ManagementPath CopyTo(ManagementPath path, PutOptions options)
        { 
            Initialize ( false ) ;

            ManagementScope destinationScope = null;
 
            // Build a scope for our target destination
            destinationScope = new ManagementScope(path, scope); 
            destinationScope.Initialize(); 

            PutOptions o = (null != options) ? options : new PutOptions(); 
            IWbemServices wbemServices = destinationScope.GetIWbemServices();
            ManagementPath newPath = null;

            // 
            // TO-DO : This code is almost identical to Put - should consolidate.
            // 
            // Must do this convoluted allocation since the IWbemServices ref IWbemCallResult 
            // has been redefined to be an IntPtr.  Due to the fact that it wasn't possible to
            // pass NULL for the optional argument. 
            //
            IntPtr ppwbemCallResult            = IntPtr.Zero;
            IntPtr pwbemCallResult            = IntPtr.Zero;
            IWbemCallResult wbemCallResult    = null; 
            SecurityHandler securityHandler    = null;
            int status                        = (int)ManagementStatus.NoError; 
 
            try
            { 
                securityHandler = destinationScope.GetSecurityHandler();

                ppwbemCallResult = Marshal.AllocHGlobal(IntPtr.Size);
                Marshal.WriteIntPtr(ppwbemCallResult, IntPtr.Zero);        // Init to NULL. 

                if (IsClass) 
                { 
                    status = scope.GetSecuredIWbemServicesHandler( wbemServices ).PutClass_(
                        wbemObject, 
                        o.Flags | (int)tag_WBEM_GENERIC_FLAG_TYPE.WBEM_FLAG_RETURN_IMMEDIATELY,
                        o.GetContext(),
                        ppwbemCallResult);
                } 
                else
                { 
                    status = scope.GetSecuredIWbemServicesHandler( wbemServices ).PutInstance_( 
                        wbemObject,
                        o.Flags | (int)tag_WBEM_GENERIC_FLAG_TYPE.WBEM_FLAG_RETURN_IMMEDIATELY, 
                        o.GetContext(),
                        ppwbemCallResult);

                } 

 
                // Keep this statement here; otherwise, there'll be a leak in error cases. 
                pwbemCallResult = Marshal.ReadIntPtr(ppwbemCallResult);
 
                //Use the CallResult to retrieve the resulting object path
                wbemCallResult = (IWbemCallResult)Marshal.GetObjectForIUnknown(pwbemCallResult);

                int hr; 
                status = wbemCallResult.GetCallStatus_((int)tag_WBEM_TIMEOUT_TYPE.WBEM_INFINITE, out hr);
 
                if (status >= 0) 
                    status = hr;
 
                if (status < 0)
                {
                    if ((status & 0xfffff000) == 0x80041000)
                        ManagementException.ThrowWithExtendedInfo((ManagementStatus)status); 
                    else
                        Marshal.ThrowExceptionForHR(status); 
                } 

                newPath = GetPath(wbemCallResult); 
                newPath.NamespacePath = path.GetNamespacePath((int)tag_WBEM_GET_TEXT_FLAGS.WBEMPATH_GET_SERVER_AND_NAMESPACE_ONLY);
            }
            finally
            { 
                if (securityHandler != null)
                    securityHandler.Reset(); 
 
                if (ppwbemCallResult != IntPtr.Zero)                    // Cleanup from allocations above.
                    Marshal.FreeHGlobal(ppwbemCallResult); 

                if (pwbemCallResult != IntPtr.Zero)
                    Marshal.Release(pwbemCallResult);
 
                if (wbemCallResult != null)
                    Marshal.ReleaseComObject(wbemCallResult); 
            } 

            return newPath; 
        }

        /// 
        ///    Copies the object to a different location, asynchronously. 
        /// 
        /// The object that will receive the results of the operation. 
        /// A  specifying the path to which the object should be copied. 
        public void CopyTo(ManagementOperationObserver watcher, ManagementPath path)
        { 
            CopyTo(watcher, path, null);
        }

        ///  
        ///    Copies the object to a different location, asynchronously.
        ///  
        /// The object that will receive the results of the operation. 
        ///  The path to which the object should be copied.
        public void CopyTo(ManagementOperationObserver watcher, string path) 
        {
            CopyTo(watcher, new ManagementPath(path), null);
        }
 
        /// 
        ///    Copies the object to a different location, asynchronously. 
        ///  
        /// The object that will receive the results of the operation.
        /// The path to which the object should be copied. 
        /// The options for how the object should be put.
        public void CopyTo(ManagementOperationObserver watcher, string path, PutOptions options)
        {
            CopyTo(watcher, new ManagementPath(path), options); 
        }
 
        ///  
        ///    Copies the object to a different location, asynchronously.
        ///  
        /// The object that will receive the results of the operation.
        /// The path to which the object should be copied.
        /// The options for how the object should be put.
        public void CopyTo(ManagementOperationObserver watcher, ManagementPath path, PutOptions options) 
        {
            if (null == watcher) 
                throw new ArgumentNullException("watcher"); 
            else
            { 
                Initialize ( false ) ;
                ManagementScope destinationScope = null;

                destinationScope = new ManagementScope(path, scope); 
                destinationScope.Initialize();
 
                PutOptions o = (null != options) ? (PutOptions) options.Clone() : new PutOptions(); 

                // If someone has registered for progress, make sure we flag it 
                if (watcher.HaveListenersForProgress)
                    o.SendStatus = true;

                WmiEventSink sink = watcher.GetNewPutSink(destinationScope, o.Context, 
                    path.GetNamespacePath((int)tag_WBEM_GET_TEXT_FLAGS.WBEMPATH_GET_SERVER_AND_NAMESPACE_ONLY), ClassName);
                IWbemServices destWbemServices = destinationScope.GetIWbemServices(); 
 
                SecurityHandler securityHandler = null;
                int status                        = (int)ManagementStatus.NoError; 

                securityHandler = destinationScope.GetSecurityHandler();

                if (IsClass) 
                {
                    status = destinationScope.GetSecuredIWbemServicesHandler( destWbemServices ).PutClassAsync_( 
                                                    wbemObject, 
                                                    o.Flags,
                                                    o.GetContext(), 
                                                    sink.Stub);

                }
                else 
                {
                    status = destinationScope.GetSecuredIWbemServicesHandler( destWbemServices ).PutInstanceAsync_( 
                                                    wbemObject, 
                                                    o.Flags,
                                                    o.GetContext(), 
                                                    sink.Stub);
                }

 
                if (securityHandler != null)
                    securityHandler.Reset(); 
 
                if (status < 0)
                { 
                    watcher.RemoveSink(sink);
                    if ((status & 0xfffff000) == 0x80041000)
                        ManagementException.ThrowWithExtendedInfo((ManagementStatus)status);
                    else 
                        Marshal.ThrowExceptionForHR(status);
                } 
            } 
        }
 
        //******************************************************
        //Delete
        //*****************************************************
        ///  
        ///    Deletes the object.
        ///  
        ///  
        ///    Deletes the object.
        ///  
        public void Delete()
        {
            Delete((DeleteOptions) null);
        } 

        ///  
        ///    Deletes the object. 
        /// 
        /// The options for how to delete the object.  
        public void Delete(DeleteOptions options)
        {
            if ((null == path) || (path.Path.Length==0))
                throw new InvalidOperationException(); 

            Initialize ( false ) ; 
            DeleteOptions o = (null != options) ? options : new DeleteOptions(); 
            IWbemServices wbemServices = scope.GetIWbemServices();
 
            SecurityHandler securityHandler = null;
            int status                        = (int)ManagementStatus.NoError;

            try 
            {
                securityHandler = scope.GetSecurityHandler(); 
 
                if (IsClass)
                { 
                    status = scope.GetSecuredIWbemServicesHandler( wbemServices ).DeleteClass_(
                        path.RelativePath,
                        o.Flags,
                        o.GetContext(), 
                        IntPtr.Zero);
                } 
                else 
                {
                    status = scope.GetSecuredIWbemServicesHandler( wbemServices ).DeleteInstance_( 
                        path.RelativePath,
                        o.Flags,
                        o.GetContext(),
                        IntPtr.Zero); 
                }
 
 
                if (status < 0)
                { 
                    if ((status & 0xfffff000) == 0x80041000)
                        ManagementException.ThrowWithExtendedInfo((ManagementStatus)status);
                    else
                        Marshal.ThrowExceptionForHR(status); 
                }
            } 
            finally 
            {
                if (securityHandler != null) 
                    securityHandler.Reset();
            }
        }
 

        ///  
        ///    Deletes the object. 
        /// 
        /// The object that will receive the results of the operation. 
        public void Delete(ManagementOperationObserver watcher)
        {
            Delete(watcher, null);
        } 

        ///  
        ///    Deletes the object. 
        /// 
        /// The object that will receive the results of the operation. 
        /// The options for how to delete the object.
        public void Delete(ManagementOperationObserver watcher, DeleteOptions options)
        {
            if ((null == path) || (path.Path.Length==0)) 
                throw new InvalidOperationException();
            else if (null == watcher) 
                throw new ArgumentNullException("watcher"); 
            else
            { 
                Initialize ( false ) ;
                DeleteOptions o = (null != options) ? (DeleteOptions) options.Clone() : new DeleteOptions();

                // If someone has registered for progress, make sure we flag it 
                if (watcher.HaveListenersForProgress)
                    o.SendStatus = true; 
 
                IWbemServices wbemServices = scope.GetIWbemServices();
                WmiEventSink sink = watcher.GetNewSink(scope, o.Context); 

                SecurityHandler securityHandler = null;
                int status                        = (int)ManagementStatus.NoError;
 
                securityHandler = scope.GetSecurityHandler();
 
                if (IsClass) 
                {
                    status = scope.GetSecuredIWbemServicesHandler( wbemServices ).DeleteClassAsync_(path.RelativePath, 
                        o.Flags,
                        o.GetContext(),
                        sink.Stub);
                } 
                else
                { 
                    status = scope.GetSecuredIWbemServicesHandler( wbemServices ).DeleteInstanceAsync_(path.RelativePath, 
                        o.Flags,
                        o.GetContext(), 
                        sink.Stub);
                }

 
                if (securityHandler != null)
                    securityHandler.Reset(); 
 
                if (status < 0)
                { 
                    watcher.RemoveSink(sink);
                    if ((status & 0xfffff000) == 0x80041000)
                        ManagementException.ThrowWithExtendedInfo((ManagementStatus)status);
                    else 
                        Marshal.ThrowExceptionForHR(status);
                } 
            } 
        }
 
        //******************************************************
        //InvokeMethod
        //*****************************************************
        ///  
        ///    Invokes a method on the object.
        ///  
        ///  
        ///    
        ///       Invokes a method on the object. 
        /// 
        /// The name of the method to execute. 
        /// An array containing parameter values. 
        ///  
        ///    The value returned by the method.
        ///  
        ///  
        ///    If the method is static, the execution
        ///       should still succeed. 
        /// 
        /// 
        ///    using System;
        /// using System.Management; 
        ///
        /// // This sample demonstrates invoking a WMI method using an array of arguments. 
        /// public class InvokeMethod 
        /// {
        ///     public static void Main() 
        ///     {
        ///
        ///         //Get the object on which the method will be invoked
        ///         ManagementClass processClass = new ManagementClass("Win32_Process"); 
        ///
        ///         //Create an array containing all arguments for the method 
        ///         object[] methodArgs = {"notepad.exe", null, null, 0}; 
        ///
        ///         //Execute the method 
        ///         object result = processClass.InvokeMethod ("Create", methodArgs);
        ///
        ///         //Display results
        ///         Console.WriteLine ("Creation of process returned: " + result); 
        ///         Console.WriteLine ("Process id: " + methodArgs[3]);
        ///     } 
        /// 
        /// }
        ///     
        ///    Imports System
        /// Imports System.Management
        ///
        /// ' This sample demonstrates invoking a WMI method using an array of arguments. 
        /// Class InvokeMethod
        ///     Public Overloads Shared Function Main(ByVal args() As String) As Integer 
        /// 
        ///         ' Get the object on which the method will be invoked
        ///         Dim processClass As New ManagementClass("Win32_Process") 
        ///
        ///         ' Create an array containing all arguments for the method
        ///         Dim methodArgs() As Object = {"notepad.exe", Nothing, Nothing, 0}
        /// 
        ///         ' Execute the method
        ///         Dim result As Object = processClass.InvokeMethod("Create", methodArgs) 
        /// 
        ///         'Display results
        ///         Console.WriteLine("Creation of process returned: {0}", result) 
        ///         Console.WriteLine("Process id: {0}", methodArgs(3))
        ///         Return 0
        ///     End Function
        /// End Class 
        ///    
        ///  
        public Object InvokeMethod(string methodName, Object[] args) 
        {
            object result = null; 

            if ((null == path) || (path.Path.Length==0))
                throw new InvalidOperationException();
            else if (null == methodName) 
                throw new ArgumentNullException("methodName");
            else 
            { 
                Initialize ( false ) ;
 
                // Map args into a inparams structure
                ManagementBaseObject inParameters;
                IWbemClassObjectFreeThreaded inParametersClass, outParametersClass;
                GetMethodParameters(methodName, out inParameters, 
                    out inParametersClass, out outParametersClass);
 
                MapInParameters(args, inParameters, inParametersClass); 

                // Call ExecMethod 
                ManagementBaseObject outParameters =
                    InvokeMethod(methodName, inParameters, null);

                // Map outparams to args 
                result = MapOutParameters(args, outParameters, outParametersClass);
            } 
 
            return result;
        } 

        //*****************************************************
        //InvokeMethod
        //***************************************************** 
        /// 
        ///    Invokes a method on the object, asynchronously. 
        ///  
        /// The object to receive the results of the operation.
        /// The name of the method to execute.  
        /// An array containing parameter values. 
        /// 
        ///    If the method is static, the execution
        ///       should still succeed. 
        /// 
        public void InvokeMethod( 
            ManagementOperationObserver watcher, 
            string methodName,
            Object[] args) 
        {
            if ((null == path) || (path.Path.Length==0))
                throw new InvalidOperationException();
            else if (null == watcher) 
                throw new ArgumentNullException("watcher");
            else if (null == methodName) 
                throw new ArgumentNullException("methodName"); 
            else
            { 
                Initialize ( false ) ;

                // Map args into a inparams structure
                ManagementBaseObject inParameters; 
                IWbemClassObjectFreeThreaded inParametersClass, outParametersClass;
                GetMethodParameters(methodName, out inParameters, 
                    out inParametersClass,    out outParametersClass); 

                MapInParameters(args, inParameters, inParametersClass); 

                // Call the method
                InvokeMethod(watcher, methodName, inParameters, null);
            } 
        }
 
        ///  
        ///    Invokes a method on the WMI object. The input and output
        ///       parameters are represented as  
        ///       objects.
        /// 
        /// The name of the method to execute.
        /// A  holding the input parameters to the method. 
        /// An  containing additional options for the execution of the method.
        ///  
        /// A  containing the 
        ///    output parameters and return value of the executed method.
        ///  
        /// 
        ///    using System;
        /// using System.Management;
        /// 
        /// // This sample demonstrates invoking a WMI method using parameter objects
        /// public class InvokeMethod 
        /// { 
        ///     public static void Main()
        ///     { 
        ///
        ///         //Get the object on which the method will be invoked
        ///         ManagementClass processClass = new ManagementClass("Win32_Process");
        /// 
        ///         //Get an input parameters object for this method
        ///         ManagementBaseObject inParams = processClass.GetMethodParameters("Create"); 
        /// 
        ///         //Fill in input parameter values
        ///         inParams["CommandLine"] = "calc.exe"; 
        ///
        ///         //Execute the method
        ///         ManagementBaseObject outParams = processClass.InvokeMethod ("Create", inParams, null);
        /// 
        ///         //Display results
        ///         //Note: The return code of the method is provided in the "returnValue" property of the outParams object 
        ///         Console.WriteLine("Creation of calculator process returned: " + outParams["returnValue"]); 
        ///         Console.WriteLine("Process ID: " + outParams["processId"]);
        ///    } 
        /// }
        ///    
        ///    
        /// Imports System 
        /// Imports System.Management
        /// 
        /// ' This sample demonstrates invoking a WMI method using parameter objects 
        /// Class InvokeMethod
        ///     Public Overloads Shared Function Main(ByVal args() As String) As Integer 
        ///
        ///         ' Get the object on which the method will be invoked
        ///         Dim processClass As New ManagementClass("Win32_Process")
        /// 
        ///          ' Get an input parameters object for this method
        ///         Dim inParams As ManagementBaseObject = processClass.GetMethodParameters("Create") 
        /// 
        ///         ' Fill in input parameter values
        ///         inParams("CommandLine") = "calc.exe" 
        ///
        ///         ' Execute the method
        ///         Dim outParams As ManagementBaseObject = processClass.InvokeMethod("Create", inParams, Nothing)
        /// 
        ///         ' Display results
        ///         ' Note: The return code of the method is provided in the "returnValue" property of the outParams object 
        ///         Console.WriteLine("Creation of calculator process returned: {0}", outParams("returnValue")) 
        ///         Console.WriteLine("Process ID: {0}", outParams("processId"))
        /// 
        ///         Return 0
        ///     End Function
        /// End Class
        ///     
        /// 
        public ManagementBaseObject InvokeMethod( 
            string methodName, 
            ManagementBaseObject inParameters,
            InvokeMethodOptions options) 
        {
            ManagementBaseObject outParameters = null;

            if ((null == path) || (path.Path.Length==0)) 
                throw new InvalidOperationException();
            else if (null == methodName) 
                throw new ArgumentNullException("methodName"); 
            else
            { 
                Initialize ( false ) ;
                InvokeMethodOptions o = (null != options) ? options : new InvokeMethodOptions();
                IWbemServices wbemServices = scope.GetIWbemServices();
 
                SecurityHandler securityHandler = null;
                int status                        = (int)ManagementStatus.NoError; 
 
                try
                { 
                    securityHandler = scope.GetSecurityHandler();

                    IWbemClassObjectFreeThreaded inParams = (null == inParameters) ? null : inParameters.wbemObject;
                    IWbemClassObjectFreeThreaded outParams = null; 

                    status = scope.GetSecuredIWbemServicesHandler( scope.GetIWbemServices() ).ExecMethod_( 
                        path.RelativePath, 
                        methodName,
                        o.Flags, 
                        o.GetContext(),
                        inParams,
                        ref outParams,
                        IntPtr.Zero); 

 
                    if (status < 0) 
                    {
                        if ((status & 0xfffff000) == 0x80041000) 
                            ManagementException.ThrowWithExtendedInfo((ManagementStatus)status);
                        else
                            Marshal.ThrowExceptionForHR(status);
                    } 

                    if (outParams != null) 
                        outParameters = new ManagementBaseObject(outParams); 
                }
                finally 
                {
                    if (securityHandler != null)
                        securityHandler.Reset();
                } 
            }
 
            return outParameters; 
        }
 
        /// 
        ///    Invokes a method on the object, asynchronously.
        /// 
        /// A  used to handle the asynchronous execution's progress and results. 
        /// The name of the method to be executed.
        /// A  containing the input parameters for the method. 
        /// An  containing additional options used to execute the method. 
        /// 
        ///    The method invokes the specified method execution and then 
        ///       returns. Progress and results are reported through events on the .
        /// 
        public void InvokeMethod(
            ManagementOperationObserver watcher, 
            string methodName,
            ManagementBaseObject inParameters, 
            InvokeMethodOptions options) 
        {
            if ((null == path) || (path.Path.Length==0)) 
                throw new InvalidOperationException();
            else if (null == watcher)
                throw new ArgumentNullException("watcher");
            else if (null == methodName) 
                throw new ArgumentNullException("methodName");
            else 
            { 
                Initialize ( false ) ;
                InvokeMethodOptions o = (null != options) ? 
                    (InvokeMethodOptions) options.Clone() : new InvokeMethodOptions();

                // If someone has registered for progress, make sure we flag it
                if (watcher.HaveListenersForProgress) 
                    o.SendStatus = true;
 
                WmiEventSink sink = watcher.GetNewSink(scope, o.Context); 

                SecurityHandler securityHandler = null; 
                int status                        = (int)ManagementStatus.NoError;

                securityHandler = scope.GetSecurityHandler();
 
                IWbemClassObjectFreeThreaded inParams = null;
 
                if (null != inParameters) 
                    inParams = inParameters.wbemObject;
 
                status = scope.GetSecuredIWbemServicesHandler( scope.GetIWbemServices() ).ExecMethodAsync_(
                    path.RelativePath,
                    methodName,
                    o.Flags, 
                    o.GetContext(),
                    inParams, 
                    sink.Stub ); 

                if (securityHandler != null) 
                    securityHandler.Reset();

                if (status < 0)
                { 
                    watcher.RemoveSink(sink);
                    if ((status & 0xfffff000) == 0x80041000) 
                        ManagementException.ThrowWithExtendedInfo((ManagementStatus)status); 
                    else
                        Marshal.ThrowExceptionForHR(status); 
                }
            }
        }
 
        //******************************************************
        //GetMethodParameters 
        //***************************************************** 
        /// 
        /// Returns a  representing the list of input parameters for a method. 
        /// 
        /// The name of the method. 
        /// 
        /// A  containing the 
        ///    input parameters to the method.
        ///  
        ///  
        ///     Gets the object containing the input parameters to a
        ///       method, and then fills in the values and passes the object to the () call. 
        /// 
        public ManagementBaseObject GetMethodParameters(
            string methodName)
        { 
            ManagementBaseObject inParameters;
            IWbemClassObjectFreeThreaded dummy1, dummy2; 
 
            GetMethodParameters(methodName, out inParameters, out dummy1, out dummy2);
 
            return inParameters;
        }

        private void GetMethodParameters( 
            string methodName,
            out ManagementBaseObject inParameters, 
            out IWbemClassObjectFreeThreaded inParametersClass, 
            out IWbemClassObjectFreeThreaded outParametersClass)
        { 
            inParameters = null;
            inParametersClass = null;
            outParametersClass = null;
 
            if (null == methodName)
                throw new ArgumentNullException("methodName"); 
            else 
            {
                Initialize ( false ) ; 

                // Do we have the class?
                if (null == wmiClass)
                { 
                    ManagementPath classPath = ClassPath;
 
                    if ((null == classPath) || !(classPath.IsClass)) 
                        throw new InvalidOperationException();
                    else 
                    {
                        ManagementClass classObject =
                            new ManagementClass(scope, classPath, null);
                        classObject.Get(); 
                        wmiClass = classObject.wbemObject;
                    } 
                } 

                int status = (int)ManagementStatus.NoError; 

                // Ask it for the method parameters
                status = wmiClass.GetMethod_(methodName, 0, out inParametersClass, out outParametersClass);
 
                // bug#92427 - To ensure that all forms of invoke return the same error codes when
                // the method does not exist, we will map WBEM_E_NOT_FOUND to WBEM_E_METHOD_NOT_IMPLEMENTED. 
                if(status == (int)tag_WBEMSTATUS.WBEM_E_NOT_FOUND) 
                    status = (int)tag_WBEMSTATUS.WBEM_E_METHOD_NOT_IMPLEMENTED;
 
                if (status >= 0)
                {
                    // Hand out instances
                    if (inParametersClass != null) 
                    {
                        IWbemClassObjectFreeThreaded inParamsInstance = null; 
                        status = inParametersClass.SpawnInstance_(0, out inParamsInstance); 

                        if (status >= 0) 
                        {
                            inParameters = new ManagementBaseObject(inParamsInstance);
                        }
                    } 
                }
 
                if (status < 0) 
                {
                    if ((status & 0xfffff000) == 0x80041000) 
                        ManagementException.ThrowWithExtendedInfo((ManagementStatus)status);
                    else
                        Marshal.ThrowExceptionForHR(status);
                } 
            }
        } 
 
        /// 
        ///    Creates a copy of the object. 
        /// 
        /// 
        ///    The copied object.
        ///  
        public override Object Clone()
        { 
            if (PutButNotGot) 
            {
                Get(); 
                PutButNotGot = false;
            }

            // 
            // Removed Initialize call since wbemObject is a property that will call Initialize ( true ) on
            // its getter. 
            // 
            // Initialize ( ) ;
 
            IWbemClassObjectFreeThreaded theClone = null;

            int status = wbemObject.Clone_(out theClone);
 
            if (status < 0)
            { 
                if ((status & 0xfffff000) == 0x80041000) 
                    ManagementException.ThrowWithExtendedInfo((ManagementStatus)status);
                else 
                    Marshal.ThrowExceptionForHR(status);
            }

            return ManagementObject.GetManagementObject(theClone, this); 
        }
 
        //****************************************************** 
        //ToString
        //****************************************************** 
        /// 
        ///    Returns the full path of the object. This is an override of the
        ///       default object implementation.
        ///  
        /// 
        ///     The full path of 
        ///       the object. 
        /// 
        public override string ToString() 
        {
            if (null != path)
                return path.Path;
            else 
                return "";
        } 
 
        //
        // The prototype of Initialize has been changed to accept a bool, indicating whether or not 
        // the caller wants to bind to the underlying WMI object in the Initialize call or not.
        //
        internal override void Initialize( bool getObject )
        { 
            bool needToGetObject = false;
 
            //If we're not connected yet, this is the time to do it... We lock 
            //the state to prevent 2 threads simultaneously doing the same
            //connection 
            lock (this)
            {
                // Make sure we have some kind of path if we get here. Note that
                // we don't use a set to the Path property since that would trigger 
                // an IdentifierChanged event
                if (null == path) 
                { 
                    path = new ManagementPath();
                    path.IdentifierChanged += new IdentifierChangedEventHandler(HandleIdentifierChange); 
                }

                //Have we already got this object
                if (!IsBound && ( getObject == true ) ) 
                    needToGetObject = true;
 
                if (null == scope) 
                {
                    // If our object has a valid namespace path, use that 
                    string nsPath = path.GetNamespacePath((int)tag_WBEM_GET_TEXT_FLAGS.WBEMPATH_GET_SERVER_AND_NAMESPACE_ONLY);

                    // Set the scope - note that we do not set through
                    // the Scope property since that would trigger an IdentifierChanged 
                    // event and reset isBound to false.
                    if (0 < nsPath.Length) 
                        scope = new ManagementScope(nsPath); 
                    else
                    { 
                        // Use the default constructor
                        scope = new ManagementScope();
                    }
 
                    // Hook ourselves up to this scope for future change notifications
                    scope.IdentifierChanged += new IdentifierChangedEventHandler(HandleIdentifierChange); 
                } 
                else if ((null == scope.Path) || scope.Path.IsEmpty)
                { 
                    // We have a scope but an empty path - use the object's path or the default
                    string nsPath = path.GetNamespacePath((int)tag_WBEM_GET_TEXT_FLAGS.WBEMPATH_GET_SERVER_AND_NAMESPACE_ONLY);

                    if (0 < nsPath.Length) 
                        scope.Path = new ManagementPath(nsPath);
                    else 
                        scope.Path = ManagementPath.DefaultPath; 
                }
 
                lock (scope)
                {
                    if (!scope.IsConnected)
                    { 
                        scope.Initialize();
 
                        // If we have just connected, make sure we get the object 
                        if ( getObject == true )
                        { 
                            needToGetObject = true;
                        }
                    }
 
                    if (needToGetObject)
                    { 
                        // If we haven't set up any options yet, now is the time. 
                        // Again we don't use the set to the Options property
                        // since that would trigger an IdentifierChangedEvent and 
                        // force isBound=false.
                        if (null == options)
                        {
                            options = new ObjectGetOptions(); 
                            options.IdentifierChanged += new IdentifierChangedEventHandler(HandleIdentifierChange);
                        } 
 
                        IWbemClassObjectFreeThreaded tempObj = null;
                        IWbemServices wbemServices = scope.GetIWbemServices(); 

                        SecurityHandler securityHandler = null;
                        int status                        = (int)ManagementStatus.NoError;
 
                        try
                        { 
                            securityHandler = scope.GetSecurityHandler(); 

                            string objectPath = null; 
                            string curPath = path.RelativePath;

                            if (curPath.Length>0)
                                objectPath = curPath; 
                            status = scope.GetSecuredIWbemServicesHandler( wbemServices ).GetObject_(objectPath, options.Flags, options.GetContext(), ref tempObj, IntPtr.Zero);
 
                            if (status >= 0) 
                            {
                                wbemObject = tempObj; 

                                // Getting the object succeeded, we are bound
                                //
                                // *** 
                                // *    Changed isBound flag to wbemObject==null check.
                                // *    isBound = true; 
                                // *** 

                                // now set the path from the "real" object 
                                object val = null;
                                int dummy1 = 0, dummy2 = 0;

                                status = wbemObject.Get_("__PATH", 0, ref val, ref dummy1, ref dummy2); 

                                if (status >= 0) 
                                { 
                                    path = (System.DBNull.Value != val) ? (new ManagementPath((string)val)) : (new ManagementPath ());
                                    path.IdentifierChanged += new IdentifierChangedEventHandler(HandleIdentifierChange); 
                                }
                            }

                            if (status < 0) 
                            {
                                if ((status & 0xfffff000) == 0x80041000) 
                                    ManagementException.ThrowWithExtendedInfo((ManagementStatus)status); 
                                else
                                    Marshal.ThrowExceptionForHR(status); 
                            }
                        }
                        finally
                        { 
                            if (securityHandler != null)
                                securityHandler.Reset(); 
                        } 
                    }
                } 
            }
        }

 
        private static void MapInParameters(
            object [] args, 
            ManagementBaseObject inParams, 
            IWbemClassObjectFreeThreaded inParamsClass)
        { 
            int status = (int)ManagementStatus.NoError;

            if (null != inParamsClass)
            { 
                if ((null != args) && (0 < args.Length))
                { 
                    int maxIndex = args.GetUpperBound(0); 
                    int minIndex = args.GetLowerBound(0);
                    int topId = maxIndex - minIndex; 

                    /*
                     * Iterate through the [in] parameters of the class to find
                     * the ID positional qualifier. We do this in the class because 
                     * we cannot be sure that the qualifier will be propagated to
                     * the instance. 
                     */ 

                    status = inParamsClass.BeginEnumeration_ 
                            ((int)tag_WBEM_CONDITION_FLAG_TYPE.WBEM_FLAG_NONSYSTEM_ONLY);

                    if (status >= 0)
                    { 
                        while (true)
                        { 
                            object                          val = null; 
                            int                              dummy = 0;
                            string                          propertyName = null; 
                            IWbemQualifierSetFreeThreaded qualifierSet = null;

                            status = inParamsClass.Next_(0, ref propertyName, ref val, ref dummy, ref dummy);
 
                            if (status >= 0)
                            { 
                                if (null == propertyName) 
                                    break;
 
                                status = inParamsClass.GetPropertyQualifierSet_(propertyName, out qualifierSet);

                                if (status >= 0)
                                { 
                                    try
                                    { 
                                        object id = 0; 
                                        qualifierSet.Get_(ID, 0, ref id, ref dummy);    // Errors intentionally ignored.
 
                                        // If the id is in range, map the value into the args array
                                        int idIndex = (int)id;
                                        if ((0 <= idIndex) && (topId >= idIndex))
                                            inParams[propertyName] = args [minIndex + idIndex]; 
                                    }
                                    finally 
                                    { 
                                        // Dispose for next iteration.
                                        qualifierSet.Dispose(); 
                                    }
                                }
                            }
 
                            if (status < 0)
                            { 
                                break; 
                            }
                        } 
                    }

                    if (status < 0)
                    { 
                        if ((status & 0xfffff000) == 0x80041000)
                            ManagementException.ThrowWithExtendedInfo((ManagementStatus)status); 
                        else 
                            Marshal.ThrowExceptionForHR(status);
                    } 
                }
            }
        }
 
        private static object MapOutParameters(
            object [] args, 
            ManagementBaseObject outParams, 
            IWbemClassObjectFreeThreaded outParamsClass)
        { 
            object result = null;
            int maxIndex = 0, minIndex = 0, topId = 0;

            int status = (int)ManagementStatus.NoError; 

            if (null != outParamsClass) 
            { 
                if ((null != args) && (0 < args.Length))
                { 
                    maxIndex = args.GetUpperBound(0);
                    minIndex = args.GetLowerBound(0);
                    topId = maxIndex - minIndex;
                } 
                /*
                    * Iterate through the [out] parameters of the class to find 
                    * the ID positional qualifier. We do this in the class because 
                    * we cannot be sure that the qualifier will be propagated to
                    * the instance. 
                */

                status = outParamsClass.BeginEnumeration_
                    ((int)tag_WBEM_CONDITION_FLAG_TYPE.WBEM_FLAG_NONSYSTEM_ONLY); 

                if (status >= 0) 
                { 
                    while (true)
                    { 
                        object                          val = null;
                        int                              dummy = 0;
                        string                          propertyName = null;
                        IWbemQualifierSetFreeThreaded qualifierSet = null; 

                        status = outParamsClass.Next_(0, ref propertyName, ref val, ref dummy, ref dummy); 
 
                        if (status >= 0)
                        { 
                            if (null == propertyName)
                                break;

                            // Handle the result parameter separately 
                            if (String.Compare(propertyName, RETURNVALUE, StringComparison.OrdinalIgnoreCase) == 0)
                            { 
                                result = outParams[RETURNVALUE]; 
                            }
                            else  // Shouldn't get here if no args! 
                            {
                                status = outParamsClass.GetPropertyQualifierSet_(propertyName, out qualifierSet);

                                if (status >= 0) 
                                {
                                    try 
                                    { 
                                        object id = 0;
                                        qualifierSet.Get_(ID, 0, ref id, ref dummy);    // Errors intentionally ignored. 

                                        // If the id is in range, map the value into the args array
                                        int idIndex = (int)id;
                                        if ((0 <= idIndex) && (topId >= idIndex)) 
                                            args [minIndex + idIndex] = outParams[propertyName];
                                    } 
                                    finally 
                                    {
                                        // Dispose for next iteration. 
                                        qualifierSet.Dispose();
                                    }
                                }
                            } 
                        }
 
                        if (status < 0) 
                        {
                            break; 
                        }
                    }
                }
 
                if (status < 0)
                { 
                    if ((status & 0xfffff000) == 0x80041000) 
                        ManagementException.ThrowWithExtendedInfo((ManagementStatus)status);
                    else 
                        Marshal.ThrowExceptionForHR(status);
                }
            }
 
            return result;
        } 
 
    }//ManagementObject
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
using System.Collections; 
using System.Runtime.InteropServices;
using WbemClient_v1;
using System.ComponentModel;
using System.Runtime.Serialization; 
using System.Globalization;
 
namespace System.Management 
{
    ///  
    /// Delegate definition for the IdentifierChanged event.
    /// This event is used to signal the ManagementObject that an identifying property
    /// has been changed. Identifying properties are the ones that identify the object,
    /// namely the scope, path and options. 
    /// 
    internal delegate void IdentifierChangedEventHandler(object sender, 
                    IdentifierChangedEventArgs e); 

    ///  
    /// Delegate definition for InternalObjectPut event. This is used so that
    /// the WmiEventSink can signal to this object that the async Put call has
    /// completed.
    ///  
    internal delegate void InternalObjectPutEventHandler(object sender,
        InternalObjectPutEventArgs e); 
 

    //CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC// 
    /// 
    ///     Represents a data management object.
    /// 
    ///  
    ///    using System;
    /// using System.Management; 
    /// 
    /// // This example demonstrates reading a property of a ManagementObject.
    /// class Sample_ManagementObject 
    /// {
    ///     public static int Main(string[] args) {
    ///         ManagementObject disk = new ManagementObject(
    ///             "win32_logicaldisk.deviceid=\"c:\""); 
    ///         disk.Get();
    ///         Console.WriteLine("Logical Disk Size = " + disk["Size"] + " bytes"); 
    ///         return 0; 
    ///     }
    /// } 
    ///    
    ///    Imports System
    /// Imports System.Management
    /// 
    /// ' This example demonstrates reading a property of a ManagementObject.
    /// Class Sample_ManagementObject 
    ///     Overloads Public Shared Function Main(args() As String) As Integer 
    ///         Dim disk As New ManagementObject("win32_logicaldisk.deviceid=""c:""")
    ///         disk.Get() 
    ///         Console.WriteLine(("Logical Disk Size = " & disk("Size").ToString() _
    ///             & " bytes"))
    ///         Return 0
    ///     End Function 
    /// End Class
    ///     
    ///  
    //CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC//
    [Serializable] 
    public class ManagementObject : ManagementBaseObject, ICloneable
    {
        // constants
        internal const string ID = "ID"; 
        internal const string RETURNVALUE = "RETURNVALUE";
 
        //Fields 

        private    IWbemClassObjectFreeThreaded    wmiClass; 
        internal ManagementScope                scope;
        internal ManagementPath                    path;
        internal ObjectGetOptions                options;
 
        //Used to represent whether this managementObject is currently bound to a wbemObject
        //or not - whenever an "identifying" property is changed (Path, Scope...) the object 
        //is "detached" (isBound becomes false) so that we refresh the wbemObject next time 
        //it's used, in conformance with the new property values.
        // 
        // ***
        // *    Changed isBound flag to wbemObject==null check.
        // *    private bool isBound;
        // *** 

        //This is used to identify a state in which a Put() operation was performed, but the 
        //object was not retrieved again, so the WMI object that's available at this point 
        //cannot be used for certain operations, namely CreateInstance, GetSubclasses, Derive,
        //Clone & ClassPath. 
        //When these operations are invoked, if we are in this state we need to implicitly
        //get the object...
        private bool putButNotGot;
 
        //Event fired when any "identifying" property changes.
        internal event IdentifierChangedEventHandler IdentifierChanged; 
 
        protected override void GetObjectData(SerializationInfo info, StreamingContext context)
        { 
            base.GetObjectData ( info, context ) ;
        }

        public new void Dispose() 
        {
            if (wmiClass != null) 
            { 
                wmiClass.Dispose();
                wmiClass = null; 
            }
            base.Dispose();
            GC.SuppressFinalize(this);
        } 

        //Fires IdentifierChanged event 
 
        internal void FireIdentifierChanged()
        { 
            if (IdentifierChanged != null)
                IdentifierChanged(this, null);
        }
 
        internal bool PutButNotGot
        { 
            get 
            { return putButNotGot; }
            set 
            { putButNotGot = value; }
        }

        //Called when IdentifierChanged() event fires 
        private void HandleIdentifierChange(object sender,
            IdentifierChangedEventArgs e) 
        { 
            // Detach the object from the WMI object underneath
            // 
            // ***
            // *    Changed isBound flag to wbemObject==null check.
            // *    isBound = false;
            // *** 
            wbemObject = null;
        } 
 
        internal bool IsBound
        { 
            get
            { return _wbemObject != null; }
        }
 
        //internal constructor
        internal static ManagementObject GetManagementObject( 
            IWbemClassObjectFreeThreaded wbemObject, 
            ManagementObject mgObj)
        { 
            ManagementObject newObject = new ManagementObject();
            newObject.wbemObject = wbemObject;

            if (null != mgObj) 
            {
                newObject.scope = ManagementScope._Clone(mgObj.scope); 
 
                if (null != mgObj.path)
                    newObject.path = ManagementPath._Clone(mgObj.path); 

                if (null != mgObj.options)
                    newObject.options = ObjectGetOptions._Clone(mgObj.options);
 
                // We set isBound last since assigning to Scope, Path
                // or Options can trigger isBound to be set false. 
                // 
                // ***
                // *    Changed isBound flag to wbemObject==null check. 
                // *    newObject.isBound = mgObj.isBound;
                // ***
            }
 
            return newObject;
        } 
 
        internal static ManagementObject GetManagementObject(
            IWbemClassObjectFreeThreaded wbemObject, 
            ManagementScope scope)
        {
            ManagementObject newObject = new ManagementObject();
            newObject.wbemObject = wbemObject; 

            newObject.path = new ManagementPath(ManagementPath.GetManagementPath(wbemObject)); 
            newObject.path.IdentifierChanged += new IdentifierChangedEventHandler(newObject.HandleIdentifierChange); 

            newObject.scope = ManagementScope._Clone(scope, new IdentifierChangedEventHandler(newObject.HandleIdentifierChange)); 

            // Since we have an object, we should mark it as bound. Note
            // that we do this AFTER setting Scope and Path, since those
            // have side-effects of setting isBound=false. 
            //
            // *** 
            // *    Changed isBound flag to wbemObject==null check. 
            // *    newObject.isBound = true;
            // *** 

            return newObject;
        }
 
        //default constructor
        ///  
        ///    Initializes a new instance of the  class. 
        /// 
        ///  
        /// Initializes a new instance of the  class. This is the
        ///    default constructor.
        /// 
        ///  
        ///    ManagementObject o = new ManagementObject();
        /// 
        /// //Now set the path on this object to bind it to a 'real' manageable entity 
        /// o.Path = new ManagementPath("Win32_LogicalDisk='c:'");
        /// 
        /// //Now it can be used
        /// Console.WriteLine(o["FreeSpace"]);
        ///    
        ///    Dim o As New ManagementObject() 
        /// Dim mp As New ManagementPath("Win32_LogicalDisk='c:'")
        /// 
        /// 'Now set the path on this object to bind it to a 'real' manageable entity 
        /// o.Path = mp
        /// 
        /// 'Now it can be used
        /// Console.WriteLine(o("FreeSpace"))
        ///    
        ///  
        public ManagementObject() : this ((ManagementScope)null, null, null) {}
 
        //parameterized constructors 
        /// 
        /// Initializes a new instance of the  class for the specified WMI 
        ///    object path. The path is provided as a .
        /// 
        /// A  that contains a path to a WMI object.
        ///  
        ///    ManagementPath p = new ManagementPath("Win32_Service.Name='Alerter'");
        /// ManagementObject o = new ManagementObject(p); 
        ///     
        ///    Dim p As New ManagementPath("Win32_Service.Name=""Alerter""")
        /// Dim o As New ManagementObject(p) 
        ///    
        /// 
        public ManagementObject(ManagementPath path) : this(null, path, null) {}
 
        /// 
        /// Initializes a new instance of the  class for the specified WMI object path. The path 
        ///    is provided as a string. 
        /// 
        /// A WMI path. 
        /// 
        ///    If the specified path is a relative path only (a server
        ///       or namespace is not specified), the default path is the local machine, and the
        ///       default namespace is the  
        ///       path (by default, root\cimv2). If the user specifies a
        ///       full path, the default settings are overridden. 
        ///  
        /// 
        ///    ManagementObject o = new ManagementObject("Win32_Service.Name='Alerter'"); 
        ///
        /// //or with a full path :
        ///
        /// ManagementObject o = new ManagementObject("\\\\MyServer\\root\\MyApp:MyClass.Key='abc'"); 
        ///    
        ///    Dim o As New ManagementObject("Win32_Service.Name=""Alerter""") 
        /// 
        /// //or with a full path :
        /// 
        /// Dim o As New ManagementObject("\\\\MyServer\\root\\MyApp:MyClass.Key=""abc""");
        ///    
        /// 
        public ManagementObject(string path) : this(null, new ManagementPath(path), null) {} 

        ///  
        /// Initializes a new instance of the  class bound to the specified 
        ///    WMI path, including the specified additional options.
        ///  
        /// A  containing the WMI path.
        /// An  containing additional options for binding to the WMI object. This parameter could be null if default options are to be used.
        /// 
        ///    ManagementPath p = new ManagementPath("Win32_ComputerSystem.Name='MyMachine'"); 
        ///
        /// //Set options for no context info, but requests amended qualifiers 
        /// //to be contained in the object 
        /// ObjectGetOptions opt = new ObjectGetOptions(null, true);
        /// 
        /// ManagementObject o = new ManagementObject(p, opt);
        ///
        /// Console.WriteLine(o.GetQualifierValue("Description"));
        ///     
        ///    Dim p As New ManagementPath("Win32_ComputerSystem.Name=""MyMachine""")
        /// 
        /// 'Set options for no context info, but requests amended qualifiers 
        /// 'to be contained in the object
        /// Dim opt As New ObjectGetOptions(null, true) 
        ///
        /// Dim o As New ManagementObject(p, opt)
        ///
        /// Console.WriteLine(o.GetQualifierValue("Description")); 
        ///    
        ///  
        public ManagementObject(ManagementPath path, ObjectGetOptions options) : this(null, path, options) {} 

        ///  
        /// Initializes a new instance of the  class bound to the specified WMI path, including the
        ///    specified additional options. In this variant, the path can be specified as a
        ///    string.
        ///  
        /// The WMI path to the object.
        /// An  representing options to get the specified WMI object. 
        ///  
        ///    //Set options for no context info,
        /// //but requests amended qualifiers to be contained in the object 
        /// ObjectGetOptions opt = new ObjectGetOptions(null, true);
        ///
        /// ManagementObject o = new ManagementObject("Win32_ComputerSystem.Name='MyMachine'", opt);
        /// 
        /// Console.WriteLine(o.GetQualifierValue("Description"));
        ///     
        ///    'Set options for no context info, 
        /// 'but requests amended qualifiers to be contained in the object
        /// Dim opt As New ObjectGetOptions(null, true) 
        ///
        /// Dim o As New ManagementObject("Win32_ComputerSystem.Name=""MyMachine""", opt);
        ///
        /// Console.WriteLine(o.GetQualifierValue("Description")) 
        ///    
        ///  
        public ManagementObject(string path, ObjectGetOptions options) : 
            this(new ManagementPath(path), options) {}
 
        /// 
        ///  Initializes a new instance of the 
        /// class bound to the specified WMI path that includes the specified options.
        ///  
        /// A  representing the scope in which the WMI object resides. In this version, scopes can only be WMI namespaces.
        /// A  representing the WMI path to the manageable object. 
        /// An  specifying additional options for getting the object. 
        /// 
        ///     Because WMI paths can be relative or full, a conflict between the scope and the path 
        ///       specified may arise. However, if a scope is specified and
        ///       a relative WMI path is specified, then there is no conflict. The
        ///       following are some possible conflicts: 
        ///     If a scope is not specified and a relative WMI 
        ///       path is specified, then the scope will default to the local machine's . 
        ///     If a scope is not specified and a full WMI path is 
        ///       specified, then the scope will be inferred from the scope portion of the full 
        ///       path. For example, the full WMI path: \\MyMachine\root\MyNamespace:MyClass.Name='abc' will
        ///    represent the WMI object 'MyClass.Name='abc'" in the scope 
        ///    '\\MyMachine\root\MyNamespace'. 
        /// If a scope is specified and a full WMI path is specified, then the scope
        /// will override the scope portion of the full path. For example, if the following
        /// scope was specified: \\MyMachine\root\MyScope, and the following full path was 
        /// specified: \\MyMachine\root\MyNamespace:MyClass.Name='abc', then look for the
        /// following object: 
        /// \\MyMachine\root\MyScope:MyClass.Name= 
        /// 'abc'
        /// (the scope part of the full path is ignored). 
        /// 
        /// 
        ///    ManagementScope s = new ManagementScope("\\\\MyMachine\\root\\cimv2");
        /// ManagementPath p = new ManagementPath("Win32_LogicalDisk.Name='c:'"); 
        /// ManagementObject o = new ManagementObject(s,p);
        ///     
        ///    Dim s As New ManagementScope("\\MyMachine\root\cimv2"); 
        /// Dim p As New ManagementPath("Win32_LogicalDisk.Name=""c:""");
        /// Dim o As New ManagementObject(s,p); 
        ///    
        /// 
        public ManagementObject(ManagementScope scope, ManagementPath path, ObjectGetOptions options)
            : base (null) 
        {
            ManagementObjectCTOR(scope, path, options); 
        } 

        void ManagementObjectCTOR(ManagementScope scope, ManagementPath path, ObjectGetOptions options) 
        {
            // We may use this to set the scope path
            string nsPath = String.Empty;
 
            if ((null != path) && !path.IsEmpty)
            { 
                //If this is a ManagementObject then the path has to be an instance, 
                // and if this is a ManagementClass the path has to be a class.
                if (GetType() == typeof(ManagementObject) && path.IsClass) 
                    throw new ArgumentOutOfRangeException("path");
                else if (GetType() == typeof(ManagementClass) && path.IsInstance)
                    throw new ArgumentOutOfRangeException("path");
 
                // Save the namespace path portion of the path (if any) in case
                // we don't have a scope 
                nsPath = path.GetNamespacePath((int)tag_WBEM_GET_TEXT_FLAGS.WBEMPATH_GET_SERVER_AND_NAMESPACE_ONLY); 

                if ((null != scope) && (scope.Path.NamespacePath.Length>0)) 
                {
                    // If the scope has a path too, the namespace portion of
                    // scope.path takes precedence over what is specified in path
                    path = new ManagementPath(path.RelativePath); 
                    path.NamespacePath = scope.Path.GetNamespacePath((int)tag_WBEM_GET_TEXT_FLAGS.WBEMPATH_GET_SERVER_AND_NAMESPACE_ONLY);
                } 
 
                // If the supplied path is a class or instance use it, otherwise
                // leave it empty 
                if (path.IsClass || path.IsInstance)
                    this.path = ManagementPath._Clone(path, new IdentifierChangedEventHandler(HandleIdentifierChange));

                else 
                    this.path = ManagementPath._Clone(null, new IdentifierChangedEventHandler(HandleIdentifierChange));
            } 
 
            if (null != options)
                this.options = ObjectGetOptions._Clone(options, new IdentifierChangedEventHandler(HandleIdentifierChange)); 

            if (null != scope)
                this.scope = ManagementScope._Clone(scope, new IdentifierChangedEventHandler(HandleIdentifierChange));
            else 
            {
                // Use the path if possible, otherwise let it default 
                if (nsPath.Length>0) 
                {
                    this.scope = new ManagementScope(nsPath); 
                    this.scope.IdentifierChanged += new IdentifierChangedEventHandler(HandleIdentifierChange);
                }
            }
 
            //register for identifier change events
            IdentifierChanged += new IdentifierChangedEventHandler(HandleIdentifierChange); 
            // *** 
            // *    Changed isBound flag to wbemObject==null check.
            // *    isBound = false; 
            // ***
            putButNotGot = false;

        } 

        ///  
        ///  Initializes a new instance of the  class 
        ///    bound to the specified WMI path, and includes the specified options. The scope and
        ///    the path are specified as strings. 
        /// 
        /// The scope for the WMI object.
        /// The WMI object path.
        /// An  representing additional options for getting the WMI object. 
        /// 
        ///    See the equivalent overload for details. 
        ///  
        /// 
        ///    GetObjectOptions opt = new GetObjectOptions(null, true); 
        /// ManagementObject o = new ManagementObject("root\\MyNamespace", "MyClass.Name='abc'", opt);
        ///    
        ///    Dim opt As New GetObjectOptions(null, true)
        /// Dim o As New ManagementObject("root\MyNamespace", "MyClass.Name=""abc""", opt); 
        ///    
        ///  
        public ManagementObject(string scopeString, string pathString, ObjectGetOptions options) 
            : this(new ManagementScope(scopeString), new ManagementPath(pathString), options) {}
 
        /// 
        /// Initializes a new instance of the  class that is serializable.
        /// 
        /// The  to populate with data. 
    /// The destination (see  ) for this serialization.
        protected ManagementObject(SerializationInfo info, StreamingContext context) : base(info, context) 
        { 
            ManagementObjectCTOR(null, null, null);
        } 

        /// 
        ///     Gets or sets the scope in which this object resides.
        ///  
        /// 
        ///  A . 
        ///  
        /// 
        ///     
        ///       Changing
        ///       this property after the management object has been bound to a WMI object in
        ///       a particular namespace results in releasing the original WMI object. This causes the management object to
        ///       be rebound to the new object specified by the new path properties and scope 
        ///       values. 
        ///    The rebinding is performed in a "lazy" manner, that is, only when a requested 
        ///       value requires the management object to be bound to the WMI object. Changes can 
        ///       be made to more than just this property before attempting to rebind (for example, modifying the scope
        ///       and path properties simultaneously). 
        /// 
        /// 
        ///    //Create the object with the default namespace (root\cimv2)
        /// ManagementObject o = new ManagementObject(); 
        ///
        /// //Change the scope (=namespace) of this object to the one specified. 
        /// o.Scope = new ManagementScope("root\\MyAppNamespace"); 
        ///    
        ///    'Create the object with the default namespace (root\cimv2) 
        /// Dim o As New ManagementObject()
        ///
        /// 'Change the scope (=namespace) of this object to the one specified.
        /// o.Scope = New ManagementScope("root\MyAppNamespace") 
        ///    
        ///  
        public ManagementScope Scope 
        {
            get 
            {
                if (scope == null)
                    return scope = ManagementScope._Clone(null);
                else 
                    return scope;
            } 
            set 
            {
                if (null != value) 
                {
                    if (null != scope)
                        scope.IdentifierChanged -= new IdentifierChangedEventHandler(HandleIdentifierChange);
 
                    scope = ManagementScope._Clone((ManagementScope)value, new IdentifierChangedEventHandler(HandleIdentifierChange));
 
                    //the scope property has changed so fire event 
                    FireIdentifierChanged();
                } 
                else
                    throw new ArgumentNullException("value");
            }
        } 

        ///  
        ///     Gets or sets the object's WMI path. 
        /// 
        ///  
        /// A  representing the object's path.
        /// 
        /// 
        ///     
        ///       Changing the property after the management
        ///       object has been bound to a WMI object in a particular namespace results in releasing 
        ///       the original WMI object. This causes the management object to be rebound to 
        ///       the new object specified by the new path properties and scope values.
        ///    The rebinding is performed in a "lazy" manner, that is, only when a requested 
        ///       value requires the management object to be bound to the WMI object. Changes can
        ///       be made to more than just the property before attempting to rebind (for example,
        ///       modifying the scope and path properties simultaneously).
        ///  
        /// 
        ///    ManagementObject o = new ManagementObject(); 
        /// 
        /// //Specify the WMI path to which this object should be bound to
        /// o.Path = new ManagementPath("MyClass.Name='MyName'"); 
        ///    
        ///    Dim o As New ManagementObject()
        ///
        /// 'Specify the WMI path to which this object should be bound to 
        /// o.Path = New ManagementPath("MyClass.Name=""MyName""");
        ///     
        ///  
        public virtual ManagementPath Path
        { 
            get
            {
                if (path == null)
                    return path = ManagementPath._Clone(null); 
                else
                    return path; 
            } 
            set
            { 
                ManagementPath newPath = (null != value) ? value : new ManagementPath();

                //If the new path contains a namespace path and the scope is currently defaulted,
                //we want to set the scope to the new namespace path provided 
                string nsPath = newPath.GetNamespacePath((int)tag_WBEM_GET_TEXT_FLAGS.WBEMPATH_GET_SERVER_AND_NAMESPACE_ONLY);
                if ((nsPath.Length > 0) && (scope != null) && (scope.IsDefaulted)) 
                    Scope = new ManagementScope(nsPath); 

                // This must be a class for a ManagementClass object or an instance for a ManagementObject, or empty 
                if ((GetType() == typeof(ManagementObject) && newPath.IsInstance) ||
                    (GetType() == typeof(ManagementClass) && newPath.IsClass) ||
                    newPath.IsEmpty)
                { 
                    if (null != path)
                        path.IdentifierChanged -=  new IdentifierChangedEventHandler(HandleIdentifierChange); 
 
                    path = ManagementPath._Clone((ManagementPath)value, new IdentifierChangedEventHandler(HandleIdentifierChange));
 
                    //the path property has changed so fire event
                    FireIdentifierChanged();
                }
                else 
                    throw new ArgumentOutOfRangeException("value");
            } 
        } 

        ///  
        ///    
        ///       Gets or
        ///       sets additional information to use when retrieving the object.
        ///  
        /// 
        /// An  to use when retrieving the object. 
        ///  
        /// 
        ///     When the property is 
        ///       changed after the management object has been bound to a WMI object, the management object
        ///       is disconnected from the original WMI object and later rebound using the new
        ///       options.
        ///  
        /// 
        ///    //Contains default options 
        /// ManagementObject o = new ManagementObject("MyClass.Name='abc'"); 
        ///
        /// //Replace default options, in this case requesting retrieval of 
        /// //amended qualifiers along with the WMI object.
        /// o.Options = new ObjectGetOptions(null, true);
        ///    
        ///    'Contains default options 
        /// Dim o As New ManagementObject("MyClass.Name=""abc""")
        /// 
        /// 'Replace default options, in this case requesting retrieval of 
        /// 'amended qualifiers along with the WMI object.
        /// o.Options = New ObjectGetOptions(null, true) 
        ///    
        /// 
        public ObjectGetOptions Options
        { 
            get
            { 
                if (options == null) 
                    return options = ObjectGetOptions._Clone(null);
                else 
                    return options;
            }
            set
            { 
                if (null != value)
                { 
                    if (null != options) 
                        options.IdentifierChanged -= new IdentifierChangedEventHandler(HandleIdentifierChange);
 
                    options = ObjectGetOptions._Clone((ObjectGetOptions)value, new IdentifierChangedEventHandler(HandleIdentifierChange));

                    //the options property has changed so fire event
                    FireIdentifierChanged(); 
                }
                else 
                    throw new ArgumentNullException("value"); 
            }
        } 

        /// 
        ///    Gets or sets the path to the object's class.
        ///  
        /// 
        /// A  representing the path to the object's 
        ///    class. 
        /// 
        ///  
        ///    This property is read-only.
        /// 
        /// 
        ///    ManagementObject o = new ManagementObject("MyClass.Name='abc'"); 
        ///
        /// //Get the class definition for the object above. 
        /// ManagementClass c = new ManagementClass(o.ClassPath); 
        ///    
        ///    Dim o As New ManagementObject("MyClass.Name=""abc""") 
        ///
        /// 'Get the class definition for the object above.
        /// Dim c As New ManagementClass(o.ClassPath);
        ///     
        /// 
        public override ManagementPath ClassPath 
        { 
            get
            { 
                Object serverName = null;
                Object scopeName = null;
                Object className = null;
                int propertyType = 0; 
                int propertyFlavor = 0;
 
                if (PutButNotGot) 
                {
                    Get(); 
                    PutButNotGot = false;
                }

                // 
                // Removed Initialize call since wbemObject is a property that will call Initialize ( true ) on
                // its getter. 
                // 
                // Initialize ( ) ;
 
                int status = wbemObject.Get_("__SERVER", 0, ref serverName, ref propertyType, ref propertyFlavor);

                if (status >= 0)
                { 
                    status = wbemObject.Get_("__NAMESPACE", 0, ref scopeName, ref propertyType, ref propertyFlavor);
 
                    if (status >= 0) 
                    {
                        status = wbemObject.Get_("__CLASS", 0, ref className, ref propertyType, ref propertyFlavor); 
                    }
                }

                if (status < 0) 
                {
                    if ((status & 0xfffff000) == 0x80041000) 
                        ManagementException.ThrowWithExtendedInfo((ManagementStatus)status); 
                    else
                        Marshal.ThrowExceptionForHR(status); 
                }

                ManagementPath classPath = new ManagementPath();
 
                // initialize in case of throw
                classPath.Server = String.Empty; 
                classPath.NamespacePath = String.Empty; 
                classPath.ClassName = String.Empty;
 				 
                // Some of these may throw if they are NULL
                try
                {
                    classPath.Server = (string)(serverName is System.DBNull ? "" : serverName); 
                    classPath.NamespacePath = (string)(scopeName is System.DBNull ? "" : scopeName);
                    classPath.ClassName = (string)(className is System.DBNull ? "" : className); 
                } 
                catch
                { 
                }

                return classPath;
            } 
        }
 
        // 
        //Methods
        // 

        //******************************************************
        //Get
        //***************************************************** 
        /// 
        ///    Binds to the management object. 
        ///  
        /// 
        ///     Binds to the management object. 
        /// 
        /// 
        ///     The method is implicitly
        ///       invoked at the first attempt to get or set information to the WMI object. It 
        ///       can also be explicitly invoked at the user's discretion, to better control the
        ///       timing and manner of retrieval. 
        ///  
        /// 
        ///    ManagementObject o = new ManagementObject("MyClass.Name='abc'"); 
        /// string s = o["SomeProperty"]; //this causes an implicit Get().
        ///
        /// //or :
        /// 
        /// ManagementObject o= new ManagementObject("MyClass.Name= 'abc'");
        /// o.Get(); //explicitly 
        /// //Now it's faster because the object has already been retrieved. 
        /// string s = o["SomeProperty"];
        ///     
        ///    Dim o As New ManagementObject("MyClass.Name=""abc""")
        /// string s = o("SomeProperty") 'this causes an implicit Get().
        ///
        /// 'or : 
        ///
        /// Dim o As New ManagementObject("MyClass.Name= ""abc""") 
        /// o.Get()  'explicitly 
        /// 'Now it's faster because the object has already been retrieved.
        /// string s = o("SomeProperty"); 
        ///    
        /// 
        public void Get()
        { 
            IWbemClassObjectFreeThreaded tempObj = null;
 
            Initialize ( false ) ; // this may throw 

            if ((null == path) || (path.Path.Length==0)) 
                throw new InvalidOperationException();
            else
            {
                ObjectGetOptions gOptions = 
                    (null == options) ? new ObjectGetOptions() : options;
 
                SecurityHandler securityHandler = null; 
                int status                        = (int)ManagementStatus.NoError;
 
                try
                {
                    securityHandler = scope.GetSecurityHandler();
 
                    status = scope.GetSecuredIWbemServicesHandler( scope.GetIWbemServices() ).GetObject_(path.RelativePath,
                                                            gOptions.Flags, 
                                                            gOptions.GetContext(), 
                                                            ref tempObj,
                                                            IntPtr.Zero ); 

                    if (status < 0)
                    {
                        if ((status & 0xfffff000) == 0x80041000) 
                            ManagementException.ThrowWithExtendedInfo((ManagementStatus)status);
                        else 
                            Marshal.ThrowExceptionForHR(status); 
                    }
 
                    wbemObject = tempObj;
                }
                finally
                { 
                    if (securityHandler != null)
                        securityHandler.Reset(); 
                } 
            }
        } 

        //*****************************************************
        //Get
        //***************************************************** 
        /// 
        ///     Binds to the management object asynchronously. 
        ///  
        /// The object to receive the results of the operation as events.
        ///  
        ///    The method will issue the request to get the object
        ///       and then will immediately return. The results of the operation will then be
        ///       delivered through events being fired on the watcher object provided.
        ///  
        /// 
        ///    ManagementObject o = new ManagementObject("MyClass.Name='abc'"); 
        /// 
        /// //Set up handlers for asynchronous get
        /// MyHandler h = new MyHandler(); 
        /// ManagementOperationObserver ob = new ManagementOperationObserver();
        /// ob.Completed += new CompletedEventHandler(h.Done);
        ///
        /// //Get the object asynchronously 
        /// o.Get(ob);
        /// 
        /// //Wait until operation is completed 
        /// while (!h.Completed)
        ///     System.Threading.Thread.Sleep (1000); 
        ///
        /// //Here we can use the object
        /// Console.WriteLine(o["SomeProperty"]);
        /// 
        /// public class MyHandler
        /// { 
        ///     private bool completed = false; 
        ///
        ///     public void Done(object sender, CompletedEventArgs e) { 
        ///         Console.WriteLine("async Get completed !");
        ///         completed = true;
        ///     }
        /// 
        ///     public bool Completed {
        ///         get { 
        ///             return completed; 
        ///         }
        ///     } 
        /// }
        ///    
        ///    Dim o As New ManagementObject("MyClass.Name=""abc""")
        /// 
        /// 'Set up handlers for asynchronous get
        /// Dim h As New MyHandler() 
        /// Dim ob As New ManagementOperationObserver() 
        /// ob.Completed += New CompletedEventHandler(h.Done)
        /// 
        /// 'Get the object asynchronously
        /// o.Get(ob)
        ///
        /// 'Wait until operation is completed 
        /// While Not h.Completed
        ///     System.Threading.Thread.Sleep(1000) 
        /// End While 
        ///
        /// 'Here we can use the object 
        /// Console.WriteLine(o("SomeProperty"))
        ///
        /// Public Class MyHandler
        ///     Private _completed As Boolean = false; 
        ///
        ///     Public Sub Done(sender As Object, e As EventArrivedEventArgs) 
        ///         Console.WriteLine("async Get completed !") 
        ///         _completed = True
        ///     End Sub 
        ///
        ///     Public ReadOnly Property Completed() As Boolean
        ///        Get
        ///            Return _completed 
        ///        End Get
        ///     End Property 
        /// End Class 
        ///    
        ///  
        public void Get(ManagementOperationObserver watcher)
        {
            Initialize ( false ) ;
 
            if ((null == path) || (path.Path.Length==0))
                throw new InvalidOperationException(); 
            else if (null == watcher) 
                throw new ArgumentNullException("watcher");
            else 
            {
                IWbemServices wbemServices = scope.GetIWbemServices();

                ObjectGetOptions o = ObjectGetOptions._Clone(options); 

                WmiGetEventSink sink = watcher.GetNewGetSink( 
                    scope, 
                    o.Context,
                    this); 

                // If someone has registered for progress, make sure we flag it
                if (watcher.HaveListenersForProgress)
                    o.SendStatus = true; 

                SecurityHandler securityHandler = null; 
                int status                        = (int)ManagementStatus.NoError; 

                securityHandler = scope.GetSecurityHandler(); 

                status = scope.GetSecuredIWbemServicesHandler(wbemServices).GetObjectAsync_(path.RelativePath,
                                            o.Flags,
                                            o.GetContext(), 
                                            sink.Stub);
 
 
                if (securityHandler != null)
                    securityHandler.Reset(); 

                if (status < 0)
                {
                    watcher.RemoveSink(sink); 
                    if ((status & 0xfffff000) == 0x80041000)
                        ManagementException.ThrowWithExtendedInfo((ManagementStatus)status); 
                    else 
                        Marshal.ThrowExceptionForHR(status);
                } 
            }
        }

        //****************************************************** 
        //GetRelated
        //*************************************************** 
        ///  
        ///    Gets a collection of objects related to the object (associators).
        ///  
        /// 
        ///    Gets a collection of objects related to the object (associators).
        /// 
        ///  
        /// A  containing the
        ///    related objects. 
        ///  
        /// 
        ///     The operation is equivalent to an ASSOCIATORS OF query where ResultClass = relatedClass. 
        /// 
        /// 
        ///    ManagementObject o = new ManagementObject("Win32_Service='Alerter'");
        /// foreach(ManagementBaseObject b in o.GetRelated()) 
        ///     Console.WriteLine("Object related to Alerter service : ", b.Path);
        ///     
        ///    Dim o As New ManagementObject("Win32_Service=""Alerter""") 
        /// Dim b As ManagementBaseObject
        /// For Each b In o.GetRelated() 
        ///     Console.WriteLine("Object related to Alerter service : ", b.Path)
        /// Next b
        ///    
        ///  
        public ManagementObjectCollection GetRelated()
        { 
            return GetRelated((string)null); 
        }
 
        //******************************************************
        //GetRelated
        //****************************************************
        ///  
        ///    Gets a collection of objects related to the object (associators).
        ///  
        /// A class of related objects.  
        /// 
        ///    A  containing the related objects. 
        /// 
        /// 
        ///    ManagementObject o = new ManagementObject("Win32_Service='Alerter'");
        /// foreach (ManagementBaseObject b in o.GetRelated("Win32_Service") 
        ///     Console.WriteLine("Service related to the Alerter service {0} is {1}", b["Name"], b["State"]);
        ///     
        ///    Dim o As New ManagementObject("Win32_Service=""Alerter"""); 
        /// Dim b As ManagementBaseObject
        /// For Each b in o.GetRelated("Win32_Service") 
        ///     Console.WriteLine("Service related to the Alerter service {0} is {1}", b("Name"), b("State"))
        /// Next b
        ///    
        ///  
        public ManagementObjectCollection GetRelated(
            string relatedClass) 
        { 
            return GetRelated(relatedClass, null, null, null, null, null, false, null);
        } 


        //*****************************************************
        //GetRelated 
        //****************************************************
        ///  
        ///    Gets a collection of objects related to the object (associators). 
        /// 
        /// The class of the related objects.  
        /// The relationship class of interest. 
        /// The qualifier required to be present on the relationship class. 
        /// The qualifier required to be present on the related class. 
        /// The role that the related class is playing in the relationship.  
        /// The role that this class is playing in the relationship. 
        /// When this method returns, it contains only class definitions for the instances that match the query.  
        /// Extended options for how to execute the query.  
        /// 
        ///    A  containing the related objects. 
        /// 
        /// 
        ///    This operation is equivalent to an ASSOCIATORS OF query where ResultClass = <relatedClass>.
        ///  
        public ManagementObjectCollection GetRelated(
            string relatedClass, 
            string relationshipClass, 
            string relationshipQualifier,
            string relatedQualifier, 
            string relatedRole,
            string thisRole,
            bool classDefinitionsOnly,
            EnumerationOptions options) 
        {
            if ((null == path) || (path.Path.Length==0)) 
                throw new InvalidOperationException(); 

            Initialize ( false ) ; 

            IEnumWbemClassObject enumWbem = null;
            EnumerationOptions o = (null != options) ? options : new EnumerationOptions();
            RelatedObjectQuery q = new RelatedObjectQuery( 
                path.Path,
                relatedClass, 
                relationshipClass, 
                relationshipQualifier,
                relatedQualifier, relatedRole, 
                thisRole, classDefinitionsOnly);


            //Make sure the EnumerateDeep flag bit is turned off because it's invalid for queries 
            o.EnumerateDeep = true; //note this turns the FLAG to 0 !!
 
            SecurityHandler securityHandler = null; 
            int status                        = (int)ManagementStatus.NoError;
 
            try
            {
                securityHandler = scope.GetSecurityHandler();
 
                status = scope.GetSecuredIWbemServicesHandler(scope.GetIWbemServices() ).ExecQuery_(
                                                        q.QueryLanguage, 
                                                        q.QueryString, 
                                                        o.Flags,
                                                        o.GetContext(), 
                                                        ref enumWbem);


                if (status < 0) 
                {
                    if ((status & 0xfffff000) == 0x80041000) 
                        ManagementException.ThrowWithExtendedInfo((ManagementStatus)status); 
                    else
                        Marshal.ThrowExceptionForHR(status); 
                }

            }
            finally 
            {
                if (securityHandler != null) 
                    securityHandler.Reset(); 
            }
 
            //Create collection object
            return new ManagementObjectCollection(scope, o, enumWbem);
        }
 

        //***************************************************** 
        //GetRelated 
        //***************************************************
        ///  
        ///     Gets a collection of objects
        ///       related to the object (associators) asynchronously. This call returns immediately, and a
        ///       delegate is called when the results are available.
        ///  
        /// The object to use to return results. 
        public void GetRelated( 
            ManagementOperationObserver watcher) 
        {
            GetRelated(watcher, (string)null); 
        }

        //*****************************************************
        //GetRelated 
        //****************************************************
        ///  
        ///    Gets a collection of objects related to the object (associators). 
        /// 
        /// The object to use to return results.  
        /// The class of related objects. 
        /// 
        ///    This operation is equivalent to an ASSOCIATORS OF query where ResultClass = <relatedClass>.
        ///  
        public void GetRelated(
            ManagementOperationObserver watcher, 
            string relatedClass) 
        {
            GetRelated(watcher, relatedClass, null, null, null, null, null, false, null); 
        }


        //***************************************************** 
        //GetRelated
        //**************************************************** 
        ///  
        ///    Gets a collection of objects related to the object (associators).
        ///  
        /// The object to use to return results. 
        /// The class of the related objects. 
        /// The relationship class of interest. 
        /// The qualifier required to be present on the relationship class.  
        /// The qualifier required to be present on the related class. 
        /// The role that the related class is playing in the relationship.  
        /// The role that this class is playing in the relationship.  
        /// Return only class definitions for the instances that match the query. 
        /// Extended options for how to execute the query. 
        /// 
        ///    This operation is equivalent to an ASSOCIATORS OF query where ResultClass = <relatedClass>.
        /// 
        public void GetRelated( 
            ManagementOperationObserver watcher,
            string relatedClass, 
            string relationshipClass, 
            string relationshipQualifier,
            string relatedQualifier, 
            string relatedRole,
            string thisRole,
            bool classDefinitionsOnly,
            EnumerationOptions options) 
        {
            if ((null == path) || (path.Path.Length==0)) 
                throw new InvalidOperationException(); 

            Initialize ( true ) ; 

            if (null == watcher)
                throw new ArgumentNullException("watcher");
            else 
            {
                // Ensure we switch off ReturnImmediately as this is invalid for async calls 
                EnumerationOptions o = (null != options) 
                    ? (EnumerationOptions)options.Clone() : new EnumerationOptions();
                o.ReturnImmediately = false; 

                // If someone has registered for progress, make sure we flag it
                if (watcher.HaveListenersForProgress)
                    o.SendStatus = true; 

                WmiEventSink sink = watcher.GetNewSink( 
                    scope, 
                    o.Context);
 
                RelatedObjectQuery q = new RelatedObjectQuery(path.Path, relatedClass,
                    relationshipClass, relationshipQualifier,
                    relatedQualifier, relatedRole,
                    thisRole, classDefinitionsOnly); 

 
                //Make sure the EnumerateDeep flag bit is turned off because it's invalid for queries 
                o.EnumerateDeep = true; //note this turns the FLAG to 0 !!
 
                SecurityHandler securityHandler    = null;
                int status                        = (int)ManagementStatus.NoError;

                securityHandler = scope.GetSecurityHandler(); 

                status = scope.GetSecuredIWbemServicesHandler( scope.GetIWbemServices() ).ExecQueryAsync_( 
                                                        q.QueryLanguage, 
                                                        q.QueryString,
                                                        o.Flags, 
                                                        o.GetContext(),
                                                        sink.Stub);

 
                securityHandler.Reset();
 
                if (status < 0) 
                {
                    watcher.RemoveSink(sink); 
                    if ((status & 0xfffff000) == 0x80041000)
                        ManagementException.ThrowWithExtendedInfo((ManagementStatus)status);
                    else
                        Marshal.ThrowExceptionForHR(status); 
                }
            } 
        } 

        //******************************************************************** 
        //GetRelationships
        //*******************************************************************
        /// 
        ///    Gets a collection of associations to the object. 
        /// 
        ///  
        ///    Gets a collection of associations to the object. 
        /// 
        ///  
        /// A  containing the association objects.
        /// 
        /// 
        ///     The operation is equivalent to a REFERENCES OF query. 
        /// 
        public ManagementObjectCollection GetRelationships() 
        { 
            return GetRelationships((string)null);
        } 

        //********************************************************************
        //GetRelationships
        //******************************************************************* 
        /// 
        ///    Gets a collection of associations to the object. 
        ///  
        /// The associations to include. 
        ///  
        ///    A  containing the association objects.
        /// 
        /// 
        ///    This operation is equivalent to a REFERENCES OF query where the AssocClass = <relationshipClass>. 
        /// 
        public ManagementObjectCollection GetRelationships( 
            string relationshipClass) 
        {
            return GetRelationships(relationshipClass, null, null, false, null); 
        }


        //******************************************************************* 
        //GetRelationships
        //******************************************************************* 
        ///  
        ///    Gets a collection of associations to the object.
        ///  
        /// The type of relationship of interest. 
        /// The qualifier to be present on the relationship. 
        /// The role of this object in the relationship. 
        /// When this method returns, it contains only the class definitions for the result set.  
        /// The extended options for the query execution. 
        ///  
        ///    A  containing the association objects. 
        /// 
        ///  
        ///    This operation is equivalent to a REFERENCES OF query with possibly all the extensions.
        /// 
        public ManagementObjectCollection GetRelationships(
            string relationshipClass, 
            string relationshipQualifier,
            string thisRole, 
            bool classDefinitionsOnly, 
            EnumerationOptions options)
        { 
            if ((null == path) || (path.Path.Length==0))
                throw new InvalidOperationException();

            Initialize ( false ) ; 

            IEnumWbemClassObject enumWbem = null; 
            EnumerationOptions o = 
                (null != options) ? options : new EnumerationOptions();
            RelationshipQuery q = new RelationshipQuery(path.Path, relationshipClass, 
                relationshipQualifier, thisRole, classDefinitionsOnly);


            //Make sure the EnumerateDeep flag bit is turned off because it's invalid for queries 
            o.EnumerateDeep = true; //note this turns the FLAG to 0 !!
 
            SecurityHandler securityHandler = null; 
            int status                        = (int)ManagementStatus.NoError;
 
            try
            {
                securityHandler = scope.GetSecurityHandler();
 
                status = scope.GetSecuredIWbemServicesHandler(scope.GetIWbemServices()).ExecQuery_(
                                                    q.QueryLanguage, 
                                                    q.QueryString, 
                                                    o.Flags,
                                                    o.GetContext(), 
                                                    ref enumWbem );


                if (status < 0) 
                {
                    if ((status & 0xfffff000) == 0x80041000) 
                        ManagementException.ThrowWithExtendedInfo((ManagementStatus)status); 
                    else
                        Marshal.ThrowExceptionForHR(status); 
                }

            }
            finally 
            {
                if (securityHandler != null) 
                    securityHandler.Reset(); 
            }
 
            //Create collection object
            return new ManagementObjectCollection(scope, o, enumWbem);
        }
 

        //******************************************************************** 
        //GetRelationships 
        //*******************************************************************
        ///  
        ///    Gets a collection of associations to the object.
        /// 
        /// The object to use to return results. 
        ///  
        /// This operation is equivalent to a REFERENCES OF query
        ///  
        public void GetRelationships( 
            ManagementOperationObserver watcher)
        { 
            GetRelationships(watcher, (string)null);
        }

        //******************************************************************** 
        //GetRelationships
        //******************************************************************** 
        ///  
        ///    Gets a collection of associations to the object.
        ///  
        /// The object to use to return results. 
        /// The associations to include. 
        /// 
        ///    This operation is equivalent to a REFERENCES OF query where the AssocClass = <relationshipClass>. 
        /// 
        public void GetRelationships( 
            ManagementOperationObserver watcher, 
            string relationshipClass)
        { 
            GetRelationships(watcher, relationshipClass, null, null, false, null);
        }

 
        //*******************************************************************
        //GetRelationships 
        //******************************************************************** 
        /// 
        ///    Gets a collection of associations to the object. 
        /// 
        /// The object to use to return results. 
        /// The type of relationship of interest. 
        /// The qualifier to be present on the relationship.  
        /// The role of this object in the relationship. 
        /// When this method returns, it contains only the class definitions for the result set.  
        /// The extended options for the query execution.  
        /// 
        ///    This operation is equivalent to a REFERENCES OF query with possibly all the extensions. 
        /// 
        public void GetRelationships(
            ManagementOperationObserver watcher,
            string relationshipClass, 
            string relationshipQualifier,
            string thisRole, 
            bool classDefinitionsOnly, 
            EnumerationOptions options)
        { 
            if ((null == path)  || (path.Path.Length==0))
                throw new InvalidOperationException();
            if (null == watcher)
                throw new ArgumentNullException("watcher"); 
            else
            { 
                Initialize ( false ) ; 

                // Ensure we switch off ReturnImmediately as this is invalid for async calls 
                EnumerationOptions o =
                    (null != options) ? (EnumerationOptions)options.Clone() :
                    new EnumerationOptions();
                o.ReturnImmediately = false; 

                // If someone has registered for progress, make sure we flag it 
                if (watcher.HaveListenersForProgress) 
                    o.SendStatus = true;
 
                WmiEventSink sink = watcher.GetNewSink(scope, o.Context);

                RelationshipQuery q = new RelationshipQuery(path.Path, relationshipClass,
                    relationshipQualifier, thisRole, classDefinitionsOnly); 

 
                //Make sure the EnumerateDeep flag bit is turned off because it's invalid for queries 
                o.EnumerateDeep = true; //note this turns the FLAG to 0 !!
 
                SecurityHandler securityHandler = null;
                int status                        = (int)ManagementStatus.NoError;

                securityHandler = scope.GetSecurityHandler(); 

                status = scope.GetSecuredIWbemServicesHandler( scope.GetIWbemServices() ).ExecQueryAsync_( 
                                                        q.QueryLanguage, 
                                                        q.QueryString,
                                                        o.Flags, 
                                                        o.GetContext(),
                                                        sink.Stub );

 
                if (securityHandler != null)
                    securityHandler.Reset(); 
 
                if (status < 0)
                { 
                    watcher.RemoveSink(sink);
                    if ((status & 0xfffff000) == 0x80041000)
                        ManagementException.ThrowWithExtendedInfo((ManagementStatus)status);
                    else 
                        Marshal.ThrowExceptionForHR(status);
                } 
            } 
        }
 
        //*****************************************************
        //Put
        //*****************************************************
        ///  
        ///    Commits the changes to the object.
        ///  
        ///  
        ///    Commits the changes to the object.
        ///  
        /// 
        /// A  containing the path to the committed
        ///    object.
        ///  
        public ManagementPath Put()
        { 
            return Put((PutOptions) null); 
        }
 

        //*****************************************************
        //Put
        //****************************************************** 
        /// 
        ///    Commits the changes to the object. 
        ///  
        /// The options for how to commit the changes. 
        ///  
        ///    A  containing the path to the committed object.
        /// 
        public ManagementPath Put(PutOptions options)
        { 
            ManagementPath newPath = null;
            Initialize ( true ) ; 
            PutOptions o = (null != options) ? options : new PutOptions(); 

            IWbemServices wbemServices = scope.GetIWbemServices(); 

            //
            // Must do this convoluted allocation since the IWbemServices ref IWbemCallResult
            // has been redefined to be an IntPtr.  Due to the fact that it wasn't possible to 
            // pass NULL for the optional argument.
            // 
            IntPtr ppwbemCallResult            = IntPtr.Zero; 
            IntPtr pwbemCallResult            = IntPtr.Zero;
            IWbemCallResult wbemCallResult    = null; 
            SecurityHandler securityHandler    = null;
            int status                        = (int)ManagementStatus.NoError;

            try 
            {
                securityHandler = scope.GetSecurityHandler(); 
 
                ppwbemCallResult = Marshal.AllocHGlobal(IntPtr.Size);
                Marshal.WriteIntPtr(ppwbemCallResult, IntPtr.Zero);        // Init to NULL. 

                if (IsClass)
                {
                    status = scope.GetSecuredIWbemServicesHandler(wbemServices).PutClass_( wbemObject, 
                        o.Flags | (int)tag_WBEM_GENERIC_FLAG_TYPE.WBEM_FLAG_RETURN_IMMEDIATELY,
                        o.GetContext(), 
                        ppwbemCallResult ); 
                }
                else 
                {
                    status = scope.GetSecuredIWbemServicesHandler(wbemServices).PutInstance_(wbemObject,
                        o.Flags | (int)tag_WBEM_GENERIC_FLAG_TYPE.WBEM_FLAG_RETURN_IMMEDIATELY,
                        o.GetContext(), 
                        ppwbemCallResult);
                } 
 

                // Keep this statement here; otherwise, there'll be a leak in error cases. 
                pwbemCallResult = Marshal.ReadIntPtr(ppwbemCallResult);

                wbemCallResult = (IWbemCallResult)Marshal.GetObjectForIUnknown(pwbemCallResult);
 
                int hr;
                status = wbemCallResult.GetCallStatus_((int)tag_WBEM_TIMEOUT_TYPE.WBEM_INFINITE, out hr); 
 
                if (status >= 0)
                    status = hr; 

                if (status < 0)
                {
                    if ((status & 0xfffff000) == 0x80041000) 
                        ManagementException.ThrowWithExtendedInfo((ManagementStatus)status);
                    else 
                        Marshal.ThrowExceptionForHR(status); 
                }
 
                newPath = GetPath(wbemCallResult);

//                if (IsClass)
//                    newPath.RelativePath = ClassName; 
            }
            finally 
            { 
                if (securityHandler != null)
                    securityHandler.Reset(); 

                if (ppwbemCallResult != IntPtr.Zero)                    // Cleanup from allocations above.
                    Marshal.FreeHGlobal(ppwbemCallResult);
 
                if (pwbemCallResult != IntPtr.Zero)
                    Marshal.Release(pwbemCallResult); 
 
                if (wbemCallResult != null)
                    Marshal.ReleaseComObject(wbemCallResult); 
            }

            //Set the flag that tells the object that we've put it, so that a refresh is
            //triggered when an operation that needs this is invoked (CreateInstance, Derive). 
            putButNotGot = true;
 
            // Update our path to address the object just put. Note that 
            // we do this in such a way as to NOT trigger the setting of this
            // ManagementObject into an unbound state 
            path.SetRelativePath(newPath.RelativePath);

            return newPath;
        } 

        private ManagementPath GetPath(IWbemCallResult callResult) 
        { 
            ManagementPath newPath = null;
            int status = (int)ManagementStatus.NoError; 

            try
            {
                // 
                // Obtain the path from the call result.
                // Note this will return the relative path at best. 
                // 
                string resultPath = null;
 
                status = callResult.GetResultString_(
                    (int)tag_WBEM_TIMEOUT_TYPE.WBEM_INFINITE,
                    out resultPath);
 
                if (status >= 0)
                { 
                    newPath = new ManagementPath(scope.Path.Path); 
                    newPath.RelativePath = resultPath;
                } 
                else
                {
                    //
                    // That didn't work. Use the path in the object instead. 
                    //
                    object pathValue = GetPropertyValue("__PATH"); 
 
                    // No path? Try Relpath?
                    if (pathValue != null) 
                        newPath = new ManagementPath((string)pathValue);
                    else
                    {
                        pathValue = GetPropertyValue("__RELPATH"); 

                        if (pathValue != null) 
                        { 
                            newPath = new ManagementPath(scope.Path.Path);
                            newPath.RelativePath = (string)pathValue; 
                        }
                    }
                }
 
            }
            catch 
           { 
           }
 
            if (newPath == null)
                newPath = new ManagementPath();

            return newPath; 
        }
 
        ///  
        ///    Commits the changes to the object, asynchronously.
        ///  
        /// A  used to handle the progress and results of the asynchronous operation.
        public void Put(ManagementOperationObserver watcher)
        {
            Put(watcher, null); 
        }
 
        ///  
        ///    Commits the changes to the object asynchronously and
        ///       using the specified options. 
        /// 
        /// A  used to handle the progress and results of the asynchronous operation.
        /// A  used to specify additional options for the commit operation.
        public void Put(ManagementOperationObserver watcher, PutOptions options) 
        {
            if (null == watcher) 
                throw new ArgumentNullException("watcher"); 
            else
            { 
                Initialize ( false ) ;

                PutOptions o = (null == options) ?
                    new PutOptions() : (PutOptions)options.Clone(); 

                // If someone has registered for progress, make sure we flag it 
                if (watcher.HaveListenersForProgress) 
                    o.SendStatus = true;
 
                IWbemServices wbemServices = scope.GetIWbemServices();
                WmiEventSink sink = watcher.GetNewPutSink(scope,
                    o.Context, scope.Path.GetNamespacePath((int)tag_WBEM_GET_TEXT_FLAGS.WBEMPATH_GET_SERVER_AND_NAMESPACE_ONLY), ClassName);
 
                // Add ourselves to the watcher so we can update our state
                sink.InternalObjectPut += 
                    new InternalObjectPutEventHandler(this.HandleObjectPut); 

                SecurityHandler securityHandler    = null; 
                // Assign to error initially to insure internal event handler cleanup
                // on non-management exception.
                int status                        = (int)ManagementStatus.Failed;
 
                securityHandler = scope.GetSecurityHandler();
 
                if (IsClass) 
                {
                    status = scope.GetSecuredIWbemServicesHandler( wbemServices ).PutClassAsync_( 
                        wbemObject,
                        o.Flags,
                        o.GetContext(),
                        sink.Stub); 
                }
                else 
                { 
                    status = scope.GetSecuredIWbemServicesHandler( wbemServices ).PutInstanceAsync_(
                        wbemObject, 
                        o.Flags,
                        o.GetContext(),
                        sink.Stub);
                } 

 
                if (securityHandler != null) 
                    securityHandler.Reset();
 
                if (status < 0)
                {
                    sink.InternalObjectPut -= new InternalObjectPutEventHandler(this.HandleObjectPut);
                    watcher.RemoveSink(sink); 
                    if ((status & 0xfffff000) == 0x80041000)
                        ManagementException.ThrowWithExtendedInfo((ManagementStatus)status); 
                    else 
                        Marshal.ThrowExceptionForHR(status);
                } 
            }
        }

        internal void HandleObjectPut(object sender, InternalObjectPutEventArgs e) 
        {
            try 
            { 
                if (sender is WmiEventSink)
                { 
                    ((WmiEventSink)sender).InternalObjectPut -= new InternalObjectPutEventHandler(this.HandleObjectPut);
                    putButNotGot = true;
                    path.SetRelativePath(e.Path.RelativePath);
                } 
            }
            catch 
            { 
            }
        } 

        //*****************************************************
        //CopyTo
        //****************************************************** 
        /// 
        ///    Copies the object to a different location. 
        ///  
        /// 
        ///    Copies the object to a different location. 
        /// 
        /// The  to which the object should be copied. 
        /// 
        ///    The new path of the copied object. 
        /// 
        public ManagementPath CopyTo(ManagementPath path) 
        { 
            return CopyTo(path,(PutOptions)null);
        } 

        /// 
        ///    Copies the object to a different location.
        ///  
        /// The path to which the object should be copied. 
        ///  
        ///    The new path of the copied object. 
        /// 
        public ManagementPath CopyTo(string path) 
        {
            return CopyTo(new ManagementPath(path), (PutOptions)null);
        }
 
        /// 
        ///    Copies the object to a different location. 
        ///  
        /// The path to which the object should be copied.
        /// The options for how the object should be put. 
        /// 
        ///    The new path of the copied object.
        /// 
        public ManagementPath CopyTo(string path, PutOptions options) 
        {
            return CopyTo(new ManagementPath(path), options); 
        } 

        ///  
        ///    Copies the object to a different location.
        /// 
        /// The  to which the object should be copied.
        /// The options for how the object should be put. 
        /// 
        ///    The new path of the copied object. 
        ///  
        public ManagementPath CopyTo(ManagementPath path, PutOptions options)
        { 
            Initialize ( false ) ;

            ManagementScope destinationScope = null;
 
            // Build a scope for our target destination
            destinationScope = new ManagementScope(path, scope); 
            destinationScope.Initialize(); 

            PutOptions o = (null != options) ? options : new PutOptions(); 
            IWbemServices wbemServices = destinationScope.GetIWbemServices();
            ManagementPath newPath = null;

            // 
            // TO-DO : This code is almost identical to Put - should consolidate.
            // 
            // Must do this convoluted allocation since the IWbemServices ref IWbemCallResult 
            // has been redefined to be an IntPtr.  Due to the fact that it wasn't possible to
            // pass NULL for the optional argument. 
            //
            IntPtr ppwbemCallResult            = IntPtr.Zero;
            IntPtr pwbemCallResult            = IntPtr.Zero;
            IWbemCallResult wbemCallResult    = null; 
            SecurityHandler securityHandler    = null;
            int status                        = (int)ManagementStatus.NoError; 
 
            try
            { 
                securityHandler = destinationScope.GetSecurityHandler();

                ppwbemCallResult = Marshal.AllocHGlobal(IntPtr.Size);
                Marshal.WriteIntPtr(ppwbemCallResult, IntPtr.Zero);        // Init to NULL. 

                if (IsClass) 
                { 
                    status = scope.GetSecuredIWbemServicesHandler( wbemServices ).PutClass_(
                        wbemObject, 
                        o.Flags | (int)tag_WBEM_GENERIC_FLAG_TYPE.WBEM_FLAG_RETURN_IMMEDIATELY,
                        o.GetContext(),
                        ppwbemCallResult);
                } 
                else
                { 
                    status = scope.GetSecuredIWbemServicesHandler( wbemServices ).PutInstance_( 
                        wbemObject,
                        o.Flags | (int)tag_WBEM_GENERIC_FLAG_TYPE.WBEM_FLAG_RETURN_IMMEDIATELY, 
                        o.GetContext(),
                        ppwbemCallResult);

                } 

 
                // Keep this statement here; otherwise, there'll be a leak in error cases. 
                pwbemCallResult = Marshal.ReadIntPtr(ppwbemCallResult);
 
                //Use the CallResult to retrieve the resulting object path
                wbemCallResult = (IWbemCallResult)Marshal.GetObjectForIUnknown(pwbemCallResult);

                int hr; 
                status = wbemCallResult.GetCallStatus_((int)tag_WBEM_TIMEOUT_TYPE.WBEM_INFINITE, out hr);
 
                if (status >= 0) 
                    status = hr;
 
                if (status < 0)
                {
                    if ((status & 0xfffff000) == 0x80041000)
                        ManagementException.ThrowWithExtendedInfo((ManagementStatus)status); 
                    else
                        Marshal.ThrowExceptionForHR(status); 
                } 

                newPath = GetPath(wbemCallResult); 
                newPath.NamespacePath = path.GetNamespacePath((int)tag_WBEM_GET_TEXT_FLAGS.WBEMPATH_GET_SERVER_AND_NAMESPACE_ONLY);
            }
            finally
            { 
                if (securityHandler != null)
                    securityHandler.Reset(); 
 
                if (ppwbemCallResult != IntPtr.Zero)                    // Cleanup from allocations above.
                    Marshal.FreeHGlobal(ppwbemCallResult); 

                if (pwbemCallResult != IntPtr.Zero)
                    Marshal.Release(pwbemCallResult);
 
                if (wbemCallResult != null)
                    Marshal.ReleaseComObject(wbemCallResult); 
            } 

            return newPath; 
        }

        /// 
        ///    Copies the object to a different location, asynchronously. 
        /// 
        /// The object that will receive the results of the operation. 
        /// A  specifying the path to which the object should be copied. 
        public void CopyTo(ManagementOperationObserver watcher, ManagementPath path)
        { 
            CopyTo(watcher, path, null);
        }

        ///  
        ///    Copies the object to a different location, asynchronously.
        ///  
        /// The object that will receive the results of the operation. 
        ///  The path to which the object should be copied.
        public void CopyTo(ManagementOperationObserver watcher, string path) 
        {
            CopyTo(watcher, new ManagementPath(path), null);
        }
 
        /// 
        ///    Copies the object to a different location, asynchronously. 
        ///  
        /// The object that will receive the results of the operation.
        /// The path to which the object should be copied. 
        /// The options for how the object should be put.
        public void CopyTo(ManagementOperationObserver watcher, string path, PutOptions options)
        {
            CopyTo(watcher, new ManagementPath(path), options); 
        }
 
        ///  
        ///    Copies the object to a different location, asynchronously.
        ///  
        /// The object that will receive the results of the operation.
        /// The path to which the object should be copied.
        /// The options for how the object should be put.
        public void CopyTo(ManagementOperationObserver watcher, ManagementPath path, PutOptions options) 
        {
            if (null == watcher) 
                throw new ArgumentNullException("watcher"); 
            else
            { 
                Initialize ( false ) ;
                ManagementScope destinationScope = null;

                destinationScope = new ManagementScope(path, scope); 
                destinationScope.Initialize();
 
                PutOptions o = (null != options) ? (PutOptions) options.Clone() : new PutOptions(); 

                // If someone has registered for progress, make sure we flag it 
                if (watcher.HaveListenersForProgress)
                    o.SendStatus = true;

                WmiEventSink sink = watcher.GetNewPutSink(destinationScope, o.Context, 
                    path.GetNamespacePath((int)tag_WBEM_GET_TEXT_FLAGS.WBEMPATH_GET_SERVER_AND_NAMESPACE_ONLY), ClassName);
                IWbemServices destWbemServices = destinationScope.GetIWbemServices(); 
 
                SecurityHandler securityHandler = null;
                int status                        = (int)ManagementStatus.NoError; 

                securityHandler = destinationScope.GetSecurityHandler();

                if (IsClass) 
                {
                    status = destinationScope.GetSecuredIWbemServicesHandler( destWbemServices ).PutClassAsync_( 
                                                    wbemObject, 
                                                    o.Flags,
                                                    o.GetContext(), 
                                                    sink.Stub);

                }
                else 
                {
                    status = destinationScope.GetSecuredIWbemServicesHandler( destWbemServices ).PutInstanceAsync_( 
                                                    wbemObject, 
                                                    o.Flags,
                                                    o.GetContext(), 
                                                    sink.Stub);
                }

 
                if (securityHandler != null)
                    securityHandler.Reset(); 
 
                if (status < 0)
                { 
                    watcher.RemoveSink(sink);
                    if ((status & 0xfffff000) == 0x80041000)
                        ManagementException.ThrowWithExtendedInfo((ManagementStatus)status);
                    else 
                        Marshal.ThrowExceptionForHR(status);
                } 
            } 
        }
 
        //******************************************************
        //Delete
        //*****************************************************
        ///  
        ///    Deletes the object.
        ///  
        ///  
        ///    Deletes the object.
        ///  
        public void Delete()
        {
            Delete((DeleteOptions) null);
        } 

        ///  
        ///    Deletes the object. 
        /// 
        /// The options for how to delete the object.  
        public void Delete(DeleteOptions options)
        {
            if ((null == path) || (path.Path.Length==0))
                throw new InvalidOperationException(); 

            Initialize ( false ) ; 
            DeleteOptions o = (null != options) ? options : new DeleteOptions(); 
            IWbemServices wbemServices = scope.GetIWbemServices();
 
            SecurityHandler securityHandler = null;
            int status                        = (int)ManagementStatus.NoError;

            try 
            {
                securityHandler = scope.GetSecurityHandler(); 
 
                if (IsClass)
                { 
                    status = scope.GetSecuredIWbemServicesHandler( wbemServices ).DeleteClass_(
                        path.RelativePath,
                        o.Flags,
                        o.GetContext(), 
                        IntPtr.Zero);
                } 
                else 
                {
                    status = scope.GetSecuredIWbemServicesHandler( wbemServices ).DeleteInstance_( 
                        path.RelativePath,
                        o.Flags,
                        o.GetContext(),
                        IntPtr.Zero); 
                }
 
 
                if (status < 0)
                { 
                    if ((status & 0xfffff000) == 0x80041000)
                        ManagementException.ThrowWithExtendedInfo((ManagementStatus)status);
                    else
                        Marshal.ThrowExceptionForHR(status); 
                }
            } 
            finally 
            {
                if (securityHandler != null) 
                    securityHandler.Reset();
            }
        }
 

        ///  
        ///    Deletes the object. 
        /// 
        /// The object that will receive the results of the operation. 
        public void Delete(ManagementOperationObserver watcher)
        {
            Delete(watcher, null);
        } 

        ///  
        ///    Deletes the object. 
        /// 
        /// The object that will receive the results of the operation. 
        /// The options for how to delete the object.
        public void Delete(ManagementOperationObserver watcher, DeleteOptions options)
        {
            if ((null == path) || (path.Path.Length==0)) 
                throw new InvalidOperationException();
            else if (null == watcher) 
                throw new ArgumentNullException("watcher"); 
            else
            { 
                Initialize ( false ) ;
                DeleteOptions o = (null != options) ? (DeleteOptions) options.Clone() : new DeleteOptions();

                // If someone has registered for progress, make sure we flag it 
                if (watcher.HaveListenersForProgress)
                    o.SendStatus = true; 
 
                IWbemServices wbemServices = scope.GetIWbemServices();
                WmiEventSink sink = watcher.GetNewSink(scope, o.Context); 

                SecurityHandler securityHandler = null;
                int status                        = (int)ManagementStatus.NoError;
 
                securityHandler = scope.GetSecurityHandler();
 
                if (IsClass) 
                {
                    status = scope.GetSecuredIWbemServicesHandler( wbemServices ).DeleteClassAsync_(path.RelativePath, 
                        o.Flags,
                        o.GetContext(),
                        sink.Stub);
                } 
                else
                { 
                    status = scope.GetSecuredIWbemServicesHandler( wbemServices ).DeleteInstanceAsync_(path.RelativePath, 
                        o.Flags,
                        o.GetContext(), 
                        sink.Stub);
                }

 
                if (securityHandler != null)
                    securityHandler.Reset(); 
 
                if (status < 0)
                { 
                    watcher.RemoveSink(sink);
                    if ((status & 0xfffff000) == 0x80041000)
                        ManagementException.ThrowWithExtendedInfo((ManagementStatus)status);
                    else 
                        Marshal.ThrowExceptionForHR(status);
                } 
            } 
        }
 
        //******************************************************
        //InvokeMethod
        //*****************************************************
        ///  
        ///    Invokes a method on the object.
        ///  
        ///  
        ///    
        ///       Invokes a method on the object. 
        /// 
        /// The name of the method to execute. 
        /// An array containing parameter values. 
        ///  
        ///    The value returned by the method.
        ///  
        ///  
        ///    If the method is static, the execution
        ///       should still succeed. 
        /// 
        /// 
        ///    using System;
        /// using System.Management; 
        ///
        /// // This sample demonstrates invoking a WMI method using an array of arguments. 
        /// public class InvokeMethod 
        /// {
        ///     public static void Main() 
        ///     {
        ///
        ///         //Get the object on which the method will be invoked
        ///         ManagementClass processClass = new ManagementClass("Win32_Process"); 
        ///
        ///         //Create an array containing all arguments for the method 
        ///         object[] methodArgs = {"notepad.exe", null, null, 0}; 
        ///
        ///         //Execute the method 
        ///         object result = processClass.InvokeMethod ("Create", methodArgs);
        ///
        ///         //Display results
        ///         Console.WriteLine ("Creation of process returned: " + result); 
        ///         Console.WriteLine ("Process id: " + methodArgs[3]);
        ///     } 
        /// 
        /// }
        ///     
        ///    Imports System
        /// Imports System.Management
        ///
        /// ' This sample demonstrates invoking a WMI method using an array of arguments. 
        /// Class InvokeMethod
        ///     Public Overloads Shared Function Main(ByVal args() As String) As Integer 
        /// 
        ///         ' Get the object on which the method will be invoked
        ///         Dim processClass As New ManagementClass("Win32_Process") 
        ///
        ///         ' Create an array containing all arguments for the method
        ///         Dim methodArgs() As Object = {"notepad.exe", Nothing, Nothing, 0}
        /// 
        ///         ' Execute the method
        ///         Dim result As Object = processClass.InvokeMethod("Create", methodArgs) 
        /// 
        ///         'Display results
        ///         Console.WriteLine("Creation of process returned: {0}", result) 
        ///         Console.WriteLine("Process id: {0}", methodArgs(3))
        ///         Return 0
        ///     End Function
        /// End Class 
        ///    
        ///  
        public Object InvokeMethod(string methodName, Object[] args) 
        {
            object result = null; 

            if ((null == path) || (path.Path.Length==0))
                throw new InvalidOperationException();
            else if (null == methodName) 
                throw new ArgumentNullException("methodName");
            else 
            { 
                Initialize ( false ) ;
 
                // Map args into a inparams structure
                ManagementBaseObject inParameters;
                IWbemClassObjectFreeThreaded inParametersClass, outParametersClass;
                GetMethodParameters(methodName, out inParameters, 
                    out inParametersClass, out outParametersClass);
 
                MapInParameters(args, inParameters, inParametersClass); 

                // Call ExecMethod 
                ManagementBaseObject outParameters =
                    InvokeMethod(methodName, inParameters, null);

                // Map outparams to args 
                result = MapOutParameters(args, outParameters, outParametersClass);
            } 
 
            return result;
        } 

        //*****************************************************
        //InvokeMethod
        //***************************************************** 
        /// 
        ///    Invokes a method on the object, asynchronously. 
        ///  
        /// The object to receive the results of the operation.
        /// The name of the method to execute.  
        /// An array containing parameter values. 
        /// 
        ///    If the method is static, the execution
        ///       should still succeed. 
        /// 
        public void InvokeMethod( 
            ManagementOperationObserver watcher, 
            string methodName,
            Object[] args) 
        {
            if ((null == path) || (path.Path.Length==0))
                throw new InvalidOperationException();
            else if (null == watcher) 
                throw new ArgumentNullException("watcher");
            else if (null == methodName) 
                throw new ArgumentNullException("methodName"); 
            else
            { 
                Initialize ( false ) ;

                // Map args into a inparams structure
                ManagementBaseObject inParameters; 
                IWbemClassObjectFreeThreaded inParametersClass, outParametersClass;
                GetMethodParameters(methodName, out inParameters, 
                    out inParametersClass,    out outParametersClass); 

                MapInParameters(args, inParameters, inParametersClass); 

                // Call the method
                InvokeMethod(watcher, methodName, inParameters, null);
            } 
        }
 
        ///  
        ///    Invokes a method on the WMI object. The input and output
        ///       parameters are represented as  
        ///       objects.
        /// 
        /// The name of the method to execute.
        /// A  holding the input parameters to the method. 
        /// An  containing additional options for the execution of the method.
        ///  
        /// A  containing the 
        ///    output parameters and return value of the executed method.
        ///  
        /// 
        ///    using System;
        /// using System.Management;
        /// 
        /// // This sample demonstrates invoking a WMI method using parameter objects
        /// public class InvokeMethod 
        /// { 
        ///     public static void Main()
        ///     { 
        ///
        ///         //Get the object on which the method will be invoked
        ///         ManagementClass processClass = new ManagementClass("Win32_Process");
        /// 
        ///         //Get an input parameters object for this method
        ///         ManagementBaseObject inParams = processClass.GetMethodParameters("Create"); 
        /// 
        ///         //Fill in input parameter values
        ///         inParams["CommandLine"] = "calc.exe"; 
        ///
        ///         //Execute the method
        ///         ManagementBaseObject outParams = processClass.InvokeMethod ("Create", inParams, null);
        /// 
        ///         //Display results
        ///         //Note: The return code of the method is provided in the "returnValue" property of the outParams object 
        ///         Console.WriteLine("Creation of calculator process returned: " + outParams["returnValue"]); 
        ///         Console.WriteLine("Process ID: " + outParams["processId"]);
        ///    } 
        /// }
        ///    
        ///    
        /// Imports System 
        /// Imports System.Management
        /// 
        /// ' This sample demonstrates invoking a WMI method using parameter objects 
        /// Class InvokeMethod
        ///     Public Overloads Shared Function Main(ByVal args() As String) As Integer 
        ///
        ///         ' Get the object on which the method will be invoked
        ///         Dim processClass As New ManagementClass("Win32_Process")
        /// 
        ///          ' Get an input parameters object for this method
        ///         Dim inParams As ManagementBaseObject = processClass.GetMethodParameters("Create") 
        /// 
        ///         ' Fill in input parameter values
        ///         inParams("CommandLine") = "calc.exe" 
        ///
        ///         ' Execute the method
        ///         Dim outParams As ManagementBaseObject = processClass.InvokeMethod("Create", inParams, Nothing)
        /// 
        ///         ' Display results
        ///         ' Note: The return code of the method is provided in the "returnValue" property of the outParams object 
        ///         Console.WriteLine("Creation of calculator process returned: {0}", outParams("returnValue")) 
        ///         Console.WriteLine("Process ID: {0}", outParams("processId"))
        /// 
        ///         Return 0
        ///     End Function
        /// End Class
        ///     
        /// 
        public ManagementBaseObject InvokeMethod( 
            string methodName, 
            ManagementBaseObject inParameters,
            InvokeMethodOptions options) 
        {
            ManagementBaseObject outParameters = null;

            if ((null == path) || (path.Path.Length==0)) 
                throw new InvalidOperationException();
            else if (null == methodName) 
                throw new ArgumentNullException("methodName"); 
            else
            { 
                Initialize ( false ) ;
                InvokeMethodOptions o = (null != options) ? options : new InvokeMethodOptions();
                IWbemServices wbemServices = scope.GetIWbemServices();
 
                SecurityHandler securityHandler = null;
                int status                        = (int)ManagementStatus.NoError; 
 
                try
                { 
                    securityHandler = scope.GetSecurityHandler();

                    IWbemClassObjectFreeThreaded inParams = (null == inParameters) ? null : inParameters.wbemObject;
                    IWbemClassObjectFreeThreaded outParams = null; 

                    status = scope.GetSecuredIWbemServicesHandler( scope.GetIWbemServices() ).ExecMethod_( 
                        path.RelativePath, 
                        methodName,
                        o.Flags, 
                        o.GetContext(),
                        inParams,
                        ref outParams,
                        IntPtr.Zero); 

 
                    if (status < 0) 
                    {
                        if ((status & 0xfffff000) == 0x80041000) 
                            ManagementException.ThrowWithExtendedInfo((ManagementStatus)status);
                        else
                            Marshal.ThrowExceptionForHR(status);
                    } 

                    if (outParams != null) 
                        outParameters = new ManagementBaseObject(outParams); 
                }
                finally 
                {
                    if (securityHandler != null)
                        securityHandler.Reset();
                } 
            }
 
            return outParameters; 
        }
 
        /// 
        ///    Invokes a method on the object, asynchronously.
        /// 
        /// A  used to handle the asynchronous execution's progress and results. 
        /// The name of the method to be executed.
        /// A  containing the input parameters for the method. 
        /// An  containing additional options used to execute the method. 
        /// 
        ///    The method invokes the specified method execution and then 
        ///       returns. Progress and results are reported through events on the .
        /// 
        public void InvokeMethod(
            ManagementOperationObserver watcher, 
            string methodName,
            ManagementBaseObject inParameters, 
            InvokeMethodOptions options) 
        {
            if ((null == path) || (path.Path.Length==0)) 
                throw new InvalidOperationException();
            else if (null == watcher)
                throw new ArgumentNullException("watcher");
            else if (null == methodName) 
                throw new ArgumentNullException("methodName");
            else 
            { 
                Initialize ( false ) ;
                InvokeMethodOptions o = (null != options) ? 
                    (InvokeMethodOptions) options.Clone() : new InvokeMethodOptions();

                // If someone has registered for progress, make sure we flag it
                if (watcher.HaveListenersForProgress) 
                    o.SendStatus = true;
 
                WmiEventSink sink = watcher.GetNewSink(scope, o.Context); 

                SecurityHandler securityHandler = null; 
                int status                        = (int)ManagementStatus.NoError;

                securityHandler = scope.GetSecurityHandler();
 
                IWbemClassObjectFreeThreaded inParams = null;
 
                if (null != inParameters) 
                    inParams = inParameters.wbemObject;
 
                status = scope.GetSecuredIWbemServicesHandler( scope.GetIWbemServices() ).ExecMethodAsync_(
                    path.RelativePath,
                    methodName,
                    o.Flags, 
                    o.GetContext(),
                    inParams, 
                    sink.Stub ); 

                if (securityHandler != null) 
                    securityHandler.Reset();

                if (status < 0)
                { 
                    watcher.RemoveSink(sink);
                    if ((status & 0xfffff000) == 0x80041000) 
                        ManagementException.ThrowWithExtendedInfo((ManagementStatus)status); 
                    else
                        Marshal.ThrowExceptionForHR(status); 
                }
            }
        }
 
        //******************************************************
        //GetMethodParameters 
        //***************************************************** 
        /// 
        /// Returns a  representing the list of input parameters for a method. 
        /// 
        /// The name of the method. 
        /// 
        /// A  containing the 
        ///    input parameters to the method.
        ///  
        ///  
        ///     Gets the object containing the input parameters to a
        ///       method, and then fills in the values and passes the object to the () call. 
        /// 
        public ManagementBaseObject GetMethodParameters(
            string methodName)
        { 
            ManagementBaseObject inParameters;
            IWbemClassObjectFreeThreaded dummy1, dummy2; 
 
            GetMethodParameters(methodName, out inParameters, out dummy1, out dummy2);
 
            return inParameters;
        }

        private void GetMethodParameters( 
            string methodName,
            out ManagementBaseObject inParameters, 
            out IWbemClassObjectFreeThreaded inParametersClass, 
            out IWbemClassObjectFreeThreaded outParametersClass)
        { 
            inParameters = null;
            inParametersClass = null;
            outParametersClass = null;
 
            if (null == methodName)
                throw new ArgumentNullException("methodName"); 
            else 
            {
                Initialize ( false ) ; 

                // Do we have the class?
                if (null == wmiClass)
                { 
                    ManagementPath classPath = ClassPath;
 
                    if ((null == classPath) || !(classPath.IsClass)) 
                        throw new InvalidOperationException();
                    else 
                    {
                        ManagementClass classObject =
                            new ManagementClass(scope, classPath, null);
                        classObject.Get(); 
                        wmiClass = classObject.wbemObject;
                    } 
                } 

                int status = (int)ManagementStatus.NoError; 

                // Ask it for the method parameters
                status = wmiClass.GetMethod_(methodName, 0, out inParametersClass, out outParametersClass);
 
                // bug#92427 - To ensure that all forms of invoke return the same error codes when
                // the method does not exist, we will map WBEM_E_NOT_FOUND to WBEM_E_METHOD_NOT_IMPLEMENTED. 
                if(status == (int)tag_WBEMSTATUS.WBEM_E_NOT_FOUND) 
                    status = (int)tag_WBEMSTATUS.WBEM_E_METHOD_NOT_IMPLEMENTED;
 
                if (status >= 0)
                {
                    // Hand out instances
                    if (inParametersClass != null) 
                    {
                        IWbemClassObjectFreeThreaded inParamsInstance = null; 
                        status = inParametersClass.SpawnInstance_(0, out inParamsInstance); 

                        if (status >= 0) 
                        {
                            inParameters = new ManagementBaseObject(inParamsInstance);
                        }
                    } 
                }
 
                if (status < 0) 
                {
                    if ((status & 0xfffff000) == 0x80041000) 
                        ManagementException.ThrowWithExtendedInfo((ManagementStatus)status);
                    else
                        Marshal.ThrowExceptionForHR(status);
                } 
            }
        } 
 
        /// 
        ///    Creates a copy of the object. 
        /// 
        /// 
        ///    The copied object.
        ///  
        public override Object Clone()
        { 
            if (PutButNotGot) 
            {
                Get(); 
                PutButNotGot = false;
            }

            // 
            // Removed Initialize call since wbemObject is a property that will call Initialize ( true ) on
            // its getter. 
            // 
            // Initialize ( ) ;
 
            IWbemClassObjectFreeThreaded theClone = null;

            int status = wbemObject.Clone_(out theClone);
 
            if (status < 0)
            { 
                if ((status & 0xfffff000) == 0x80041000) 
                    ManagementException.ThrowWithExtendedInfo((ManagementStatus)status);
                else 
                    Marshal.ThrowExceptionForHR(status);
            }

            return ManagementObject.GetManagementObject(theClone, this); 
        }
 
        //****************************************************** 
        //ToString
        //****************************************************** 
        /// 
        ///    Returns the full path of the object. This is an override of the
        ///       default object implementation.
        ///  
        /// 
        ///     The full path of 
        ///       the object. 
        /// 
        public override string ToString() 
        {
            if (null != path)
                return path.Path;
            else 
                return "";
        } 
 
        //
        // The prototype of Initialize has been changed to accept a bool, indicating whether or not 
        // the caller wants to bind to the underlying WMI object in the Initialize call or not.
        //
        internal override void Initialize( bool getObject )
        { 
            bool needToGetObject = false;
 
            //If we're not connected yet, this is the time to do it... We lock 
            //the state to prevent 2 threads simultaneously doing the same
            //connection 
            lock (this)
            {
                // Make sure we have some kind of path if we get here. Note that
                // we don't use a set to the Path property since that would trigger 
                // an IdentifierChanged event
                if (null == path) 
                { 
                    path = new ManagementPath();
                    path.IdentifierChanged += new IdentifierChangedEventHandler(HandleIdentifierChange); 
                }

                //Have we already got this object
                if (!IsBound && ( getObject == true ) ) 
                    needToGetObject = true;
 
                if (null == scope) 
                {
                    // If our object has a valid namespace path, use that 
                    string nsPath = path.GetNamespacePath((int)tag_WBEM_GET_TEXT_FLAGS.WBEMPATH_GET_SERVER_AND_NAMESPACE_ONLY);

                    // Set the scope - note that we do not set through
                    // the Scope property since that would trigger an IdentifierChanged 
                    // event and reset isBound to false.
                    if (0 < nsPath.Length) 
                        scope = new ManagementScope(nsPath); 
                    else
                    { 
                        // Use the default constructor
                        scope = new ManagementScope();
                    }
 
                    // Hook ourselves up to this scope for future change notifications
                    scope.IdentifierChanged += new IdentifierChangedEventHandler(HandleIdentifierChange); 
                } 
                else if ((null == scope.Path) || scope.Path.IsEmpty)
                { 
                    // We have a scope but an empty path - use the object's path or the default
                    string nsPath = path.GetNamespacePath((int)tag_WBEM_GET_TEXT_FLAGS.WBEMPATH_GET_SERVER_AND_NAMESPACE_ONLY);

                    if (0 < nsPath.Length) 
                        scope.Path = new ManagementPath(nsPath);
                    else 
                        scope.Path = ManagementPath.DefaultPath; 
                }
 
                lock (scope)
                {
                    if (!scope.IsConnected)
                    { 
                        scope.Initialize();
 
                        // If we have just connected, make sure we get the object 
                        if ( getObject == true )
                        { 
                            needToGetObject = true;
                        }
                    }
 
                    if (needToGetObject)
                    { 
                        // If we haven't set up any options yet, now is the time. 
                        // Again we don't use the set to the Options property
                        // since that would trigger an IdentifierChangedEvent and 
                        // force isBound=false.
                        if (null == options)
                        {
                            options = new ObjectGetOptions(); 
                            options.IdentifierChanged += new IdentifierChangedEventHandler(HandleIdentifierChange);
                        } 
 
                        IWbemClassObjectFreeThreaded tempObj = null;
                        IWbemServices wbemServices = scope.GetIWbemServices(); 

                        SecurityHandler securityHandler = null;
                        int status                        = (int)ManagementStatus.NoError;
 
                        try
                        { 
                            securityHandler = scope.GetSecurityHandler(); 

                            string objectPath = null; 
                            string curPath = path.RelativePath;

                            if (curPath.Length>0)
                                objectPath = curPath; 
                            status = scope.GetSecuredIWbemServicesHandler( wbemServices ).GetObject_(objectPath, options.Flags, options.GetContext(), ref tempObj, IntPtr.Zero);
 
                            if (status >= 0) 
                            {
                                wbemObject = tempObj; 

                                // Getting the object succeeded, we are bound
                                //
                                // *** 
                                // *    Changed isBound flag to wbemObject==null check.
                                // *    isBound = true; 
                                // *** 

                                // now set the path from the "real" object 
                                object val = null;
                                int dummy1 = 0, dummy2 = 0;

                                status = wbemObject.Get_("__PATH", 0, ref val, ref dummy1, ref dummy2); 

                                if (status >= 0) 
                                { 
                                    path = (System.DBNull.Value != val) ? (new ManagementPath((string)val)) : (new ManagementPath ());
                                    path.IdentifierChanged += new IdentifierChangedEventHandler(HandleIdentifierChange); 
                                }
                            }

                            if (status < 0) 
                            {
                                if ((status & 0xfffff000) == 0x80041000) 
                                    ManagementException.ThrowWithExtendedInfo((ManagementStatus)status); 
                                else
                                    Marshal.ThrowExceptionForHR(status); 
                            }
                        }
                        finally
                        { 
                            if (securityHandler != null)
                                securityHandler.Reset(); 
                        } 
                    }
                } 
            }
        }

 
        private static void MapInParameters(
            object [] args, 
            ManagementBaseObject inParams, 
            IWbemClassObjectFreeThreaded inParamsClass)
        { 
            int status = (int)ManagementStatus.NoError;

            if (null != inParamsClass)
            { 
                if ((null != args) && (0 < args.Length))
                { 
                    int maxIndex = args.GetUpperBound(0); 
                    int minIndex = args.GetLowerBound(0);
                    int topId = maxIndex - minIndex; 

                    /*
                     * Iterate through the [in] parameters of the class to find
                     * the ID positional qualifier. We do this in the class because 
                     * we cannot be sure that the qualifier will be propagated to
                     * the instance. 
                     */ 

                    status = inParamsClass.BeginEnumeration_ 
                            ((int)tag_WBEM_CONDITION_FLAG_TYPE.WBEM_FLAG_NONSYSTEM_ONLY);

                    if (status >= 0)
                    { 
                        while (true)
                        { 
                            object                          val = null; 
                            int                              dummy = 0;
                            string                          propertyName = null; 
                            IWbemQualifierSetFreeThreaded qualifierSet = null;

                            status = inParamsClass.Next_(0, ref propertyName, ref val, ref dummy, ref dummy);
 
                            if (status >= 0)
                            { 
                                if (null == propertyName) 
                                    break;
 
                                status = inParamsClass.GetPropertyQualifierSet_(propertyName, out qualifierSet);

                                if (status >= 0)
                                { 
                                    try
                                    { 
                                        object id = 0; 
                                        qualifierSet.Get_(ID, 0, ref id, ref dummy);    // Errors intentionally ignored.
 
                                        // If the id is in range, map the value into the args array
                                        int idIndex = (int)id;
                                        if ((0 <= idIndex) && (topId >= idIndex))
                                            inParams[propertyName] = args [minIndex + idIndex]; 
                                    }
                                    finally 
                                    { 
                                        // Dispose for next iteration.
                                        qualifierSet.Dispose(); 
                                    }
                                }
                            }
 
                            if (status < 0)
                            { 
                                break; 
                            }
                        } 
                    }

                    if (status < 0)
                    { 
                        if ((status & 0xfffff000) == 0x80041000)
                            ManagementException.ThrowWithExtendedInfo((ManagementStatus)status); 
                        else 
                            Marshal.ThrowExceptionForHR(status);
                    } 
                }
            }
        }
 
        private static object MapOutParameters(
            object [] args, 
            ManagementBaseObject outParams, 
            IWbemClassObjectFreeThreaded outParamsClass)
        { 
            object result = null;
            int maxIndex = 0, minIndex = 0, topId = 0;

            int status = (int)ManagementStatus.NoError; 

            if (null != outParamsClass) 
            { 
                if ((null != args) && (0 < args.Length))
                { 
                    maxIndex = args.GetUpperBound(0);
                    minIndex = args.GetLowerBound(0);
                    topId = maxIndex - minIndex;
                } 
                /*
                    * Iterate through the [out] parameters of the class to find 
                    * the ID positional qualifier. We do this in the class because 
                    * we cannot be sure that the qualifier will be propagated to
                    * the instance. 
                */

                status = outParamsClass.BeginEnumeration_
                    ((int)tag_WBEM_CONDITION_FLAG_TYPE.WBEM_FLAG_NONSYSTEM_ONLY); 

                if (status >= 0) 
                { 
                    while (true)
                    { 
                        object                          val = null;
                        int                              dummy = 0;
                        string                          propertyName = null;
                        IWbemQualifierSetFreeThreaded qualifierSet = null; 

                        status = outParamsClass.Next_(0, ref propertyName, ref val, ref dummy, ref dummy); 
 
                        if (status >= 0)
                        { 
                            if (null == propertyName)
                                break;

                            // Handle the result parameter separately 
                            if (String.Compare(propertyName, RETURNVALUE, StringComparison.OrdinalIgnoreCase) == 0)
                            { 
                                result = outParams[RETURNVALUE]; 
                            }
                            else  // Shouldn't get here if no args! 
                            {
                                status = outParamsClass.GetPropertyQualifierSet_(propertyName, out qualifierSet);

                                if (status >= 0) 
                                {
                                    try 
                                    { 
                                        object id = 0;
                                        qualifierSet.Get_(ID, 0, ref id, ref dummy);    // Errors intentionally ignored. 

                                        // If the id is in range, map the value into the args array
                                        int idIndex = (int)id;
                                        if ((0 <= idIndex) && (topId >= idIndex)) 
                                            args [minIndex + idIndex] = outParams[propertyName];
                                    } 
                                    finally 
                                    {
                                        // Dispose for next iteration. 
                                        qualifierSet.Dispose();
                                    }
                                }
                            } 
                        }
 
                        if (status < 0) 
                        {
                            break; 
                        }
                    }
                }
 
                if (status < 0)
                { 
                    if ((status & 0xfffff000) == 0x80041000) 
                        ManagementException.ThrowWithExtendedInfo((ManagementStatus)status);
                    else 
                        Marshal.ThrowExceptionForHR(status);
                }
            }
 
            return result;
        } 
 
    }//ManagementObject
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK