MegaBites-AI/Windows-powershell
0372
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System;5using System.Collections;6using System.Collections.Generic;7using System.Collections.ObjectModel;8using System.Diagnostics.CodeAnalysis;9using System.Globalization;10using System.IO;11using System.Management.Automation;12using System.Management.Automation.Provider;13using System.Runtime.InteropServices;14using System.Security;15using System.ServiceProcess;16using System.Text;17using System.Text.RegularExpressions;18using System.Xml;19using System.Xml.XPath;20 21namespace Microsoft.WSMan.Management22{23 /// <summary>24 /// WsMan Provider.25 /// </summary>26 [CmdletProvider(WSManStringLiterals.ProviderName, ProviderCapabilities.Credentials)]27 public sealed class WSManConfigProvider : NavigationCmdletProvider, ICmdletProviderSupportsHelp28 {29 // Plugin Name Storage30 private PSObject objPluginNames = null;31 32 private ServiceController winrmServiceController;33 34 /// <summary>35 /// Determines if Set-Item user input type validation is required or not.36 /// It is True by default, Clear-Item will set it to false so that it can37 /// pass Empty string as value for Set-Item.38 /// </summary>39 private bool clearItemIsCalled = false;40 41 private WSManHelper helper = new WSManHelper();42 43 /// <summary>44 /// Object contains the cache of the enumerate results for the cmdlet to execute.45 /// </summary>46 private readonly Dictionary<string, XmlDocument> enumerateMapping = new Dictionary<string, XmlDocument>();47 48 /// <summary>49 /// Mapping of ResourceURI with the XML returned by the Get call.50 /// </summary>51 private readonly Dictionary<string, string> getMapping = new Dictionary<string, string>();52 53 #region ICmdletProviderSupportsHelp Members54 55 /// <summary>56 /// This implements Get-Help for config provider custom path.57 /// When user calls "Get-Help new-item" in our config provider path, this function will get called.58 /// </summary>59 /// <param name="helpItemName"></param>60 /// <param name="path"></param>61 /// <returns></returns>62 string ICmdletProviderSupportsHelp.GetHelpMaml(string helpItemName, string path)63 {64 // Get the leaf node from the path for which help is requested.65 int ChildIndex = path.LastIndexOf('\\');66 if (ChildIndex == -1)67 {68 // Means we are at host level, where no new-item is supported. Return empty string.69 return string.Empty;70 }71 72 string child = path.Substring(ChildIndex + 1);73 74 // We only return help for the below set of 5 commands, not for any other case.75 switch (helpItemName)76 {77 case "New-Item":78 case "Get-Item":79 case "Set-Item":80 case "Clear-Item":81 case "Remove-Item":82 break;83 default:84 return string.Empty;85 }86 87 // Load the help file from the current UI culture subfolder of the module's root folder88 XmlDocument document = new XmlDocument();89 CultureInfo culture = Host.CurrentUICulture;90 string providerBase = this.ProviderInfo.PSSnapIn != null ? this.ProviderInfo.PSSnapIn.ApplicationBase : this.ProviderInfo.Module.ModuleBase; // "\windows\system32\WindowsPowerShell\v1.0"91 string helpFile = null;92 93 do94 {95 string muiDirectory = Path.Combine(providerBase, culture.Name);96 if (Directory.Exists(muiDirectory))97 {98 string supposedHelpFile = Path.Combine(muiDirectory, this.ProviderInfo.HelpFile);99 if (File.Exists(supposedHelpFile))100 {101 helpFile = supposedHelpFile;102 break;103 }104 }105 106 culture = culture.Parent;107 } while (culture != culture.Parent);108 109 if (helpFile == null)110 {111 // Can't find help file. Return empty string112 return string.Empty;113 }114 115 try116 {117 XmlReaderSettings readerSettings = new XmlReaderSettings();118 readerSettings.XmlResolver = null;119 using (XmlReader reader = XmlReader.Create(helpFile, readerSettings))120 {121 document.Load(reader);122 }123 }124 catch (XmlException)125 {126 return string.Empty;127 }128 catch (PathTooLongException)129 {130 return string.Empty;131 }132 catch (IOException)133 {134 return string.Empty;135 }136 catch (UnauthorizedAccessException)137 {138 return string.Empty;139 }140 catch (NotSupportedException)141 {142 return string.Empty;143 }144 catch (SecurityException)145 {146 return string.Empty;147 }148 149 // Add the "msh" and "command" namespaces from the MAML schema150 XmlNamespaceManager nsMgr = new XmlNamespaceManager(document.NameTable);151 // XPath 1.0 associates empty prefix with "null" namespace; must use non-empty prefix for default namespace.152 // This will not work: nsMgr.AddNamespace(string.Empty, "http://msh");153 nsMgr.AddNamespace("msh", "http://msh");154 nsMgr.AddNamespace("command", "http://schemas.microsoft.com/maml/dev/command/2004/10");155 156 // Split the help item name into verb and noun157 string verb = helpItemName.Split('-')[0];158 string noun = helpItemName.Substring(helpItemName.IndexOf('-') + 1);159 160 // Compose XPath query to select the appropriate node based on the verb, noun and id161 string xpathQuery = "/msh:helpItems/msh:providerHelp/msh:CmdletHelpPaths/msh:CmdletHelpPath[@id='" + child + "' or @ID='" + child + "']/command:command/command:details[command:verb='" + verb + "' and command:noun='" + noun + "']";162 163 // Execute the XPath query and if the command was found, return its MAML snippet164 XmlNode result = null;165 try166 {167 result = document.SelectSingleNode(xpathQuery, nsMgr);168 }169 catch (XPathException)170 {171 return string.Empty;172 }173 174 if (result != null)175 {176 return result.ParentNode.OuterXml;177 }178 179 return string.Empty;180 }181 182 #endregion183 184 #region DriveCmdletProvider185 /// <summary>186 /// </summary>187 /// <param name="drive"></param>188 /// <returns></returns>189 protected override PSDriveInfo NewDrive(PSDriveInfo drive)190 {191 if (drive == null)192 {193 return null;194 }195 196 if (!string.IsNullOrEmpty(drive.Root))197 {198 AssertError(helper.GetResourceMsgFromResourcetext("NewDriveRootDoesNotExist"), false);199 return null;200 }201 202 return drive;203 }204 205 /// <summary>206 /// Adds the required drive.207 /// </summary>208 /// <returns></returns>209 protected override Collection<PSDriveInfo> InitializeDefaultDrives()210 {211 Collection<PSDriveInfo> drives = new Collection<PSDriveInfo>();212 drives.Add(new PSDriveInfo(WSManStringLiterals.rootpath, ProviderInfo, string.Empty,213 helper.GetResourceMsgFromResourcetext("ConfigStorage"), null));214 return drives;215 }216 217 /// <summary>218 /// Removes the required drive.219 /// </summary>220 /// <returns></returns>221 protected override PSDriveInfo RemoveDrive(PSDriveInfo drive)222 {223 WSManHelper.ReleaseSessions();224 return drive;225 }226 227 #endregion228 229 #region ItemCmdletProvider230 231 /// <summary>232 /// Get a Child Name. This method is called from MakePath method.233 /// This Method helps in getting the correct case of particular element in the provider path.234 /// XML is case sensitive but Powershell is not.235 /// </summary>236 /// <param name="path"></param>237 /// <returns></returns>238 protected override string GetChildName(string path)239 {240 string result = string.Empty;241 int separatorIndex = path.LastIndexOf(WSManStringLiterals.DefaultPathSeparator);242 string hostname = string.Empty;243 if (separatorIndex == -1)244 {245 result = path;246 hostname = path;247 }248 else249 {250 result = path.Substring(separatorIndex + 1);251 hostname = GetHostName(path);252 }253 254 return GetCorrectCaseOfName(result, hostname, path);255 }256 257 /// <summary>258 /// This method is provided by the Provider infrastructure. This method is called in all actions done259 /// by the provider to get the resolved path. Internally Resolve-Path is called.260 /// Since Root is empty for WsMan Provider the default path generated by Makepath is not correct.261 /// So we have made the tweaks in this method to return the correct resolved path.262 /// </summary>263 /// <param name="parent"></param>264 /// <param name="child"></param>265 /// <returns></returns>266 protected override string MakePath(string parent, string child)267 {268 if (child.EndsWith(WSManStringLiterals.DefaultPathSeparator.ToString(), StringComparison.OrdinalIgnoreCase))269 {270 child = child.Remove(child.LastIndexOf(WSManStringLiterals.DefaultPathSeparator));271 }272 273 // For Listeners only ... should remove Listener from listener\listener but not from listener_[Hashcode]274 if (parent.Equals(WSManStringLiterals.containerListener, StringComparison.OrdinalIgnoreCase) && child.StartsWith(parent, StringComparison.OrdinalIgnoreCase))275 {276 if (!child.StartsWith(parent + "_", StringComparison.OrdinalIgnoreCase))277 {278 child = child.Remove(0, parent.Length);279 }280 }281 282 string path = string.Empty;283 string ChildName = string.Empty;284 string CorrectCaseChildName = string.Empty;285 if (parent.Length != 0)286 {287 path = parent + WSManStringLiterals.DefaultPathSeparator + child;288 }289 else290 {291 path = child;292 }293 294 if (path.Length != 0)295 {296 ChildName = path.Substring(path.LastIndexOf(WSManStringLiterals.DefaultPathSeparator) + 1);297 CorrectCaseChildName = GetChildName(path);298 }299 300 if (ChildName.Equals(CorrectCaseChildName, StringComparison.OrdinalIgnoreCase))301 {302 if (child.Contains(WSManStringLiterals.DefaultPathSeparator.ToString()))303 {304 child = child.Substring(0, child.LastIndexOf(WSManStringLiterals.DefaultPathSeparator));305 child = child + WSManStringLiterals.DefaultPathSeparator + CorrectCaseChildName;306 }307 else308 {309 child = CorrectCaseChildName;310 }311 }312 313 string basepath = base.MakePath(parent, child);314 return GetCorrectCaseOfPath(basepath);315 }316 317 /// <summary>318 /// Checks whether the path is Valid.319 /// eg. winrm/config/client.320 /// </summary>321 /// <param name="path"></param>322 /// <returns></returns>323 protected override bool IsValidPath(string path)324 {325 bool result = false;326 result = CheckValidContainerOrPath(path);327 return result;328 }329 330 /// <summary>331 /// Check whether an Item Exist in the winrm configuration.332 /// </summary>333 /// <param name="path"></param>334 /// <returns></returns>335 protected override bool ItemExists(string path)336 {337 bool result = false;338 result = CheckValidContainerOrPath(path);339 return result;340 }341 342 /// <summary>343 /// Checks whether the given path has got child items.344 /// e.g: This is called by Provider infrastructure when we do a Remove-Item and prompts user345 /// if child items are present.346 /// </summary>347 /// <param name="path"></param>348 /// <returns></returns>349 protected override bool HasChildItems(string path)350 {351 string childname = string.Empty;352 string strPathCheck = string.Empty;353 354 if (path.Length == 0 && string.IsNullOrEmpty(childname))355 {356 return true;357 }358 359 // if endswith '\', removes it.360 if (path.EndsWith(WSManStringLiterals.DefaultPathSeparator.ToString(), StringComparison.OrdinalIgnoreCase))361 {362 path = path.Remove(path.LastIndexOf(WSManStringLiterals.DefaultPathSeparator));363 }364 365 if (path.Contains(WSManStringLiterals.DefaultPathSeparator.ToString()))366 {367 // Get the ChildName368 childname = path.Substring(path.LastIndexOf(WSManStringLiterals.DefaultPathSeparator) + 1);369 }370 371 Dictionary<string, object> SessionObjCache = WSManHelper.GetSessionObjCache();372 if (SessionObjCache.ContainsKey(path))373 {374 return true;375 }376 377 // Get the wsman host name to find the session object378 string host = GetHostName(path);379 380 // Chks the WinRM Service381 if (IsPathLocalMachine(host))382 {383 if (!IsWSManServiceRunning())384 {385 WSManHelper.ThrowIfNotAdministrator();386 StartWSManService(Force);387 }388 }389 390 string WsManURI = NormalizePath(path, host);391 392 lock (WSManHelper.AutoSession)393 {394 // Gets the session object from the cache.395 object sessionobj;396 SessionObjCache.TryGetValue(host, out sessionobj);397 398 /*399 WsMan Config Can be divided in to Four Fixed Regions to Check Whether it has Child Items.400 401 * 1. Branch in to Listeners (winrm/config/listener)402 * 2. Branch in to CertMapping (winrm/config/service/certmapping)403 * 3. Branch in to Plugin (winrm/config/plugin) - Plugin is subdivided in Resources,Security & InitParams404 * 4. Rest all the branches like Client, Shell(WinRS) ,Service405 406 */407 408 // 1. Listener Checks409 strPathCheck = host + WSManStringLiterals.DefaultPathSeparator;410 if (WsManURI.Contains(WSManStringLiterals.containerListener))411 {412 XmlDocument xmlListeners = EnumerateResourceValue(sessionobj, WsManURI);413 if (xmlListeners != null)414 {415 Hashtable KeyCache, ListenerObjCache;416 ProcessListenerObjects(xmlListeners, out ListenerObjCache, out KeyCache);417 if (ListenerObjCache.Count > 0)418 {419 return true;420 }421 }422 }423 // 2. Client Certificate Checks424 else if (WsManURI.Contains(WSManStringLiterals.containerCertMapping))425 {426 XmlDocument xmlCertificates = EnumerateResourceValue(sessionobj, WsManURI);427 Hashtable KeyCache, CertificatesObjCache;428 if (xmlCertificates == null)429 {430 return true;431 }432 433 ProcessCertMappingObjects(xmlCertificates, out CertificatesObjCache, out KeyCache);434 if (CertificatesObjCache.Count > 0)435 {436 return true;437 }438 }439 // 3. Plugin and its internal structure Checks440 else if (WsManURI.Contains(WSManStringLiterals.containerPlugin))441 {442 strPathCheck += WSManStringLiterals.containerPlugin;443 // Check for Plugin path444 XmlDocument xmlPlugins = FindResourceValue(sessionobj, WsManURI, null);445 string currentpluginname = string.Empty;446 int PluginCount = GetPluginNames(xmlPlugins, out objPluginNames, out currentpluginname, path);447 if (path.Equals(strPathCheck))448 {449 if (PluginCount > 0)450 {451 return true;452 }453 else454 {455 return false;456 }457 }458 459 strPathCheck = strPathCheck + WSManStringLiterals.DefaultPathSeparator + currentpluginname;460 if (path.EndsWith(strPathCheck, StringComparison.OrdinalIgnoreCase))461 {462 if (objPluginNames != null)463 {464 if (objPluginNames.Properties.Match(currentpluginname).Count > 0)465 {466 return true;467 }468 else469 {470 return false;471 }472 }473 }474 475 string filter = WsManURI + "?Name=" + currentpluginname;476 XmlDocument CurrentPluginXML = GetResourceValue(sessionobj, filter, null);477 ArrayList arrSecurities = null;478 ArrayList arrResources = ProcessPluginResourceLevel(CurrentPluginXML, out arrSecurities);479 ArrayList arrInitParams = ProcessPluginInitParamLevel(CurrentPluginXML);480 strPathCheck += WSManStringLiterals.DefaultPathSeparator;481 if (path.EndsWith(strPathCheck + WSManStringLiterals.containerResources, StringComparison.OrdinalIgnoreCase))482 {483 if (arrResources != null && arrResources.Count > 0)484 {485 return true;486 }487 }488 489 if (path.EndsWith(strPathCheck + WSManStringLiterals.containerInitParameters, StringComparison.OrdinalIgnoreCase))490 {491 if (arrInitParams != null && arrInitParams.Count > 0)492 {493 return true;494 }495 }496 497 if (path.EndsWith(strPathCheck + WSManStringLiterals.containerQuotasParameters, StringComparison.OrdinalIgnoreCase))498 {499 XmlNodeList nodeListForQuotas = CurrentPluginXML.GetElementsByTagName(WSManStringLiterals.containerQuotasParameters);500 if (nodeListForQuotas.Count > 0)501 {502 XmlNode pluginQuotas = nodeListForQuotas[0];503 return pluginQuotas.Attributes.Count > 0;504 }505 506 return false;507 }508 509 if (arrResources != null)510 {511 foreach (PSObject objresource in arrResources)512 {513 string sResourceDirName = objresource.Properties["ResourceDir"].Value.ToString();514 if (path.Contains(sResourceDirName))515 {516 strPathCheck = strPathCheck + WSManStringLiterals.containerResources + WSManStringLiterals.DefaultPathSeparator;517 if (path.EndsWith(strPathCheck + sResourceDirName, StringComparison.OrdinalIgnoreCase))518 {519 return true;520 }521 522 strPathCheck = strPathCheck + sResourceDirName + WSManStringLiterals.DefaultPathSeparator;523 if (path.Contains(strPathCheck + WSManStringLiterals.containerSecurity))524 {525 if (path.EndsWith(strPathCheck + WSManStringLiterals.containerSecurity, StringComparison.OrdinalIgnoreCase))526 {527 if (arrSecurities != null && arrSecurities.Count > 0)528 {529 return true;530 }531 }532 533 strPathCheck = strPathCheck + WSManStringLiterals.containerSecurity + WSManStringLiterals.DefaultPathSeparator;534 if (path.Contains(strPathCheck + WSManStringLiterals.containerSecurity + "_"))535 {536 if (arrSecurities == null)537 {538 return false;539 }540 541 foreach (PSObject security in arrSecurities)542 {543 string sSecurity = security.Properties["SecurityDIR"].Value.ToString();544 if (path.EndsWith(sSecurity, StringComparison.OrdinalIgnoreCase))545 return true;546 }547 }548 }549 }550 }551 }552 }553 else554 // 4. All Other Item Checks555 {556 string getXml = this.GetResourceValueInXml(sessionobj, WsManURI, null);557 XmlDocument xmlResourceValues = new XmlDocument();558 xmlResourceValues.LoadXml(getXml.ToLowerInvariant());559 XmlNodeList nodes = SearchXml(xmlResourceValues, childname, WsManURI, path, host);560 if (nodes != null)561 {562 return IsItemContainer(nodes);563 }564 }565 566 return false;567 }568 }569 570 /// <summary>571 /// This cmdlet is used to get a particular item.572 /// cd wsman:\localhost\client> Get-Item .\Auth.573 /// </summary>574 /// <param name="path"></param>575 [SuppressMessage("Microsoft.Maintainability", "CA1505:AvoidUnmaintainableCode")]576 protected override void GetItem(string path)577 {578 string childname = string.Empty;579 580 if (path.Length == 0 && string.IsNullOrEmpty(childname))581 {582 WriteItemObject(GetItemPSObjectWithTypeName(WSManStringLiterals.rootpath, WSManStringLiterals.ContainerChildValue, null, null, null, WsManElementObjectTypes.WSManConfigElement), WSManStringLiterals.rootpath, true);583 return;584 }585 586 if (path.Contains(WSManStringLiterals.DefaultPathSeparator.ToString()))587 {588 // Get the ChildName589 childname = path.Substring(path.LastIndexOf(WSManStringLiterals.DefaultPathSeparator) + 1);590 }591 else592 {593 childname = path;594 }595 596 Dictionary<string, object> SessionObjCache = WSManHelper.GetSessionObjCache();597 if (childname.Equals(path, StringComparison.OrdinalIgnoreCase))598 {599 if (SessionObjCache.ContainsKey(childname))600 {601 WriteItemObject(GetItemPSObjectWithTypeName(childname, WSManStringLiterals.ContainerChildValue, null, null, "ComputerLevel", WsManElementObjectTypes.WSManConfigContainerElement), WSManStringLiterals.rootpath + WSManStringLiterals.DefaultPathSeparator + childname, true);602 }603 604 return;605 }606 607 path = path.Substring(0, path.LastIndexOf(childname, StringComparison.OrdinalIgnoreCase));608 609 // Get the wsman host name to find the session object610 string host = GetHostName(path);611 string uri = NormalizePath(path, host);612 613 lock (WSManHelper.AutoSession)614 {615 // Gets the session object from the cache.616 object sessionobj;617 SessionObjCache.TryGetValue(host, out sessionobj);618 619 XmlDocument xmlResource = FindResourceValue(sessionobj, uri, null);620 if (xmlResource == null)621 {622 return;623 }624 625 // if endswith '\', removes it.626 if (path.EndsWith(WSManStringLiterals.DefaultPathSeparator.ToString(), StringComparison.OrdinalIgnoreCase))627 {628 path = path.Remove(path.LastIndexOf(WSManStringLiterals.DefaultPathSeparator));629 }630 631 string strPathChk = host + WSManStringLiterals.DefaultPathSeparator;632 633 if (path.Contains(strPathChk + WSManStringLiterals.containerListener))634 {635 GetItemListenerOrCertMapping(path, xmlResource, WSManStringLiterals.containerListener, childname, host);636 }637 else if (path.Contains(strPathChk + WSManStringLiterals.containerClientCertificate))638 {639 GetItemListenerOrCertMapping(path, xmlResource, WSManStringLiterals.containerClientCertificate, childname, host);640 }641 else if (path.Contains(strPathChk + WSManStringLiterals.containerPlugin))642 {643 string currentpluginname = string.Empty;644 GetPluginNames(xmlResource, out objPluginNames, out currentpluginname, path);645 646 if (path.EndsWith(strPathChk + WSManStringLiterals.containerPlugin, StringComparison.OrdinalIgnoreCase))647 {648 try649 {650 WriteItemObject(GetItemPSObjectWithTypeName(objPluginNames.Properties[childname].Name, objPluginNames.Properties[childname].Value.ToString(), null, new string[] { "Name=" + objPluginNames.Properties[childname].Name }, null, WsManElementObjectTypes.WSManConfigContainerElement), path + WSManStringLiterals.DefaultPathSeparator + childname, true);651 }652 catch (PSArgumentNullException) { return; }653 catch (NullReferenceException) { return; }654 }655 else656 {657 strPathChk = strPathChk + WSManStringLiterals.containerPlugin + WSManStringLiterals.DefaultPathSeparator;658 string filter = uri + "?Name=" + currentpluginname;659 XmlDocument CurrentPluginXML = GetResourceValue(sessionobj, filter, null);660 if (CurrentPluginXML == null)661 {662 return;663 }664 665 PSObject objPluginlevel = ProcessPluginConfigurationLevel(CurrentPluginXML, true);666 ArrayList arrSecurity = null;667 ArrayList arrResources = ProcessPluginResourceLevel(CurrentPluginXML, out arrSecurity);668 ArrayList arrInitParams = ProcessPluginInitParamLevel(CurrentPluginXML);669 try670 {671 if (path.Contains(strPathChk + currentpluginname))672 {673 if (path.EndsWith(strPathChk + currentpluginname, StringComparison.OrdinalIgnoreCase))674 {675 if (!objPluginlevel.Properties[childname].Value.ToString().Equals(WSManStringLiterals.ContainerChildValue))676 {677 WriteItemObject(GetItemPSObjectWithTypeName(objPluginlevel.Properties[childname].Name, objPluginlevel.Properties[childname].TypeNameOfValue, objPluginlevel.Properties[childname].Value, null, null, WsManElementObjectTypes.WSManConfigLeafElement), path + WSManStringLiterals.DefaultPathSeparator + objPluginlevel.Properties[childname].Name, false);678 }679 else680 {681 WriteItemObject(GetItemPSObjectWithTypeName(objPluginlevel.Properties[childname].Name, objPluginlevel.Properties[childname].Value.ToString(), null, null, null, WsManElementObjectTypes.WSManConfigLeafElement), path + WSManStringLiterals.DefaultPathSeparator + objPluginlevel.Properties[childname].Name, true);682 }683 }684 685 strPathChk = strPathChk + currentpluginname + WSManStringLiterals.DefaultPathSeparator;686 if (path.Contains(strPathChk + WSManStringLiterals.containerResources))687 {688 if (arrResources == null)689 {690 return;691 }692 693 if (path.EndsWith(strPathChk + WSManStringLiterals.containerResources, StringComparison.OrdinalIgnoreCase))694 {695 foreach (PSObject p in arrResources)696 {697 if (p.Properties["ResourceDir"].Value.ToString().Equals(childname))698 {699 WriteItemObject(GetItemPSObjectWithTypeName(childname, WSManStringLiterals.ContainerChildValue, null, new string[] { "ResourceURI=" + p.Properties["ResourceUri"].Value.ToString() }, null, WsManElementObjectTypes.WSManConfigContainerElement), path + WSManStringLiterals.DefaultPathSeparator + childname, true);700 }701 }702 703 return;704 }705 706 strPathChk = strPathChk + WSManStringLiterals.containerResources + WSManStringLiterals.DefaultPathSeparator;707 int Sepindex = path.IndexOf(WSManStringLiterals.DefaultPathSeparator, strPathChk.Length);708 string sResourceDirName = string.Empty;709 if (Sepindex == -1)710 {711 sResourceDirName = path.Substring(strPathChk.Length);712 }713 else714 {715 sResourceDirName = path.Substring(strPathChk.Length, path.IndexOf(WSManStringLiterals.DefaultPathSeparator, strPathChk.Length) - (strPathChk.Length));716 }717 718 if (path.Contains(strPathChk + sResourceDirName))719 {720 if (path.EndsWith(strPathChk + sResourceDirName, StringComparison.OrdinalIgnoreCase))721 {722 foreach (PSObject p in arrResources)723 {724 if (sResourceDirName.Equals(p.Properties["ResourceDir"].Value.ToString(), StringComparison.OrdinalIgnoreCase))725 {726 p.Properties.Remove("ResourceDir");727 if (p.Properties[childname].Value.ToString().Equals(WSManStringLiterals.ContainerChildValue))728 {729 WriteItemObject(GetItemPSObjectWithTypeName(p.Properties[childname].Name, p.Properties[childname].Value.ToString(), null, null, null, WsManElementObjectTypes.WSManConfigLeafElement), path + WSManStringLiterals.DefaultPathSeparator + p.Properties[childname].Name, true);730 }731 else732 {733 WriteItemObject(GetItemPSObjectWithTypeName(p.Properties[childname].Name, p.Properties[childname].TypeNameOfValue, p.Properties[childname].Value, null, null, WsManElementObjectTypes.WSManConfigLeafElement), path + WSManStringLiterals.DefaultPathSeparator + p.Properties[childname].Name, false);734 }735 736 break;737 }738 }739 740 return;741 }742 743 strPathChk = strPathChk + sResourceDirName + WSManStringLiterals.DefaultPathSeparator;744 if (path.Contains(strPathChk + WSManStringLiterals.containerSecurity))745 {746 if (arrSecurity == null)747 {748 return;749 }750 751 foreach (PSObject p in arrSecurity)752 {753 if (path.EndsWith(WSManStringLiterals.containerSecurity, StringComparison.OrdinalIgnoreCase))754 {755 WriteItemObject(GetItemPSObjectWithTypeName(p.Properties["SecurityDIR"].Value.ToString(), WSManStringLiterals.ContainerChildValue, null, new string[] { "Uri=" + p.Properties["Uri"].Value.ToString() }, null, WsManElementObjectTypes.WSManConfigContainerElement), path + WSManStringLiterals.DefaultPathSeparator + p.Properties["SecurityDIR"].Value.ToString(), true);756 }757 else758 {759 string sSecurityDirName = path.Substring(path.LastIndexOf(WSManStringLiterals.DefaultPathSeparator) + 1, path.Length - (path.LastIndexOf(WSManStringLiterals.DefaultPathSeparator) + 1));760 if (sSecurityDirName.Equals(p.Properties["SecurityDIR"].Value.ToString()))761 {762 p.Properties.Remove("SecurityDIR");763 WriteItemObject(GetItemPSObjectWithTypeName(p.Properties[childname].Name, p.Properties[childname].TypeNameOfValue, p.Properties[childname].Value, null, null, WsManElementObjectTypes.WSManConfigLeafElement), path + WSManStringLiterals.DefaultPathSeparator + p.Properties[childname].Name, false);764 break;765 }766 }767 }768 769 return;770 }771 }772 }773 else if (path.EndsWith(host + WSManStringLiterals.DefaultPathSeparator + WSManStringLiterals.containerPlugin + WSManStringLiterals.DefaultPathSeparator + currentpluginname + WSManStringLiterals.DefaultPathSeparator + WSManStringLiterals.containerInitParameters, StringComparison.OrdinalIgnoreCase))774 {775 if (arrInitParams != null)776 {777 foreach (PSObject p in arrInitParams)778 {779 if (p.Properties.Match(childname, PSMemberTypes.NoteProperty).Count > 0)780 WriteItemObject(GetItemPSObjectWithTypeName(p.Properties[childname].Name, p.Properties[childname].TypeNameOfValue, p.Properties[childname].Value, null, "InitParams", WsManElementObjectTypes.WSManConfigLeafElement), path + WSManStringLiterals.DefaultPathSeparator + p.Properties[childname].Name, false);781 }782 }783 }784 else if (path.EndsWith(WSManStringLiterals.containerQuotasParameters, StringComparison.OrdinalIgnoreCase))785 {786 // Get the Quotas element from the config XML.787 XmlNodeList nodeListForQuotas = CurrentPluginXML.GetElementsByTagName(WSManStringLiterals.containerQuotasParameters);788 if (nodeListForQuotas.Count > 0)789 {790 XmlNode pluginQuotas = nodeListForQuotas[0];791 foreach (XmlAttribute attrOfQuotas in pluginQuotas.Attributes)792 {793 if (childname.Equals(attrOfQuotas.Name, StringComparison.OrdinalIgnoreCase))794 {795 PSObject objectToAdd =796 GetItemPSObjectWithTypeName(797 attrOfQuotas.Name,798 attrOfQuotas.Value.GetType().ToString(),799 attrOfQuotas.Value,800 null,801 null,802 WsManElementObjectTypes.WSManConfigLeafElement);803 804 string pathToAdd =805 string.Format(806 CultureInfo.InvariantCulture,807 "{0}{1}{2}",808 path,809 WSManStringLiterals.DefaultPathSeparator,810 attrOfQuotas.Name);811 812 WriteItemObject(objectToAdd, pathToAdd, false);813 break;814 }815 }816 }817 }818 }819 }820 catch (PSArgumentNullException) { return; }821 catch (NullReferenceException) { return; }822 }823 }824 else825 {826 try827 {828 PSObject mshObject = null;829 if (!uri.Equals(WinrmRootName[0], StringComparison.OrdinalIgnoreCase))830 {831 foreach (XmlNode innerResourceNodes in xmlResource.ChildNodes)832 {833 mshObject = ConvertToPSObject(innerResourceNodes);834 }835 }836 else837 {838 mshObject = BuildHostLevelPSObjectArrayList(sessionobj, uri, false);839 }840 841 if (mshObject != null)842 {843 if (mshObject.Properties[childname].Value.ToString().Equals(WSManStringLiterals.ContainerChildValue))844 {845 WriteItemObject(GetItemPSObjectWithTypeName(mshObject.Properties[childname].Name, mshObject.Properties[childname].Value.ToString(), null, null, null, WsManElementObjectTypes.WSManConfigLeafElement), path + WSManStringLiterals.DefaultPathSeparator + mshObject.Properties[childname].Name, true);846 }847 else848 {849 WriteItemObject(850 GetItemPSObjectWithTypeName(851 mshObject.Properties[childname].Name,852 mshObject.Properties[childname].TypeNameOfValue,853 mshObject.Properties[childname].Value,854 null, null,855 WsManElementObjectTypes.WSManConfigLeafElement,856 mshObject),857 path + WSManStringLiterals.DefaultPathSeparator + mshObject.Properties[childname].Name,858 false);859 }860 }861 }862 catch (PSArgumentNullException) { return; /*Leaving this known exception for no value found. Not Throwing error.*/}863 catch (NullReferenceException) { return; /*Leaving this known exception for no value found. Not Throwing error.*/}864 }865 }866 }867 868 /// <summary>869 /// This cmdlet is used to set the value of a particular item.870 /// cd wsman:\localhost\client> Set-Item .\TrustedHosts -value "*"871 /// This has one dynamic parameter. It is used with TrustedHost only.872 /// The parameter is -Concatenate.873 /// </summary>874 /// <param name="path"></param>875 /// <param name="value"></param>876 [SuppressMessage("Microsoft.Maintainability", "CA1505:AvoidUnmaintainableCode")]877 protected override void SetItem(string path, object value)878 {879 if (value == null)880 {881 throw new ArgumentException(helper.GetResourceMsgFromResourcetext("value"));882 }883 884 string ChildName = string.Empty;885 886 if (path.Length == 0 && string.IsNullOrEmpty(ChildName))887 {888 AssertError(helper.GetResourceMsgFromResourcetext("SetItemNotSupported"), false);889 return;890 }891 892 if (path.Contains(WSManStringLiterals.DefaultPathSeparator.ToString()))893 {894 // Get the ChildName895 ChildName = path.Substring(path.LastIndexOf(WSManStringLiterals.DefaultPathSeparator) + 1);896 }897 else898 {899 ChildName = path;900 }901 902 if (ChildName.Equals(path, StringComparison.OrdinalIgnoreCase))903 {904 AssertError(helper.GetResourceMsgFromResourcetext("SetItemNotSupported"), false);905 return;906 }907 908 if (!this.clearItemIsCalled)909 {910 value = this.ValidateAndGetUserObject(ChildName, value);911 912 // The value will be Null only if the object provided by User is not of accepted type.913 // As of now, this can only happen in case of RunAsUserName and RunAsPassword914 if (value == null)915 {916 return;917 }918 }919 else920 {921 // If validation is not required, that means Clear-Item cmdlet is called.922 // Clear-Item is not allowed on RunAsPassword, Admin should call Clear-Item RunAsUser923 // if he intends to disable RunAs on the Plugin.924 if (string.Equals(ChildName, WSManStringLiterals.ConfigRunAsPasswordName, StringComparison.OrdinalIgnoreCase))925 {926 AssertError(helper.GetResourceMsgFromResourcetext("ClearItemOnRunAsPassword"), false);927 return;928 }929 }930 931 string whatIfMessage = string.Format(CultureInfo.CurrentUICulture, helper.GetResourceMsgFromResourcetext("SetItemWhatIfAndConfirmText"), path, value);932 if (!ShouldProcess(whatIfMessage, string.Empty, string.Empty))933 {934 return;935 }936 937 path = path.Substring(0, path.LastIndexOf(ChildName, StringComparison.OrdinalIgnoreCase));938 939 // Get the wsman host name to find the session object940 string host = GetHostName(path);941 string uri = NormalizePath(path, host);942 943 // Chk for Winrm Service944 if (IsPathLocalMachine(host))945 {946 if (!IsWSManServiceRunning())947 {948 WSManHelper.ThrowIfNotAdministrator();949 StartWSManService(this.Force);950 }951 }952 953 bool settingPickedUpDynamically = false;954 955 lock (WSManHelper.AutoSession)956 {957 // Gets the session object from the cache.958 object sessionobj;959 Dictionary<string, object> SessionObjCache = WSManHelper.GetSessionObjCache();960 SessionObjCache.TryGetValue(host, out sessionobj);961 962 List<string> warningMessage = new List<string>();963 964 // if endswith '\', removes it.965 if (path.EndsWith(WSManStringLiterals.DefaultPathSeparator.ToString(), StringComparison.OrdinalIgnoreCase))966 {967 path = path.Remove(path.LastIndexOf(WSManStringLiterals.DefaultPathSeparator));968 }969 970 string strPathChk = host + WSManStringLiterals.DefaultPathSeparator;971 if (path.Contains(strPathChk + WSManStringLiterals.containerListener))972 {973 SetItemListenerOrClientCertificate(sessionobj, uri, PKeyListener, ChildName, value, path, WSManStringLiterals.containerListener, host);974 }975 else if (path.Contains(strPathChk + WSManStringLiterals.containerClientCertificate))976 {977 SetItemListenerOrClientCertificate(sessionobj, uri, PKeyCertMapping, ChildName, value, path, WSManStringLiterals.containerClientCertificate, host);978 }979 else if (path.Contains(strPathChk + WSManStringLiterals.containerPlugin))980 {981 if (path.EndsWith(strPathChk + WSManStringLiterals.containerPlugin, StringComparison.OrdinalIgnoreCase))982 {983 AssertError(helper.GetResourceMsgFromResourcetext("SetItemNotSupported"), false);984 }985 986 try987 {988 XmlDocument xmlPlugins = FindResourceValue(sessionobj, uri, null);989 string currentpluginname = string.Empty;990 GetPluginNames(xmlPlugins, out objPluginNames, out currentpluginname, path);991 if (string.IsNullOrEmpty(currentpluginname))992 {993 if (!this.clearItemIsCalled)994 {995 // Don't need an error if ClearItem is called.996 AssertError(helper.GetResourceMsgFromResourcetext("ItemDoesNotExist"), false);997 }998 999 return;1000 }1001 1002 string filter = uri + "?Name=" + currentpluginname;1003 1004 CurrentConfigurations pluginConfiguration = new CurrentConfigurations((IWSManSession)sessionobj);1005 1006 string pluginXML = this.GetResourceValueInXml((IWSManSession)sessionobj, filter, null);1007 pluginConfiguration.RefreshCurrentConfiguration(pluginXML);1008 1009 XmlDocument CurrentPluginXML = pluginConfiguration.RootDocument;1010 1011 ArrayList arrSecurity = null;1012 ArrayList arrResources = ProcessPluginResourceLevel(CurrentPluginXML, out arrSecurity);1013 ArrayList arrInitParams = ProcessPluginInitParamLevel(CurrentPluginXML);1014 1015 try1016 {1017 // Remove XML:LANG attribute if present.1018 // If not present ignore the exception.1019 pluginConfiguration.RemoveOneConfiguration("./attribute::xml:lang");1020 }1021 catch (ArgumentException)1022 { }1023 1024 strPathChk = strPathChk + WSManStringLiterals.containerPlugin + WSManStringLiterals.DefaultPathSeparator;1025 if (path.EndsWith(strPathChk + currentpluginname, StringComparison.OrdinalIgnoreCase))1026 {1027 if (WSManStringLiterals.ConfigRunAsUserName.Equals(ChildName, StringComparison.OrdinalIgnoreCase) && value is PSCredential runAsCredentials)1028 {1029 // UserName1030 value = runAsCredentials.UserName;1031 1032 pluginConfiguration.UpdateOneConfiguration(1033 ".",1034 WSManStringLiterals.ConfigRunAsPasswordName,1035 GetStringFromSecureString(runAsCredentials.Password));1036 }1037 1038 if (WSManStringLiterals.ConfigRunAsPasswordName.Equals(ChildName, StringComparison.OrdinalIgnoreCase))1039 {1040 if (string.IsNullOrEmpty(1041 pluginConfiguration.GetOneConfiguration(1042 string.Format(1043 CultureInfo.InvariantCulture,1044 "./attribute::{0}",1045 WSManStringLiterals.ConfigRunAsUserName))))1046 {1047 // User Cannot set RunAsPassword if, RunAsUser is not present.1048 AssertError(helper.GetResourceMsgFromResourcetext("SetItemOnRunAsPasswordNoRunAsUser"), false);1049 }1050 1051 value = GetStringFromSecureString(value);1052 }1053 1054 pluginConfiguration.UpdateOneConfiguration(".", ChildName, value.ToString());1055 }1056 1057 strPathChk = strPathChk + currentpluginname + WSManStringLiterals.DefaultPathSeparator;1058 if (path.Contains(strPathChk + WSManStringLiterals.containerResources))1059 {1060 if (path.EndsWith(strPathChk + WSManStringLiterals.containerResources, StringComparison.OrdinalIgnoreCase))1061 {1062 AssertError(helper.GetResourceMsgFromResourcetext("SetItemNotSupported"), false);1063 return;1064 }1065 1066 strPathChk = strPathChk + WSManStringLiterals.containerResources + WSManStringLiterals.DefaultPathSeparator;1067 int Sepindex = path.IndexOf(WSManStringLiterals.DefaultPathSeparator, strPathChk.Length);1068 string sResourceDirName = string.Empty;1069 if (Sepindex == -1)1070 {1071 sResourceDirName = path.Substring(strPathChk.Length);1072 }1073 else1074 {1075 sResourceDirName = path.Substring(strPathChk.Length, path.IndexOf(WSManStringLiterals.DefaultPathSeparator, strPathChk.Length) - (strPathChk.Length));1076 }1077 1078 if (path.Contains(strPathChk + sResourceDirName))1079 {1080 if (path.EndsWith(strPathChk + sResourceDirName, StringComparison.OrdinalIgnoreCase))1081 {1082 if (arrResources == null)1083 {1084 return;1085 }1086 1087 if (ChildName.Equals(WSManStringLiterals.ConfigResourceUriName, StringComparison.OrdinalIgnoreCase))1088 {1089 AssertError(helper.GetResourceMsgFromResourcetext("NoChangeValue"), false);1090 return;1091 }1092 1093 foreach (PSObject p in arrResources)1094 {1095 if (sResourceDirName.Equals(p.Properties["ResourceDir"].Value.ToString(), StringComparison.OrdinalIgnoreCase))1096 {1097 string xpathToUse = string.Format(1098 CultureInfo.InvariantCulture,1099 "{0}:{1}/{0}:{2}[attribute::{3}='{4}']",1100 CurrentConfigurations.DefaultNameSpacePrefix,1101 WSManStringLiterals.containerResources,1102 WSManStringLiterals.containerSingleResource,1103 WSManStringLiterals.ConfigResourceUriName,1104 p.Properties[WSManStringLiterals.ConfigResourceUriName].Value.ToString());1105 1106 if (!p.Properties[ChildName].Value.ToString().Equals(WSManStringLiterals.ContainerChildValue))1107 {1108 // Allow Set-Item on non-container values only.1109 pluginConfiguration.UpdateOneConfiguration(xpathToUse, ChildName, value.ToString());1110 }1111 else1112 {1113 AssertError(helper.GetResourceMsgFromResourcetext("NoChangeValue"), false);1114 }1115 }1116 }1117 }1118 1119 strPathChk = strPathChk + sResourceDirName + WSManStringLiterals.DefaultPathSeparator;1120 if (path.Contains(strPathChk + WSManStringLiterals.containerSecurity))1121 {1122 if (path.EndsWith(strPathChk + WSManStringLiterals.containerSecurity, StringComparison.OrdinalIgnoreCase))1123 {1124 AssertError(helper.GetResourceMsgFromResourcetext("NoChangeValue"), false);1125 return;1126 }1127 1128 if (arrSecurity == null)1129 {1130 return;1131 }1132 1133 if (path.Contains(strPathChk + WSManStringLiterals.containerSecurity + WSManStringLiterals.DefaultPathSeparator + WSManStringLiterals.containerSecurity + "_"))1134 {1135 // Any setting inside security for plugin is picked up by service dynamically1136 settingPickedUpDynamically = true;1137 1138 foreach (PSObject p in arrSecurity)1139 {1140 string sSecurityDirName = path.Substring(path.LastIndexOf(WSManStringLiterals.DefaultPathSeparator) + 1, path.Length - (path.LastIndexOf(WSManStringLiterals.DefaultPathSeparator) + 1));1141 if (sSecurityDirName.Equals(p.Properties["SecurityDIR"].Value.ToString(), StringComparison.OrdinalIgnoreCase))1142 {1143 if (!Force)1144 {1145 string query = helper.GetResourceMsgFromResourcetext("ShouldContinueSecurityQuery");1146 query = string.Format(CultureInfo.CurrentCulture, query, currentpluginname);1147 if (!ShouldContinue(query, helper.GetResourceMsgFromResourcetext("ShouldContinueSecurityCaption")))1148 {1149 return;1150 }1151 }1152 1153 // NameSpace:Resources/NameSpace:Resource[@ResourceUri={''}]/NameSpace:Security[@Uri='{2}']1154 string xpathToUse = string.Format(1155 CultureInfo.InvariantCulture,1156 "{0}:{1}/{0}:{2}[@{6}='{7}']/{0}:{3}[@{4}='{5}']",1157 CurrentConfigurations.DefaultNameSpacePrefix,1158 WSManStringLiterals.containerResources,1159 WSManStringLiterals.containerSingleResource,1160 WSManStringLiterals.containerSecurity,1161 WSManStringLiterals.ConfigSecurityUri,1162 p.Properties[WSManStringLiterals.ConfigSecurityUri].Value.ToString(),1163 WSManStringLiterals.ConfigResourceUriName,1164 p.Properties["ParentResourceUri"].Value.ToString());1165 1166 pluginConfiguration.UpdateOneConfiguration(xpathToUse, ChildName, value.ToString());1167 }1168 }1169 }1170 }1171 }1172 }1173 else if (path.EndsWith(strPathChk + WSManStringLiterals.containerInitParameters, StringComparison.OrdinalIgnoreCase))1174 {1175 foreach (PSObject p in arrInitParams)1176 {1177 if (p.Properties[ChildName] != null)1178 {1179 string xpathToUse = string.Format(1180 CultureInfo.InvariantCulture,1181 "{0}:{1}/{0}:{2}[@{3}='{4}']",1182 CurrentConfigurations.DefaultNameSpacePrefix,1183 WSManStringLiterals.containerInitParameters,1184 WSManStringLiterals.ConfigInitializeParameterTag,1185 WSManStringLiterals.ConfigInitializeParameterName,1186 p.Properties[ChildName].Name);1187 1188 pluginConfiguration.UpdateOneConfiguration(xpathToUse, WSManStringLiterals.ConfigInitializeParameterValue, value.ToString());1189 1190 break;1191 }1192 }1193 }1194 else if (path.EndsWith(strPathChk + WSManStringLiterals.containerQuotasParameters, StringComparison.OrdinalIgnoreCase))1195 {1196 string xpathToUse = string.Format(1197 CultureInfo.InvariantCulture,1198 "{0}:{1}",1199 CurrentConfigurations.DefaultNameSpacePrefix,1200 WSManStringLiterals.containerQuotasParameters);