MegaBites-AI/Windows-powershell
0372
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System;5using System.Collections.Generic;6using System.Diagnostics.CodeAnalysis;7using System.Diagnostics.Eventing;8using System.Diagnostics.Eventing.Reader;9using System.Globalization;10using System.IO;11using System.Management.Automation;12using System.Resources;13using System.Xml;14 15namespace Microsoft.PowerShell.Commands16{17 /// <summary>18 /// Class that implements the New-WinEvent cmdlet.19 /// This cmdlet writes a new Etw event using the provider specified in parameter.20 /// </summary>21 [Cmdlet(VerbsCommon.New, "WinEvent", HelpUri = "https://go.microsoft.com/fwlink/?LinkID=2096808")]22 public sealed class NewWinEventCommand : PSCmdlet23 {24 private ProviderMetadata _providerMetadata;25 private EventDescriptor? _eventDescriptor;26 27 private const string TemplateTag = "template";28 private const string DataTag = "data";29 30 private readonly ResourceManager _resourceMgr = Microsoft.PowerShell.Commands.Diagnostics.Common.CommonUtilities.GetResourceManager();31 32 /// <summary>33 /// ProviderName.34 /// </summary>35 [Parameter(36 Position = 0,37 Mandatory = true,38 ParameterSetName = ParameterAttribute.AllParameterSets)]39 public string ProviderName { get; set; }40 41 /// <summary>42 /// Id (EventId defined in manifest file)43 /// </summary>44 [Parameter(45 Position = 1,46 Mandatory = true,47 ParameterSetName = ParameterAttribute.AllParameterSets)]48 public int Id49 {50 get51 {52 return _id;53 }54 55 set56 {57 _id = value;58 _idSpecified = true;59 }60 }61 62 private int _id;63 private bool _idSpecified = false;64 65 /// <summary>66 /// Version (event version)67 /// </summary>68 [Parameter(69 Mandatory = false,70 ParameterSetName = ParameterAttribute.AllParameterSets)]71 public byte Version72 {73 get74 {75 return _version;76 }77 78 set79 {80 _version = value;81 _versionSpecified = true;82 }83 }84 85 private byte _version;86 private bool _versionSpecified = false;87 88 /// <summary>89 /// Event Payload.90 /// </summary>91 [Parameter(92 Position = 2,93 Mandatory = false,94 ParameterSetName = ParameterAttribute.AllParameterSets),95 AllowEmptyCollection,96 SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays",97 Target = "Microsoft.PowerShell.Commands",98 Justification = "A string[] is required here because that is the type Powershell supports")]99 public object[] Payload { get; set; }100 101 /// <summary>102 /// BeginProcessing.103 /// </summary>104 protected override void BeginProcessing()105 {106 LoadProvider();107 LoadEventDescriptor();108 109 base.BeginProcessing();110 }111 112 private void LoadProvider()113 {114 if (string.IsNullOrEmpty(ProviderName))115 {116 throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, _resourceMgr.GetString("ProviderNotSpecified")), "ProviderName");117 }118 119 using (EventLogSession session = new())120 {121 foreach (string providerName in session.GetProviderNames())122 {123 if (string.Equals(providerName, ProviderName, StringComparison.OrdinalIgnoreCase))124 {125 try126 {127 _providerMetadata = new ProviderMetadata(providerName);128 }129 catch (EventLogException exc)130 {131 string msg = string.Format(CultureInfo.InvariantCulture, _resourceMgr.GetString("ProviderMetadataUnavailable"), providerName, exc.Message);132 throw new Exception(msg, exc);133 }134 135 break;136 }137 }138 }139 140 if (_providerMetadata == null)141 {142 string msg = string.Format(CultureInfo.InvariantCulture, _resourceMgr.GetString("NoProviderFound"), ProviderName);143 throw new ArgumentException(msg);144 }145 }146 147 private void LoadEventDescriptor()148 {149 if (_idSpecified)150 {151 List<EventMetadata> matchedEvents = new();152 foreach (EventMetadata emd in _providerMetadata.Events)153 {154 if (emd.Id == _id)155 {156 matchedEvents.Add(emd);157 }158 }159 160 if (matchedEvents.Count == 0)161 {162 string msg = string.Format(CultureInfo.InvariantCulture,163 _resourceMgr.GetString("IncorrectEventId"),164 _id,165 ProviderName);166 throw new EventWriteException(msg);167 }168 169 EventMetadata matchedEvent = null;170 if (!_versionSpecified && matchedEvents.Count == 1)171 {172 matchedEvent = matchedEvents[0];173 }174 else175 {176 if (_versionSpecified)177 {178 foreach (EventMetadata emd in matchedEvents)179 {180 if (emd.Version == _version)181 {182 matchedEvent = emd;183 break;184 }185 }186 187 if (matchedEvent == null)188 {189 string msg = string.Format(CultureInfo.InvariantCulture,190 _resourceMgr.GetString("IncorrectEventVersion"),191 _version,192 _id,193 ProviderName);194 195 throw new EventWriteException(msg);196 }197 }198 else199 {200 string msg = string.Format(CultureInfo.InvariantCulture,201 _resourceMgr.GetString("VersionNotSpecified"),202 _id,203 ProviderName);204 205 throw new EventWriteException(msg);206 }207 }208 209 VerifyTemplate(matchedEvent);210 _eventDescriptor = CreateEventDescriptor(_providerMetadata, matchedEvent);211 }212 else213 {214 throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, _resourceMgr.GetString("EventIdNotSpecified")), "Id");215 }216 }217 218 private bool VerifyTemplate(EventMetadata emd)219 {220 if (emd.Template != null)221 {222 XmlReaderSettings readerSettings = new()223 {224 CheckCharacters = false,225 IgnoreComments = true,226 IgnoreProcessingInstructions = true,227 MaxCharactersInDocument = 0, // no limit228 ConformanceLevel = ConformanceLevel.Fragment,229 XmlResolver = null230 };231 232 int definedParameterCount = 0;233 using (XmlReader reader = XmlReader.Create(new StringReader(emd.Template), readerSettings))234 {235 if (reader.ReadToFollowing(TemplateTag))236 {237 bool found = reader.ReadToDescendant(DataTag);238 while (found)239 {240 definedParameterCount++;241 found = reader.ReadToFollowing(DataTag);242 }243 }244 }245 246 if ((Payload == null && definedParameterCount != 0)247 || ((Payload != null) && Payload.Length != definedParameterCount))248 {249 string warning = string.Format(CultureInfo.InvariantCulture, _resourceMgr.GetString("PayloadMismatch"), _id, emd.Template);250 WriteWarning(warning);251 252 return false;253 }254 }255 256 return true;257 }258 259 private static EventDescriptor CreateEventDescriptor(ProviderMetadata providerMetaData, EventMetadata emd)260 {261 long keywords = 0;262 foreach (EventKeyword keyword in emd.Keywords)263 {264 keywords |= keyword.Value;265 }266 267 byte channel = 0;268 foreach (EventLogLink logLink in providerMetaData.LogLinks)269 {270 if (string.Equals(logLink.LogName, emd.LogLink.LogName, StringComparison.OrdinalIgnoreCase))271 break;272 channel++;273 }274 275 return new EventDescriptor(276 (int)emd.Id,277 emd.Version,278 channel,279 (byte)emd.Level.Value,280 (byte)emd.Opcode.Value,281 emd.Task.Value,282 keywords);283 }284 285 /// <summary>286 /// ProcessRecord.287 /// </summary>288 protected override void ProcessRecord()289 {290 using (EventProvider provider = new(_providerMetadata.Id))291 {292 EventDescriptor ed = _eventDescriptor.Value;293 294 if (Payload != null && Payload.Length > 0)295 {296 for (int i = 0; i < Payload.Length; i++)297 {298 if (Payload[i] == null)299 {300 Payload[i] = string.Empty;301 }302 }303 304 provider.WriteEvent(in ed, Payload);305 }306 else307 {308 provider.WriteEvent(in ed);309 }310 }311 312 base.ProcessRecord();313 }314 315 /// <summary>316 /// EndProcessing.317 /// </summary>318 protected override void EndProcessing()319 {320 _providerMetadata?.Dispose();321 322 base.EndProcessing();323 }324 }325 326 internal sealed class EventWriteException : Exception327 {328 internal EventWriteException(string msg, Exception innerException)329 : base(msg, innerException)330 { }331 332 internal EventWriteException(string msg)333 : base(msg)334 { }335 }336}337 