diff --git a/src/powershell-native/map.json b/src/powershell-native/map.json index 8a19f017e8..1ab477129e 100644 --- a/src/powershell-native/map.json +++ b/src/powershell-native/map.json @@ -20,5 +20,12 @@ "monad/nttargets/assemblies/nativemsh/pwrshplugin/pwrshheaders.h": "nativemsh/pwrshplugin/pwrshheaders.h", "monad/nttargets/assemblies/nativemsh/pwrshplugin/pwrshplugin.h": "nativemsh/pwrshplugin/pwrshplugin.h", "monad/nttargets/assemblies/nativemsh/pwrshplugin/pwrshplugindefs.h": "nativemsh/pwrshplugin/pwrshplugindefs.h", - "monad/nttargets/assemblies/nativemsh/pwrshplugin/pwrshplugin.def": "nativemsh/pwrshplugin/pwrshplugin.def" + "monad/nttargets/assemblies/nativemsh/pwrshplugin/pwrshplugin.def": "nativemsh/pwrshplugin/pwrshplugin.def", + "monad/nttargets/assemblies/nativemsh/pwrshexe/CssMainEntry.cpp": "nativemsh/pwrshexe/CssMainEntry.cpp", + "monad/nttargets/assemblies/nativemsh/pwrshexe/Monad.ico": "nativemsh/pwrshexe/Monad.ico", + "monad/nttargets/assemblies/nativemsh/pwrshexe/MshResources.rc": "nativemsh/pwrshexe/MshResources.rc", + "monad/nttargets/assemblies/nativemsh/pwrshexe/nativemsh.mc": "nativemsh/pwrshexe/NativeMsh.mc", + "monad/nttargets/assemblies/nativemsh/pwrshexe/PowerShell.exe.manifest": "nativemsh/pwrshexe/PowerShell.exe.manifest", + "monad/nttargets/assemblies/nativemsh/pwrshexe/PowerShell_securitybadge.ico": "nativemsh/pwrshexe/PowerShell_securitybadge.ico", + "monad/nttargets/assemblies/nativemsh/pwrshexe/version.rc": "nativemsh/pwrshexe/version.rc" } diff --git a/src/powershell-native/nativemsh/pwrshexe/CssMainEntry.cpp b/src/powershell-native/nativemsh/pwrshexe/CssMainEntry.cpp new file mode 100644 index 0000000000..038ca0299b --- /dev/null +++ b/src/powershell-native/nativemsh/pwrshexe/CssMainEntry.cpp @@ -0,0 +1,267 @@ +// ---------------------------------------------------------------------- +// +// Microsoft Windows NT +// Copyright (C) Microsoft Corporation, 2005. +// +// File: CoreCLRHost.cpp +// +// Contents: Unmanaged startup point for powershell.exe console app. +// +// ---------------------------------------------------------------------- + +#include +#include +#include +#include "mscoree.h" +#include "NativeMsh.h" +#include "ClrHostWrapper.h" +#include "OutputWriter.h" +#include "WinSystemCallFacade.h" + +namespace NativeMsh +{ + // Define the function pointer for the powershell entry point. + typedef int (STDMETHODCALLTYPE *MonadRunHelperFp)(LPCWSTR consoleFilePath, LPCWSTR * args, int argc); // int UnmanagedPSEntry.Start(string consoleFilePath, string[] args, int argc) + + // Define the function pointer for AssemblyLoadContext initializer. + typedef void (STDMETHODCALLTYPE *LoaderRunHelperFp)(LPCWSTR appPath); + + bool TryRun(const int argc, const wchar_t* argv[], HostEnvironment &hostEnvironment, int &exitCode, bool verbose) + { + // Assume failure + exitCode = -1; + + // All these objects will be destroyed when commonFuncs goes out of scope. + PwrshExeOutput* output = new PwrshExeOutput(); + PwrshCommon commonFuncs(output, new WinSystemCallFacade()); + ICLRRuntimeHost2Wrapper hostWrapper; + + exitCode = commonFuncs.LaunchCoreCLR(&hostWrapper, hostEnvironment); + if (EXIT_CODE_SUCCESS != exitCode) + { + if (verbose) + ::wprintf(L"Unable to launch CoreCLR\n"); + return false; + } + + if (!hostWrapper.IsInitialized()) // TODO: redundant? + { + if (verbose) + ::wprintf(L"Unable to initialize CoreCLR\n"); + return false; + } + + exitCode = commonFuncs.CreateAppDomain(&hostWrapper, hostEnvironment.GetHostBinaryName(), hostEnvironment); + if (EXIT_CODE_SUCCESS != exitCode) + { + if (verbose) + ::wprintf(L"Unable to create app domain\n"); + return false; + } + + //------------------------------------------------------------- + // Set the powershell custom assembly loader to be the default + LoaderRunHelperFp initDelegate = NULL; + HRESULT hr = hostWrapper.CreateDelegate( + hostWrapper.GetAppDomainId(), + L"Microsoft.PowerShell.CoreCLR.AssemblyLoadContext, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35", + L"System.Management.Automation.PowerShellAssemblyLoadContextInitializer", + L"SetPowerShellAssemblyLoadContext", + (INT_PTR*)&initDelegate); + + if (FAILED(hr)) + { + output->DisplayMessage(false, g_CREATING_MSH_ENTRANCE_FAILED, hr); + } + else + { + initDelegate(hostEnvironment.GetHostDirectoryPath()); + } + + //------------------------------------------------------------- + // Start the assembly + MonadRunHelperFp pfnDelegate = NULL; + hr = hostWrapper.CreateDelegate( + hostWrapper.GetAppDomainId(), + L"Microsoft.PowerShell.ConsoleHost, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35", + L"Microsoft.PowerShell.UnmanagedPSEntry", + L"Start", + (INT_PTR*)&pfnDelegate); + + if (FAILED(hr)) + { + output->DisplayMessage(false, g_CREATING_MSH_ENTRANCE_FAILED, hr); + } + else + { + exitCode = pfnDelegate(NULL, &argv[0], argc); + } + + // Unload the AppDomain + if (verbose) + ::wprintf(L"Unloading the AppDomain\n"); + + int utilExitCode = hostWrapper.CleanUpHostWrapper(); + if (EXIT_CODE_SUCCESS != utilExitCode) + { + if (verbose) + { + if (g_UNLOAD_APPDOMAIN_FAILED == utilExitCode) + { + // TODO: If we want localization, these must be added to nativemsh.mc + ::wprintf(L"Failed to unload the AppDomain. ERRORCODE: %u\n", utilExitCode); + } + else if (g_STOP_CLR_HOST_FAILED == utilExitCode) + { + ::wprintf(L"Failed to stop the host. ERRORCODE: %u\n", utilExitCode); + } + else if (g_RELEASE_CLR_HOST_FAILED == utilExitCode) + { + ::wprintf(L"Failed to release the host.ERRORCODE: %u\n", utilExitCode); + } + } + return false; + } + + return true; + } + + void showHelp() { + static PCWSTR coreCLRInstallDirectory = L"%windir%\\system32\\DotNetCore\\v1.0\\"; + ::wprintf( + L"USAGE: powershell [-Verbose] [-Debug] [-File ] [-Command] \r\n" + L"\r\n" + L" CoreCLR is searched for in the directory that powershell.exe is in,\r\n" + L" then in %s.\r\n", + coreCLRInstallDirectory + ); + } + +} // namespace NativeMsh + +int __cdecl wmain(const int argc, const wchar_t* argv[]) +{ + // Parse the options from the command line + const wchar_t *verboseParameter = L"-Verbose"; + const wchar_t *debugParameter = L"-Debug"; + + const wchar_t *versionParameter = L"-Version"; + const wchar_t *psConsoleFileParameter = L"-PSConsoleFile"; + const wchar_t *runtimeVersionParameter = L"-RuntimeVersion"; + + bool verbose = false; + bool debug = false; + bool helpRequested = false; + + bool versionSpecified = false; + bool psConsoleFileSpecified = false; + bool runtimeVersionSpecified = false; + + + int newArgc = argc - 1; + const wchar_t **newArgv = argv + 1; + + auto stringsMatch = [](const wchar_t * const userInput, const wchar_t * const parameter) -> bool { + size_t userInputLength = ::wcslen(userInput); + size_t parameterLength = ::wcslen(parameter); + + // If the user input is longer than the parameter, they cannot be matched. + if (userInputLength > parameterLength) { + return false; + } + + // Return true if the user input is a prefix of the parameter + return ::_wcsnicmp(userInput, parameter, userInputLength) == 0; + }; + + auto stringsEqual = [](const wchar_t * const a, const wchar_t * const b) -> bool { + return ::_wcsicmp(a, b) == 0; + }; + + // These parameters are considered 'native only' - they should NOT be passed to managed layer + auto skipParameter = [&](const wchar_t * arg) -> bool { + if (stringsMatch(arg, verboseParameter)) { + verbose = true; + } + else if (stringsEqual(arg, L"/?") || stringsEqual(arg, L"-?")) { + helpRequested = true; + } + else if (stringsMatch(arg, debugParameter)) + { + debug = true; + } + else if (stringsEqual(arg, versionParameter)) + { + versionSpecified = true; + } + else if (stringsMatch(arg, psConsoleFileParameter)) + { + psConsoleFileSpecified = true; + } + else if (stringsMatch(arg, runtimeVersionParameter)) { + runtimeVersionSpecified = true; + } + else { + return false; + } + + return true; + }; + + // Find the last 'native' parameter, and chomp everything up until it. + while (newArgc > 0 && skipParameter(newArgv[0])) + { + newArgc--; + newArgv++; + + if (versionSpecified) { + // skip the next arg if there is one + versionSpecified = false; + if (newArgc > 0) { + newArgc--; + newArgv++; + } + } + + if (psConsoleFileSpecified) { + // skip the next arg if there is one + psConsoleFileSpecified = false; + if (newArgc > 0) { + newArgc--; + newArgv++; + } + } + + if (runtimeVersionSpecified) { + // skip the next arg if there is one + runtimeVersionSpecified = false; + if (newArgc > 0) { + newArgc--; + newArgv++; + } + } + } + + if (debug) + { + ::wprintf(L" Attach the debugger to powershell.exe and press any key to continue\n"); + ::getchar(); + } + + if (helpRequested) + { + NativeMsh::showHelp(); + return -1; + } + else + { + int exitCode; + NativeMsh::HostEnvironment hostEnvironment; + + auto success = TryRun(newArgc, newArgv, hostEnvironment, exitCode, verbose); + + if (verbose) + ::wprintf(L"Execution %s\n", (success ? L"succeeded" : L"failed")); + return exitCode; + } +} diff --git a/src/powershell-native/nativemsh/pwrshexe/Monad.ico b/src/powershell-native/nativemsh/pwrshexe/Monad.ico new file mode 100644 index 0000000000..b3285f9678 Binary files /dev/null and b/src/powershell-native/nativemsh/pwrshexe/Monad.ico differ diff --git a/src/powershell-native/nativemsh/pwrshexe/MshResources.rc b/src/powershell-native/nativemsh/pwrshexe/MshResources.rc new file mode 100644 index 0000000000..7180af2633 --- /dev/null +++ b/src/powershell-native/nativemsh/pwrshexe/MshResources.rc @@ -0,0 +1,46 @@ +// Copyright (C) 2005 Microsoft Corporation +// +// resource script for msh.exe +// + +#include + +#define MANIFEST_RESOURCE_ID 1 + +MANIFEST_RESOURCE_ID RT_MANIFEST "powershell.exe.manifest" +MSH_MAIN ICON "monad.ico" +MSH_SECURITY ICON "powershell_securitybadge.ico" + +STRINGTABLE DISCARDABLE +BEGIN + + // Elements of our jump list, and file descriptions, and LNK + // descriptions + 101 "Windows PowerShell ISE" + 102 "Windows PowerShell ISE (x86)" + 103 "Windows PowerShell Script" + 104 "Windows PowerShell Data File" + 105 "Windows PowerShell XML Document" + 106 "Windows PowerShell Script Module" + 107 "Windows PowerShell Console File" + 108 "Run with PowerShell" + 109 "Windows PowerShell" + 110 "Windows PowerShell (x86)" + 111 "Performs object-based (command-line) functions" + 112 "Run as 32" + 113 "Windows PowerShell Integrated Scripting Environment. Performs object-based (command-line) functions" + 118 "Run as Administrator" + 119 "Runs with administrator privileges" + 120 "Windows PowerShell Cmdlet Definition XML Document" + 121 "Windows PowerShell Session Configuration File" + 122 "Run ISE as Administrator" + 123 "Runs ISE with administrator privileges" + + // Misc resources + + // Friendly name for our OID mapping + 124 "Document Encryption" +END + +#include "nativemsh.rc" +#include "version.rc" diff --git a/src/powershell-native/nativemsh/pwrshexe/NativeMsh.mc b/src/powershell-native/nativemsh/pwrshexe/NativeMsh.mc new file mode 100644 index 0000000000..3ff1a74938 --- /dev/null +++ b/src/powershell-native/nativemsh/pwrshexe/NativeMsh.mc @@ -0,0 +1,235 @@ +;// Copyright (C) Microsoft Corporation, 2000 - 2002 + +MessageId=1 +SymbolicName=MISSING_COMMAND_LINE_ARGUMENT +Language=English +Missing argument for parameter %1!ls!. +. + +MessageId=2 +SymbolicName=INVALID_CONSOLE_FILE_PATH +Language=English +Windows PowerShell console file path "%1!ls!" is invalid. +. + +MessageId=3 +SymbolicName=CLR_VERSION_NOT_INSTALLED +Language=English +Version %1!ls! of the .NET Framework is not installed and it is required to run version %2!ls! of Windows PowerShell. +. + +MessageId=4 +SymbolicName=CORBINDTORUNTIME_FAILED +Language=English +CLR initialization failed with error %1!lx!. +. + +MessageId=5 +SymbolicName=STARTING_CLR_FAILED +Language=English +Starting the CLR failed with HRESULT %1!lx!. +. + +MessageId=6 +SymbolicName=GETTING_DEFAULT_DOMAIN_FAILED +Language=English +Internal Windows PowerShell error. Default CLR domain initialization failed with error %1!lx!. +. + +MessageId=7 +SymbolicName=CREATING_MSH_ENTRANCE_FAILED +Language=English +Internal Windows PowerShell error. Loading managed Windows PowerShell failed with error %1!lx!. +. + +MessageId=8 +SymbolicName=GETTING_DISPATCH_ID_FAILED +Language=English +Internal Windows PowerShell error. Retrieving Dispatch ID for managed Windows PowerShell entrance method failed with error %1!lx!. +. + +MessageId=9 +SymbolicName=INOVKING_MSH_ENTRANCE_FAILED +Language=English +Internal Windows PowerShell error. Invoking managed Windows PowerShell failed with error %1!lx!. +. + +MessageId=10 +SymbolicName=MANAGED_MSH_EXCEPTION +Language=English +Windows PowerShell terminated with the following error: %n %1!ls! +. + +MessageId=11 +SymbolicName=READ_XML_COM_INIT_FAILED +Language=English +Internal Windows PowerShell error. COM initialization failed while reading Windows PowerShell console file with error %1!lx!. +. + +MessageId=12 +SymbolicName=READ_XML_CREATE_DOMDOCUMENT_FAILED +Language=English +Internal Windows PowerShell error. DOMDocument creation for Windows PowerShell console file failed with error %1!lx!. +. + +MessageId=13 +SymbolicName=READ_XML_LOAD_FILE_FAILED +Language=English +Failed to load Windows PowerShell console file "%1!ls!". +. + +MessageId=14 +SymbolicName=EMPTY_REG_SZ_VALUE +Language=English +The value of the registry key %1!ls!\%2!ls! cannot be empty. +. + +MessageId=15 +SymbolicName=READ_XML_GET_CONSOLE_SCHEMA_VERSION_FAILED +Language=English +Cannot locate the required element ConsoleSchemaVersion in the Windows PowerShell console file "%1!ls!". +. + +MessageId=16 +SymbolicName=READ_XML_INVALID_CONSOLE_SCHEMA_VERSION +Language=English +A required element ConsoleSchemaVersion in Windows PowerShell console file "%1!ls!" is invalid. +. + +MessageId=17 +SymbolicName=INVALID_MONAD_VERSION +Language=English +"%1!ls!" is not a valid Windows PowerShell version. Specify a valid Windows PowerShell version of the format major.minor version. +. + +MessageId=18 +SymbolicName=READ_XML_GET_MONAD_VERSION_TEXT_FAILED +Language=English +Cannot read the Windows PowerShell version from Windows PowerShell console file "%1!ls!". +. + +MessageId=19 +SymbolicName=SEARCH_LATEST_REG_KEY_FAILED_WITH +Language=English +Encountered a problem reading the registry. Cannot read registry key %1!ls!. System error:%n %2!ls!. +. + +MessageId=20 +SymbolicName=OPEN_REG_KEY_FAILED_WITH +Language=English +Encountered a problem reading the registry. Cannot open registry key %1!ls!. System error:%n %2!ls!. +. + +MessageId=21 +SymbolicName=CLOSE_REG_KEY_FAILED_WITH +Language=English +Closing registry key %1!ls! causes the following Win32 error:%n %2!ls! +. + +MessageId=22 +SymbolicName=READ_REG_VALUE_FAILED_WITH +Language=English +Reading the value of registry key %1!ls!\%2!ls! causes the following Win32 error:%n %3!ls! +. + +MessageId=23 +SymbolicName=CREATE_MSHENGINE_REG_KEY_PATH_FAILED_WITH +Language=English +Encountered a problem creating the registry key path PowerShellEngine. System error:%n %1!ls!. +. + +MessageId=24 +SymbolicName=EXPECT_REG_SZ_VALUE +Language=English +Invalid registry key value. Value for registry key %1!ls!\%2!ls! must be REG_SZ. +. + +MessageId=25 +SymbolicName=MSH_VERSION_NOT_INSTALLED +Language=English +Cannot start Windows PowerShell version %1!ls! because it is not installed. +. + +MessageId=26 +SymbolicName=INCORRECT_CONSOLE_FILE_EXTENSION +Language=English +Windows PowerShell console file "%1!ls!" extension is not psc1. Windows PowerShell console file extension must be psc1. +. + +MessageId=27 +SymbolicName=INVALID_REG_MSHVERSION_VALUE +Language=English +The value of registry key %1!ls!\%2!ls! is an invalid .NET version. Valid version format is major.minor.build.revision. +. + +MessageId=28 +SymbolicName=INCOMPATIBLE_MINOR_VERSION +Language=English +Cannot start Windows PowerShell. No version of Windows PowerShell compatible to %1!ls! is installed. +. + +MessageId=29 +SymbolicName=NO_COMPLETELY_INSTALLED_FOUND_VERSION +Language=English +Cannot start Windows PowerShell. No correctly installed versions of Windows PowerShell found. +. + +MessageId=30 +SymbolicName=MISSING_REG_KEY +Language=English +Encountered a problem reading the registry. Cannot find registry key %1!ls!. +. + +MessageId=31 +SymbolicName=READ_XML_LOAD_FILE_FAILED_WITH_SPECIFIC_ERROR +Language=English +Failed to load Windows PowerShell console file "%1!ls!". WIN 32 error: %2!ls! +. + +MessageId=32 +SymbolicName=READ_XML_LOAD_FILE_FAILED_WITH_SPECIFIC_POSITION_ERROR +Language=English +Failed to load Windows PowerShell console file "%1!ls!": %2!ls!At line:%3!li! char:%4!li! +. + +MessageId=33 +SymbolicName=READ_XML_GET_EMPTY_MONAD_VERSION_TEXT +Language=English +Windows PowerShell version in the Windows PowerShell console file "%1!ls!" cannot be empty. +. + +MessageId=34 +SymbolicName=READ_XML_GET_PSCONSOLEFILE_FAILED +Language=English +Cannot locate the required element PSConsoleFile in the Windows PowerShell console file "%1!ls!". +. + +MessageId=35 +SymbolicName=NOTSUPPORTED_MONAD_VERSION +Language=English +The requested Windows PowerShell version %1!d! is not supported on WinPE. WinPE supports only Windows PowerShell %1!d!. +. + +MessageId=36 +SymbolicName=NONSTANDARD_CLR_VERSION +Language=English +Warning: Windows PowerShell was started with CLR version "%1!ls!". This CLR version has not been tested with Windows PowerShell and might not operate properly. For more information about supported versions of the CLR, see http://go.microsoft.com/fwlink/?LinkId=215538.%r%n +. + +MessageId=37 +SymbolicName=SHELLBANNER1 +Language=English +Windows PowerShell +. + +MessageId=38 +SymbolicName=SHELLBANNER2 +Language=English +Copyright (C) 2015 Microsoft Corporation. All rights reserved. +. + +MessageId=39 +SymbolicName=MISSING_REG_KEY1 +Language=English +Encountered a problem reading the registry. Cannot find registry key %1!ls!. The Windows PowerShell %2!ls! engine is not installed on this computer. +. diff --git a/src/powershell-native/nativemsh/pwrshexe/PowerShell.exe.manifest b/src/powershell-native/nativemsh/pwrshexe/PowerShell.exe.manifest new file mode 100644 index 0000000000..782c9bfaab --- /dev/null +++ b/src/powershell-native/nativemsh/pwrshexe/PowerShell.exe.manifest @@ -0,0 +1,36 @@ + + + PowerShell + + + + + + + + + + + + + + + + + + + + + + + + true + + + diff --git a/src/powershell-native/nativemsh/pwrshexe/PowerShell_securitybadge.ico b/src/powershell-native/nativemsh/pwrshexe/PowerShell_securitybadge.ico new file mode 100644 index 0000000000..0aa11972d8 Binary files /dev/null and b/src/powershell-native/nativemsh/pwrshexe/PowerShell_securitybadge.ico differ diff --git a/src/powershell-native/nativemsh/pwrshexe/version.rc b/src/powershell-native/nativemsh/pwrshexe/version.rc new file mode 100644 index 0000000000..071f08b7cf --- /dev/null +++ b/src/powershell-native/nativemsh/pwrshexe/version.rc @@ -0,0 +1,13 @@ +// +// Copyright (C) Microsoft. All rights reserved. +// +#include +#include + +#define VER_FILETYPE VFT_APP +#define VER_FILESUBTYPE VFT2_UNKNOWN +#define VER_FILEDESCRIPTION_STR "Windows PowerShell" +#define VER_INTERNALNAME_STR "POWERSHELL" +#define VER_ORIGINALFILENAME_STR "PowerShell.EXE" + +#include