//int statusFromMTA; void InitializeGuts(object o) { ManagementScope threadParam = (ManagementScope)o; IWbemLocator loc = (IWbemLocator) new WbemLocator(); if (null == options) { threadParam.Options = new ConnectionOptions(); } string nsPath = threadParam.prvpath.GetNamespacePath((int)tag_WBEM_GET_TEXT_FLAGS.WBEMPATH_GET_SERVER_AND_NAMESPACE_ONLY); // If no namespace specified, fill in the default one if ((null == nsPath) || (0 == nsPath.Length)) { // NB: we use a special method to set the namespace // path here as we do NOT want to trigger an // IdentifierChanged event as a result of this set bool bUnused; nsPath = threadParam.prvpath.SetNamespacePath(ManagementPath.DefaultPath.Path, out bUnused); } // If we have privileges to enable, now is the time SecurityHandler securityHandler = GetSecurityHandler(); int status = (int)ManagementStatus.NoError; //If we're on XP or higher, always use the "max_wait" flag to avoid hanging if ((Environment.OSVersion.Platform == PlatformID.Win32NT) && (Environment.OSVersion.Version.Major >= 5) && (Environment.OSVersion.Version.Minor >= 1)) { threadParam.options.Flags |= (int)tag_WBEM_CONNECT_OPTIONS.WBEM_FLAG_CONNECT_USE_MAX_WAIT; } try { status = loc.ConnectServer_( nsPath, threadParam.options.Username, threadParam.options.GetPassword(), threadParam.options.Locale, threadParam.options.Flags, threadParam.options.Authority, threadParam.options.GetContext(), out threadParam.wbemServices); //Set security on services pointer GetSecurityHandler().Secure(threadParam.wbemServices); // // RAID: 127453 [marioh] // Make sure we enable RPC garbage collection to avoid tons // of useless idle connections not being recycled. This only // has impact on Win2k and below since XP has this enabled by // default. // if (rpcGarbageCollectionEnabled == false) { RpcMgmtEnableIdleCleanup( ); rpcGarbageCollectionEnabled = true; } Marshal.ReleaseComObject(loc); loc = null; } catch (Exception e) { // BUGBUG : securityHandler.Reset()? ManagementException.ThrowWithExtendedInfo(e); } finally { securityHandler.Reset(); } //statusFromMTA = status; if ((status & 0xfffff000) == 0x80041000) { ManagementException.ThrowWithExtendedInfo((ManagementStatus)status); } else if ((status & 0x80000000) != 0) { Marshal.ThrowExceptionForHR(status); } }
/// <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(); #pragma warning disable CA2002 lock (this) #pragma warning restore CA2002 { 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.GetSecuredIWbemServicesHandler(Scope.GetIWbemServices()).ExecNotificationQuery_( query.QueryLanguage, query.QueryString, options.Flags, options.GetContext(), ref enumWbem); } if (status >= 0) { if ((cachedCount - cacheIndex) == 0) //cache is empty - need to get more objects { //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 = scope.GetSecuredIEnumWbemClassObjectHandler(enumWbem).Next_(timeout, (uint)options.BlockSize, tempArray, ref 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. if (cachedCount == 0) { ManagementException.ThrowWithExtendedInfo(ManagementStatus.Timedout); } for (int i = 0; i < cachedCount; i++) { cachedObjects[i] = new IWbemClassObjectFreeThreaded(Marshal.GetIUnknownForObject(tempArray[i])); } } } 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, WmiNetUtilsHelper.GetErrorInfo_f()); } } } return(obj); }
//**************************************** //MoveNext //**************************************** /// <summary> /// Indicates whether the enumerator has moved to /// the next object in the enumeration. /// </summary> /// <returns> /// <para><see langword='true'/>, if the enumerator was /// successfully advanced to the next element; <see langword='false'/> if the enumerator has /// passed the end of the collection.</para> /// </returns> public bool MoveNext() { if (isDisposed) { throw new ObjectDisposedException(name); } //If there are no more objects in the collection return false if (atEndOfCollection) { return(false); } //Look for the next object cacheIndex++; if ((cachedCount - cacheIndex) == 0) //cache is empty - need to get more objects { //If the timeout is set to infinite, need to use the WMI infinite constant int timeout = (collectionObject.options.Timeout.Ticks == long.MaxValue) ? (int)tag_WBEM_TIMEOUT_TYPE.WBEM_INFINITE : (int)collectionObject.options.Timeout.TotalMilliseconds; //Get the next [BLockSize] objects within the specified timeout SecurityHandler securityHandler = collectionObject.scope.GetSecurityHandler(); //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[collectionObject.options.BlockSize]; int status = collectionObject.scope.GetSecuredIEnumWbemClassObjectHandler(enumWbem).Next_(timeout, (uint)collectionObject.options.BlockSize, tempArray, ref cachedCount); securityHandler.Reset(); if (status >= 0) { //Convert results and put them in cache. for (int i = 0; i < cachedCount; i++) { cachedObjects[i] = new IWbemClassObjectFreeThreaded ( Marshal.GetIUnknownForObject(tempArray[i]) ); } } if (status < 0) { if ((status & 0xfffff000) == 0x80041000) { ManagementException.ThrowWithExtendedInfo((ManagementStatus)status); } else { Marshal.ThrowExceptionForHR(status, WmiNetUtilsHelper.GetErrorInfo_f()); } } else { //If there was a timeout and no object can be returned we throw a timeout exception... if ((status == (int)tag_WBEMSTATUS.WBEM_S_TIMEDOUT) && (cachedCount == 0)) { ManagementException.ThrowWithExtendedInfo((ManagementStatus)status); } //If not timeout and no objects were returned - we're at the end of the collection if ((status == (int)tag_WBEMSTATUS.WBEM_S_FALSE) && (cachedCount == 0)) { atEndOfCollection = true; cacheIndex--; //back to last object /* This call to Dispose is being removed as per discussion with URT people and the newly supported * Dispose() call in the foreach implementation itself. * * //Release the COM object (so that the user doesn't have to) * Dispose(); */ return(false); } } cacheIndex = 0; } return(true); }
// //IEnumerable methods // //**************************************** //GetEnumerator //**************************************** /// <summary> /// <para>Returns the enumerator for the collection. If the collection was retrieved from an operation that /// specified the EnumerationOptions.Rewindable = false only one iteration through this enumerator is allowed. /// Note that this applies to using the Count property of the collection as well since an iteration over the collection /// is required. Due to this, code using the Count property should never specify EnumerationOptions.Rewindable = false. /// </para> /// </summary> /// <returns> /// An <see cref='System.Collections.IEnumerator'/>that can be used to iterate through the /// collection. /// </returns> public ManagementObjectEnumerator GetEnumerator() { if (isDisposed) { throw new ObjectDisposedException(name); } // // We do not clone the enumerator if its the first enumerator. // If it is the first enumerator we pass the reference // to the enumerator implementation rather than a clone. If the enumerator is used // from within a foreach statement in the client code, the foreach statement will // dec the ref count on the reference which also happens to be the reference to the // original enumerator causing subsequent uses of the collection to fail. // To prevent this we always clone the enumerator (assuming its a rewindable enumerator) // to avoid invalidating the collection. // // If its a forward only enumerator we simply pass back the original enumerator (i.e. // not cloned) and if it gets disposed we end up throwing the next time its used. Essentially, // the enumerator becomes the collection. // // Unless this is the first enumerator, we have // to clone. This may throw if we are non-rewindable. if (this.options.Rewindable == true) { IEnumWbemClassObject enumWbemClone = null; int status = (int)ManagementStatus.NoError; try { status = scope.GetSecuredIEnumWbemClassObjectHandler(enumWbem).Clone_(ref enumWbemClone); if ((status & 0x80000000) == 0) { //since the original enumerator might not be reset, we need //to reset the new one. status = scope.GetSecuredIEnumWbemClassObjectHandler(enumWbemClone).Reset_(); } } catch (COMException e) { ManagementException.ThrowWithExtendedInfo(e); } if ((status & 0xfffff000) == 0x80041000) { ManagementException.ThrowWithExtendedInfo((ManagementStatus)status); } else if ((status & 0x80000000) != 0) { Marshal.ThrowExceptionForHR(status, WmiNetUtilsHelper.GetErrorInfo_f()); } return(new ManagementObjectEnumerator(this, enumWbemClone)); } else { // // Notice that we use the original enumerator and hence enum position is retained. // For example, if the client code manually walked half the collection and then // used a foreach statement, the foreach statement would continue from where the // manual walk ended. // return(new ManagementObjectEnumerator(this, enumWbem)); } }
internal void Initialize() { //If the path is not set yet we can't do it if (null == path) { throw new InvalidOperationException(); } /* * 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. To avoid taking the lock unnecessarily we examine * isConnected first */ if (!IsConnected) { lock (this) { if (!IsConnected) { IWbemLocator loc = (IWbemLocator) new WbemLocator(); if (null == options) { Options = new ConnectionOptions(); } string nsPath = path.NamespacePath; // If no namespace specified, fill in the default one if ((null == nsPath) || (0 == nsPath.Length)) { // NB: we use a special method to set the namespace // path here as we do NOT want to trigger an // IdentifierChanged event as a result of this set path.SetNamespacePath(ManagementPath.DefaultPath.Path); } // If we have privileges to enable, now is the time SecurityHandler securityHandler = GetSecurityHandler(); int status = (int)ManagementStatus.NoError; try { status = loc.ConnectServer_( path.NamespacePath, options.Username, options.GetPassword(), options.Locale, options.Flags, options.Authority, options.GetContext(), out wbemServices); //Set security on services pointer Secure(wbemServices); } 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); } } } } }
internal string SetNamespacePath(string nsPath, out bool bChange) { int status = (int)ManagementStatus.NoError; string nsOrg = null; string nsNew = null; IWbemPath wmiPathTmp = null; bChange = false; Debug.Assert(nsPath != null); //Do some validation on the path to make sure it is a valid namespace path (at least syntactically) if (!IsValidNamespaceSyntax(nsPath)) { ManagementException.ThrowWithExtendedInfo((ManagementStatus)tag_WBEMSTATUS.WBEM_E_INVALID_NAMESPACE); } wmiPathTmp = CreateWbemPath(nsPath); if (wmiPath == null) { wmiPath = this.CreateWbemPath(""); } else if (isWbemPathShared) { // Check if this IWbemPath is shared among multiple managed objects. // With this write, it will have to maintain its own copy. wmiPath = CreateWbemPath(this.GetWbemPath()); isWbemPathShared = false; } nsOrg = GetNamespacePath(wmiPath, (int)tag_WBEM_GET_TEXT_FLAGS.WBEMPATH_GET_NAMESPACE_ONLY); nsNew = GetNamespacePath(wmiPathTmp, (int)tag_WBEM_GET_TEXT_FLAGS.WBEMPATH_GET_NAMESPACE_ONLY); if (!string.Equals(nsOrg, nsNew, StringComparison.OrdinalIgnoreCase)) { wmiPath.RemoveAllNamespaces_(); // Out with the old... Ignore status code. // Add the new ones in bChange = true; // Now dirty from above. uint nCount = 0; status = wmiPathTmp.GetNamespaceCount_(out nCount); if (status >= 0) { for (uint i = 0; i < nCount; i++) { uint uLen = 0; status = wmiPathTmp.GetNamespaceAt_(i, ref uLen, null); if (status >= 0) { char[] space = new char[(int)uLen]; status = wmiPathTmp.GetNamespaceAt_(i, ref uLen, space); if (status >= 0) { status = wmiPath.SetNamespaceAt_(i, space); if (status < 0) { break; } } else { break; } } else { break; } } } } else { ; } // Continue on. Could have different server name, same ns specified. // // Update Server property if specified in the namespace. // eg: "\\MyServer\root\cimv2". // if (status >= 0 && nsPath.Length > 1 && (nsPath[0] == '\\' && nsPath[1] == '\\' || nsPath[0] == '/' && nsPath[1] == '/')) { uint uLen = 0; status = wmiPathTmp.GetServer_(ref uLen, null); if (status >= 0 && uLen > 0) { char[] newServerChars = new char[(int)uLen]; status = wmiPathTmp.GetServer_(ref uLen, newServerChars); string serverNew = new string(newServerChars, 0, Array.IndexOf(newServerChars, '\0')); if (status >= 0) { // Compare server name on this object, if specified, to the caller's. // Update this object if different or unspecified. uLen = 0; status = wmiPath.GetServer_(ref uLen, null); // NB: Cannot use property get since it may throw. if (status >= 0) { char[] orgServerChars = new char[(int)uLen]; status = wmiPath.GetServer_(ref uLen, orgServerChars); string serverOrg = new string(orgServerChars, 0, Array.IndexOf(orgServerChars, '\0')); if (status >= 0 && !string.Equals(serverOrg, serverNew, StringComparison.OrdinalIgnoreCase)) { status = wmiPath.SetServer_(serverNew); } } else if (status == (int)tag_WBEMSTATUS.WBEM_E_NOT_AVAILABLE) { status = wmiPath.SetServer_(serverNew); if (status >= 0) { bChange = true; } } } } else if (status == (int)tag_WBEMSTATUS.WBEM_E_NOT_AVAILABLE) // No caller-supplied server name; { status = (int)ManagementStatus.NoError; // Ignore error. } } if (status < 0) { if ((status & 0xfffff000) == 0x80041000) { ManagementException.ThrowWithExtendedInfo((ManagementStatus)status); } else { Marshal.ThrowExceptionForHR(status, WmiNetUtilsHelper.GetErrorInfo_f()); } } return(nsNew); }
/// <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); }