diff --git a/.gitignore b/.gitignore
index 2007446..c236109 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,6 +6,7 @@ tmp
/.vs/
/.vscode/
*.sln
+*.slnx
*.user
*.csproj
*.vcxproj
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a1d62c5..25e355c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -379,10 +379,10 @@ if (DEFINED WSL_DEV_BINARY_PATH) # Development shortcut to make the package smal
WSL_KERNEL_MODULES_PATH="${WSL_DEV_BINARY_PATH}/modules.vhd"
WSL_DEV_INSTALL_PATH="${WSL_DEV_BINARY_PATH}"
WSL_GPU_LIB_PATH="${WSL_DEV_BINARY_PATH}/lib")
-endif()
-if (NOT DEFINED OFFICIAL_BUILD AND ${TARGET_PLATFORM} STREQUAL "x64")
- add_compile_definitions(WSLA_TEST_DISTRO_PATH="${WSLA_TEST_DISTRO_SOURCE_DIR}/wslatestrootfs.vhd")
+ if (NOT OFFICIAL_BUILD AND ${TARGET_PLATFORM} STREQUAL "x64")
+ add_compile_definitions(WSLA_TEST_DISTRO_PATH="${WSLA_TEST_DISTRO_SOURCE_DIR}/wslatestrootfs.vhd")
+ endif()
endif()
# Common include paths
diff --git a/NOTICE.txt b/NOTICE.txt
index 71b6e1d..24abab4 100644
--- a/NOTICE.txt
+++ b/NOTICE.txt
@@ -486,1116 +486,6 @@ Apache-2.0 WITH LLVM-exception
---------------------------------------------------------
-StrawberryPerl 5.28.0.1 - GPL-1.0-or-later OR Artistic-1.0-Perl
-
-
-(c) 2009,2012
-(c) OMIX, Inc.
-Copyright 1998
-Copyright 2000
-Copyright 2004
-Copyright 2010
-Copyright 2001.
-copyright 2014.
-(c) Mnemonic C's
-Copyright 1998 I
-(c) 2000 Dr. Seuss
-(c) Copyright 2000
-COPYRIGHT (c) 2010
-Copyright (c) 2000
-Copyright (c) 2001
-Copyright (c) 2006
-Copyright (c) 2008
-Copyright (c) 2010
-Copyright (c) 2011
-Copyright (c) 2012
-Copyright (c) 2013
-Copyright (c) 2016
-Copyright (c) 2017
-Copyright (c) 2018
-copyright (c) 2011
-Copyright 1995-2015
-Copyright 2009-2017
-copyright 1996 King
-copyright_year 2017
-2003 SP1, Sever 2008
-COPYRIGHT Yves Orton
-Copyright 1996 Zenin
-copyright 1995-2004.
-copyright year//2017
-copyrighted (c) 1996
-(c) 2005 Byrne Reese.
-2003 SP1, Server 2008
-Copyright Mark Fowler
-copyrighted by Adobe.
-Copyright (c) 1994-1997
-Copyright (c) 2001-2015
-Copyright (c) 2004-2014
-Copyright (c) 2005-2015
-Copyright (c) 2010 KMX.
-Copyright (c) 2010-2012
-Copyright (c) 2010-2016
-Copyright (c) 2011-2015
-Portions Copyright 2001
-copyright 1996 King Tut
-copyright 2000 Fred Foo
-(c) Rafael Garcia-Suarez
-Copyright (c) 1997, 1998
-Copyright (c) 2009, 2011
-Copyright Mark Overmeer.
-(c) 2017 Unicode(r), Inc.
-Copyright (c) 2001 Single
-Copyright (c) 2005 by mst
-Copyright (c) 2006 - 2011
-Copyright (c) 2007 - 2010
-Copyright (c) 2007 - 2013
-Copyright 2000 Gisle Aas.
-Copyright 2001 Gisle Aas.
-Copyright 2002 Gisle Aas.
-Copyright 2002 Johnny Lee
-Copyright 2003, Gisle Aas
-Copyright 2006 Yves Orton
-Copyright 2009 Gisle Aas.
-Gisle Aas, Copyright 2003
-copyright 2004, Published
-copyright by Ken Williams
-COPYRIGHT Tom Christiansen
-Copyright (c) 2009 by yvbl
-Copyright 2003 Graham Barr
-Copyright 2004 Simon Flack
-Copyright 2015 Chad Granum
-Copyright 2016 Chad Granum
-Copyright 2016 cPanel Inc.
-Copyright 2018 Chad Granum
-copyright (c) 2008 by yvbl
-(c) 2004 Dennis K. Paulsen.
-(c) Copyright 2000 Fred Foo
-Copyright (c) 1996 by Eryq.
-Copyright (c) 2007 - 2010 L
-Copyright (c) Ken Williams.
-Copyright 1999 Tye McQueen.
-Copyright 2001, Larry Wall.
-Copyright 2006 Chris Dolan.
-Copyright 2010 Adam Kennedy
-Copyright 2010 Grant McLean
-Copyright 2012 David Golden
-Copyright 2017 Jens Rehsack
-copyright 2008 Audrey Tang.
-Copyright (c) 1998 Gisle Aas
-Copyright (c) 2001,2002 RIPE
-Copyright (c) 2001-2005 RIPE
-Copyright (c) 2002 Your Name
-Copyright (c) 2003 Tim Bunce
-Copyright (c) 2003-2005 RIPE
-Copyright (c) 2007 Bob Free.
-Copyright (c) 2015 Bob Free.
-Copyright 2006-2018 Sisyphus
-Copyright 2009, Paul Fenwick
-Copyright 2010, Shlomi Fish.
-Copyright 2011 Joachim Zobel
-Copyright 2012 David Oswald.
-Copyright 2014 Laurent Dami.
-Copyright 2016 Unicode, Inc.
-Copyright 2017 Stefan Hermes
-Copyright, 2005 Simon Wistow
-Copyright, 2006 Simon Wistow
-Copyright (c) 1995 Your Name.
-Copyright (c) 1996 Dave Roth.
-Copyright (c) 1998, Tim Bunce
-Copyright (c) 2001 Dave Cross
-Copyright (c) 2002 Sam Tregar
-Copyright (c) 2009-2010, Goro
-Copyright (c) 2013 Fred Moyer
-Copyright (c) 2014 Steve Hay.
-Copyright (c) 2016 Cpanel Inc
-Copyright (c) Takumi Akiyama.
-Copyright 2000-2002 Tim Bunce
-Copyright 2001, Sean M. Burke
-Copyright 2002 Sreeji K. Das.
-Copyright 2002-2014 Dan Kogai
-Copyright 2004 by Daniel Muey
-Copyright 2006 by Randy Kobes
-Copyright 2010 Curtis Jewell.
-Copyright 2013, Niels Thykier
-Copyright Laurent Dami, 2014.
-(c) Copyright 2007 Arthur Dent
-Copyright (c) 2000 Mark Kvale.
-Copyright (c) 2004-2005 Nokia.
-Copyright (c) 2005 Byrne Reese
-Copyright (c) 2006 Google Inc.
-Copyright (c) 2006-2017 Hatuka
-Copyright (c) 2009, Goro Fuji.
-Copyright (c) 2009-2012 Hatuka
-Copyright (c) 2009-2013 Hatuka
-Copyright (c) 2009-2018 Hatuka
-Copyright (c) 2011 Mark Allen.
-Copyright (c) 2012 M. Nunberg.
-Copyright (c) 2013 Google Inc.
-Copyright (c) 2014 cPanel Inc.
-Copyright (c) 2017 Mark Allen.
-Copyright (c) 2017 Reini Urban
-Copyright 1987-2018 Larry Wall
-Copyright 1995 Martijn Koster.
-Copyright 1995, Martijn Koster
-Copyright 1995-1998 Gisle Aas.
-Copyright 1995-1999 Gisle Aas.
-Copyright 1995-2000 Gisle Aas.
-Copyright 1995-2001 Gisle Aas.
-Copyright 1995-2004 Gisle Aas.
-Copyright 1995-2006 Gisle Aas.
-Copyright 1995-2009 Gisle Aas.
-Copyright 1995-2009, Gisle Aas
-Copyright 1995-2017 Mark Adler
-Copyright 1996,2001 Gisle Aas.
-Copyright 1996-2001 Gisle Aas.
-Copyright 1996-2001, Gisle Aas
-Copyright 1996-2003, Gisle Aas
-Copyright 1996-2004 Gisle Aas.
-Copyright 1996-2010, Gisle Aas
-Copyright 1996-2016 Gisle Aas.
-Copyright 1997 Uwe Hollerbach.
-Copyright 1997-1998, Gisle Aas
-Copyright 1997-1999 Gisle Aas.
-Copyright 1997-2011 Gisle Aas.
-Copyright 1998-1999 Gisle Aas.
-Copyright 1998-2000 Gisle Aas.
-Copyright 1998-2001 Gisle Aas.
-Copyright 1998-2002 Gisle Aas.
-Copyright 1998-2003 Gisle Aas.
-Copyright 1998-2005 Gisle Aas.
-Copyright 1998-2006 Gisle Aas.
-Copyright 1998-2008 Gisle Aas.
-Copyright 1998-2010 Gisle Aas.
-Copyright 1999-2004 Gisle Aas.
-Copyright 2001 Benjamin Trott.
-Copyright 2001-2017 Ray Finch.
-Copyright 2002, Sean M. Burke.
-Copyright 2003 Julius C. Duque
-Copyright 2007 David Cantrell.
-Copyright 2010 by Mark Dootson
-Copyright 2012 Steffen Mueller
-copyright (c) 2002 Jos Boumans
-copyright (c) 2005 Jos Boumans
-copyright (c) 2014 cPanel Inc.
-(c) 1995 Microsoft Corporation.
-(c) 1999 Microsoft Corporation.
-Copyright (c) 1998 Graham Barr.
-Copyright (c) 2000 Clark Cooper
-Copyright (c) 2000 Graham Barr.
-Copyright (c) 2002 Mark Fowler.
-Copyright (c) 2002 T.J. Mather.
-Copyright (c) 2003 Graham Barr.
-Copyright (c) 2004 X Consortium
-Copyright (c) 2006 Bob Mathews.
-Copyright (c) 2006 DelTel, Inc.
-Copyright (c) 2008 Paul Fenwick
-Copyright (c) 2010 Mark Dootson
-Copyright (c) 2011 Dick Franks.
-Copyright (c) 2011 Tim Jenness.
-Copyright (c) 2012 Dick Franks.
-Copyright (c) 2013 Dick Franks.
-Copyright (c) 2014 Dick Franks.
-Copyright (c) 2015 Dick Franks.
-Copyright (c) 2016 Dick Franks.
-Copyright (c) 2016, cPanel Inc.
-Copyright (c) 2017 Dick Franks.
-Copyright (c) Mihai Bazon 2008.
-Copyright (c) MingW-W64 Project
-Copyright 1995-1999, Gisle Aas.
-Copyright 2002 Jonathan Leffler
-Copyright 2008 by Laurent Dami.
-Copyright 2011 Christian Hansen
-Copyright 2012 by Dana Jacobsen
-Copyright 2013 by Dana Jacobsen
-Copyright 2017 by Dana Jacobsen
-copyright 1998 by Gabor Egressy
-copyright 2000 - 2004 Ned Konz.
-copyrighted by Dovecot authors.
-Copyright (c) 1997 Michael Fuhr.
-Copyright (c) 2000 Andy Wardley.
-Copyright (c) 2000 Michael Fuhr.
-Copyright (c) 2000, W3Works, LLC
-Copyright (c) 2001, Kurt Kincaid
-Copyright (c) 2003 Simon Cozens.
-Copyright (c) 2008 Andy Wardley.
-Copyright (c) 2008 Yuval Kogman.
-Copyright (c) 2016 Unicode, Inc.
-Copyright (c) jQuery Foundation.
-Copyright 1995 Lincoln D. Stein.
-Copyright 1995,1996 Neil Winton.
-Copyright 1995-1996 Neil Winton.
-Copyright 1998 The Perl Journal.
-Copyright 1999 Barrie Slaymaker.
-Copyright 1999-2004 Grant McLean
-Copyright 2001 Barrie Slaymaker.
-Copyright 2001, Barrie Slaymaker
-Copyright 2002-2008 by chromatic
-Copyright 2004-2010 John Peacock
-Copyright 2004-2018 by Dan Sully
-Copyright 2005-2008 Andy Lester.
-Copyright 2007-2009 Matt S Trout
-Copyright 2008 by Chia-liang Kao
-Copyright 2011-2015 Mateu Hunter
-Copyright 2013 Tom Christiansen.
-Copyright 2018 Gianni Ceccarelli
-Copyright MM-MMX, John McNamara.
-Copyrights 1995-2000 Graham Barr
-copyright (c) 1994 by Tim Bunce.
-copyright 2000 The Perl Journal.
-COPYRIGHT (c) MMV, John McNamara.
-Copyright (c) 1990-2007 Info-ZIP.
-Copyright (c) 1994-2006 Tim Bunce
-Copyright (c) 1994-2007 Tim Bunce
-Copyright (c) 1997-8 Graham Barr.
-Copyright (c) 1999, Ken Williams.
-Copyright (c) 2000-2002 Ned Konz.
-Copyright (c) 2001 Paul Kulchenko
-Copyright (c) 2002 James Tillman.
-Copyright (c) 2002 Richard Clamp.
-Copyright (c) 2002 Sean M. Burke.
-Copyright (c) 2003 Richard Clamp.
-Copyright (c) 2004 Sean M. Burke.
-Copyright (c) 2004 by Jeff Zucker
-Copyright (c) 2005 Paul Marquess.
-Copyright (c) 2005, Damian Conway
-Copyright (c) 2007 Martin Kutter.
-Copyright (c) 2007-14 Rob Kinyon.
-Copyright (c) 2009 Yann Kerherve.
-Copyright (c) 2010-2015 the Moo L
-Copyright (c) 2012, Steve Peters.
-Copyright (c) 2013 by Joel Berger
-Copyright (c) 2014 A. Sinan Unur.
-Copyright (c) 2014 Douglas Wilson
-Copyright (c) 2017 Stefan Hermes.
-Copyright 2000,2001 Sean M. Burke
-Copyright 2001 Abhijit Menon-Sen.
-Copyright 2001-2014. Ingy dot Net
-Copyright 2002-2006 Abe Timmerman
-Copyright 2002-2007 Adrian Howard
-Copyright 2008-2009, Paul Fenwick
-Copyright Andy Wardley 1998-2007.
-Copyright Micheal G Schwern 2001.
-copyright (c) 2004 by Casey West.
-copyright (c) 2014 by Arthur Axel
-copyright (c) 2014 by Mark Allen.
-copyright (c) 2016 by Arthur Axel
-copyright (c) 2018 by Arthur Axel
-copyright 1999-2010 W3Works, LLC.
-copyright 2004, Lincoln D. Stein.
-parts copyright 2011 Aaron Crane.
-COPYRIGHT (c) MMXV, John McNamara.
-Copyright (c) 1994-2013 Larry Wall
-Copyright (c) 1997 Alan Citterman.
-Copyright (c) 1997 Jochen Wiedmann
-Copyright (c) 1998+ Sean M. Burke.
-Copyright (c) 1998-2004 Tom Hughes
-Copyright (c) 2000 Paul Kulchenko.
-Copyright (c) 2000 Simon Matthews.
-Copyright (c) 2000, Andrew Benham.
-Copyright (c) 2000-9, Leon Brocard
-Copyright (c) 2001+ Sean M. Burke.
-Copyright (c) 2001, Paul Marquess.
-Copyright (c) 2003-2005 Yves Orton
-Copyright (c) 2003-2017 J-L Morel.
-Copyright (c) 2006 Simon Wilkinson
-Copyright (c) 2007 Brandon L Black
-Copyright (c) 2008- Martin Kutter.
-Copyright (c) 2010 Krasimir Berov.
-Copyright (c) 2010 by Jens Rehsack
-Copyright (c) 2011 by Dave Rolsky.
-Copyright (c) 2013 Chris Williams.
-Copyright (c) 2013-2014 Steve Hay.
-Copyright (c) 2013-2016 Steve Hay.
-Copyright (c) 2013-2017 Steve Hay.
-Copyright (c) 2014 by Dave Rolsky.
-Copyright (c) 2015-2016 cPanel Inc
-Copyright (c) 2016 Chris Marshall.
-Copyright (c) 2016 by Dave Rolsky.
-Copyright (c) 2017 by Dave Rolsky.
-Copyright 1999 - 2006 Tye McQueen.
-Copyright 2000-2005 Sean M. Burke.
-Copyright 2000-2018, Steve Hancock
-Copyright 2001, t0mas@netlords.net
-Copyright 2001-2003 AxKit.com Ltd.
-Copyright 2001-2009 AxKit.com Ltd.
-Copyright 2001-2018. Ingy dot Net.
-Copyright 2002 by Janek Schleicher
-Copyright 2002-2010 by Audrey Tang
-Copyright 2003 - 2007 Fergal Daly.
-Copyright 2003 by Michel Rodriguez
-Copyright 2003-2008 by Audrey Tang
-Copyright 2003-2010 by Audrey Tang
-Copyright 2003-2011 by Audrey Tang
-Copyright 2004-2009 by Audrey Tang
-Copyright 2004-2014. Ingy dot Net.
-Copyright 2004-2017. Ingy dot Net.
-Copyright 2005, 2006 Adam Kennedy.
-Copyright 2005-2018. Ingy dot Net.
-Copyright 2006,2008 by Randy Kobes
-Copyright 2007-2018. Ingy dot Net.
-Copyright 2012 Alessandro Ghedini.
-Copyright 2013 Alessandro Ghedini.
-Copyright 2013 by Kenichi Ishigaki
-Copyright 2013-2014, Niels Thykier
-Copyright 2014 Alessandro Ghedini.
-Copyright MM-MMXII, John McNamara.
-Copyright MM-MMXVI, John McNamara.
-Portions Copyright 2001 Ray Finch.
-copyright (c) 2009 by Philip Gwyn.
-copyright (c) 2017 by Dave Rolsky.
-copyright (c) 2018 by Dave Rolsky.
-copyright 2002, Daniel J. Harasty.
-parts copyright 2005 Steve Peters.
-parts copyright 2006 Chris Nandor.
-parts copyright 2009 Adam Kennedy.
-parts copyright 2010 Adam Kennedy.
-COPYRIGHT 2001-2007, AxKit.com Ltd.
-Copyright (c) 1998, Jochen Wiedmann
-Copyright (c) 2000 Andrew Tridgell.
-Copyright (c) 2001 Michael Hennecke
-Copyright (c) 2001, Colin McMillen.
-Copyright (c) 2001-2010 Neil Bowers
-Copyright (c) 2002 Jonathan Leffler
-Copyright (c) 2002-2003, Rob Brown.
-Copyright (c) 2002-2009 Neil Bowers
-Copyright (c) 2003 Chris Reinhardt.
-Copyright (c) 2003-2018 Mark Shelor
-Copyright (c) 2004 Peter Marschall.
-Copyright (c) 2006-2008 Gabor Szabo
-Copyright (c) 2007,2008 NLnet Labs.
-Copyright (c) 2007-10 Max Maischein
-Copyright (c) 2009 by David Golden.
-Copyright (c) 2011 by Joachim Zobel
-Copyright (c) 2012 by Daniel Dragan
-Copyright (c) 2013 by David Golden.
-Copyright (c) 2013,2015 Dick Franks
-Copyright (c) 2014 by David Golden.
-Copyright (c) 2014,2017 Dick Franks
-Copyright (c) 2014-2017 cPanel Inc.
-Copyright (c) 2016 by Jesse Luehrs.
-Copyright (c) 2016- by Jens Rehsack
-Copyright 1995-1998,2004 Gisle Aas.
-Copyright 2000-2010, John McNamara.
-Copyright 2001 - 2011 Adam Kennedy.
-Copyright 2001 by Jarkko Hietaniemi
-Copyright 2001 by Michael G Schwern
-Copyright 2001-2009, AxKit.com Ltd.
-Copyright 2003, 2004 by Fergal Daly
-Copyright 2003, R. Barrie Slaymaker
-Copyright 2005 - 2009 Adam Kennedy.
-Copyright 2005 - 2011 Adam Kennedy.
-Copyright 2005 - 2012 Adam Kennedy.
-Copyright 2006 - 2010 Adam Kennedy.
-Copyright 2006 - 2011 Adam Kennedy.
-Copyright 2006 - 2013 Adam Kennedy.
-Copyright 2006-2008 Curtis Ovid Poe
-Copyright 2007 - 2011 Adam Kennedy.
-Copyright 2007-2011 Andy Armstrong.
-Copyright 2008 - 2009 Adam Kennedy.
-Copyright 2008 - 2011 Adam Kennedy.
-Copyright 2009 - 2011 Adam Kennedy.
-Copyright 2009 - 2012 Adam Kennedy.
-Copyright 2010- Tatsuhiko Miyagawa.
-Copyright 2011 Breno G. de Oliveira
-Copyright 2014 - 2018 Jens Rehsack.
-Copyright 2015-2017 by Jens Rehsack
-Copyright 2017- by Kenichi Ishigaki
-copyright (c) 2003 by Simon Cozens.
-copyright (c) 2004 by Simon Cozens.
-copyright (c) 2010 by Adam Kennedy.
-copyright (c) 2013 by David Golden.
-copyright (c) 2013 by Jesse Luehrs.
-copyright (c) 2014 by Jesse Luehrs.
-copyright (c) 2015 by Robin Berjon.
-copyright (c) 2016 by Adam Kennedy.
-copyright (c) 2016 by David Golden.
-copyright (c) 2016 by Jesse Luehrs.
-copyright (c) 2017 by Adam Kennedy.
-copyright (c) 2017 by Graham Ollis.
-parts copyright 2000 Sean M. Burke.
-Copyright (c) 1995-1997 Graham Barr.
-Copyright (c) 1995-1998 Graham Barr.
-Copyright (c) 1995-2004 Graham Barr.
-Copyright (c) 1995-2006 Graham Barr.
-Copyright (c) 1995-2009 Graham Barr.
-Copyright (c) 1997, 1999 Tom Phoenix
-Copyright (c) 1997-1998 Graham Barr.
-Copyright (c) 1998-2004 Graham Barr.
-Copyright (c) 1998-2005 Graham Barr.
-Copyright (c) 1998-2011 Graham Barr.
-Copyright (c) 2000 Ilya Zakharevich.
-Copyright (c) 2000,2002 Thomas Pfau.
-Copyright (c) 2000-2004 Tim Jenness.
-Copyright (c) 2002-2004 Graham Barr.
-Copyright (c) 2003 Sidney Markowitz.
-Copyright (c) 2003- Euro6IX project.
-Copyright (c) 2005-6 Joshua Hoblitt.
-Copyright (c) 2006, Portugal Telecom
-Copyright (c) 2008 - 2010 Kazuho Oku
-Copyright (c) 2009 Tokuhiro Matsuno.
-Copyright (c) 2009,2012 Dick Franks.
-Copyright (c) 2009-2011 Dick Franks.
-Copyright (c) 2011-2012 Dick Franks.
-Copyright (c) 2011-2014 Reini Urban.
-Copyright (c) 2012 Tom Christiansen.
-Copyright (c) 2012,2016 Dick Franks.
-Copyright (c) 2012-2013 Google, Inc.
-Copyright (c) 2012-2017 Joel Berger.
-Copyright (c) 2017- Kenichi Ishigaki
-Copyright 1987-2018, Larry Wall Perl
-Copyright 1997 - 2001 Damian Conway.
-Copyright 2001-2008 Barrie Slaymaker
-Copyright 2006, William Hart. SIMPQS
-Copyright 2006-2016 by Brian Cassidy
-Copyright 2007-2008 Brandon L. Black
-Copyright 2008-2009 by Brian Cassidy
-Copyright 2009 - 2011 Jerome Quelin.
-Copyright 2011 by Serguei Trouchelle
-Copyright 2011-2017 by Dana Jacobsen
-Copyright 2012-2013 by Dana Jacobsen
-Copyright 2012-2016 by Dana Jacobsen
-Copyright 2014 Christopher J. Madsen
-Copyright 2014-2016 by Dana Jacobsen
-Copyright MM-MMXVIII, John McNamara.
-copyright (c) 1998 by Gabor Egressy.
-copyright (c) 2001 by Damian Conway.
-copyright (c) 2007 by Shawn M Moore.
-copyright (c) 2008 by Shawn M Moore.
-copyright (c) 2012-2017 Joel Berger.
-copyright 2002 - 2007 Matt Sergeant.
-(c) by Tels L
-Copyright (c) 1996-2000 Andy Wardley.
-Copyright (c) 1996-2001 Andy Wardley.
-Copyright (c) 1996-2006 Andy Wardley.
-Copyright (c) 1996-2007 Andy Wardley.
-Copyright (c) 1996-2008 Andy Wardley.
-Copyright (c) 1996-2013 Andy Wardley.
-Copyright (c) 1996-2014 Andy Wardley.
-Copyright (c) 1996-2015 Andy Wardley.
-Copyright (c) 1997,1998 Michael Fuhr.
-Copyright (c) 1997-2000 Michael Fuhr.
-Copyright (c) 1997-2001 Michael Fuhr.
-Copyright (c) 1997-2003 Andy Wardley.
-Copyright (c) 1997-2007 Andy Wardley.
-Copyright (c) 1998 by Jochen Wiedmann
-Copyright (c) 1998-2008 Andy Wardley.
-Copyright (c) 1999-2003 Joshua Chamas
-Copyright (c) 2000,2001 Michael Fuhr.
-Copyright (c) 2000-2007 Andy Wardley.
-Copyright (c) 2001-2006 Ken Williams.
-Copyright (c) 2001-2007 Andy Wardley.
-Copyright (c) 2001-2008 Ken Williams.
-Copyright (c) 2001-2008 Robin Berjon.
-Copyright (c) 2001-2009 Andy Wardley.
-Copyright (c) 2001-2011 Ken Williams.
-Copyright (c) 2002 Tim Bunce Ireland.
-Copyright (c) 2002,3,4 Sean M. Burke.
-Copyright (c) 2002-2007 Andy Wardley.
-Copyright (c) 2003-2005 Ken Williams.
-Copyright (c) 2003-2014 Max Maischein
-Copyright (c) 2006 by Steffen Mueller
-Copyright (c) 2006, 2013 Google Inc..
-Copyright (c) 2007-2008 Martin Kutter
-Copyright (c) 2009-2013 John McNamara
-Copyright (c) 2010-2014 A. Sinan Unur
-Copyright (c) 2010-2018 Sullivan Beck
-Copyright (c) 2011-2015 Buddy Burden.
-Copyright (c) 2011-2018 Sullivan Beck
-Copyright (c) 2012 by Leon Timmermans
-Copyright (c) 2013-2017 Jens Rehsack.
-Copyright (c) 2014 by David A Golden.
-Copyright (c) 2015 by Salvador FandiE
-Copyright (c) 2017-2018, Reini Urban.
-Copyright (c) 2018 by David A Golden.
-Copyright 1990,2015 by Johan Vromans.
-Copyright 1996-1998 Gurusamy Sarathy.
-Copyright 1999-2000 Michael A. Chase.
-Copyright 2001-2011 Jarkko Hietaniemi
-Copyright 2006 - 2011 Benjamin Trott.
-Copyright 2013 - 2017 by Jens Rehsack
-Copyrights 1995-2018 by Mark Overmeer
-Copyrights 2016-2018 by Mark Overmeer
-Portions copyright 2007 David Golden.
-copyright (c) 1994-2017 by Gisle Aas.
-copyright (c) 1998 by Maurice Aubrey.
-copyright (c) 2001-2017 by Gisle Aas.
-copyright (c) 2002 - 2009 Jos Boumans
-copyright (c) 2002-2017 by Gisle Aas.
-copyright (c) 2004 by Ricardo SIGNES.
-copyright (c) 2005 by Ricardo SIGNES.
-copyright (c) 2006 by Ricardo Signes.
-copyright (c) 2007 by Ricardo Signes.
-copyright (c) 2010 by Ricardo Signes.
-copyright (c) 2013 by Ricardo Signes.
-copyright (c) 2015 by Ricardo SIGNES.
-copyright (c) 2015 by Ricardo Signes.
-copyright (c) 2017 by Ricardo Signes.
-copyright (c) 2018 by Ricardo Signes.
-(c) Copyright 1998-2007 by Mark Mielke
-Copyright (c) 1994,1997,1998 Tim Bunce
-Copyright (c) 1995-2011 Paul Marquess.
-Copyright (c) 1995-2016 Paul Marquess.
-Copyright (c) 1995-2018 Paul Marquess.
-Copyright (c) 1997 Roderick Schertler.
-Copyright (c) 1997,1999 Tim Bunce With
-Copyright (c) 1997-2007, Damian Conway
-Copyright (c) 1997-2015 Paul Marquess.
-Copyright (c) 1998, Robert D. Cameron.
-Copyright (c) 1998-2004 Sean M. Burke.
-Copyright (c) 1999-2002 Marko Asplund.
-Copyright (c) 1999-2004 Sean M. Burke.
-Copyright (c) 2000 by James H. Turner.
-Copyright (c) 2000, Vipul Ved Prakash.
-Copyright (c) 2000-2006 Kawai Takanori
-Copyright (c) 2000-2008 Takanori Kawai
-Copyright (c) 2001, Vipul Ved Prakash.
-Copyright (c) 2001-2004 Sean M. Burke.
-Copyright (c) 2001-2011 Ian Robertson.
-Copyright (c) 2002 Andreas Gustafsson.
-Copyright (c) 2002,2011 Richard Clamp.
-Copyright (c) 2002-2004 Sean M. Burke.
-Copyright (c) 2002-2007 Sean M. Burke.
-Copyright (c) 2002-2009 Richard Clamp.
-Copyright (c) 2004-2009 by Jeff Zucker
-Copyright (c) 2005 Aristotle Pagaltzis
-Copyright (c) 2005-2018 Paul Marquess.
-Copyright (c) 2006-2007 David Landgren
-Copyright (c) 2009-2017 H.Merijn Brand
-Copyright (c) 2011-2018 Paul Marquess.
-Copyright (c) AEvar Arnfjord Bjarmason
-Copyright 1995-1998, Lincoln D. Stein.
-Copyright 2005-2010 by Steffen Mueller
-Copyright 2006-2009 by Steffen Mueller
-Copyright 2006-2010 by Steffen Mueller
-Portions Copyright (c) 2002 Rob Brown.
-copyright (c) 1996- by Andreas Koenig.
-copyright (c) 2001 - 2007, Jos Boumans
-copyright (c) 2003 Mark Jason Dominus.
-copyright (c) 2005 by Curtis Ovid Poe.
-copyright (c) 2008 by Florian Ragwitz.
-copyright (c) 2008 by Leon Timmermans.
-copyright (c) 2009 by Florian Ragwitz.
-copyright (c) 2010 by Leon Timmermans.
-copyright (c) 2012 by Leon Timmermans.
-copyright (c) 2013 by Karen Etheridge.
-copyright (c) 2013 by Leon Timmermans.
-copyright (c) 2014 by Karen Etheridge.
-copyright (c) 2014 by Leon Timmermans.
-copyright (c) 2015 by Leon Timmermans.
-copyright 1995-2005, Lincoln D. Stein.
-copyright 1995-2007, Lincoln D. Stein.
-copyright 1995-2010, Lincoln D. Stein.
-parts copyright 2006 Stephen Steneker.
-Copyright (c) 1995-98 Ilya Zakharevich.
-Copyright (c) 1997,1998 Jochen Wiedmann
-Copyright (c) 1998-2002 Ernesto Guisado
-Copyright (c) 1999, Kenneth Albanowski.
-Copyright (c) 2000-2001 Paul Kulchenko.
-Copyright (c) 2000-2001, Damian Conway.
-Copyright (c) 2000-2004 Paul Kulchenko.
-Copyright (c) 2000-2005 Paul Kulchenko.
-Copyright (c) 2000-2007 Paul Kulchenko.
-Copyright (c) 2000-2008 James H. Turner
-Copyright (c) 2000-2014, Damian Conway.
-Copyright (c) 2001-2014, Damian Conway.
-Copyright (c) 2002-2005 Peter Behroozi.
-Copyright (c) 2003-2005 Allison Randal.
-Copyright (c) 2006 by Philipp K. Janert
-Copyright (c) 2006-2008 by Paul Fenwick
-Copyright (c) 2007, Tim Bunce, Ireland.
-Copyright (c) 2007-2011, Andy Armstrong
-Copyright (c) 2007-2016 H.Merijn Brand.
-Copyright (c) 2007-2018 H.Merijn Brand.
-Copyright (c) 2009-2012 Daniel Stenberg
-Copyright (c) 2010, Tim Bunce, Ireland.
-Copyright (c) 2011 John Scoles. Canada.
-Copyright (c) 2013-2015 Salvador FandiE
-Copyright (c) 2016,2017 by Jens Rehsack
-Copyright 1995 - 2013 by Andreas Koenig
-Copyright 2010 Gisle Aas
-Copyright 2015-2018 by Janek Schleicher
-Parts Copyright (c) 2000-2004 Ned Konz.
-Portions Copyright (c) 2014 Dick Franks
-Portions copyright 2007, Joel Bernstein
-copyright (c) 1998-2003 by Mark Mielke.
-copyright (c) 2002 by Ilya Zakharevich.
-copyright (c) 2004-2016 by Andy Lester.
-copyright (c) 2015 by Christian Hansen.
-copyright (c) 2016 by Christian Hansen.
-parts copyright 2008 Wolfgang Sourdeau.
-(c) JS Foundation and other contributors
-COPYRIGHT (c) MM-MMXVIII, John McNamara.
-Copyright (c) 1996, 1997 Malcolm Beattie
-Copyright (c) 1998-2001 Jochen Wiedmann.
-Copyright (c) 2000-2011 Adekunle Olonoh.
-Copyright (c) 2000-2018 by Steve Hancock
-Copyright (c) 2003,2004 Chris Reinhardt.
-Copyright (c) 2004-2006 Peter Marschall.
-Copyright (c) 2004-2011 Steffen Goeldner
-Copyright (c) 2006-2007 by (Anno Siegel)
-Copyright (c) 2006-2014 Steffen Ullrich.
-Copyright (c) 2008, 2009 Florian Ragwitz
-Copyright (c) 2009 Christopher Marshall.
-Copyright (c) 2013-2014, 2016 Steve Hay.
-Copyright 1995-1997,2002-2004 Gisle Aas.
-Copyright 2001-2008 by Michael G Schwern
-Copyright 2003 Matthew Simon Cavalletto.
-Copyright 2004-2007, 2010 by Audrey Tang
-Copyright 2007-2008 by Michael G Schwern
-Copyright 2011-2017 Breno G. de Oliveira
-Copyright 2011-2017 by Christian Hansen.
-Copyright 2013-2017 by Christian Hansen.
-Copyright 2015-2017 by Christian Hansen.
-Portions Copyright (c) 2011 Dick Franks.
-Portions Copyright (c) 2012 Dick Franks.
-Portions Copyright (c) 2013 Dick Franks.
-Portions Copyright (c) 2015 Dick Franks.
-Portions Copyright (c) 2017 Dick Franks.
-Portions Copyright 2006 Portugal Telecom
-copyright (c) 2008 by John Napiorkowski.
-copyright (c) 2014-2018 by Graham Ollis.
-copyright (c) 2016 by chromatic@wgz.org.
-parts copyright 2008 Francis J. Lacoste.
-parts copyright 2009-2011 Jerome Quelin.
-COPYRIGHT (c) 1995 Microsoft Corporation.
-Copyright (c) 1994-2003 Tim Bunce Ireland
-Copyright (c) 1994-2010 Tim Bunce Ireland
-Copyright (c) 1994-2012 Tim Bunce Ireland
-Copyright (c) 1995-2001, Raphael Manfredi
-Copyright (c) 1996-2017 Gurusamy Sarathy.
-Copyright (c) 1997-2002 Tim Bunce Ireland
-Copyright (c) 1999-2000 by Marek Rouchal.
-Copyright (c) 2000-2003 Stephen McCamant.
-Copyright (c) 2001-2016 by Marek Rouchal.
-Copyright (c) 2002-2005 Steffen Goeldner.
-Copyright (c) 2003 - 2018 by Dave Rolsky.
-Copyright (c) 2004 by the Perl 5 Porters.
-Copyright (c) 2006-2009 by Steffen Muller
-Copyright (c) 2009-2011,2017 Dick Franks.
-Copyright (c) 2012 - 2017 by Dave Rolsky.
-Copyright (c) 2016 - 2018 by Dave Rolsky.
-Copyright (c) 2017, GoodData Corporation.
-Copyright 2004, 2006, 2010 by Audrey Tang
-Copyright 2010 by Makamaka Hannyaharamitu
-Copyright 2011-2013 by Serguei Trouchelle
-Copyright 2011-2014 by Serguei Trouchelle
-Portions Copyright (c) 1997 Michael Fuhr.
-Portions Copyright (c) 2001 Tony M Hoyle.
-Portions Copyright (c) 2003 Olaf Kolkman.
-Portions Copyright (c) 2005 Olaf Kolkman.
-copyright (c) 2003 - 2018 by Dave Rolsky.
-copyright (c) 2014, 2017 by Toby Inkster.
-parts copyright 2006 - 2012 Adam Kennedy.
-parts copyright 2007 - 2009 Adam Kennedy.
-parts copyright 2008 - 2009 Adam Kennedy.
-parts copyright 2008 - 2013 Adam Kennedy.
-parts copyright 2010 - 2011 Adam Kennedy.
-Copyright (c) 1994-2005 Tim Bunce, Ireland
-Copyright (c) 1996, Kenneth J. Albanowski.
-Copyright (c) 1998, 2002, 2003 Jon Orwant.
-Copyright (c) 1998-2004 by Jochen Wiedmann
-Copyright (c) 2000 - 2017 by David Rolsky.
-Copyright (c) 2001,2002 Michael K. Neylon.
-Copyright (c) 2002,2003 Tim Bunce Ireland.
-Copyright (c) 2006-2007 Jarkko Hietaniemi.
-Copyright (c) 2006-2009 by Steffen Mueller
-Copyright (c) 2010-2018, Sebastian Riedel.
-Copyright (c) 2011, 2012, 2013 Andrew Main
-Copyright (c) 2012-2018 by Richard Simoes.
-Portions Copyright (c) 1994-1997 Tim Bunce
-Portions copyright 2006-2008 Adam Kennedy.
-(c) (c) PS. Attributes PSPS EUR. Attributes
-Additions copyright 1996 by Charles Bailey.
-Copyright (c) 1994,1995,1996,1998 Tim Bunce
-Copyright (c) 1994-2006 Tim Bunce. Ireland.
-Copyright (c) 1994-2012 Tim Bunce. Ireland.
-Copyright (c) 1998,1999 Kenneth Albanowski.
-Copyright (c) 2000, 2003, 2004 Tim Jenness.
-Copyright (c) 2000-2001, Vipul Ved Prakash.
-Copyright (c) 2000-2008, Vipul Ved Prakash.
-Copyright (c) 2001-2002 Michael G. Schwern.
-Copyright (c) 2002 VeriSign, Mike Schiraldi
-Copyright (c) 2004, 2008 Matthijs van Duin.
-Copyright (c) 2005, 2006 by David B. Robins
-Copyright (c) 2007, 2008, 2009 Matt S Trout
-Copyright (c) 2008 by Larry Wall and others
-Copyright (c) 2008-2009 Greg Sabino Mullane
-Copyright (c) 2012 by Larry Wall and others
-Copyright (c) 2014 by Larry Wall and others
-Copyright (c) 2015 by Larry Wall and others
-Copyright 1990-1992 RSA Data Security, Inc.
-Copyright 1991-1992 RSA Data Security, Inc.
-Copyright 2002, 2003, 2004 by Autrijus Tang
-Copyright 2005 Ken Williams and Randy Sims.
-Copyright 2013, Paul Fenwick
-Copyright E Chris Williams and Jos Boumans.
-Portions Copyright (c) 1997 Alan Citterman.
-copyright (c) 2008 by Infinity Interactive.
-copyrighted by the Free Software Foundation
-Copyright (c) 1994-2018, Greg Sabino Mullane
-Copyright (c) 1996-2009 David Muir Sharnoff.
-Copyright (c) 2000 Lincoln D. Stein Slightly
-Copyright (c) 2000, Tim Bunce, Thomas Lowery
-Copyright (c) 2000, by Larry Wall and others
-Copyright (c) 2002, ActiveState Corporation.
-Copyright (c) 2004-14 by the Perl 5 Porters.
-Copyright (c) 2005 Olaf Kolkman, NLnet Labs.
-Copyright (c) 2007 Olaf Kolkman, NLnet Labs.
-Copyright (c) 2007-2008, Tim Bunce, Ireland.
-Copyright (c) 2008 Olaf Kolkman, NLnet Labs.
-Copyright (c) 2009 Olaf Kolkman, NLnet Labs.
-Copyright (c) 2011 - 2018 by Salvador FandiE
-Copyright 1997, 2000, 2002, 2013 Jay Rogers.
-Copyright 2006 by Infinity Interactive, Inc.
-Portions Copyright (c) 2002 Jeffrey W. Baker
-Portions Copyright (c) 2003 Chris Reinhardt.
-Portions Copyright (c) 2007,2008 NLnet Labs.
-Portions Copyright (c) 2007-2015 Dick Franks
-Portions Copyright 1994 David Muir Sharnoff.
-copyright (c) 1996 by Kenneth J. Albanowski.
-copyright (c) 2013 by Tim Jenness and the UK
-copyright (c) 2014 by Christopher J. Madsen.
-portions Copyright (c) 1997-2004 Jeff Urlwin
-Copyright (c) 1991-2, RSA Data Security, Inc.
-Copyright (c) 1994-2000 by Bradford Appleton.
-Copyright (c) 1996-2000 by Bradford Appleton.
-Copyright (c) 1996-2002 Douglas E. Wegscheid.
-Copyright (c) 1998-2000 by Bradford Appleton.
-Copyright (c) 2002-2007 by D.H. aka PodMaster
-Copyright (c) 2002-2014 by the Perl 5 Porters
-Copyright (c) 2003-2008, 2012-2014 Steve Hay.
-Copyright (c) 2008,2009 Larry Wall and others
-Copyright (c) 2012 Willem Toorop, NLnet Labs.
-Copyright 2004 - 2010 by Tassilo von Parseval
-Portions Copyright (c) 1997-2001 Edmund Mergl
-Portions Copyright (c) 2002-2009 Olaf Kolkman
-Portions Copyright (c) 2007,2012 Dick Franks.
-Portions Copyright (c) 2010,2012 Dick Franks.
-Portions Copyright (c) 2011,2017 Dick Franks.
-Portions Copyright (c) 2012,2015 Dick Franks.
-Portions Copyright (c) 2012,2017 Dick Franks.
-Portions Copyright (c) 2014,2015 Dick Franks.
-Portions Copyright (c) 2014-2017 Dick Franks.
-copyright (c) 2004, 2008 by Matthijs van Duin
-parts copyright 2009 - 2013 Kenichi Ishigaki.
-portions Copyright (c) 1997 Thomas K. Wenrich
-COPYRIGHTS Benjamin Trott, ben@rhumba.pair.com
-Copyright (c) 1996, 1997, 1998 Malcolm Beattie
-Copyright (c) 1997 Jochen Wiedmann Am Eisteich
-Copyright (c) 1997,1998,1999 Tim Bunce England
-Copyright (c) 1999-2004 Igor Pavlov 2004-02-15
-Copyright (c) 2000 Lincoln D. Stein Formatting
-Copyright (c) 2000,2001 Kawai Takanori. Japan.
-Copyright (c) 2004,2007 by the Perl 5 Porters.
-Copyright (c) 2004-2013 by the Perl 5 Porters.
-Copyright (c) 2005-2013 by Adriano R. Ferreira
-Copyright 2005-2013 by Makamaka Hannyaharamitu
-Copyright 2005-2015 by Makamaka Hannyaharamitu
-Copyright 2006-2011, 2014, 2016, 2018 Sisyphus
-Copyright 2007-2011 by Makamaka Hannyaharamitu
-Copyright 2007-2012 by Makamaka Hannyaharamitu
-Copyright 2007-2014 by Makamaka Hannyaharamitu
-Copyright 2007-2016 by Makamaka Hannyaharamitu
-Copyright 2015 Michael LaGrasta and Dan Kogai.
-Copyright Benjamin Trott, cpan@stupidfool.org.
-Portions Copyright (c) 2003-2005 Rudolf Lippan
-Portions Copyright (c) 2005-2007 Olaf Kolkman.
-copyright (c) 2007 by Robert phaylon Sedlacek.
-copyright (c) 2012 by Robert phaylon Sedlacek.
-copyright (c) 2013-2014, 2017 by Toby Inkster.
-copyright 2008-2009, Ash Berlin
-parts copyright 2004 - 2005 Richard Soderberg.
-(c) 1998-2007 (W3C) MIT, ERCIM, Keio University
-(c) 1998-2008 (W3C) MIT, ERCIM, Keio University
-Copyright (c) 1999,2001 by ZeeGee Software Inc.
-Copyright (c) 2001 Canon Research Centre Europe
-Copyright (c) 2004-2013, Marcus Holland-Moritz.
-Copyright (c) 2015-2018 by Pali
-Copyright (c) 2016-2017 by Pali
-Copyright 1995-1999, 2001-2004, 2010 Gisle Aas.
-Copyright 1997, 2000, 2002, 2013 by Jay Rogers.
-Copyright 2000, Andrew Benham, adsb@bigfoot.com
-Copyright 2001, Lincoln Stein
-Copyright 2003, 2004, 2005, 2006 by Audrey Tang
-Copyright 2004, 2005, 2006, 2007 by Audrey Tang
-Portions Copyright 2006-2011 by Benjamin Trott.
-copyright (c) 2014 by Dagfinn Ilmari Mannsaker.
-portions copyright 2006, 2007 by Joel Bernstein
-(c) Paul Evans, 2010-2015 leonerd@leonerd.org.uk
-Copyright (c) 1991-1992, RSA Data Security, Inc.
-Copyright (c) 1998 Graham Barr
-Copyright (c) 2002 Graham Barr
-Copyright (c) 2004 Cold Spring Harbor Laboratory
-Copyright (c) 2004-2015 Best Practical Solutions
-Copyright (c) 2005-2015 Makamaka Hannyaharamitu.
-Copyright (c) 2007-2015 Makamaka Hannyaharamitu.
-Copyright (c) 2008 Graham Barr
-Copyright (c) 2008, 2010, 2013, 2014 Reini Urban
-Copyright (c) 2015-2018 by Pali E pali@cpan.orgE
-Copyright 1998 (c) Byron Brummer. Copyright 1998
-Copyright 2004 by Audrey Tang
-Copyright 2009, 2010, 2011, 2012 Steffen Mueller
-Portions Copyright (c) 1997-2003 Jochen Wiedmann
-Portions Copyright (c) 2001 Jonathan M Gilligan.
-copyright (c) 1998 Francois Desarmenien, France.
-copyright (c) 2006 by Infinity Interactive, Inc.
-copyright 2005 Fergal Daly
-copyright Systemics Ltd http://www.systemics.com
-portions Copyright (c) 2007-2014 Martin J. Evans
-Copyright (c) 1989 Free Software Foundation, Inc.
-Copyright (c) 1990-2011 by Larry Wall and others.
-Copyright (c) 1990-2012 by Larry Wall and others.
-Copyright (c) 1999 Tuomas J. Lukka
-Copyright (c) 2001-2005 RIPE NCC, Olaf M. Kolkman
-Copyright (c) 2007, 2011 by Larry Wall and others
-Copyright (c) 2008 Marc Lehmann
-Copyright (c) 2010, 2011 by Larry Wall and others
-Copyright (c) Katholieke Universiteit Leuven 1996
-Copyright 1991 Bell Communications Research, Inc.
-Copyright 2000 by Joe Smith
-Copyright 2001 Abhijit Menon-Sen
-Portions Copyright (c) 2002,2003 Chris Reinhardt.
-Portions Copyright (c) 2002-2003 Chris Reinhardt.
-Portions Copyright (c) 2002-2004 Chris Reinhardt.
-Portions Copyright (c) 2004-2006 Alexey Stroganov
-Portions Copyright (c) 2005 Robert Martin-Legene.
-Copyright (c) 1995 Graham Barr & Nick Ing-Simmons.
-Copyright (c) 1996-8 Graham Barr
-Copyright (c) 1997-8 Graham Barr
-Copyright (c) 1998-2000 Joshua Nathaniel Pritikin.
-Copyright (c) 2001-2012, SADAHIRO Tomoyuki. Japan.
-Copyright (c) 2001-2017, SADAHIRO Tomoyuki. Japan.
-Copyright (c) 2004 Peter Marschall
-Copyright (c) 2004-2017, SADAHIRO Tomoyuki. Japan.
-Copyright 2000-2007 Michael Stevens, Andy Wardley.
-Copyright 2005, 2006 by Infinity Interactive, Inc.
-Portions Copyright (c) 2003,2006-2011 Dick Franks.
-Portions Copyright (c) 2004-2013 Patrick Galbraith
-copyright (c) 2004 by Simon Cozens and Casey West.
-Copyright (c) 1998-2000 Larry Wall and Clark Cooper
-Copyright (c) 1998-2004 Tom Hughes
-Copyright (c) 1999, Tim Bunce, Phlip, Thomas Lowery
-Copyright (c) 2000-2006 Paul Kulchenko, Byrne Reese
-Copyright (c) 2002, 2003, 2006, 2007 Richard Clamp.
-Copyright (c) 2002, Thomas Lowery, Steffen Goeldner
-Copyright (c) 2003, Thomas Lowery, Steffen Goeldner
-Copyright (c) 2007-2008 NLnet Labs, Olaf M. Kolkman
-Copyright (c) 2010 by H.Merijn Brand & Jens Rehsack
-Copyright (c) 2011 by Jonathan Yu
-Copyright 1995-2017 Jean-loup Gailly and Mark Adler
-Copyright 2001 Benjamin Trott, ben@rhumba.pair.com.
-Copyright 2001 Benjamin Trott, cpan@stupidfool.org.
-Copyright 2001-2006 Ken Williams. 2010 Matt S Trout
-Copyright 2003 by Fergal Daly
-Copyright 2004 Benjamin Trott, cpan@stupidfool.org.
-Portions Copyright (c) 2005-2009 O.M, Kolkman, RIPE
-copyright (c) 2015 by Simon Flack and David Golden.
-copyright_holder E. Xavier Ample
-Copyright (c) 1997-2001 Canon Research Centre Europe
-Copyright (c) 1998 Canon Research Centre Europe Ltd.
-Copyright (c) 2000-2012 Graham Barr
-Copyright (c) 2005 Florian Ragwitz
-Copyright (c) 2010-2011 Matt Trout and David Golden.
-Copyright 2012 Kurt Starsinic
-Copyright 2017 Marty Pauley
-Portions Copyright (c) 2009 Olaf Kolkman, NLnet Labs
-copyright (c) 2004 by Ken Williams, Leon Timmermans.
-copyright (c) 2006 by Ken Williams, Leon Timmermans.
-copyright (c) 2011 by Ken Williams, Leon Timmermans.
-copyright (c) 2011 by Leon Timmermans, David Golden.
-copyright (c) 2014 by Adam Kennedy and Contributors.
-copyright (c) 2017 by Kent Fredric
-Copyright (c) 1997-2003 Graham Barr
-Copyright (c) 1997-2007 Graham Barr
-Copyright (c) 1997-2009 Graham Barr
-Copyright (c) 2000-2002 Graham Barr
-Copyright (c) 2000-2005 Graham Barr
-Copyright (c) 2004-2006 Graham Barr
-Copyright (c) 2008-2018, Sebastian Riedel and others.
-Copyright (c) 2010 by David Golden and Ricardo Signes
-Copyright 1998, 1999, 2000, 2001, 2012 M. J. Dominus.
-Portions Copyright (c) 2005 Olaf Kolkman, NLnet Labs.
-Portions Copyright (c) 2006 Olaf Kolkman (NLnet Labs)
-Copyright (c) 1996-2002,2005,2006 David Muir Sharnoff.
-Copyright (c) 1996-2003 Sampo Kellomaki
-Copyright (c) 2000-2007 Michael Stevens, Andy Wardley.
-Copyright (c) 2001-2007 Nathan Wiger
-Copyright (c) 2002-2018 Greg Sabino Mullane and others
-Copyright (c) 2003-2018 Mark Shelor
-Copyright (c) 2005 Mike McCauley
-Copyright (c) 2007-2014 Dave Rolsky
-Copyright (c) 2014 Paul Evans
-Copyright 1999-2000 by Russ Allbery
-Copyright 2000-2010, John McNamara, jmcnamara@cpan.org
-Copyright 2000-2012, John McNamara, jmcnamara@cpan.org
-Copyright 2000-2016, John McNamara, jmcnamara@cpan.org
-Copyright 2000-2018, John McNamara, jmcnamara@cpan.org
-Copyright 2004, 2010 by Audrey Tang
-Copyright 2009, 2010, 2011, 2012, 2013 Steffen Mueller
-copyright (c) 2004 by Adam Kennedy and Ricardo SIGNES.
-copyright (c) 2010 by David Golden and Ricardo Signes.
-Copyright (c) 2007-2016 H.Merijn Brand for PROCURA B.V.
-Copyright (c) 2008, 2010, 2011 by Larry Wall and others
-Copyright 1998 M-J. Dominus. (mjd-perl-diff@plover.com)
-Copyright 2004-2014 by Christian Renz
-Copyrights 1999-2018 by Mark Overmeer
-Copyrights 2007-2018 by Mark Overmeer
-copyright (c) 1997 - 2018 by Graham Barr & Dave Rolsky.
-copyright (c) 2017 by Michael Schwern and David Golden.
-Copyright (c) 2003-2004, 2012-2013 by the gtk2-perl team
-Copyright (c) 2009-2013 by H.Merijn Brand & Jens Rehsack
-Copyright (c) 2010 Simon Josefsson
-Copyright (c) 2010-2013 by H.Merijn Brand & Jens Rehsack
-Copyright (c) 2010-2013 by Jens Rehsack & H.Merijn Brand
-Portions Copyright (c) 2005 Olaf M. Kolkman, NLnet Labs.
-Copyright (c) 1997,1998 Canon Research Centre Europe Ltd.
-Copyright (c) 1998-2000 Canon Research Centre Europe Ltd.
-Copyright (c) 1998-2001 Canon Research Centre Europe Ltd.
-Copyright (c) 1998-2003 Canon Research Centre Europe Ltd.
-Copyright (c) 2000, 1996, 1991, 2012 O'Reilly Media, Inc.
-Copyright (c) 2000-2016 Hajimu UMEMOTO
-Copyright (c) 2002, 2003, 2004, 2012 Elizabeth Mattijsen.
-Copyright (c) 2004-2009, Sara Golemon
-Copyright (c) 2005-2006 Florian Ragwitz
-Copyrights 2013-2018 by Mark Overmeer
-Copyright 1999-2010, 2012-2018 Russ Allbery
-copyright (c) 2015 by Michael G. Schwern and David Golden.
-Copyright (c) 1996-2003 Sampo Kellomaki
-Copyright (c) 1997-2010 Tom Christiansen, Nathan Torkington
-Copyright (c) 1997-2013 Tom Christiansen, Nathan Torkington
-Copyright (c) 2008 Martin Kutter (martin.kutter@fen-net.de)
-Copyright 2000 Christian Lackas, Imperia Software Solutions
-Copyright (c) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
-Copyright (c) 1998 - 2016, Daniel Stenberg,
-Copyright (c) 2000-2007 Thierry-Michel Barral, Andy Wardley.
-Copyright (c) 2014-2018 by David Pinkowitz
-Copyright 1998, 1999, 2000, 2001, 2012 by Mark Jason Dominus
-Copyright 2004, 2006, 2010 by Audrey Tang
-Copyright 2006-2010, Andy Lester 2010-2015 David E. Wheeler.
-copyright (c) 2002 by Per Einar Ellefsen
-Copyright (c) 2000-2005, Damian Conway and Michael G Schwern.
-Copyright (c) 1996, 2000, 2001, 2005, by Larry Wall and others
-Copyright (c) 2000-2001 Paul Kulchenko (paulclinger@yahoo.com)
-Copyright (c) 2000-2003 Paul Kulchenko (paulclinger@yahoo.com)
-Copyright (c) 2000-2004 Paul Kulchenko (paulclinger@yahoo.com)
-Copyright (c) 2000-2005 Paul Kulchenko (paulclinger@yahoo.com)
-Copyright (c) 2000-2007 Paul Kulchenko (paulclinger@yahoo.com)
-Copyright (c) 2001, Tim Bunce, Thomas Lowery, Steffen Goeldner
-Copyright (c) 2004-2017 Jean-Louis Morel
-Copyright (c) 2002, 2003, 2004, 2006, 2009, 2011 Richard Clamp.
-Copyright (c) 2006-2008 John Scoles (The Pythian Group), Canada
-Copyright 2007-2014 by Alexandr Ciornii, L
-copyright (c) 2006, 2009 by Qindel Formacion y Servicios, S. L.
-Copyright (c) 2006, 2007, 2009, 2010, 2011 Larry Wall and others
-Copyright (c) 2006-2011 John Scoles (The Pythian Group). Canada.
-Copyright (c) 2010 - 2016 by Rafael Kitover (rkitover@cpan.org).
-Copyright 1998-2001, 2004, 2007 by Sean M. Burke and David Hand.
-Copyright (c) 2005 - 2010 by David B. Robins (dbrobins@cpan.org).
-Copyright (c) 1995, 1996 Systemics Ltd (http://www.systemics.com/)
-Copyright (c) 2006-2010 Matt S. Trout
-Copyright 2001, 2008, 2009, 2014, 2018 Russ Allbery
-copyright (c) 1994 by the Regents of the University of California.
-Copyright (c) 2002, 2003, 2005, 2006, 2007 by Larry Wall and others
-Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 by Steffen Mueller
-Portions (c) 1999 ActiveState Tool Corp, http://www.ActiveState.com
-Copyright (c) 1995, 1996, 1997, 1998 Doug MacEachern and Jon Orwant.
-Copyright (c) 1989, 1993 The Regents of the University of California.
-Copyright (c) 2000-2002 Kawai Takanori and Nippon-RAD Co. OP Division
-Copyright (c) 2006 Simon Wilkinson, Achim Grolms and Peter Marschall.
-Copyright 2001, 2004, 2008, 2014, 2018 by Russ Allbery
-Parts Copyright (c) 1999, 2001 W3Works, LLC (http://www.w3works.com/)
-Copyright (c) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc.
-Copyright (c) 1998-2000, 2002, 2003, 2004, 2005, 2006 Stephen McCamant.
-Copyright Tim Bunce, Thomas K. Wenrich, Jeff Urlwin and Martin J. Evans
-Parts Copyright (c) 1995, 1996 Systemics Ltd (http://www.systemics.com/)
-Copyright (c) 1991, 1992, 1993, 2000, 2004, 2011 by Larry Wall and others
-Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 Jarkko Hietaniemi.
-Copyright (c) 2003- Rafael Martinez Torres
-Copyright 2002-2014 by Ken Williams, David Golden and other contributors.
-Copyright 2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017 Vincent Pit
-copyright (c) 2008 by Infinity Interactive, Inc. http://www.iinteractive.com.
-Copyright (c) 2004, 2006, 2007, 2009, 2010, 2011, 2012, 2014, 2017 Andrew Main
-Copyright 1999, 2001, 2004, 2006, 2008, 2009, 2018 Russ Allbery
-copyright (c) 2008, 2009, 2010, 2011, 2012 by Leon Timmermans
-Copyright (c) 1994-1999 Kenneth Albanowski. 2001-2005 Jonathan Stowe and others
-Copyright 2003-2004, 2012-2013 by muppet, Ross McFarland, and the gtk2-perl team
-copyright (c) 2018 by Jos Boumans, Ken Williams, Chris Williams and David Golden.
-Copyright 1999-2001, 2004, 2006, 2008, 2010, 2012-2018 Russ Allbery
-copyright (c) 2010 by David Golden, Ricardo Signes, Adam Kennedy and Contributors.
-Copyright 1999, 2000, 2001, 2004, 2006, 2008, 2010, 2015 Russ Allbery
-Copyright (c) 1997, 1998, 2000, 2001, 2005, 2006, 2007, 2011 by Larry Wall and others
-Copyright (c) 1991, 1992, 1993, 1995, 1996, 1998, 2000, 2001, by Larry Wall and others
-Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, by Larry Wall and others
-Copyright 1999-2002, 2004, 2006, 2008-2009, 2012-2016, 2018 Russ Allbery
-copyright 1998 The Perl Journal. It appears courtesy of Jon Orwant and The Perl Journal.
-copyright 1999 The Perl Journal. It appears courtesy of Jon Orwant and The Perl Journal.
-copyright 2000 The Perl Journal. It appears courtesy of Jon Orwant and The Perl Journal.
-Copyright (c) 1997-2003 Jonathan Leffler, Jochen Wiedmann, Steffen Goeldner and Tim Bunce
-Copyright (c) 1997-2006 Jonathan Leffler, Jochen Wiedmann, Steffen Goeldner and Tim Bunce
-Copyright 1999, 2000, 2001, 2004, 2006, 2008, 2010, 2015, 2018 Russ Allbery
-Copyright (c) 2000, 2001, 2002, 2005, 2006, 2007, 2009, 2010, 2011 by Larry Wall and others
-Copyright (c) 2002, 2003, 2005, 2006, 2007, 2008, 2009, 2010, 2011 by Larry Wall and others
-Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, by Larry Wall and others
-Copyright 1999, 2001-2002, 2004, 2006, 2008-2009, 2014-2015, 2018 Russ Allbery
-Copyright (c) 1998-2002 Graham Barr and 2001 Chris Ridd
-Copyright (c) 1997-2006 by Gurusamy Sarathy and Jan Dubois
-Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 by Larry Wall and others
-Copyright (c) 1991, 1992, 1993, 1995, 1996, 1997, 1998, 1999, 2000, 2001, by Larry Wall and others
-Copyright (c) 1991, 1992, 1993, 1999, 2001, 2002, 2003, 2004, 2005, 2007, by Larry Wall and others
-Copyright (c) 1993, 1994, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2007, by Larry Wall and others
-copyright (c) Charles Bailey, Tim Bunce, David Landgren, James Keenan and Richard Elberger 1995-2017.
-Copyright (c) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2002, 2005, 2006, 2007 by Larry Wall and others
-Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2006, 2007, 2008 by Larry Wall and others
-Copyright (c) 1996, 1997, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, by Larry Wall and others
-Copyright (c) 1993, 1994, 1996, 1997, 1999, 2000, 2001, 2003, 2005, 2006, 2007, 2008 by Larry Wall and others
-Copyright (c) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 by Larry Wall and others
-Copyright (c) 2003-2009 Graham Barr, Djamel Boudjerda, Paul Connolly, Julian Onions, Nexor and Yann Kerherve.
-Copyright (c) 1993, 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2002, 2003, 2006, 2007, by Larry Wall and others
-Copyright (c) 2001, 2002, 2003, 2005, 2006, 2007, 2009, 2010, 2011 by Larry Wall, Nick Ing-Simmons, and others
-Copyright (c) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1999, 2000, 2002, 2005, 2006, 2007, 2008 by Larry Wall and others
-Copyright (c) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 by Larry Wall and others
-Copyright (c) 1993, 1994, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2008 by Larry Wall and others
-Copyright (c) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2016 by Larry Wall and others
-Copyright (c) 2003-2009 Graham Barr, Djamel Boudjerda, Paul Connolly, Julian Onions, Nexor, Peter Marschall and Yann Kerherve.
-Copyright (c) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 by Larry Wall and others
-Copyright (c) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 by Larry Wall and others
-Copyright (c) 1991, 1992, 1993, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2005, 2006, 2007, 2008, by Larry Wall and others
-Copyright (c) 1991, 1992, 1993, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006, 2007, 2008, by Larry Wall and others
-Copyright (c) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 by Larry Wall and others
-Copyright (c) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, by Larry Wall and others
-Copyright (c) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006, 2007, by Larry Wall and others
-Copyright (c) 1993, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, by Larry Wall and others
-Copyright (c) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 by Larry Wall and others
-Copyright 1995-1998 Gisle Aas, 1999-2004 Sean M. Burke, 2005 Andy Lester, 2006 Pete Krawczyk, 2010 Jeff Fearn, 2012 Christopher J. Madsen.
-Copyright 1996, 1997, 1998, 2000, 2001, 2002, 2005, 2006, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Russ Allbery
-Copyright (c) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 by Larry Wall and others
-Copyright (c) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2008, 2012 by Larry Wall and others
-Copyright (c) 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 by Larry Wall and others
-Copyright (c) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 by Larry Wall and others
-Copyright (c) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 by Larry Wall and others
-Copyright (c) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 by Larry Wall and others
-Copyright (c) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011, 2012, 2013 by Larry Wall and others
-Copyright (c) 1998-2003 World Wide Web Consortium (Massachusetts Institute of Technology, European Research Consortium for Informatics and Mathematics, Keio University).
-Copyright (c) 1998-2008 World Wide Web Consortium (Massachusetts Institute of Technology, European Research Consortium for Informatics and Mathematics, Keio University).
-
-GPL-1.0-or-later OR Artistic-1.0-Perl
-
----------------------------------------------------------
-
----------------------------------------------------------
-
-Microsoft.Windows.SDK.NET.Ref 10.0.26100.75 - LicenseRef-scancode-unknown
-
-
-(c) Microsoft Corporation
-Copyright (c) Microsoft Corporation
-
-LicenseRef-scancode-unknown
-
----------------------------------------------------------
-
----------------------------------------------------------
-
CommunityToolkit.Mvvm 8.4.0 - MIT
@@ -1676,7 +566,7 @@ THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
---------------------------------------------------------
-Microsoft.Extensions.Hosting 9.0.8 - MIT
+Microsoft.Extensions.Hosting 10.0.0 - MIT
Copyright (c) 2021
@@ -1699,7 +589,7 @@ Copyright (c) 2005-2020 Rich Felker
Copyright (c) 2012-2021 Yann Collet
Copyright (c) Microsoft Corporation
Copyright (c) 2007 James Newton-King
-Copyright (c) 1991-2022 Unicode, Inc.
+Copyright (c) 1991-2024 Unicode, Inc.
Copyright (c) 2013-2017, Alfred Klomp
Copyright (c) 2018 Nemanja Mijailovic
Copyright 2012 the V8 project authors
@@ -1720,7 +610,6 @@ Copyright (c) The Internet Society (2003)
Copyright (c) .NET Foundation Contributors
(c) 1995-2024 Jean-loup Gailly and Mark Adler
Copyright (c) 2020 Mara Bos
-Copyright (c) .NET Foundation and Contributors
Copyright (c) 2012 - present, Victor Zverovich
Copyright (c) 2006 Jb Evain (jbevain@gmail.com)
Copyright (c) 2008-2020 Advanced Micro Devices, Inc.
@@ -1737,252 +626,15 @@ Copyright (c) 1980, 1986, 1993 The Regents of the University of California
Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California
Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass
-The MIT License (MIT)
+MIT License
-Copyright (c) .NET Foundation and Contributors
+Copyright (c)
-All rights reserved.
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
-
----------------------------------------------------------
-
----------------------------------------------------------
-
-Microsoft.NETCore.App.Runtime.win-arm64 9.0.10 - MIT
-
-
-Copyright (c) 2021
-Copyright (c) Six Labors
-(c) Microsoft Corporation
-Copyright (c) 2022 FormatJS
-Copyright (c) Andrew Arnott
-Copyright 2019 LLVM Project
-Copyright (c) 1998 Microsoft
-Copyright 2018 Daniel Lemire
-Copyright (c) .NET Foundation
-Copyright 1995-2022 Mark Adler
-Copyright 1995-2024 Mark Adler
-Copyright (c) 2011, Google Inc.
-Copyright (c) 2020 Dan Shechter
-(c) 1997-2005 Sean Eron Anderson
-Copyright (c) 2015 Andrew Gallant
-Copyright (c) 2022, Wojciech Mula
-Copyright (c) 2017 Yoshifumi Kawai
-Copyright (c) 2022, Geoff Langdale
-Copyright (c) 2005-2020 Rich Felker
-Copyright (c) 2012-2021 Yann Collet
-Copyright (c) Microsoft Corporation
-Copyright (c) 2007 James Newton-King
-Copyright (c) 1991-2022 Unicode, Inc.
-Copyright (c) 2013-2017, Alfred Klomp
-Copyright (c) 2018 Nemanja Mijailovic
-Copyright 2012 the V8 project authors
-Copyright (c) 1999 Lucent Technologies
-Copyright (c) 2008-2016, Wojciech Mula
-Copyright (c) 2011-2020 Microsoft Corp
-Copyright (c) 2015-2017, Wojciech Mula
-Copyright (c) 2015-2018, Wojciech Mula
-Copyright (c) 2005-2007, Nick Galbreath
-Copyright (c) 2015 The Chromium Authors
-Copyright (c) 2018 Alexander Chermyanin
-Copyright (c) The Internet Society 1997
-Copyright (c) 2004-2006 Intel Corporation
-Copyright (c) 2011-2015 Intel Corporation
-Copyright (c) 2013-2017, Milosz Krajewski
-Copyright (c) 2016-2017, Matthieu Darbois
-Copyright (c) The Internet Society (2003)
-Copyright (c) .NET Foundation Contributors
-(c) 1995-2024 Jean-loup Gailly and Mark Adler
-Copyright (c) 2020 Mara Bos
-Copyright (c) .NET Foundation and Contributors
-Copyright (c) 2012 - present, Victor Zverovich
-Copyright (c) 2006 Jb Evain (jbevain@gmail.com)
-Copyright (c) 2008-2020 Advanced Micro Devices, Inc.
-Copyright (c) 2019 Microsoft Corporation, Daan Leijen
-Copyright (c) 2011 Novell, Inc (http://www.novell.com)
-Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com)
-Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors
-Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com
-Copyright 1995-2024 Jean-loup Gailly and Mark Adler Qkkbal
-Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc.
-Portions (c) International Organization for Standardization 1986
-Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang) Disclaimers
-Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip
-Copyright (c) 1980, 1986, 1993 The Regents of the University of California
-Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California
-Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass
-
-The MIT License (MIT)
-
-Copyright (c) .NET Foundation and Contributors
-
-All rights reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
-
----------------------------------------------------------
-
----------------------------------------------------------
-
-Microsoft.NETCore.App.Runtime.win-x64 9.0.10 - MIT
-
-
-Copyright (c) 2021
-Copyright (c) Six Labors
-(c) Microsoft Corporation
-Copyright (c) 2022 FormatJS
-Copyright (c) Andrew Arnott
-Copyright 2019 LLVM Project
-Copyright (c) 1998 Microsoft
-Copyright 2018 Daniel Lemire
-Copyright (c) .NET Foundation
-Copyright 1995-2022 Mark Adler
-Copyright 1995-2024 Mark Adler
-Copyright (c) 2011, Google Inc.
-Copyright (c) 2020 Dan Shechter
-(c) 1997-2005 Sean Eron Anderson
-Copyright (c) 2015 Andrew Gallant
-Copyright (c) 2022, Wojciech Mula
-Copyright (c) 2017 Yoshifumi Kawai
-Copyright (c) 2022, Geoff Langdale
-Copyright (c) 2005-2020 Rich Felker
-Copyright (c) 2012-2021 Yann Collet
-Copyright (c) Microsoft Corporation
-Copyright (c) 2007 James Newton-King
-Copyright (c) 1991-2022 Unicode, Inc.
-Copyright (c) 2013-2017, Alfred Klomp
-Copyright (c) 2018 Nemanja Mijailovic
-Copyright 2012 the V8 project authors
-Copyright (c) 1999 Lucent Technologies
-Copyright (c) 2008-2016, Wojciech Mula
-Copyright (c) 2011-2020 Microsoft Corp
-Copyright (c) 2015-2017, Wojciech Mula
-Copyright (c) 2015-2018, Wojciech Mula
-Copyright (c) 2005-2007, Nick Galbreath
-Copyright (c) 2015 The Chromium Authors
-Copyright (c) 2018 Alexander Chermyanin
-Copyright (c) The Internet Society 1997
-Copyright (c) 2004-2006 Intel Corporation
-Copyright (c) 2011-2015 Intel Corporation
-Copyright (c) 2013-2017, Milosz Krajewski
-Copyright (c) 2016-2017, Matthieu Darbois
-Copyright (c) The Internet Society (2003)
-Copyright (c) .NET Foundation Contributors
-(c) 1995-2024 Jean-loup Gailly and Mark Adler
-Copyright (c) 2020 Mara Bos
-Copyright (c) .NET Foundation and Contributors
-Copyright (c) 2012 - present, Victor Zverovich
-Copyright (c) 2006 Jb Evain (jbevain@gmail.com)
-Copyright (c) 2008-2020 Advanced Micro Devices, Inc.
-Copyright (c) 2019 Microsoft Corporation, Daan Leijen
-Copyright (c) 2011 Novell, Inc (http://www.novell.com)
-Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com)
-Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors
-Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com
-Copyright 1995-2024 Jean-loup Gailly and Mark Adler Qkkbal
-Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc.
-Portions (c) International Organization for Standardization 1986
-Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang) Disclaimers
-Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip
-Copyright (c) 1980, 1986, 1993 The Regents of the University of California
-Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California
-Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass
-
-The MIT License (MIT)
-
-Copyright (c) .NET Foundation and Contributors
-
-All rights reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
-
----------------------------------------------------------
-
----------------------------------------------------------
-
-Microsoft.Windows.ImplementationLibrary 1.0.250325.1 - MIT
-
-
-(c) Microsoft 2025
-Copyright (c) Microsoft
-(c) Microsoft Corporation
-Copyright (c) Microsoft Corporation
-Copyright (c) 2009-2014 by the contributors
-
- MIT License
-
- Copyright (c) Microsoft Corporation. All rights reserved.
-
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
-
- The above copyright notice and this permission notice shall be included in all
- copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- SOFTWARE
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
---------------------------------------------------------
@@ -2062,9 +714,13 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
---------------------------------------------------------
-WinUIEx 2.5.1 - MIT
+WinUIEx 2.9.0 - MIT
+Copyright (c) Microsoft Corporation
+Copyright 2021-2025 - Morten Nielsen
+Copyright 2021-2025 - Morten Nielsen A
+Copyright (c) 2021-2025 - Morten Nielsen
MIT License
diff --git a/distributions/DistributionInfo.json b/distributions/DistributionInfo.json
index 3e32652..c68dd67 100644
--- a/distributions/DistributionInfo.json
+++ b/distributions/DistributionInfo.json
@@ -151,12 +151,12 @@
"FriendlyName": "AlmaLinux OS 10",
"Default": true,
"Amd64Url": {
- "Url": "https://github.com/AlmaLinux/wsl-images/releases/download/v10.0.20250529.0/AlmaLinux-10.0_x64_20250529.0.wsl",
- "Sha256": "6775711048b86743588da7173ab45ca449b5c50a72fb87635313f059a9813d4b"
+ "Url": "https://github.com/AlmaLinux/wsl-images/releases/download/v10.1.20251124.0/AlmaLinux-10.1_x64_20251124.0.wsl",
+ "Sha256": "24e8fa286a4081979d97e83a227fb89f332bcf731fe4b422679a3b455ab0be37"
},
"Arm64Url": {
- "Url": "https://github.com/AlmaLinux/wsl-images/releases/download/v10.0.20250529.0/AlmaLinux-10.0_ARM64_20250529.0.wsl",
- "Sha256": "bc424bd9f954d36e871d4d874d35bc25e3ea7bdfe48337c30b927ed73a79b2fa"
+ "Url": "https://github.com/AlmaLinux/wsl-images/releases/download/v10.1.20251124.0/AlmaLinux-10.1_ARM64_20251124.0.wsl",
+ "Sha256": "20700a4467214074f8a1a3d4e0e1cad25af36b8127d047ab6d5b4a1355e998b8"
}
}
],
diff --git a/localization/strings/zh-CN/Resources.resw b/localization/strings/zh-CN/Resources.resw
index 6188c44..e336d02 100644
--- a/localization/strings/zh-CN/Resources.resw
+++ b/localization/strings/zh-CN/Resources.resw
@@ -132,7 +132,7 @@
{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated
- 该磁盘“{}”已连接。
+ 磁盘“{}”已连接。
{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated
@@ -683,7 +683,7 @@ Windows: {}
正在导入,这可能需要几分钟时间。
- 通过 {} 或 /etc/wsl.conf 禁用 GUI 应用程序支持。
+ 已通过 {} 或 /etc/wsl.conf 禁用 GUI 应用程序支持。
{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated
@@ -822,11 +822,11 @@ Windows: {}
{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated
- 分发名称无效:“{}”。
+ 无效分发名称:“{}”。
{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated
- 使用旧分发注册。请考虑改用基于 tar 的分发。
+ 正在使用旧分发注册。请考虑改用基于 tar 的分发。
旧分发注册不支持 --version 参数。
@@ -864,7 +864,7 @@ Windows: {}
此计算机上不支持嵌套虚拟化。
- 无法创建地址为“{}”的网络终结点,已分配新地址:“{}”
+ 无法创建地址为“{}”的网络端点,已分配新地址:“{}”
{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated
@@ -905,10 +905,10 @@ Windows: {}
检测到 IPv6 代理配置,但未镜像到 WSL。NAT 模式下的 WSL 不支持 IPv6。
- 检测到 localhost IPv6 代理配置,但未镜像到 WSL 中。WSL 不支持 localhost IPv6 代理。
+ 检测到 localhost IPv6 代理配置,但未镜像到 WSL。WSL 不支持 localhost IPv6 代理。
- 尝试解析代理设置时发生意外错误,代理设置未镜像到 WSL 中。
+ 尝试解析代理设置时发生意外错误,代理设置未镜像到 WSL。
访问注册表时出错。路径:“{}”。错误: {}
@@ -947,14 +947,14 @@ Windows: {}
{FixedPlaceholder="{}"}{Locked=".wslconfig"}Command line arguments, file names and string inserts should not be translated
- 计算机策略禁用调试 shell。
+ 计算机策略已禁用调试 shell。
wsl.exe --mount 被计算机策略禁用。
{Locked="--mount "}Command line arguments, file names and string inserts should not be translated
- WSL1 被计算机策略禁用。
+ 计算机策略已禁用 WSL1。
请运行“wsl.exe --set-version {} 2”以升级到 WSL2。
@@ -1070,7 +1070,7 @@ Windows: {}
{Locked="--vhd "}Command line arguments, file names and string inserts should not be translated
- 未能从以下Microsoft Store安装 {}: {}
+ 未能从 Microsoft Store 安装 {}:{}
正在尝试 Web 下载...
{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated
@@ -1082,7 +1082,7 @@ Windows: {}
WSL 安装似乎已损坏 (错误代码: {})。
-按任意键修复 WSL,或 CTRL-C 取消。
+按任意键修复 WSL,或按 CTRL-C 取消。
此提示将在 60 秒后超时。
{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated
@@ -1114,7 +1114,7 @@ Windows: {}
提供的自定义内核模块未指定自定义内核。有关详细信息,请参阅 https://aka.ms/wslcustomkernel。
- 由于当前与全球安全访问客户端的兼容性问题,DNS 隧道被禁用。
+ 由于当前与全局安全访问客户端的兼容性问题,DNS 隧道被禁用。
由于潜在的数据损坏,目前已禁用稀疏 VHD 支持。
@@ -1127,7 +1127,7 @@ wsl.exe --manage <DistributionName> --set-sparse true --allow-unsafe{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated
- 使用装载 -a 处理 /etc/fstab 失败。
+ 使用 mount -a 处理 /etc/fstab 失败。
装载分发磁盘时出错,该磁盘作为回退以只读方式装载。
@@ -1138,7 +1138,7 @@ wsl.exe --manage <DistributionName> --set-sparse true --allow-unsafe{FixedPlaceholder="{}"}Command line arguments, file names and string inserts should not be translated
- 出现错误。请稍后再试一次。
+ 出现错误。请稍后再试。
关于
@@ -1160,28 +1160,28 @@ wsl.exe --manage <DistributionName> --set-sparse true --allow-unsafe自动内存回收
- 检测到空闲 CPU 使用情况后自动释放缓存内存。为缓存的即时释放设置为慢速释放和 dropcache。
+ 检测到空闲 CPU 使用情况后自动释放缓存内存。设为 gradual 缓慢释放;设为 dropcache 迅速释放。
自动内存回收。
- 检测到空闲 CPU 使用情况后自动释放缓存内存。为缓存的即时释放设置为慢速释放和 dropcache。
+ 检测到空闲 CPU 使用情况后自动释放缓存内存。设为 gradual 缓慢释放;设为 dropcache 迅速释放。
已启用自动代理
- 使 WSL 能够使用 Windows 的 HTTP 代理信息。
+ 允许 WSL 使用 Windows 的 HTTP 代理信息。
已启用自动代理。
- 使 WSL 能够使用 Windows 的 HTTP 代理信息。
+ 允许 WSL 使用 Windows 的 HTTP 代理信息。
- 尽力进行 DNS 分析
+ 尽力进行 DNS 解析
仅当 wsl2.dnsTunneling 设置为 true 时适用。设置为 true 时,Windows 将从 DNS 请求中提取问题并尝试解决该问题,忽略未知记录。
@@ -1191,7 +1191,7 @@ wsl.exe --manage <DistributionName> --set-sparse true --allow-unsafe尽力进行 DNS 分析。
- 仅当 wsl2.dnsTunneling 设置为 true 时才适用。设置为 true 时,Windows 将从 DNS 请求中提取问题并尝试解决该问题,忽略未知记录。
+ 仅当 wsl2.dnsTunneling 设置为 true 时适用。设置为 true 时,Windows 将从 DNS 请求中提取问题并尝试解决该问题,忽略未知记录。
自定义内核
@@ -1230,7 +1230,7 @@ wsl.exe --manage <DistributionName> --set-sparse true --allow-unsafe浏览发行版
- 指定 VHD 的路径,该路径将作为自定义系统发行版加载,主要用于为 WSL 中的 GUI 应用提供电源。[在此处详细了解系统发行]。
+ 指定一个 VHD 路径,该 VHD 将作为自定义系统发行版加载,主要用于在 WSL 中运行 GUI 应用。[在此处详细了解系统发行]。
{Locked="["}{Locked="]"}The text in between the delimiters [ ] is made into a hyperlink in code, and the delimiters are removed
@@ -1241,7 +1241,7 @@ wsl.exe --manage <DistributionName> --set-sparse true --allow-unsafe自定义系统发行版
- 指定 VHD 的路径,该路径将作为自定义系统发行版加载,主要用于为 WSL 中的 GUI 应用提供电源。
+ 指定一个 VHD 路径,该 VHD 将作为自定义系统发行版加载,主要用于在 WSL 中运行 GUI 应用。
启用调试控制台
@@ -1259,7 +1259,7 @@ wsl.exe --manage <DistributionName> --set-sparse true --allow-unsafe默认 VHD 大小
- 对于新创建的分发,可扩展 WSL 虚拟硬盘 (VHD) 的默认最大大小。
+ 为可扩展的 WSL 虚拟硬盘指定的默认最大大小 (VHD),仅用于新创建的分发。
重设大小
@@ -1268,7 +1268,7 @@ wsl.exe --manage <DistributionName> --set-sparse true --allow-unsafe默认 VHD 大小
- 为可扩展的 WSL 虚拟硬盘指定的默认最大大小 (VHD) 仅用于新创建的分发。
+ 为可扩展的 WSL 虚拟硬盘指定的默认最大大小 (VHD),仅用于新创建的分发。
开发人员
@@ -1284,20 +1284,20 @@ wsl.exe --manage <DistributionName> --set-sparse true --allow-unsafe更改 DrvFS 模式
- 更改 WSL 中的跨 OS 文件访问实施。
+ 更改 WSL 中的跨系统文件访问实现。
已启用 DNS 代理
- 仅当 wsl2.networkingMode 设置为 NAT 时适用。布尔值通知 WSL 将 Linux 中的 DNS 服务器配置为主机上的 NAT。设置为 false 将镜像从 Windows 到 Linux 的 DNS 服务器。
+ 仅当 wsl2.networkingMode 设置为 NAT 时适用。用于通知 WSL 将 Linux 中的 DNS 服务器配置为主机上的 NAT 的布尔值。设置为 false 将把 Windows 中 DNS 服务器镜像到 Linux。
{Locked="wsl2.networkingMode"}.wslconfig property key names should not be translated
已启用 DNS 代理。
- 仅当 wsl2.networkingMode 设置为 NAT 时适用。布尔值通知 WSL 将 Linux 中的 DNS 服务器配置为主机上的 NAT。设置为 false 将镜像从 Windows 到 Linux 的 DNS 服务器。
+ 仅当 wsl2.networkingMode 设置为 NAT 时适用。用于通知 WSL 将 Linux 中的 DNS 服务器配置为主机上的 NAT 的布尔值。设置为 false 将把 Windows 中 DNS 服务器镜像到 Linux。
已启用 DNS 隧道
@@ -1358,20 +1358,20 @@ wsl.exe --manage <DistributionName> --set-sparse true --allow-unsafe主机地址环回
- 仅当 wsl2.networkingMode 设置为镜像时适用。设置为 True 时,将允许容器通过分配给主机的 IP 地址连接到主机或主机连接到容器。请注意,始终可以使用 127.0.0.1 环回地址 - 此选项还允许使用所有额外分配的本地 IP 地址。
+ 仅当 wsl2.networkingMode 设置为镜像(mirrored)时适用。设置为 True 时,将允许容器与主机通过分配给主机的 IP 地址互相连接。请注意,始终可以使用 127.0.0.1 环回地址 - 此选项还允许使用所有额外分配的本地 IP 地址。
{Locked="wsl2.networkingMode"}.wslconfig property key names should not be translated
主机地址环回。
- 仅当 wsl2.networkingMode 设置为镜像时适用。设置为 True 时,将允许容器通过分配给主机的 IP 地址连接到主机或主机连接到容器。请注意,始终可以使用 127.0.0.1 环回地址 - 此选项还允许使用所有额外分配的本地 IP 地址。
+ 仅当 wsl2.networkingMode 设置为镜像(mirrored)时适用。设置为 True 时,将允许容器与主机通过分配给主机的 IP 地址互相连接。请注意,始终可以使用 127.0.0.1 环回地址 - 此选项还允许使用所有额外分配的本地 IP 地址。
忽略的端口
- 仅当 wsl2.networkingMode 设置为镜像时适用。指定 Linux 应用程序可以绑定到的端口,不会在 Windows 中自动转发或考虑这些端口。应以逗号分隔的列表格式化,例如: 3000,9000,9090。
+ 仅当 wsl2.networkingMode 设置为镜像(mirrored)时适用。指定 Linux 应用程序可以绑定的端口,这些端口不会 Windows 自动转发或考虑。应采用逗号分隔的列表格式,例如:3000,9000,9090。
{Locked="wsl2.networkingMode"}.wslconfig property key names should not be translated
@@ -1381,13 +1381,13 @@ wsl.exe --manage <DistributionName> --set-sparse true --allow-unsafe忽略的端口
- 仅当 wsl2.networkingMode 设置为镜像时适用。指定 Linux 应用程序可以绑定到的端口,不会在 Windows 中自动转发或考虑这些端口。应以逗号分隔的列表格式化,例如 3000、9000、9090。
+ 仅当 wsl2.networkingMode 设置为镜像(mirrored)时适用。指定 Linux 应用程序可以绑定的端口,这些端口不会在 Windows 中自动转发或考虑。应采用逗号分隔的列表格式,例如 3000,9000,9090。
初始自动代理超时
- 仅当 wsl2.autoProxy 设置为 true 时适用。配置在启动 WSL 容器时 WSL 等待检索 HTTP 代理信息) (毫秒。如果在此时间后解析代理设置,则必须重新启动 WSL 实例才能使用检索到的代理设置。
+ 仅当 wsl2.autoProxy 设置为 true 时适用。配置启动 WSL 容器时 WSL 等待检索 HTTP 代理信息的时间(以毫秒计)。如果在此时间后解析到代理设置,则必须重新启动 WSL 实例才能使用检索到的代理设置。
{Locked="wsl2.autoProxy"}.wslconfig property key names should not be translated
@@ -1397,25 +1397,25 @@ wsl.exe --manage <DistributionName> --set-sparse true --allow-unsafe初始自动代理超时
- 仅当 wsl2.autoProxy 设置为 true 时才适用。配置启动 WSL 容器时 WSL 等待检索 HTTP 代理信息的时间,以毫秒为单位。如果在此时间后解析代理设置,则必须重新启动 WSL 实例才能使用检索到的代理设置。
+ 仅当 wsl2.autoProxy 设置为 true 时才适用。配置启动 WSL 容器时 WSL 等待检索 HTTP 代理信息的时间,以毫秒为单位。如果在此时间后解析到代理设置,则必须重新启动 WSL 实例才能使用检索到的代理设置。
内核命令行
- 其他内核命令行参数。
+ 额外的内核命令行参数。
启用 localhost 转发
- 布尔值,指定是否应通过 localhost:port 从主机连接到 WSL 2 VM 中通配符或 localhost 的端口。
+ 布尔值,用于指定 WSL 2 VM 中绑定通配符或本地主机的端口是否应允许主机通过`localhost:端口号`进行连接。
启用 localhost 转发。
- 一个布尔值,指定绑定到 WSL 2 VM 中的通配符或 localhost 的端口是否应可通过 localhost、colon、port 从主机连接。
+ 布尔值,用于指定 WSL 2 VM 中绑定通配符或本地主机的端口是否应允许主机通过`localhost:端口号`进行连接。
{0} MB
@@ -1445,13 +1445,13 @@ wsl.exe --manage <DistributionName> --set-sparse true --allow-unsafe启用嵌套虚拟化
- 用于打开或关闭嵌套虚拟化的布尔值,使其他嵌套 VM 能够在 WSL 2 内运行。
+ 用于打开或关闭嵌套虚拟化的布尔值,使其他嵌套虚拟机能够在 WSL 2 内运行。
启用嵌套虚拟化。
- 用于打开或关闭嵌套虚拟化的布尔值,使其他嵌套 VM 能够在 WSL 2 内运行。
+ 用于打开或关闭嵌套虚拟化的布尔值,使其他嵌套虚拟机能够在 WSL 2 内运行。
网络模式
@@ -1472,7 +1472,7 @@ wsl.exe --manage <DistributionName> --set-sparse true --allow-unsafe你可以跨操作系统处理所有文件!
- 跨 OS 文件访问
+ 跨系统文件访问
从 Linux 访问 Windows 文件
@@ -1515,7 +1515,7 @@ wsl.exe --manage <DistributionName> --set-sparse true --allow-unsafeWSL 还包括一种称为镜像模式的新网络模式,该模式添加了 IPv6 支持等高级功能,并且能够访问局域网中的网络应用程序。
- 了解有关跨 OS 文件访问的详细信息
+ 了解有关跨系统文件访问的详细信息
https://aka.ms/wslfilesystems
@@ -1552,7 +1552,7 @@ wsl.exe --manage <DistributionName> --set-sparse true --allow-unsafe{Locked="-l -o"}Command line arguments and file names should not be translated
- 安装命名的 WSL 发行版命令
+ 安装指定名称的 WSL 发行版命令
'wsl.exe --install <DistroName>'
@@ -1568,11 +1568,11 @@ wsl.exe --manage <DistributionName> --set-sparse true --allow-unsafe
Docker Desktop 非常适合与 WSL 配合使用,可帮助你使用 Linux 容器进行开发。
-将 Docker Desktop 与 WSL 配合使用的一些优点是:
+一些将 Docker Desktop 与 WSL 配合使用的优点:
• 可以使用相同的 Docker 守护程序和映像在 WSL 或 Windows 中运行 Docker 命令。
• 可以使用 WSL 中的 Windows 驱动器自动装载功能在 Windows 和 Linux 之间无缝共享文件和文件夹。
-• 由于 WSL 的互操作性,你可以使用首选的 Windows 工具和编辑器处理 Linux 代码和文件,反之亦然。
+• 由于 WSL 的互操作性,你可以使用偏好的 Windows 工具和编辑器处理 Linux 代码和文件,反之亦然。
Docker Desktop 集成
@@ -1754,7 +1754,7 @@ wsl.exe --manage <DistributionName> --set-sparse true --allow-unsafe关于
- 开发商
+ 开发人员
发行版管理
@@ -1802,7 +1802,7 @@ wsl.exe --manage <DistributionName> --set-sparse true --allow-unsafe新增功能
- 跨文件系统工作
+ 跨系统文件访问
问题
@@ -1857,7 +1857,7 @@ wsl.exe --manage <DistributionName> --set-sparse true --allow-unsafe启用 VirtIO
- 使用 virtiofs 而不是计划 9 来访问主机文件,加快速度。
+ 使用 virtiofs 而不是 plan 9 来访问主机文件,加快速度。
启用 Virtio 9p
diff --git a/msipackage/package.wix.in b/msipackage/package.wix.in
index f51bc8f..277fd13 100644
--- a/msipackage/package.wix.in
+++ b/msipackage/package.wix.in
@@ -40,6 +40,12 @@
+
+
+
+
+
+
@@ -337,6 +343,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages.config b/packages.config
index 64d7fbf..36372a9 100644
--- a/packages.config
+++ b/packages.config
@@ -6,19 +6,19 @@
-
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
+
@@ -27,8 +27,8 @@
-
+
-
+
diff --git a/src/shared/inc/defs.h b/src/shared/inc/defs.h
index cdeda12..b468533 100644
--- a/src/shared/inc/defs.h
+++ b/src/shared/inc/defs.h
@@ -30,6 +30,10 @@ Abstract:
Type(Type&&) = delete; \
Type& operator=(Type&&) = delete;
+#define DEFAULT_MOVABLE(Type) \
+ Type(Type&&) = default; \
+ Type& operator=(Type&&) = default;
+
namespace wsl::shared {
inline constexpr std::uint32_t VersionMajor = WSL_PACKAGE_VERSION_MAJOR;
diff --git a/src/shared/inc/lxinitshared.h b/src/shared/inc/lxinitshared.h
index ca7d204..f0499d0 100644
--- a/src/shared/inc/lxinitshared.h
+++ b/src/shared/inc/lxinitshared.h
@@ -1666,10 +1666,8 @@ struct WSLA_TTY_RELAY
int32_t TtyInput;
int32_t TtyOutput;
int32_t TtyControl;
- uint32_t Rows;
- uint32_t Columns;
- PRETTY_PRINT(FIELD(Header), FIELD(TtyMaster), FIELD(TtyInput), FIELD(TtyOutput), FIELD(TtyControl), FIELD(Rows), FIELD(Columns));
+ PRETTY_PRINT(FIELD(Header), FIELD(TtyMaster), FIELD(TtyInput), FIELD(TtyOutput), FIELD(TtyControl));
};
struct WSLA_ACCEPT
diff --git a/src/windows/common/CMakeLists.txt b/src/windows/common/CMakeLists.txt
index 4424603..73e290e 100644
--- a/src/windows/common/CMakeLists.txt
+++ b/src/windows/common/CMakeLists.txt
@@ -2,16 +2,16 @@ set(SOURCES
ConsoleProgressBar.cpp
ConsoleProgressIndicator.cpp
DeviceHostProxy.cpp
- DeviceHostProxy.h
disk.cpp
Distribution.cpp
Dmesg.cpp
- Dmesg.h
DnsResolver.cpp
DnsTunnelingChannel.cpp
ExecutionContext.cpp
filesystem.cpp
GnsChannel.cpp
+ GnsPortTrackerChannel.cpp
+ GuestDeviceManager.cpp
HandleConsoleProgressBar.cpp
hcs.cpp
helpers.cpp
@@ -34,6 +34,8 @@ set(SOURCES
SubProcess.cpp
svccomm.cpp
svccommio.cpp
+ WSLAContainerLauncher.cpp
+ VirtioNetworking.cpp
WSLAProcessLauncher.cpp
WslClient.cpp
WslCoreConfig.cpp
@@ -55,11 +57,11 @@ set(HEADERS
../inc/LxssDynamicFunction.h
../inc/traceloggingconfig.h
../inc/wdk.h
- ../inc/wslconfig.h
../inc/wsl.h
+ ../inc/wslconfig.h
../inc/wslhost.h
- ../inc/WslPluginApi.h
../inc/wslpolicies.h
+ ../inc/WslPluginApi.h
../inc/wslrelay.h
../../shared/inc/CommandLine.h
../../shared/inc/defs.h
@@ -75,13 +77,17 @@ set(HEADERS
../../shared/inc/stringshared.h
ConsoleProgressBar.h
ConsoleProgressIndicator.h
+ DeviceHostProxy.h
disk.hpp
Distribution.h
+ Dmesg.h
DnsResolver.h
DnsTunnelingChannel.h
ExecutionContext.h
filesystem.hpp
GnsChannel.h
+ GnsPortTrackerChannel.h
+ GuestDeviceManager.h
HandleConsoleProgressBar.h
hcs.hpp
hcs_schema.h
@@ -106,6 +112,8 @@ set(HEADERS
SubProcess.h
svccomm.hpp
svccommio.hpp
+ WSLAContainerLauncher.h
+ VirtioNetworking.h
WSLAProcessLauncher.h
WslClient.h
WslCoreConfig.h
@@ -118,7 +126,7 @@ set(HEADERS
WslInstall.h
WslSecurity.h
WslTelemetry.h
- wslutil.cpp
+ wslutil.h
)
include_directories(${CMAKE_SOURCE_DIR}/src/windows/wslaclient)
diff --git a/src/windows/service/exe/GnsPortTrackerChannel.cpp b/src/windows/common/GnsPortTrackerChannel.cpp
similarity index 100%
rename from src/windows/service/exe/GnsPortTrackerChannel.cpp
rename to src/windows/common/GnsPortTrackerChannel.cpp
diff --git a/src/windows/service/exe/GnsPortTrackerChannel.h b/src/windows/common/GnsPortTrackerChannel.h
similarity index 100%
rename from src/windows/service/exe/GnsPortTrackerChannel.h
rename to src/windows/common/GnsPortTrackerChannel.h
diff --git a/src/windows/common/GuestDeviceManager.cpp b/src/windows/common/GuestDeviceManager.cpp
new file mode 100644
index 0000000..6b23a3b
--- /dev/null
+++ b/src/windows/common/GuestDeviceManager.cpp
@@ -0,0 +1,143 @@
+// Copyright (C) Microsoft Corporation. All rights reserved.
+
+#include "precomp.h"
+#include "GuestDeviceManager.h"
+#include "DeviceHostProxy.h"
+
+GuestDeviceManager::GuestDeviceManager(_In_ const std::wstring& machineId, _In_ const GUID& runtimeId) :
+ m_machineId(machineId), m_deviceHostSupport(wil::MakeOrThrow(machineId, runtimeId))
+{
+}
+
+_Requires_lock_not_held_(m_lock)
+GUID GuestDeviceManager::AddGuestDevice(
+ _In_ const GUID& DeviceId, _In_ const GUID& ImplementationClsid, _In_ PCWSTR AccessName, _In_opt_ PCWSTR Options, _In_ PCWSTR Path, _In_ UINT32 Flags, _In_ HANDLE UserToken)
+{
+ auto guestDeviceLock = m_lock.lock_exclusive();
+ return AddHdvShareWithOptions(DeviceId, ImplementationClsid, AccessName, Options, Path, Flags, UserToken);
+}
+
+_Requires_lock_held_(m_lock)
+GUID GuestDeviceManager::AddHdvShareWithOptions(
+ _In_ const GUID& DeviceId, _In_ const GUID& ImplementationClsid, _In_ PCWSTR AccessName, _In_opt_ PCWSTR Options, _In_ PCWSTR Path, _In_ UINT32 Flags, _In_ HANDLE UserToken)
+{
+ wil::com_ptr server;
+
+ // Options are appended to the name with a semi-colon separator.
+ // "name;key1=value1;key2=value2"
+ // The AddSharePath implementation is responsible for separating them out and interpreting them.
+ std::wstring nameWithOptions{AccessName};
+ if (ARGUMENT_PRESENT(Options))
+ {
+ nameWithOptions += L";";
+ nameWithOptions += Options;
+ }
+
+ {
+ auto revert = wil::impersonate_token(UserToken);
+
+ server = GetRemoteFileSystem(ImplementationClsid, c_defaultDeviceTag);
+ if (!server)
+ {
+ server = wil::CoCreateInstance(ImplementationClsid, (CLSCTX_LOCAL_SERVER | CLSCTX_ENABLE_CLOAKING | CLSCTX_ENABLE_AAA));
+ AddRemoteFileSystem(ImplementationClsid, c_defaultDeviceTag.c_str(), server);
+ }
+
+ THROW_IF_FAILED(server->AddSharePath(nameWithOptions.c_str(), Path, Flags));
+ }
+
+ // This requires more privileges than the user may have, so impersonation is disabled.
+ return AddNewDevice(DeviceId, server, AccessName);
+}
+
+GUID GuestDeviceManager::AddNewDevice(_In_ const GUID& deviceId, _In_ const wil::com_ptr& server, _In_ PCWSTR tag)
+{
+ return m_deviceHostSupport->AddNewDevice(deviceId, server, tag);
+}
+
+void GuestDeviceManager::AddRemoteFileSystem(_In_ REFCLSID clsid, _In_ PCWSTR tag, _In_ const wil::com_ptr& server)
+{
+ m_deviceHostSupport->AddRemoteFileSystem(clsid, tag, server);
+}
+
+void GuestDeviceManager::AddSharedMemoryDevice(_In_ const GUID& ImplementationClsid, _In_ PCWSTR Tag, _In_ PCWSTR Path, _In_ UINT32 SizeMb, _In_ HANDLE UserToken)
+{
+ auto guestDeviceLock = m_lock.lock_exclusive();
+ auto objectLifetime = CreateSectionObjectRoot(Path, UserToken);
+
+ // For virtiofs hdv, the flags parameter has been overloaded. Flags are placed in the lower
+ // 16 bits, while the shared memory size in megabytes are placed in the upper 16 bits.
+ static constexpr auto VIRTIO_FS_FLAGS_SHMEM_SIZE_SHIFT = 16;
+ UINT32 flags = (SizeMb << VIRTIO_FS_FLAGS_SHMEM_SIZE_SHIFT);
+ WI_SetFlag(flags, VIRTIO_FS_FLAGS_TYPE_SECTIONS);
+ (void)AddHdvShareWithOptions(VIRTIO_FS_DEVICE_ID, ImplementationClsid, Tag, {}, objectLifetime.Path.c_str(), flags, UserToken);
+ m_objectDirectories.emplace_back(std::move(objectLifetime));
+}
+
+GuestDeviceManager::DirectoryObjectLifetime GuestDeviceManager::CreateSectionObjectRoot(_In_ std::wstring_view RelativeRootPath, _In_ HANDLE UserToken) const
+{
+ auto revert = wil::impersonate_token(UserToken);
+ DWORD sessionId;
+ DWORD bytesWritten;
+ THROW_LAST_ERROR_IF(!GetTokenInformation(GetCurrentThreadToken(), TokenSessionId, &sessionId, sizeof(sessionId), &bytesWritten));
+
+ // /Sessions/1/BaseNamedObjects/WSL//
+ std::wstringstream sectionPathBuilder;
+ sectionPathBuilder << L"\\Sessions\\" << sessionId << L"\\BaseNamedObjects" << L"\\WSL\\" << m_machineId << L"\\" << RelativeRootPath;
+ auto sectionPath = sectionPathBuilder.str();
+
+ UNICODE_STRING ntPath{};
+ OBJECT_ATTRIBUTES attributes{};
+ attributes.Length = sizeof(OBJECT_ATTRIBUTES);
+ attributes.ObjectName = &ntPath;
+ std::vector directoryHierarchy;
+ auto remainingPath = std::wstring_view(sectionPath.data(), sectionPath.length());
+ while (remainingPath.length() > 0)
+ {
+ // Find the next path substring, ignoring the root path backslash.
+ auto nextDir = remainingPath;
+ const auto separatorPos = nextDir.find(L"\\", remainingPath[0] == L'\\' ? 1 : 0);
+ if (separatorPos != std::wstring_view::npos)
+ {
+ nextDir = nextDir.substr(0, separatorPos);
+ remainingPath = remainingPath.substr(separatorPos + 1, std::wstring_view::npos);
+
+ // Skip concurrent backslashes.
+ while (remainingPath.length() > 0 && remainingPath[0] == L'\\')
+ {
+ remainingPath = remainingPath.substr(1, std::wstring_view::npos);
+ }
+ }
+ else
+ {
+ remainingPath = remainingPath.substr(remainingPath.length(), std::wstring_view::npos);
+ }
+
+ attributes.RootDirectory = directoryHierarchy.size() > 0 ? directoryHierarchy.back().get() : nullptr;
+ ntPath.Buffer = const_cast(nextDir.data());
+ ntPath.Length = sizeof(WCHAR) * gsl::narrow_cast(nextDir.length());
+ ntPath.MaximumLength = ntPath.Length;
+ wil::unique_handle nextHandle;
+ NTSTATUS status = ZwCreateDirectoryObject(&nextHandle, DIRECTORY_ALL_ACCESS, &attributes);
+ if (status == STATUS_OBJECT_NAME_COLLISION)
+ {
+ status = NtOpenDirectoryObject(&nextHandle, MAXIMUM_ALLOWED, &attributes);
+ }
+ THROW_IF_NTSTATUS_FAILED(status);
+ directoryHierarchy.emplace_back(std::move(nextHandle));
+ }
+
+ return {std::move(sectionPath), std::move(directoryHierarchy)};
+}
+
+wil::com_ptr GuestDeviceManager::GetRemoteFileSystem(_In_ REFCLSID clsid, _In_ std::wstring_view tag)
+{
+ return m_deviceHostSupport->GetRemoteFileSystem(clsid, tag);
+}
+
+void GuestDeviceManager::Shutdown()
+try
+{
+ m_deviceHostSupport->Shutdown();
+}
+CATCH_LOG()
diff --git a/src/windows/common/GuestDeviceManager.h b/src/windows/common/GuestDeviceManager.h
new file mode 100644
index 0000000..53de3c6
--- /dev/null
+++ b/src/windows/common/GuestDeviceManager.h
@@ -0,0 +1,71 @@
+// Copyright (C) Microsoft Corporation. All rights reserved.
+
+#pragma once
+
+#include "DeviceHostProxy.h"
+
+// Flags for virtiofs vdev device creation.
+#define VIRTIO_FS_FLAGS_TYPE_FILES 0x8000
+#define VIRTIO_FS_FLAGS_TYPE_SECTIONS 0x4000
+
+inline const std::wstring c_defaultDeviceTag = L"default";
+
+// These device types are implemented by the external wsldevicehost vdev.
+DEFINE_GUID(VIRTIO_FS_DEVICE_ID, 0x872270E1, 0xA899, 0x4AF6, 0xB4, 0x54, 0x71, 0x93, 0x63, 0x44, 0x35, 0xAD); // {872270E1-A899-4AF6-B454-7193634435AD}
+DEFINE_GUID(VIRTIO_NET_DEVICE_ID, 0xF07010D0, 0x0EA9, 0x447F, 0x88, 0xEF, 0xBD, 0x95, 0x2A, 0x4D, 0x2F, 0x14); // {F07010D0-0EA9-447F-88EF-BD952A4D2F14}
+DEFINE_GUID(VIRTIO_PMEM_DEVICE_ID, 0xEDBB24BB, 0x5E19, 0x40F4, 0x8A, 0x0F, 0x82, 0x24, 0x31, 0x30, 0x64, 0xFD); // {EDBB24BB-5E19-40F4-8A0F-8224313064FD}
+
+//
+// Provides synchronized access to guest device operations.
+//
+class GuestDeviceManager
+{
+public:
+ GuestDeviceManager(_In_ const std::wstring& machineId, _In_ const GUID& runtimeId);
+
+ _Requires_lock_not_held_(m_lock)
+ GUID AddGuestDevice(
+ _In_ const GUID& DeviceId,
+ _In_ const GUID& ImplementationClsid,
+ _In_ PCWSTR AccessName,
+ _In_opt_ PCWSTR Options,
+ _In_ PCWSTR Path,
+ _In_ UINT32 Flags,
+ _In_ HANDLE UserToken);
+
+ GUID AddNewDevice(_In_ const GUID& deviceId, _In_ const wil::com_ptr& server, _In_ PCWSTR tag);
+
+ void AddRemoteFileSystem(_In_ REFCLSID clsid, _In_ PCWSTR tag, _In_ const wil::com_ptr& server);
+
+ void AddSharedMemoryDevice(_In_ const GUID& ImplementationClsid, _In_ PCWSTR Tag, _In_ PCWSTR Path, _In_ UINT32 SizeMb, _In_ HANDLE UserToken);
+
+ wil::com_ptr GetRemoteFileSystem(_In_ REFCLSID clsid, _In_ std::wstring_view tag);
+
+ void Shutdown();
+
+private:
+ _Requires_lock_held_(m_lock)
+ GUID AddHdvShareWithOptions(
+ _In_ const GUID& DeviceId,
+ _In_ const GUID& ImplementationClsid,
+ _In_ PCWSTR AccessName,
+ _In_opt_ PCWSTR Options,
+ _In_ PCWSTR Path,
+ _In_ UINT32 Flags,
+ _In_ HANDLE UserToken);
+
+ struct DirectoryObjectLifetime
+ {
+ std::wstring Path;
+ // Directory objects are temporary, even if they have children, so need to keep
+ // any created handles open in order for the directory to remain accessible.
+ std::vector HierarchyLifetimes;
+ };
+
+ DirectoryObjectLifetime CreateSectionObjectRoot(_In_ std::wstring_view RelativeRootPath, _In_ HANDLE UserToken) const;
+
+ wil::srwlock m_lock;
+ std::wstring m_machineId;
+ wil::com_ptr m_deviceHostSupport;
+ _Guarded_by_(m_lock) std::vector m_objectDirectories;
+};
diff --git a/src/windows/service/exe/VirtioNetworking.cpp b/src/windows/common/VirtioNetworking.cpp
similarity index 82%
rename from src/windows/service/exe/VirtioNetworking.cpp
rename to src/windows/common/VirtioNetworking.cpp
index 80766d7..aeb3722 100644
--- a/src/windows/service/exe/VirtioNetworking.cpp
+++ b/src/windows/common/VirtioNetworking.cpp
@@ -2,6 +2,7 @@
#include "precomp.h"
#include "VirtioNetworking.h"
+#include "GuestDeviceManager.h"
#include "Stringify.h"
#include "stringshared.h"
@@ -12,34 +13,18 @@ using wsl::core::VirtioNetworking;
static constexpr auto c_loopbackDeviceName = TEXT(LX_INIT_LOOPBACK_DEVICE_NAME);
-VirtioNetworking::VirtioNetworking(GnsChannel&& gnsChannel, const Config& config) :
- m_gnsChannel(std::move(gnsChannel)), m_config(config)
+VirtioNetworking::VirtioNetworking(
+ GnsChannel&& gnsChannel, bool enableLocalhostRelay, std::shared_ptr guestDeviceManager, GUID classId, wil::shared_handle userToken) :
+ m_guestDeviceManager(std::move(guestDeviceManager)),
+ m_userToken(std::move(userToken)),
+ m_gnsChannel(std::move(gnsChannel)),
+ m_enableLocalhostRelay(enableLocalhostRelay),
+ m_virtioNetworkClsid(classId)
{
}
-VirtioNetworking& VirtioNetworking::OnAddGuestDevice(const AddGuestDeviceRoutine& addGuestDeviceRoutine)
-{
- m_addGuestDeviceRoutine = addGuestDeviceRoutine;
- return *this;
-}
-
-VirtioNetworking& VirtioNetworking::OnModifyOpenPorts(const ModifyOpenPortsCallback& modifyOpenPortsCallback)
-{
- m_modifyOpenPortsCallback = modifyOpenPortsCallback;
- return *this;
-}
-
-VirtioNetworking& VirtioNetworking::OnGuestInterfaceStateChanged(const GuestInterfaceStateChangeCallback& guestInterfaceStateChangedCallback)
-{
- m_guestInterfaceStateChangeCallback = guestInterfaceStateChangedCallback;
- return *this;
-}
-
void VirtioNetworking::Initialize()
-try
{
- THROW_HR_IF(E_NOT_SET, !m_addGuestDeviceRoutine || !m_modifyOpenPortsCallback || !m_guestInterfaceStateChangeCallback);
-
m_networkSettings = GetHostEndpointSettings();
// TODO: Determine gateway MAC address
@@ -83,11 +68,12 @@ try
device_options << L"nameservers=" << dns_servers;
}
- // Add virtio net adapter to guest
- m_adapterId = (*m_addGuestDeviceRoutine)(c_virtioNetworkClsid, c_virtioNetworkDeviceId, L"eth0", device_options.str().c_str());
-
auto lock = m_lock.lock_exclusive();
+ // Add virtio net adapter to guest
+ m_adapterId = m_guestDeviceManager->AddGuestDevice(
+ VIRTIO_NET_DEVICE_ID, m_virtioNetworkClsid, L"eth0", nullptr, device_options.str().c_str(), 0, m_userToken.get());
+
hns::HNSEndpoint endpointProperties;
endpointProperties.ID = m_adapterId;
endpointProperties.IPAddress = m_networkSettings->PreferredIpAddress.AddressString;
@@ -121,19 +107,24 @@ try
UpdateDns(std::move(dnsSettings));
}
- if (m_config.EnableLocalhostRelay)
+ if (m_enableLocalhostRelay)
{
SetupLoopbackDevice();
}
THROW_IF_WIN32_ERROR(NotifyNetworkConnectivityHintChange(&VirtioNetworking::OnNetworkConnectivityChange, this, true, &m_networkNotifyHandle));
}
-CATCH_LOG()
void VirtioNetworking::SetupLoopbackDevice()
{
- m_localhostAdapterId = (*m_addGuestDeviceRoutine)(
- c_virtioNetworkClsid, c_virtioNetworkDeviceId, c_loopbackDeviceName, L"client_ip=127.0.0.1;client_mac=00:11:22:33:44:55");
+ m_localhostAdapterId = m_guestDeviceManager->AddGuestDevice(
+ VIRTIO_NET_DEVICE_ID,
+ m_virtioNetworkClsid,
+ c_loopbackDeviceName,
+ nullptr,
+ L"client_ip=127.0.0.1;client_mac=00:11:22:33:44:55",
+ 0,
+ m_userToken.get());
hns::HNSEndpoint endpointProperties;
endpointProperties.ID = m_localhostAdapterId;
@@ -162,7 +153,7 @@ void VirtioNetworking::StartPortTracker(wil::unique_socket&& socket)
m_gnsPortTrackerChannel.emplace(
std::move(socket),
[&](const SOCKADDR_INET& addr, int protocol, bool allocate) { return HandlePortNotification(addr, protocol, allocate); },
- [&](_In_ const std::string& interfaceName, _In_ bool up) { (*m_guestInterfaceStateChangeCallback)(interfaceName, up); });
+ [](const std::string&, bool) {}); // TODO: reconsider if InterfaceStateCallback is needed.
}
HRESULT VirtioNetworking::HandlePortNotification(const SOCKADDR_INET& addr, int protocol, bool allocate) const noexcept
@@ -181,7 +172,7 @@ HRESULT VirtioNetworking::HandlePortNotification(const SOCKADDR_INET& addr, int
}
}
- if (m_config.EnableLocalhostRelay && (unspecified || loopback))
+ if (m_enableLocalhostRelay && (unspecified || loopback))
{
SOCKADDR_INET localAddr = addr;
if (!loopback)
@@ -196,21 +187,65 @@ HRESULT VirtioNetworking::HandlePortNotification(const SOCKADDR_INET& addr, int
localAddr.Ipv6.sin6_port = addr.Ipv6.sin6_port;
}
}
- result = (*m_modifyOpenPortsCallback)(c_virtioNetworkClsid, c_loopbackDeviceName, localAddr, protocol, allocate);
+ result = ModifyOpenPorts(c_loopbackDeviceName, localAddr, protocol, allocate);
LOG_HR_IF_MSG(E_FAIL, result != S_OK, "Failure adding localhost relay port %d", localAddr.Ipv4.sin_port);
}
+
if (!loopback)
{
- const int localResult = (*m_modifyOpenPortsCallback)(c_virtioNetworkClsid, L"eth0", addr, protocol, allocate);
+ const int localResult = ModifyOpenPorts(L"eth0", addr, protocol, allocate);
LOG_HR_IF_MSG(E_FAIL, localResult != S_OK, "Failure adding relay port %d", addr.Ipv4.sin_port);
if (result == 0)
{
result = localResult;
}
}
+
return result;
}
+int VirtioNetworking::ModifyOpenPorts(_In_ PCWSTR tag, _In_ const SOCKADDR_INET& addr, _In_ int protocol, _In_ bool isOpen) const
+{
+ if (protocol != IPPROTO_TCP && protocol != IPPROTO_UDP)
+ {
+ LOG_HR_MSG(HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), "Unsupported bind protocol %d", protocol);
+ return 0;
+ }
+ else if (addr.si_family == AF_INET6)
+ {
+ // The virtio net adapter does not yet support IPv6 packets, so any traffic would arrive via
+ // IPv4. If the caller wants IPv4 they will also likely listen on an IPv4 address, which will
+ // be handled as a separate callback to this same code.
+ return 0;
+ }
+
+ auto lock = m_lock.lock_exclusive();
+ const auto server = m_guestDeviceManager->GetRemoteFileSystem(m_virtioNetworkClsid, c_defaultDeviceTag);
+ if (server)
+ {
+ std::wstring portString = std::format(L"tag={};port_number={}", tag, addr.Ipv4.sin_port);
+ if (protocol == IPPROTO_UDP)
+ {
+ portString += L";udp";
+ }
+
+ if (!isOpen)
+ {
+ portString += L";allocate=false";
+ }
+ else
+ {
+ wchar_t addrStr[16]; // "000.000.000.000" + null terminator
+ RtlIpv4AddressToStringW(&addr.Ipv4.sin_addr, addrStr);
+ portString += std::format(L";listen_addr={}", addrStr);
+ }
+
+ LOG_IF_FAILED(server->AddShare(portString.c_str(), nullptr, 0));
+ }
+
+ return 0;
+}
+
void NETIOAPI_API_ VirtioNetworking::OnNetworkConnectivityChange(PVOID context, NL_NETWORK_CONNECTIVITY_HINT hint)
{
static_cast(context)->RefreshGuestConnection(hint);
diff --git a/src/windows/service/exe/VirtioNetworking.h b/src/windows/common/VirtioNetworking.h
similarity index 58%
rename from src/windows/service/exe/VirtioNetworking.h
rename to src/windows/common/VirtioNetworking.h
index 617195e..2c78515 100644
--- a/src/windows/service/exe/VirtioNetworking.h
+++ b/src/windows/common/VirtioNetworking.h
@@ -6,23 +6,16 @@
#include "GnsChannel.h"
#include "WslCoreHostDnsInfo.h"
#include "GnsPortTrackerChannel.h"
+#include "GuestDeviceManager.h"
namespace wsl::core {
-using AddGuestDeviceRoutine = std::function;
-using ModifyOpenPortsCallback = std::function;
-using GuestInterfaceStateChangeCallback = std::function;
-
class VirtioNetworking : public INetworkingEngine
{
public:
- VirtioNetworking(GnsChannel&& gnsChannel, const Config& config);
+ VirtioNetworking(GnsChannel&& gnsChannel, bool enableLocalhostRelay, std::shared_ptr guestDeviceManager, GUID classId, wil::shared_handle userToken);
~VirtioNetworking() = default;
- VirtioNetworking& OnAddGuestDevice(const AddGuestDeviceRoutine& addGuestDeviceRoutine);
- VirtioNetworking& OnModifyOpenPorts(const ModifyOpenPortsCallback& modifyOpenPortsCallback);
- VirtioNetworking& OnGuestInterfaceStateChanged(const GuestInterfaceStateChangeCallback& guestInterfaceStateChangedCallback);
-
// Note: This class cannot be moved because m_networkNotifyHandle captures a 'this' pointer.
VirtioNetworking(const VirtioNetworking&) = delete;
VirtioNetworking(VirtioNetworking&&) = delete;
@@ -42,6 +35,7 @@ private:
static std::optional FindVirtioInterfaceLuid(const SOCKADDR_INET& virtioAddress, const NL_NETWORK_CONNECTIVITY_HINT& currentConnectivityHint);
HRESULT HandlePortNotification(const SOCKADDR_INET& addr, int protocol, bool allocate) const noexcept;
+ int ModifyOpenPorts(_In_ PCWSTR tag, _In_ const SOCKADDR_INET& addr, _In_ int protocol, _In_ bool isOpen) const;
void RefreshGuestConnection(NL_NETWORK_CONNECTIVITY_HINT hint) noexcept;
void SetupLoopbackDevice();
void UpdateDns(wsl::shared::hns::DNS&& dnsSettings);
@@ -49,17 +43,15 @@ private:
mutable wil::srwlock m_lock;
- std::optional m_addGuestDeviceRoutine;
+ std::shared_ptr m_guestDeviceManager;
+ wil::shared_handle m_userToken;
GnsChannel m_gnsChannel;
std::optional m_gnsPortTrackerChannel;
std::shared_ptr m_networkSettings;
- const Config& m_config;
+ bool m_enableLocalhostRelay;
GUID m_localhostAdapterId;
GUID m_adapterId;
- std::optional m_connectivityLevel;
- std::optional m_connectivityCost;
- std::optional m_modifyOpenPortsCallback;
- std::optional m_guestInterfaceStateChangeCallback;
+ GUID m_virtioNetworkClsid;
std::optional m_interfaceLuid;
ULONG m_networkMtu = 0;
@@ -67,11 +59,6 @@ private:
// Note: this field must be destroyed first to stop the callbacks before any other field is destroyed.
networking::unique_notify_handle m_networkNotifyHandle;
-
- // 16479D2E-F0C3-4DBA-BF7A-04FFF0892B07
- static constexpr GUID c_virtioNetworkClsid = {0x16479D2E, 0xF0C3, 0x4DBA, {0xBF, 0x7A, 0x04, 0xFF, 0xF0, 0x89, 0x2B, 0x07}};
- // F07010D0-0EA9-447F-88EF-BD952A4D2F14
- static constexpr GUID c_virtioNetworkDeviceId = {0xF07010D0, 0x0EA9, 0x447F, {0x88, 0xEF, 0xBD, 0x95, 0x2A, 0x4D, 0x2F, 0x14}};
};
} // namespace wsl::core
diff --git a/src/windows/common/WSLAContainerLauncher.cpp b/src/windows/common/WSLAContainerLauncher.cpp
new file mode 100644
index 0000000..950fb64
--- /dev/null
+++ b/src/windows/common/WSLAContainerLauncher.cpp
@@ -0,0 +1,74 @@
+/*++
+
+Copyright (c) Microsoft. All rights reserved.
+
+Module Name:
+
+ WSLAContainerLauncher.cpp
+
+Abstract:
+
+ This file contains the implementation for WSLAContainerLauncher.
+
+--*/
+#include "WSLAContainerLauncher.h"
+
+using wsl::windows::common::ClientRunningWSLAProcess;
+using wsl::windows::common::RunningWSLAContainer;
+using wsl::windows::common::WSLAContainerLauncher;
+
+RunningWSLAContainer::RunningWSLAContainer(wil::com_ptr&& Container, std::vector&& fds) :
+ m_container(std::move(Container)), m_fds(std::move(fds))
+{
+}
+
+IWSLAContainer& RunningWSLAContainer::Get()
+{
+ return *m_container;
+}
+
+WSLA_CONTAINER_STATE RunningWSLAContainer::State()
+{
+ WSLA_CONTAINER_STATE state{};
+ THROW_IF_FAILED(m_container->GetState(&state));
+ return state;
+}
+
+ClientRunningWSLAProcess RunningWSLAContainer::GetInitProcess()
+{
+ wil::com_ptr process;
+ THROW_IF_FAILED(m_container->GetInitProcess(&process));
+
+ return ClientRunningWSLAProcess{std::move(process), std::move(m_fds)};
+}
+
+WSLAContainerLauncher::WSLAContainerLauncher(
+ const std::string& Image,
+ const std::string& Name,
+ const std::string& EntryPoint,
+ const std::vector& Arguments,
+ const std::vector& Environment,
+ ProcessFlags Flags) :
+ WSLAProcessLauncher(EntryPoint, Arguments, Environment, Flags), m_image(Image), m_name(Name)
+{
+}
+
+RunningWSLAContainer WSLAContainerLauncher::Launch(IWSLASession& Session)
+{
+ WSLA_CONTAINER_OPTIONS options{};
+ options.Image = m_image.c_str();
+ options.Name = m_name.c_str();
+ auto [processOptions, commandLinePtrs, environmentPtrs] = CreateProcessOptions();
+ options.InitProcessOptions = processOptions;
+
+ if (m_executable.empty())
+ {
+ options.InitProcessOptions.Executable = nullptr;
+ }
+
+ // TODO: Support volumes, ports, flags, shm size, container networking mode, etc.
+ wil::com_ptr container;
+ THROW_IF_FAILED(Session.CreateContainer(&options, &container));
+
+ return RunningWSLAContainer{std::move(container), std::move(m_fds)};
+}
\ No newline at end of file
diff --git a/src/windows/common/WSLAContainerLauncher.h b/src/windows/common/WSLAContainerLauncher.h
new file mode 100644
index 0000000..9a4447e
--- /dev/null
+++ b/src/windows/common/WSLAContainerLauncher.h
@@ -0,0 +1,59 @@
+/*++
+
+Copyright (c) Microsoft. All rights reserved.
+
+Module Name:
+
+ WSLAContainerLauncher.h
+
+Abstract:
+
+ This file contains the definition for WSLAContainerLauncher.
+
+--*/
+
+#pragma once
+#include "WSLAProcessLauncher.h"
+
+namespace wsl::windows::common {
+
+class RunningWSLAContainer
+{
+public:
+ NON_COPYABLE(RunningWSLAContainer);
+ DEFAULT_MOVABLE(RunningWSLAContainer);
+ RunningWSLAContainer(wil::com_ptr&& Container, std::vector&& fds);
+ IWSLAContainer& Get();
+
+ WSLA_CONTAINER_STATE State();
+ ClientRunningWSLAProcess GetInitProcess();
+
+private:
+ wil::com_ptr m_container;
+ std::vector m_fds;
+};
+
+class WSLAContainerLauncher : public WSLAProcessLauncher
+{
+public:
+ NON_COPYABLE(WSLAContainerLauncher);
+ NON_MOVABLE(WSLAContainerLauncher);
+
+ WSLAContainerLauncher(
+ const std::string& Image,
+ const std::string& Name,
+ const std::string& EntryPoint = "",
+ const std::vector& Arguments = {},
+ const std::vector& Environment = {},
+ ProcessFlags Flags = ProcessFlags::Stdout | ProcessFlags::Stderr);
+
+ void AddVolume(const std::string& HostPath, const std::string& ContainerPath, bool ReadOnly);
+ void AddPort(uint16_t WindowsPort, uint16_t ContainerPort, int Family);
+
+ RunningWSLAContainer Launch(IWSLASession& Session);
+
+private:
+ std::string m_image;
+ std::string m_name;
+};
+} // namespace wsl::windows::common
\ No newline at end of file
diff --git a/src/windows/common/WSLAProcessLauncher.cpp b/src/windows/common/WSLAProcessLauncher.cpp
index 6e2b4cd..84a3cf4 100644
--- a/src/windows/common/WSLAProcessLauncher.cpp
+++ b/src/windows/common/WSLAProcessLauncher.cpp
@@ -48,6 +48,12 @@ void WSLAProcessLauncher::AddFd(WSLA_PROCESS_FD Fd)
m_fds.push_back(Fd);
}
+void WSLAProcessLauncher::SetTtySize(ULONG Rows, ULONG Columns)
+{
+ m_rows = Rows;
+ m_columns = Columns;
+}
+
std::tuple, std::vector> WSLAProcessLauncher::CreateProcessOptions()
{
std::vector commandLine;
@@ -64,6 +70,8 @@ std::tuple, std::vector(m_fds.size());
options.Environment = environment.data();
options.EnvironmentCount = static_cast(environment.size());
+ options.TtyColumns = m_columns;
+ options.TtyRows = m_rows;
return std::make_tuple(options, std::move(commandLine), std::move(environment));
}
@@ -150,7 +158,7 @@ ClientRunningWSLAProcess WSLAProcessLauncher::Launch(IWSLASession& Session)
THROW_HR_MSG(hresult, "Failed to launch process: %hs (commandline: %hs). Errno = %i", m_executable.c_str(), commandLine.c_str(), error);
}
- return process.value();
+ return std::move(process.value());
}
std::tuple> WSLAProcessLauncher::LaunchNoThrow(IWSLASession& Session)
diff --git a/src/windows/common/WSLAProcessLauncher.h b/src/windows/common/WSLAProcessLauncher.h
index 97fd2ac..e86b068 100644
--- a/src/windows/common/WSLAProcessLauncher.h
+++ b/src/windows/common/WSLAProcessLauncher.h
@@ -43,6 +43,9 @@ public:
};
RunningWSLAProcess(std::vector&& fds);
+ NON_COPYABLE(RunningWSLAProcess);
+ DEFAULT_MOVABLE(RunningWSLAProcess);
+
ProcessResult WaitAndCaptureOutput(DWORD TimeoutMs = INFINITE, std::vector>&& ExtraHandles = {});
virtual wil::unique_handle GetStdHandle(int Index) = 0;
virtual wil::unique_event GetExitEvent() = 0;
@@ -57,6 +60,9 @@ protected:
class ClientRunningWSLAProcess : public RunningWSLAProcess
{
public:
+ NON_COPYABLE(ClientRunningWSLAProcess);
+ DEFAULT_MOVABLE(ClientRunningWSLAProcess);
+
ClientRunningWSLAProcess(wil::com_ptr&& process, std::vector&& fds);
wil::unique_handle GetStdHandle(int Index) override;
wil::unique_event GetExitEvent() override;
@@ -68,7 +74,6 @@ protected:
private:
wil::com_ptr m_process;
};
-
class WSLAProcessLauncher
{
public:
@@ -82,6 +87,7 @@ public:
ProcessFlags Flags = ProcessFlags::Stdout | ProcessFlags::Stderr);
void AddFd(WSLA_PROCESS_FD Fd);
+ void SetTtySize(ULONG Rows, ULONG Columns);
// TODO: Add overloads for IWSLAContainer once implemented.
ClientRunningWSLAProcess Launch(IWSLASession& Session);
@@ -95,6 +101,8 @@ protected:
std::string m_executable;
std::vector m_arguments;
std::vector m_environment;
+ DWORD m_rows = 0;
+ DWORD m_columns = 0;
};
} // namespace wsl::windows::common
\ No newline at end of file
diff --git a/src/windows/common/WslClient.cpp b/src/windows/common/WslClient.cpp
index 6b40f92..f17e0a2 100644
--- a/src/windows/common/WslClient.cpp
+++ b/src/windows/common/WslClient.cpp
@@ -1525,64 +1525,61 @@ int RunDebugShell()
THROW_HR(HCS_E_CONNECTION_CLOSED);
}
+DEFINE_ENUM_FLAG_OPERATORS(WSLAFeatureFlags);
+
// Temporary debugging tool for WSLA
int WslaShell(_In_ std::wstring_view commandLine)
{
-#ifdef WSLA_TEST_DISTRO_PATH
+ WSLA_SESSION_SETTINGS sessionSettings{};
+ sessionSettings.DisplayName = L"WSLAShell";
+ sessionSettings.CpuCount = 4;
+ sessionSettings.MemoryMb = 4096;
+ sessionSettings.NetworkingMode = WSLANetworkingModeNAT;
+ sessionSettings.BootTimeoutMs = 30 * 1000;
+ sessionSettings.MaximumStorageSizeMb = 4096;
- std::wstring vhd = TEXT(WSLA_TEST_DISTRO_PATH);
std::string shell = "/bin/sh";
- std::string fsType = "squashfs";
-#else
-
- std::wstring vhd = wsl::windows::common::wslutil::GetMsiPackagePath().value() + L"/system.vhd";
- std::string shell = "/bin/bash";
- std::string fsType = "ext4";
-
-#endif
-
- VIRTUAL_MACHINE_SETTINGS settings{};
- settings.CpuCount = 4;
- settings.DisplayName = L"WSLA";
- settings.MemoryMb = 1024;
- settings.BootTimeoutMs = 30000;
- settings.NetworkingMode = WSLANetworkingModeNAT;
- std::wstring containerRootVhd;
+ std::string containerImage;
bool help = false;
+ std::wstring debugShell;
+ std::wstring storagePath;
+ std::wstring rootVhdOverride;
+ std::string rootVhdTypeOverride;
ArgumentParser parser(std::wstring{commandLine}, WSL_BINARY_NAME);
- parser.AddArgument(vhd, L"--vhd");
+ parser.AddArgument(rootVhdOverride, L"--vhd");
parser.AddArgument(Utf8String(shell), L"--shell");
- parser.AddArgument(reinterpret_cast(settings.EnableDnsTunneling), L"--dns-tunneling");
- parser.AddArgument(Integer(settings.MemoryMb), L"--memory");
- parser.AddArgument(Integer(settings.CpuCount), L"--cpu");
- parser.AddArgument(Utf8String(fsType), L"--fstype");
- parser.AddArgument(containerRootVhd, L"--container-vhd");
+ parser.AddArgument(
+ SetFlag(reinterpret_cast(sessionSettings.FeatureFlags)), L"--dns-tunneling");
+ parser.AddArgument(Integer(sessionSettings.MemoryMb), L"--memory");
+ parser.AddArgument(Integer(sessionSettings.CpuCount), L"--cpu");
+ parser.AddArgument(Utf8String(rootVhdTypeOverride), L"--fstype");
+ parser.AddArgument(storagePath, L"--storage");
+ parser.AddArgument(Integer(reinterpret_cast(sessionSettings.NetworkingMode)), L"--networking-mode");
+ parser.AddArgument(Utf8String(containerImage), L"--image");
+ parser.AddArgument(debugShell, L"--debug-shell");
parser.AddArgument(help, L"--help");
parser.Parse();
if (help)
{
const auto usage = std::format(
- LR"({} --wsla [--vhd ] [--shell ] [--memory ] [--cpu ] [--dns-tunneling] [--fstype ] [--container-vhd ] [--help])",
+ LR"({} --wsla [--vhd ] [--shell ] [--memory ] [--cpu ] [--dns-tunneling] [--networking-mode ] [--fstype ] [--container-vhd ] [--help])",
WSL_BINARY_NAME);
wprintf(L"%ls\n", usage.c_str());
return 1;
}
- if (!containerRootVhd.empty())
+ switch (sessionSettings.NetworkingMode)
{
- settings.ContainerRootVhd = containerRootVhd.c_str();
-
- if (!std::filesystem::exists(containerRootVhd))
- {
- auto token = wil::open_current_access_token();
- auto tokenInfo = wil::get_token_information(token.get());
- wsl::core::filesystem::CreateVhd(containerRootVhd.c_str(), 5368709120 /* 5 GB */, tokenInfo->User.Sid, FALSE, FALSE);
- settings.FormatContainerRootVhd = TRUE;
- }
+ case WSLANetworkingMode::WSLANetworkingModeNone:
+ case WSLANetworkingMode::WSLANetworkingModeNAT:
+ case WSLANetworkingMode::WSLANetworkingModeVirtioProxy:
+ break;
+ default:
+ THROW_HR(E_INVALIDARG);
}
wil::com_ptr userSession;
@@ -1590,33 +1587,86 @@ int WslaShell(_In_ std::wstring_view commandLine)
wsl::windows::common::security::ConfigureForCOMImpersonation(userSession.get());
wil::com_ptr virtualMachine;
- WSLA_SESSION_SETTINGS sessionSettings{L"WSLA Test Session"};
wil::com_ptr session;
- settings.RootVhd = vhd.c_str();
- settings.RootVhdType = fsType.c_str();
- THROW_IF_FAILED(userSession->CreateSession(&sessionSettings, &settings, &session));
- THROW_IF_FAILED(session->GetVirtualMachine(&virtualMachine));
- wsl::windows::common::security::ConfigureForCOMImpersonation(userSession.get());
-
- if (!containerRootVhd.empty())
+ if (!rootVhdOverride.empty())
{
- wsl::windows::common::WSLAProcessLauncher initProcessLauncher{shell, {shell, "/etc/lsw-init.sh"}};
- auto initProcess = initProcessLauncher.Launch(*session);
- THROW_HR_IF(E_FAIL, initProcess.WaitAndCaptureOutput().Code != 0);
+ if (rootVhdTypeOverride.empty())
+ {
+ wprintf(L"--fstype required when --vhd is passed\n");
+ return 1;
+ }
+
+ sessionSettings.RootVhdOverride = rootVhdOverride.c_str();
+ sessionSettings.RootVhdTypeOverride = rootVhdTypeOverride.c_str();
}
+ if (!storagePath.empty())
+ {
+ storagePath = std::filesystem::weakly_canonical(storagePath).wstring();
+ sessionSettings.StoragePath = storagePath.c_str();
+ }
+
+ if (!debugShell.empty())
+ {
+ THROW_IF_FAILED(userSession->OpenSessionByName(debugShell.c_str(), &session));
+ }
+ else
+ {
+ THROW_IF_FAILED(userSession->CreateSession(&sessionSettings, &session));
+ THROW_IF_FAILED(session->GetVirtualMachine(&virtualMachine));
+
+ wsl::windows::common::security::ConfigureForCOMImpersonation(userSession.get());
+ }
+
+ std::optional> container;
+ std::optional process;
+ // Get the terminal size.
+ HANDLE Stdout = GetStdHandle(STD_OUTPUT_HANDLE);
+ HANDLE Stdin = GetStdHandle(STD_INPUT_HANDLE);
+
+ CONSOLE_SCREEN_BUFFER_INFOEX Info{};
+ Info.cbSize = sizeof(Info);
+ THROW_IF_WIN32_BOOL_FALSE(::GetConsoleScreenBufferInfoEx(Stdout, &Info));
+
wsl::windows::common::WSLAProcessLauncher launcher{shell, {shell}, {"TERM=xterm-256color"}, ProcessFlags::None};
launcher.AddFd(WSLA_PROCESS_FD{.Fd = 0, .Type = WSLAFdTypeTerminalInput});
launcher.AddFd(WSLA_PROCESS_FD{.Fd = 1, .Type = WSLAFdTypeTerminalOutput});
launcher.AddFd(WSLA_PROCESS_FD{.Fd = 2, .Type = WSLAFdTypeTerminalControl});
+ launcher.SetTtySize(Info.srWindow.Bottom - Info.srWindow.Top + 1, Info.srWindow.Right - Info.srWindow.Left + 1);
- auto process = launcher.Launch(*session);
+ if (containerImage.empty())
+ {
+ wsl::windows::common::WSLAProcessLauncher launcher{shell, {shell}, {"TERM=xterm-256color"}, ProcessFlags::None};
+ launcher.AddFd(WSLA_PROCESS_FD{.Fd = 0, .Type = WSLAFdTypeTerminalInput});
+ launcher.AddFd(WSLA_PROCESS_FD{.Fd = 1, .Type = WSLAFdTypeTerminalOutput});
+ launcher.AddFd(WSLA_PROCESS_FD{.Fd = 2, .Type = WSLAFdTypeTerminalControl});
+
+ process = launcher.Launch(*session);
+ }
+ else
+ {
+ std::vector fds{
+ WSLA_PROCESS_FD{.Fd = 0, .Type = WSLAFdTypeTerminalInput},
+ WSLA_PROCESS_FD{.Fd = 1, .Type = WSLAFdTypeTerminalOutput},
+ WSLA_PROCESS_FD{.Fd = 2, .Type = WSLAFdTypeTerminalControl},
+ };
+
+ WSLA_CONTAINER_OPTIONS containerOptions{};
+ containerOptions.Image = containerImage.c_str();
+ containerOptions.Name = "test-container";
+ containerOptions.InitProcessOptions.Fds = fds.data();
+ containerOptions.InitProcessOptions.FdsCount = static_cast(fds.size());
+
+ container.emplace();
+ THROW_IF_FAILED(session->CreateContainer(&containerOptions, &container.value()));
+
+ wil::com_ptr initProcess;
+ THROW_IF_FAILED((*container)->GetInitProcess(&initProcess));
+ process.emplace(std::move(initProcess), std::move(fds));
+ }
// Configure console for interactive usage.
-
- HANDLE Stdout = GetStdHandle(STD_OUTPUT_HANDLE);
- HANDLE Stdin = GetStdHandle(STD_INPUT_HANDLE);
{
DWORD OutputMode{};
THROW_LAST_ERROR_IF(!::GetConsoleMode(Stdout, &OutputMode));
@@ -1641,7 +1691,7 @@ int WslaShell(_In_ std::wstring_view commandLine)
auto exitEvent = wil::unique_event(wil::EventOptions::ManualReset);
wsl::shared::SocketChannel controlChannel{
- wil::unique_socket{(SOCKET)process.GetStdHandle(2).release()}, "TerminalControl", exitEvent.get()};
+ wil::unique_socket{(SOCKET)process->GetStdHandle(2).release()}, "TerminalControl", exitEvent.get()};
std::thread inputThread([&]() {
auto updateTerminal = [&controlChannel, &Stdout]() {
@@ -1657,7 +1707,7 @@ int WslaShell(_In_ std::wstring_view commandLine)
controlChannel.SendMessage(message);
};
- wsl::windows::common::relay::StandardInputRelay(Stdin, process.GetStdHandle(0).get(), updateTerminal, exitEvent.get());
+ wsl::windows::common::relay::StandardInputRelay(Stdin, process->GetStdHandle(0).get(), updateTerminal, exitEvent.get());
});
auto joinThread = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [&]() {
@@ -1666,12 +1716,12 @@ int WslaShell(_In_ std::wstring_view commandLine)
});
// Relay the contents of the pipe to stdout.
- wsl::windows::common::relay::InterruptableRelay(process.GetStdHandle(1).get(), Stdout);
+ wsl::windows::common::relay::InterruptableRelay(process->GetStdHandle(1).get(), Stdout);
}
- process.GetExitEvent().wait();
+ process->GetExitEvent().wait();
- auto [code, signalled] = process.GetExitState();
+ auto [code, signalled] = process->GetExitState();
wprintf(L"%hs exited with: %i%hs", shell.c_str(), code, signalled ? " (signalled)" : "");
return code;
diff --git a/src/windows/common/WslCoreFilesystem.cpp b/src/windows/common/WslCoreFilesystem.cpp
index 6fd79b3..92cbe01 100644
--- a/src/windows/common/WslCoreFilesystem.cpp
+++ b/src/windows/common/WslCoreFilesystem.cpp
@@ -29,8 +29,10 @@ wil::unique_hfile wsl::core::filesystem::CreateFile(
void wsl::core::filesystem::CreateVhd(_In_ LPCWSTR target, _In_ ULONGLONG maximumSize, _In_ PSID userSid, _In_ BOOL sparse, _In_ BOOL fixed)
{
- WI_ASSERT(wsl::windows::common::string::IsPathComponentEqual(
- std::filesystem::path{target}.extension().native(), windows::common::wslutil::c_vhdxFileExtension));
+ THROW_HR_IF(
+ E_INVALIDARG,
+ !wsl::windows::common::string::IsPathComponentEqual(
+ std::filesystem::path{target}.extension().native(), windows::common::wslutil::c_vhdxFileExtension));
// Disable creation of sparse VHDs while data corruption is being debugged.
if (sparse)
diff --git a/src/windows/common/svccomm.cpp b/src/windows/common/svccomm.cpp
index 4f33f4b..c82c0d8 100644
--- a/src/windows/common/svccomm.cpp
+++ b/src/windows/common/svccomm.cpp
@@ -167,16 +167,13 @@ wsl::windows::common::SvcComm::SvcComm()
};
wsl::shared::retry::RetryWithTimeout(
- [this]() {
- THROW_IF_FAILED(CoCreateInstance(__uuidof(LxssUserSession), nullptr, CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&m_userSession)));
- },
+ [this]() { m_userSession = wil::CoCreateInstance(CLSCTX_LOCAL_SERVER); },
std::chrono::seconds(1),
std::chrono::minutes(1),
retry_pred);
// Query client security interface.
- wil::com_ptr_nothrow clientSecurity;
- THROW_IF_FAILED(m_userSession->QueryInterface(IID_PPV_ARGS(&clientSecurity)));
+ auto clientSecurity = m_userSession.query();
// Get the current proxy blanket settings.
DWORD authnSvc, authzSvc, authnLvl, capabilities;
diff --git a/src/windows/common/wslutil.cpp b/src/windows/common/wslutil.cpp
index fd0f10c..8c4ad8a 100644
--- a/src/windows/common/wslutil.cpp
+++ b/src/windows/common/wslutil.cpp
@@ -143,7 +143,8 @@ static const std::map g_commonErrors{
X_WIN32(ERROR_OPERATION_ABORTED),
X_WIN32(WSAECONNREFUSED),
X_WIN32(ERROR_BAD_PATHNAME),
- X(WININET_E_TIMEOUT)};
+ X(WININET_E_TIMEOUT),
+ X_WIN32(ERROR_INVALID_SID)};
#undef X
@@ -624,6 +625,11 @@ std::wstring wsl::windows::common::wslutil::DownloadFileImpl(
void wsl::windows::common::wslutil::EnforceFileLimit(LPCWSTR Path, size_t Limit, const std::function& pred)
{
+ if (Limit <= 0)
+ {
+ return;
+ }
+
std::map files;
for (auto const& e : std::filesystem::directory_iterator{Path})
{
@@ -633,7 +639,7 @@ void wsl::windows::common::wslutil::EnforceFileLimit(LPCWSTR Path, size_t Limit,
}
}
- if (Limit < 0 || files.size() < Limit)
+ if (files.size() < Limit)
{
return;
}
diff --git a/src/windows/common/wslutil.h b/src/windows/common/wslutil.h
index 34a6d71..99af59b 100644
--- a/src/windows/common/wslutil.h
+++ b/src/windows/common/wslutil.h
@@ -79,6 +79,22 @@ void CoInitializeSecurity();
void ConfigureCrt();
+///
+/// Creates a COM server with user impersonation.
+///
+template
+wil::com_ptr_t CreateComServerAsUser(_In_ REFCLSID RefClsId, _In_ HANDLE UserToken)
+{
+ auto revert = wil::impersonate_token(UserToken);
+ return wil::CoCreateInstance(RefClsId, (CLSCTX_LOCAL_SERVER | CLSCTX_ENABLE_CLOAKING | CLSCTX_ENABLE_AAA));
+}
+
+template
+wil::com_ptr_t CreateComServerAsUser(_In_ HANDLE UserToken)
+{
+ return CreateComServerAsUser(__uuidof(Class), UserToken);
+}
+
std::wstring ConstructPipePath(_In_ std::wstring_view PipeName);
GUID CreateV5Uuid(const GUID& namespaceGuid, const std::span name);
diff --git a/src/windows/inc/comservicehelper.h b/src/windows/inc/comservicehelper.h
index 9c412db..227cf3a 100644
--- a/src/windows/inc/comservicehelper.h
+++ b/src/windows/inc/comservicehelper.h
@@ -77,7 +77,7 @@ namespace Windows { namespace Internal {
// Tell COM how to mask fatal exceptions.
if (ownProcess)
{
- Microsoft::WRL::ComPtr pIGLB;
+ wil::com_ptr pIGLB;
RETURN_IF_FAILED(CoCreateInstance(CLSID_GlobalOptions, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pIGLB)));
RETURN_IF_FAILED(pIGLB->Set(COMGLB_EXCEPTION_HANDLING, TExceptionPolicy));
}
@@ -294,7 +294,7 @@ namespace Windows { namespace Internal {
bool m_addedModuleReference = false;
// COM callback object to support unloading shared-process services
- Microsoft::WRL::ComPtr m_icc;
+ wil::com_ptr m_icc;
// COM Server descriptor
ServerDescriptor m_serverDescriptor{};
diff --git a/src/windows/service/exe/CMakeLists.txt b/src/windows/service/exe/CMakeLists.txt
index 636fa25..620e127 100644
--- a/src/windows/service/exe/CMakeLists.txt
+++ b/src/windows/service/exe/CMakeLists.txt
@@ -4,13 +4,11 @@ set(SOURCES
LxssUserSession.cpp
LxssUserSessionFactory.cpp
LxssIptables.cpp
- LxssUserCallback.cpp
LxssHttpProxy.cpp
LxssInstance.cpp
PluginManager.cpp
ServiceMain.cpp
BridgedNetworking.cpp
- GnsPortTrackerChannel.cpp
GnsRpcServer.cpp
GuestTelemetryLogger.cpp
Lifetime.cpp
@@ -22,7 +20,6 @@ set(SOURCES
WslMirroredNetworking.cpp
WslCoreTcpIpStateTracking.cpp
WslCoreVm.cpp
- VirtioNetworking.cpp
main.rc
${CMAKE_CURRENT_BINARY_DIR}/../mc/${TARGET_PLATFORM}/${CMAKE_BUILD_TYPE}/wsleventschema.rc
application.manifest)
@@ -38,7 +35,6 @@ set(HEADERS
PluginManager.h
LxssInstance.h
BridgedNetworking.h
- GnsPortTrackerChannel.h
GnsRpcServer.h
GuestTelemetryLogger.h
IMirroredNetworkManager.h
diff --git a/src/windows/service/exe/LxssIpTables.cpp b/src/windows/service/exe/LxssIpTables.cpp
index afd1cc0..2b7a143 100644
--- a/src/windows/service/exe/LxssIpTables.cpp
+++ b/src/windows/service/exe/LxssIpTables.cpp
@@ -335,7 +335,7 @@ const std::wstring LxssNetworkingFirewall::s_FriendlyNamePrefix(L"WSLRULE_177744
LxssNetworkingFirewall::LxssNetworkingFirewall()
{
- THROW_IF_FAILED(::CoCreateInstance(__uuidof(NetFwPolicy2), NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&m_firewall)));
+ m_firewall = wil::CoCreateInstance(CLSCTX_INPROC_SERVER);
}
void LxssNetworkingFirewall::CopyPartialArray(SAFEARRAY* Destination, SAFEARRAY* Source, ULONG DestinationIndexStart, ULONG SourceIndexStart, ULONG ElementsToCopy)
@@ -388,8 +388,7 @@ void LxssNetworkingFirewall::CopyPartialArray(SAFEARRAY* Destination, SAFEARRAY*
std::wstring LxssNetworkingFirewall::AddPortRule(const IP_ADDRESS_PREFIX& Address) const
{
- Microsoft::WRL::ComPtr newRule;
- THROW_IF_FAILED(::CoCreateInstance(__uuidof(NetFwRule), NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&newRule)));
+ auto newRule = wil::CoCreateInstance(CLSCTX_INPROC_SERVER);
// Open a port via the firewall by creating a rule that specifies the local
// address and the local port to allow. Currently this rule only applies to
@@ -412,9 +411,9 @@ std::wstring LxssNetworkingFirewall::AddPortRule(const IP_ADDRESS_PREFIX& Addres
THROW_IF_FAILED(newRule->put_Description(s_DefaultRuleDescription.get()));
THROW_IF_FAILED(newRule->put_Enabled(VARIANT_TRUE));
// Add the rule to the existing set.
- Microsoft::WRL::ComPtr rules;
+ wil::com_ptr rules;
THROW_IF_FAILED(m_firewall->get_Rules(&rules));
- THROW_IF_FAILED(rules->Add(newRule.Get()));
+ THROW_IF_FAILED(rules->Add(newRule.get()));
// Return the unique rule name to the caller.
return generatedName;
}
@@ -423,12 +422,11 @@ void LxssNetworkingFirewall::CleanupRemnants()
{
auto firewall = std::make_shared();
THROW_HR_IF(E_OUTOFMEMORY, !firewall);
- Microsoft::WRL::ComPtr rules;
+ wil::com_ptr rules;
THROW_IF_FAILED(firewall->m_firewall->get_Rules(&rules));
- Microsoft::WRL::ComPtr enumInterface;
- THROW_IF_FAILED(rules->get__NewEnum(enumInterface.GetAddressOf()));
- Microsoft::WRL::ComPtr rulesEnum;
- THROW_IF_FAILED(enumInterface.As(&rulesEnum));
+ wil::com_ptr enumInterface;
+ THROW_IF_FAILED(rules->get__NewEnum(enumInterface.addressof()));
+ auto rulesEnum = enumInterface.query();
// Find any rules with the unique WSL prefix and destroy them.
for (;;)
{
@@ -440,7 +438,7 @@ void LxssNetworkingFirewall::CleanupRemnants()
break;
}
- Microsoft::WRL::ComPtr nextRule;
+ wil::com_ptr nextRule;
THROW_IF_FAILED(next.pdispVal->QueryInterface(IID_PPV_ARGS(&nextRule)));
wil::unique_bstr nextRuleName;
THROW_IF_FAILED(nextRule->get_Name(nextRuleName.addressof()));
@@ -558,7 +556,7 @@ void LxssNetworkingFirewall::RemoveExcludedAdapter(const std::wstring& AdapterNa
void LxssNetworkingFirewall::RemovePortRule(const std::wstring& RuleName) const
{
- Microsoft::WRL::ComPtr rules;
+ wil::com_ptr rules;
THROW_IF_FAILED(m_firewall->get_Rules(&rules));
THROW_IF_FAILED(rules->Remove(wil::make_bstr_failfast(RuleName.c_str()).get()));
}
@@ -572,8 +570,7 @@ LxssNetworkingFirewallPort::LxssNetworkingFirewallPort(const std::shared_ptr& Firewall, const Microsoft::WRL::ComPtr& Existing) :
+LxssNetworkingFirewallPort::LxssNetworkingFirewallPort(const std::shared_ptr& Firewall, const wil::com_ptr& Existing) :
m_firewall(Firewall)
{
wil::unique_bstr ruleName;
diff --git a/src/windows/service/exe/LxssIpTables.h b/src/windows/service/exe/LxssIpTables.h
index fca26e3..0429d9a 100644
--- a/src/windows/service/exe/LxssIpTables.h
+++ b/src/windows/service/exe/LxssIpTables.h
@@ -262,7 +262,7 @@ private:
///
/// COM firewall instance.
///
- Microsoft::WRL::ComPtr m_firewall;
+ wil::com_ptr m_firewall;
///
/// Lock to protect class members.
@@ -295,7 +295,7 @@ public:
///
/// Constructor to take ownership of an existing rule.
///
- LxssNetworkingFirewallPort(const std::shared_ptr& Firewall, const Microsoft::WRL::ComPtr& Existing);
+ LxssNetworkingFirewallPort(const std::shared_ptr& Firewall, const wil::com_ptr& Existing);
///
/// Destructor.
diff --git a/src/windows/service/exe/LxssUserSession.cpp b/src/windows/service/exe/LxssUserSession.cpp
index 2e5611c..1471b6b 100644
--- a/src/windows/service/exe/LxssUserSession.cpp
+++ b/src/windows/service/exe/LxssUserSession.cpp
@@ -2674,8 +2674,7 @@ try
THROW_IF_FAILED(shellLink->SetArguments(commandLine.c_str()));
THROW_IF_FAILED(shellLink->SetIconLocation(ShortcutIcon, 0));
- Microsoft::WRL::ComPtr storage;
- THROW_IF_FAILED(shellLink->QueryInterface(IID_IPersistFile, &storage));
+ auto storage = shellLink.query();
THROW_IF_FAILED(storage->Save(shortcutPath.c_str(), true));
registration.Write(Property::ShortcutPath, shortcutPath.c_str());
diff --git a/src/windows/service/exe/WslCoreVm.cpp b/src/windows/service/exe/WslCoreVm.cpp
index 9737a5a..b1907df 100644
--- a/src/windows/service/exe/WslCoreVm.cpp
+++ b/src/windows/service/exe/WslCoreVm.cpp
@@ -39,27 +39,18 @@ using namespace std::string_literals;
// Start of unaddressable memory if guest only supports the minimum 36-bit addressing.
#define MAX_36_BIT_PAGE_IN_MB (0x1000000000 / _1MB)
-// This device type is implemented by the external virtiofs vdev.
-// {872270E1-A899-4AF6-B454-7193634435AD}
-DEFINE_GUID(VIRTIO_VIRTIOFS_DEVICE_ID, 0x872270E1, 0xA899, 0x4AF6, 0xB4, 0x54, 0x71, 0x93, 0x63, 0x44, 0x35, 0xAD);
-
-// This device type is implemented by the external virtio-pmem vdev.
-// {EDBB24BB-5E19-40F4-8A0F-8224313064FD}
-DEFINE_GUID(VIRTIO_PMEM_DEVICE_ID, 0xEDBB24BB, 0x5E19, 0x40F4, 0x8A, 0x0F, 0x82, 0x24, 0x31, 0x30, 0x64, 0xFD);
-
-// Flags for virtiofs vdev device creation.
-#define VIRTIO_FS_FLAGS_TYPE_FILES 0x8000
-#define VIRTIO_FS_FLAGS_TYPE_SECTIONS 0x4000
-
#define WSLG_SHARED_MEMORY_SIZE_MB 8192
#define PAGE_SIZE 0x1000
+// WSL-specific virtio device class IDs.
+DEFINE_GUID(VIRTIO_FS_ADMIN_CLASS_ID, 0x7E6AD219, 0xD1B3, 0x42D5, 0xB8, 0xEE, 0xD9, 0x63, 0x24, 0xE6, 0x4F, 0xF6); // {7E6AD219-D1B3-42D5-B8EE-D96324E64FF6}
+DEFINE_GUID(VIRTIO_FS_CLASS_ID, 0x60285AE6, 0xAAF3, 0x4456, 0xB4, 0x44, 0xA6, 0xC2, 0xD0, 0xDE, 0xDA, 0x38); // {60285AE6-AAF3-4456-B444-A6C2D0DEDA38}
+DEFINE_GUID(VIRTIO_NET_CLASS_ID, 0x16479D2E, 0xF0C3, 0x4DBA, 0xBF, 0x7A, 0x04, 0xFF, 0xF0, 0x89, 0x2B, 0x07); // {16479D2E-F0C3-4DBA-BF7A-04FFF0892B07}
+DEFINE_GUID(VIRTIO_PMEM_CLASS_ID, 0xABB755FC, 0x1B86, 0x4255, 0x83, 0xE2, 0xE5, 0x78, 0x7A, 0xBC, 0xF6, 0xC2); // {ABB755FC-1B86-4255-83E2-E5787ABCF6C2}
+
static constexpr size_t c_bootEntropy = 0x1000;
static constexpr auto c_localDevicesKey = L"SOFTWARE\\Microsoft\\Terminal Server Client\\LocalDevices";
-// {ABB755FC-1B86-4255-83E2-E5787ABCF6C2}
-static constexpr GUID c_pmemClassId = {0xABB755FC, 0x1B86, 0x4255, {0x83, 0xe2, 0xe5, 0x78, 0x7a, 0xbc, 0xf6, 0xc2}};
-
#define LXSS_ENABLE_GUI_APPS() (m_vmConfig.EnableGuiApps && (m_systemDistroDeviceId != ULONG_MAX))
using namespace wsl::windows::common;
@@ -70,8 +61,6 @@ using wsl::shared::Localization;
using wsl::windows::common::Context;
using wsl::windows::common::ExecutionContext;
-const std::wstring WslCoreVm::c_defaultTag = L"default"s;
-
namespace {
INT64
RequiredExtraMmioSpaceForPmemFileInMb(_In_ PCWSTR FilePath)
@@ -335,7 +324,8 @@ void WslCoreVm::Initialize(const GUID& VmId, const wil::shared_handle& UserToken
m_runtimeId = wsl::windows::common::hcs::GetRuntimeId(m_system.get());
WI_ASSERT(IsEqualGUID(VmId, m_runtimeId));
- m_deviceHostSupport = wil::MakeOrThrow(m_machineId, m_runtimeId);
+ // Initialize the guest device manager.
+ m_guestDeviceManager = std::make_shared(m_machineId, m_runtimeId);
// Create a socket listening for connections from mini_init.
m_listenSocket = wsl::windows::common::hvsocket::Listen(m_runtimeId, LX_INIT_UTILITY_VM_INIT_PORT);
@@ -462,7 +452,7 @@ void WslCoreVm::Initialize(const GUID& VmId, const wil::shared_handle& UserToken
break;
case LxMiniInitMountDeviceTypePmem:
- m_systemDistroDeviceId = MountFileAsPersistentMemory(c_pmemClassId, m_vmConfig.SystemDistroPath.c_str(), true);
+ m_systemDistroDeviceId = MountFileAsPersistentMemory(m_vmConfig.SystemDistroPath.c_str(), true);
break;
default:
@@ -600,55 +590,8 @@ void WslCoreVm::Initialize(const GUID& VmId, const wil::shared_handle& UserToken
}
else if (m_vmConfig.NetworkingMode == NetworkingMode::VirtioProxy)
{
- auto virtioNetworkingEngine = std::make_unique(std::move(gnsChannel), m_vmConfig);
- virtioNetworkingEngine->OnAddGuestDevice([&](const GUID& Clsid, const GUID& DeviceId, PCWSTR Tag, PCWSTR Options) {
- auto guestDeviceLock = m_guestDeviceLock.lock_exclusive();
- return AddHdvShareWithOptions(DeviceId, Clsid, Tag, {}, Options, 0, m_userToken.get());
- });
-
- virtioNetworkingEngine->OnModifyOpenPorts([&](const GUID& Clsid, PCWSTR Tag, const SOCKADDR_INET& addr, int protocol, bool isOpen) {
- if (protocol != IPPROTO_TCP && protocol != IPPROTO_UDP)
- {
- LOG_HR_MSG(HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), "Unsupported bind protocol %d", protocol);
- return 0;
- }
- else if (addr.si_family == AF_INET6)
- {
- // The virtio net adapter does not yet support IPv6 packets, so any traffic would arrive via
- // IPv4. If the caller wants IPv4 they will also likely listen on an IPv4 address, which will
- // be handled as a separate callback to this same code.
- return 0;
- }
-
- auto guestDeviceLock = m_guestDeviceLock.lock_exclusive();
- const auto server = m_deviceHostSupport->GetRemoteFileSystem(Clsid, c_defaultTag);
- if (server)
- {
- std::wstring portString(L"tag=");
- portString += Tag;
- portString += L";port_number=";
- portString += std::to_wstring(addr.Ipv4.sin_port);
- if (protocol == IPPROTO_UDP)
- {
- portString += L";udp";
- }
- if (!isOpen)
- {
- portString += L";allocate=false";
- }
- else
- {
- std::wstring addrStr(L"000.000.000.000\0");
- RtlIpv4AddressToStringW(&addr.Ipv4.sin_addr, addrStr.data());
- portString += L";listen_addr=";
- portString += addrStr;
- }
- LOG_IF_FAILED(server->AddShare(portString.c_str(), nullptr, 0));
- }
- return 0;
- });
- virtioNetworkingEngine->OnGuestInterfaceStateChanged([&](const std::string& name, bool isUp) {});
- m_networkingEngine.reset(virtioNetworkingEngine.release());
+ m_networkingEngine = std::make_unique(
+ std::move(gnsChannel), m_vmConfig.EnableLocalhostRelay, m_guestDeviceManager, VIRTIO_NET_CLASS_ID, m_userToken);
}
else if (m_vmConfig.NetworkingMode == NetworkingMode::Bridged)
{
@@ -831,9 +774,9 @@ WslCoreVm::~WslCoreVm() noexcept
}
// Shutdown virtio device hosts.
- if (m_deviceHostSupport)
+ if (m_guestDeviceManager)
{
- m_deviceHostSupport->Shutdown();
+ m_guestDeviceManager->Shutdown();
}
// Call RevokeVmAccess on each VHD that was added to the utility VM. This
@@ -956,7 +899,7 @@ void WslCoreVm::AddPlan9Share(
if (m_vmConfig.EnableVirtio9p)
{
- server = m_deviceHostSupport->GetRemoteFileSystem(__uuidof(p9fs::Plan9FileSystem), VirtIoTag);
+ server = m_guestDeviceManager->GetRemoteFileSystem(__uuidof(p9fs::Plan9FileSystem), VirtIoTag);
}
else
{
@@ -969,10 +912,10 @@ void WslCoreVm::AddPlan9Share(
if (!server)
{
- server = CreateComServerAsUser(UserToken);
+ server = wsl::windows::common::wslutil::CreateComServerAsUser(UserToken);
if (m_vmConfig.EnableVirtio9p)
{
- m_deviceHostSupport->AddRemoteFileSystem(__uuidof(p9fs::Plan9FileSystem), VirtIoTag, server);
+ m_guestDeviceManager->AddRemoteFileSystem(__uuidof(p9fs::Plan9FileSystem), VirtIoTag, server);
// Start with one device to handle the first mount request. After
// each mount, the Plan9 file-system will request additional
@@ -1000,66 +943,10 @@ void WslCoreVm::AddPlan9Share(
if (addNewDevice)
{
// This requires more privileges than the user may have, so impersonation is disabled.
- (void)m_deviceHostSupport->AddNewDevice(VIRTIO_PLAN9_DEVICE_ID, server, VirtIoTag);
+ (void)m_guestDeviceManager->AddNewDevice(VIRTIO_PLAN9_DEVICE_ID, server, VirtIoTag);
}
}
-WslCoreVm::DirectoryObjectLifetime WslCoreVm::CreateSectionObjectRoot(_In_ std::wstring_view RelativeRootPath, _In_ HANDLE UserToken) const
-{
- auto revert = wil::impersonate_token(UserToken);
- DWORD sessionId;
- DWORD bytesWritten;
- THROW_LAST_ERROR_IF(!GetTokenInformation(GetCurrentThreadToken(), TokenSessionId, &sessionId, sizeof(sessionId), &bytesWritten));
-
- // /Sessions/1/BaseNamedObjects/WSL//
- std::wstringstream sectionPathBuilder;
- sectionPathBuilder << L"\\Sessions\\" << sessionId << L"\\BaseNamedObjects" << L"\\WSL\\" << m_machineId << L"\\" << RelativeRootPath;
- auto sectionPath = sectionPathBuilder.str();
-
- UNICODE_STRING ntPath{};
- OBJECT_ATTRIBUTES attributes{};
- attributes.Length = sizeof(OBJECT_ATTRIBUTES);
- attributes.ObjectName = &ntPath;
- std::vector directoryHierarchy;
- auto remainingPath = std::wstring_view(sectionPath.data(), sectionPath.length());
- while (remainingPath.length() > 0)
- {
- // Find the next path substring, ignoring the root path backslash.
- auto nextDir = remainingPath;
- const auto separatorPos = nextDir.find(L"\\", remainingPath[0] == L'\\' ? 1 : 0);
- if (separatorPos != std::wstring_view::npos)
- {
- nextDir = nextDir.substr(0, separatorPos);
- remainingPath = remainingPath.substr(separatorPos + 1, std::wstring_view::npos);
-
- // Skip concurrent backslashes.
- while (remainingPath.length() > 0 && remainingPath[0] == L'\\')
- {
- remainingPath = remainingPath.substr(1, std::wstring_view::npos);
- }
- }
- else
- {
- remainingPath = remainingPath.substr(remainingPath.length(), std::wstring_view::npos);
- }
-
- attributes.RootDirectory = directoryHierarchy.size() > 0 ? directoryHierarchy.back().get() : nullptr;
- ntPath.Buffer = const_cast(nextDir.data());
- ntPath.Length = sizeof(WCHAR) * gsl::narrow_cast(nextDir.length());
- ntPath.MaximumLength = ntPath.Length;
- wil::unique_handle nextHandle;
- NTSTATUS status = ZwCreateDirectoryObject(&nextHandle, DIRECTORY_ALL_ACCESS, &attributes);
- if (status == STATUS_OBJECT_NAME_COLLISION)
- {
- status = NtOpenDirectoryObject(&nextHandle, MAXIMUM_ALLOWED, &attributes);
- }
- THROW_IF_NTSTATUS_FAILED(status);
- directoryHierarchy.emplace_back(std::move(nextHandle));
- }
-
- return {std::move(sectionPath), std::move(directoryHierarchy)};
-}
-
ULONG WslCoreVm::AttachDisk(_In_ PCWSTR Disk, _In_ DiskType Type, _In_ std::optional Lun, _In_ bool IsUserDisk, _In_ HANDLE UserToken)
{
auto lock = m_lock.lock_exclusive();
@@ -1868,7 +1755,8 @@ void WslCoreVm::InitializeGuest()
{
try
{
- MountSharedMemoryDevice(c_virtiofsClassId, L"wslg", L"wslg", WSLG_SHARED_MEMORY_SIZE_MB);
+ m_guestDeviceManager->AddSharedMemoryDevice(
+ VIRTIO_FS_CLASS_ID, L"wslg", L"wslg", WSLG_SHARED_MEMORY_SIZE_MB, m_userToken.get());
m_sharedMemoryRoot = std::format(L"WSL\\{}\\wslg", m_machineId);
}
CATCH_LOG()
@@ -1967,7 +1855,7 @@ bool WslCoreVm::InitializeDrvFsLockHeld(_In_ HANDLE UserToken)
{
// Before checking whether DrvFs is already initialized, make sure any existing Plan 9 servers
// are usable.
- VerifyDrvFsServers();
+ VerifyPlan9Servers();
const auto elevated = wsl::windows::common::security::IsTokenElevated(UserToken);
if (elevated)
@@ -1999,6 +1887,12 @@ bool WslCoreVm::IsDnsTunnelingSupported() const
return SUCCEEDED_LOG(wsl::core::networking::DnsResolver::LoadDnsResolverMethods());
}
+bool WslCoreVm::IsVhdAttached(_In_ PCWSTR VhdPath)
+{
+ auto lock = m_lock.lock_exclusive();
+ return m_attachedDisks.contains({DiskType::VHD, VhdPath});
+}
+
WslCoreVm::DiskMountResult WslCoreVm::MountDisk(
_In_ PCWSTR Disk, _In_ DiskType MountDiskType, _In_ ULONG PartitionIndex, _In_opt_ PCWSTR Name, _In_opt_ PCWSTR Type, _In_opt_ PCWSTR Options)
{
@@ -2098,33 +1992,8 @@ void WslCoreVm::MountRootNamespaceFolder(_In_ LPCWSTR HostPath, _In_ LPCWSTR Gue
ResultMessage.Result);
}
-void WslCoreVm::MountSharedMemoryDevice(_In_ const GUID& ImplementationClsid, _In_ PCWSTR Tag, _In_ PCWSTR Path, _In_ UINT32 SizeMb)
-{
- if (!m_vmConfig.EnableVirtio)
- {
- return;
- }
-
- auto guestDeviceLock = m_guestDeviceLock.lock_exclusive();
- MountSharedMemoryDeviceLockHeld(ImplementationClsid, Tag, Path, SizeMb);
-}
-
-_Requires_lock_held_(m_guestDeviceLock)
-void WslCoreVm::MountSharedMemoryDeviceLockHeld(_In_ const GUID& ImplementationClsid, _In_ PCWSTR Tag, _In_ PCWSTR Path, _In_ UINT32 SizeMb)
-{
- auto objectLifetime = CreateSectionObjectRoot(Path, m_userToken.get());
-
- // For virtiofs hdv, the flags parameter has been overloaded. Flags are placed in the lower
- // 16 bits, while the shared memory size in megabytes are placed in the upper 16 bits.
- static constexpr auto VIRTIO_FS_FLAGS_SHMEM_SIZE_SHIFT = 16;
- UINT32 flags = (SizeMb << VIRTIO_FS_FLAGS_SHMEM_SIZE_SHIFT);
- WI_SetFlag(flags, VIRTIO_FS_FLAGS_TYPE_SECTIONS);
- (void)AddHdvShare(VIRTIO_VIRTIOFS_DEVICE_ID, ImplementationClsid, Tag, objectLifetime.Path.c_str(), flags, m_userToken.get());
- m_objectDirectories.emplace_back(std::move(objectLifetime));
-}
-
ULONG
-WslCoreVm::MountFileAsPersistentMemory(_In_ const GUID& ImplementationClsid, _In_ PCWSTR FilePath, _In_ bool ReadOnly)
+WslCoreVm::MountFileAsPersistentMemory(_In_ PCWSTR FilePath, _In_ bool ReadOnly)
{
hcs::Plan9ShareFlags flags{};
@@ -2146,7 +2015,7 @@ WslCoreVm::MountFileAsPersistentMemory(_In_ const GUID& ImplementationClsid, _In
// a symlink that points to a path like:
// /sys/devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0004:00/VMBUS:00//pcicceb:00//cceb:00:00.0/virtio1/ndbus0/region0/namespace0.0/block/pmem0
// Notice the GUID in the middle of that path. That GUID is the instance ID, which is randomly
- // generated by AddHdvShare. So once we find a path with the instance ID, we know that
+ // generated by AddGuestDevice. So once we find a path with the instance ID, we know that
// eventually /dev/pmemX will appear in the guest.
auto persistentMemoryLock = m_persistentMemoryLock.lock_exclusive();
@@ -2157,8 +2026,8 @@ WslCoreVm::MountFileAsPersistentMemory(_In_ const GUID& ImplementationClsid, _In
// added as part of VM creation and therefore any failure will result in VM termination
// (in which case there's no need to remove the device).
{
- auto guestDeviceLock = m_guestDeviceLock.lock_exclusive();
- (void)AddHdvShare(VIRTIO_PMEM_DEVICE_ID, ImplementationClsid, L"", FilePath, static_cast(flags), m_userToken.get());
+ (void)m_guestDeviceManager->AddGuestDevice(
+ VIRTIO_PMEM_DEVICE_ID, VIRTIO_PMEM_CLASS_ID, L"", nullptr, FilePath, static_cast(flags), m_userToken.get());
}
// Wait for the pmem device to appear in the VM at /dev/pmemX. Guess the value of X given the
@@ -2207,56 +2076,6 @@ void WslCoreVm::WaitForPmemDeviceInVm(_In_ ULONG PmemId)
}
}
-_Requires_lock_held_(m_guestDeviceLock)
-GUID WslCoreVm::AddHdvShareWithOptions(
- _In_ const GUID& DeviceId,
- _In_ const GUID& ImplementationClsid,
- _In_ std::wstring_view AccessName,
- _In_ std::wstring_view Options,
- _In_ std::wstring_view Path,
- _In_ UINT32 Flags,
- _In_ HANDLE UserToken)
-{
- wil::com_ptr server;
-
- THROW_HR_IF(E_NOTIMPL, !m_vmConfig.EnableVirtio);
-
- // Options are appended to the name with a semi-colon separator.
- // "name;key1=value1;key2=value2"
- // The AddSharePath implementation is responsible for separating them out and interpreting them.
- std::wstring nameWithOptions{AccessName};
- if (!Options.empty())
- {
- nameWithOptions += L";";
- nameWithOptions += Options;
- }
-
- {
- auto revert = wil::impersonate_token(UserToken);
-
- server = m_deviceHostSupport->GetRemoteFileSystem(ImplementationClsid, c_defaultTag);
- if (!server)
- {
- server = CreateComServerAsUser(ImplementationClsid, UserToken);
- m_deviceHostSupport->AddRemoteFileSystem(ImplementationClsid, c_defaultTag, server);
- }
-
- const std::wstring SharePath(Path);
- THROW_IF_FAILED(server->AddSharePath(nameWithOptions.c_str(), SharePath.c_str(), Flags));
- }
-
- // This requires more privileges than the user may have, so impersonation is disabled.
- const std::wstring VirtioTag(AccessName);
- return m_deviceHostSupport->AddNewDevice(DeviceId, server, VirtioTag.c_str());
-}
-
-_Requires_lock_held_(m_guestDeviceLock)
-GUID WslCoreVm::AddHdvShare(
- _In_ const GUID& DeviceId, _In_ const GUID& ImplementationClsid, _In_ PCWSTR AccessName, _In_ PCWSTR Path, _In_ UINT32 Flags, _In_ HANDLE UserToken)
-{
- return AddHdvShareWithOptions(DeviceId, ImplementationClsid, AccessName, {}, Path, Flags, UserToken);
-}
-
_Requires_lock_held_(m_guestDeviceLock)
std::wstring WslCoreVm::AddVirtioFsShare(_In_ bool Admin, _In_ PCWSTR Path, _In_ PCWSTR Options, _In_opt_ HANDLE UserToken)
{
@@ -2289,8 +2108,14 @@ std::wstring WslCoreVm::AddVirtioFsShare(_In_ bool Admin, _In_ PCWSTR Path, _In_
tag += std::to_wstring(m_virtioFsShares.size());
WI_ASSERT(!FindVirtioFsShare(tag.c_str(), Admin));
- (void)AddHdvShareWithOptions(
- VIRTIO_VIRTIOFS_DEVICE_ID, Admin ? c_virtiofsAdminClassId : c_virtiofsClassId, tag, key.OptionsString(), sharePath, VIRTIO_FS_FLAGS_TYPE_FILES, UserToken);
+ (void)m_guestDeviceManager->AddGuestDevice(
+ VIRTIO_FS_DEVICE_ID,
+ Admin ? VIRTIO_FS_ADMIN_CLASS_ID : VIRTIO_FS_CLASS_ID,
+ tag.c_str(),
+ key.OptionsString().c_str(),
+ sharePath.c_str(),
+ VIRTIO_FS_FLAGS_TYPE_FILES,
+ UserToken);
m_virtioFsShares.emplace(std::move(key), tag);
created = true;
@@ -2640,7 +2465,7 @@ std::pair WslCoreVm::UnmountVolume(_In_ const AttachedD
}
_Requires_lock_held_(m_guestDeviceLock)
-void WslCoreVm::VerifyDrvFsServers()
+void WslCoreVm::VerifyPlan9Servers()
{
for (auto it = m_plan9Servers.begin(); it != m_plan9Servers.end();)
{
@@ -2810,12 +2635,6 @@ LX_INIT_DRVFS_MOUNT WslCoreVm::s_InitializeDrvFs(_Inout_ WslCoreVm* VmContext, _
}
}
-bool WslCoreVm::IsVhdAttached(_In_ PCWSTR VhdPath)
-{
- auto lock = m_lock.lock_exclusive();
- return m_attachedDisks.contains({DiskType::VHD, VhdPath});
-}
-
void CALLBACK WslCoreVm::s_OnExit(_In_ HCS_EVENT* Event, _In_opt_ void* Context)
try
{
diff --git a/src/windows/service/exe/WslCoreVm.h b/src/windows/service/exe/WslCoreVm.h
index 17ed189..431bb6d 100644
--- a/src/windows/service/exe/WslCoreVm.h
+++ b/src/windows/service/exe/WslCoreVm.h
@@ -29,6 +29,7 @@ Abstract:
#include "INetworkingEngine.h"
#include "SocketChannel.h"
#include "DeviceHostProxy.h"
+#include "GuestDeviceManager.h"
#define UTILITY_VM_SHUTDOWN_TIMEOUT (30 * 1000)
#define UTILITY_VM_TERMINATE_TIMEOUT (30 * 1000)
@@ -39,11 +40,6 @@ inline constexpr auto c_optionsValueName = L"Options";
inline constexpr auto c_typeValueName = L"Type";
inline constexpr auto c_mountNameValueName = L"Name";
-static constexpr GUID c_virtiofsAdminClassId = {0x7e6ad219, 0xd1b3, 0x42d5, {0xb8, 0xee, 0xd9, 0x63, 0x24, 0xe6, 0x4f, 0xf6}};
-
-// {60285AE6-AAF3-4456-B444-A6C2D0DEDA38}
-static constexpr GUID c_virtiofsClassId = {0x60285ae6, 0xaaf3, 0x4456, {0xb4, 0x44, 0xa6, 0xc2, 0xd0, 0xde, 0xda, 0x38}};
-
namespace wrl = Microsoft::WRL;
///
@@ -114,10 +110,8 @@ public:
ReadOnly = 0x1
};
- void MountSharedMemoryDevice(_In_ const GUID& ImplementationClsid, _In_ PCWSTR Tag, _In_ PCWSTR Path, _In_ UINT32 SizeMb);
-
ULONG
- MountFileAsPersistentMemory(_In_ const GUID& ImplementationClsid, _In_ PCWSTR FilePath, _In_ bool ReadOnly);
+ MountFileAsPersistentMemory(_In_ PCWSTR FilePath, _In_ bool ReadOnly);
void MountRootNamespaceFolder(_In_ LPCWSTR HostPath, _In_ LPCWSTR GuestPath, _In_ bool ReadOnly, _In_ LPCWSTR Name);
@@ -129,7 +123,7 @@ public:
void SaveAttachedDisksState();
_Requires_lock_held_(m_guestDeviceLock)
- void VerifyDrvFsServers();
+ void VerifyPlan9Servers();
enum DiskStateFlags
{
@@ -166,14 +160,6 @@ private:
DiskStateFlags Flags;
};
- struct DirectoryObjectLifetime
- {
- std::wstring Path;
- // Directory objects are temporary, even if they have children, so need to keep
- // any created handles open in order for the directory to remain accessible.
- std::vector HierarchyLifetimes;
- };
-
struct VirtioFsShare
{
VirtioFsShare(PCWSTR Path, PCWSTR Options, bool Admin);
@@ -196,19 +182,6 @@ private:
_Requires_lock_held_(m_guestDeviceLock)
void AddPlan9Share(_In_ PCWSTR AccessName, _In_ PCWSTR Path, _In_ UINT32 Port, _In_ wsl::windows::common::hcs::Plan9ShareFlags Flags, _In_ HANDLE UserToken, _In_ PCWSTR VirtIoTag);
- _Requires_lock_held_(m_guestDeviceLock)
- GUID AddHdvShare(_In_ const GUID& DeviceId, _In_ const GUID& ImplementationClsid, _In_ PCWSTR AccessName, _In_opt_ PCWSTR Path, _In_ UINT32 Flags, _In_ HANDLE UserToken);
-
- _Requires_lock_held_(m_guestDeviceLock)
- GUID AddHdvShareWithOptions(
- _In_ const GUID& DeviceId,
- _In_ const GUID& ImplementationClsid,
- _In_ std::wstring_view AccessName,
- _In_ std::wstring_view Options,
- _In_ std::wstring_view Path,
- _In_ UINT32 Flags,
- _In_ HANDLE UserToken);
-
_Requires_lock_held_(m_guestDeviceLock)
std::wstring AddVirtioFsShare(_In_ bool Admin, _In_ PCWSTR Path, _In_ PCWSTR Options, _In_opt_ HANDLE UserToken = nullptr);
@@ -217,19 +190,6 @@ private:
void CollectCrashDumps(wil::unique_socket&& socket) const;
- template
- wil::com_ptr_t CreateComServerAsUser(_In_ REFCLSID RefClsId, _In_ HANDLE UserToken)
- {
- auto revert = wil::impersonate_token(UserToken);
- return wil::CoCreateInstance(RefClsId, (CLSCTX_LOCAL_SERVER | CLSCTX_ENABLE_CLOAKING | CLSCTX_ENABLE_AAA));
- }
-
- template
- wil::com_ptr_t CreateComServerAsUser(_In_ HANDLE UserToken)
- {
- return CreateComServerAsUser(__uuidof(Class), UserToken);
- }
-
std::shared_ptr CreateInstanceInternal(
_In_ const GUID& InstanceId,
_In_ const LXSS_DISTRO_CONFIGURATION& Configuration,
@@ -239,8 +199,6 @@ private:
_In_ bool LaunchSystemDistro = false,
_Out_opt_ ULONG* ConnectPort = nullptr);
- DirectoryObjectLifetime CreateSectionObjectRoot(_In_ std::wstring_view RelativeRootPath, _In_ HANDLE UserToken) const;
-
_Requires_lock_held_(m_lock)
void EjectVhdLockHeld(_In_ PCWSTR VhdPath);
@@ -269,9 +227,6 @@ private:
DiskMountResult MountDiskLockHeld(
_In_ PCWSTR Disk, _In_ DiskType MountDiskType, _In_ ULONG PartitionIndex, _In_opt_ PCWSTR Name, _In_opt_ PCWSTR Type, _In_opt_ PCWSTR Options);
- _Requires_lock_held_(m_guestDeviceLock)
- void MountSharedMemoryDeviceLockHeld(_In_ const GUID& ImplementationClsid, _In_ PCWSTR Tag, _In_ PCWSTR Path, _In_ UINT32 SizeMb);
-
void WaitForPmemDeviceInVm(_In_ ULONG PmemId);
void OnCrash(_In_ LPCWSTR Details);
@@ -302,12 +257,14 @@ private:
static void CALLBACK s_OnExit(_In_ HCS_EVENT* Event, _In_opt_ void* Context);
- wil::srwlock m_lock;
wil::srwlock m_guestDeviceLock;
+ std::shared_ptr m_guestDeviceManager;
_Guarded_by_(m_guestDeviceLock) std::future m_drvfsInitialResult;
_Guarded_by_(m_guestDeviceLock) wil::unique_handle m_drvfsToken;
_Guarded_by_(m_guestDeviceLock) wil::unique_handle m_adminDrvfsToken;
_Guarded_by_(m_guestDeviceLock) std::map m_virtioFsShares;
+ _Guarded_by_(m_guestDeviceLock) std::map> m_plan9Servers;
+ wil::srwlock m_lock;
_Guarded_by_(m_lock) wil::unique_event m_terminatingEvent { wil::EventOptions::ManualReset };
_Guarded_by_(m_lock) wil::unique_event m_vmExitEvent { wil::EventOptions::ManualReset };
wil::unique_event m_vmCrashEvent{wil::EventOptions::ManualReset};
@@ -339,12 +296,9 @@ private:
wsl::shared::SocketChannel m_miniInitChannel;
wil::unique_socket m_notifyChannel;
SE_SID m_userSid;
- Microsoft::WRL::ComPtr m_deviceHostSupport;
std::shared_ptr m_systemDistro;
_Guarded_by_(m_lock) std::bitset m_lunBitmap;
_Guarded_by_(m_lock) std::map m_attachedDisks;
- _Guarded_by_(m_guestDeviceLock) std::map> m_plan9Servers;
- _Guarded_by_(m_guestDeviceLock) std::vector m_objectDirectories;
std::tuple m_kernelVersion;
std::wstring m_kernelVersionString;
bool m_seccompAvailable;
@@ -363,8 +317,6 @@ private:
_Guarded_by_(m_persistentMemoryLock) ULONG m_nextPersistentMemoryId = 0;
std::unique_ptr m_networkingEngine;
-
- static const std::wstring c_defaultTag;
};
DEFINE_ENUM_FLAG_OPERATORS(WslCoreVm::DiskStateFlags);
diff --git a/src/windows/wslaservice/exe/ServiceProcessLauncher.h b/src/windows/wslaservice/exe/ServiceProcessLauncher.h
index e9b61e0..88b4b06 100644
--- a/src/windows/wslaservice/exe/ServiceProcessLauncher.h
+++ b/src/windows/wslaservice/exe/ServiceProcessLauncher.h
@@ -24,7 +24,7 @@ class ServiceRunningProcess : public common::RunningWSLAProcess
{
public:
NON_COPYABLE(ServiceRunningProcess);
- NON_MOVABLE(ServiceRunningProcess);
+ DEFAULT_MOVABLE(ServiceRunningProcess);
ServiceRunningProcess(const Microsoft::WRL::ComPtr& process, std::vector&& fds);
wil::unique_handle GetStdHandle(int Index) override;
diff --git a/src/windows/wslaservice/exe/WSLAContainer.cpp b/src/windows/wslaservice/exe/WSLAContainer.cpp
index 4e7a68b..f603d5f 100644
--- a/src/windows/wslaservice/exe/WSLAContainer.cpp
+++ b/src/windows/wslaservice/exe/WSLAContainer.cpp
@@ -18,6 +18,14 @@ Abstract:
using wsl::windows::service::wsla::WSLAContainer;
+constexpr const char* nerdctlPath = "/usr/bin/nerdctl";
+
+// Constants for required default arguments for "nerdctl run..."
+static std::vector defaultNerdctlRunArgs{//"--pull=never", // TODO: Uncomment once PullImage() is implemented.
+ "--net=host", // TODO: default for now, change later
+ "--ulimit",
+ "nofile=65536:65536"};
+
HRESULT WSLAContainer::Start()
{
return E_NOTIMPL;
@@ -38,10 +46,12 @@ HRESULT WSLAContainer::GetState(WSLA_CONTAINER_STATE* State)
return E_NOTIMPL;
}
-HRESULT WSLAContainer::GetInitProcess(IWSLAProcess** process)
+HRESULT WSLAContainer::GetInitProcess(IWSLAProcess** Process)
+try
{
- return E_NOTIMPL;
+ return m_containerProcess.Get().QueryInterface(__uuidof(IWSLAProcess), (void**)Process);
}
+CATCH_RETURN();
HRESULT WSLAContainer::Exec(const WSLA_PROCESS_OPTIONS* Options, IWSLAProcess** Process, int* Errno)
try
@@ -53,3 +63,101 @@ try
return S_OK;
}
CATCH_RETURN();
+
+Microsoft::WRL::ComPtr WSLAContainer::Create(const WSLA_CONTAINER_OPTIONS& containerOptions, WSLAVirtualMachine& parentVM)
+{
+ // TODO: Switch to nerdctl create, and call nerdctl start in Start().
+
+ bool hasStdin = false;
+ bool hasTty = false;
+ for (size_t i = 0; i < containerOptions.InitProcessOptions.FdsCount; i++)
+ {
+ if (containerOptions.InitProcessOptions.Fds[i].Fd == 0)
+ {
+ hasStdin = true;
+ }
+
+ if (containerOptions.InitProcessOptions.Fds[i].Type == WSLAFdTypeTerminalInput ||
+ containerOptions.InitProcessOptions.Fds[i].Type == WSLAFdTypeTerminalOutput)
+ {
+ hasTty = true;
+ }
+ }
+
+ std::vector inputOptions;
+ if (hasStdin)
+ {
+ inputOptions.push_back("-i");
+ }
+
+ if (hasTty)
+ {
+ inputOptions.push_back("-t");
+ }
+
+ auto args = PrepareNerdctlRunCommand(containerOptions, std::move(inputOptions));
+
+ ServiceProcessLauncher launcher(nerdctlPath, args, {}, common::ProcessFlags::None);
+ for (size_t i = 0; i < containerOptions.InitProcessOptions.FdsCount; i++)
+ {
+ launcher.AddFd(containerOptions.InitProcessOptions.Fds[i]);
+ }
+
+ return wil::MakeOrThrow(&parentVM, launcher.Launch(parentVM));
+}
+
+std::vector WSLAContainer::PrepareNerdctlRunCommand(const WSLA_CONTAINER_OPTIONS& options, std::vector&& inputOptions)
+{
+ std::vector args{nerdctlPath};
+ args.push_back("run");
+ args.push_back("--name");
+ args.push_back(options.Name);
+ if (options.ShmSize > 0)
+ {
+ args.push_back(std::format("--shm-size={}m", options.ShmSize));
+ }
+ if (options.Flags & WSLA_CONTAINER_FLAG_ENABLE_GPU)
+ {
+ args.push_back("--gpus");
+ // TODO: Parse GPU device list from WSLA_CONTAINER_OPTIONS. For now, just enable all GPUs.
+ args.push_back("all");
+ }
+
+ args.insert(args.end(), defaultNerdctlRunArgs.begin(), defaultNerdctlRunArgs.end());
+ args.insert(args.end(), inputOptions.begin(), inputOptions.end());
+
+ for (ULONG i = 0; i < options.InitProcessOptions.EnvironmentCount; i++)
+ {
+ THROW_HR_IF_MSG(
+ E_INVALIDARG,
+ options.InitProcessOptions.Environment[i][0] == L'-',
+ "Invalid environment string: %hs",
+ options.InitProcessOptions.Environment[i]);
+
+ args.insert(args.end(), {"-e", options.InitProcessOptions.Environment[i]});
+ }
+
+ if (options.InitProcessOptions.Executable != nullptr)
+ {
+ args.push_back("--entrypoint");
+ args.push_back(options.InitProcessOptions.Executable);
+ }
+
+ // TODO:
+ // - Implement volume mounts
+ // - Implement port mapping
+
+ args.push_back(options.Image);
+
+ if (options.InitProcessOptions.CommandLineCount > 0)
+ {
+ args.push_back("--");
+
+ for (ULONG i = 0; i < options.InitProcessOptions.CommandLineCount; i++)
+ {
+ args.push_back(options.InitProcessOptions.CommandLine[i]);
+ }
+ }
+
+ return args;
+}
\ No newline at end of file
diff --git a/src/windows/wslaservice/exe/WSLAContainer.h b/src/windows/wslaservice/exe/WSLAContainer.h
index f9bed4c..d84eaac 100644
--- a/src/windows/wslaservice/exe/WSLAContainer.h
+++ b/src/windows/wslaservice/exe/WSLAContainer.h
@@ -14,7 +14,9 @@ Abstract:
#pragma once
+#include "ServiceProcessLauncher.h"
#include "wslaservice.h"
+#include "WSLAVirtualMachine.h"
namespace wsl::windows::service::wsla {
@@ -23,6 +25,10 @@ class DECLSPEC_UUID("B1F1C4E3-C225-4CAE-AD8A-34C004DE1AE4") WSLAContainer
{
public:
WSLAContainer() = default; // TODO
+ WSLAContainer(WSLAVirtualMachine* parentVM, ServiceRunningProcess&& containerProcess) :
+ m_parentVM(parentVM), m_containerProcess(std::move(containerProcess))
+ {
+ }
WSLAContainer(const WSLAContainer&) = delete;
WSLAContainer& operator=(const WSLAContainer&) = delete;
@@ -33,6 +39,12 @@ public:
IFACEMETHOD(GetInitProcess)(_Out_ IWSLAProcess** process) override;
IFACEMETHOD(Exec)(_In_ const WSLA_PROCESS_OPTIONS* Options, _Out_ IWSLAProcess** Process, _Out_ int* Errno) override;
+ static Microsoft::WRL::ComPtr Create(const WSLA_CONTAINER_OPTIONS& Options, WSLAVirtualMachine& parentVM);
+
private:
+ ServiceRunningProcess m_containerProcess;
+ WSLAVirtualMachine* m_parentVM = nullptr;
+
+ static std::vector