diff --git a/DistroLauncher.sln b/DistroLauncher.sln index 7a231ff4..dff0e263 100644 --- a/DistroLauncher.sln +++ b/DistroLauncher.sln @@ -16,95 +16,66 @@ EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU - Debug|ARM = Debug|ARM Debug|ARM64 = Debug|ARM64 Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU - Release|ARM = Release|ARM Release|ARM64 = Release|ARM64 Release|x64 = Release|x64 - Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {BA627106-E5F7-46EE-B8D7-2D5A760F2FB2}.Debug|Any CPU.ActiveCfg = Debug|x64 - {BA627106-E5F7-46EE-B8D7-2D5A760F2FB2}.Debug|ARM.ActiveCfg = Debug|x64 {BA627106-E5F7-46EE-B8D7-2D5A760F2FB2}.Debug|ARM64.ActiveCfg = Debug|ARM64 {BA627106-E5F7-46EE-B8D7-2D5A760F2FB2}.Debug|ARM64.Build.0 = Debug|ARM64 {BA627106-E5F7-46EE-B8D7-2D5A760F2FB2}.Debug|x64.ActiveCfg = Debug|x64 {BA627106-E5F7-46EE-B8D7-2D5A760F2FB2}.Debug|x64.Build.0 = Debug|x64 - {BA627106-E5F7-46EE-B8D7-2D5A760F2FB2}.Debug|x86.ActiveCfg = Debug|x64 {BA627106-E5F7-46EE-B8D7-2D5A760F2FB2}.Release|Any CPU.ActiveCfg = Release|x64 - {BA627106-E5F7-46EE-B8D7-2D5A760F2FB2}.Release|ARM.ActiveCfg = Release|x64 {BA627106-E5F7-46EE-B8D7-2D5A760F2FB2}.Release|ARM64.ActiveCfg = Release|ARM64 {BA627106-E5F7-46EE-B8D7-2D5A760F2FB2}.Release|ARM64.Build.0 = Release|ARM64 {BA627106-E5F7-46EE-B8D7-2D5A760F2FB2}.Release|x64.ActiveCfg = Release|x64 {BA627106-E5F7-46EE-B8D7-2D5A760F2FB2}.Release|x64.Build.0 = Release|x64 - {BA627106-E5F7-46EE-B8D7-2D5A760F2FB2}.Release|x86.ActiveCfg = Release|x64 {4175DAA1-10E2-45BF-88BD-6577AF555B1B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4175DAA1-10E2-45BF-88BD-6577AF555B1B}.Debug|ARM.ActiveCfg = Debug|ARM {4175DAA1-10E2-45BF-88BD-6577AF555B1B}.Debug|ARM64.ActiveCfg = Debug|ARM64 {4175DAA1-10E2-45BF-88BD-6577AF555B1B}.Debug|ARM64.Build.0 = Debug|ARM64 {4175DAA1-10E2-45BF-88BD-6577AF555B1B}.Debug|ARM64.Deploy.0 = Debug|ARM64 {4175DAA1-10E2-45BF-88BD-6577AF555B1B}.Debug|x64.ActiveCfg = Debug|x64 {4175DAA1-10E2-45BF-88BD-6577AF555B1B}.Debug|x64.Build.0 = Debug|x64 {4175DAA1-10E2-45BF-88BD-6577AF555B1B}.Debug|x64.Deploy.0 = Debug|x64 - {4175DAA1-10E2-45BF-88BD-6577AF555B1B}.Debug|x86.ActiveCfg = Debug|x86 {4175DAA1-10E2-45BF-88BD-6577AF555B1B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4175DAA1-10E2-45BF-88BD-6577AF555B1B}.Release|ARM.ActiveCfg = Release|ARM {4175DAA1-10E2-45BF-88BD-6577AF555B1B}.Release|ARM64.ActiveCfg = Release|ARM64 {4175DAA1-10E2-45BF-88BD-6577AF555B1B}.Release|ARM64.Build.0 = Release|ARM64 {4175DAA1-10E2-45BF-88BD-6577AF555B1B}.Release|ARM64.Deploy.0 = Release|ARM64 {4175DAA1-10E2-45BF-88BD-6577AF555B1B}.Release|x64.ActiveCfg = Release|x64 {4175DAA1-10E2-45BF-88BD-6577AF555B1B}.Release|x64.Build.0 = Release|x64 {4175DAA1-10E2-45BF-88BD-6577AF555B1B}.Release|x64.Deploy.0 = Release|x64 - {4175DAA1-10E2-45BF-88BD-6577AF555B1B}.Release|x86.ActiveCfg = Release|x86 - {3FBA1AEE-63DF-4490-82AE-74AAAB1BFD80}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {3FBA1AEE-63DF-4490-82AE-74AAAB1BFD80}.Debug|ARM.ActiveCfg = Debug|Win32 - {3FBA1AEE-63DF-4490-82AE-74AAAB1BFD80}.Debug|ARM64.ActiveCfg = Debug|Win32 + {3FBA1AEE-63DF-4490-82AE-74AAAB1BFD80}.Debug|Any CPU.ActiveCfg = Debug|x64 + {3FBA1AEE-63DF-4490-82AE-74AAAB1BFD80}.Debug|ARM64.ActiveCfg = Debug|x64 {3FBA1AEE-63DF-4490-82AE-74AAAB1BFD80}.Debug|x64.ActiveCfg = Debug|x64 {3FBA1AEE-63DF-4490-82AE-74AAAB1BFD80}.Debug|x64.Build.0 = Debug|x64 - {3FBA1AEE-63DF-4490-82AE-74AAAB1BFD80}.Debug|x86.ActiveCfg = Debug|Win32 - {3FBA1AEE-63DF-4490-82AE-74AAAB1BFD80}.Release|Any CPU.ActiveCfg = Release|Win32 - {3FBA1AEE-63DF-4490-82AE-74AAAB1BFD80}.Release|ARM.ActiveCfg = Release|Win32 - {3FBA1AEE-63DF-4490-82AE-74AAAB1BFD80}.Release|ARM64.ActiveCfg = Release|Win32 + {3FBA1AEE-63DF-4490-82AE-74AAAB1BFD80}.Release|Any CPU.ActiveCfg = Release|x64 + {3FBA1AEE-63DF-4490-82AE-74AAAB1BFD80}.Release|ARM64.ActiveCfg = Release|x64 {3FBA1AEE-63DF-4490-82AE-74AAAB1BFD80}.Release|x64.ActiveCfg = Release|x64 {3FBA1AEE-63DF-4490-82AE-74AAAB1BFD80}.Release|x64.Build.0 = Release|x64 - {3FBA1AEE-63DF-4490-82AE-74AAAB1BFD80}.Release|x86.ActiveCfg = Release|Win32 - {4F3B346B-175D-46BC-B233-92D0B25D5576}.Debug|Any CPU.ActiveCfg = Debug|x86 - {4F3B346B-175D-46BC-B233-92D0B25D5576}.Debug|ARM.ActiveCfg = Debug|ARM + {4F3B346B-175D-46BC-B233-92D0B25D5576}.Debug|Any CPU.ActiveCfg = Debug|x64 {4F3B346B-175D-46BC-B233-92D0B25D5576}.Debug|ARM64.ActiveCfg = Debug|ARM64 {4F3B346B-175D-46BC-B233-92D0B25D5576}.Debug|ARM64.Build.0 = Debug|ARM64 {4F3B346B-175D-46BC-B233-92D0B25D5576}.Debug|x64.ActiveCfg = Debug|x64 {4F3B346B-175D-46BC-B233-92D0B25D5576}.Debug|x64.Build.0 = Debug|x64 - {4F3B346B-175D-46BC-B233-92D0B25D5576}.Debug|x86.ActiveCfg = Debug|x86 - {4F3B346B-175D-46BC-B233-92D0B25D5576}.Release|Any CPU.ActiveCfg = Release|x86 - {4F3B346B-175D-46BC-B233-92D0B25D5576}.Release|ARM.ActiveCfg = Release|ARM + {4F3B346B-175D-46BC-B233-92D0B25D5576}.Release|Any CPU.ActiveCfg = Release|x64 {4F3B346B-175D-46BC-B233-92D0B25D5576}.Release|ARM64.ActiveCfg = Release|ARM64 {4F3B346B-175D-46BC-B233-92D0B25D5576}.Release|ARM64.Build.0 = Release|ARM64 {4F3B346B-175D-46BC-B233-92D0B25D5576}.Release|x64.ActiveCfg = Release|x64 {4F3B346B-175D-46BC-B233-92D0B25D5576}.Release|x64.Build.0 = Release|x64 - {4F3B346B-175D-46BC-B233-92D0B25D5576}.Release|x86.ActiveCfg = Release|x86 {D666189E-1DDB-4059-B362-213824968E68}.Debug|Any CPU.ActiveCfg = Debug|x64 - {D666189E-1DDB-4059-B362-213824968E68}.Debug|Any CPU.Build.0 = Debug|x64 - {D666189E-1DDB-4059-B362-213824968E68}.Debug|ARM.ActiveCfg = Debug|x64 - {D666189E-1DDB-4059-B362-213824968E68}.Debug|ARM.Build.0 = Debug|x64 - {D666189E-1DDB-4059-B362-213824968E68}.Debug|ARM64.ActiveCfg = Debug|x64 - {D666189E-1DDB-4059-B362-213824968E68}.Debug|ARM64.Build.0 = Debug|x64 + {D666189E-1DDB-4059-B362-213824968E68}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {D666189E-1DDB-4059-B362-213824968E68}.Debug|ARM64.Build.0 = Debug|ARM64 {D666189E-1DDB-4059-B362-213824968E68}.Debug|x64.ActiveCfg = Debug|x64 {D666189E-1DDB-4059-B362-213824968E68}.Debug|x64.Build.0 = Debug|x64 - {D666189E-1DDB-4059-B362-213824968E68}.Debug|x86.ActiveCfg = Debug|Win32 - {D666189E-1DDB-4059-B362-213824968E68}.Debug|x86.Build.0 = Debug|Win32 {D666189E-1DDB-4059-B362-213824968E68}.Release|Any CPU.ActiveCfg = Release|x64 {D666189E-1DDB-4059-B362-213824968E68}.Release|Any CPU.Build.0 = Release|x64 - {D666189E-1DDB-4059-B362-213824968E68}.Release|ARM.ActiveCfg = Release|x64 - {D666189E-1DDB-4059-B362-213824968E68}.Release|ARM.Build.0 = Release|x64 - {D666189E-1DDB-4059-B362-213824968E68}.Release|ARM64.ActiveCfg = Release|x64 - {D666189E-1DDB-4059-B362-213824968E68}.Release|ARM64.Build.0 = Release|x64 + {D666189E-1DDB-4059-B362-213824968E68}.Release|ARM64.ActiveCfg = Release|ARM64 + {D666189E-1DDB-4059-B362-213824968E68}.Release|ARM64.Build.0 = Release|ARM64 {D666189E-1DDB-4059-B362-213824968E68}.Release|x64.ActiveCfg = Release|x64 {D666189E-1DDB-4059-B362-213824968E68}.Release|x64.Build.0 = Release|x64 - {D666189E-1DDB-4059-B362-213824968E68}.Release|x86.ActiveCfg = Release|Win32 - {D666189E-1DDB-4059-B362-213824968E68}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/DistroLauncher/DistributionInfo.cpp b/DistroLauncher/DistributionInfo.cpp index b8ee5fe6..b62bcd27 100644 --- a/DistroLauncher/DistributionInfo.cpp +++ b/DistroLauncher/DistributionInfo.cpp @@ -13,6 +13,8 @@ HRESULT DistributionInfo::ChangeDefaultUserInWslConf(const std::wstring_view use _swprintf_p(commandLine, _countof(commandLine), L"if [ $(grep -c \"\\[user\\]\" /etc/wsl.conf) -eq \"0\" ]; then echo -e \"\\n[user]\\ndefault=%1$s\">>/etc/wsl.conf; else sed -i \"s/\\(default=\\)\\(.*\\)/\\1%1$s/\" /etc/wsl.conf ; fi", std::wstring(userName).c_str()); + MessageBoxW(nullptr, commandLine, L"Hola", MB_OK); + if (const auto hr = g_wslApi.WslLaunchInteractive(commandLine, true, &exitCode); FAILED(hr) || exitCode != 0) { diff --git a/DistroLauncher/DistroLauncher.cpp b/DistroLauncher/DistroLauncher.cpp index 9713e66c..e1992168 100644 --- a/DistroLauncher/DistroLauncher.cpp +++ b/DistroLauncher/DistroLauncher.cpp @@ -1,295 +1,308 @@ -// -// Copyright (C) Microsoft. All rights reserved. -// Licensed under the terms described in the LICENSE file in the root of this project. -// - -#include "stdafx.h" - -// Commandline arguments: -constexpr auto ARG_CONFIG = L"config"; -constexpr auto ARG_CONFIG_DEFAULT_USER = L"--default-user"; -constexpr auto ARG_INSTALL = L"install"; -constexpr auto ARG_INSTALL_ROOT = L"--root"; -constexpr auto ARG_RUN = L"run"; -constexpr auto ARG_RUN_C = L"-c"; - -#include -#include -#include - - -using namespace winrt; -using namespace Windows::Foundation; -using namespace Windows::System; -using namespace Windows::Storage; - - -// Helper class for calling WSL Functions: -// https://msdn.microsoft.com/en-us/library/windows/desktop/mt826874(v=vs.85).aspx -// ReSharper disable once CppInconsistentNaming -WslApiLoader g_wslApi(DistributionInfo::NAME); - -static HRESULT InstallDistribution(bool createUser); -static HRESULT SetDefaultUser(std::wstring_view userName); - -HRESULT InstallDistribution(const bool createUser) -{ - // Register the distribution. - Helpers::PrintMessage(MSG_STATUS_INSTALLING); - auto hr = g_wslApi.WslRegisterDistribution(); - if (FAILED(hr)) - { - return hr; - } - - // Delete /etc/resolv.conf to allow WSL to generate a version based on Windows networking information. - DWORD exitCode; - hr = g_wslApi.WslLaunchInteractive(L"/bin/rm /etc/resolv.conf", true, &exitCode); - if (FAILED(hr)) - { - return hr; - } - - // Create a user account. - if (createUser) - { - Helpers::PrintMessage(MSG_CREATE_USER_PROMPT); - std::wstring userName; - do - { - userName = Helpers::GetUserInput(MSG_ENTER_USERNAME, 32); - } - while (!DistributionInfo::CreateUser(userName)); - - // Set this user account as the default. - hr = SetDefaultUser(userName); - if (FAILED(hr)) - { - return hr; - } - } - - return hr; -} - -HRESULT SetDefaultUser(std::wstring_view userName) -{ - // Query the UID of the given user name and configure the distribution - // to use this UID as the default. - const ULONG uid = DistributionInfo::QueryUid(userName); - if (uid == UID_INVALID) - { - return E_INVALIDARG; - } - - // Set the default user as root, so ChangeDefaultUserInWslConf chan make the change - HRESULT hr = g_wslApi.WslConfigureDistribution(0, WSL_DISTRIBUTION_FLAGS_DEFAULT); - if (FAILED(hr)) - { - return hr; - } - - hr = DistributionInfo::ChangeDefaultUserInWslConf(userName); - if (FAILED(hr)) - { - return hr; - } - - hr = g_wslApi.WslConfigureDistribution(uid, WSL_DISTRIBUTION_FLAGS_DEFAULT); - if (FAILED(hr)) - { - return hr; - } - - return hr; -} - -int RetrieveCurrentTheme() -{ - DWORD value = 0; - DWORD size = sizeof value; - - // ReSharper disable once CppTooWideScope - // ReSharper disable once CppTooWideScopeInitStatement - const auto status = RegGetValueW(HKEY_CURRENT_USER, - L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", - L"AppsUseLightTheme", - RRF_RT_DWORD, - nullptr, - &value, - &size - ); - - if (status == ERROR_SUCCESS) - { - return static_cast(value); - } - - return -1; -} - -fire_and_forget SyncIcon(const hstring& iconName) -{ - const hstring nameSuffix = L""; //value == 0 ? L"" : L""; - - const hstring extension = L".png"; - const hstring composedPath = iconName + nameSuffix + extension; - const auto path = Uri(L"ms-appx:///Assets/" + composedPath); - - try - { - const auto iconFile = StorageFile::GetFileFromApplicationUriAsync(path).get(); - - co_await iconFile.CopyAsync(ApplicationData::Current().LocalFolder(), iconName + extension, - NameCollisionOption::FailIfExists); - } - catch (...) - { - } -} - -int RetrieveWindowsVersion(); - -// ReSharper disable once IdentifierTypo -fire_and_forget ShowPengwinUi() -{ - // ReSharper disable once CppTooWideScope - // ReSharper disable once CppTooWideScopeInitStatement - const auto& file = - co_await ApplicationData::Current().LocalFolder().TryGetItemAsync(L"MicrosoftStoreEngagementSDKId.txt"); - - if (! file) - { - // ReSharper disable once StringLiteralTypo - const hstring str = L"pengwinui://"; - - const auto uri = Uri(str); - - co_await Launcher::LaunchUriAsync(uri); - } -} - -// ReSharper disable once IdentifierTypo -int wmain(const int argc, const wchar_t* argv[]) -{ - // Update the title bar of the console window. - SetConsoleTitleW(DistributionInfo::WINDOW_TITLE.c_str()); - - // Initialize a vector of arguments. - std::vector arguments; - for (auto index = 1; index < argc; index += 1) - { - arguments.push_back(argv[index]); - } - - // Ensure that the Windows Subsystem for Linux optional component is installed. - DWORD exitCode = 1; - if (!g_wslApi.WslIsOptionalComponentInstalled()) - { - Helpers::PrintMessage(MSG_MISSING_OPTIONAL_COMPONENT); - if (arguments.empty()) - { - Helpers::PromptForInput(); - } - - return static_cast(exitCode); - } - - // Install the distribution if it is not already. - const auto installOnly = arguments.size() > 0 && arguments[0] == ARG_INSTALL; - auto hr = S_OK; - if (!g_wslApi.WslIsDistributionRegistered()) - { - // If the "--root" option is specified, do not create a user account. - const auto useRoot = installOnly && arguments.size() > 1 && arguments[1] == ARG_INSTALL_ROOT; - hr = InstallDistribution(!useRoot); - if (FAILED(hr)) - { - if (hr == HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS)) - { - Helpers::PrintMessage(MSG_INSTALL_ALREADY_EXISTS); - } - } - else - { - Helpers::PrintMessage(MSG_INSTALL_SUCCESS); - } - - exitCode = SUCCEEDED(hr) ? 0 : 1; - } - - // Parse the command line arguments. - if (SUCCEEDED(hr) && !installOnly) - { - // ReSharper disable once StringLiteralTypo - SyncIcon(L"pengwin"); - SyncIcon(L"background1"); - SyncIcon(L"background2"); - ShowPengwinUi(); - - if (arguments.empty()) - { - hr = g_wslApi.WslLaunchInteractive(L"", false, &exitCode); - - // Check exitCode to see if wsl.exe returned that it could not start the Linux process - // then prompt users for input so they can view the error message. - if (SUCCEEDED(hr) && exitCode == UINT_MAX) - { - Helpers::PromptForInput(); - } - } - else if (arguments[0] == ARG_RUN || - arguments[0] == ARG_RUN_C) - { - std::wstring command; - for (size_t index = 1; index < arguments.size(); index += 1) - { - command += L" "; - command += arguments[index]; - } - - hr = g_wslApi.WslLaunchInteractive(command.c_str(), true, &exitCode); - } - else if (arguments[0] == ARG_CONFIG) - { - hr = E_INVALIDARG; - if (arguments.size() == 3) - { - if (arguments[1] == ARG_CONFIG_DEFAULT_USER) - { - hr = SetDefaultUser(arguments[2]); - } - } - - if (SUCCEEDED(hr)) - { - exitCode = 0; - } - } - else - { - Helpers::PrintMessage(MSG_USAGE); - return static_cast(exitCode); - } - } - - // If an error was encountered, print an error message. - if (FAILED(hr)) - { - if (hr == HRESULT_FROM_WIN32(ERROR_LINUX_SUBSYSTEM_NOT_PRESENT)) - { - Helpers::PrintMessage(MSG_MISSING_OPTIONAL_COMPONENT); - } - else - { - Helpers::PrintErrorMessage(hr); - } - - if (arguments.empty()) - { - Helpers::PromptForInput(); - } - } - - return SUCCEEDED(hr) ? exitCode : 1; -} +// +// Copyright (C) Microsoft. All rights reserved. +// Licensed under the terms described in the LICENSE file in the root of this project. +// + +#include "stdafx.h" + +// Commandline arguments: +constexpr auto ARG_CONFIG = L"config"; +constexpr auto ARG_CONFIG_DEFAULT_USER = L"--default-user"; +constexpr auto ARG_INSTALL = L"install"; +constexpr auto ARG_INSTALL_ROOT = L"--root"; +constexpr auto ARG_RUN = L"run"; +constexpr auto ARG_RUN_C = L"-c"; +constexpr auto ARG_DISTRO = L"--distribution"; +constexpr auto ARG_DISTRO_D = L"-d"; + +#include +#include +#include + + +using namespace winrt; +using namespace Windows::Foundation; +using namespace Windows::System; +using namespace Windows::Storage; + + +// Helper class for calling WSL Functions: +// https://msdn.microsoft.com/en-us/library/windows/desktop/mt826874(v=vs.85).aspx +// ReSharper disable once CppInconsistentNaming +WslApiLoader g_wslApi(DistributionInfo::NAME); + +static HRESULT InstallDistribution(bool createUser); +static HRESULT SetDefaultUser(std::wstring_view userName); + +HRESULT InstallDistribution(const bool createUser) +{ + // Register the distribution. + Helpers::PrintMessage(MSG_STATUS_INSTALLING); + auto hr = g_wslApi.WslRegisterDistribution(); + if (FAILED(hr)) + { + return hr; + } + + // Delete /etc/resolv.conf to allow WSL to generate a version based on Windows networking information. + DWORD exitCode; + hr = g_wslApi.WslLaunchInteractive(L"/bin/rm /etc/resolv.conf", true, &exitCode); + if (FAILED(hr)) + { + return hr; + } + + // Create a user account. + if (createUser) + { + Helpers::PrintMessage(MSG_CREATE_USER_PROMPT); + std::wstring userName; + do + { + userName = Helpers::GetUserInput(MSG_ENTER_USERNAME, 32); + } + while (!DistributionInfo::CreateUser(userName)); + + // Set this user account as the default. + hr = SetDefaultUser(userName); + if (FAILED(hr)) + { + return hr; + } + } + + return hr; +} + +HRESULT SetDefaultUser(std::wstring_view userName) +{ + // Query the UID of the given user name and configure the distribution + // to use this UID as the default. + const ULONG uid = DistributionInfo::QueryUid(userName); + if (uid == UID_INVALID) + { + return E_INVALIDARG; + } + + // Set the default user as root, so ChangeDefaultUserInWslConf chan make the change + HRESULT hr = g_wslApi.WslConfigureDistribution(0, WSL_DISTRIBUTION_FLAGS_DEFAULT); + if (FAILED(hr)) + { + return hr; + } + + hr = DistributionInfo::ChangeDefaultUserInWslConf(userName); + if (FAILED(hr)) + { + return hr; + } + + hr = g_wslApi.WslConfigureDistribution(uid, WSL_DISTRIBUTION_FLAGS_DEFAULT); + if (FAILED(hr)) + { + return hr; + } + + return hr; +} + +int RetrieveCurrentTheme() +{ + DWORD value = 0; + DWORD size = sizeof value; + + // ReSharper disable once CppTooWideScope + // ReSharper disable once CppTooWideScopeInitStatement + const auto status = RegGetValueW(HKEY_CURRENT_USER, + L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", + L"AppsUseLightTheme", + RRF_RT_DWORD, + nullptr, + &value, + &size + ); + + if (status == ERROR_SUCCESS) + { + return static_cast(value); + } + + return -1; +} + +fire_and_forget SyncIcon(const hstring& iconName) +{ + const hstring nameSuffix = L""; //value == 0 ? L"" : L""; + + const hstring extension = L".png"; + const hstring composedPath = iconName + nameSuffix + extension; + const auto path = Uri(L"ms-appx:///Assets/" + composedPath); + + try + { + const auto iconFile = StorageFile::GetFileFromApplicationUriAsync(path).get(); + + co_await iconFile.CopyAsync(ApplicationData::Current().LocalFolder(), iconName + extension, + NameCollisionOption::FailIfExists); + } + catch (...) + { + } +} + +int RetrieveWindowsVersion(); + +// ReSharper disable once IdentifierTypo +fire_and_forget ShowPengwinUi() +{ + // ReSharper disable once CppTooWideScope + // ReSharper disable once CppTooWideScopeInitStatement + const auto& file = + co_await ApplicationData::Current().LocalFolder().TryGetItemAsync(L"MicrosoftStoreEngagementSDKId.txt"); + + if (! file) + { + // ReSharper disable once StringLiteralTypo + const hstring str = L"pengwinui://"; + + const auto uri = Uri(str); + + co_await Launcher::LaunchUriAsync(uri); + } +} + +// ReSharper disable once IdentifierTypo +int wmain(const int argc, const wchar_t* argv[]) +{ + // Update the title bar of the console window. + SetConsoleTitleW(DistributionInfo::WINDOW_TITLE.c_str()); + + // Initialize a vector of arguments. + std::vector arguments; + for (auto index = 1; index < argc; index += 1) + { + arguments.push_back(argv[index]); + } + + // Ensure that the Windows Subsystem for Linux optional component is installed. + DWORD exitCode = 1; + if (!g_wslApi.WslIsOptionalComponentInstalled()) + { + Helpers::PrintMessage(MSG_MISSING_OPTIONAL_COMPONENT); + if (arguments.empty()) + { + Helpers::PromptForInput(); + } + + return static_cast(exitCode); + } + + // Install the distribution if it is not already. + const auto installOnly = arguments.size() > 0 && arguments[0] == ARG_INSTALL; + auto hr = S_OK; + if (!g_wslApi.WslIsDistributionRegistered()) + { + // If the "--root" option is specified, do not create a user account. + const auto useRoot = installOnly && arguments.size() > 1 && arguments[1] == ARG_INSTALL_ROOT; + hr = InstallDistribution(!useRoot); + if (FAILED(hr)) + { + if (hr == HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS)) + { + Helpers::PrintMessage(MSG_INSTALL_ALREADY_EXISTS); + } + } + else + { + Helpers::PrintMessage(MSG_INSTALL_SUCCESS); + } + + exitCode = SUCCEEDED(hr) ? 0 : 1; + } + + // Parse the command line arguments. + if (SUCCEEDED(hr) && !installOnly) + { + // ReSharper disable once StringLiteralTypo + SyncIcon(L"pengwin"); + SyncIcon(L"background1"); + SyncIcon(L"background2"); + ShowPengwinUi(); + + if (arguments.size() >= 2 && (arguments[0] == ARG_DISTRO || + arguments[0] == ARG_DISTRO_D)) + { + g_wslApi.SetDistributionName(arguments[1]); + arguments.erase(arguments.begin(), arguments.begin() + 2); + } + + if (arguments.empty()) + { + hr = g_wslApi.WslLaunchInteractive(L"", false, &exitCode); + + // Check exitCode to see if wsl.exe returned that it could not start the Linux process + // then prompt users for input so they can view the error message. + if (SUCCEEDED(hr) && exitCode == UINT_MAX) + { + Helpers::PromptForInput(); + } + } + else if (arguments[0] == ARG_RUN || + arguments[0] == ARG_RUN_C) + { + std::wstring command; + for (size_t index = 1; index < arguments.size(); index += 1) + { + command += L" "; + command += arguments[index]; + } + + hr = g_wslApi.WslLaunchInteractive(command.c_str(), true, &exitCode); + } + else if (arguments[0] == ARG_CONFIG) + { + hr = E_INVALIDARG; + if (arguments.size() == 3) + { + if (arguments[1] == ARG_CONFIG_DEFAULT_USER) + { + hr = SetDefaultUser(arguments[2]); + } + } + + if (SUCCEEDED(hr)) + { + exitCode = 0; + } + } + else + { + Helpers::PrintMessage(MSG_USAGE, DistributionInfo::WINDOW_TITLE.c_str()); + return static_cast(exitCode); + } + } + + // If an error was encountered, print an error message. + if (FAILED(hr)) + { + if (hr == HRESULT_FROM_WIN32(ERROR_LINUX_SUBSYSTEM_NOT_PRESENT)) + { + Helpers::PrintMessage(MSG_MISSING_OPTIONAL_COMPONENT); + } + else if (hr == HCS_E_HYPERV_NOT_INSTALLED) + { + Helpers::PrintMessage(MSG_ENABLE_VIRTUALIZATION); + } + else + { + Helpers::PrintErrorMessage(hr); + } + + if (arguments.empty()) + { + Helpers::PromptForInput(); + } + } + + return SUCCEEDED(hr) ? exitCode : 1; +} diff --git a/DistroLauncher/DistroLauncher.vcxproj b/DistroLauncher/DistroLauncher.vcxproj index faea5b44..5860de0a 100644 --- a/DistroLauncher/DistroLauncher.vcxproj +++ b/DistroLauncher/DistroLauncher.vcxproj @@ -121,6 +121,7 @@ true stdcpp17 MultiThreaded + Speed Console @@ -141,6 +142,7 @@ true stdcpp17 MultiThreaded + Speed Console @@ -170,9 +172,6 @@ - - - Document @@ -185,6 +184,9 @@ + + + diff --git a/DistroLauncher/DistroLauncher.vcxproj.filters b/DistroLauncher/DistroLauncher.vcxproj.filters index 8ef31573..8c4a6f12 100644 --- a/DistroLauncher/DistroLauncher.vcxproj.filters +++ b/DistroLauncher/DistroLauncher.vcxproj.filters @@ -56,15 +56,15 @@ Resource Files - - - Resource Files - - + + + Resource Files + + \ No newline at end of file diff --git a/DistroLauncher/WslApiLoader.cpp b/DistroLauncher/WslApiLoader.cpp index fbcc4754..c359e3f1 100644 --- a/DistroLauncher/WslApiLoader.cpp +++ b/DistroLauncher/WslApiLoader.cpp @@ -31,12 +31,12 @@ WslApiLoader::~WslApiLoader() BOOL WslApiLoader::WslIsOptionalComponentInstalled() const { - return ((_wslApiDll != nullptr) && - (_isDistributionRegistered != nullptr) && - (_registerDistribution != nullptr) && - (_configureDistribution != nullptr) && - (_launchInteractive != nullptr) && - (_launch != nullptr)); + return _wslApiDll != nullptr && + _isDistributionRegistered != nullptr && + _registerDistribution != nullptr && + _configureDistribution != nullptr && + _launchInteractive != nullptr && + _launch != nullptr; } BOOL WslApiLoader::WslIsDistributionRegistered() const @@ -89,3 +89,8 @@ HRESULT WslApiLoader::WslLaunch(PCWSTR command, BOOL useCurrentWorkingDirectory, return hr; } + +void WslApiLoader::SetDistributionName(const std::wstring_view& distributionName) +{ + _distributionName = std::wstring(distributionName); +} diff --git a/DistroLauncher/WslApiLoader.h b/DistroLauncher/WslApiLoader.h index a51bdcf6..0edb4a8e 100644 --- a/DistroLauncher/WslApiLoader.h +++ b/DistroLauncher/WslApiLoader.h @@ -45,6 +45,8 @@ class WslApiLoader HANDLE stdErr, HANDLE* process) const; + void SetDistributionName(const std::wstring_view& distributionName); + private: std::wstring _distributionName; HMODULE _wslApiDll; diff --git a/DistroLauncher/messages.mc b/DistroLauncher/messages.mc index 8a8c310a..7fd4d6c8 100644 --- a/DistroLauncher/messages.mc +++ b/DistroLauncher/messages.mc @@ -28,12 +28,15 @@ Usage: Launches the user's default shell in the user's home directory. + --distribution, -d + Launches the user's default shell in the user's home directory in the specified distribution. Suitable when you have more than one %1 installation. + install [--root] Install the distribution and do not launch the shell when complete. --root Do not create a user account and leave the default user set to root. - run + run, -c Run the provided command line in the current working directory. If no command line is provided, the default shell is launched. diff --git a/LauncherTests/LauncherTests.vcxproj b/LauncherTests/LauncherTests.vcxproj index 383f8ab2..77af697c 100644 --- a/LauncherTests/LauncherTests.vcxproj +++ b/LauncherTests/LauncherTests.vcxproj @@ -2,14 +2,6 @@ - - Debug - Win32 - - - Release - Win32 - Debug x64 @@ -39,8 +31,6 @@ - Create - Create Create Create @@ -59,21 +49,6 @@ - - - Use - pch.h - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - Level3 - - - true - Console - - Use @@ -89,22 +64,6 @@ Console - - - Use - pch.h - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDLL - Level3 - ProgramDatabase - - - true - Console - true - true - - Use diff --git a/Pengwin/Package.appxmanifest b/Pengwin/Package.appxmanifest index d392cc20..5632ba27 100644 --- a/Pengwin/Package.appxmanifest +++ b/Pengwin/Package.appxmanifest @@ -11,7 +11,7 @@ + Version="22.3.1.0" /> Pengwin diff --git a/Pengwin/Pengwin.wapproj b/Pengwin/Pengwin.wapproj index 43b70cd1..201a3aff 100644 --- a/Pengwin/Pengwin.wapproj +++ b/Pengwin/Pengwin.wapproj @@ -4,14 +4,6 @@ 15.0 - - Debug - x86 - - - Release - x86 - Debug x64 @@ -20,14 +12,6 @@ Release x64 - - Debug - ARM - - - Release - ARM - Debug ARM64 @@ -66,9 +50,6 @@ http://timestamp.comodoca.com/%3f__hstc=116687193.ca0320fdf84fdaebb49c623303fc35cd.1574461157682.1575409935578.1578516608285.3&__hssc=116687193.1.1578516608285&__hsfp=100782785 StoreAndSideload - - Always - Always @@ -84,18 +65,9 @@ Always - - Always - Always - - Always - - - Always - Designer diff --git a/PengwinUI/PengwinUI.csproj b/PengwinUI/PengwinUI.csproj index 7b590e36..61620cf3 100644 --- a/PengwinUI/PengwinUI.csproj +++ b/PengwinUI/PengwinUI.csproj @@ -19,52 +19,6 @@ true false - - true - bin\x86\Debug\ - DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP - ;2008 - full - x86 - false - prompt - true - - - bin\x86\Release\ - TRACE;NETFX_CORE;WINDOWS_UWP - true - ;2008 - pdbonly - x86 - false - prompt - true - true - - - true - bin\ARM\Debug\ - DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP - ;2008 - full - ARM - false - prompt - true - - - bin\ARM\Release\ - TRACE;NETFX_CORE;WINDOWS_UWP - true - ;2008 - pdbonly - ARM - false - prompt - true - true - true bin\ARM64\Debug\ diff --git a/PengwinW/PengwinW.cpp b/PengwinW/PengwinW.cpp index bb8c04a9..ddc44d49 100644 --- a/PengwinW/PengwinW.cpp +++ b/PengwinW/PengwinW.cpp @@ -3,23 +3,11 @@ #include "framework.h" #include "PengwinW.h" - +#include #include -#define MAX_LOADSTRING 100 - using namespace std; -// Global Variables: -HINSTANCE hInst; // current instance -WCHAR szTitle[MAX_LOADSTRING]; // The title bar text -WCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name - -// Forward declarations of functions included in this code module: -ATOM MyRegisterClass(HINSTANCE hInstance); -LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); -INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); - void RunProcess(LPWSTR cmdline) { // additional information @@ -57,13 +45,6 @@ void RunProcess(LPWSTR cmdline) CloseHandle(pi.hThread); } -wstring GetBasePath(const std::wstring& path) -{ - auto found = path.find_last_of(L"/\\"); - found = path.find_last_of(L"/\\", found - 1); - return path.substr(0, found + 1); -} - int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, @@ -71,115 +52,18 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance, { wchar_t buff[1024]; - MessageBoxW(nullptr, lpCmdLine, L"Hola", MB_OK); - GetModuleFileNameW(nullptr, buff, _countof(buff)); - std::wstring path(buff); - path = GetBasePath(path); - path.append(L"DistroLauncher\\pengwin.exe "); - path.append(lpCmdLine); + PathCchRemoveFileSpec(buff, _countof(buff)); + PathCchRemoveFileSpec(buff, _countof(buff)); + PathCchAppendEx(buff, _countof(buff), L"DistroLauncher", PATHCCH_ALLOW_LONG_PATHS); + PathCchAppendEx(buff, _countof(buff), L"pengwin.exe", PATHCCH_ALLOW_LONG_PATHS); - _swprintf_p(buff, _countof(buff), - path.c_str()); + wcscat_s(buff, _countof(buff), L" "); + wcscat_s(buff, _countof(buff), lpCmdLine); RunProcess(buff); return 0; } - - -// -// FUNCTION: MyRegisterClass() -// -// PURPOSE: Registers the window class. -// -ATOM MyRegisterClass(HINSTANCE hInstance) -{ - WNDCLASSEXW wcex; - - wcex.cbSize = sizeof(WNDCLASSEX); - - wcex.style = CS_HREDRAW | CS_VREDRAW; - wcex.lpfnWndProc = WndProc; - wcex.cbClsExtra = 0; - wcex.cbWndExtra = 0; - wcex.hInstance = hInstance; - wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_PENGWINW)); - wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); - wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); - wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_PENGWINW); - wcex.lpszClassName = szWindowClass; - wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); - - return RegisterClassExW(&wcex); -} - -// -// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM) -// -// PURPOSE: Processes messages for the main window. -// -// WM_COMMAND - process the application menu -// WM_PAINT - Paint the main window -// WM_DESTROY - post a quit message and return -// -// -LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - switch (message) - { - case WM_COMMAND: - { - const int wmId = LOWORD(wParam); - // Parse the menu selections: - switch (wmId) - { - case IDM_ABOUT: - DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); - break; - case IDM_EXIT: - DestroyWindow(hWnd); - break; - default: - return DefWindowProc(hWnd, message, wParam, lParam); - } - } - break; - case WM_PAINT: - { - PAINTSTRUCT ps; - HDC hdc = BeginPaint(hWnd, &ps); - // TODO: Add any drawing code that uses hdc here... - EndPaint(hWnd, &ps); - } - break; - case WM_DESTROY: - PostQuitMessage(0); - break; - default: - return DefWindowProc(hWnd, message, wParam, lParam); - } - return 0; -} - -// Message handler for about box. -INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) -{ - UNREFERENCED_PARAMETER(lParam); - switch (message) - { - case WM_INITDIALOG: - return (INT_PTR)TRUE; - - case WM_COMMAND: - if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) - { - EndDialog(hDlg, LOWORD(wParam)); - return (INT_PTR)TRUE; - } - break; - } - return (INT_PTR)FALSE; -} diff --git a/PengwinW/PengwinW.ico b/PengwinW/PengwinW.ico index b3ec03bd..569f5050 100644 Binary files a/PengwinW/PengwinW.ico and b/PengwinW/PengwinW.ico differ diff --git a/PengwinW/PengwinW.rc b/PengwinW/PengwinW.rc index f3a49acc..e37587cd 100644 Binary files a/PengwinW/PengwinW.rc and b/PengwinW/PengwinW.rc differ diff --git a/PengwinW/PengwinW.vcxproj b/PengwinW/PengwinW.vcxproj index 299f79c5..e5a2429b 100644 --- a/PengwinW/PengwinW.vcxproj +++ b/PengwinW/PengwinW.vcxproj @@ -1,13 +1,13 @@ - + Debug - Win32 + ARM64 - + Release - Win32 + ARM64 Debug @@ -26,26 +26,26 @@ 10.0 - + Application true v143 Unicode - + Application - false + true v143 - true Unicode - + Application - true + false v143 + true Unicode - + Application false v143 @@ -57,72 +57,76 @@ - + - + - + - + - + true - - false - - + true false - + + false + + Level3 true - WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + _DEBUG;_WINDOWS;%(PreprocessorDefinitions) true Windows true + pathcch.lib;Shlwapi.lib;%(AdditionalDependencies) - + Level3 - true - true true - WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + _DEBUG;_WINDOWS;%(PreprocessorDefinitions) true Windows - true - true true + pathcch.lib;Shlwapi.lib;%(AdditionalDependencies) - + Level3 + true + true true - _DEBUG;_WINDOWS;%(PreprocessorDefinitions) + NDEBUG;_WINDOWS;%(PreprocessorDefinitions) true + Speed Windows + true + true true + pathcch.lib;Shlwapi.lib;%(AdditionalDependencies) - + Level3 true @@ -130,12 +134,14 @@ true NDEBUG;_WINDOWS;%(PreprocessorDefinitions) true + Speed Windows true true true + pathcch.lib;Shlwapi.lib;%(AdditionalDependencies) @@ -152,7 +158,6 @@ - diff --git a/PengwinW/PengwinW.vcxproj.filters b/PengwinW/PengwinW.vcxproj.filters index 8a7e32de..8d450c15 100644 --- a/PengwinW/PengwinW.vcxproj.filters +++ b/PengwinW/PengwinW.vcxproj.filters @@ -39,9 +39,6 @@ - - Resource Files - Resource Files diff --git a/PengwinW/Resource.h b/PengwinW/Resource.h index cf5069d8..2628a2fb 100644 --- a/PengwinW/Resource.h +++ b/PengwinW/Resource.h @@ -1,30 +1,24 @@ //{{NO_DEPENDENCIES}} // Microsoft Visual C++ generated include file. // Used by PengwinW.rc +// +#define IDC_MYICON 2 +#define IDD_PENGWINW_DIALOG 102 +#define IDS_APP_TITLE 103 +#define IDI_PENGWINW 107 +#define IDI_SMALL 108 +#define IDC_PENGWINW 109 +#define IDR_MAINFRAME 128 +#define IDC_STATIC -1 -#define IDS_APP_TITLE 103 - -#define IDR_MAINFRAME 128 -#define IDD_PENGWINW_DIALOG 102 -#define IDD_ABOUTBOX 103 -#define IDM_ABOUT 104 -#define IDM_EXIT 105 -#define IDI_PENGWINW 107 -#define IDI_SMALL 108 -#define IDC_PENGWINW 109 -#define IDC_MYICON 2 -#ifndef IDC_STATIC -#define IDC_STATIC -1 -#endif // Next default values for new objects -// +// #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS - -#define _APS_NO_MFC 130 -#define _APS_NEXT_RESOURCE_VALUE 129 -#define _APS_NEXT_COMMAND_VALUE 32771 -#define _APS_NEXT_CONTROL_VALUE 1000 -#define _APS_NEXT_SYMED_VALUE 110 +#define _APS_NO_MFC 1 +#define _APS_NEXT_RESOURCE_VALUE 129 +#define _APS_NEXT_COMMAND_VALUE 32771 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 110 #endif #endif diff --git a/PengwinW/small.ico b/PengwinW/small.ico deleted file mode 100644 index b3ec03bd..00000000 Binary files a/PengwinW/small.ico and /dev/null differ