├── .github └── FUNDING.yml ├── Screenshots └── Screenshot.PNG ├── DistroLauncher ├── images │ ├── icon.ico │ └── icon.png ├── ChecksumVerify.h ├── targetver.h ├── DistributionInfo.h ├── DistroLauncher.h ├── stdafx.cpp ├── resource.h ├── Helpers.h ├── application.manifest ├── DownloadUserland.h ├── stdafx.h ├── DistroLauncher.rc ├── DistroSpecial.h ├── WslApiLoader.h ├── messages.mc ├── WslApiLoader.cpp ├── DistributionInfo.cpp ├── DistroLauncher.vcxproj.filters ├── Helpers.cpp ├── ChecksumVerify.cpp ├── DownloadUserland.cpp ├── DistroLauncher.cpp └── DistroLauncher.vcxproj ├── DistroLauncher-Appx ├── Assets │ ├── LargeTile.scale-100.png │ ├── LargeTile.scale-125.png │ ├── LargeTile.scale-150.png │ ├── LargeTile.scale-200.png │ ├── LargeTile.scale-400.png │ ├── SmallTile.scale-100.png │ ├── SmallTile.scale-125.png │ ├── SmallTile.scale-150.png │ ├── SmallTile.scale-200.png │ ├── SmallTile.scale-400.png │ ├── StoreLogo.scale-100.png │ ├── StoreLogo.scale-125.png │ ├── StoreLogo.scale-150.png │ ├── StoreLogo.scale-200.png │ ├── StoreLogo.scale-400.png │ ├── SplashScreen.scale-100.png │ ├── SplashScreen.scale-125.png │ ├── SplashScreen.scale-150.png │ ├── SplashScreen.scale-200.png │ ├── SplashScreen.scale-400.png │ ├── Square150x150Logo.scale-100.png │ ├── Square150x150Logo.scale-125.png │ ├── Square150x150Logo.scale-150.png │ ├── Square150x150Logo.scale-200.png │ ├── Square150x150Logo.scale-400.png │ ├── Square44x44Logo.scale-100.png │ ├── Square44x44Logo.scale-125.png │ ├── Square44x44Logo.scale-150.png │ ├── Square44x44Logo.scale-200.png │ ├── Square44x44Logo.scale-400.png │ ├── Wide310x150Logo.scale-100.png │ ├── Wide310x150Logo.scale-125.png │ ├── Wide310x150Logo.scale-150.png │ ├── Wide310x150Logo.scale-200.png │ ├── Wide310x150Logo.scale-400.png │ ├── Square44x44Logo.targetsize-16.png │ ├── Square44x44Logo.targetsize-24.png │ ├── Square44x44Logo.targetsize-32.png │ ├── Square44x44Logo.targetsize-48.png │ ├── Square44x44Logo.targetsize-256.png │ ├── Square44x44Logo.altform-unplated_targetsize-16.png │ ├── Square44x44Logo.altform-unplated_targetsize-256.png │ ├── Square44x44Logo.altform-unplated_targetsize-32.png │ ├── Square44x44Logo.altform-unplated_targetsize-48.png │ └── Square44x44Logo.targetsize-24_altform-unplated.png ├── Alpine.appxmanifest ├── DistroLauncher-Appx.vcxproj.filters ├── DistroLauncher-Appx.vcxproj └── Package.xml ├── LICENSE ├── DistroLauncher.sln ├── .gitignore └── README.md /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | --- 2 | custom: "https://wiki.alpinelinux.org/wiki/Alpine_Linux:Developers" 3 | github: agowa338 4 | -------------------------------------------------------------------------------- /Screenshots/Screenshot.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agowa/WSL-DistroLauncher-Alpine/HEAD/Screenshots/Screenshot.PNG -------------------------------------------------------------------------------- /DistroLauncher/images/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agowa/WSL-DistroLauncher-Alpine/HEAD/DistroLauncher/images/icon.ico -------------------------------------------------------------------------------- /DistroLauncher/images/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agowa/WSL-DistroLauncher-Alpine/HEAD/DistroLauncher/images/icon.png -------------------------------------------------------------------------------- /DistroLauncher-Appx/Assets/LargeTile.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agowa/WSL-DistroLauncher-Alpine/HEAD/DistroLauncher-Appx/Assets/LargeTile.scale-100.png -------------------------------------------------------------------------------- /DistroLauncher-Appx/Assets/LargeTile.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agowa/WSL-DistroLauncher-Alpine/HEAD/DistroLauncher-Appx/Assets/LargeTile.scale-125.png -------------------------------------------------------------------------------- /DistroLauncher-Appx/Assets/LargeTile.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agowa/WSL-DistroLauncher-Alpine/HEAD/DistroLauncher-Appx/Assets/LargeTile.scale-150.png -------------------------------------------------------------------------------- /DistroLauncher-Appx/Assets/LargeTile.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agowa/WSL-DistroLauncher-Alpine/HEAD/DistroLauncher-Appx/Assets/LargeTile.scale-200.png -------------------------------------------------------------------------------- /DistroLauncher-Appx/Assets/LargeTile.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agowa/WSL-DistroLauncher-Alpine/HEAD/DistroLauncher-Appx/Assets/LargeTile.scale-400.png -------------------------------------------------------------------------------- /DistroLauncher-Appx/Assets/SmallTile.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agowa/WSL-DistroLauncher-Alpine/HEAD/DistroLauncher-Appx/Assets/SmallTile.scale-100.png -------------------------------------------------------------------------------- /DistroLauncher-Appx/Assets/SmallTile.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agowa/WSL-DistroLauncher-Alpine/HEAD/DistroLauncher-Appx/Assets/SmallTile.scale-125.png -------------------------------------------------------------------------------- /DistroLauncher-Appx/Assets/SmallTile.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agowa/WSL-DistroLauncher-Alpine/HEAD/DistroLauncher-Appx/Assets/SmallTile.scale-150.png -------------------------------------------------------------------------------- /DistroLauncher-Appx/Assets/SmallTile.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agowa/WSL-DistroLauncher-Alpine/HEAD/DistroLauncher-Appx/Assets/SmallTile.scale-200.png -------------------------------------------------------------------------------- /DistroLauncher-Appx/Assets/SmallTile.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agowa/WSL-DistroLauncher-Alpine/HEAD/DistroLauncher-Appx/Assets/SmallTile.scale-400.png -------------------------------------------------------------------------------- /DistroLauncher-Appx/Assets/StoreLogo.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agowa/WSL-DistroLauncher-Alpine/HEAD/DistroLauncher-Appx/Assets/StoreLogo.scale-100.png -------------------------------------------------------------------------------- /DistroLauncher-Appx/Assets/StoreLogo.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agowa/WSL-DistroLauncher-Alpine/HEAD/DistroLauncher-Appx/Assets/StoreLogo.scale-125.png -------------------------------------------------------------------------------- /DistroLauncher-Appx/Assets/StoreLogo.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agowa/WSL-DistroLauncher-Alpine/HEAD/DistroLauncher-Appx/Assets/StoreLogo.scale-150.png -------------------------------------------------------------------------------- /DistroLauncher-Appx/Assets/StoreLogo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agowa/WSL-DistroLauncher-Alpine/HEAD/DistroLauncher-Appx/Assets/StoreLogo.scale-200.png -------------------------------------------------------------------------------- /DistroLauncher-Appx/Assets/StoreLogo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agowa/WSL-DistroLauncher-Alpine/HEAD/DistroLauncher-Appx/Assets/StoreLogo.scale-400.png -------------------------------------------------------------------------------- /DistroLauncher-Appx/Assets/SplashScreen.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agowa/WSL-DistroLauncher-Alpine/HEAD/DistroLauncher-Appx/Assets/SplashScreen.scale-100.png -------------------------------------------------------------------------------- /DistroLauncher-Appx/Assets/SplashScreen.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agowa/WSL-DistroLauncher-Alpine/HEAD/DistroLauncher-Appx/Assets/SplashScreen.scale-125.png -------------------------------------------------------------------------------- /DistroLauncher-Appx/Assets/SplashScreen.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agowa/WSL-DistroLauncher-Alpine/HEAD/DistroLauncher-Appx/Assets/SplashScreen.scale-150.png -------------------------------------------------------------------------------- /DistroLauncher-Appx/Assets/SplashScreen.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agowa/WSL-DistroLauncher-Alpine/HEAD/DistroLauncher-Appx/Assets/SplashScreen.scale-200.png -------------------------------------------------------------------------------- /DistroLauncher-Appx/Assets/SplashScreen.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agowa/WSL-DistroLauncher-Alpine/HEAD/DistroLauncher-Appx/Assets/SplashScreen.scale-400.png -------------------------------------------------------------------------------- /DistroLauncher-Appx/Assets/Square150x150Logo.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agowa/WSL-DistroLauncher-Alpine/HEAD/DistroLauncher-Appx/Assets/Square150x150Logo.scale-100.png -------------------------------------------------------------------------------- /DistroLauncher-Appx/Assets/Square150x150Logo.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agowa/WSL-DistroLauncher-Alpine/HEAD/DistroLauncher-Appx/Assets/Square150x150Logo.scale-125.png -------------------------------------------------------------------------------- /DistroLauncher-Appx/Assets/Square150x150Logo.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agowa/WSL-DistroLauncher-Alpine/HEAD/DistroLauncher-Appx/Assets/Square150x150Logo.scale-150.png -------------------------------------------------------------------------------- /DistroLauncher-Appx/Assets/Square150x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agowa/WSL-DistroLauncher-Alpine/HEAD/DistroLauncher-Appx/Assets/Square150x150Logo.scale-200.png -------------------------------------------------------------------------------- /DistroLauncher-Appx/Assets/Square150x150Logo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agowa/WSL-DistroLauncher-Alpine/HEAD/DistroLauncher-Appx/Assets/Square150x150Logo.scale-400.png -------------------------------------------------------------------------------- /DistroLauncher-Appx/Assets/Square44x44Logo.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agowa/WSL-DistroLauncher-Alpine/HEAD/DistroLauncher-Appx/Assets/Square44x44Logo.scale-100.png -------------------------------------------------------------------------------- /DistroLauncher-Appx/Assets/Square44x44Logo.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agowa/WSL-DistroLauncher-Alpine/HEAD/DistroLauncher-Appx/Assets/Square44x44Logo.scale-125.png -------------------------------------------------------------------------------- /DistroLauncher-Appx/Assets/Square44x44Logo.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agowa/WSL-DistroLauncher-Alpine/HEAD/DistroLauncher-Appx/Assets/Square44x44Logo.scale-150.png -------------------------------------------------------------------------------- /DistroLauncher-Appx/Assets/Square44x44Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agowa/WSL-DistroLauncher-Alpine/HEAD/DistroLauncher-Appx/Assets/Square44x44Logo.scale-200.png -------------------------------------------------------------------------------- /DistroLauncher-Appx/Assets/Square44x44Logo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agowa/WSL-DistroLauncher-Alpine/HEAD/DistroLauncher-Appx/Assets/Square44x44Logo.scale-400.png -------------------------------------------------------------------------------- /DistroLauncher-Appx/Assets/Wide310x150Logo.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agowa/WSL-DistroLauncher-Alpine/HEAD/DistroLauncher-Appx/Assets/Wide310x150Logo.scale-100.png -------------------------------------------------------------------------------- /DistroLauncher-Appx/Assets/Wide310x150Logo.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agowa/WSL-DistroLauncher-Alpine/HEAD/DistroLauncher-Appx/Assets/Wide310x150Logo.scale-125.png -------------------------------------------------------------------------------- /DistroLauncher-Appx/Assets/Wide310x150Logo.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agowa/WSL-DistroLauncher-Alpine/HEAD/DistroLauncher-Appx/Assets/Wide310x150Logo.scale-150.png -------------------------------------------------------------------------------- /DistroLauncher-Appx/Assets/Wide310x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agowa/WSL-DistroLauncher-Alpine/HEAD/DistroLauncher-Appx/Assets/Wide310x150Logo.scale-200.png -------------------------------------------------------------------------------- /DistroLauncher-Appx/Assets/Wide310x150Logo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agowa/WSL-DistroLauncher-Alpine/HEAD/DistroLauncher-Appx/Assets/Wide310x150Logo.scale-400.png -------------------------------------------------------------------------------- /DistroLauncher-Appx/Assets/Square44x44Logo.targetsize-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agowa/WSL-DistroLauncher-Alpine/HEAD/DistroLauncher-Appx/Assets/Square44x44Logo.targetsize-16.png -------------------------------------------------------------------------------- /DistroLauncher-Appx/Assets/Square44x44Logo.targetsize-24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agowa/WSL-DistroLauncher-Alpine/HEAD/DistroLauncher-Appx/Assets/Square44x44Logo.targetsize-24.png -------------------------------------------------------------------------------- /DistroLauncher-Appx/Assets/Square44x44Logo.targetsize-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agowa/WSL-DistroLauncher-Alpine/HEAD/DistroLauncher-Appx/Assets/Square44x44Logo.targetsize-32.png -------------------------------------------------------------------------------- /DistroLauncher-Appx/Assets/Square44x44Logo.targetsize-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agowa/WSL-DistroLauncher-Alpine/HEAD/DistroLauncher-Appx/Assets/Square44x44Logo.targetsize-48.png -------------------------------------------------------------------------------- /DistroLauncher-Appx/Assets/Square44x44Logo.targetsize-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agowa/WSL-DistroLauncher-Alpine/HEAD/DistroLauncher-Appx/Assets/Square44x44Logo.targetsize-256.png -------------------------------------------------------------------------------- /DistroLauncher-Appx/Assets/Square44x44Logo.altform-unplated_targetsize-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agowa/WSL-DistroLauncher-Alpine/HEAD/DistroLauncher-Appx/Assets/Square44x44Logo.altform-unplated_targetsize-16.png -------------------------------------------------------------------------------- /DistroLauncher-Appx/Assets/Square44x44Logo.altform-unplated_targetsize-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agowa/WSL-DistroLauncher-Alpine/HEAD/DistroLauncher-Appx/Assets/Square44x44Logo.altform-unplated_targetsize-256.png -------------------------------------------------------------------------------- /DistroLauncher-Appx/Assets/Square44x44Logo.altform-unplated_targetsize-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agowa/WSL-DistroLauncher-Alpine/HEAD/DistroLauncher-Appx/Assets/Square44x44Logo.altform-unplated_targetsize-32.png -------------------------------------------------------------------------------- /DistroLauncher-Appx/Assets/Square44x44Logo.altform-unplated_targetsize-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agowa/WSL-DistroLauncher-Alpine/HEAD/DistroLauncher-Appx/Assets/Square44x44Logo.altform-unplated_targetsize-48.png -------------------------------------------------------------------------------- /DistroLauncher-Appx/Assets/Square44x44Logo.targetsize-24_altform-unplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agowa/WSL-DistroLauncher-Alpine/HEAD/DistroLauncher-Appx/Assets/Square44x44Logo.targetsize-24_altform-unplated.png -------------------------------------------------------------------------------- /DistroLauncher/ChecksumVerify.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #pragma comment(lib, "crypt32.lib") 3 | 4 | namespace ChecksumVerify 5 | { 6 | bool Verify(std::wstring path, std::wstring sha256hash); 7 | std::string GetSHA256(std::wstring path); 8 | } 9 | -------------------------------------------------------------------------------- /DistroLauncher/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include 9 | -------------------------------------------------------------------------------- /DistroLauncher/DistributionInfo.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) Microsoft. All rights reserved. 3 | // Licensed under the terms described in the LICENSE file in the root of this project. 4 | // 5 | 6 | #pragma once 7 | 8 | namespace DistributionInfo 9 | { 10 | // Create and configure a user account. 11 | bool CreateUser(std::wstring_view userName); 12 | 13 | // Query the UID of the user account. 14 | ULONG QueryUid(std::wstring_view userName); 15 | } -------------------------------------------------------------------------------- /DistroLauncher/DistroLauncher.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Commandline arguments: 4 | #define ARG_CONFIG L"config" 5 | #define ARG_CONFIG_DEFAULT_USER L"--default-user" 6 | #define ARG_INSTALL L"install" 7 | #define ARG_INSTALL_ROOT L"--root" 8 | #define ARG_RUN L"run" 9 | #define ARG_RUN_C L"-c" 10 | 11 | static HRESULT InstallDistribution(bool createUser, PCWSTR tarGzFilename); 12 | static HRESULT SetDefaultUser(std::wstring_view userName); 13 | -------------------------------------------------------------------------------- /DistroLauncher/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) Microsoft. All rights reserved. 3 | // Licensed under the terms described in the LICENSE file in the root of this project. 4 | // 5 | // stdafx.cpp : source file that includes just the standard includes 6 | // DistroInstaller.pch will be the pre-compiled header 7 | // stdafx.obj will contain the pre-compiled type information 8 | // 9 | 10 | #include "stdafx.h" 11 | 12 | // Reference any additional headers you need in stdafx.h and not in this file. 13 | 14 | -------------------------------------------------------------------------------- /DistroLauncher/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by DistroInstaller.rc 4 | // 5 | #define IDI_ICON1 101 6 | 7 | // Next default values for new objects 8 | // 9 | #ifdef APSTUDIO_INVOKED 10 | #ifndef APSTUDIO_READONLY_SYMBOLS 11 | #define _APS_NEXT_RESOURCE_VALUE 103 12 | #define _APS_NEXT_COMMAND_VALUE 40001 13 | #define _APS_NEXT_CONTROL_VALUE 1001 14 | #define _APS_NEXT_SYMED_VALUE 101 15 | #endif 16 | #endif 17 | -------------------------------------------------------------------------------- /DistroLauncher/Helpers.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) Microsoft. All rights reserved. 3 | // Licensed under the terms described in the LICENSE file in the root of this project. 4 | // 5 | 6 | #pragma once 7 | 8 | #define UID_INVALID ((ULONG)-1) 9 | 10 | namespace Helpers 11 | { 12 | std::wstring GetUserInput(DWORD promptMsg, DWORD maxCharacters); 13 | void PrintErrorMessage(HRESULT hr); 14 | HRESULT PrintMessage(DWORD messageId, ...); 15 | void PromptForInput(); 16 | std::wstring CreateTemporaryDirectory(); 17 | void SetWorkingDirectory(std::wstring newPath); 18 | } -------------------------------------------------------------------------------- /DistroLauncher/application.manifest: -------------------------------------------------------------------------------- 1 | 2 | 6 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /DistroLauncher/DownloadUserland.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // 3 | //void LoadBar(unsigned curr_val, unsigned max_val, unsigned bar_width = 20); 4 | HRESULT DownloadUserland(); 5 | //class CallbackHandler : public IBindStatusCallback { 6 | //private: 7 | // int m_percentLast; 8 | //public: 9 | // CallbackHandler() : m_percentLast(0) {}; 10 | // HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject); 11 | // ULONG STDMETHODCALLTYPE AddRef(); 12 | // ULONG STDMETHODCALLTYPE Release(); 13 | // HRESULT STDMETHODCALLTYPE OnStartBinding(DWORD /*dwReserved*/, IBinding* /*pib*/); 14 | // HRESULT STDMETHODCALLTYPE GetPriority(LONG* /*pnPriority*/); 15 | // HRESULT STDMETHODCALLTYPE OnLowResource(DWORD /*reserved*/); 16 | // HRESULT STDMETHODCALLTYPE OnProgress(ULONG ulProgress, ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR /*szStatusText*/); 17 | // HRESULT STDMETHODCALLTYPE OnStopBinding(HRESULT /*hresult*/, LPCWSTR /*szError*/); 18 | // HRESULT STDMETHODCALLTYPE GetBindInfo(DWORD* /*grfBINDF*/, BINDINFO* /*pbindinfo*/); 19 | // HRESULT STDMETHODCALLTYPE OnDataAvailable(DWORD /*grfBSCF*/, DWORD /*dwSize*/, FORMATETC* /*pformatetc*/, STGMEDIUM* /*pstgmed*/); 20 | // HRESULT STDMETHODCALLTYPE OnObjectAvailable(REFIID /*riid*/, IUnknown* /*punk*/); 21 | //}; 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 agowa338 4 | Copyright (c) Microsoft Corporation. All rights reserved. 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE 23 | -------------------------------------------------------------------------------- /DistroLauncher/stdafx.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) Microsoft. All rights reserved. 3 | // Licensed under the terms described in the LICENSE file in the root of this project. 4 | // 5 | // stdafx.h : include file for standard system include files, 6 | // or project specific include files that are used frequently, but 7 | // are changed infrequently 8 | // 9 | 10 | #pragma once 11 | 12 | #ifndef STDAFX_HEADER 13 | #define STDAFX_HEADER 14 | 15 | #include "targetver.h" 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include "WslApiLoader.h" 42 | #include "Helpers.h" 43 | #include "DistributionInfo.h" 44 | #include "DistroLauncher.h" 45 | #include "DistroSpecial.h" 46 | #include "DownloadUserland.h" 47 | #include "ChecksumVerify.h" 48 | #ifdef _UNICODE 49 | #define tcout wcout 50 | #else 51 | #define tcout cout 52 | #endif 53 | 54 | // Message strings compiled from .MC file. 55 | #include "messages.h" 56 | 57 | namespace fs = std::filesystem; 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /DistroLauncher/DistroLauncher.rc: -------------------------------------------------------------------------------- 1 | // Microsoft Visual C++ generated resource script. 2 | // 3 | #include "resource.h" 4 | 5 | #define APSTUDIO_READONLY_SYMBOLS 6 | ///////////////////////////////////////////////////////////////////////////// 7 | // 8 | // Generated from the TEXTINCLUDE 2 resource. 9 | // 10 | #include "winres.h" 11 | 12 | ///////////////////////////////////////////////////////////////////////////// 13 | #undef APSTUDIO_READONLY_SYMBOLS 14 | 15 | ///////////////////////////////////////////////////////////////////////////// 16 | // English (United States) resources 17 | 18 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) 19 | LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US 20 | 21 | #ifdef APSTUDIO_INVOKED 22 | ///////////////////////////////////////////////////////////////////////////// 23 | // 24 | // TEXTINCLUDE 25 | // 26 | 27 | 1 TEXTINCLUDE 28 | BEGIN 29 | "resource.h\0" 30 | END 31 | 32 | 2 TEXTINCLUDE 33 | BEGIN 34 | "#include ""winres.h""\r\n" 35 | "\0" 36 | END 37 | 38 | 3 TEXTINCLUDE 39 | BEGIN 40 | "\r\n" 41 | "\0" 42 | END 43 | 44 | #endif // APSTUDIO_INVOKED 45 | 46 | 47 | ///////////////////////////////////////////////////////////////////////////// 48 | // 49 | // Icon 50 | // 51 | 52 | // Icon with lowest ID value placed first to ensure application icon 53 | // remains consistent on all systems. 54 | IDI_ICON1 ICON ".\images\icon.ico" 55 | 56 | #endif // English (United States) resources 57 | ///////////////////////////////////////////////////////////////////////////// 58 | 59 | 60 | 61 | #ifndef APSTUDIO_INVOKED 62 | ///////////////////////////////////////////////////////////////////////////// 63 | // 64 | // Generated from the TEXTINCLUDE 3 resource. 65 | // 66 | 67 | 68 | ///////////////////////////////////////////////////////////////////////////// 69 | #endif // not APSTUDIO_INVOKED 70 | 71 | #include "messages.rc" 72 | 73 | -------------------------------------------------------------------------------- /DistroLauncher.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27130.2036 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "launcher", "DistroLauncher\DistroLauncher.vcxproj", "{BA627106-E5F7-46EE-B8D7-2D5A760F2FB2}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DistroLauncher-Appx", "DistroLauncher-Appx\DistroLauncher-Appx.vcxproj", "{F63472F9-D0A0-412E-AA3D-A4E822970486}" 9 | ProjectSection(ProjectDependencies) = postProject 10 | {BA627106-E5F7-46EE-B8D7-2D5A760F2FB2} = {BA627106-E5F7-46EE-B8D7-2D5A760F2FB2} 11 | EndProjectSection 12 | EndProject 13 | Global 14 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 15 | Debug|x64 = Debug|x64 16 | Release|x64 = Release|x64 17 | EndGlobalSection 18 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 19 | {BA627106-E5F7-46EE-B8D7-2D5A760F2FB2}.Debug|x64.ActiveCfg = Debug|x64 20 | {BA627106-E5F7-46EE-B8D7-2D5A760F2FB2}.Debug|x64.Build.0 = Debug|x64 21 | {BA627106-E5F7-46EE-B8D7-2D5A760F2FB2}.Release|x64.ActiveCfg = Release|x64 22 | {BA627106-E5F7-46EE-B8D7-2D5A760F2FB2}.Release|x64.Build.0 = Release|x64 23 | {F63472F9-D0A0-412E-AA3D-A4E822970486}.Debug|x64.ActiveCfg = Debug|x64 24 | {F63472F9-D0A0-412E-AA3D-A4E822970486}.Debug|x64.Build.0 = Debug|x64 25 | {F63472F9-D0A0-412E-AA3D-A4E822970486}.Debug|x64.Deploy.0 = Debug|x64 26 | {F63472F9-D0A0-412E-AA3D-A4E822970486}.Release|x64.ActiveCfg = Release|x64 27 | {F63472F9-D0A0-412E-AA3D-A4E822970486}.Release|x64.Build.0 = Release|x64 28 | {F63472F9-D0A0-412E-AA3D-A4E822970486}.Release|x64.Deploy.0 = Release|x64 29 | EndGlobalSection 30 | GlobalSection(SolutionProperties) = preSolution 31 | HideSolutionNode = FALSE 32 | EndGlobalSection 33 | GlobalSection(ExtensibilityGlobals) = postSolution 34 | SolutionGuid = {1CBEEAE2-D963-465A-A538-A30F8D615037} 35 | EndGlobalSection 36 | EndGlobal 37 | -------------------------------------------------------------------------------- /DistroLauncher/DistroSpecial.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace DistroSpecial 4 | { 5 | // The name of the distribution. This will be displayed to the user via 6 | // wslconfig.exe and in other places. It must conform to the following 7 | // regular expression: ^[a-zA-Z0-9._-]+$ 8 | // 9 | // WARNING: This value must not change between versions of your app, 10 | // otherwise users upgrading from older versions will see launch failures. 11 | const std::wstring Name = L"Alpine"; 12 | 13 | // The title bar for the console window while the distribution is installing. 14 | const std::wstring WindowTitle = L"Alpine"; 15 | 16 | // Command Lines 17 | const std::wstring commandLinePreAddUser[] = { 18 | L"/bin/chmod 755 /", // Alpine tar.gz image has wrong permissions on the "/" aka. root folder, this prevents su from working, so only "install --root" is working. 19 | L"/sbin/apk --no-cache add shadow", // Provides /usr/sbin/usermod 20 | L"/sbin/apk --no-cache add alpine-base", // Make sure files like /etc/alpine-release are properly updated and common tools like lbu are present 21 | L"/bin/sed -i 's/^export PATH/#export PATH/' /etc/profile" // Remove the explicitly exported path variable, as wsl is preinitializing path for us, so that windows applications can also be called from within wsl. 22 | }; 23 | const std::wstring commandLineAddUser = L"/usr/sbin/adduser -g '' -D "; 24 | const bool askForRootPassword = true; 25 | // const std::wstring commandLineAddUserToGroups = L"/usr/sbin/usermod -aG adm,cdrom,sudo,dip,plugdev "; 26 | const std::wstring commandLineAddUserToGroups = L"/usr/sbin/usermod -aG adm,floppy,cdrom,tape,wheel,ping "; 27 | const std::wstring commandLineDeleteUSer = L"/usr/sbin/deluser --remove-home "; 28 | const std::wstring commandLineQueryUID = L"/usr/bin/id -u "; 29 | const PCWSTR commandLineDeleteResolvConf = L"/bin/rm /etc/resolv.conf"; 30 | const TCHAR UserlandDownloadURL[] = _T("https://dl-cdn.alpinelinux.org/alpine/v3.18/releases/x86_64/alpine-minirootfs-3.18.4-x86_64.tar.gz"); 31 | const std::wstring UserlandChecksum = L"C59D5203BC6B8B6EF81F3F6B63E32C28D6E47BE806BA8528F8766A4CA506C7BA"; 32 | } 33 | -------------------------------------------------------------------------------- /DistroLauncher/WslApiLoader.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) Microsoft. All rights reserved. 3 | // Licensed under the terms described in the LICENSE file in the root of this project. 4 | // 5 | 6 | #pragma once 7 | #include 8 | 9 | // This error definition is present in the Spring Creators Update SDK. 10 | #ifndef ERROR_LINUX_SUBSYSTEM_NOT_PRESENT 11 | #define ERROR_LINUX_SUBSYSTEM_NOT_PRESENT 414L 12 | #endif // !ERROR_LINUX_SUBSYSTEM_NOT_PRESENT 13 | 14 | typedef BOOL(STDAPICALLTYPE* WSL_IS_DISTRIBUTION_REGISTERED)(PCWSTR); 15 | typedef HRESULT(STDAPICALLTYPE* WSL_REGISTER_DISTRIBUTION)(PCWSTR, PCWSTR); 16 | typedef HRESULT(STDAPICALLTYPE* WSL_CONFIGURE_DISTRIBUTION)(PCWSTR, ULONG, WSL_DISTRIBUTION_FLAGS); 17 | typedef HRESULT(STDAPICALLTYPE* WSL_GET_DISTRIBUTION_CONFIGURATION)(PCWSTR, ULONG *, ULONG *, WSL_DISTRIBUTION_FLAGS *, PSTR **, ULONG *); 18 | typedef HRESULT(STDAPICALLTYPE* WSL_LAUNCH_INTERACTIVE)(PCWSTR, PCWSTR, BOOL, DWORD *); 19 | typedef HRESULT(STDAPICALLTYPE* WSL_LAUNCH)(PCWSTR, PCWSTR, BOOL, HANDLE, HANDLE, HANDLE, HANDLE *); 20 | 21 | class WslApiLoader 22 | { 23 | public: 24 | WslApiLoader(const std::wstring& distributionName); 25 | ~WslApiLoader(); 26 | 27 | BOOL WslIsOptionalComponentInstalled(); 28 | 29 | BOOL WslIsDistributionRegistered(); 30 | 31 | HRESULT WslRegisterDistribution(PCWSTR tarGzFilename = L"install.tar.gz"); 32 | 33 | HRESULT WslConfigureDistribution(ULONG defaultUID, 34 | WSL_DISTRIBUTION_FLAGS wslDistributionFlags); 35 | 36 | HRESULT WslLaunchInteractive(PCWSTR command, 37 | BOOL useCurrentWorkingDirectory, 38 | DWORD *exitCode); 39 | 40 | HRESULT WslLaunch(PCWSTR command, 41 | BOOL useCurrentWorkingDirectory, 42 | HANDLE stdIn, 43 | HANDLE stdOut, 44 | HANDLE stdErr, 45 | HANDLE *process); 46 | 47 | private: 48 | std::wstring _distributionName; 49 | HMODULE _wslApiDll; 50 | WSL_IS_DISTRIBUTION_REGISTERED _isDistributionRegistered; 51 | WSL_REGISTER_DISTRIBUTION _registerDistribution; 52 | WSL_CONFIGURE_DISTRIBUTION _configureDistribution; 53 | WSL_LAUNCH_INTERACTIVE _launchInteractive; 54 | WSL_LAUNCH _launch; 55 | }; 56 | 57 | extern WslApiLoader g_wslApi; 58 | -------------------------------------------------------------------------------- /DistroLauncher-Appx/Alpine.appxmanifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Alpine Linux 7 | agowa338 8 | Assets/StoreLogo.png 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /DistroLauncher/messages.mc: -------------------------------------------------------------------------------- 1 | LanguageNames = (English=0x409:MSG00409) 2 | 3 | MessageId=1001 SymbolicName=MSG_WSL_REGISTER_DISTRIBUTION_FAILED 4 | Language=English 5 | WslRegisterDistribution failed with error: 0x%1!x! 6 | . 7 | 8 | MessageId=1002 SymbolicName=MSG_WSL_CONFIGURE_DISTRIBUTION_FAILED 9 | Language=English 10 | WslGetDistributionConfiguration failed with error: 0x%1!x! 11 | . 12 | 13 | MessageId=1003 SymbolicName=MSG_WSL_LAUNCH_INTERACTIVE_FAILED 14 | Language=English 15 | WslLaunchInteractive %1 failed with error: 0x%2!x! 16 | . 17 | 18 | MessageId=1004 SymbolicName=MSG_WSL_LAUNCH_FAILED 19 | Language=English 20 | WslLaunch %1 failed with error: 0x%2!x! 21 | . 22 | 23 | MessageId=1005 SymbolicName=MSG_USAGE 24 | Language=English 25 | Launches or configures a Linux distribution. 26 | 27 | Usage: 28 | 29 | Launches the user's default shell in the user's home directory. 30 | 31 | install [--root] 32 | Install the distribution and do not launch the shell when complete. 33 | --root 34 | Do not create a user account and leave the default user set to root. 35 | 36 | run 37 | Run the provided command line in the current working directory. If no 38 | command line is provided, the default shell is launched. 39 | 40 | config [setting [value]] 41 | Configure settings for this distribution. 42 | Settings: 43 | --default-user 44 | Sets the default user to . This must be an existing user. 45 | 46 | help 47 | Print usage information. 48 | . 49 | 50 | MessageId=1006 SymbolicName=MSG_STATUS_INSTALLING 51 | Language=English 52 | Installing, this may take a few minutes... 53 | . 54 | 55 | MessageId=1007 SymbolicName=MSG_INSTALL_SUCCESS 56 | Language=English 57 | Installation successful! 58 | . 59 | 60 | MessageId=1008 SymbolicName=MSG_ERROR_CODE 61 | Language=English 62 | Error: 0x%1!x! %2 63 | . 64 | 65 | MessageId=1009 SymbolicName=MSG_ENTER_USERNAME 66 | Language=English 67 | Enter new UNIX username: %0 68 | . 69 | 70 | MessageId=1010 SymbolicName=MSG_CREATE_USER_PROMPT 71 | Language=English 72 | Please create a default UNIX user account. The username does not need to match your Windows username. 73 | For more information visit: https://aka.ms/wslusers 74 | . 75 | 76 | MessageId=1011 SymbolicName=MSG_PRESS_A_KEY 77 | Language=English 78 | Press any key to continue... 79 | . 80 | 81 | MessageId=1012 SymbolicName=MSG_MISSING_OPTIONAL_COMPONENT 82 | Language=English 83 | The Windows Subsystem for Linux optional component is not enabled. Please enable it and try again. 84 | See https://aka.ms/wslinstall for details. 85 | . 86 | 87 | MessageId=1013 SymbolicName=MSG_INSTALL_ALREADY_EXISTS 88 | Language=English 89 | The distribution installation has become corrupted. 90 | Please select Reset from App Settings or uninstall and reinstall the app. 91 | . 92 | -------------------------------------------------------------------------------- /DistroLauncher/WslApiLoader.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) Microsoft. All rights reserved. 3 | // Licensed under the terms described in the LICENSE file in the root of this project. 4 | // 5 | 6 | #include "stdafx.h" 7 | #include "WslApiLoader.h" 8 | 9 | WslApiLoader::WslApiLoader(const std::wstring& distributionName) : 10 | _distributionName(distributionName) 11 | { 12 | _wslApiDll = LoadLibraryEx(L"wslapi.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32); 13 | if (_wslApiDll != nullptr) { 14 | _isDistributionRegistered = (WSL_IS_DISTRIBUTION_REGISTERED)GetProcAddress(_wslApiDll, "WslIsDistributionRegistered"); 15 | _registerDistribution = (WSL_REGISTER_DISTRIBUTION)GetProcAddress(_wslApiDll, "WslRegisterDistribution"); 16 | _configureDistribution = (WSL_CONFIGURE_DISTRIBUTION)GetProcAddress(_wslApiDll, "WslConfigureDistribution"); 17 | _launchInteractive = (WSL_LAUNCH_INTERACTIVE)GetProcAddress(_wslApiDll, "WslLaunchInteractive"); 18 | _launch = (WSL_LAUNCH)GetProcAddress(_wslApiDll, "WslLaunch"); 19 | } 20 | } 21 | 22 | WslApiLoader::~WslApiLoader() 23 | { 24 | if (_wslApiDll != nullptr) { 25 | FreeLibrary(_wslApiDll); 26 | } 27 | } 28 | 29 | BOOL WslApiLoader::WslIsOptionalComponentInstalled() 30 | { 31 | return ((_wslApiDll != nullptr) && 32 | (_isDistributionRegistered != nullptr) && 33 | (_registerDistribution != nullptr) && 34 | (_configureDistribution != nullptr) && 35 | (_launchInteractive != nullptr) && 36 | (_launch != nullptr)); 37 | } 38 | 39 | BOOL WslApiLoader::WslIsDistributionRegistered() 40 | { 41 | return _isDistributionRegistered(_distributionName.c_str()); 42 | } 43 | 44 | HRESULT WslApiLoader::WslRegisterDistribution(PCWSTR tarGzFilename) 45 | { 46 | HRESULT hr = _registerDistribution(_distributionName.c_str(), tarGzFilename); 47 | if (FAILED(hr)) { 48 | Helpers::PrintMessage(MSG_WSL_REGISTER_DISTRIBUTION_FAILED, hr); 49 | } 50 | 51 | return hr; 52 | } 53 | 54 | HRESULT WslApiLoader::WslConfigureDistribution(ULONG defaultUID, WSL_DISTRIBUTION_FLAGS wslDistributionFlags) 55 | { 56 | HRESULT hr = _configureDistribution(_distributionName.c_str(), defaultUID, wslDistributionFlags); 57 | if (FAILED(hr)) { 58 | Helpers::PrintMessage(MSG_WSL_CONFIGURE_DISTRIBUTION_FAILED, hr); 59 | } 60 | 61 | return hr; 62 | } 63 | 64 | HRESULT WslApiLoader::WslLaunchInteractive(PCWSTR command, BOOL useCurrentWorkingDirectory, DWORD *exitCode) 65 | { 66 | HRESULT hr = _launchInteractive(_distributionName.c_str(), command, useCurrentWorkingDirectory, exitCode); 67 | if (FAILED(hr)) { 68 | Helpers::PrintMessage(MSG_WSL_LAUNCH_INTERACTIVE_FAILED, command, hr); 69 | } 70 | 71 | return hr; 72 | } 73 | 74 | HRESULT WslApiLoader::WslLaunch(PCWSTR command, BOOL useCurrentWorkingDirectory, HANDLE stdIn, HANDLE stdOut, HANDLE stdErr, HANDLE *process) 75 | { 76 | HRESULT hr = _launch(_distributionName.c_str(), command, useCurrentWorkingDirectory, stdIn, stdOut, stdErr, process); 77 | if (FAILED(hr)) { 78 | Helpers::PrintMessage(MSG_WSL_LAUNCH_FAILED, command, hr); 79 | } 80 | 81 | return hr; 82 | } 83 | -------------------------------------------------------------------------------- /DistroLauncher/DistributionInfo.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) Microsoft. All rights reserved. 3 | // Licensed under the terms described in the LICENSE file in the root of this project. 4 | // 5 | 6 | #include "stdafx.h" 7 | 8 | bool DistributionInfo::CreateUser(std::wstring_view userName) 9 | { 10 | DWORD exitCode; 11 | std::wstring commandLine; 12 | HRESULT hr; 13 | 14 | // Create the user account. 15 | commandLine = DistroSpecial::commandLineAddUser; 16 | commandLine += userName; 17 | hr = g_wslApi.WslLaunchInteractive(commandLine.c_str(), true, &exitCode); 18 | if ((FAILED(hr)) || (exitCode != 0)) { 19 | std::wcerr << "Adding user to groups failed. Performing cleanup for retry." << std::endl; 20 | return false; 21 | } 22 | 23 | // Add the user account to any relevant groups. 24 | commandLine = DistroSpecial::commandLineAddUserToGroups; 25 | commandLine += userName; 26 | hr = g_wslApi.WslLaunchInteractive(commandLine.c_str(), true, &exitCode); 27 | if ((FAILED(hr)) || (exitCode != 0)) { 28 | std::wcerr << "Adding user to groups failed. Performing cleanup for retry." << std::endl; 29 | 30 | // Delete the user if the group add command failed. 31 | commandLine = DistroSpecial::commandLineDeleteUSer; 32 | commandLine += userName; 33 | hr = g_wslApi.WslLaunchInteractive(commandLine.c_str(), true, &exitCode); 34 | if ((FAILED(hr)) || (exitCode != 0)) { 35 | std::wcerr << "Deleting useraccount failed." << std::endl; 36 | } 37 | return false; 38 | } 39 | 40 | return true; 41 | } 42 | 43 | ULONG DistributionInfo::QueryUid(std::wstring_view userName) 44 | { 45 | // Create a pipe to read the output of the launched process. 46 | HANDLE readPipe; 47 | HANDLE writePipe; 48 | SECURITY_ATTRIBUTES sa{ sizeof(sa), nullptr, true }; 49 | ULONG uid = UID_INVALID; 50 | if (CreatePipe(&readPipe, &writePipe, &sa, 0)) { 51 | // Query the UID of the supplied username. 52 | std::wstring command = DistroSpecial::commandLineQueryUID; 53 | command += userName; 54 | int returnValue = 0; 55 | HANDLE child; 56 | HRESULT hr = g_wslApi.WslLaunch(command.c_str(), true, GetStdHandle(STD_INPUT_HANDLE), writePipe, GetStdHandle(STD_ERROR_HANDLE), &child); 57 | if (SUCCEEDED(hr)) { 58 | // Wait for the child to exit and ensure process exited successfully. 59 | WaitForSingleObject(child, INFINITE); 60 | DWORD exitCode; 61 | if ((GetExitCodeProcess(child, &exitCode) == false) || (exitCode != 0)) { 62 | hr = E_INVALIDARG; 63 | } 64 | 65 | CloseHandle(child); 66 | if (SUCCEEDED(hr)) { 67 | char buffer[64]; 68 | DWORD bytesRead; 69 | 70 | // Read the output of the command from the pipe and convert to a UID. 71 | if (ReadFile(readPipe, buffer, (sizeof(buffer) - 1), &bytesRead, nullptr)) { 72 | buffer[bytesRead] = ANSI_NULL; 73 | try { 74 | uid = std::stoul(buffer, nullptr, 10); 75 | 76 | } 77 | catch (...) {} 78 | } 79 | } 80 | } 81 | 82 | CloseHandle(readPipe); 83 | CloseHandle(writePipe); 84 | } 85 | 86 | return uid; 87 | } 88 | -------------------------------------------------------------------------------- /DistroLauncher/DistroLauncher.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | Header Files 32 | 33 | 34 | Header Files 35 | 36 | 37 | Header Files 38 | 39 | 40 | Header Files 41 | 42 | 43 | Header Files 44 | 45 | 46 | Header Files 47 | 48 | 49 | 50 | 51 | Source Files 52 | 53 | 54 | Source Files 55 | 56 | 57 | Source Files 58 | 59 | 60 | Source Files 61 | 62 | 63 | Source Files 64 | 65 | 66 | Source Files 67 | 68 | 69 | Source Files 70 | 71 | 72 | 73 | 74 | Header Files\Resource Files 75 | 76 | 77 | 78 | 79 | Header Files\Resource Files 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | Header Files\Resource Files 88 | 89 | 90 | -------------------------------------------------------------------------------- /DistroLauncher/Helpers.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) Microsoft. All rights reserved. 3 | // Licensed under the terms described in the LICENSE file in the root of this project. 4 | // 5 | 6 | #include "stdafx.h" 7 | 8 | 9 | namespace { 10 | HRESULT FormatMessageHelperVa(DWORD messageId, va_list vaList, std::wstring* message); 11 | HRESULT PrintMessageVa(DWORD messageId, va_list vaList); 12 | } 13 | 14 | std::wstring Helpers::CreateTemporaryDirectory() { 15 | std::wstring strTempPath = L""; 16 | wchar_t wchPath[MAX_PATH]; 17 | if (GetTempPathW(MAX_PATH, wchPath)) 18 | strTempPath = wchPath; 19 | 20 | fs::path dir(strTempPath); 21 | fs::path dir2(L"wsl_" + DistroSpecial::Name + L"_setup"); 22 | fs::path full_path = dir / dir2; 23 | CreateDirectoryW(full_path.c_str(), NULL); // TODO: Check return status 24 | std::wcout << L"Temporary directory: " << full_path << std::endl; 25 | return full_path; 26 | } 27 | 28 | void Helpers::SetWorkingDirectory(std::wstring newPath) { 29 | SetCurrentDirectoryW(newPath.c_str()); 30 | } 31 | 32 | std::wstring Helpers::GetUserInput(DWORD promptMsg, DWORD maxCharacters) 33 | { 34 | Helpers::PrintMessage(promptMsg); 35 | size_t bufferSize = maxCharacters + 1; 36 | std::unique_ptr inputBuffer(new wchar_t[bufferSize]); 37 | std::wstring input; 38 | if (wscanf_s(L"%s", inputBuffer.get(), (unsigned int)bufferSize) == 1) { 39 | input = inputBuffer.get(); 40 | } 41 | 42 | // Throw away any additional chracters that did not fit in the buffer. 43 | wchar_t wch; 44 | do { 45 | wch = getwchar(); 46 | 47 | } while ((wch != L'\n') && (wch != WEOF)); 48 | 49 | return input; 50 | } 51 | 52 | void Helpers::PrintErrorMessage(HRESULT error) 53 | { 54 | PWSTR buffer = nullptr; 55 | ::FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, 56 | nullptr, 57 | error, 58 | 0, 59 | (PWSTR)&buffer, 60 | 0, 61 | nullptr); 62 | 63 | Helpers::PrintMessage(MSG_ERROR_CODE, error, buffer); 64 | if (buffer != nullptr) { 65 | HeapFree(GetProcessHeap(), 0, buffer); 66 | } 67 | 68 | return; 69 | } 70 | 71 | HRESULT Helpers::PrintMessage(DWORD messageId, ...) 72 | { 73 | va_list argList; 74 | va_start(argList, messageId); 75 | HRESULT hr = PrintMessageVa(messageId, argList); 76 | va_end(argList); 77 | return hr; 78 | } 79 | 80 | void Helpers::PromptForInput() 81 | { 82 | Helpers::PrintMessage(MSG_PRESS_A_KEY); 83 | _getwch(); 84 | return; 85 | } 86 | 87 | namespace { 88 | HRESULT FormatMessageHelperVa(DWORD messageId, va_list vaList, std::wstring* message) 89 | { 90 | PWSTR buffer = nullptr; 91 | DWORD written = ::FormatMessageW(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ALLOCATE_BUFFER, 92 | nullptr, 93 | messageId, 94 | 0, 95 | (PWSTR)&buffer, 96 | 10, 97 | &vaList); 98 | *message = buffer; 99 | if (buffer != nullptr) { 100 | HeapFree(GetProcessHeap(), 0, buffer); 101 | } 102 | 103 | return (written > 0) ? S_OK : HRESULT_FROM_WIN32(GetLastError()); 104 | } 105 | 106 | HRESULT PrintMessageVa(DWORD messageId, va_list vaList) 107 | { 108 | std::wstring message; 109 | HRESULT hr = FormatMessageHelperVa(messageId, vaList, &message); 110 | if (SUCCEEDED(hr)) { 111 | wprintf(L"%ls", message.c_str()); 112 | } 113 | 114 | return hr; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /DistroLauncher/ChecksumVerify.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #define BUFSIZE 1024 3 | #define HASHLEN 32 // 256/8 A sha256 hash requires 256 bits or 32 bytes 4 | 5 | namespace ChecksumVerify { 6 | bool Verify(std::wstring path, std::wstring sha256hash) { 7 | std::string calculatedHash = GetSHA256(path); 8 | std::wstring calculatedHash_w(calculatedHash.begin(), calculatedHash.end()); 9 | std::wstring userlandChecksum_w(DistroSpecial::UserlandChecksum); 10 | 11 | std::tcout << std::endl; 12 | 13 | int countIsEqual = 0; 14 | for (DWORD i = 0; i < DistroSpecial::UserlandChecksum.length(); i++) 15 | { 16 | if (DistroSpecial::UserlandChecksum[i] == calculatedHash_w[i]) { 17 | countIsEqual += 1; 18 | } 19 | } 20 | if (DistroSpecial::UserlandChecksum.length() == countIsEqual && DistroSpecial::UserlandChecksum.length() > 0) { 21 | std::tcout << "Verifying Hash: OK" << std::endl; 22 | return true; 23 | } else { 24 | std::tcout << "Verifying Hash: Failed" << std::endl; 25 | return false; 26 | } 27 | } 28 | std::string GetSHA256(std::wstring path) { 29 | DWORD dwStatus = 0; 30 | BOOL bResult = FALSE; 31 | HCRYPTPROV hProv = 0; 32 | HCRYPTHASH hHash = 0; 33 | HANDLE hFile = NULL; 34 | BYTE rgbFile[BUFSIZE]; 35 | DWORD cbRead = 0; 36 | BYTE rgbHash[HASHLEN]; 37 | DWORD cbHash = 0; 38 | CHAR rgbDigits[] = "0123456789abcdef"; 39 | LPCWSTR filenameLPCWSTR = L"install.tar.gz"; 40 | const char *filename = "install.tar.gz"; 41 | char sha256sum[65]; 42 | sha256sum[64] = 0; // Strings are null terminated, so the last character needs to be '\0' 43 | 44 | hFile = CreateFile(filenameLPCWSTR, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); 45 | 46 | if (INVALID_HANDLE_VALUE == hFile) { 47 | dwStatus = GetLastError(); 48 | printf("Error opening file %s\nError: %d\n", filename, dwStatus); 49 | } 50 | 51 | // Get handle to the crypto provider 52 | if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) { 53 | dwStatus = GetLastError(); 54 | printf("CryptAcquireContext failed: %d\n", dwStatus); 55 | } 56 | 57 | if (!CryptCreateHash(hProv, CALG_SHA_256, 0, 0, &hHash)) { 58 | dwStatus = GetLastError(); 59 | printf("CryptAcquireContext failed: %d\n", dwStatus); 60 | } 61 | 62 | while (bResult = ReadFile(hFile, rgbFile, BUFSIZE, &cbRead, NULL)) { 63 | if (0 == cbRead) 64 | { 65 | break; 66 | } 67 | 68 | if (!CryptHashData(hHash, rgbFile, cbRead, 0)) 69 | { 70 | dwStatus = GetLastError(); 71 | printf("CryptHashData failed: %d\n", dwStatus); 72 | } 73 | } 74 | 75 | if (!bResult) 76 | { 77 | dwStatus = GetLastError(); 78 | printf("ReadFile failed: %d\n", dwStatus); 79 | } 80 | 81 | cbHash = HASHLEN; 82 | if (CryptGetHashParam(hHash, HP_HASHVAL, rgbHash, &cbHash, 0)) 83 | { 84 | printf("Hash of file %s is: ", filename); 85 | for (DWORD i = 0; i < cbHash; i++) 86 | { 87 | printf("%c%c", rgbDigits[rgbHash[i] >> 4], rgbDigits[rgbHash[i] & 0xf]); 88 | sha256sum[i*2] = rgbDigits[rgbHash[i] >> 4]; 89 | sha256sum[i*2+1] = rgbDigits[rgbHash[i] & 0xf]; 90 | } 91 | std::tcout << std::endl; 92 | } 93 | else 94 | { 95 | dwStatus = GetLastError(); 96 | printf("CryptGetHashParam failed: %d\n", dwStatus); 97 | } 98 | 99 | CryptDestroyHash(hHash); 100 | CryptReleaseContext(hProv, 0); 101 | CloseHandle(hFile); 102 | return sha256sum; 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /DistroLauncher/DownloadUserland.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | #pragma comment(lib, "urlmon.lib") 4 | 5 | // Adapted from: 6 | // Creating a progress bar in C/C++ (or any other console app.) 7 | // http://www.rosshemsley.co.uk/2011/02/creating-a-progress-bar-in-c-or-any-other-console-app/ 8 | void LoadBar(unsigned curr_val, unsigned max_val, unsigned bar_width = 20) 9 | { 10 | if ((curr_val != max_val) && (curr_val % (max_val / 100) != 0)) 11 | return; 12 | 13 | double ratio = curr_val / (double)max_val; 14 | unsigned bar_now = (unsigned)(ratio * bar_width); 15 | 16 | std::tcout << _T("\r") << std::setw(3) << (unsigned)(ratio * 100.0) << _T("% ["); 17 | for (unsigned curr_val = 0; curr_val < bar_now; ++curr_val) 18 | std::tcout << _T("="); 19 | for (unsigned curr_val = bar_now; curr_val < bar_width; ++curr_val) 20 | std::tcout << _T(" "); 21 | std::tcout << _T("]") << std::flush; 22 | } 23 | 24 | class CallbackHandler : public IBindStatusCallback 25 | { 26 | private: 27 | int m_percentLast; 28 | 29 | public: 30 | CallbackHandler() : m_percentLast(0) {}; 31 | 32 | // IUnknown 33 | 34 | HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject) { 35 | if (IsEqualIID(IID_IBindStatusCallback, riid) || IsEqualIID(IID_IUnknown, riid)) { 36 | *ppvObject = reinterpret_cast(this); 37 | return S_OK; 38 | }; 39 | return E_NOINTERFACE; 40 | }; 41 | 42 | ULONG STDMETHODCALLTYPE AddRef() 43 | { 44 | return 2UL; 45 | }; 46 | 47 | ULONG STDMETHODCALLTYPE Release() { 48 | return 1UL; 49 | }; 50 | 51 | // IBindStatusCallback 52 | 53 | HRESULT STDMETHODCALLTYPE OnStartBinding(DWORD /*dwReserved*/, IBinding* /*pib*/) { 54 | return E_NOTIMPL; 55 | }; 56 | 57 | HRESULT STDMETHODCALLTYPE GetPriority(LONG* /*pnPriority*/) { 58 | return E_NOTIMPL; 59 | }; 60 | 61 | HRESULT STDMETHODCALLTYPE OnLowResource(DWORD /*reserved*/) { 62 | return E_NOTIMPL; 63 | }; 64 | 65 | HRESULT STDMETHODCALLTYPE OnProgress(ULONG ulProgress, ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR /*szStatusText*/) 66 | { 67 | switch (ulStatusCode) 68 | { 69 | case BINDSTATUS_FINDINGRESOURCE: 70 | std::tcout << _T("Finding resource...") << std::endl; 71 | break; 72 | case BINDSTATUS_CONNECTING: 73 | std::tcout << _T("Connecting...") << std::endl; 74 | break; 75 | case BINDSTATUS_SENDINGREQUEST: 76 | std::tcout << _T("Sending request...") << std::endl; 77 | break; 78 | case BINDSTATUS_MIMETYPEAVAILABLE: 79 | std::tcout << _T("Mime type available") << std::endl; 80 | break; 81 | case BINDSTATUS_CACHEFILENAMEAVAILABLE: 82 | std::tcout << _T("Cache filename available") << std::endl; 83 | break; 84 | case BINDSTATUS_BEGINDOWNLOADDATA: 85 | std::tcout << _T("Begin download") << std::endl; 86 | break; 87 | case BINDSTATUS_DOWNLOADINGDATA: 88 | case BINDSTATUS_ENDDOWNLOADDATA: 89 | { 90 | int percent = (int)(100.0 * static_cast(ulProgress) 91 | / static_cast(ulProgressMax)); 92 | if (m_percentLast < percent) 93 | { 94 | LoadBar(percent, 100); 95 | m_percentLast = percent; 96 | } 97 | if (ulStatusCode == BINDSTATUS_ENDDOWNLOADDATA) 98 | { 99 | std::tcout << std::endl << _T("End download") << std::endl; 100 | } 101 | } 102 | break; 103 | 104 | default: 105 | { 106 | std::tcout << _T("Status code : ") << ulStatusCode << std::endl; 107 | } 108 | } 109 | // The download can be cancelled by returning E_ABORT here 110 | // of from any other of the methods. 111 | return S_OK; 112 | }; 113 | 114 | HRESULT STDMETHODCALLTYPE OnStopBinding(HRESULT /*hresult*/, LPCWSTR /*szError*/) { 115 | return E_NOTIMPL; 116 | }; 117 | 118 | HRESULT STDMETHODCALLTYPE GetBindInfo(DWORD* /*grfBINDF*/, BINDINFO* /*pbindinfo*/) { 119 | return E_NOTIMPL; 120 | }; 121 | 122 | HRESULT STDMETHODCALLTYPE OnDataAvailable(DWORD /*grfBSCF*/, DWORD /*dwSize*/, FORMATETC* /*pformatetc*/, STGMEDIUM* /*pstgmed*/) { 123 | return E_NOTIMPL; 124 | }; 125 | 126 | HRESULT STDMETHODCALLTYPE OnObjectAvailable(REFIID /*riid*/, IUnknown* /*punk*/) { 127 | return E_NOTIMPL; 128 | }; 129 | }; 130 | 131 | HRESULT DownloadUserland() { 132 | const TCHAR* url = DistroSpecial::UserlandDownloadURL; 133 | const TCHAR filePath[] = _T("install.tar.gz"); 134 | 135 | std::tcout << "Downloading : " << url << std::endl; 136 | std::tcout << "To local file : " << filePath << std::endl; 137 | 138 | char* buffer; 139 | // Get the current working directory: 140 | // Passing NULL as the buffer forces getcwd to allocate 141 | // memory for the path, which allows the code to support file paths 142 | // longer than _MAX_PATH, which are supported by NTFS. 143 | if ((buffer = _getcwd(NULL, 0)) == NULL) { 144 | perror("_getcwd error"); 145 | } else { 146 | std::tcout << "The current working directory is: " << buffer << std::endl; 147 | free(buffer); 148 | } 149 | 150 | if (remove("install.tar.gz") != 0) { 151 | perror("Error deleting file"); 152 | } 153 | else { 154 | puts("File successfully deleted"); 155 | } 156 | 157 | // invalidate cache, so file is always downloaded from web site 158 | // (if not called, the file will be retieved from the cache if 159 | // it's already been downloaded.) 160 | //FIXME: DeleteUrlCacheEntry(url); 161 | 162 | CallbackHandler callbackHandler; 163 | IBindStatusCallback* pBindStatusCallback = NULL; 164 | callbackHandler.QueryInterface(IID_IBindStatusCallback, reinterpret_cast(&pBindStatusCallback)); 165 | 166 | HRESULT hr = URLDownloadToFile( 167 | NULL, // A pointer to the controlling IUnknown interface 168 | url, 169 | filePath, 170 | 0, // Reserved. Must be set to 0. 171 | pBindStatusCallback); 172 | callbackHandler.Release(); 173 | if (SUCCEEDED(hr)) 174 | { 175 | std::tcout << _T("Downloaded OK") << std::endl; 176 | return S_OK; 177 | } 178 | else 179 | { 180 | std::tcout << _T("An error occured : error code = 0x") << std::hex << hr << std::endl; 181 | return hr; 182 | } 183 | }; 184 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.suo 8 | *.user 9 | *.userosscache 10 | *.sln.docstates 11 | 12 | # User-specific files (MonoDevelop/Xamarin Studio) 13 | *.userprefs 14 | 15 | # Build results 16 | [Dd]ebug/ 17 | [Dd]ebugPublic/ 18 | [Rr]elease/ 19 | [Rr]eleases/ 20 | x64/ 21 | x86/ 22 | bld/ 23 | [Bb]in/ 24 | [Oo]bj/ 25 | [Ll]og/ 26 | 27 | # Visual Studio 2015 cache/options directory 28 | .vs/ 29 | # Uncomment if you have tasks that create the project's static files in wwwroot 30 | #wwwroot/ 31 | 32 | # MSTest test Results 33 | [Tt]est[Rr]esult*/ 34 | [Bb]uild[Ll]og.* 35 | 36 | # NUNIT 37 | *.VisualState.xml 38 | TestResult.xml 39 | 40 | # Build Results of an ATL Project 41 | [Dd]ebugPS/ 42 | [Rr]eleasePS/ 43 | dlldata.c 44 | 45 | # .NET Core 46 | project.lock.json 47 | project.fragment.lock.json 48 | artifacts/ 49 | **/Properties/launchSettings.json 50 | 51 | *_i.c 52 | *_p.c 53 | *_i.h 54 | *.ilk 55 | *.meta 56 | *.obj 57 | *.pch 58 | *.pdb 59 | *.pgc 60 | *.pgd 61 | *.rsp 62 | *.sbr 63 | *.tlb 64 | *.tli 65 | *.tlh 66 | *.tmp 67 | *.tmp_proj 68 | *.log 69 | *.vspscc 70 | *.vssscc 71 | .builds 72 | *.pidb 73 | *.svclog 74 | *.scc 75 | 76 | # Chutzpah Test files 77 | _Chutzpah* 78 | 79 | # Visual C++ cache files 80 | ipch/ 81 | *.aps 82 | *.ncb 83 | *.opendb 84 | *.opensdf 85 | *.sdf 86 | *.cachefile 87 | *.VC.db 88 | *.VC.VC.opendb 89 | 90 | # Visual Studio profiler 91 | *.psess 92 | *.vsp 93 | *.vspx 94 | *.sap 95 | 96 | # TFS 2012 Local Workspace 97 | $tf/ 98 | 99 | # Guidance Automation Toolkit 100 | *.gpState 101 | 102 | # ReSharper is a .NET coding add-in 103 | _ReSharper*/ 104 | *.[Rr]e[Ss]harper 105 | *.DotSettings.user 106 | 107 | # JustCode is a .NET coding add-in 108 | .JustCode 109 | 110 | # TeamCity is a build add-in 111 | _TeamCity* 112 | 113 | # DotCover is a Code Coverage Tool 114 | *.dotCover 115 | 116 | # Visual Studio code coverage results 117 | *.coverage 118 | *.coveragexml 119 | 120 | # NCrunch 121 | _NCrunch_* 122 | .*crunch*.local.xml 123 | nCrunchTemp_* 124 | 125 | # MightyMoose 126 | *.mm.* 127 | AutoTest.Net/ 128 | 129 | # Web workbench (sass) 130 | .sass-cache/ 131 | 132 | # Installshield output folder 133 | [Ee]xpress/ 134 | 135 | # DocProject is a documentation generator add-in 136 | DocProject/buildhelp/ 137 | DocProject/Help/*.HxT 138 | DocProject/Help/*.HxC 139 | DocProject/Help/*.hhc 140 | DocProject/Help/*.hhk 141 | DocProject/Help/*.hhp 142 | DocProject/Help/Html2 143 | DocProject/Help/html 144 | 145 | # Click-Once directory 146 | publish/ 147 | 148 | # Publish Web Output 149 | *.[Pp]ublish.xml 150 | *.azurePubxml 151 | # TODO: Comment the next line if you want to checkin your web deploy settings 152 | # but database connection strings (with potential passwords) will be unencrypted 153 | *.pubxml 154 | *.publishproj 155 | 156 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 157 | # checkin your Azure Web App publish settings, but sensitive information contained 158 | # in these scripts will be unencrypted 159 | PublishScripts/ 160 | 161 | # NuGet Packages 162 | *.nupkg 163 | # The packages folder can be ignored because of Package Restore 164 | **/packages/* 165 | # except build/, which is used as an MSBuild target. 166 | !**/packages/build/ 167 | # Uncomment if necessary however generally it will be regenerated when needed 168 | #!**/packages/repositories.config 169 | # NuGet v3's project.json files produces more ignorable files 170 | *.nuget.props 171 | *.nuget.targets 172 | 173 | # Microsoft Azure Build Output 174 | csx/ 175 | *.build.csdef 176 | 177 | # Microsoft Azure Emulator 178 | ecf/ 179 | rcf/ 180 | 181 | # Windows Store app package directories and files 182 | AppPackages/ 183 | BundleArtifacts/ 184 | Package.StoreAssociation.xml 185 | _pkginfo.txt 186 | 187 | # Visual Studio cache files 188 | # files ending in .cache can be ignored 189 | *.[Cc]ache 190 | # but keep track of directories ending in .cache 191 | !*.[Cc]ache/ 192 | 193 | # Others 194 | ClientBin/ 195 | ~$* 196 | *~ 197 | *.dbmdl 198 | *.dbproj.schemaview 199 | *.jfm 200 | *.pfx 201 | *.publishsettings 202 | orleans.codegen.cs 203 | 204 | # Since there are multiple workflows, uncomment next line to ignore bower_components 205 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 206 | #bower_components/ 207 | 208 | # RIA/Silverlight projects 209 | Generated_Code/ 210 | 211 | # Backup & report files from converting an old project file 212 | # to a newer Visual Studio version. Backup files are not needed, 213 | # because we have git ;-) 214 | _UpgradeReport_Files/ 215 | Backup*/ 216 | UpgradeLog*.XML 217 | UpgradeLog*.htm 218 | 219 | # SQL Server files 220 | *.mdf 221 | *.ldf 222 | *.ndf 223 | 224 | # Business Intelligence projects 225 | *.rdl.data 226 | *.bim.layout 227 | *.bim_*.settings 228 | 229 | # Microsoft Fakes 230 | FakesAssemblies/ 231 | 232 | # GhostDoc plugin setting file 233 | *.GhostDoc.xml 234 | 235 | # Node.js Tools for Visual Studio 236 | .ntvs_analysis.dat 237 | node_modules/ 238 | 239 | # Typescript v1 declaration files 240 | typings/ 241 | 242 | # Visual Studio 6 build log 243 | *.plg 244 | 245 | # Visual Studio 6 workspace options file 246 | *.opt 247 | 248 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 249 | *.vbw 250 | 251 | # Visual Studio LightSwitch build output 252 | **/*.HTMLClient/GeneratedArtifacts 253 | **/*.DesktopClient/GeneratedArtifacts 254 | **/*.DesktopClient/ModelManifest.xml 255 | **/*.Server/GeneratedArtifacts 256 | **/*.Server/ModelManifest.xml 257 | _Pvt_Extensions 258 | 259 | # Paket dependency manager 260 | .paket/paket.exe 261 | paket-files/ 262 | 263 | # FAKE - F# Make 264 | .fake/ 265 | 266 | # JetBrains Rider 267 | .idea/ 268 | *.sln.iml 269 | 270 | # CodeRush 271 | .cr/ 272 | 273 | # Python Tools for Visual Studio (PTVS) 274 | __pycache__/ 275 | *.pyc 276 | 277 | # Cake - Uncomment if you are using it 278 | # tools/** 279 | # !tools/packages.config 280 | 281 | # Telerik's JustMock configuration file 282 | *.jmconfig 283 | 284 | # BizTalk build output 285 | *.btp.cs 286 | *.btm.cs 287 | *.odx.cs 288 | *.xsd.cs 289 | 290 | 291 | 292 | DistroLauncher/MSG*.bin 293 | DistroLauncher/messages.rc 294 | DistroLauncher/messages.h 295 | *.lib 296 | *.dll 297 | *.exe 298 | *.tar.gz -------------------------------------------------------------------------------- /DistroLauncher-Appx/DistroLauncher-Appx.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | f63472f9-d0a0-412e-aa3d-a4e822970486 6 | 7 | 8 | 3cd39ea5-301d-4878-9d47-b5dbb30f6c95 9 | bmp;fbx;gif;jpg;jpeg;tga;tiff;tif;png 10 | 11 | 12 | 13 | 14 | Assets 15 | 16 | 17 | Assets 18 | 19 | 20 | Assets 21 | 22 | 23 | Assets 24 | 25 | 26 | Assets 27 | 28 | 29 | Assets 30 | 31 | 32 | Assets 33 | 34 | 35 | Assets 36 | 37 | 38 | Assets 39 | 40 | 41 | Assets 42 | 43 | 44 | Assets 45 | 46 | 47 | Assets 48 | 49 | 50 | Assets 51 | 52 | 53 | Assets 54 | 55 | 56 | Assets 57 | 58 | 59 | Assets 60 | 61 | 62 | Assets 63 | 64 | 65 | Assets 66 | 67 | 68 | Assets 69 | 70 | 71 | Assets 72 | 73 | 74 | Assets 75 | 76 | 77 | Assets 78 | 79 | 80 | Assets 81 | 82 | 83 | Assets 84 | 85 | 86 | Assets 87 | 88 | 89 | Assets 90 | 91 | 92 | Assets 93 | 94 | 95 | Assets 96 | 97 | 98 | Assets 99 | 100 | 101 | Assets 102 | 103 | 104 | Assets 105 | 106 | 107 | Assets 108 | 109 | 110 | Assets 111 | 112 | 113 | Assets 114 | 115 | 116 | Assets 117 | 118 | 119 | Assets 120 | 121 | 122 | Assets 123 | 124 | 125 | Assets 126 | 127 | 128 | Assets 129 | 130 | 131 | Assets 132 | 133 | 134 | Assets 135 | 136 | 137 | Assets 138 | 139 | 140 | Assets 141 | 142 | 143 | Assets 144 | 145 | 146 | Assets 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | -------------------------------------------------------------------------------- /DistroLauncher/DistroLauncher.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) Microsoft. All rights reserved. 3 | // Licensed under the terms described in the LICENSE file in the root of this project. 4 | // 5 | 6 | #include "stdafx.h" 7 | 8 | // Helper class for calling WSL Functions: 9 | // https://msdn.microsoft.com/en-us/library/windows/desktop/mt826874(v=vs.85).aspx 10 | WslApiLoader g_wslApi(DistroSpecial::Name); 11 | 12 | 13 | HRESULT InstallDistribution(bool createUser, PCWSTR tarGzFilename) 14 | { 15 | // Register the distribution. 16 | Helpers::PrintMessage(MSG_STATUS_INSTALLING); 17 | HRESULT hr = g_wslApi.WslRegisterDistribution(tarGzFilename); 18 | if (FAILED(hr)) { 19 | std::wcout << "WslRegisterDistribution failed" << std::endl; 20 | return hr; 21 | } 22 | 23 | // Delete /etc/resolv.conf to allow WSL to generate a version based on Windows networking information. 24 | DWORD exitCode; 25 | hr = g_wslApi.WslLaunchInteractive(DistroSpecial::commandLineDeleteResolvConf, true, &exitCode); 26 | if (FAILED(hr)) { 27 | return hr; 28 | } 29 | 30 | // Pre create user actions, used to fix issues (if any) and/or install dependencies before a user account is created. 31 | // Like wrong permissions on / 32 | for (const std::wstring &commandLine : DistroSpecial::commandLinePreAddUser) { 33 | if (!commandLine.empty()) { 34 | std::wcout << "Executing bugfixing command: " << commandLine << std::endl; 35 | hr = g_wslApi.WslLaunchInteractive(commandLine.c_str(), true, &exitCode); 36 | if ((FAILED(hr)) || (exitCode != 0)) { 37 | std::wcerr << "Bugfixing command failed." << std::endl; 38 | break; 39 | } 40 | } 41 | } 42 | if ((FAILED(hr)) || (exitCode != 0)) { 43 | std::wcerr << std::endl << std::endl << "==== MANUAL STEP ====" << std::endl; 44 | std::wcerr << "If you're on Windows 10 1803 17134, manually execute this/these command(s), NOW:" << std::endl << "Or upgrade to the latest version of windows 10" << std::endl; 45 | for (const std::wstring &commandLine : DistroSpecial::commandLinePreAddUser) { 46 | if (!commandLine.empty()) { 47 | std::wcerr << commandLine << std::endl; 48 | } 49 | } 50 | std::wcerr << std::endl; 51 | std::wcerr << "Also you need to provide a /bin/bash executable to use bash.exe from Windows." << std::endl; 52 | std::wcerr << "Either by symlinking any other shell to /bin/bash or by installing bash." << std::endl; 53 | std::wcerr << "If you want to change the default user (after you created one), run:" << std::endl; 54 | std::wcerr << DistroSpecial::Name << ".exe /config --default-user " << std::endl; 55 | std::wcerr << "== // MANUAL STEP // ==" << std::endl; 56 | return hr; 57 | } 58 | 59 | // Create a user account. 60 | if (createUser) { 61 | Helpers::PrintMessage(MSG_CREATE_USER_PROMPT); 62 | std::wstring userName; 63 | do { 64 | userName = Helpers::GetUserInput(MSG_ENTER_USERNAME, 32); 65 | } while (!DistributionInfo::CreateUser(userName)); 66 | 67 | // Set this user account as the default. 68 | hr = SetDefaultUser(userName); 69 | if (FAILED(hr)) { 70 | std::wcerr << "SetDefaultUser failed." << std::endl; 71 | return hr; 72 | } 73 | } 74 | 75 | // Set a root password 76 | if (DistroSpecial::askForRootPassword) { 77 | std::wcout << std::endl << "To (re-)set root password run `wsl.exe --user root --distribution Alpine passwd`" << std::endl << std::endl; 78 | std::system("C:\\Windows\\System32\\wsl.exe --user root --distribution Alpine passwd"); 79 | } 80 | 81 | return hr; 82 | } 83 | 84 | HRESULT SetDefaultUser(std::wstring_view userName) 85 | { 86 | // Query the UID of the given user name and configure the distribution 87 | // to use this UID as the default. 88 | ULONG uid = DistributionInfo::QueryUid(userName); 89 | if (uid == UID_INVALID) { 90 | std::wcerr << "UID is invalid or query command failed." << std::endl; 91 | return E_INVALIDARG; 92 | } 93 | 94 | HRESULT hr = g_wslApi.WslConfigureDistribution(uid, WSL_DISTRIBUTION_FLAGS_DEFAULT); 95 | if (FAILED(hr)) { 96 | return hr; 97 | } 98 | 99 | return hr; 100 | } 101 | 102 | int wmain(int argc, wchar_t const *argv[]) 103 | { 104 | //while (!::IsDebuggerPresent()) 105 | // ::Sleep(100); // to avoid 100% CPU load 106 | 107 | // Update the title bar of the console window. 108 | SetConsoleTitleW(DistroSpecial::WindowTitle.c_str()); 109 | 110 | // Initialize a vector of arguments. 111 | std::vector arguments; 112 | for (int index = 1; index < argc; index += 1) { 113 | arguments.push_back(argv[index]); 114 | } 115 | 116 | // Ensure that the Windows Subsystem for Linux optional component is installed. 117 | DWORD exitCode = 1; 118 | if (!g_wslApi.WslIsOptionalComponentInstalled()) { 119 | Helpers::PrintMessage(MSG_MISSING_OPTIONAL_COMPONENT); 120 | if (arguments.empty()) { 121 | Helpers::PromptForInput(); 122 | } 123 | 124 | return exitCode; 125 | } 126 | 127 | // Install the distribution if it is not already. 128 | bool installOnly = ((arguments.size() > 0) && (arguments[0] == ARG_INSTALL)); 129 | HRESULT hr = S_OK; 130 | if (!g_wslApi.WslIsDistributionRegistered()) { 131 | // Switch workingdirectory to temporary folder 132 | const std::wstring tempWorkingDir = Helpers::CreateTemporaryDirectory(); 133 | Helpers::SetWorkingDirectory(tempWorkingDir); 134 | fs::path file(L"install.tar.gz"); 135 | fs::path full_path = tempWorkingDir / file; 136 | 137 | do { 138 | DownloadUserland(); 139 | //Verify if download completed successfully with SHA256 140 | } while (!ChecksumVerify::Verify(full_path.c_str(), DistroSpecial::UserlandChecksum)); 141 | 142 | // If the "--root" option is specified, do not create a user account. 143 | bool useRoot = ((installOnly) && (arguments.size() > 1) && (arguments[1] == ARG_INSTALL_ROOT)); 144 | hr = InstallDistribution(!useRoot, full_path.c_str()); 145 | if (FAILED(hr)) { 146 | if (hr == HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS)) { 147 | Helpers::PrintMessage(MSG_INSTALL_ALREADY_EXISTS); 148 | } 149 | 150 | } 151 | else { 152 | Helpers::PrintMessage(MSG_INSTALL_SUCCESS); 153 | } 154 | 155 | exitCode = SUCCEEDED(hr) ? 0 : 1; 156 | } 157 | 158 | // Parse the command line arguments. 159 | if ((SUCCEEDED(hr)) && (!installOnly)) { 160 | if (arguments.empty()) { 161 | hr = g_wslApi.WslLaunchInteractive(L"", false, &exitCode); 162 | 163 | } 164 | else if ((arguments[0] == ARG_RUN) || 165 | (arguments[0] == ARG_RUN_C)) { 166 | 167 | std::wstring command = L""; 168 | for (size_t index = 1; index < arguments.size(); index += 1) { 169 | command += arguments[index]; 170 | command += L" "; 171 | } 172 | 173 | hr = g_wslApi.WslLaunchInteractive(command.c_str(), true, &exitCode); 174 | 175 | } 176 | else if (arguments[0] == ARG_CONFIG) { 177 | hr = E_INVALIDARG; 178 | if (arguments.size() == 3) { 179 | if (arguments[1] == ARG_CONFIG_DEFAULT_USER) { 180 | hr = SetDefaultUser(arguments[2]); 181 | } 182 | } 183 | 184 | if (SUCCEEDED(hr)) { 185 | exitCode = 0; 186 | } 187 | 188 | } 189 | else { 190 | Helpers::PrintMessage(MSG_USAGE); 191 | return exitCode; 192 | } 193 | } 194 | 195 | // If an error was encountered, print an error message. 196 | if (FAILED(hr)) { 197 | if (hr == HRESULT_FROM_WIN32(ERROR_LINUX_SUBSYSTEM_NOT_PRESENT)) { 198 | Helpers::PrintMessage(MSG_MISSING_OPTIONAL_COMPONENT); 199 | 200 | } 201 | else { 202 | Helpers::PrintErrorMessage(hr); 203 | } 204 | 205 | if (arguments.empty()) { 206 | Helpers::PromptForInput(); 207 | } 208 | } 209 | 210 | return SUCCEEDED(hr) ? exitCode : 1; 211 | } 212 | -------------------------------------------------------------------------------- /DistroLauncher/DistroLauncher.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | ARM64 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | ARM64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {BA627106-E5F7-46EE-B8D7-2D5A760F2FB2} 23 | Win32Proj 24 | DistroLauncher 25 | 10.0 26 | launcher 27 | 28 | 29 | 30 | Application 31 | true 32 | v143 33 | Unicode 34 | 35 | 36 | Application 37 | true 38 | v143 39 | Unicode 40 | true 41 | 42 | 43 | Application 44 | false 45 | v143 46 | true 47 | Unicode 48 | 49 | 50 | Application 51 | false 52 | v143 53 | true 54 | Unicode 55 | true 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | true 68 | ClCompile 69 | 70 | 71 | 72 | Use 73 | Level3 74 | Disabled 75 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 76 | true 77 | stdcpp17 78 | 79 | 80 | Console 81 | true 82 | onecore.lib; 83 | 84 | 85 | 86 | 87 | Use 88 | Level3 89 | Disabled 90 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 91 | true 92 | stdcpp17 93 | 94 | 95 | Console 96 | true 97 | onecore.lib; 98 | 99 | 100 | 101 | 102 | Level3 103 | Use 104 | MaxSpeed 105 | true 106 | true 107 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 108 | true 109 | stdcpp17 110 | MultiThreaded 111 | 112 | 113 | Console 114 | true 115 | true 116 | true 117 | onecore.lib; 118 | 119 | 120 | 121 | 122 | Level3 123 | Use 124 | MaxSpeed 125 | true 126 | true 127 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 128 | true 129 | stdcpp17 130 | MultiThreaded 131 | 132 | 133 | Console 134 | true 135 | true 136 | true 137 | onecore.lib; 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | Create 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | Document 172 | false 173 | mc %(FullPath) 174 | Compiling Messages... 175 | %(Filename).rc;%(Filename).h;MSG0409.bin 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WSL Alpine DistroLauncher 2 | ## Introduction 3 | This is the Alpine Launcher implementation for a Windows Subsystem for Linux (WSL) distribution. 4 | 5 | Note: This project is written in C++. 6 | 7 | ### Goals 8 | The goal of this project is to enable: 9 | * Allow devolopers to use Alpine on their Windows machines for simple tasks (basically everything except kernel modules) 10 | * Allow developers to use the WSL with a very low footprint (compared to debian/ubuntu) 11 | * Use the official tar.gz userland release without building a custom userland tar.gz 12 | * Make the project "self maintained", i.e. don't require to ship any dependencies that require being updated and automatically pull the latest stable userland from the official source (WIP) 13 | 14 | ### Project Status 15 | This project is an active repo maintained by agowa338. 16 | The official windows Store download can be found here: https://www.microsoft.com/en-us/p/alpine-wsl/9p804crf0395 17 | 18 | ### Contents 19 | The sample provides the following functionality: 20 | 21 | * `Alpine.exe` 22 | - Launches the user's default shell in the user's home directory. 23 | 24 | * `Alpine.exe install [--root]` 25 | - Install the distribution and do not launch the shell when complete. 26 | - `--root`: Do not create a user account and leave the default user set to root. 27 | 28 | * `Alpine.exe run ` 29 | - Run the provided command line in the current working directory. If no command line is provided, the default shell is launched. 30 | - Everything after `run` is passed to WslLaunchInteractive. 31 | 32 | * `Alpine.exe config [setting [value]]` 33 | - Configure settings for this distribution. 34 | - Settings: 35 | - `--default-user `: Sets the default user to . This must be an existing user. 36 | 37 | * `Alpine.exe help` 38 | - Print usage information. 39 | 40 | ## Getting Started (Project Participants) 41 | 0. Clone this repository and open it with Visual Studio ( >= 2017 ) 42 | 1. Generate a test certificate. 43 | 2. Import it to your Cert:\CurrentUser\My and Cert:\LocalMachine\TrustedPublisher as well as Cert:\LocalMachine\Root. If you have a dedicated testing VM, import the certificate only to Cert:\CurrentUser\My on your production system, or you may make yourself vulnerable to all kinds of attacks. That is the reason why you would want to protect this certificate nearly as well as a bought code signing certificate. 44 | 3. Open `DistroLauncher-Appx/MyDistro.appxmanifest`, select the Packaging tab, select Choose Certificate, click the Configure Certificate drop down and select Create test certificate. 45 | 4. Edit your distribution-specific information in `DistroSpecial.h`. **NOTE: The `DistroSpecial::Name` variable must uniquely identify your distribution and cannot change from one version of your app to the next. Otherwise it will register as another distribution within WSL. If you want to have one distro twice, you would change this name.** 46 | 5. Update `Alpine.appxmanifest`. There are several properties that are in the manifest that will need to be updated with your specific values. 47 | - Make sure to note the `Identity Publisher` value (by default, `"CN=DistroOwner"`). We'll need that for testing the application. 48 | - Make sure that `` is set to something that ends in ".exe". This is the command that will be used to launch your distro from the command line. 49 | 50 | ## Build and Test 51 | To help building and testing the Alpine Launcher project, there are the following scripts to automate some tasks. You can either choose to use these scripts from the command line, or work directly in Visual Studio, whatever your preference is. 52 | 53 | **Please Note** some sideloading/deployment steps don't work if you mix and match Visual Studio and the command line for development. If you run into errors while trying to deploy your app after already deploying it once, the easiest step is usually just to uninstall the previously sideloaded version and try again. By right-clicking the App and selecting "Uninstall", if WSL is still installed, but the app is not, just run `wslconfig.exe /u Alpine`. 54 | 55 | ### Setting up your Windows Environment 56 | You will need a Windows environment to test that your app installs and works as expected. To set up a Windows environment for testing you can follow the steps from the [Windows Dev Center](https://developer.microsoft.com/en-us/windows/downloads/virtual-machines). 57 | 58 | Note: If you are using Hyper-V you can use the new VM gallery to easily spin up a Windows instance. 59 | 60 | ### Building Project (Command line): 61 | To compile the project, you can simply type `.\build.bat` in the root of the project to use MSBuild to build the solution. This is useful for verifying that your application compiles. It will also build an appx for you to sideload on your dev machine for testing. 62 | 63 | `build.bat` assumes that MSBuild is installed at one of the following paths: 64 | `%ProgramFiles*%\MSBuild\14.0\bin\msbuild.exe` or 65 | `%ProgramFiles*%\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin\msbuild.exe` or 66 | `%ProgramFiles*%\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\msbuild.exe`. 67 | 68 | If that's not the case, then you will need to modify that script. 69 | 70 | Once you've completed the build, the packaged appx should be placed in the directory `Alpine-DistroLauncher\x64\Debug\DistroLauncher-Appx` and should be named something like `DistroLauncher-Appx_1.0.0.0_x64_Debug.appx`. Simply double click that appx file to open the sideloading dialog. 71 | 72 | You can also use the PowerShell cmdlet `Add-AppxPackage` to register your appx: 73 | ``` powershell 74 | powershell Add-AppxPackage x64\Debug\DistroLauncher-Appx\DistroLauncher-Appx_1.0.0.0_x64_Debug.appx 75 | ``` 76 | 77 | ### Building Project (Visual Studio): 78 | 79 | You can also easily build and deploy the distro launcher from Visual Studio. To sideload your appx on your machine for testing, all you need to do is right-click on the "Solution (DistroLauncher)" in the Solution Explorer and click "Deploy Solution". This should build the project and sideload it automatically for testing. 80 | 81 | **NOTE: In order run your solution under the Visual Studio debugger, you will need to manually unregister it via `wslconfig.exe /u Alpine`.** 82 | 83 | ### Testing 84 | You should now have a finished appx sideloaded on your machine for testing. 85 | 86 | But before you do that, make sure you've enabled Developer Mode in the Settings app (sideloading won't work without it). Then double click on the signed appx and click "Install" to install it. Note that this only installed the appx on your system, but it doesn't unzip the tar.gz or register the distro yet. 87 | 88 | You can then begin the distro registration by launching the app from the Start Menu or executing `Alpine` from the command line. Or just select "Start after installation" while installing. 89 | 90 | ### Publishing 91 | Once you are ready to upload your appx to the store, you will need to change a few small things to prepare the appx for the store. 92 | 93 | 1. In the appxmanifest, you will need to change the values of the Identity to match the value given to you by the store. This should look like the following: 94 | 95 | ``` xml 96 | 100 | ``` 101 | 102 | **NOTE**: Visual Studio can update this for you. You can do that by right-clicking on "DistroLauncher-Appx (Universal Windows)" in the solution explorer and clicking on "Store... Associate App with the Store..." and following the wizard. 103 | 104 | 2. You will either need to run `.\build.bat rel` from the command line to generate the Release version of your appx or use Visual Studio directly to upload your package to the store. You can do this by right-clicking on "DistroLauncher-Appx (Universal Windows)" in the solution explorer and clicking on "Store... Create App Packages..." and following the wizard. 105 | 106 | Also, make sure to check out the [Notes for uploading to the Store](https://github.com/Microsoft/WSL-DistroLauncher/wiki/Notes-for-uploading-to-the-Store) page on our wiki for more information. 107 | 108 | # Issues & Contact 109 | Any bugs or problems discovered with the Launcher should be filed in this project's Issues list. 110 | 111 | # Contributing 112 | ## Base Project 113 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. 114 | -------------------------------------------------------------------------------- /DistroLauncher-Appx/DistroLauncher-Appx.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {f63472f9-d0a0-412e-aa3d-a4e822970486} 5 | DistroLauncher_Appx 6 | en-US 7 | 14.0 8 | true 9 | Windows Store 10 | 10.0.16299.0 11 | 10.0.16215.0 12 | 10.0 13 | Alpine 14 | DistroLauncher-Appx 15 | 16 | 17 | 18 | 19 | Debug 20 | ARM64 21 | 22 | 23 | Debug 24 | x64 25 | 26 | 27 | Release 28 | ARM64 29 | 30 | 31 | Release 32 | x64 33 | 34 | 35 | 36 | Application 37 | true 38 | v141 39 | 40 | 41 | Application 42 | true 43 | v141 44 | true 45 | 46 | 47 | Application 48 | false 49 | true 50 | v141 51 | true 52 | 53 | 54 | Application 55 | false 56 | true 57 | v141 58 | true 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | False 78 | B2E070DE0B3D05D51A5AA5620158104DE48669F6 79 | Always 80 | x64 81 | False 82 | 1 83 | OnApplicationRun 84 | DistroLauncher-Appx_StoreKey.pfx 85 | 86 | 87 | 88 | false 89 | 90 | 91 | 92 | 93 | 94 | Designer 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | true 135 | 136 | 137 | 138 | 139 | true 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | Document 154 | false 155 | Copy $(SolutionDir)\$(platform)\$(Configuration)\launcher.exe into $(SolutionDir)\$(platform)\$(Configuration)\$(ProjectName)\$(targetname).exe 156 | copy $(SolutionDir)\$(platform)\$(Configuration)\launcher.exe $(SolutionDir)\$(platform)\$(Configuration)\$(ProjectName)\$(targetname).exe 157 | $(targetname).exe 158 | 159 | 160 | 161 | 162 | 163 | 164 | Designer 165 | 166 | 167 | 168 | 169 | Designer 170 | 171 | 172 | -------------------------------------------------------------------------------- /DistroLauncher-Appx/Package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | CN=060C3DE6-76FF-4382-8BCB-4D1E0E080DA7 4 | agowa338 5 | MSA 6 | http://www.w3.org/2001/04/xmlenc#sha256 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 36828agowa338.AlpineWSL 363 | 364 | Alpine WSL 365 | 366 | 367 | 368 | 36828agowa338.AlpineLauncher 369 | 370 | 371 | --------------------------------------------------------------------------------