Exemple #1
0
        internal IWbemServices GetIWbemServices()
        {
            // Lets start by assuming that we'll return the RCW that we already have
            IWbemServices localCopy = wbemServices;

            // Get an IUnknown for this apartment
            IntPtr pUnk = Marshal.GetIUnknownForObject(wbemServices);

            // Get an 'IUnknown RCW' for this apartment
            Object unknown = Marshal.GetObjectForIUnknown(pUnk);

            // Release the ref count on the IUnknwon
            Marshal.Release(pUnk);

            // See if we are in the same apartment as where the original IWbemServices lived
            // If we are in a different apartment, give the caller an RCW generated just for their
            // apartment, and set the proxy blanket appropriately
            if (!object.ReferenceEquals(unknown, wbemServices))
            {
                // We need to set the proxy blanket on 'unknown' or else the QI for IWbemServices may
                // fail if we are running under a local user account.  The QI has to be done by
                // someone who is a member of the 'Everyone' group on the target machine, or DCOM
                // won't let the call through.
                SecurityHandler securityHandler = GetSecurityHandler();
                securityHandler.SecureIUnknown(unknown);

                // Now, we can QI and secure the IWbemServices
                localCopy = (IWbemServices)unknown;

                // We still need to bless the IWbemServices in this apartment
                securityHandler.Secure(localCopy);
            }

            return(localCopy); // STRANGE: Why does it still work if I return 'wbemServices'?
        }
Exemple #2
0
        internal IWbemServices GetIWbemServices()
        {
            IWbemServices wbemServices      = this.wbemServices;
            IntPtr        iUnknownForObject = Marshal.GetIUnknownForObject(this.wbemServices);
            object        objectForIUnknown = Marshal.GetObjectForIUnknown(iUnknownForObject);

            Marshal.Release(iUnknownForObject);
            if (!object.ReferenceEquals(objectForIUnknown, this.wbemServices))
            {
                SecurityHandler securityHandler = this.GetSecurityHandler();
                securityHandler.SecureIUnknown(objectForIUnknown);
                wbemServices = (IWbemServices)objectForIUnknown;
                securityHandler.Secure(wbemServices);
            }
            return(wbemServices);
        }
        //********************************************
        //Get()
        //********************************************
        /// <overload>
        ///    Invokes the specified WMI query and returns the resulting collection.
        /// </overload>
        /// <summary>
        ///    <para>Invokes the specified WMI query and returns the
        ///       resulting collection.</para>
        /// </summary>
        /// <returns>
        /// <para>A <see cref='System.Management.ManagementObjectCollection'/> containing the objects that match the
        ///    specified query.</para>
        /// </returns>
        public ManagementObjectCollection Get()
        {
            Initialize();
            IEnumWbemClassObject ew = null;
            SecurityHandler      securityHandler = scope.GetSecurityHandler();
            EnumerationOptions   enumOptions     = (EnumerationOptions)options.Clone();

            int status = (int)ManagementStatus.NoError;

            try {
                //If this is a simple SelectQuery (className only), and the enumerateDeep is set, we have
                //to find out whether this is a class enumeration or instance enumeration and call CreateInstanceEnum/
                //CreateClassEnum appropriately, because with ExecQuery we can't do a deep enumeration.
                if ((query.GetType() == typeof(SelectQuery)) &&
                    (((SelectQuery)query).Condition == null) &&
                    (((SelectQuery)query).SelectedProperties == null) &&
                    (options.EnumerateDeep == true))
                {
                    //Need to make sure that we're not passing invalid flags to enumeration APIs.
                    //The only flags not valid for enumerations are EnsureLocatable & PrototypeOnly.
                    enumOptions.EnsureLocatable = false; enumOptions.PrototypeOnly = false;

                    if (((SelectQuery)query).IsSchemaQuery == false)                     //deep instance enumeration
                    {
                        status = scope.GetIWbemServices().CreateInstanceEnum_(
                            ((SelectQuery)query).ClassName,
                            enumOptions.Flags,
                            enumOptions.GetContext(),
                            out ew);
                    }
                    else                     //deep class enumeration
                    {
                        status = scope.GetIWbemServices().CreateClassEnum_(
                            ((SelectQuery)query).ClassName,
                            enumOptions.Flags,
                            enumOptions.GetContext(),
                            out ew);
                    }
                }
                else                 //we can use ExecQuery
                {
                    //Make sure the EnumerateDeep flag bit is turned off because it's invalid for queries
                    enumOptions.EnumerateDeep = true;
                    status = scope.GetIWbemServices().ExecQuery_(
                        query.QueryLanguage,
                        query.QueryString,
                        enumOptions.Flags,
                        enumOptions.GetContext(),
                        out ew);
                }

                //Set security on the enumerator
                if ((status & 0x80000000) == 0)
                {
                    securityHandler.Secure(ew);
                }
            }       catch (Exception e) {
                // BUGBUG : securityHandler.Reset()?
                ManagementException.ThrowWithExtendedInfo(e);
            } finally {
                securityHandler.Reset();
            }

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

            //Create a new collection object for the results

            return(new ManagementObjectCollection(scope, options, ew));
        }        //Get()
        /// <summary>
        ///    <para>Waits for the next event that matches the specified query to arrive, and
        ///       then returns it.</para>
        /// </summary>
        /// <returns>
        /// <para>A <see cref='System.Management.ManagementBaseObject'/> representing the
        ///    newly arrived event.</para>
        /// </returns>
        /// <remarks>
        ///    <para>If the event watcher object contains options with
        ///       a specified timeout, the API will wait for the next event only for the specified
        ///       amount of time; otherwise, the API will be blocked until the next event occurs.</para>
        /// </remarks>
        public ManagementBaseObject WaitForNextEvent()
        {
            ManagementBaseObject obj = null;

            Initialize();

            lock (this)
            {
                SecurityHandler securityHandler = Scope.GetSecurityHandler();

                int status = (int)ManagementStatus.NoError;

                try
                {
                    if (null == enumWbem)                       //don't have an enumerator yet - get it
                    {
                        //Execute the query
                        status = Scope.GetIWbemServices().ExecNotificationQuery_(
                            query.QueryLanguage,
                            query.QueryString,
                            options.Flags,
                            options.GetContext(),
                            out enumWbem);

                        //Set security on enumerator
                        if (status >= 0)
                        {
                            securityHandler.Secure(enumWbem);
                        }
                    }

                    if (status >= 0)
                    {
                        if ((cachedCount - cacheIndex) == 0)                         //cache is empty - need to get more objects
                        {
        #if true
                            //Because Interop doesn't support custom marshalling for arrays, we have to use
                            //the "DoNotMarshal" objects in the interop and then convert to the "FreeThreaded"
                            //counterparts afterwards.
                            IWbemClassObject_DoNotMarshal[] tempArray = new IWbemClassObject_DoNotMarshal[options.BlockSize];

                            int timeout = (ManagementOptions.InfiniteTimeout == options.Timeout)
                                                                ? (int)tag_WBEM_TIMEOUT_TYPE.WBEM_INFINITE :
                                          (int)options.Timeout.TotalMilliseconds;

                            status = enumWbem.Next_(timeout, (uint)options.BlockSize,
                                                    tempArray, out cachedCount);
                            cacheIndex = 0;

                            if (status >= 0)
                            {
                                //Convert results and put them in cache. Note that we may have timed out
                                //in which case we might not have all the objects. If no object can be returned
                                //we throw a timeout exception... - TODO: what should happen if there was a timeout
                                //but at least some objects were returned ??
                                if (cachedCount == 0)
                                {
                                    ManagementException.ThrowWithExtendedInfo(ManagementStatus.Timedout);
                                }

                                for (int i = 0; i < cachedCount; i++)
                                {
                                    cachedObjects[i] = new IWbemClassObjectFreeThreaded(Marshal.GetIUnknownForObject(tempArray[i]));
                                }
                            }
        #else
                            //This was workaround when using TLBIMP we couldn't pass in arrays...

                            IWbemClassObjectFreeThreaded cachedObject = cachedObjects[0];
                            int timeout = (ManagementOptions.InfiniteTimeout == options.Timeout)
                                                                ? (int)tag_WBEM_TIMEOUT_TYPE.WBEM_INFINITE :
                                          (int)options.Timeout.TotalMilliseconds;
                            status = enumWbem.Next_(timeout, 1, out cachedObjects, out cachedCount);

                            cacheIndex = 0;

                            if (status >= 0)
                            {
                                //Create ManagementObject for result. Note that we may have timed out
                                //in which case we won't have an object
                                if (null == cachedObject)
                                {
                                    ManagementException.ThrowWithExtendedInfo(ManagementStatus.Timedout);
                                }

                                cachedObjects[0] = cachedObject;
                            }
        #endif
                        }

                        if (status >= 0)
                        {
                            obj = new ManagementBaseObject(cachedObjects[cacheIndex]);
                            cacheIndex++;
                        }
                    }
                }
                finally
                {
                    securityHandler.Reset();
                }

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

            return(obj);
        }
        /// <summary>
        ///    <para>Waits until the next event that matches the specified query arrives,
        ///       and returns it</para>
        /// </summary>
        /// <remarks>
        ///    If the event watcher object contains
        ///    options with a specified timeout, this API will wait for the next event only for
        ///    the specified time. If not, the API will block until the next event occurs.
        /// </remarks>
        public ManagementBaseObject WaitForNextEvent()
        {
            Trace.WriteLine("Entering WaitForNextEvent...");
            ManagementBaseObject obj = null;

            Initialize();

            lock (this)
            {
                SecurityHandler securityHandler = Scope.GetSecurityHandler();

                int status = (int)ManagementStatus.NoError;

                try
                {
                    if (null == enumWbem)                       //don't have an enumerator yet - get it
                    {
                        //Execute the query
                        status = Scope.GetIWbemServices().ExecNotificationQuery_(
                            query.QueryLanguage,
                            query.QueryString,
                            options.Flags,
                            options.GetContext(),
                            out enumWbem);

                        //Set security on enumerator
                        if ((status & 0x80000000) == 0)
                        {
                            securityHandler.Secure(enumWbem);
                        }
                    }

                    if ((status & 0x80000000) == 0)
                    {
                        if ((cachedCount - cacheIndex) == 0)                         //cache is empty - need to get more objects
                        {
                            // TODO - due to TLBIMP restrictions IEnumWBemClassObject.Next will
                            // not work with arrays - have to set count to 1
        #if false
                            enumWbem.Next((int)options.Timeout.TotalMilliseconds, (uint)options.BlockCount,
                                          out cachedObjects, out cachedCount);
        #else
                            IWbemClassObjectFreeThreaded cachedObject = cachedObjects[0];
                            int timeout = (ManagementOptions.InfiniteTimeout == options.Timeout)
                                                                ? (int)tag_WBEM_TIMEOUT_TYPE.WBEM_INFINITE :
                                          (int)options.Timeout.TotalMilliseconds;
                            status = enumWbem.Next_(timeout, 1, out cachedObject, out cachedCount);

                            cacheIndex = 0;

                            if ((status & 0x80000000) == 0)
                            {
                                //Create ManagementObject for result. Note that we may have timed out
                                //in which case we won't have an object
                                if (null == cachedObject)
                                {
                                    ManagementException.ThrowWithExtendedInfo(ManagementStatus.Timedout);
                                }

                                cachedObjects[0] = cachedObject;
                            }
        #endif
                        }

                        if ((status & 0x80000000) == 0)
                        {
                            obj = new ManagementBaseObject(cachedObjects[cacheIndex]);
                            cacheIndex++;
                        }
                    }
                } catch (Exception e) {
                    // BUGBUG : securityHandler.Reset()?
                    if (e is ManagementException)
                    {
                        throw;                         //just let it propagate
                    }
                    ManagementException.ThrowWithExtendedInfo(e);
                }
                finally {
                    securityHandler.Reset();
                    Trace.WriteLine("Returning from WaitForNextEvent...");
                }

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

            return(obj);
        }