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'? }
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); }