diff --git a/build.psm1 b/build.psm1 index 83a7948011..5e508fa958 100644 --- a/build.psm1 +++ b/build.psm1 @@ -99,12 +99,11 @@ function Start-PSBuild { Use-MSBuild #mc.exe is Message Compiler for native resources - <# This currently doesn't work reliably and clean systems. Removing for now since mc.exe is not being used yet. + # This currently doesn't work reliably and clean systems. Removing for now since mc.exe is not being used yet. $mcexe = Get-ChildItem "${env:ProgramFiles(x86)}\Microsoft SDKs\Windows\" -Recurse -Filter 'mc.exe' | ? {$_.FullName -match 'x64'} | select -First 1 | % {$_.FullName} if (-not $mcexe) { throw 'mc.exe not found. Install Microsoft Windows SDK.' } - #> $vcVarsPath = (Get-Item(Join-Path -Path "$env:VS140COMNTOOLS" -ChildPath '../../vc')).FullName if ((Test-Path -Path $vcVarsPath\vcvarsall.bat) -eq $false) @@ -223,7 +222,6 @@ function Start-PSBuild { try { Push-Location "$PSScriptRoot\src\powershell-native" - <# # Compile native resources @("nativemsh/pwrshplugin") | % { $nativeResourcesFolder = $_ @@ -231,7 +229,6 @@ function Start-PSBuild { & $mcexe -o -d -c -U $_.FullName -h $nativeResourcesFolder -r $nativeResourcesFolder } } - #> # Disabling until I figure out if it is necessary # $overrideFlags = "-DCMAKE_USER_MAKE_RULES_OVERRIDE=$PSScriptRoot\src\powershell-native\windows-compiler-override.txt" diff --git a/src/powershell-native/nativemsh/pwrshcommon/CMakeLists.txt b/src/powershell-native/nativemsh/pwrshcommon/CMakeLists.txt index c3971e88d8..24fd4afe40 100644 --- a/src/powershell-native/nativemsh/pwrshcommon/CMakeLists.txt +++ b/src/powershell-native/nativemsh/pwrshcommon/CMakeLists.txt @@ -4,7 +4,9 @@ # add_library(pwrshcommon pwrshcommon.cpp - WinSystemCallFacade.cpp) + WinSystemCallFacade.cpp + ConfigFileReader.cpp + ) target_include_directories(pwrshcommon PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/src/powershell-native/nativemsh/pwrshcommon/ClrHostWrapper.h b/src/powershell-native/nativemsh/pwrshcommon/ClrHostWrapper.h index 2c86fb9e27..cb1b870cc9 100644 --- a/src/powershell-native/nativemsh/pwrshcommon/ClrHostWrapper.h +++ b/src/powershell-native/nativemsh/pwrshcommon/ClrHostWrapper.h @@ -37,7 +37,7 @@ namespace NativeMsh // // The following methods are direct thin wrappers for the host calls. // - virtual HMODULE SetupWrapper(LPCSTR coreClrPathPtr) = 0; + virtual unsigned int SetupWrapper(LPCSTR coreClrPathPtr) = 0; virtual int InitializeClr( const char* exePath, @@ -123,15 +123,13 @@ namespace NativeMsh { return (NULL != coreClrHandle); } - - // - // TODO: This shouldn't return HMODULE because that breaks encapsulation. I need a better way to - // have the caller extract the value. Either Pass as a reference or provide an accessor. - // + + // // Attempts to load CoreCLR.dll from the specified directory. // On success pins the dll, sets coreCLRDirectoryPath and returns the HMODULE. // On failure returns NULL. - virtual HMODULE SetupWrapper(LPCSTR coreClrPathPtr) + // + virtual unsigned int SetupWrapper(LPCSTR coreClrPathPtr) { std::string coreClrPath(coreClrPathPtr); coreClrPath += coreClrDllName; @@ -139,13 +137,13 @@ namespace NativeMsh HMODULE result = LoadLibraryExA(coreClrPath.c_str(), NULL, 0); if (!result) { - return NULL; + return EXIT_CODE_INIT_FAILURE; } // Pin the module - CoreCLR.dll does not support being unloaded. if (!GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_PIN, coreClrPath.c_str(), &pinnedModuleHandle)) { - return NULL; + return EXIT_CODE_INIT_FAILURE; } initPtr = (coreclr_initialize_ptr)GetProcAddress(result, "coreclr_initialize"); @@ -156,12 +154,12 @@ namespace NativeMsh NULL == shutdownPtr || NULL == createDelegatePtr) { - return NULL; + return EXIT_CODE_INIT_FAILURE; } // Initialization succeeded. Save the handle and return success; coreClrHandle = result; - return result; + return EXIT_CODE_SUCCESS; } virtual unsigned int CleanUpHostWrapper() @@ -246,6 +244,7 @@ namespace NativeMsh private: // The path to this module char m_hostPath[MAX_PATH]; + wchar_t m_hostPathW[MAX_PATH]; // The path to the directory containing this module char m_hostDirectoryPath[MAX_PATH]; @@ -253,11 +252,56 @@ namespace NativeMsh // The name of this module, without the path std::string m_hostBinaryName; + std::wstring m_hostBinaryNameW; // The path to the directory that CoreCLR is in char m_coreCLRDirectoryPath[MAX_PATH]; wchar_t m_coreCLRDirectoryPathW[MAX_PATH]; + void convertAnsiToWide(char* ansiArray, wchar_t* wideArray) + { + // Generate the wide version of the string and save its value; + // + // This is a two call function. The first call is to get the necessary length. + // The second call is to perform the actual operation. + int length = ::MultiByteToWideChar(CP_UTF8, 0, ansiArray, -1, NULL, 0); + if (0 < length) + { + LPWSTR result = new wchar_t[length]; + if (NULL != result) + { + length = ::MultiByteToWideChar(CP_UTF8, 0, ansiArray, -1, result, length); + if (0 < length) + { + wcscpy_s(wideArray, MAX_PATH, result); + } + delete[] result; // Free the allocated string to avoid a memory leak + } + } + } + + void convertWideToAnsi(wchar_t* wideArray, char* ansiArray) + { + // Generate the ansi version of the string and save its value; + // + // This is a two call function. The first call is to get the necessary length. + // The second call is to perform the actual operation. + int length = ::WideCharToMultiByte(CP_ACP, 0, wideArray, -1, NULL, 0, NULL, NULL); + if (0 < length) + { + LPSTR result = new char[length]; + if (NULL != result) + { + length = ::WideCharToMultiByte(CP_ACP, 0, wideArray, -1, result, length, NULL, NULL); + if (0 < length) + { + strcpy_s(ansiArray, MAX_PATH, result); + } + delete[] result; // Free the allocated string to avoid a memory leak + } + } + } + public: HostEnvironment() @@ -275,6 +319,17 @@ namespace NativeMsh if (hostPath) { ::ExpandEnvironmentStringsA(hostPath, m_hostPath, MAX_PATH); + + convertAnsiToWide(m_hostPath, m_hostPathW); + } + } + void SetHostPathW(PCWSTR hostPath) + { + if (hostPath) + { + ::ExpandEnvironmentStringsW(hostPath, m_hostPathW, MAX_PATH); + + convertWideToAnsi(m_hostPathW, m_hostPath); } } @@ -284,6 +339,11 @@ namespace NativeMsh return m_hostPath; } + PCWSTR GetHostPathW() + { + return m_hostPathW; + } + // Safely copies in a host binary name void SetHostBinaryName(PCSTR hostBinaryName) { @@ -293,12 +353,25 @@ namespace NativeMsh } } + void SetHostBinaryNameW(PCWSTR hostBinaryName) + { + if (hostBinaryName) + { + m_hostBinaryNameW = std::wstring(hostBinaryName); + } + } + // Returns the name of the host module PCSTR GetHostBinaryName() { return m_hostBinaryName.c_str(); } + PCWSTR GetHostBinaryNameW() + { + return m_hostBinaryNameW.c_str(); + } + // Safely copies in a host directory path void SetHostDirectoryPath(PCSTR hostDirPath) { @@ -306,24 +379,17 @@ namespace NativeMsh { ::ExpandEnvironmentStringsA(hostDirPath, m_hostDirectoryPath, MAX_PATH); - // Generate the wide version of the string and save its value; - // - // This is a two call function. The first call is to get the necessary length. - // The second call is to perform the actual operation. - int length = MultiByteToWideChar(CP_UTF8, 0, m_hostDirectoryPath, -1, NULL, 0); - if (0 < length) - { - LPWSTR result = new wchar_t[length]; - if (NULL != result) - { - length = ::MultiByteToWideChar(CP_UTF8, 0, m_hostDirectoryPath, -1, result, length); - if (0 < length) - { - wcscpy_s(m_hostDirectoryPathW, MAX_PATH, result); - } - delete[] result; // Free the allocated string to avoid a memory leak - } - } + convertAnsiToWide(m_hostDirectoryPath, m_hostDirectoryPathW); + } + } + + void SetHostDirectoryPathW(PCWSTR hostDirPath) + { + if (hostDirPath) + { + ::ExpandEnvironmentStringsW(hostDirPath, m_hostDirectoryPathW, MAX_PATH); + + convertWideToAnsi(m_hostDirectoryPathW, m_hostDirectoryPath); } } @@ -346,24 +412,17 @@ namespace NativeMsh { ::ExpandEnvironmentStringsA(hostClrPath, m_coreCLRDirectoryPath, MAX_PATH); - // Generate the wide version of the string and save its value; - // - // This is a two call function. The first call is to get the necessary length. - // The second call is to perform the actual operation. - int length = MultiByteToWideChar(CP_UTF8, 0, m_coreCLRDirectoryPath, -1, NULL, 0); - if (0 < length) - { - LPWSTR result = new wchar_t[length]; - if (NULL != result) - { - length = ::MultiByteToWideChar(CP_UTF8, 0, m_coreCLRDirectoryPath, -1, result, length); - if (0 < length) - { - wcscpy_s(m_coreCLRDirectoryPathW, MAX_PATH, result); - } - delete[] result; // Free the allocated string to avoid a memory leak - } - } + convertAnsiToWide(m_coreCLRDirectoryPath, m_coreCLRDirectoryPathW); + } + } + + void SetCoreCLRDirectoryPathW(PCWSTR hostClrPath) + { + if (hostClrPath) + { + ::ExpandEnvironmentStringsW(hostClrPath, m_coreCLRDirectoryPathW, MAX_PATH); + + convertWideToAnsi(m_coreCLRDirectoryPathW, m_coreCLRDirectoryPath); } } @@ -378,5 +437,7 @@ namespace NativeMsh { return m_coreCLRDirectoryPathW; } + + }; } // namespace NativeMsh diff --git a/src/powershell-native/nativemsh/pwrshcommon/ConfigFileReader.cpp b/src/powershell-native/nativemsh/pwrshcommon/ConfigFileReader.cpp new file mode 100644 index 0000000000..4b1bd4b430 --- /dev/null +++ b/src/powershell-native/nativemsh/pwrshcommon/ConfigFileReader.cpp @@ -0,0 +1,131 @@ +#include +#include +#include + +#include "NativeMsh.h" +#include "ConfigFileReader.h" + +namespace NativeMsh +{ + // The name of the PowerShell config file that identifies the PowerShell install location. + // We use a config file to avoid writing to the registry during install + // or hard coding paths into the binary. + static PCWSTR powerShellConfigFileName = L"RemotePowerShellConfig.txt"; + + ConfigFileReader::ConfigFileReader() + { + } + + unsigned int ConfigFileReader::Read( + std::wstring pathToConfig) + { + std::wstring absolutePathToConfigFile(pathToConfig); + absolutePathToConfigFile += powerShellConfigFileName; + std::wfstream psConfigFile(absolutePathToConfigFile.c_str()); + + if (!psConfigFile.is_open()) + { + return EXIT_CODE_INIT_FAILURE; + } + + std::wstring line; + std::wstring psHomeDirTag(L"PSHOMEDIR="); + std::wstring coreClrDirTag(L"CORECLRDIR="); + while (std::getline(psConfigFile, line)) + { + std::wstring::const_iterator iter = line.begin(); + + // Search for the first actionable character in the line to + // limit the number of passes that are made iterating through the line. + while(iter != line.end()) + { + if (*iter == L'#') + { + // Stop parsing the line because the rest of it is a comment + break; + } + else if (*iter == L'p' || *iter == L'P') + { + this->pathToPowerShellAssemblies = this->getValueFromLine(line, psHomeDirTag); + if (this->pathToPowerShellAssemblies.size() > 0) // Found a match + { + std::wstring::const_iterator slashIter = this->pathToPowerShellAssemblies.end(); + slashIter--; + if (*slashIter != L'\\') + { + // Guarantee that there is a '\' at the end of the path + this->pathToPowerShellAssemblies.append(L"\\"); + } + } + } + else if (*iter == L'c' || *iter == L'C') + { + this->coreClrDirectory = this->getValueFromLine(line, coreClrDirTag); + if (this->coreClrDirectory.size() > 0) // Found a match + { + std::wstring::const_iterator slashIter = this->coreClrDirectory.end(); + slashIter--; + if (*slashIter != L'\\') + { + // Guarantee that there is a '\' at the end of the path + this->coreClrDirectory.append(L"\\"); + } + } + } + + // Do nothing to ignore unmatched characters (whitespace, etc.) + iter++; + } + } + if (0 == this->pathToPowerShellAssemblies.size() || + 0 == this->coreClrDirectory.size()) + { + return EXIT_CODE_INIT_FAILURE; + } + else + { + return EXIT_CODE_SUCCESS; + } + } + + // This trim function removes beginning and ending whitespace. It does not + // remove internal whitespace because that is valid within paths. + std::wstring ConfigFileReader::trim( + const std::wstring& toTrim) + { + static PCWSTR WHITESPACE_CHARS = L" \n\r\t"; + std::wstring copyToTrim = toTrim; + std::size_t first = copyToTrim.find_first_not_of(WHITESPACE_CHARS); + + if (first == std::wstring::npos) + { + // No non-whitespace found + return std::wstring(L""); + } + + // Result not checked for std::wstring::npos because it is guaranteed to have a value if the first pass succeeded. + copyToTrim.erase(copyToTrim.find_last_not_of(WHITESPACE_CHARS)+1); + + return copyToTrim.substr(first); + } + + // Parses the specified line for the given tag. Tags are assumed to include + // the "=" separator character. + std::wstring ConfigFileReader::getValueFromLine( + const std::wstring& line, // Passed by value to preserve the original line. + std::wstring& tagToFind) + { + std::wstring trimmedLine = this->trim(line); + std::size_t index = trimmedLine.find(tagToFind); + if (std::string::npos != index) + { + std::wstring value = trimmedLine.substr(index + tagToFind.size()); // Everything else after the tag + return this->trim(value); + } + else + { + return std::wstring(L""); + } + } +} + diff --git a/src/powershell-native/nativemsh/pwrshcommon/ConfigFileReader.h b/src/powershell-native/nativemsh/pwrshcommon/ConfigFileReader.h new file mode 100644 index 0000000000..265992dbcc --- /dev/null +++ b/src/powershell-native/nativemsh/pwrshcommon/ConfigFileReader.h @@ -0,0 +1,36 @@ +// --------------------------------------------------------------------------- +// +// Microsoft Windows NT +// Copyright (C) Microsoft Corporation, 2014. +// +// Contents: A class that extracts the path to $PSHOME and the path to its +// CoreCLR from a configuration file. +// --------------------------------------------------------------------------- + +#pragma once + +#include + +namespace NativeMsh +{ + class ConfigFileReader + { + private: + std::wstring pathToPowerShellAssemblies; + std::wstring coreClrDirectory; + + std::wstring trim(const std::wstring& toTrim); + std::wstring getValueFromLine(const std::wstring& line, std::wstring& tagToFind); + + public: + ConfigFileReader(); + + // Initiates a Read operation of the specified configuration file. + unsigned int Read(std::wstring pathToConfig); + + // Information Getters + std::wstring GetPathToPowerShell() { return pathToPowerShellAssemblies; } + std::wstring GetPathToCoreClr() { return coreClrDirectory; } + }; +} // namespace NativeMsh + diff --git a/src/powershell-native/nativemsh/pwrshcommon/NativeMsh.h b/src/powershell-native/nativemsh/pwrshcommon/NativeMsh.h index eee01a4983..924fc5e342 100644 --- a/src/powershell-native/nativemsh/pwrshcommon/NativeMsh.h +++ b/src/powershell-native/nativemsh/pwrshcommon/NativeMsh.h @@ -17,6 +17,7 @@ #include "NativeMshConstants.h" #include "ClrHostWrapper.h" #include "SystemCallFacade.h" +#include "ConfigFileReader.h" #include "IPwrshCommonOutput.h" #if !CORECLR @@ -29,6 +30,7 @@ namespace NativeMsh { private: IPwrshCommonOutput* output; + ConfigFileReader* reader; SystemCallFacade* sysCalls; public: @@ -41,6 +43,7 @@ namespace NativeMsh // allocate them with "new". PwrshCommon( IPwrshCommonOutput* outObj, // Enables clients to specify how error messages are displayed or suppressed + ConfigFileReader* rdr, // Enables specification of how the config file is read. SystemCallFacade* systemCalls); // Wraps all calls to Windows APIs to allow for dependency injection via unit test ~PwrshCommon(); diff --git a/src/powershell-native/nativemsh/pwrshcommon/pwrshcommon.cpp b/src/powershell-native/nativemsh/pwrshcommon/pwrshcommon.cpp index b687fed711..fef8380581 100644 --- a/src/powershell-native/nativemsh/pwrshcommon/pwrshcommon.cpp +++ b/src/powershell-native/nativemsh/pwrshcommon/pwrshcommon.cpp @@ -820,29 +820,40 @@ namespace NativeMsh // The name of the CoreCLR native runtime DLL. static PCSTR coreClrDll = "CoreCLR.dll"; - // The location where CoreCLR is expected to be installed. If CoreCLR.dll isn't + // The location where CoreCLR is expected to be installed for inbox PowerShell. If CoreCLR.dll isn't // found in the same directory as the host, it will be looked for here. static PCSTR coreCLRInstallDirectory = "%windir%\\system32\\DotNetCore\\v1.0\\"; - // The location where CoreCLR PowerShell Ext binaries are expected to be installed. + // The location where CoreCLR PowerShell Ext binaries are expected to be installed for inbox PowerShell. static PCSTR coreCLRPowerShellExtInstallDirectory = "%windir%\\system32\\CoreClrPowerShellExt\\v1.0\\"; - // The default PowerShell install directory. This location may be overridden through a config file in %windir%\System32. + // The default PowerShell install directory for inbox PowerShell. + // This location may be overridden by placing a config file in the same directory as the PowerShell host. static PCSTR powerShellInstallPath = "%windir%\\System32\\WindowsPowerShell\\v1.0\\"; unsigned int PwrshCommon::IdentifyHostDirectory( HostEnvironment& hostEnvironment) { - // Discover the path to the exe's module (powershell.exe or wsmprovhost.exe). - // For remoting, this is expected to be %windir%\system32 since that is the location of wsmprovhost.exe. - char hostPath[MAX_PATH]; - DWORD thisModuleLength = sysCalls->GetModuleFileNameA(sysCalls->GetModuleHandleA(NULL), hostPath, MAX_PATH); + // Discover the path to the plugin or the executable (pwrshplugin.dll or powershell.exe). + // For PowerShell Core, the plugin no longer resides in %windir%\\system32 (it is in a sub-directory). + // If pwrshplugin.dll is not loaded, it means that this is running via powershell.exe. + wchar_t hostPath[MAX_PATH]; + DWORD thisModuleLength; - if (0 == thisModuleLength) + if (GetModuleHandleW(L"pwrshplugin.dll")) + { + thisModuleLength = GetModuleFileNameW(GetModuleHandleW(L"pwrshplugin.dll"), hostPath, MAX_PATH); + } + else + { + thisModuleLength = GetModuleFileNameW(GetModuleHandleW(NULL), hostPath, MAX_PATH); + } + if (0 == thisModuleLength) // Greater than zero means it is the length of the fully qualified path (without the NULL character) { // TODO: Use GetLastError() to find the specific error # return EXIT_CODE_INIT_FAILURE; } + // Search for the last backslash in the host path. int lastBackslashIndex; for (lastBackslashIndex = thisModuleLength - 1; lastBackslashIndex >= 0; lastBackslashIndex--) @@ -854,14 +865,34 @@ namespace NativeMsh } // The remaining part of the path after the last '\' is the binary name. - hostEnvironment.SetHostBinaryName(hostPath + lastBackslashIndex + 1); + hostEnvironment.SetHostBinaryNameW(hostPath + lastBackslashIndex + 1); // Copy the directory path portion of the path hostPath[lastBackslashIndex + 1] = '\0'; - hostEnvironment.SetHostPath(hostPath); - - hostEnvironment.SetHostDirectoryPath(powerShellInstallPath); + hostEnvironment.SetHostPathW(hostPath); + // Read the config file to determine the appropriate host path and CoreCLR path to use. + unsigned int result = reader->Read(hostPath); + if (EXIT_CODE_SUCCESS == result) + { + // The config file was successfully parsed. Use those directories. + hostEnvironment.SetHostDirectoryPathW(reader->GetPathToPowerShell().c_str()); + hostEnvironment.SetCoreCLRDirectoryPathW(reader->GetPathToCoreClr().c_str()); + } + else + { + // There was an issue accessing or parsing the config file OR + // we are working for the EXE. + // + // TODO: This should not be the fallback for inbox PowerShell.exe. + // It should use coreCLRInstallDirectory and coreCLRPowerShellExtInstallDirectory. + // + // Use the directory detected via GetModuleFileName + GetModuleHandle + hostEnvironment.SetHostDirectoryPathW(hostPath); + // At the moment, CoreCLR is in the same directory as PowerShell Core. + // This path must be modified if we decide to use a different directory. + hostEnvironment.SetCoreCLRDirectoryPathW(hostPath); + } return EXIT_CODE_SUCCESS; } @@ -959,20 +990,26 @@ namespace NativeMsh // PwrshCommon::PwrshCommon() - : output(new PwrshCommonOutputDefault()), sysCalls(new WinSystemCallFacade()) + : output(new PwrshCommonOutputDefault()), reader(new ConfigFileReader()), sysCalls(new WinSystemCallFacade()) { } PwrshCommon::PwrshCommon( IPwrshCommonOutput* outObj, + ConfigFileReader* rdr, SystemCallFacade* systemCalls) - : output(outObj), sysCalls(systemCalls) + : output(outObj), reader(rdr), sysCalls(systemCalls) { if (NULL == output) { output = new PwrshCommonOutputDefault(); } + if (NULL == reader) + { + reader = new ConfigFileReader(); + } + if (NULL == sysCalls) { sysCalls = new WinSystemCallFacade(); @@ -987,6 +1024,12 @@ namespace NativeMsh output = NULL; } + if (reader) + { + delete reader; + reader = NULL; + } + if (sysCalls) { delete sysCalls; @@ -1299,37 +1342,13 @@ namespace NativeMsh return exitCode; } - // Try to load from the well-known location. - char coreCLRInstallPath[MAX_PATH]; - exitCode = ::ExpandEnvironmentStringsA(coreCLRInstallDirectory, coreCLRInstallPath, MAX_PATH); - if (0 == exitCode || _countof(coreCLRInstallPath) <= exitCode) + exitCode = hostWrapper->SetupWrapper(hostEnvironment.GetCoreCLRDirectoryPath()); + if (EXIT_CODE_SUCCESS != exitCode) { this->output->DisplayMessage(false, g_STARTING_CLR_FAILED, GetLastError()); - return EXIT_CODE_INIT_FAILURE; - } - - HMODULE coreClrModule = hostWrapper->SetupWrapper(coreCLRInstallPath); - if (!coreClrModule) - { - this->output->DisplayMessage(false, g_STARTING_CLR_FAILED, GetLastError()); - return EXIT_CODE_INIT_FAILURE; + return exitCode; } - // Save the directory that CoreCLR was found in - char coreCLRDirectoryPath[MAX_PATH]; - DWORD modulePathLength = sysCalls->GetModuleFileNameA(coreClrModule, coreCLRDirectoryPath, MAX_PATH); - - // Search for the last backslash and terminate it there to keep just the directory path with trailing slash - for (int lastBackslashIndex = modulePathLength - 1; lastBackslashIndex >= 0; lastBackslashIndex--) - { - if (coreCLRDirectoryPath[lastBackslashIndex] == L'\\') - { - coreCLRDirectoryPath[lastBackslashIndex + 1] = L'\0'; - break; - } - } - hostEnvironment.SetCoreCLRDirectoryPath(coreCLRDirectoryPath); - const int nMaxProps = 8; LPCSTR props[nMaxProps]; LPCSTR vals[nMaxProps]; diff --git a/src/powershell-native/nativemsh/pwrshexe/CMakeLists.txt b/src/powershell-native/nativemsh/pwrshexe/CMakeLists.txt index cddff23d3b..e0f8ada213 100644 --- a/src/powershell-native/nativemsh/pwrshexe/CMakeLists.txt +++ b/src/powershell-native/nativemsh/pwrshexe/CMakeLists.txt @@ -34,7 +34,7 @@ else () # CoreCLR libs ${STATIC_MT_CRT_LIB} ${STATIC_MT_VCRT_LIB} - ${STATIC_UCRT_LIB} + # ${STATIC_UCRT_LIB} # ole32.lib # oleaut32.lib # uuid.lib diff --git a/src/powershell-native/nativemsh/pwrshexe/CssMainEntry.cpp b/src/powershell-native/nativemsh/pwrshexe/CssMainEntry.cpp index bf0853bff2..c8a2017604 100644 --- a/src/powershell-native/nativemsh/pwrshexe/CssMainEntry.cpp +++ b/src/powershell-native/nativemsh/pwrshexe/CssMainEntry.cpp @@ -18,6 +18,7 @@ #include "NativeMsh.h" #include "ClrHostWrapper.h" #include "OutputWriter.h" +#include "ConfigFileReader.h" #include "WinSystemCallFacade.h" namespace NativeMsh @@ -35,7 +36,7 @@ namespace NativeMsh // All these objects will be destroyed when commonFuncs goes out of scope. PwrshExeOutput* output = new PwrshExeOutput(); - PwrshCommon commonFuncs(output, new WinSystemCallFacade()); + PwrshCommon commonFuncs(output, new ConfigFileReader(), new WinSystemCallFacade()); CoreClrHostingApiWrapper hostWrapper; exitCode = commonFuncs.LaunchCoreCLR(&hostWrapper, hostEnvironment, "powershell"); diff --git a/src/powershell-native/nativemsh/pwrshexe/MainEntry.cpp b/src/powershell-native/nativemsh/pwrshexe/MainEntry.cpp index e85bed577e..7253d31b66 100644 --- a/src/powershell-native/nativemsh/pwrshexe/MainEntry.cpp +++ b/src/powershell-native/nativemsh/pwrshexe/MainEntry.cpp @@ -26,6 +26,7 @@ #include #include #include "OutputWriter.h" +#include "ConfigFileReader.h" #include "WinSystemCallFacade.h" // include the tlb for mscorlib for access to the default AppDomain through COM Interop @@ -49,7 +50,7 @@ WCHAR g_IconApp[MAX_PATH+1]; // All these objects will be destroyed when pwrshCommon goes out of scope. PwrshExeOutput* pwrshExeOutput = new PwrshExeOutput(); -PwrshCommon pwrshCommon(pwrshExeOutput, new WinSystemCallFacade()); +PwrshCommon pwrshCommon(pwrshExeOutput, new ConfigFileReader(), new WinSystemCallFacade()); bool ConvertArgvToSafeArray( IN int argc, diff --git a/src/powershell-native/nativemsh/pwrshplugin/CMakeLists.txt b/src/powershell-native/nativemsh/pwrshplugin/CMakeLists.txt index fb5f05f827..981d69d82a 100644 --- a/src/powershell-native/nativemsh/pwrshplugin/CMakeLists.txt +++ b/src/powershell-native/nativemsh/pwrshplugin/CMakeLists.txt @@ -5,7 +5,8 @@ add_library(pwrshplugin SHARED entrypoints.cpp pwrshclrhost.cpp pwrshpluginerrorcodes.mc - pwrshpluginerrorcodes.rc + #pwrshpluginerrorcodes.rc + pwrshpluginResources.rc pwrshplugin.def ) @@ -40,7 +41,7 @@ else () # CoreCLR lib ${STATIC_MT_CRT_LIB} ${STATIC_MT_VCRT_LIB} - ${STATIC_UCRT_LIB} + # ${STATIC_UCRT_LIB} legacy_stdio_definitions.lib # Resolves: LNK2019: unresolved external symbol _vsnwprintf ) set(pwrshplugin_definitions ${common_pwrsh_definitions}) diff --git a/src/powershell-native/nativemsh/pwrshplugin/pwrshclrhost.cpp b/src/powershell-native/nativemsh/pwrshplugin/pwrshclrhost.cpp index 8c0d5890e8..054e1f1f50 100644 --- a/src/powershell-native/nativemsh/pwrshplugin/pwrshclrhost.cpp +++ b/src/powershell-native/nativemsh/pwrshplugin/pwrshclrhost.cpp @@ -130,7 +130,7 @@ PowerShellCoreClrWorker::PowerShellCoreClrWorker( if (NULL == commonLib) { - commonLib = new PwrshCommon(new PwrshPluginOutputDefault(), new WinSystemCallFacade()); + commonLib = new PwrshCommon(new PwrshPluginOutputDefault(), new ConfigFileReader(), new WinSystemCallFacade()); } } @@ -344,7 +344,8 @@ unsigned int PowerShellClrManagedWorker::LoadWorkerCallbackPtrs( // use CreateInstance because we use the assembly strong name (as opposed to CreateInstanceFrom) // - // wszMgdPlugInFileName is %systemdir%\Windows\System32\WindowsPowerShell\v1.0\system.management.automation.dll. + // wszMgdPlugInFileName is system.management.automation.dll within the powershell install path. + // For inbox PowerShell, this is %systemdir%\Windows\System32\WindowsPowerShell\v1.0\system.management.automation.dll (Aka $PSHOME\system.management.automation.dll) _bstr_t bstrConsoleHostAssemblyName = _bstr_t(L"System.Management.Automation, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"); _bstr_t bstrUnmanagedMshEntryClass = _bstr_t(L"System.Management.Automation.Remoting.WSManPluginManagedEntryInstanceWrapper");