MegaBites-AI/Windows-powershell
0308
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System.Collections;5using System.Collections.Generic;6using System.Collections.ObjectModel;7using System.Collections.Specialized;8using System.ComponentModel;9using System.Globalization;10using System.Management.Automation.Internal;11using System.Text;12 13using Microsoft.PowerShell;14 15using Dbg = System.Management.Automation.Diagnostics;16 17#pragma warning disable 1634, 1691 // Stops compiler from warning about unknown warnings18 19namespace System.Management.Automation20{21 /// <summary>22 /// Deals with ManagementObject objects.23 /// This is a base class that interacts with other entities.24 /// </summary>25 internal abstract class BaseWMIAdapter : Adapter26 {27 #region WMIMethodCacheEntry28 29 /// <summary>30 /// Method information is cached for every unique ManagementClassPath created/used.31 /// This structure stores information such as MethodDefinition as displayed32 /// by Get-Member cmdlet, original MethodData and computed method information such33 /// as whether a method is static etc.34 /// </summary>35 internal class WMIMethodCacheEntry : CacheEntry36 {37 public string Name { get; }38 39 public string ClassPath { get; }40 41 public MethodInformation MethodInfoStructure { get; }42 43 public string MethodDefinition { get; }44 45 internal WMIMethodCacheEntry(string n, string cPath, MethodData mData)46 {47 Name = n;48 ClassPath = cPath;49 MethodInfoStructure = ManagementObjectAdapter.GetMethodInformation(mData);50 MethodDefinition = ManagementObjectAdapter.GetMethodDefinition(mData);51 }52 }53 54 #endregion55 56 #region WMIParameterInformation57 58 internal class WMIParameterInformation : ParameterInformation59 {60 public string Name { get; }61 62 public WMIParameterInformation(string name, Type ty) : base(ty, true, null, false)63 {64 Name = name;65 }66 }67 68 #endregion69 70 #region Member related Overrides71 72 /// <summary>73 /// Returns the TypeNameHierarchy using the __Derivation SystemProperties74 /// and dotnetBaseType.75 /// </summary>76 /// <param name="managementObj"></param>77 /// <param name="dotnetBaseType"></param>78 /// <param name="shouldIncludeNamespace"></param>79 /// <returns></returns>80 private static IEnumerable<string> GetTypeNameHierarchyFromDerivation(ManagementBaseObject managementObj,81 string dotnetBaseType, bool shouldIncludeNamespace)82 {83 StringBuilder type = new StringBuilder(200);84 // give the typename based on NameSpace and Class85 type.Append(dotnetBaseType);86 type.Append('#');87 if (shouldIncludeNamespace)88 {89 type.Append(managementObj.SystemProperties["__NAMESPACE"].Value);90 type.Append('\\');91 }92 93 type.Append(managementObj.SystemProperties["__CLASS"].Value);94 yield return type.ToString();95 96 // Win8: 186792: PSTypeNames does not include full WMI class derivation97 // From MSDN: __Derivation; Data type: CIM_STRING array98 // Access type: Read-only for both instances and classes99 // Class hierarchy of the current class or instance. The first element is100 // the immediate parent class, the next is its parent, and so on; the last element101 // is the base class.102 PropertyData derivationData = managementObj.SystemProperties["__Derivation"];103 if (derivationData != null)104 {105 Dbg.Assert(derivationData.IsArray, "__Derivation must be a string array as per MSDN documentation");106 107 // give the typenames based on NameSpace + __Derivation108 string[] typeHierarchy = PropertySetAndMethodArgumentConvertTo(derivationData.Value, typeof(string[]), CultureInfo.InvariantCulture) as string[];109 if (typeHierarchy != null)110 {111 foreach (string t in typeHierarchy)112 {113 type.Clear();114 type.Append(dotnetBaseType);115 type.Append('#');116 if (shouldIncludeNamespace)117 {118 type.Append(managementObj.SystemProperties["__NAMESPACE"].Value);119 type.Append('\\');120 }121 122 type.Append(t);123 yield return type.ToString();124 }125 }126 }127 }128 129 /// <summary>130 /// Returns the TypeNameHierarchy out of an ManagementBaseObject.131 /// </summary>132 /// <param name="obj">Object to get the TypeNameHierarchy from.</param>133 /// <remarks>134 /// TypeName is of the format ObjectType#__Namespace\\__Class135 /// </remarks>136 protected override IEnumerable<string> GetTypeNameHierarchy(object obj)137 {138 ManagementBaseObject managementObj = obj as ManagementBaseObject;139 140 bool isLoopStarted = false;141 foreach (string baseType in GetDotNetTypeNameHierarchy(obj))142 {143 if (!isLoopStarted)144 {145 isLoopStarted = true;146 // Win8: 186792 Return the hierarchy using the __Derivation property as well147 // as NameSpace + Class.148 foreach (string typeFromDerivation in GetTypeNameHierarchyFromDerivation(managementObj, baseType, true))149 {150 yield return typeFromDerivation;151 }152 153 // without namespace154 foreach (string typeFromDerivation in GetTypeNameHierarchyFromDerivation(managementObj, baseType, false))155 {156 yield return typeFromDerivation;157 }158 }159 160 yield return baseType;161 }162 }163 164 /// <summary>165 /// Returns null if memberName is not a member in the adapter or166 /// the corresponding PSMemberInfo.167 /// </summary>168 /// <param name="obj">Object to retrieve the PSMemberInfo from.</param>169 /// <param name="memberName">Name of the member to be retrieved.</param>170 /// <returns>The PSMemberInfo corresponding to memberName from obj.</returns>171 protected override T GetMember<T>(object obj, string memberName)172 {173 tracer.WriteLine("Getting member with name {0}", memberName);174 175 if (obj is not ManagementBaseObject mgmtObject)176 {177 return null;178 }179 180 PSProperty property = DoGetProperty(mgmtObject, memberName);181 182 if (typeof(T).IsAssignableFrom(typeof(PSProperty)) && property != null)183 {184 return property as T;185 }186 187 if (typeof(T).IsAssignableFrom(typeof(PSMethod)))188 {189 T returnValue = GetManagementObjectMethod<T>(mgmtObject, memberName);190 // We only return a method if there is no property by the same name191 // to match the behavior we have in GetMembers192 if (returnValue != null && property == null)193 {194 return returnValue;195 }196 }197 198 return null;199 }200 201 protected override T GetFirstMemberOrDefault<T>(object obj, MemberNamePredicate predicate)202 {203 if (obj is ManagementBaseObject wmiObject)204 {205 return GetFirstOrDefaultProperty<T>(wmiObject, predicate)206 ?? GetFirstOrDefaultMethod<T>(wmiObject, predicate);207 }208 209 return null;210 }211 212 /// <summary>213 /// Retrieves all the members available in the object.214 /// The adapter implementation is encouraged to cache all properties/methods available215 /// in the first call to GetMember and GetMembers so that subsequent216 /// calls can use the cache.217 /// In the case of the .NET adapter that would be a cache from the .NET type to218 /// the public properties and fields available in that type.219 /// In the case of the DirectoryEntry adapter, this could be a cache of the objectClass220 /// to the properties available in it.221 /// </summary>222 /// <param name="obj">Object to get all the member information from.</param>223 /// <returns>All members in obj.</returns>224 protected override PSMemberInfoInternalCollection<T> GetMembers<T>(object obj)225 {226 // obj should never be null227 Diagnostics.Assert(obj != null, "Input object is null");228 229 ManagementBaseObject wmiObject = (ManagementBaseObject)obj;230 PSMemberInfoInternalCollection<T> returnValue = new PSMemberInfoInternalCollection<T>();231 AddAllProperties<T>(wmiObject, returnValue);232 AddAllMethods<T>(wmiObject, returnValue);233 return returnValue;234 }235 236 /// <summary>237 /// Called after a non null return from GetMember to try to call238 /// the method with the arguments.239 /// </summary>240 /// <param name="method">The non empty return from GetMethods.</param>241 /// <param name="arguments">The arguments to use.</param>242 /// <returns>The return value for the method.</returns>243 protected override object MethodInvoke(PSMethod method, object[] arguments)244 {245 ManagementObject mgmtObject = method.baseObject as ManagementObject;246 Diagnostics.Assert(mgmtObject != null,247 "Object is not of ManagementObject type");248 249 WMIMethodCacheEntry methodEntry = (WMIMethodCacheEntry)method.adapterData;250 251 return AuxillaryInvokeMethod(mgmtObject, methodEntry, arguments);252 }253 254 /// <summary>255 /// Called after a non null return from GetMember to return the overloads.256 /// </summary>257 /// <param name="method">The return of GetMember.</param>258 /// <returns></returns>259 protected override Collection<string> MethodDefinitions(PSMethod method)260 {261 WMIMethodCacheEntry methodEntry = (WMIMethodCacheEntry)method.adapterData;262 Collection<string> returnValue = new Collection<string>();263 returnValue.Add(methodEntry.MethodDefinition);264 265 return returnValue;266 }267 268 /// <summary>269 /// Returns true if the property is settable.270 /// </summary>271 /// <param name="property">Property to check.</param>272 /// <returns>True if the property is settable.</returns>273 protected override bool PropertyIsSettable(PSProperty property)274 {275 ManagementBaseObject mObj = property.baseObject as ManagementBaseObject;276 try277 {278 ManagementClass objClass = CreateClassFrmObject(mObj);279 return (bool)objClass.GetPropertyQualifierValue(property.Name, "Write");280 }281 catch (ManagementException)282 {283 // A property that lacks the Write qualifier may still be writeable.284 // The provider implementation may allow any properties in the provider285 // classes to be changed, whether the Write qualifier is present or not.286 return true;287 }288 catch (UnauthorizedAccessException)289 {290 // A property that lacks the Write qualifier may still be writeable.291 // The provider implementation may allow any properties in the provider292 // classes to be changed, whether the Write qualifier is present or not.293 return true;294 }295 catch (System.Runtime.InteropServices.COMException)296 {297 // A property that lacks the Write qualifier may still be writeable.298 // The provider implementation may allow any properties in the provider299 // classes to be changed, whether the Write qualifier is present or not.300 return true;301 }302 }303 304 /// <summary>305 /// Returns true if the property is gettable.306 /// </summary>307 /// <param name="property">Property to check.</param>308 /// <returns>True if the property is gettable.</returns>309 protected override bool PropertyIsGettable(PSProperty property)310 {311 return true;312 }313 314 /// <summary>315 /// Returns the name of the type corresponding to the property.316 /// </summary>317 /// <param name="property">PSProperty obtained in a previous DoGetProperty.</param>318 /// <param name="forDisplay">True if the result is for display purposes only.</param>319 /// <returns>The name of the type corresponding to the property.</returns>320 protected override string PropertyType(PSProperty property, bool forDisplay)321 {322 PropertyData pd = property.adapterData as PropertyData;323 // GetDotNetType will never return null324 Type dotNetType = GetDotNetType(pd);325 string typeName;326 327 // Display Embedded object type name to328 // assist users in passing appropriate329 // object330 if (pd.Type == CimType.Object)331 {332 typeName = GetEmbeddedObjectTypeName(pd);333 334 if (pd.IsArray)335 {336 typeName += "[]";337 }338 }339 else340 {341 typeName = forDisplay ? ToStringCodeMethods.Type(dotNetType) : dotNetType.ToString();342 }343 344 return typeName;345 }346 347 /// <summary>348 /// Returns the value from a property coming from a previous call to DoGetProperty.349 /// </summary>350 /// <param name="property">PSProperty coming from a previous call to DoGetProperty.</param>351 /// <returns>The value of the property.</returns>352 protected override object PropertyGet(PSProperty property)353 {354 PropertyData pd = property.adapterData as PropertyData;355 return pd.Value;356 }357 /// <summary>358 /// Sets the value of a property coming from a previous call to DoGetProperty.359 /// This method will only set the property on a particular instance. If you want360 /// to update the WMI store, call Put().361 /// </summary>362 /// <param name="property">PSProperty coming from a previous call to DoGetProperty.</param>363 /// <param name="setValue">Value to set the property with.</param>364 /// <param name="convertIfPossible">Instructs the adapter to convert before setting, if the adapter supports conversion.</param>365 protected override void PropertySet(PSProperty property, object setValue, bool convertIfPossible)366 {367 if (property.baseObject is not ManagementBaseObject mObj)368 {369 throw new SetValueInvocationException("CannotSetNonManagementObjectMsg",370 null,371 ExtendedTypeSystem.CannotSetNonManagementObject,372 property.Name, property.baseObject.GetType().FullName,373 typeof(ManagementBaseObject).FullName);374 }375 376 if (!PropertyIsSettable(property))377 {378 throw new SetValueException("ReadOnlyWMIProperty",379 null,380 ExtendedTypeSystem.ReadOnlyProperty,381 property.Name);382 }383 384 PropertyData pd = property.adapterData as PropertyData;385 386 if ((convertIfPossible) && (setValue != null))387 {388 // Convert only if value is not null389 Type paramType = GetDotNetType(pd);390 setValue = PropertySetAndMethodArgumentConvertTo(391 setValue, paramType, CultureInfo.InvariantCulture);392 }393 394 pd.Value = setValue;395 return;396 }397 398 /// <summary>399 /// Returns the string representation of the property in the object.400 /// </summary>401 /// <param name="property">Property obtained in a previous GetMember.</param>402 /// <returns>The string representation of the property in the object.</returns>403 protected override string PropertyToString(PSProperty property)404 {405 StringBuilder returnValue = new StringBuilder();406 // if (PropertyIsStatic(property))407 // {408 // returnValue.Append("static ");409 // }410 411 returnValue.Append(PropertyType(property, forDisplay: true));412 returnValue.Append(' ');413 returnValue.Append(property.Name);414 returnValue.Append(" {");415 if (PropertyIsGettable(property))416 {417 returnValue.Append("get;");418 }419 420 if (PropertyIsSettable(property))421 {422 returnValue.Append("set;");423 }424 425 returnValue.Append('}');426 return returnValue.ToString();427 }428 429 /// <summary>430 /// Returns an array with the property attributes.431 /// </summary>432 /// <param name="property">Property we want the attributes from.</param>433 /// <returns>An array with the property attributes.</returns>434 protected override AttributeCollection PropertyAttributes(PSProperty property)435 {436 return null;437 }438 439 #endregion440 441 #region Private/Internal Methods442 443 /// <summary>444 /// Retrieves the table for instance methods.445 /// </summary>446 /// <param name="wmiObject">Object containing methods to load in typeTable.</param>447 /// <param name="staticBinding">Controls what methods are adapted.</param>448 protected static CacheTable GetInstanceMethodTable(ManagementBaseObject wmiObject,449 bool staticBinding)450 {451 lock (s_instanceMethodCacheTable)452 {453 CacheTable typeTable = null;454 455 // unique identifier for identifying this ManagementObject's type456 ManagementPath classPath = wmiObject.ClassPath;457 string key = string.Create(CultureInfo.InvariantCulture, $"{classPath.Path}#{staticBinding}");458 459 typeTable = (CacheTable)s_instanceMethodCacheTable[key];460 if (typeTable != null)461 {462 tracer.WriteLine("Returning method information from internal cache");463 return typeTable;464 }465 466 tracer.WriteLine("Method information not found in internal cache. Constructing one");467 468 try469 {470 // try to populate method table..if there is any exception471 // generating the method metadata..suppress the exception472 // but dont store the info in the cache. This is to allow473 // for method look up again in future (after the wmi object474 // is fixed)475 typeTable = new CacheTable();476 // Construct a ManagementClass object for this object to get the member metadata477 ManagementClass mgmtClass = wmiObject as ManagementClass ?? CreateClassFrmObject(wmiObject);478 PopulateMethodTable(mgmtClass, typeTable, staticBinding);479 s_instanceMethodCacheTable[key] = typeTable;480 }481 catch (ManagementException)482 {483 }484 catch (UnauthorizedAccessException)485 {486 }487 catch (System.Runtime.InteropServices.COMException)488 {489 }490 491 return typeTable;492 }493 }494 495 /// <summary>496 /// Populates methods of a ManagementClass in a CacheTable.497 /// </summary>498 /// <param name="mgmtClass">Class to get the method info from.</param>499 /// <param name="methodTable">Cachetable to update.</param>500 /// <param name="staticBinding">Controls what methods are adapted.</param>501 /// <exception cref="UnauthorizedAccessException"></exception>502 /// <exception cref="ManagementException"></exception>503 private static void PopulateMethodTable(ManagementClass mgmtClass, CacheTable methodTable, bool staticBinding)504 {505 Dbg.Assert(mgmtClass != null, "ManagementClass cannot be null in this method");506 MethodDataCollection mgmtMethods = mgmtClass.Methods;507 if (mgmtMethods != null)508 {509 ManagementPath classPath = mgmtClass.ClassPath;510 // new operation will never fail511 foreach (MethodData mdata in mgmtMethods)512 {513 // is method static514 bool isStatic = IsStaticMethod(mdata);515 if (isStatic == staticBinding)516 {517 // a method is added depending on518 // whether staticBinding is requested or not.519 string methodName = mdata.Name;520 WMIMethodCacheEntry mCache = new WMIMethodCacheEntry(methodName, classPath.Path, mdata);521 methodTable.Add(methodName, mCache);522 }523 }524 }525 }526 527 /// <summary>528 /// Constructs a ManagementClass object from the supplied mgmtBaseObject.529 /// ManagementObject has scope, options, path which need to be carried over to the ManagementClass for530 /// retrieving method/property/parameter metadata.531 /// </summary>532 /// <param name="mgmtBaseObject"></param>533 /// <returns></returns>534 private static ManagementClass CreateClassFrmObject(ManagementBaseObject mgmtBaseObject)535 {536 // Construct a ManagementClass object for this object to get the member metadata537 ManagementClass mgmtClass = mgmtBaseObject as ManagementClass;538 539 // try to use the actual object sent to this method..otherwise construct one540 if (mgmtClass == null)541 {542 mgmtClass = new ManagementClass(mgmtBaseObject.ClassPath);543 544 // inherit ManagementObject properties545 ManagementObject mgmtObject = mgmtBaseObject as ManagementObject;546 if (mgmtObject != null)547 {548 mgmtClass.Scope = mgmtObject.Scope;549 mgmtClass.Options = mgmtObject.Options;550 }551 }552 553 return mgmtClass;554 }555 556 /// <summary>557 /// Gets the object type associated with a CimType:object.558 /// </summary>559 /// <param name="pData">PropertyData representing a parameter.</param>560 /// <returns>561 /// typeof(object)#EmbeddedObjectTypeName if one found562 /// typeof(object) otherwise563 /// </returns>564 /// <remarks>565 /// This helps users of WMI in identifying exactly what type566 /// the underlying WMI provider will accept.567 /// </remarks>568 protected static string GetEmbeddedObjectTypeName(PropertyData pData)569 {570 string result = typeof(object).FullName;571 572 if (pData == null)573 {574 return result;575 }576 577 try578 {579 string cimType = (string)pData.Qualifiers["cimtype"].Value;580 result = string.Format(581 CultureInfo.InvariantCulture,582 "{0}#{1}",583 typeof(ManagementObject).FullName,584 cimType.Replace("object:", string.Empty));585 }586 catch (ManagementException)587 {588 }589 catch (System.Runtime.InteropServices.COMException)590 {591 }592 593 return result;594 }595 596 /// <summary>597 /// Gets the dotnet type of a given PropertyData.598 /// </summary>599 /// <param name="pData">PropertyData input.</param>600 /// <returns>A string representing dotnet type.</returns>601 protected static Type GetDotNetType(PropertyData pData)602 {603 Diagnostics.Assert(pData != null,604 "Input PropertyData should not be null");605 606 tracer.WriteLine("Getting DotNet Type for CimType : {0}", pData.Type);607 608 string retValue;609 switch (pData.Type)610 {611 case CimType.SInt8:612 retValue = typeof(sbyte).FullName;613 break;614 case CimType.UInt8:615 retValue = typeof(byte).FullName;616 break;617 case CimType.SInt16:618 retValue = typeof(System.Int16).FullName;619 break;620 case CimType.UInt16:621 retValue = typeof(System.UInt16).FullName;622 break;623 case CimType.SInt32:624 retValue = typeof(System.Int32).FullName;625 break;626 case CimType.UInt32:627 retValue = typeof(System.UInt32).FullName;628 break;629 case CimType.SInt64:630 retValue = typeof(System.Int64).FullName;631 break;632 case CimType.UInt64:633 retValue = typeof(System.UInt64).FullName;634 break;635 case CimType.Real32:636 retValue = typeof(Single).FullName;637 break;638 case CimType.Real64:639 retValue = typeof(double).FullName;640 break;641 case CimType.Boolean:642 retValue = typeof(bool).FullName;643 break;644 case CimType.String:645 retValue = typeof(string).FullName;646 break;647 case CimType.DateTime:648 // this is actually a string649 retValue = typeof(string).FullName;650 break;651 case CimType.Reference:652 // this is actually a string653 retValue = typeof(string).FullName;654 break;655 case CimType.Char16:656 retValue = typeof(char).FullName;657 break;658 case CimType.Object:659 default:660 retValue = typeof(object).FullName;661 break;662 }663 664 if (pData.IsArray)665 {666 retValue += "[]";667 }668 669 return Type.GetType(retValue);670 }671 672 /// <summary>673 /// Checks whether a given MethodData is static or not.674 /// </summary>675 /// <param name="mdata"></param>676 /// <returns>677 /// true, if static678 /// </returns>679 /// <remarks>680 /// This method relies on the qualifier "static"681 /// </remarks>682 protected static bool IsStaticMethod(MethodData mdata)683 {684 try685 {686 QualifierData staticQualifier = mdata.Qualifiers["static"];687 if (staticQualifier == null)688 return false;689 690 bool result = false;691 LanguagePrimitives.TryConvertTo<bool>(staticQualifier.Value, out result);692 693 return result;694 }695 catch (ManagementException)696 {697 }698 catch (System.Runtime.InteropServices.COMException)699 {700 }701 702 return false;703 }704 705 private object AuxillaryInvokeMethod(ManagementObject obj, WMIMethodCacheEntry mdata, object[] arguments)706 {707 // Evaluate method and arguments708 object[] verifiedArguments;709 710 MethodInformation[] methods = new MethodInformation[1];711 methods[0] = mdata.MethodInfoStructure;712 713 // This will convert Null Strings to Empty Strings714 GetBestMethodAndArguments(mdata.Name, methods, arguments, out verifiedArguments);715 716 ParameterInformation[] parameterList = mdata.MethodInfoStructure.parameters;717 718 // GetBestMethodAndArguments should fill verifiedArguments with719 // correct values (even if some values are not specified)720 tracer.WriteLine("Parameters found {0}. Arguments supplied {0}",721 parameterList.Length, verifiedArguments.Length);722 723 Diagnostics.Assert(parameterList.Length == verifiedArguments.Length,724 "The number of parameters and arguments should match");725 726 // we should not cache inParameters as we are updating727 // inParameters object with argument values..Caching will728 // have side effects in this scenario like we have to clear729 // the values once the method is invoked.730 // Also caching MethodData occupies lot of memory compared to731 // caching string.732 ManagementClass mClass = CreateClassFrmObject(obj);733 ManagementBaseObject inParameters = mClass.GetMethodParameters(mdata.Name);734 735 for (int i = 0; i < parameterList.Length; i++)736 {737 // this cast should always succeed738 WMIParameterInformation pInfo = (WMIParameterInformation)parameterList[i];739 740 // Should not convert null input arguments741 // GetBestMethodAndArguments converts null strings to empty strings742 // and also null ints to 0. But WMI providers do not like these743 // conversions. So dont convert input arguments if they are null.744 // We could have done this in the base adapter but the change would be745 // costly for other adapters which dont mind the conversion.746 if ((i < arguments.Length) && (arguments[i] == null))747 {748 verifiedArguments[i] = null;749 }750 751 inParameters[pInfo.Name] = verifiedArguments[i];752 }753 754 return InvokeManagementMethod(obj, mdata.Name, inParameters);755 }756 757 /// <summary>758 /// Decode parameter information from the supplied object.759 /// </summary>760 /// <param name="parameters">A ManagementBaseObject describing the parameters.</param>761 /// <param name="parametersList">A sorted list to store parameter information.</param>762 /// <remarks>763 /// Should not throw exceptions764 /// </remarks>765 internal static void UpdateParameters(ManagementBaseObject parameters,766 SortedList<int, WMIParameterInformation> parametersList)767 {768 // ManagementObject class do not populate parameters when there are none.769 if (parameters == null)770 return;771 772 foreach (PropertyData data in parameters.Properties)773 {774 // parameter position..775 int location = -1;776 WMIParameterInformation pInfo = new WMIParameterInformation(data.Name, GetDotNetType(data));777 778 try779 {780 location = (int)data.Qualifiers["ID"].Value;781 }782 catch (ManagementException)783 {784 // If there is an exception accessing location785 // add the parameter to the end.786 }787 catch (System.Runtime.InteropServices.COMException)788 {789 // If there is an exception accessing location790 // add the parameter to the end.791 }792 793 if (location < 0)794 {795 location = parametersList.Count;796 }797 798 parametersList[location] = pInfo;799 }800 }801 802 /// <summary>803 /// Gets WMI method information.804 /// </summary>805 /// <param name="mData"></param>806 /// <returns></returns>807 /// <remarks>808 /// Decodes only input parameters.809 /// </remarks>810 internal static MethodInformation GetMethodInformation(MethodData mData)811 {812 Diagnostics.Assert(mData != null, "MethodData should not be null");813 814 // Get Method parameters815 var parameters = new SortedList<int, WMIParameterInformation>();816 UpdateParameters(mData.InParameters, parameters);817 818 // parameters is never null819 WMIParameterInformation[] pInfos = new WMIParameterInformation[parameters.Count];820 if (parameters.Count > 0)821 {822 parameters.Values.CopyTo(pInfos, 0);823 }824 825 MethodInformation returnValue = new MethodInformation(false, true, pInfos);826 827 return returnValue;828 }829 830 internal static string GetMethodDefinition(MethodData mData)831 {832 // gather parameter information for this method.833 // input and output parameters reside in 2 different groups..834 // we dont know the order they appear on the arguments line..835 var parameters = new SortedList<int, WMIParameterInformation>();836 UpdateParameters(mData.InParameters, parameters);837 838 StringBuilder inParameterString = new StringBuilder();839 840 if (parameters.Count > 0)841 {842 for (int i = 0; i < parameters.Values.Count; i++)843 {844 WMIParameterInformation parameter = parameters.Values[i];845 string typeName = parameter.parameterType.ToString();846 847 PropertyData pData = mData.InParameters.Properties[parameter.Name];848 if (pData.Type == CimType.Object)849 {850 typeName = GetEmbeddedObjectTypeName(pData);851 852 if (pData.IsArray)853 {854 typeName += "[]";855 }856 }857 858 inParameterString.Append(typeName);859 inParameterString.Append(' ');860 inParameterString.Append(parameter.Name);861 inParameterString.Append(", ");862 }863 }864 865 if (inParameterString.Length > 2)866 {867 inParameterString.Remove(inParameterString.Length - 2, 2);868 }869 870 tracer.WriteLine("Constructing method definition for method {0}", mData.Name);871 StringBuilder builder = new StringBuilder();872 873 builder.Append("System.Management.ManagementBaseObject ");874 builder.Append(mData.Name);875 builder.Append('(');876 builder.Append(inParameterString);877 builder.Append(')');878 879 string returnValue = builder.ToString();880 tracer.WriteLine("Definition constructed: {0}", returnValue);881 882 return returnValue;883 }884 885 #endregion886 887 #region Abstract Methods888 889 /// <summary>890 /// Retrieves all the properties available in the object.891 /// </summary>892 /// <param name="wmiObject">Object to get all the property information from.</param>893 /// <param name="members">Collection where the members will be added.</param>894 protected abstract void AddAllProperties<T>(ManagementBaseObject wmiObject,895 PSMemberInfoInternalCollection<T> members) where T : PSMemberInfo;896 897 /// <summary>898 /// Adds method information of the ManagementObject. This is done by accessing899 /// the ManagementClass corresponding to this ManagementObject. All the method900 /// information is cached for a particular ManagementObject.901 /// </summary>902 /// <typeparam name="T">PSMemberInfo</typeparam>903 /// <param name="wmiObject">Object for which the members need to be retrieved.</param>904 /// <param name="members">Method information is added to this.</param>905 protected abstract void AddAllMethods<T>(ManagementBaseObject wmiObject,906 PSMemberInfoInternalCollection<T> members) where T : PSMemberInfo;907 908 protected abstract object InvokeManagementMethod(ManagementObject wmiObject,909 string methodName, ManagementBaseObject inParams);910 911 /// <summary>912 /// Get a method object given method name.913 /// </summary>914 /// <typeparam name="T">PSMemberInfo</typeparam>915 /// <param name="wmiObject">Object for which the method is required.</param>916 /// <param name="methodName">Name of the method.</param>917 /// <returns>918 /// PsMemberInfo if method exists.919 /// Null otherwise.920 /// </returns>921 protected abstract T GetManagementObjectMethod<T>(ManagementBaseObject wmiObject,922 string methodName) where T : PSMemberInfo;923 924 /// <summary>925 /// Returns null if propertyName is not a property in the adapter or926 /// the corresponding PSProperty with its adapterData set to information927 /// to be used when retrieving the property.928 /// </summary>929 /// <param name="wmiObject">Object to retrieve the PSProperty from.</param>930 /// <param name="propertyName">Name of the property to be retrieved.</param>931 /// <returns>The PSProperty corresponding to propertyName from obj.</returns>932 protected abstract PSProperty DoGetProperty(ManagementBaseObject wmiObject,933 string propertyName);934 935 /// <summary>936 /// Returns the first property whose name matches the specified <see cref="MemberNamePredicate"/>937 /// </summary>938 protected abstract T GetFirstOrDefaultProperty<T>(ManagementBaseObject wmiObject, MemberNamePredicate predicate) where T : PSMemberInfo;939 940 /// <summary>941 /// Returns the first method whose name matches the specified <see cref="MemberNamePredicate"/>942 /// </summary>943 protected abstract T GetFirstOrDefaultMethod<T>(ManagementBaseObject wmiObject, MemberNamePredicate predicate) where T : PSMemberInfo;944 945 #endregion946 947 #region Private Data948 949 private static readonly HybridDictionary s_instanceMethodCacheTable = new HybridDictionary();950 951 #endregion952 }953 954 /// <summary>955 /// Deals with ManagementClass objects.956 /// Adapts only static methods and SystemProperties of a957 /// ManagementClass object.958 /// </summary>959 internal class ManagementClassApdapter : BaseWMIAdapter960 {961 protected override void AddAllProperties<T>(ManagementBaseObject wmiObject,962 PSMemberInfoInternalCollection<T> members)963 {964 if (wmiObject.SystemProperties != null)965 {966 foreach (PropertyData property in wmiObject.SystemProperties)967 {968 members.Add(new PSProperty(property.Name, this, wmiObject, property) as T);969 }970 }971 }972 973 protected override PSProperty DoGetProperty(ManagementBaseObject wmiObject, string propertyName)974 {975 if (wmiObject.SystemProperties != null)976 {977 foreach (PropertyData property in wmiObject.SystemProperties)978 {979 if (propertyName.Equals(property.Name, StringComparison.OrdinalIgnoreCase))980 {981 return new PSProperty(property.Name, this, wmiObject, property);982 }983 }984 }985 986 return null;987 }988 989 /// <summary>990 /// Invokes method represented by <paramref name="mdata"/> using supplied arguments.991 /// </summary>992 /// <param name="wmiObject">ManagementObject on which the method is invoked.</param>993 /// <param name="methodName">Method data.</param>994 /// <param name="inParams">Method arguments.</param>995 /// <returns></returns>996 protected override object InvokeManagementMethod(ManagementObject wmiObject,997 string methodName, ManagementBaseObject inParams)998 {999 tracer.WriteLine("Invoking class method: {0}", methodName);1000 1001 ManagementClass mClass = wmiObject as ManagementClass;1002 1003 try1004 {1005 return mClass.InvokeMethod(methodName, inParams, null);1006 }1007 catch (Exception e)1008 {1009 throw new MethodInvocationException(1010 "WMIMethodException",1011 e,1012 ExtendedTypeSystem.WMIMethodInvocationException,1013 methodName, e.Message);1014 }1015 }1016 1017 /// <summary>1018 /// Adds method information of the ManagementClass. Only static methods are added for1019 /// an object of type ManagementClass.1020 /// </summary>1021 /// <typeparam name="T">PSMemberInfo</typeparam>1022 /// <param name="wmiObject">Object for which the members need to be retrieved.</param>1023 /// <param name="members">Method information is added to this.</param>1024 protected override void AddAllMethods<T>(ManagementBaseObject wmiObject,1025 PSMemberInfoInternalCollection<T> members)1026 {1027 Diagnostics.Assert((wmiObject != null) && (members != null),1028 "Input arguments should not be null.");1029 1030 if (!typeof(T).IsAssignableFrom(typeof(PSMethod)))1031 {1032 return;1033 }1034 1035 CacheTable table;1036 table = GetInstanceMethodTable(wmiObject, true);1037 1038 foreach (WMIMethodCacheEntry methodEntry in table.memberCollection)1039 {1040 if (members[methodEntry.Name] == null)1041 {1042 tracer.WriteLine("Adding method {0}", methodEntry.Name);1043 members.Add(new PSMethod(methodEntry.Name, this, wmiObject, methodEntry) as T);1044 }1045 }1046 }1047 1048 /// <summary>1049 /// Returns method information for a ManagementClass method.1050 /// </summary>1051 /// <typeparam name="T"></typeparam>1052 /// <param name="wmiObject"></param>1053 /// <param name="methodName"></param>1054 /// <returns>1055 /// PSMethod if method exists and is static. Null otherwise.1056 /// </returns>1057 protected override T GetManagementObjectMethod<T>(ManagementBaseObject wmiObject, string methodName)1058 {1059 if (!typeof(T).IsAssignableFrom(typeof(PSMethod)))1060 {1061 return null;1062 }1063 1064 CacheTable typeTable = GetInstanceMethodTable(wmiObject, true);1065 WMIMethodCacheEntry method = (WMIMethodCacheEntry)typeTable[methodName];1066 1067 if (method == null)1068 {1069 return null;1070 }1071 1072 return new PSMethod(method.Name, this, wmiObject, method) as T;1073 }1074 1075 protected override T GetFirstOrDefaultProperty<T>(ManagementBaseObject wmiObject, MemberNamePredicate predicate)1076 {1077 if (!typeof(T).IsAssignableFrom(typeof(PSProperty)))1078 {1079 return null;1080 }1081 1082 if (wmiObject.SystemProperties != null)1083 {1084 foreach (PropertyData property in wmiObject.SystemProperties)1085 {1086 if (predicate(property.Name))1087 {1088 return new PSProperty(property.Name, this, wmiObject, property) as T;1089 }1090 }1091 }1092 1093 return null;1094 }1095 1096 protected override T GetFirstOrDefaultMethod<T>(ManagementBaseObject wmiObject, MemberNamePredicate predicate)1097 {1098 if (!typeof(T).IsAssignableFrom(typeof(PSMethod)))1099 {1100 return null;1101 }1102 1103 CacheTable table = GetInstanceMethodTable(wmiObject, true);1104 foreach (WMIMethodCacheEntry methodEntry in table.memberCollection)1105 {1106 if (predicate(methodEntry.Name))1107 {1108 return new PSMethod(methodEntry.Name, this, wmiObject, methodEntry) as T;1109 }1110 }1111 1112 return null;1113 }1114 }1115 1116 /// <summary>1117 /// Deals with ManagementObject objects.1118 /// This class do not adapt static methods.1119 /// </summary>1120 internal class ManagementObjectAdapter : ManagementClassApdapter1121 {1122 protected override void AddAllProperties<T>(ManagementBaseObject wmiObject,1123 PSMemberInfoInternalCollection<T> members)1124 {1125 // Add System properties1126 base.AddAllProperties(wmiObject, members);1127 1128 if (wmiObject.Properties != null)1129 {1130 foreach (PropertyData property in wmiObject.Properties)1131 {1132 members.Add(new PSProperty(property.Name, this, wmiObject, property) as T);1133 }1134 }1135 }1136 1137 protected override PSProperty DoGetProperty(ManagementBaseObject wmiObject, string propertyName)1138 {1139 PropertyData adapterData = null;1140 1141 // First check whether we have any Class properties by this name1142 PSProperty returnValue = base.DoGetProperty(wmiObject, propertyName);1143 1144 if (returnValue != null)1145 {1146 return returnValue;1147 }1148 1149 try1150 {1151 adapterData = wmiObject.Properties[propertyName];1152 return new PSProperty(adapterData.Name, this, wmiObject, adapterData);1153 }1154 catch (ManagementException)1155 {1156 }1157 catch (Exception e)1158 {1159 // TODO: Bug 251457. This is a workaround to unblock partners and find out the root cause.1160 Tracing.PSEtwLogProvider provider = new Tracing.PSEtwLogProvider();1161 1162 provider.WriteEvent(PSEventId.Engine_Health,1163 PSChannel.Analytic,1164 PSOpcode.Exception,1165 PSLevel.Informational,1166 PSTask.None,1167 PSKeyword.UseAlwaysOperational,1168 string.Create(CultureInfo.InvariantCulture, $"ManagementBaseObjectAdapter::DoGetProperty::PropertyName:{propertyName}, Exception:{e.Message}, StackTrace:{e.StackTrace}"),1169 string.Empty,1170 string.Empty);1171 // ignore the exception.1172 }1173 1174 return null;1175 }1176 1177 /// <summary>1178 /// Invokes method represented by <paramref name="mdata"/> using supplied arguments.1179 /// </summary>1180 /// <param name="obj">ManagementObject on which the method is invoked.</param>1181 /// <param name="methodName">Method data.</param>1182 /// <param name="inParams">Method arguments.</param>1183 /// <returns></returns>1184 protected override object InvokeManagementMethod(ManagementObject obj, string methodName, ManagementBaseObject inParams)1185 {1186 tracer.WriteLine("Invoking class method: {0}", methodName);1187 1188 try1189 {1190 ManagementBaseObject robj = obj.InvokeMethod(methodName, inParams, null);1191 return robj;1192 }1193 catch (Exception e)1194 {1195 throw new MethodInvocationException(1196 "WMIMethodException",1197 e,1198 ExtendedTypeSystem.WMIMethodInvocationException,1199 methodName, e.Message);1200 }