Full Code of M2Team/NanaRun for AI

main dfa9cccf850a cached
41 files
172.8 KB
42.4k tokens
53 symbols
1 requests
Download .txt
Repository: M2Team/NanaRun
Branch: main
Commit: dfa9cccf850a
Files: 41
Total size: 172.8 KB

Directory structure:
gitextract_8fdsknjd/

├── .editorconfig
├── .github/
│   ├── FUNDING.yml
│   └── workflows/
│       └── BuildBinaries.yml
├── .gitignore
├── BuildAllTargets.cmd
├── BuildAllTargets.proj
├── BuildInstallers.cmd
├── Directory.Build.props
├── Documents/
│   ├── People.md
│   ├── ReleaseNotes.md
│   ├── ReleaseNotesPreview.md
│   └── Versioning.md
├── License.md
├── MinSudo/
│   ├── MinSudo.cpp
│   ├── MinSudo.manifest
│   ├── MinSudo.rc
│   ├── MinSudo.vcxproj
│   ├── MinSudo.vcxproj.filters
│   ├── Resources/
│   │   ├── en/
│   │   │   └── Translations.md
│   │   └── zh-Hans/
│   │       └── Translations.md
│   └── resource.h
├── NanaRun/
│   ├── NanaRun.cpp
│   ├── NanaRun.manifest
│   ├── NanaRun.vcxproj
│   └── NanaRun.vcxproj.filters
├── NanaRun.IconResource/
│   ├── NanaRun.IconResource.h
│   ├── NanaRun.IconResource.props
│   └── NanaRun.IconResource.rc
├── NanaRun.slnx
├── ReadMe.md
├── SynthRdp/
│   ├── AutoRun.inf
│   ├── SynthRdp.cpp
│   ├── SynthRdp.iss
│   ├── SynthRdp.manifest
│   └── SynthRdp.vcxproj
├── Tools/
│   ├── Default.isl
│   ├── Setup.e32
│   └── SetupLdr.e32
└── VirtualSmb/
    ├── VirtualSmb.cpp
    ├── VirtualSmb.manifest
    └── VirtualSmb.vcxproj

================================================
FILE CONTENTS
================================================

================================================
FILE: .editorconfig
================================================
## 
## PROJECT:    Mouri Internal Library Essentials
## FILE:       .editorconfig
## PURPOSE:    The root .editorconfig file
## 
## LICENSE:    The MIT License
## 
## MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)
## 

root = true

[*]
charset = utf-8-bom
end_of_line = crlf

[*.md]
insert_final_newline = true

[*.{c,c++,cc,cpp,cxx,h,h++,hh,hpp,hxx,ixx,cppm,ipp,odl,idl,inl,ipp,tlh,tli}]
indent_style = space
indent_size = 4
insert_final_newline = true
trim_trailing_whitespace = true
vc_generate_documentation_comments = doxygen_slash_star

[*.{cs,csx,vb,vbx,asmx}]
indent_style = space
indent_size = 4
insert_final_newline = true
trim_trailing_whitespace = true

[*.{js,json,xml,toml,xaml}]
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true

[*.rc]
charset = utf-16le

[*.inf]
charset = utf-16le

[*.bat]
charset = utf-8
insert_final_newline = true

[*.sh]
charset = utf-8
end_of_line = lf
insert_final_newline = true

[*.{asm,inc,s,nasm}]
charset = utf-8
indent_style = space
indent_size = 4
insert_final_newline = true
trim_trailing_whitespace = true


================================================
FILE: .github/FUNDING.yml
================================================
patreon: MouriNaruto
custom: [
  "https://paypal.me/MouriNaruto",
  "https://afdian.net/a/MouriNaruto",
  "https://github.com/MouriNaruto/MouriNaruto/tree/main/Sponsor#alipay",
  "https://github.com/MouriNaruto/MouriNaruto/tree/main/Sponsor#wechat"
]


================================================
FILE: .github/workflows/BuildBinaries.yml
================================================
name: Build Binaries

on:
  push:
    paths-ignore:
      - '.github/*'
      - '*.md'
  pull_request:
    paths-ignore:
      - '.github/*'
      - '*.md'

jobs:
  build:
    runs-on: windows-latest
    env:
      POWERSHELL_TELEMETRY_OPTOUT: 1
    steps:
    - uses: actions/checkout@v4
      with:
        submodules: 'recursive'
    - uses: microsoft/setup-msbuild@v2
    - name: Clear local NuGet cache (workaround for failed restores on windows-latest)
      run: dotnet nuget locals all --clear
    - name: Build
      run: msbuild -m BuildAllTargets.proj
    - name: Prepare artifacts
      run: rm Output\Binaries\* -vb -Recurse -Force -Include *.exp, *.idb, *.ilk, *.iobj, *.ipdb, *.lastbuildstate, *.lib, *.obj, *.res, *.tlog
    - uses: actions/upload-artifact@v4
      with:
        name: NanaRun_CI_Build
        path: Output\Binaries


================================================
FILE: .gitignore
================================================
## 
## PROJECT:    Mouri Internal Library Essentials
## FILE:       .gitignore
## PURPOSE:    The root .gitignore file for Visual Studio C++ Project
## 
## LICENSE:    The MIT License
## 
## MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)
## 

##
## Ignore Mile.Project specific temporary files, build results,
## and files generated by popular Visual Studio add-ons.
## 
Output/

##
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##

# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates

# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs

# Mono auto generated files
mono_crash.*

# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
[Ll]ogs/

# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/

# Visual Studio 2017 auto generated files
Generated\ Files/

# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*

# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml

# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c

# Benchmark Results
BenchmarkDotNet.Artifacts/

# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/

# ASP.NET Scaffolding
ScaffoldingReadMe.txt

# StyleCop
StyleCopReport.xml

# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.tlog
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc

# Chutzpah Test files
_Chutzpah*

# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb

# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap

# Visual Studio Trace Files
*.e2e

# TFS 2012 Local Workspace
$tf/

# Guidance Automation Toolkit
*.gpState

# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user

# TeamCity is a build add-in
_TeamCity*

# DotCover is a Code Coverage Tool
*.dotCover

# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json

# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info

# Visual Studio code coverage results
*.coverage
*.coveragexml

# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*

# MightyMoose
*.mm.*
AutoTest.Net/

# Web workbench (sass)
.sass-cache/

# Installshield output folder
[Ee]xpress/

# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html

# Click-Once directory
publish/

# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj

# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/

# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets

# Microsoft Azure Build Output
csx/
*.build.csdef

# Microsoft Azure Emulator
ecf/
rcf/

# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload

# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/

# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs

# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk

# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/

# RIA/Silverlight projects
Generated_Code/

# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak

# SQL Server files
*.mdf
*.ldf
*.ndf

# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl

# Microsoft Fakes
FakesAssemblies/

# GhostDoc plugin setting file
*.GhostDoc.xml

# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/

# Visual Studio 6 build log
*.plg

# Visual Studio 6 workspace options file
*.opt

# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw

# Visual Studio 6 auto-generated project file (contains which files were open etc.)
*.vbp

# Visual Studio 6 workspace and project file (working project files containing files to include in project)
*.dsw
*.dsp

# Visual Studio 6 technical files
*.ncb
*.aps

# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions

# Paket dependency manager
.paket/paket.exe
paket-files/

# FAKE - F# Make
.fake/

# CodeRush personal settings
.cr/personal

# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc

# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config

# Tabs Studio
*.tss

# Telerik's JustMock configuration file
*.jmconfig

# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs

# OpenCover UI analysis results
OpenCover/

# Azure Stream Analytics local run output
ASALocalRun/

# MSBuild Binary and Structured Log
*.binlog

# NVidia Nsight GPU debugger configuration file
*.nvuser

# MFractors (Xamarin productivity tool) working folder
.mfractor/

# Local History for Visual Studio
.localhistory/

# Visual Studio History (VSHistory) files
.vshistory/

# BeatPulse healthcheck temp database
healthchecksdb

# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/

# Ionide (cross platform F# VS Code tools) working folder
.ionide/

# Fody - auto-generated XML schema
FodyWeavers.xsd

# VS Code files for those working on multiple tools
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
*.code-workspace

# Local History for Visual Studio Code
.history/

# Windows Installer files from build outputs
*.cab
*.msi
*.msix
*.msm
*.msp

# JetBrains Rider
*.sln.iml


================================================
FILE: BuildAllTargets.cmd
================================================
@setlocal
@echo off

rem Change to the current folder.
cd "%~dp0"

rem Remove the output folder for a fresh compile.
rd /s /q Output

rem Initialize Visual Studio environment
set VisualStudioInstallerFolder="%ProgramFiles(x86)%\Microsoft Visual Studio\Installer"
if %PROCESSOR_ARCHITECTURE%==x86 set VisualStudioInstallerFolder="%ProgramFiles%\Microsoft Visual Studio\Installer"
pushd %VisualStudioInstallerFolder%
for /f "usebackq tokens=*" %%i in (`vswhere -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath`) do (
  set VisualStudioInstallDir=%%i
)
popd
call "%VisualStudioInstallDir%\VC\Auxiliary\Build\vcvarsall.bat" x86

rem Build all targets
MSBuild -binaryLogger:Output\BuildAllTargets.binlog -m BuildAllTargets.proj

@endlocal

================================================
FILE: BuildAllTargets.proj
================================================
<?xml version="1.0" encoding="utf-8"?>
<Project 
  DefaultTargets="Restore;Build"
  xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <SolutionPath>$(MSBuildThisFileDirectory)NanaRun.slnx</SolutionPath>
  </PropertyGroup>
  <ItemGroup>
    <ProjectReference Include="$(SolutionPath)">
      <AdditionalProperties>Configuration=Debug;Platform=x86</AdditionalProperties>   
    </ProjectReference>
    <ProjectReference Include="$(SolutionPath)">
      <AdditionalProperties>Configuration=Release;Platform=x86</AdditionalProperties>   
    </ProjectReference>
    <ProjectReference Include="$(SolutionPath)">
      <AdditionalProperties>Configuration=Debug;Platform=x64</AdditionalProperties>   
    </ProjectReference>
    <ProjectReference Include="$(SolutionPath)">
      <AdditionalProperties>Configuration=Release;Platform=x64</AdditionalProperties>   
    </ProjectReference>
    <ProjectReference Include="$(SolutionPath)">
      <AdditionalProperties>Configuration=Debug;Platform=ARM64</AdditionalProperties>   
    </ProjectReference>
    <ProjectReference Include="$(SolutionPath)">
      <AdditionalProperties>Configuration=Release;Platform=ARM64</AdditionalProperties>   
    </ProjectReference>
  </ItemGroup>
  <Target Name="Restore">
    <MSBuild
      Projects="@(ProjectReference)"
      Targets="Restore"
      StopOnFirstFailure="True"
      Properties="PreferredToolArchitecture=x64" />
  </Target>
  <Target Name="Build">
    <MSBuild
      Projects="@(ProjectReference)"
      Targets="Build"
      BuildInParallel="True"
      StopOnFirstFailure="True"
      Properties="PreferredToolArchitecture=x64" />
  </Target>
</Project>

================================================
FILE: BuildInstallers.cmd
================================================
@setlocal
@echo off

rem Change to the current folder.
cd "%~dp0"

rem Remove the SynthRdp installation image output folder for a fresh compile.
rd /s /q Output\SynthRdpInstallationImage

rem Generate SynthRdp installer
Tools\ISCC.exe SynthRdp\SynthRdp.iss

rem Copy SynthRdp AutoRun.inf
copy SynthRdp\AutoRun.inf Output\SynthRdpInstallationImage

rem Generate SynthRdp installation image
Tools\oscdimg.exe -u1 -udfver102 -lSynthRdp Output\SynthRdpInstallationImage Output\SynthRdp.iso

@endlocal

================================================
FILE: Directory.Build.props
================================================
<?xml version="1.0" encoding="utf-8"?>
<Project>
  <PropertyGroup>
    <MileProjectOutputPath>$(MSBuildThisFileDirectory)Output\</MileProjectOutputPath>
  </PropertyGroup>
  <Import Sdk="Mile.Project.Configurations" Version="1.0.1917" Project="Mile.Project.Build.props" />
</Project>

================================================
FILE: Documents/People.md
================================================
# Relevant People

## Notice

- This list sort in alphabetical order.

## Development Team

- Kenji Mouri ([https://github.com/MouriNaruto](https://github.com/MouriNaruto))

## Logo Designers

- Shomnipotence ([https://github.com/Shomnipotence](https://github.com/Shomnipotence))

## Special thanks

- mingkuang ([https://github.com/mingkuang-Chuyu](https://github.com/mingkuang-Chuyu))


================================================
FILE: Documents/ReleaseNotes.md
================================================
# NanaRun Release Notes

For preview versions, please read 
[NanaRun Preview Release Notes](ReleaseNotesPreview.md).


================================================
FILE: Documents/ReleaseNotesPreview.md
================================================
# NanaRun Preview Release Notes

For stable versions, please read [NanaRun Release Notes](ReleaseNotes.md).

**NanaRun 1.0 Preview 3 (1.0.92.0)**

- Introduce the SynthRdp tool.
- Add short form command line options support for MinSudo. (Suggested by
  he3als.)
- Update icon assets. (Designed by Shomnipotence.)
- Adjust several implementations.

**NanaRun 1.0 Preview 2 (1.0.18.0)**

- Remove standard handle settings because child process will inherit the 
  parent's console for MinSudo.
- Update application icon. (Designed by Shomnipotence.)
- Make sure ignores CTRL+C signals for MinSudo itself to solve unexcepted
  behaviors.
- Fix current directory issue when put MinSudo into System32 folder. (Thanks to
  Slemoon.)
- Add System and TrustedInstaller mode for MinSudo.
- Add enable all privileges mode support for MinSudo.

**NanaRun 1.0 Preview 1 (1.0.5.0)**

- Implement MinSudo.


================================================
FILE: Documents/Versioning.md
================================================
# NanaRun Versioning

This document applies to all versions of NanaRun.

## Version Format

- Simple Version: `<Major>.<Minor> <Tag>`
  - Example: `9.0 Preview 1`
- Binary Version: `<Major>.<Minor>.<Build>.<Revision>`
  - Example: `9.0.2654.0`

## The rule for build and revision number

The build number is the number of days since May 1, 2024 because that day is the
10th anniversary of the first version of NSudo is created and published.

~~The build number is the number of days since May 16, 2022 because the first
version of NanaRun is created and published on that day.~~

The revision number is the number of releases releases in the day corresponding
to the build number, and it counts from zero. So the first revision is 0 and 
the second revision is 1.


================================================
FILE: License.md
================================================
# NanaRun License

For giving the maximum respect for the upstream projects and following the 
philosophy about open-source software from Kenji Mouri (MouriNaruto), the one
of the M2-Team founders. 

The source code of NanaRun (not including the source code from third-party 
libraries) is distributed under the MIT License.

The application file association icons of NanaRun (these contents are only in 
the `Assets` folder) are designed by Shomnipotence and authorized to the 
NanaRun project, and it is distributed under the CC BY-ND 4.0 License.

The source code from the third-party libraries is distributed under the original
license used in the third-party libraries.

This permission notice shall be included in all copies or substantial portions
of the Software.

### The philosophy about open-source software from Kenji Mouri (MouriNaruto)

- The source code from the third-party projects should be distributed under 
  their original licenses to give the maximum respect for the upstream 
  projects.

- Don't make your software open source if you don't want your source code or
  ideas used in proprietary software. Because they always have the way to cross
  restrictions if they really want to do, even you distributed your source code
  under the strictest copyleft license, they can use clean room to resolve it.

- I prefer permissive licenses because using copyleft licenses will make you
  feel anxious in most cases because you always need to worry about someone
  using your source code in proprietary software. So, I choose to give the
  maximum respect to users, and I also hope people can try their best to treat
  others kindly.

### The MIT License

```
The MIT License (MIT)

Copyright (c) M2-Team 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.
```

### The CC BY-ND 4.0 License

```
Copyright (c) Shomnipotence and M2-Team. All rights reserved.

This work is licensed under a Creative Commons Attribution-NoDerivatives 4.0
International License.

Attribution-NoDerivatives 4.0 International

=======================================================================

Creative Commons Corporation ("Creative Commons") is not a law firm and
does not provide legal services or legal advice. Distribution of
Creative Commons public licenses does not create a lawyer-client or
other relationship. Creative Commons makes its licenses and related
information available on an "as-is" basis. Creative Commons gives no
warranties regarding its licenses, any material licensed under their
terms and conditions, or any related information. Creative Commons
disclaims all liability for damages resulting from their use to the
fullest extent possible.

Using Creative Commons Public Licenses

Creative Commons public licenses provide a standard set of terms and
conditions that creators and other rights holders may use to share
original works of authorship and other material subject to copyright
and certain other rights specified in the public license below. The
following considerations are for informational purposes only, are not
exhaustive, and do not form part of our licenses.

     Considerations for licensors: Our public licenses are
     intended for use by those authorized to give the public
     permission to use material in ways otherwise restricted by
     copyright and certain other rights. Our licenses are
     irrevocable. Licensors should read and understand the terms
     and conditions of the license they choose before applying it.
     Licensors should also secure all rights necessary before
     applying our licenses so that the public can reuse the
     material as expected. Licensors should clearly mark any
     material not subject to the license. This includes other CC-
     licensed material, or material used under an exception or
     limitation to copyright. More considerations for licensors:
    wiki.creativecommons.org/Considerations_for_licensors

     Considerations for the public: By using one of our public
     licenses, a licensor grants the public permission to use the
     licensed material under specified terms and conditions. If
     the licensor's permission is not necessary for any reason--for
     example, because of any applicable exception or limitation to
     copyright--then that use is not regulated by the license. Our
     licenses grant only permissions under copyright and certain
     other rights that a licensor has authority to grant. Use of
     the licensed material may still be restricted for other
     reasons, including because others have copyright or other
     rights in the material. A licensor may make special requests,
     such as asking that all changes be marked or described.
     Although not required by our licenses, you are encouraged to
     respect those requests where reasonable. More considerations
     for the public:
    wiki.creativecommons.org/Considerations_for_licensees


=======================================================================

Creative Commons Attribution-NoDerivatives 4.0 International Public
License

By exercising the Licensed Rights (defined below), You accept and agree
to be bound by the terms and conditions of this Creative Commons
Attribution-NoDerivatives 4.0 International Public License ("Public
License"). To the extent this Public License may be interpreted as a
contract, You are granted the Licensed Rights in consideration of Your
acceptance of these terms and conditions, and the Licensor grants You
such rights in consideration of benefits the Licensor receives from
making the Licensed Material available under these terms and
conditions.


Section 1 -- Definitions.

  a. Adapted Material means material subject to Copyright and Similar
     Rights that is derived from or based upon the Licensed Material
     and in which the Licensed Material is translated, altered,
     arranged, transformed, or otherwise modified in a manner requiring
     permission under the Copyright and Similar Rights held by the
     Licensor. For purposes of this Public License, where the Licensed
     Material is a musical work, performance, or sound recording,
     Adapted Material is always produced where the Licensed Material is
     synched in timed relation with a moving image.

  b. Copyright and Similar Rights means copyright and/or similar rights
     closely related to copyright including, without limitation,
     performance, broadcast, sound recording, and Sui Generis Database
     Rights, without regard to how the rights are labeled or
     categorized. For purposes of this Public License, the rights
     specified in Section 2(b)(1)-(2) are not Copyright and Similar
     Rights.

  c. Effective Technological Measures means those measures that, in the
     absence of proper authority, may not be circumvented under laws
     fulfilling obligations under Article 11 of the WIPO Copyright
     Treaty adopted on December 20, 1996, and/or similar international
     agreements.

  d. Exceptions and Limitations means fair use, fair dealing, and/or
     any other exception or limitation to Copyright and Similar Rights
     that applies to Your use of the Licensed Material.

  e. Licensed Material means the artistic or literary work, database,
     or other material to which the Licensor applied this Public
     License.

  f. Licensed Rights means the rights granted to You subject to the
     terms and conditions of this Public License, which are limited to
     all Copyright and Similar Rights that apply to Your use of the
     Licensed Material and that the Licensor has authority to license.

  g. Licensor means the individual(s) or entity(ies) granting rights
     under this Public License.

  h. Share means to provide material to the public by any means or
     process that requires permission under the Licensed Rights, such
     as reproduction, public display, public performance, distribution,
     dissemination, communication, or importation, and to make material
     available to the public including in ways that members of the
     public may access the material from a place and at a time
     individually chosen by them.

  i. Sui Generis Database Rights means rights other than copyright
     resulting from Directive 96/9/EC of the European Parliament and of
     the Council of 11 March 1996 on the legal protection of databases,
     as amended and/or succeeded, as well as other essentially
     equivalent rights anywhere in the world.

  j. You means the individual or entity exercising the Licensed Rights
     under this Public License. Your has a corresponding meaning.


Section 2 -- Scope.

  a. License grant.

       1. Subject to the terms and conditions of this Public License,
          the Licensor hereby grants You a worldwide, royalty-free,
          non-sublicensable, non-exclusive, irrevocable license to
          exercise the Licensed Rights in the Licensed Material to:

            a. reproduce and Share the Licensed Material, in whole or
               in part; and

            b. produce and reproduce, but not Share, Adapted Material.

       2. Exceptions and Limitations. For the avoidance of doubt, where
          Exceptions and Limitations apply to Your use, this Public
          License does not apply, and You do not need to comply with
          its terms and conditions.

       3. Term. The term of this Public License is specified in Section
          6(a).

       4. Media and formats; technical modifications allowed. The
          Licensor authorizes You to exercise the Licensed Rights in
          all media and formats whether now known or hereafter created,
          and to make technical modifications necessary to do so. The
          Licensor waives and/or agrees not to assert any right or
          authority to forbid You from making technical modifications
          necessary to exercise the Licensed Rights, including
          technical modifications necessary to circumvent Effective
          Technological Measures. For purposes of this Public License,
          simply making modifications authorized by this Section 2(a)
          (4) never produces Adapted Material.

       5. Downstream recipients.

            a. Offer from the Licensor -- Licensed Material. Every
               recipient of the Licensed Material automatically
               receives an offer from the Licensor to exercise the
               Licensed Rights under the terms and conditions of this
               Public License.

            b. No downstream restrictions. You may not offer or impose
               any additional or different terms or conditions on, or
               apply any Effective Technological Measures to, the
               Licensed Material if doing so restricts exercise of the
               Licensed Rights by any recipient of the Licensed
               Material.

       6. No endorsement. Nothing in this Public License constitutes or
          may be construed as permission to assert or imply that You
          are, or that Your use of the Licensed Material is, connected
          with, or sponsored, endorsed, or granted official status by,
          the Licensor or others designated to receive attribution as
          provided in Section 3(a)(1)(A)(i).

  b. Other rights.

       1. Moral rights, such as the right of integrity, are not
          licensed under this Public License, nor are publicity,
          privacy, and/or other similar personality rights; however, to
          the extent possible, the Licensor waives and/or agrees not to
          assert any such rights held by the Licensor to the limited
          extent necessary to allow You to exercise the Licensed
          Rights, but not otherwise.

       2. Patent and trademark rights are not licensed under this
          Public License.

       3. To the extent possible, the Licensor waives any right to
          collect royalties from You for the exercise of the Licensed
          Rights, whether directly or through a collecting society
          under any voluntary or waivable statutory or compulsory
          licensing scheme. In all other cases the Licensor expressly
          reserves any right to collect such royalties.


Section 3 -- License Conditions.

Your exercise of the Licensed Rights is expressly made subject to the
following conditions.

  a. Attribution.

       1. If You Share the Licensed Material, You must:

            a. retain the following if it is supplied by the Licensor
               with the Licensed Material:

                 i. identification of the creator(s) of the Licensed
                    Material and any others designated to receive
                    attribution, in any reasonable manner requested by
                    the Licensor (including by pseudonym if
                    designated);

                ii. a copyright notice;

               iii. a notice that refers to this Public License;

                iv. a notice that refers to the disclaimer of
                    warranties;

                 v. a URI or hyperlink to the Licensed Material to the
                    extent reasonably practicable;

            b. indicate if You modified the Licensed Material and
               retain an indication of any previous modifications; and

            c. indicate the Licensed Material is licensed under this
               Public License, and include the text of, or the URI or
               hyperlink to, this Public License.

          For the avoidance of doubt, You do not have permission under
          this Public License to Share Adapted Material.

       2. You may satisfy the conditions in Section 3(a)(1) in any
          reasonable manner based on the medium, means, and context in
          which You Share the Licensed Material. For example, it may be
          reasonable to satisfy the conditions by providing a URI or
          hyperlink to a resource that includes the required
          information.

       3. If requested by the Licensor, You must remove any of the
          information required by Section 3(a)(1)(A) to the extent
          reasonably practicable.


Section 4 -- Sui Generis Database Rights.

Where the Licensed Rights include Sui Generis Database Rights that
apply to Your use of the Licensed Material:

  a. for the avoidance of doubt, Section 2(a)(1) grants You the right
     to extract, reuse, reproduce, and Share all or a substantial
     portion of the contents of the database, provided You do not Share
     Adapted Material;
  b. if You include all or a substantial portion of the database
     contents in a database in which You have Sui Generis Database
     Rights, then the database in which You have Sui Generis Database
     Rights (but not its individual contents) is Adapted Material; and
  c. You must comply with the conditions in Section 3(a) if You Share
     all or a substantial portion of the contents of the database.

For the avoidance of doubt, this Section 4 supplements and does not
replace Your obligations under this Public License where the Licensed
Rights include other Copyright and Similar Rights.


Section 5 -- Disclaimer of Warranties and Limitation of Liability.

  a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
     EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
     AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
     ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
     IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
     WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
     PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
     ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
     KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
     ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.

  b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
     TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
     NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
     INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
     COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
     USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
     ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
     DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
     IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.

  c. The disclaimer of warranties and limitation of liability provided
     above shall be interpreted in a manner that, to the extent
     possible, most closely approximates an absolute disclaimer and
     waiver of all liability.


Section 6 -- Term and Termination.

  a. This Public License applies for the term of the Copyright and
     Similar Rights licensed here. However, if You fail to comply with
     this Public License, then Your rights under this Public License
     terminate automatically.

  b. Where Your right to use the Licensed Material has terminated under
     Section 6(a), it reinstates:

       1. automatically as of the date the violation is cured, provided
          it is cured within 30 days of Your discovery of the
          violation; or

       2. upon express reinstatement by the Licensor.

     For the avoidance of doubt, this Section 6(b) does not affect any
     right the Licensor may have to seek remedies for Your violations
     of this Public License.

  c. For the avoidance of doubt, the Licensor may also offer the
     Licensed Material under separate terms or conditions or stop
     distributing the Licensed Material at any time; however, doing so
     will not terminate this Public License.

  d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
     License.


Section 7 -- Other Terms and Conditions.

  a. The Licensor shall not be bound by any additional or different
     terms or conditions communicated by You unless expressly agreed.

  b. Any arrangements, understandings, or agreements regarding the
     Licensed Material not stated herein are separate from and
     independent of the terms and conditions of this Public License.


Section 8 -- Interpretation.

  a. For the avoidance of doubt, this Public License does not, and
     shall not be interpreted to, reduce, limit, restrict, or impose
     conditions on any use of the Licensed Material that could lawfully
     be made without permission under this Public License.

  b. To the extent possible, if any provision of this Public License is
     deemed unenforceable, it shall be automatically reformed to the
     minimum extent necessary to make it enforceable. If the provision
     cannot be reformed, it shall be severed from this Public License
     without affecting the enforceability of the remaining terms and
     conditions.

  c. No term or condition of this Public License will be waived and no
     failure to comply consented to unless expressly agreed to by the
     Licensor.

  d. Nothing in this Public License constitutes or may be interpreted
     as a limitation upon, or waiver of, any privileges and immunities
     that apply to the Licensor or You, including from the legal
     processes of any jurisdiction or authority.

=======================================================================

Creative Commons is not a party to its public
licenses. Notwithstanding, Creative Commons may elect to apply one of
its public licenses to material it publishes and in those instances
will be considered the “Licensor.” The text of the Creative Commons
public licenses is dedicated to the public domain under the CC0 Public
Domain Dedication. Except for the limited purpose of indicating that
material is shared under a Creative Commons public license or as
otherwise permitted by the Creative Commons policies published at
creativecommons.org/policies, Creative Commons does not authorize the
use of the trademark "Creative Commons" or any other trademark or logo
of Creative Commons without its prior written consent including,
without limitation, in connection with any unauthorized modifications
to any of its public licenses or any other arrangements,
understandings, or agreements concerning use of licensed material. For
the avoidance of doubt, this paragraph does not form part of the
public licenses.

Creative Commons may be contacted at creativecommons.org.
```

### The third-party libraries used in NanaRun

- C++/WinRT, https://github.com/microsoft/cppwinrt
- Mile.Detours, https://github.com/ProjectMile/Mile.Detours
- Mile.Project.Windows, https://github.com/ProjectMile/Mile.Project.Windows
- VC-LTL, https://github.com/Chuyu-Team/VC-LTL5


================================================
FILE: MinSudo/MinSudo.cpp
================================================
/*
 * PROJECT:    NanaRun
 * FILE:       MinSudo.cpp
 * PURPOSE:    Implementation for MinSudo
 *
 * LICENSE:    The MIT License
 *
 * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)
 */

#include <Windows.h>

#include <WtsApi32.h>
#pragma comment(lib, "WtsApi32.lib")

#include <Userenv.h>
#pragma comment(lib, "Userenv.lib")

#include <cstdint>
#include <cwchar>

#include <map>
#include <string>
#include <vector>

#include <Mile.Project.Version.h>

#include "resource.h"

#include <Mile.Helpers.CppBase.h>

namespace
{
    void SplitCommandLineEx(
        std::wstring const& CommandLine,
        std::vector<std::wstring> const& OptionPrefixes,
        std::vector<std::wstring> const& OptionParameterSeparators,
        std::wstring& ApplicationName,
        std::map<std::wstring, std::wstring>& OptionsAndParameters,
        std::wstring& UnresolvedCommandLine)
    {
        ApplicationName.clear();
        OptionsAndParameters.clear();
        UnresolvedCommandLine.clear();

        size_t arg_size = 0;
        for (auto& SplitArgument : Mile::SplitCommandLineWideString(CommandLine))
        {
            // We need to process the application name at the beginning.
            if (ApplicationName.empty())
            {
                // For getting the unresolved command line, we need to cumulate
                // length which including spaces.
                arg_size += SplitArgument.size() + 1;

                // Save
                ApplicationName = SplitArgument;
            }
            else
            {
                bool IsOption = false;
                size_t OptionPrefixLength = 0;

                for (auto& OptionPrefix : OptionPrefixes)
                {
                    if (0 == _wcsnicmp(
                        SplitArgument.c_str(),
                        OptionPrefix.c_str(),
                        OptionPrefix.size()))
                    {
                        IsOption = true;
                        OptionPrefixLength = OptionPrefix.size();
                    }
                }

                if (IsOption)
                {
                    // For getting the unresolved command line, we need to cumulate
                    // length which including spaces.
                    arg_size += SplitArgument.size() + 1;

                    // Get the option name and parameter.

                    wchar_t* OptionStart = &SplitArgument[0] + OptionPrefixLength;
                    wchar_t* ParameterStart = nullptr;

                    for (auto& OptionParameterSeparator
                        : OptionParameterSeparators)
                    {
                        wchar_t* Result = wcsstr(
                            OptionStart,
                            OptionParameterSeparator.c_str());
                        if (nullptr == Result)
                        {
                            continue;
                        }

                        Result[0] = L'\0';
                        ParameterStart = Result + OptionParameterSeparator.size();

                        break;
                    }

                    // Save
                    OptionsAndParameters[(OptionStart ? OptionStart : L"")] =
                        (ParameterStart ? ParameterStart : L"");
                }
                else
                {
                    // Get the approximate location of the unresolved command line.
                    // We use "(arg_size - 1)" to ensure that the program path
                    // without quotes can also correctly parse.
                    wchar_t* search_start =
                        const_cast<wchar_t*>(CommandLine.c_str()) + (arg_size - 1);

                    // Get the unresolved command line. Search for the beginning of
                    // the first parameter delimiter called space and exclude the
                    // first space by adding 1 to the result.
                    wchar_t* command = wcsstr(search_start, L" ") + 1;

                    // Omit the space. (Thanks to wzzw.)
                    while (command && *command == L' ')
                    {
                        ++command;
                    }

                    // Save
                    if (command)
                    {
                        UnresolvedCommandLine = command;
                    }

                    break;
                }
            }
        }
    }

    std::wstring GetCurrentProcessModulePath()
    {
        // 32767 is the maximum path length without the terminating null character.
        std::wstring Path(32767, L'\0');
        Path.resize(::GetModuleFileNameW(
            nullptr, &Path[0], static_cast<DWORD>(Path.size())));
        return Path;
    }

    std::wstring GetWorkingDirectory()
    {
        // 32767 is the maximum path length without the terminating null character.
        std::wstring Path(32767, L'\0');
        Path.resize(::GetCurrentDirectoryW(
            static_cast<DWORD>(Path.size()), &Path[0]));
        return Path;
    }

    void WriteToConsole(
        std::wstring_view const& String)
    {
        HANDLE ConsoleOutputHandle = ::GetStdHandle(STD_OUTPUT_HANDLE);

        DWORD NumberOfCharsWritten = 0;
        if (!::WriteConsoleW(
            ConsoleOutputHandle,
            String.data(),
            static_cast<DWORD>(String.size()),
            &NumberOfCharsWritten,
            nullptr))
        {
            std::string CurrentCodePageString = Mile::ToString(
                ::GetConsoleOutputCP(),
                String);

            ::WriteFile(
                ConsoleOutputHandle,
                CurrentCodePageString.c_str(),
                static_cast<DWORD>(CurrentCodePageString.size()),
                &NumberOfCharsWritten,
                nullptr);
        }
    }

    std::map<std::string, std::wstring> ParseStringDictionary(
        std::string_view const& Content)
    {
        constexpr std::string_view KeySeparator = "\r\n- ";
        constexpr std::string_view ValueStartSeparator = "\r\n```\r\n";
        constexpr std::string_view ValueEndSeparator = "\r\n```";

        std::map<std::string, std::wstring> Result;

        if (Content.empty())
        {
            return Result;
        }

        const char* Start = Content.data();
        const char* End = Start + Content.size();

        while (Start < End)
        {
            const char* KeyStart = std::strstr(
                Start,
                KeySeparator.data());
            if (!KeyStart)
            {
                break;
            }
            KeyStart += KeySeparator.size();

            const char* KeyEnd = std::strstr(
                KeyStart,
                ValueStartSeparator.data());
            if (!KeyEnd)
            {
                break;
            }

            const char* ValueStart =
                KeyEnd + ValueStartSeparator.size();

            const char* ValueEnd = std::strstr(
                ValueStart,
                ValueEndSeparator.data());
            if (!ValueEnd)
            {
                break;
            }

            Start = ValueEnd + ValueEndSeparator.size();

            Result.emplace(std::pair(
                std::string(KeyStart, KeyEnd - KeyStart),
                Mile::ToWideString(
                    CP_UTF8,
                    std::string(ValueStart, ValueEnd - ValueStart))));
        }

        return Result;
    }

    DWORD GetActiveSessionID()
    {
        DWORD Count = 0;
        PWTS_SESSION_INFOW pSessionInfo = nullptr;
        if (::WTSEnumerateSessionsW(
            WTS_CURRENT_SERVER_HANDLE,
            0,
            1,
            &pSessionInfo,
            &Count))
        {
            for (DWORD i = 0; i < Count; ++i)
            {
                if (pSessionInfo[i].State == WTS_CONNECTSTATE_CLASS::WTSActive)
                {
                    return pSessionInfo[i].SessionId;
                }
            }

            ::WTSFreeMemory(pSessionInfo);
        }

        // We should return session 0 for the case that no active session.
        return 0;
    }

    BOOL CreateSystemToken(
        _In_ DWORD DesiredAccess,
        _Out_ PHANDLE TokenHandle)
    {
        // If the specified process is the System Idle Process (0x00000000), the
        // function fails and the last error code is ERROR_INVALID_PARAMETER.
        // So this is why 0 is the default value of dwLsassPID and dwWinLogonPID.

        // For fix the issue that @_kod0k and @DennyAmaro mentioned in
        // https://forums.mydigitallife.net/threads/59268/page-28#post-1672011 and
        // https://forums.mydigitallife.net/threads/59268/page-28#post-1674985.
        // Mile::CreateSystemToken will try to open the access token from lsass.exe
        // for maximum privileges in the access token, and try to open the access
        // token from winlogon.exe of current active session as fallback.

        // If no source process of SYSTEM access token can be found, the error code
        // will be HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER).

        DWORD dwLsassPID = 0;
        DWORD dwWinLogonPID = 0;
        PWTS_PROCESS_INFOW pProcesses = nullptr;
        DWORD dwProcessCount = 0;
        DWORD dwSessionID = ::GetActiveSessionID();

        if (::WTSEnumerateProcessesW(
            WTS_CURRENT_SERVER_HANDLE,
            0,
            1,
            &pProcesses,
            &dwProcessCount))
        {
            for (DWORD i = 0; i < dwProcessCount; ++i)
            {
                PWTS_PROCESS_INFOW pProcess = &pProcesses[i];

                if ((!pProcess->pProcessName) ||
                    (!pProcess->pUserSid) ||
                    (!::IsWellKnownSid(
                        pProcess->pUserSid,
                        WELL_KNOWN_SID_TYPE::WinLocalSystemSid)))
                {
                    continue;
                }

                if ((0 == dwLsassPID) &&
                    (0 == pProcess->SessionId) &&
                    (0 == ::_wcsicmp(L"lsass.exe", pProcess->pProcessName)))
                {
                    dwLsassPID = pProcess->ProcessId;
                    continue;
                }

                if ((0 == dwWinLogonPID) &&
                    (0 == dwSessionID || dwSessionID == pProcess->SessionId) &&
                    (0 == ::_wcsicmp(L"winlogon.exe", pProcess->pProcessName)))
                {
                    dwWinLogonPID = pProcess->ProcessId;
                    continue;
                }
            }

            ::WTSFreeMemory(pProcesses);
        }

        BOOL Result = FALSE;
        HANDLE SystemProcessHandle = nullptr;

        SystemProcessHandle = ::OpenProcess(
            PROCESS_QUERY_INFORMATION,
            FALSE,
            dwLsassPID);
        if (!SystemProcessHandle)
        {
            SystemProcessHandle = ::OpenProcess(
                PROCESS_QUERY_INFORMATION,
                FALSE,
                dwWinLogonPID);
        }

        if (SystemProcessHandle)
        {
            HANDLE SystemTokenHandle = nullptr;
            if (::OpenProcessToken(
                SystemProcessHandle,
                TOKEN_DUPLICATE,
                &SystemTokenHandle))
            {
                Result = ::DuplicateTokenEx(
                    SystemTokenHandle,
                    DesiredAccess,
                    nullptr,
                    SecurityIdentification,
                    TokenPrimary,
                    TokenHandle);

                ::CloseHandle(SystemTokenHandle);
            }

            ::CloseHandle(SystemProcessHandle);
        }

        return Result;
    }

    BOOL OpenProcessTokenByProcessId(
        _In_ DWORD ProcessId,
        _In_ DWORD DesiredAccess,
        _Out_ PHANDLE TokenHandle)
    {
        BOOL Result = FALSE;

        HANDLE ProcessHandle = ::OpenProcess(
            PROCESS_QUERY_INFORMATION,
            FALSE,
            ProcessId);
        if (ProcessHandle)
        {
            Result = ::OpenProcessToken(
                ProcessHandle,
                DesiredAccess,
                TokenHandle);

            ::CloseHandle(ProcessHandle);
        }

        return Result;
    }

    BOOL OpenServiceProcessToken(
        _In_ LPCWSTR ServiceName,
        _In_ DWORD DesiredAccess,
        _Out_ PHANDLE TokenHandle)
    {
        BOOL Result = FALSE;

        SERVICE_STATUS_PROCESS ServiceStatus;
        if (::MileStartService(
            ServiceName,
            &ServiceStatus))
        {
            Result = ::OpenProcessTokenByProcessId(
                ServiceStatus.dwProcessId,
                DesiredAccess,
                TokenHandle);
        }

        return Result;
    }

    BOOL AdjustTokenPrivilegesSimple(
        _In_ HANDLE TokenHandle,
        _In_ PLUID_AND_ATTRIBUTES Privileges,
        _In_ DWORD PrivilegeCount)
    {
        BOOL Result = FALSE;

        if (Privileges && PrivilegeCount)
        {
            DWORD PrivilegesSize = sizeof(LUID_AND_ATTRIBUTES) * PrivilegeCount;
            DWORD TokenPrivilegesSize = PrivilegesSize + sizeof(DWORD);

            PTOKEN_PRIVILEGES TokenPrivileges =
                reinterpret_cast<PTOKEN_PRIVILEGES>(
                    ::MileAllocateMemory(TokenPrivilegesSize));
            if (TokenPrivileges)
            {
                TokenPrivileges->PrivilegeCount = PrivilegeCount;
                std::memcpy(
                    TokenPrivileges->Privileges,
                    Privileges,
                    PrivilegesSize);

                ::AdjustTokenPrivileges(
                    TokenHandle,
                    FALSE,
                    TokenPrivileges,
                    TokenPrivilegesSize,
                    nullptr,
                    nullptr);
                Result = (ERROR_SUCCESS == ::GetLastError());

                ::MileFreeMemory(TokenPrivileges);
            }
            else
            {
                ::SetLastError(ERROR_NOT_ENOUGH_MEMORY);
            }
        }
        else
        {
            ::SetLastError(ERROR_INVALID_PARAMETER);
        }

        return Result;
    }

    BOOL GetTokenInformationWithMemory(
        _In_ HANDLE TokenHandle,
        _In_ TOKEN_INFORMATION_CLASS TokenInformationClass,
        _Out_ PVOID* OutputInformation)
    {
        if (!OutputInformation)
        {
            ::SetLastError(ERROR_INVALID_PARAMETER);
            return FALSE;
        }

        *OutputInformation = nullptr;

        BOOL Result = FALSE;

        DWORD Length = 0;
        ::GetTokenInformation(
            TokenHandle,
            TokenInformationClass,
            nullptr,
            0,
            &Length);
        if (ERROR_INSUFFICIENT_BUFFER == ::GetLastError())
        {
            *OutputInformation = ::MileAllocateMemory(Length);
            if (*OutputInformation)
            {
                Result = ::GetTokenInformation(
                    TokenHandle,
                    TokenInformationClass,
                    *OutputInformation,
                    Length,
                    &Length);
                if (!Result)
                {
                    ::MileFreeMemory(*OutputInformation);
                    *OutputInformation = nullptr;
                }
            }
            else
            {
                ::SetLastError(ERROR_NOT_ENOUGH_MEMORY);
            }
        }

        return Result;
    }

    BOOL AdjustTokenAllPrivileges(
        _In_ HANDLE TokenHandle,
        _In_ DWORD Attributes)
    {
        BOOL Result = FALSE;

        PTOKEN_PRIVILEGES pTokenPrivileges = nullptr;
        if (::GetTokenInformationWithMemory(
            TokenHandle,
            TokenPrivileges,
            reinterpret_cast<PVOID*>(&pTokenPrivileges)))
        {
            for (DWORD i = 0; i < pTokenPrivileges->PrivilegeCount; ++i)
            {
                pTokenPrivileges->Privileges[i].Attributes = Attributes;
            }

            Result = ::AdjustTokenPrivilegesSimple(
                TokenHandle,
                pTokenPrivileges->Privileges,
                pTokenPrivileges->PrivilegeCount);

            ::MileFreeMemory(pTokenPrivileges);
        }

        return Result;
    }

    enum class TargetProcessTokenLevel : std::uint32_t
    {
        Standard = 0,
        System = 1,
        TrustedInstaller = 2,
    };

    BOOL SimpleCreateProcess(
        _In_ TargetProcessTokenLevel TokenLevel,
        _In_ bool Privileged,
        _Inout_ LPWSTR lpCommandLine,
        _In_opt_ LPCWSTR lpCurrentDirectory,
        _In_ LPSTARTUPINFOW lpStartupInfo,
        _Out_ LPPROCESS_INFORMATION lpProcessInformation)
    {
        BOOL Result = FALSE;
        DWORD Error = ERROR_SUCCESS;

        HANDLE CurrentProcessTokenHandle = INVALID_HANDLE_VALUE;
        HANDLE ImpersonatedCurrentProcessTokenHandle = INVALID_HANDLE_VALUE;
        LUID_AND_ATTRIBUTES RawPrivilege;
        HANDLE SystemTokenHandle = INVALID_HANDLE_VALUE;
        HANDLE ImpersonatedSystemTokenHandle = INVALID_HANDLE_VALUE;
        HANDLE TrustedInstallerTokenHandle = INVALID_HANDLE_VALUE;
        HANDLE TargetTokenHandle = INVALID_HANDLE_VALUE;
        LPVOID EnvironmentBlock = nullptr;

        auto Handler = Mile::ScopeExitTaskHandler([&]()
        {
            if (EnvironmentBlock)
            {
                ::DestroyEnvironmentBlock(EnvironmentBlock);
            }

            if (TargetTokenHandle != INVALID_HANDLE_VALUE)
            {
                ::CloseHandle(TargetTokenHandle);
            }

            if (TrustedInstallerTokenHandle != INVALID_HANDLE_VALUE)
            {
                ::CloseHandle(TrustedInstallerTokenHandle);
            }

            if (ImpersonatedSystemTokenHandle != INVALID_HANDLE_VALUE)
            {
                ::CloseHandle(ImpersonatedSystemTokenHandle);
            }

            if (SystemTokenHandle != INVALID_HANDLE_VALUE)
            {
                ::CloseHandle(SystemTokenHandle);
            }

            if (ImpersonatedCurrentProcessTokenHandle != INVALID_HANDLE_VALUE)
            {
                ::CloseHandle(ImpersonatedCurrentProcessTokenHandle);
            }

            if (CurrentProcessTokenHandle != INVALID_HANDLE_VALUE)
            {
                ::CloseHandle(CurrentProcessTokenHandle);
            }

            ::SetThreadToken(nullptr, nullptr);

            if (!Result)
            {
                ::SetLastError(Error);
            }
        });

        if (!::OpenProcessToken(
            ::GetCurrentProcess(),
            MAXIMUM_ALLOWED,
            &CurrentProcessTokenHandle))
        {
            Error = ::GetLastError();
            return Result;
        }

        if (!::DuplicateTokenEx(
            CurrentProcessTokenHandle,
            MAXIMUM_ALLOWED,
            nullptr,
            SecurityImpersonation,
            TokenImpersonation,
            &ImpersonatedCurrentProcessTokenHandle))
        {
            Error = ::GetLastError();
            return Result;
        }

        if (!::LookupPrivilegeValueW(
            nullptr,
            SE_DEBUG_NAME,
            &RawPrivilege.Luid))
        {
            Error = ::GetLastError();
            return Result;
        }

        RawPrivilege.Attributes = SE_PRIVILEGE_ENABLED;

        if (!::AdjustTokenPrivilegesSimple(
            ImpersonatedCurrentProcessTokenHandle,
            &RawPrivilege,
            1))
        {
            Error = ::GetLastError();
            return Result;
        }

        if (!::SetThreadToken(
            nullptr,
            ImpersonatedCurrentProcessTokenHandle))
        {
            Error = ::GetLastError();
            return Result;
        }

        if (!::CreateSystemToken(
            MAXIMUM_ALLOWED,
            &SystemTokenHandle))
        {
            Error = ::GetLastError();
            return Result;
        }

        if (!::DuplicateTokenEx(
            SystemTokenHandle,
            MAXIMUM_ALLOWED,
            nullptr,
            SecurityImpersonation,
            TokenImpersonation,
            &ImpersonatedSystemTokenHandle))
        {
            Error = ::GetLastError();
            return Result;
        }

        if (!::AdjustTokenAllPrivileges(
            ImpersonatedSystemTokenHandle,
            SE_PRIVILEGE_ENABLED))
        {
            Error = ::GetLastError();
            return Result;
        }

        if (!::SetThreadToken(
            nullptr,
            ImpersonatedSystemTokenHandle))
        {
            Error = ::GetLastError();
            return Result;
        }

        if (TargetProcessTokenLevel::Standard == TokenLevel)
        {
            if (!::DuplicateTokenEx(
                CurrentProcessTokenHandle,
                MAXIMUM_ALLOWED,
                nullptr,
                SecurityIdentification,
                TokenPrimary,
                &TargetTokenHandle))
            {
                Error = ::GetLastError();
                return Result;
            }
        }
        else if (TargetProcessTokenLevel::System == TokenLevel)
        {
            if (!::DuplicateTokenEx(
                SystemTokenHandle,
                MAXIMUM_ALLOWED,
                nullptr,
                SecurityIdentification,
                TokenPrimary,
                &TargetTokenHandle))
            {
                Error = ::GetLastError();
                return Result;
            }
        }
        else if (TargetProcessTokenLevel::TrustedInstaller == TokenLevel)
        {
            if (!::OpenServiceProcessToken(
                L"TrustedInstaller",
                MAXIMUM_ALLOWED,
                &TrustedInstallerTokenHandle))
            {
                Error = ::GetLastError();
                return Result;
            }

            if (!::DuplicateTokenEx(
                TrustedInstallerTokenHandle,
                MAXIMUM_ALLOWED,
                nullptr,
                SecurityIdentification,
                TokenPrimary,
                &TargetTokenHandle))
            {
                Error = ::GetLastError();
                return Result;
            }
        }
        else
        {
            Error = ERROR_INVALID_PARAMETER;
            return Result;
        }

        {
            DWORD SessionID = ::GetActiveSessionID();
            if (!::SetTokenInformation(
                TargetTokenHandle,
                TokenSessionId,
                (PVOID)&SessionID,
                sizeof(DWORD)))
            {
                Error = ::GetLastError();
                return Result;
            }
        }

        if (Privileged)
        {
            if (!::AdjustTokenAllPrivileges(
                TargetTokenHandle,
                SE_PRIVILEGE_ENABLED))
            {
                Error = ::GetLastError();
                return Result;
            }
        }

        if (!::CreateEnvironmentBlock(
            &EnvironmentBlock,
            CurrentProcessTokenHandle,
            TRUE))
        {
            Error = ::GetLastError();
            return Result;
        }

        Result = ::CreateProcessAsUserW(
            TargetTokenHandle,
            nullptr,
            lpCommandLine,
            nullptr,
            nullptr,
            TRUE,
            CREATE_UNICODE_ENVIRONMENT,
            EnvironmentBlock,
            lpCurrentDirectory,
            lpStartupInfo,
            lpProcessInformation);

        return Result;
    }
}

int main()
{
    // Fall back to English in unsupported environment. (Temporary Hack)
    // Reference: https://github.com/M2Team/NSudo/issues/56
    switch (PRIMARYLANGID(::GetThreadUILanguage()))
    {
    case LANG_ENGLISH:
    case LANG_CHINESE:
        break;
    default:
        ::SetThreadUILanguage(MAKELANGID(LANG_ENGLISH, SUBLANG_NEUTRAL));
        break;
    }

    std::map<std::string, std::wstring> StringDictionary;

    MILE_RESOURCE_INFO ResourceInfo = { 0 };
    if (::MileLoadResource(
        &ResourceInfo,
        ::GetModuleHandleW(nullptr),
        L"Translations",
        MAKEINTRESOURCEW(IDR_TRANSLATIONS),
        MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL)))
    {
        StringDictionary = ::ParseStringDictionary(std::string_view(
            reinterpret_cast<const char*>(ResourceInfo.Pointer),
            ResourceInfo.Size));
    }

    std::wstring ApplicationName;
    std::map<std::wstring, std::wstring> OptionsAndParameters;
    std::wstring UnresolvedCommandLine;

    ::SplitCommandLineEx(
        std::wstring(::GetCommandLineW()),
        std::vector<std::wstring>{ L"-", L"/", L"--" },
        std::vector<std::wstring>{ L"=", L":" },
        ApplicationName,
        OptionsAndParameters,
        UnresolvedCommandLine);

    bool NoLogo = false;
    bool Verbose = false;
    std::wstring WorkDir;
    TargetProcessTokenLevel TargetLevel = TargetProcessTokenLevel::Standard;
    bool Privileged = false;

    for (auto& Current : OptionsAndParameters)
    {
        if (0 == _wcsicmp(Current.first.c_str(), L"NoLogo") ||
            0 == _wcsicmp(Current.first.c_str(), L"NoL"))
        {
            NoLogo = true;
        }
        else if (
            0 == _wcsicmp(Current.first.c_str(), L"Verbose") ||
            0 == _wcsicmp(Current.first.c_str(), L"V"))
        {
            Verbose = true;
        }
        else if (
            0 == _wcsicmp(Current.first.c_str(), L"WorkDir") ||
            0 == _wcsicmp(Current.first.c_str(), L"WD"))
        {
            WorkDir = Current.second;
        }
        else if (
            0 == _wcsicmp(Current.first.c_str(), L"System") ||
            0 == _wcsicmp(Current.first.c_str(), L"S"))
        {
            TargetLevel = TargetProcessTokenLevel::System;
        }
        else if (
            0 == _wcsicmp(Current.first.c_str(), L"TrustedInstaller") ||
            0 == _wcsicmp(Current.first.c_str(), L"TI"))
        {
            TargetLevel = TargetProcessTokenLevel::TrustedInstaller;
        }
        else if (
            0 == _wcsicmp(Current.first.c_str(), L"Privileged") ||
            0 == _wcsicmp(Current.first.c_str(), L"P"))
        {
            Privileged = true;
        }
    }

    bool ShowHelp = false;
    bool ShowInvalidCommandLine = false;

    if (1 == OptionsAndParameters.size() && UnresolvedCommandLine.empty())
    {
        auto Current = *OptionsAndParameters.begin();

        if (0 == _wcsicmp(Current.first.c_str(), L"?") ||
            0 == _wcsicmp(Current.first.c_str(), L"H") ||
            0 == _wcsicmp(Current.first.c_str(), L"Help"))
        {
            ShowHelp = true;
        }
        else if (
            0 == _wcsicmp(Current.first.c_str(), L"Version") ||
            0 == _wcsicmp(Current.first.c_str(), L"Ver"))
        {
            ::WriteToConsole(
                L"MinSudo " MILE_PROJECT_VERSION_STRING L" (Build "
                MILE_PROJECT_MACRO_TO_STRING(MILE_PROJECT_VERSION_BUILD) L")"
                L"\r\n");
            return 0;
        }
        else if (!(
            NoLogo ||
            Verbose ||
            !WorkDir.empty() ||
            TargetLevel != TargetProcessTokenLevel::Standard ||
            Privileged))
        {
            ShowInvalidCommandLine = true;
        }
    }

    if (!NoLogo)
    {
        ::WriteToConsole(
            L"MinSudo " MILE_PROJECT_VERSION_STRING L" (Build "
            MILE_PROJECT_MACRO_TO_STRING(MILE_PROJECT_VERSION_BUILD) L")" L"\r\n"
            L"(c) M2-Team and Contributors. All rights reserved.\r\n"
            L"\r\n");
    }

    if (ShowHelp)
    {
        ::WriteToConsole(StringDictionary["CommandLineHelp"]);

        return 0;
    }
    else if (ShowInvalidCommandLine)
    {
        ::WriteToConsole(StringDictionary["InvalidCommandLineError"]);

        return E_INVALIDARG;
    }

    ApplicationName = ::GetCurrentProcessModulePath();
    if (UnresolvedCommandLine.empty())
    {
        UnresolvedCommandLine = L"cmd.exe";
    }

    if (Verbose)
    {
        std::wstring VerboseInformation;
        VerboseInformation += StringDictionary["CommandLineNotice"];
        VerboseInformation += UnresolvedCommandLine;
        VerboseInformation += L"\r\n";
        ::WriteToConsole(VerboseInformation.c_str());
    }

    if (WorkDir.empty())
    {
        WorkDir = std::wstring(::GetWorkingDirectory());
    }
    if (L'\\' == WorkDir.back())
    {
        WorkDir.pop_back();
    }

    if (::MileIsCurrentProcessElevated())
    {
        ::FreeConsole();
        ::AttachConsole(ATTACH_PARENT_PROCESS);

        if (Verbose)
        {
            ::WriteToConsole(StringDictionary["Stage1Notice"]);
        }

        STARTUPINFOW StartupInfo = { 0 };
        PROCESS_INFORMATION ProcessInformation = { 0 };
        StartupInfo.cb = sizeof(STARTUPINFOW);
        if (::SimpleCreateProcess(
            TargetLevel,
            Privileged,
            const_cast<LPWSTR>(UnresolvedCommandLine.c_str()),
            WorkDir.c_str(),
            &StartupInfo,
            &ProcessInformation))
        {
            // Make sure ignores CTRL+C signals after creating the child
            // process. Because that state is heritable, but we want to make
            // child process support CTRL+C.
            ::SetConsoleCtrlHandler(nullptr, TRUE);

            ::CloseHandle(ProcessInformation.hThread);
            ::WaitForSingleObjectEx(ProcessInformation.hProcess, INFINITE, FALSE);
            ::CloseHandle(ProcessInformation.hProcess);
        }
        else
        {
            ::WriteToConsole(StringDictionary["Stage1Failed"]);
        }
    }
    else
    {
        if (Verbose)
        {
            ::WriteToConsole(StringDictionary["Stage0Notice"]);
        }

        std::wstring TargetCommandLine = L"--NoLogo ";
        if (Verbose)
        {
            TargetCommandLine += L"--Verbose ";
        }
        TargetCommandLine += L"--WorkDir=\"";
        TargetCommandLine += WorkDir;
        TargetCommandLine += L"\" ";
        if (TargetLevel == TargetProcessTokenLevel::System)
        {
            TargetCommandLine += L"--System ";
        }
        else if (TargetLevel == TargetProcessTokenLevel::TrustedInstaller)
        {
            TargetCommandLine += L"--TrustedInstaller ";
        }
        if (Privileged)
        {
            TargetCommandLine += L"--Privileged ";
        }
        TargetCommandLine += UnresolvedCommandLine;

        SHELLEXECUTEINFOW Information = { 0 };
        Information.cbSize = sizeof(SHELLEXECUTEINFOW);
        Information.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_NO_CONSOLE;
        Information.lpVerb = L"runas";
        Information.lpFile = ApplicationName.c_str();
        Information.lpParameters = TargetCommandLine.c_str();
        if (::ShellExecuteExW(&Information))
        {
            // Make sure ignores CTRL+C signals after creating the child
            // process. Because that state is heritable, but we want to make
            // child process support CTRL+C.
            ::SetConsoleCtrlHandler(nullptr, TRUE);

            ::WaitForSingleObjectEx(Information.hProcess, INFINITE, FALSE);
            ::CloseHandle(Information.hProcess);
        }
        else
        {
            ::WriteToConsole(StringDictionary["Stage0Failed"]);
        }
    }

    return 0;
}


================================================
FILE: MinSudo/MinSudo.manifest
================================================
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
	<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
		<security>
			<requestedPrivileges>
				<requestedExecutionLevel level="asInvoker" uiAccess="false"/>
			</requestedPrivileges>
		</security>
	</trustInfo>
	<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
		<application>
			<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
			<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
			<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
			<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
			<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
		</application>
	</compatibility>
</assembly>


================================================
FILE: MinSudo/MinSudo.vcxproj
================================================
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup Label="Globals">
    <ProjectGuid>{99FA5072-6C05-4027-8C8B-EA3EC9BCF9E0}</ProjectGuid>
    <RootNamespace>MinSudo</RootNamespace>
    <MileProjectType>ConsoleApplication</MileProjectType>
    <MileProjectManifestFile>MinSudo.manifest</MileProjectManifestFile>
    <MileProjectEnableVCLTLSupport>true</MileProjectEnableVCLTLSupport>
    <MileProjectUseProjectProperties>true</MileProjectUseProjectProperties>
    <MileProjectCompanyName>M2-Team</MileProjectCompanyName>
    <MileProjectFileDescription>MinSudo - Lightweight POSIX-style Sudo implementation for Windows</MileProjectFileDescription>
    <MileProjectInternalName>MinSudo</MileProjectInternalName>
    <MileProjectLegalCopyright>© M2-Team and Contributors. All rights reserved.</MileProjectLegalCopyright>
    <MileProjectOriginalFilename>MinSudo.exe</MileProjectOriginalFilename>
    <MileProjectProductName>NanaRun</MileProjectProductName>
    <MileProjectVersion>1.0.$([System.DateTime]::Today.Subtract($([System.DateTime]::Parse('2024-05-01'))).TotalDays).0</MileProjectVersion>
    <MileProjectVersionTag>Preview 3</MileProjectVersionTag>
    <MileWindowsHelpersNoCppWinRTHelpers>true</MileWindowsHelpersNoCppWinRTHelpers>
  </PropertyGroup>
  <Import Sdk="Mile.Project.Configurations" Version="1.0.1917" Project="Mile.Project.Platform.x86.props" />
  <Import Sdk="Mile.Project.Configurations" Version="1.0.1917" Project="Mile.Project.Platform.x64.props" />
  <Import Sdk="Mile.Project.Configurations" Version="1.0.1917" Project="Mile.Project.Platform.ARM64.props" />
  <Import Sdk="Mile.Project.Configurations" Version="1.0.1917" Project="Mile.Project.Cpp.Default.props" />
  <Import Sdk="Mile.Project.Configurations" Version="1.0.1917" Project="Mile.Project.Cpp.props" />
  <Import Project="..\NanaRun.IconResource\NanaRun.IconResource.props" />
  <ItemDefinitionGroup>
    <ClCompile>
      <EnableEnhancedInstructionSet Condition="'$(Platform)'=='Win32'">NoExtensions</EnableEnhancedInstructionSet>
    </ClCompile>
  </ItemDefinitionGroup>
  <ItemGroup>
    <ClCompile Include="MinSudo.cpp" />
  </ItemGroup>
  <ItemGroup>
    <Manifest Include="MinSudo.manifest" />
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="resource.h" />
  </ItemGroup>
  <ItemGroup>
    <None Include="Resources\en\Translations.md" />
    <None Include="Resources\zh-Hans\Translations.md" />
  </ItemGroup>
  <ItemGroup>
    <ResourceCompile Include="MinSudo.rc" />
  </ItemGroup>
  <ItemGroup>
    <PackageReference Include="Mile.Windows.Helpers">
      <Version>1.0.1171</Version>
    </PackageReference>
  </ItemGroup>
  <Import Sdk="Mile.Project.Configurations" Version="1.0.1917" Project="Mile.Project.Cpp.targets" />
</Project>

================================================
FILE: MinSudo/MinSudo.vcxproj.filters
================================================
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <ClCompile Include="MinSudo.cpp" />
  </ItemGroup>
  <ItemGroup>
    <Manifest Include="MinSudo.manifest" />
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="resource.h" />
  </ItemGroup>
  <ItemGroup>
    <Filter Include="Resources">
      <UniqueIdentifier>{7b09b2fc-15c9-40d3-8c68-b33226a0b2cd}</UniqueIdentifier>
    </Filter>
    <Filter Include="Resources\en">
      <UniqueIdentifier>{0e9f5c86-045b-493f-b15e-750b369fc678}</UniqueIdentifier>
    </Filter>
    <Filter Include="Resources\zh-Hans">
      <UniqueIdentifier>{71ae93ee-4aa8-44b8-bc84-e680a9768fc5}</UniqueIdentifier>
    </Filter>
  </ItemGroup>
  <ItemGroup>
    <None Include="Resources\en\Translations.md">
      <Filter>Resources\en</Filter>
    </None>
    <None Include="Resources\zh-Hans\Translations.md">
      <Filter>Resources\zh-Hans</Filter>
    </None>
  </ItemGroup>
  <ItemGroup>
    <ResourceCompile Include="MinSudo.rc" />
  </ItemGroup>
</Project>

================================================
FILE: MinSudo/Resources/en/Translations.md
================================================
```
* PROJECT:    NanaRun
* FILE:       Translations.md
* PURPOSE:    The English translation for MinSudo
*
* LICENSE:    The MIT License
*
* MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)
```

- InvalidCommandLineError
```
[Error] Invalid command line parameters. (Use '/?', '-H' or '--Help' option for
usage.)

```
- CommandLineNotice
```
[Info] Target Command Line: 
```
- Stage0Notice
```
[Info] Enter the Stage 0 (non-elevated).

```
- Stage0Failed
```
[Error] ShellExecuteExW failed.

```
- Stage1Notice
```
[Info] Enter the Stage 1 (elevated).


```
- Stage1Failed
```
[Error] CreateProcessW failed.

```
- CommandLineHelp
```
Format: MinSudo [Options] Command

Options:

  --NoLogo, -NoL
    Suppress copyright message.

  --Verbose, -V
    Show detailed information.

  --WorkDir=[Path], -WD=[Path]
    Set working directory.

  --System, -S
    Run as System instead of Administrator.

  --TrustedInstaller, -TI
    Run as TrustedInstaller instead of Administrator.

  --Privileged, -P
    Enable all privileges.

  --Version, -Ver
    Show version information.

  /?, -H, --Help
    Show this content.

Notes:

  - All command options are case-insensitive.
  - MinSudo will execute "cmd.exe" if you don't specify another command.
  - You can use the "/" or "--" override "-" and use the "=" override ":" in 
    the command line parameters. For example, "/Option:Value" and 
    "-Option=Value" are equivalent.

Example:

  If you want to run "whoami /all" as elevated in the non-elevated Console, and
  you don't want to show version information of MinSudo.
  > MinSudo --NoLogo whoami /all

```


================================================
FILE: MinSudo/Resources/zh-Hans/Translations.md
================================================
```
* PROJECT:    NanaRun
* FILE:       Translations.md
* PURPOSE:    The Chinese (Simplified) translation for MinSudo
*
* LICENSE:    The MIT License
*
* MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)
```

- InvalidCommandLineError
```
[错误] 无效的命令行参数。 (使用 '/?', '-H' 或 '--Help' 选项获取用法。)

```
- CommandLineNotice
```
[信息] 目标命令行: 
```
- Stage0Notice
```
[信息] 进入 0 阶段 (未提权).

```
- Stage0Failed
```
[信息] ShellExecuteExW 调用失败。

```
- Stage1Notice
```
[信息] 进入 1 阶段 (已提权).


```
- Stage1Failed
```
[错误] CreateProcessW 调用失败。

```
- CommandLineHelp
```
格式: MinSudo [选项] 命令

选项:

  --NoLogo, -NoL
    隐藏版权信息。

  --Verbose, -V
    显示详细信息。

  --WorkDir=[路径], -WD=[路径]
    设置工作目录。

  --System, -S
    使用 System 而不是管理员执行。

  --TrustedInstaller, -TI
    使用 TrustedInstaller 而不是管理员执行。

  --Privileged, -P
    启用全部特权。

  --Version, -Ver
    显示版本信息。

  /?, -H, --Help
    显示该内容。

提示:

  - 所有命令选项不区分大小写。
  - 如果你不指定其他命令,MinSudo 将执行 "cmd.exe"。
  - 可以在命令行参数中使用 "/" 或 "--" 代替 "-" 和使用 "=" 代替 ":"。例如
    "/Option:Value" 和 "-Option=Value" 是等价的。

用例:

  如果你想在未提权的控制台下运行提权的 "whoami /all",并且你不希望 MinSudo 显示
  版本信息。
  > MinSudo --NoLogo whoami /all

```


================================================
FILE: MinSudo/resource.h
================================================
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ 生成的包含文件。
// 供 MinSudo.rc 使用
//
#define IDR_TRANSLATIONS                101

// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        104
#define _APS_NEXT_COMMAND_VALUE         40001
#define _APS_NEXT_CONTROL_VALUE         1001
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif


================================================
FILE: NanaRun/NanaRun.cpp
================================================
/*
 * PROJECT:    NanaRun
 * FILE:       NanaRun.cpp
 * PURPOSE:    Implementation for NanaRun
 *
 * LICENSE:    The MIT License
 *
 * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)
 */

#include <cstdint>
#include <cwchar>
#include <string>
#include <vector>

enum class AccessTokenSourceType : std::int32_t
{
    CurrentProcess = 0,
    Process = 1,
    System = 2,
    CurrentSession = 3,
    Session = 4,
    Service = 5,
    User = 6,
};

enum class MandatoryLabelType : std::int32_t
{
    Default = 0,
    Untrusted = 1,
    Low = 2,
    Medium = 3,
    MediumPlus = 4,
    High = 5,
    System = 6,
    ProtectedProcess = 7,
};

enum class ProcessPriorityType : std::int32_t
{
    Default = 0,
    Idle = 1,
    BelowNormal = 2,
    Normal = 3,
    AboveNormal = 4,
    High = 5,
    RealTime = 6,
};

enum class ShowWindowModeType : std::int32_t
{
    Default = 0,
    Show = 1,
    Hide = 2,
    Maximize = 3,
    Minimize = 4
};

struct EnvironmentConfiguration
{
    AccessTokenSourceType AccessTokenSource =
        AccessTokenSourceType::CurrentProcess;
    std::uint32_t Process = 0;
    std::uint32_t Session = 0;
    std::string ServiceName;
    std::string UserName;
    std::string UserPassword;

    bool UseLinkedAccessToken = false;
    bool UseLuaAccessToken = false;

    bool EnableAllPrivileges = false;
    bool RemoveAllPrivileges = false;
    std::vector<std::string> ExcludedPrivileges;
    std::vector<std::string> IncludedPrivileges;

    MandatoryLabelType IntegrityLevel = MandatoryLabelType::Default;

    bool InheritEnvironmentVariables = true;
    std::vector<std::pair<std::string, std::string>> EnvironmentVariables;

    ProcessPriorityType ProcessPriority = ProcessPriorityType::Default;

    ShowWindowModeType ShowWindowMode = ShowWindowModeType::Default;

    bool WaitForExit = false;

    std::string CurrentDirectory;

    bool UseCurrentConsole = false;
};

int main()
{
    std::wprintf(L"Hello World! - NanaRun (Console)");

    return 0;
}


================================================
FILE: NanaRun/NanaRun.manifest
================================================
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
	<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
		<security>
			<requestedPrivileges>
				<requestedExecutionLevel level="asInvoker" uiAccess="false"/>
			</requestedPrivileges>
		</security>
	</trustInfo>
	<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
		<application>
			<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
			<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
			<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
			<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
			<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
		</application>
	</compatibility>
</assembly>


================================================
FILE: NanaRun/NanaRun.vcxproj
================================================
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup Label="Globals">
    <ProjectGuid>{3D1A07C8-17B2-4E5F-AAC1-16BE522BD4D7}</ProjectGuid>
    <RootNamespace>NanaRun</RootNamespace>
    <MileProjectType>ConsoleApplication</MileProjectType>
    <MileProjectManifestFile>NanaRun.manifest</MileProjectManifestFile>
    <MileProjectEnableVCLTLSupport>true</MileProjectEnableVCLTLSupport>
    <MileProjectUseProjectProperties>true</MileProjectUseProjectProperties>
    <MileProjectCompanyName>M2-Team</MileProjectCompanyName>
    <MileProjectFileDescription>NanaRun (Console)</MileProjectFileDescription>
    <MileProjectInternalName>NanaRun</MileProjectInternalName>
    <MileProjectLegalCopyright>© M2-Team and Contributors. All rights reserved.</MileProjectLegalCopyright>
    <MileProjectOriginalFilename>NanaRun.exe</MileProjectOriginalFilename>
    <MileProjectProductName>NanaRun</MileProjectProductName>
    <MileProjectVersion>1.0.$([System.DateTime]::Today.Subtract($([System.DateTime]::Parse('2024-05-01'))).TotalDays).0</MileProjectVersion>
    <MileProjectVersionTag>Preview 3</MileProjectVersionTag>
    <MileWindowsHelpersNoCppWinRTHelpers>true</MileWindowsHelpersNoCppWinRTHelpers>
  </PropertyGroup>
  <Import Sdk="Mile.Project.Configurations" Version="1.0.1917" Project="Mile.Project.Platform.x86.props" />
  <Import Sdk="Mile.Project.Configurations" Version="1.0.1917" Project="Mile.Project.Platform.x64.props" />
  <Import Sdk="Mile.Project.Configurations" Version="1.0.1917" Project="Mile.Project.Platform.ARM64.props" />
  <Import Sdk="Mile.Project.Configurations" Version="1.0.1917" Project="Mile.Project.Cpp.Default.props" />
  <Import Sdk="Mile.Project.Configurations" Version="1.0.1917" Project="Mile.Project.Cpp.props" />
  <Import Project="..\NanaRun.IconResource\NanaRun.IconResource.props" />
  <ItemDefinitionGroup>
    <ClCompile>
      <EnableEnhancedInstructionSet Condition="'$(Platform)'=='Win32'">NoExtensions</EnableEnhancedInstructionSet>
    </ClCompile>
  </ItemDefinitionGroup>
  <ItemGroup>
    <ClCompile Include="NanaRun.cpp" />
  </ItemGroup>
  <ItemGroup>
    <Manifest Include="NanaRun.manifest" />
  </ItemGroup>
  <ItemGroup>
    <PackageReference Include="Mile.Windows.Helpers">
      <Version>1.0.1171</Version>
    </PackageReference>
    <PackageReference Include="Mile.Windows.Internal">
      <Version>1.0.3550</Version>
    </PackageReference>
  </ItemGroup>
  <Import Sdk="Mile.Project.Configurations" Version="1.0.1917" Project="Mile.Project.Cpp.targets" />
</Project>

================================================
FILE: NanaRun/NanaRun.vcxproj.filters
================================================
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup>
    <ClCompile Include="NanaRun.cpp" />
  </ItemGroup>
  <ItemGroup>
    <Manifest Include="NanaRun.manifest" />
  </ItemGroup>
</Project>

================================================
FILE: NanaRun.IconResource/NanaRun.IconResource.h
================================================
/*
 * PROJECT:    NanaRun
 * FILE:       NanaRun.IconResource.h
 * PURPOSE:    Windows icon resource for NanaRun
 *
 * LICENSE:    The MIT License
 *
 * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)
 */

#define IDI_NANARUN                       101


================================================
FILE: NanaRun.IconResource/NanaRun.IconResource.props
================================================
<?xml version="1.0" encoding="utf-8"?>
<!--
  PROJECT:    NanaRun
  FILE:       NanaRun.IconResource.props
  PURPOSE:    Windows icon resource for NanaRun

  LICENSE:    The MIT License

  MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <IncludePath>$(MSBuildThisFileDirectory);$(IncludePath)</IncludePath>
  </PropertyGroup>
  <Target Name="NanaRunBuildIconResource" BeforeTargets="BeforeResourceCompile">
    <ItemGroup>
      <ResourceCompile Include="$(MSBuildThisFileDirectory)NanaRun.IconResource.rc" />
    </ItemGroup>
  </Target>
</Project>

================================================
FILE: NanaRun.slnx
================================================
<Solution>
  <Configurations>
    <Platform Name="ARM64" />
    <Platform Name="x64" />
    <Platform Name="x86" />
  </Configurations>
  <Project Path="MinSudo/MinSudo.vcxproj" Id="99fa5072-6c05-4027-8c8b-ea3ec9bcf9e0" />
  <Project Path="NanaRun/NanaRun.vcxproj" Id="3d1a07c8-17b2-4e5f-aac1-16be522bd4d7" />
  <Project Path="SynthRdp/SynthRdp.vcxproj" Id="abfd05c2-4673-49ec-a23e-9ca53223eec2" />
  <Project Path="VirtualSmb/VirtualSmb.vcxproj" Id="0a6fbd98-1210-4b36-a031-3e2d57e89de3" />
</Solution>


================================================
FILE: ReadMe.md
================================================
# ![NanaRun](Assets/NanaRun.png) NanaRun

Application runtime environment customization utility

## Development Status of Components

- [x] MinSudo
- [x] SynthRdp
- [ ] NanaEAM
- [ ] NanaKit
- [ ] NanaRun (Console)
- [ ] NanaRun (SDK)

## System Requirements

- MinSudo
  - Supported OS: Windows Vista RTM (Build 6000.16386) or later
  - Supported Platforms: x86 (32-bit and 64-bit) and ARM (64-bit)

- SynthRdp
  - Supported OS: Windows XP RTM (Build 2600) or later
  - Supported Platforms: x86 (32-bit and 64-bit) and ARM (64-bit)

## MinSudo

MinSudo is a lightweight POSIX-style Sudo implementation for Windows.

It makes user possible to use elevated console apps in non-elevated consoles.

For safety, the implementation uses the UAC for elevation and don't support
credential cache. It also don't use homemade Windows service and any IPC 
infrastructures.

Here is the usage.

```
Format: MinSudo [Options] Command

Options:

  --NoLogo, -NoL
    Suppress copyright message.

  --Verbose, -V
    Show detailed information.

  --WorkDir=[Path], -WD=[Path]
    Set working directory.

  --System, -S
    Run as System instead of Administrator.

  --TrustedInstaller, -TI
    Run as TrustedInstaller instead of Administrator.

  --Privileged, -P
    Enable all privileges.

  --Version, -Ver
    Show version information.

  /?, -H, --Help
    Show this content.

Notes:

  - All command options are case-insensitive.
  - MinSudo will execute "cmd.exe" if you don't specify another command.
  - You can use the "/" or "--" override "-" and use the "=" override ":" in 
    the command line parameters. For example, "/Option:Value" and 
    "-Option=Value" are equivalent.

Example:

  If you want to run "whoami /all" as elevated in the non-elevated Console, and
  you don't want to show version information of MinSudo.
  > MinSudo --NoLogo whoami /all
```

## SynthRdp

SynthRdp is a Hyper-V Enhanced Session Proxy Service for Windows, which can
redirect RDP over VMBus pipe to any RDP over TCP socket, because the Hyper-V
Enhanced Session is actually the RDP connection over the VMBus pipe.

### Features

- Make Hyper-V virtual machines with Windows 8 and earlier guest OSes support
  Hyper-V Enhanced Session mode.
- Act as a proxy service to make Hyper-V virtual machines with non-Windows
  guest OSes support Hyper-V Enhanced Session mode.

### Usage (Quick Start)

- Move SynthRdp.exe to "%SystemDrive%\Windows\System32" folder in your virtual
  machine which needs to use SynthRdp. The platform of SynthRdp.exe needs to be
  the same as the virtual machine guest OS.
- Open the Command Prompt as Administrator and execute the following commands.
  ```
  SynthRdp Install
  SynthRdp Config Set DisableRemoteDesktop False
  SynthRdp Config Set EnableUserAuthentication False
  SynthRdp Config Set DisableBlankPassword False
  ```

### Usage (Detailed)

```
Format: SynthRdp [Command] <Option1> <Option2> ...

Commands:

  Help - Show this content.

  Install - Install SynthRdp service.
  Uninstall - Uninstall SynthRdp service.
  Start - Start SynthRdp service.
  Stop - Stop SynthRdp service.

  Config List - List all configurations related to SynthRdp.
  Config Set [Key] <Value> - Set the specific configuration
                             with the specific value, or reset
                             the specific configuration if you
                             don't specify the value.

Configuration Keys:

  DisableRemoteDesktop <True|False>
    Set False to enable the remote desktop for this virtual
    machine. The default setting is True. Remote Desktop is
    necessary for the Hyper-V Enhanced Session because it is
    actually the RDP connection over the VMBus pipe.
  EnableUserAuthentication <True|False>
    Set False to allow connections without Network Level
    Authentication. The default setting is True. Set this
    configuration option False is necessary for using the
    Hyper-V Enhanced Session via the SynthRdp service.
  DisableBlankPassword <True|False>
    Set False to enable the usage of logging on this virtual
    machine as the account with the blank password via remote
    desktop. The default setting is True. Set this
    configuration option False will make you use the Hyper-V
    Enhanced Session via the SynthRdp service happier, but
    compromise the security.
  OverrideSystemImplementation <True|False>
    Set True to use the Hyper-V Enhanced Session via the
    SynthRdp service on Windows 8.1 / Server 2012 R2 or later
    guests which have the built-in Hyper-V Enhanced Session
    support for this virtual machine. The default setting is
    False. You can set this configuration option True if you
    want to use your current virtual machine as the Hyper-V
    Enhanced Session proxy server. You need to reboot your
    virtual machine for applying this configuration option
    change.
  ServerHost <Host>
    Set the server host for the remote desktop connection you
    want to use in the Hyper-V Enhanced Session. The default
    setting is 127.0.0.1.
  ServerPort <Port>
    Set the server port for the remote desktop connection you
    want to use in the Hyper-V Enhanced Session. The default
    setting is 3389.

Notes:
  - All command options are case-insensitive.
  - SynthRdp will run as a console application instead of
    service if you don't specify another command.

Examples:

  SynthRdp Install
  SynthRdp Uninstall
  SynthRdp Start
  SynthRdp Stop

  SynthRdp Config List

  SynthRdp Config Set DisableRemoteDesktop False
  SynthRdp Config Set EnableUserAuthentication False
  SynthRdp Config Set DisableBlankPassword False
  SynthRdp Config Set OverrideSystemImplementation False
  SynthRdp Config Set ServerHost 127.0.0.1
  SynthRdp Config Set ServerPort 3389

  SynthRdp Config Set DisableRemoteDesktop
  SynthRdp Config Set EnableUserAuthentication
  SynthRdp Config Set DisableBlankPassword
  SynthRdp Config Set OverrideSystemImplementation
  SynthRdp Config Set ServerHost
  SynthRdp Config Set ServerPort
```

### Suggestions

- Users should use the SynthRdp to connect to Windows Vista or later guests for
  decent user experiences.


================================================
FILE: SynthRdp/AutoRun.inf
================================================
[autorun]
open=SynthRdpInstaller.exe
icon=SynthRdpInstaller.exe
label=Hyper-V Enhanced Session Proxy Service (SynthRdp)

================================================
FILE: SynthRdp/SynthRdp.cpp
================================================
/*
 * PROJECT:    NanaRun
 * FILE:       SynthRdp.cpp
 * PURPOSE:    Implementation for Hyper-V Enhanced Session Proxy Service
 *
 * LICENSE:    The MIT License
 *
 * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)
 */

#define _WINSOCKAPI_
#include <Windows.h>

#include <WinSock2.h>
#include <WS2tcpip.h>
#pragma comment(lib, "Ws2_32.lib")

#include <Mile.Helpers.CppBase.h>

#include <Mile.HyperV.VMBus.h>
#include <Mile.HyperV.Windows.VMBusPipe.h>

#include <Mile.Project.Version.h>

EXTERN_C HANDLE WINAPI VmbusPipeClientTryOpenChannel(
    _In_ LPCGUID InterfaceType,
    _In_ LPCGUID InterfaceInstance,
    _In_ DWORD TimeoutInMsec,
    _In_ DWORD OpenMode)
{
    VMBUS_PIPE_CHANNEL_INFO ChannelInfo = { 0 };
    if (::VmbusPipeClientWaitChannel(
        InterfaceType,
        InterfaceInstance,
        TimeoutInMsec,
        &ChannelInfo))
    {
        return ::VmbusPipeClientOpenChannel(
            &ChannelInfo,
            OpenMode);
    }

    return INVALID_HANDLE_VALUE;
}

namespace
{
    static SERVICE_STATUS_HANDLE volatile g_ServiceStatusHandle = nullptr;
    static bool volatile g_ServiceIsRunning = true;
    static bool volatile g_InteractiveMode = false;
}

SOCKET SynthRdpConnectToServer()
{
    SOCKET Result = INVALID_SOCKET;

    std::string ServerHost = "127.0.0.1";
    {
        std::wstring Buffer(32767, L'\0');
        DWORD Length = static_cast<DWORD>(Buffer.size());
        if (ERROR_SUCCESS == ::RegGetValueW(
            HKEY_LOCAL_MACHINE,
            L"SYSTEM\\CurrentControlSet\\Services\\"
            L"SynthRdp\\Configurations",
            L"ServerHost",
            RRF_RT_REG_SZ | RRF_SUBKEY_WOW6464KEY,
            nullptr,
            const_cast<wchar_t*>(Buffer.c_str()),
            &Length))
        {
            Buffer.resize(std::wcslen(Buffer.c_str()));
            ServerHost = Mile::ToString(CP_UTF8, Buffer);
        }
    }

    std::string ServerPort = "3389";
    {
        DWORD Data = 0;
        DWORD Length = sizeof(DWORD);
        if (ERROR_SUCCESS == ::RegGetValueW(
            HKEY_LOCAL_MACHINE,
            L"SYSTEM\\CurrentControlSet\\Services\\"
            L"SynthRdp\\Configurations",
            L"ServerPort",
            RRF_RT_REG_DWORD | RRF_SUBKEY_WOW6464KEY,
            nullptr,
            &Data,
            &Length))
        {
            ServerPort = Mile::FormatString("%hu", Data);
        }
    }

    int LastError = 0;

    addrinfo AddressHints = { 0 };
    AddressHints.ai_family = AF_INET;
    AddressHints.ai_socktype = SOCK_STREAM;
    AddressHints.ai_protocol = IPPROTO_TCP;
    addrinfo* AddressInfo = nullptr;
    LastError = ::getaddrinfo(
        ServerHost.c_str(),
        ServerPort.c_str(),
        &AddressHints,
        &AddressInfo);
    if (0 == LastError)
    {
        for (addrinfo* Current = AddressInfo;
            nullptr != Current;
            Current = Current->ai_next)
        {
            SOCKET Socket = ::WSASocketW(
                Current->ai_family,
                Current->ai_socktype,
                Current->ai_protocol,
                nullptr,
                0,
                WSA_FLAG_OVERLAPPED);
            if (INVALID_SOCKET == Socket)
            {
                LastError = ::WSAGetLastError();
                continue;
            }

            if (SOCKET_ERROR != ::WSAConnect(
                Socket,
                Current->ai_addr,
                static_cast<int>(Current->ai_addrlen),
                nullptr,
                nullptr,
                nullptr,
                nullptr))
            {
                Result = Socket;
                break;
            }

            LastError = ::WSAGetLastError();
            ::closesocket(Socket);
        }

        ::freeaddrinfo(AddressInfo);
    }

    if (INVALID_SOCKET == Result && 0 != LastError)
    {
        ::WSASetLastError(LastError);
    }

    return Result;
}

struct SynthRdpServiceConnectionContext
{
    std::uint8_t SendBuffer[16384];
    std::uint8_t RecvBuffer[16384];
};

void SynthRdpRedirectionWorker(
    _In_ HANDLE PipeHandle)
{
    SOCKET Socket = INVALID_SOCKET;
    SynthRdpServiceConnectionContext* Context = nullptr;

    do
    {
        Socket = ::SynthRdpConnectToServer();
        if (Socket == INVALID_SOCKET)
        {
            if (g_InteractiveMode)
            {
                std::printf(
                    "[Error] SynthRdpConnectToServer failed (%d).\n",
                    ::WSAGetLastError());
            }
            break;
        }

        Context = reinterpret_cast<SynthRdpServiceConnectionContext*>(
            ::MileAllocateMemory(sizeof(SynthRdpServiceConnectionContext)));
        if (!Context)
        {
            if (g_InteractiveMode)
            {
                std::printf(
                    "[Error] MileAllocateMemory failed.\n");
            }
            break;
        }

        // X.224 Connection Request PDU (Patched)
        {
            DWORD NumberOfBytesRead = 0;
            if (!::MileReadFile(
                PipeHandle,
                Context->SendBuffer,
                static_cast<DWORD>(sizeof(Context->SendBuffer)),
                &NumberOfBytesRead))
            {
                if (g_InteractiveMode)
                {
                    std::printf(
                        "[Error] MileReadFile failed (%d).\n",
                        ::GetLastError());
                }
                break;
            }

            // Set requestedProtocols to PROTOCOL_RDP (0x00000000).
            Context->SendBuffer[15] = 0x00;

            if (g_InteractiveMode)
            {
                std::wprintf(
                    L"[Info] MileSocketSend: %d Bytes.\n",
                    NumberOfBytesRead);
            }

            DWORD NumberOfBytesSent = 0;
            DWORD Flags = 0;
            if (!::MileSocketSend(
                Socket,
                Context->SendBuffer,
                NumberOfBytesRead,
                &NumberOfBytesSent,
                Flags))
            {
                if (g_InteractiveMode)
                {
                    std::printf(
                        "[Error] MileSocketSend failed (%d).\n",
                        ::WSAGetLastError());
                }
                break;
            }
        }

        bool volatile ShouldRunning = true;

        HANDLE Vmbus2TcpThread = Mile::CreateThread([&]()
        {
            for (; ShouldRunning && g_ServiceIsRunning;)
            {
                DWORD NumberOfBytesRead = 0;
                if (!::MileReadFile(
                    PipeHandle,
                    Context->SendBuffer,
                    static_cast<DWORD>(sizeof(Context->SendBuffer)),
                    &NumberOfBytesRead))
                {
                    if (g_InteractiveMode)
                    {
                        std::printf(
                            "[Error] MileReadFile failed (%d).\n",
                            ::GetLastError());
                    }
                    break;
                }

                if (g_InteractiveMode)
                {
                    std::printf(
                        "[Info] MileSocketSend: %d Bytes.\n",
                        NumberOfBytesRead);
                }

                DWORD NumberOfBytesSent = 0;
                DWORD Flags = 0;
                if (!::MileSocketSend(
                    Socket,
                    Context->SendBuffer,
                    NumberOfBytesRead,
                    &NumberOfBytesSent,
                    Flags))
                {
                    if (g_InteractiveMode)
                    {
                        std::printf(
                            "[Error] MileSocketSend failed (%d).\n",
                            ::WSAGetLastError());
                    }
                    break;
                }
            }
        });

        HANDLE Tcp2VmbusThread = Mile::CreateThread([&]()
        {
            for (; ShouldRunning && g_ServiceIsRunning;)
            {
                DWORD NumberOfBytesRecvd = 0;
                DWORD Flags = MSG_PARTIAL;
                if (!::MileSocketRecv(
                    Socket,
                    Context->RecvBuffer,
                    static_cast<DWORD>(sizeof(Context->RecvBuffer)),
                    &NumberOfBytesRecvd,
                    &Flags))
                {
                    if (g_InteractiveMode)
                    {
                        std::printf(
                            "[Error] MileSocketRecv failed (%d).\n",
                            ::WSAGetLastError());
                    }
                    break;
                }

                if (g_InteractiveMode)
                {
                    std::printf(
                        "[Info] MileWriteFile: %d Bytes.\n",
                        NumberOfBytesRecvd);
                }

                DWORD NumberOfBytesWritten = 0;
                if (!::MileWriteFile(
                    PipeHandle,
                    Context->RecvBuffer,
                    NumberOfBytesRecvd,
                    &NumberOfBytesWritten))
                {
                    if (g_InteractiveMode)
                    {
                        std::printf(
                            "[Error] MileWriteFile failed (%d).\n",
                            ::GetLastError());
                    }
                    break;
                }
            }
        });

        for (;;)
        {
            if (WAIT_TIMEOUT != ::WaitForSingleObject(
                Vmbus2TcpThread,
                100))
            {
                ShouldRunning = false;
                break;
            }

            if (WAIT_TIMEOUT != ::WaitForSingleObject(
                Tcp2VmbusThread,
                100))
            {
                ShouldRunning = false;
                break;
            }
        }

        if (Vmbus2TcpThread)
        {
            ::CloseHandle(Vmbus2TcpThread);
            Vmbus2TcpThread = nullptr;
        }

        if (Tcp2VmbusThread)
        {
            ::CloseHandle(Tcp2VmbusThread);
            Tcp2VmbusThread = nullptr;
        }

    } while (false);

    if (Context)
    {
        ::MileFreeMemory(Context);
    }

    if (Socket != INVALID_SOCKET)
    {
        ::closesocket(Socket);
    }
}

DWORD SynthRdpMain()
{
    WSADATA WSAData = { 0 };
    {
        int WSAError = ::WSAStartup(MAKEWORD(2, 2), &WSAData);
        if (NO_ERROR != WSAError)
        {
            if (g_InteractiveMode)
            {
                std::printf(
                    "[Error] WSAStartup failed (%d).\n",
                    WSAError);
            }
            return WSAError;
        }
    }

    DWORD Error = ERROR_SUCCESS;

    HANDLE ControlChannelHandle = INVALID_HANDLE_VALUE;

    do
    {
        ControlChannelHandle = ::VmbusPipeClientTryOpenChannel(
            &SYNTHRDP_CONTROL_CLASS_ID,
            &SYNTHRDP_CONTROL_INSTANCE_ID,
            INFINITE,
            FILE_FLAG_OVERLAPPED);
        if (INVALID_HANDLE_VALUE == ControlChannelHandle)
        {
            Error = ::GetLastError();
            if (g_InteractiveMode)
            {
                std::printf(
                    "[Error] VmbusPipeClientTryOpenChannel failed (%d).\n",
                    Error);
            }
            break;
        }

        SYNTHRDP_VERSION_REQUEST_MESSAGE Request;
        std::memset(
            &Request,
            0,
            sizeof(SYNTHRDP_VERSION_REQUEST_MESSAGE));
        Request.Header.Type = SynthrdpVersionRequest;
        Request.Header.Size = 0;
        Request.Version.AsDWORD = SYNTHRDP_VERSION_WINBLUE;
        Request.Reserved = 0;
        DWORD NumberOfBytesWritten = 0;
        if (!::MileWriteFile(
            ControlChannelHandle,
            &Request,
            sizeof(Request),
            &NumberOfBytesWritten))
        {
            Error = ::GetLastError();
            if (g_InteractiveMode)
            {
                std::printf(
                    "[Error] MileWriteFile failed (%d).\n",
                    Error);
            }
            break;
        }

        if (sizeof(SYNTHRDP_VERSION_REQUEST_MESSAGE) != NumberOfBytesWritten)
        {
            Error = ERROR_INVALID_DATA;
            if (g_InteractiveMode)
            {
                std::printf(
                    "[Error] SYNTHRDP_VERSION_REQUEST_MESSAGE Invalid.\n");
            }
            break;
        }

        SYNTHRDP_VERSION_RESPONSE_MESSAGE Response;
        std::memset(
            &Response,
            0,
            sizeof(SYNTHRDP_VERSION_RESPONSE_MESSAGE));
        DWORD NumberOfBytesRead = 0;
        if (!::MileReadFile(
            ControlChannelHandle,
            &Response,
            sizeof(Response),
            &NumberOfBytesRead))
        {
            Error = ::GetLastError();
            if (g_InteractiveMode)
            {
                std::printf(
                    "[Error] MileReadFile failed (%d).\n",
                    Error);
            }
            break;
        }

        if (sizeof(SYNTHRDP_VERSION_RESPONSE_MESSAGE) != NumberOfBytesRead ||
            SYNTHRDP_TRUE_WITH_VERSION_EXCHANGE != Response.IsAccepted)
        {
            Error = ERROR_INVALID_DATA;
            if (g_InteractiveMode)
            {
                std::printf(
                    "[Error] SYNTHRDP_VERSION_RESPONSE_MESSAGE Invalid.\n");
            }
            break;
        }

        GUID Instances[] =
        {
            SYNTHRDP_DATA_INSTANCE_ID_1,
            SYNTHRDP_DATA_INSTANCE_ID_2,
            SYNTHRDP_DATA_INSTANCE_ID_3,
            SYNTHRDP_DATA_INSTANCE_ID_4,
            SYNTHRDP_DATA_INSTANCE_ID_5
        };
        for (size_t i = 0; g_ServiceIsRunning; ++i)
        {
            HANDLE DataChannelHandle = ::VmbusPipeClientTryOpenChannel(
                &SYNTHRDP_DATA_CLASS_ID,
                &Instances[i % (sizeof(Instances) / sizeof(*Instances))],
                50,
                FILE_FLAG_OVERLAPPED);
            if (INVALID_HANDLE_VALUE == DataChannelHandle)
            {
                continue;
            }

            ::SynthRdpRedirectionWorker(DataChannelHandle);

            ::CloseHandle(DataChannelHandle);
        }

    } while (false);

    if (INVALID_HANDLE_VALUE != ControlChannelHandle)
    {
        ::CloseHandle(ControlChannelHandle);
    }

    ::WSACleanup();

    return Error;
}

namespace
{
    std::wstring GetCurrentProcessModulePath()
    {
        // 32767 is the maximum path length without the terminating null
        // character.
        std::wstring Path(32767, L'\0');
        Path.resize(::GetModuleFileNameW(
            nullptr, &Path[0], static_cast<DWORD>(Path.size())));
        return Path;
    }

    static std::wstring g_ServiceName =
        L"SynthRdp";
    static std::wstring g_DisplayName =
        L"Hyper-V Enhanced Session Proxy Service";
}

void WINAPI SynthRdpServiceHandler(
    _In_ DWORD dwControl)
{
    switch (dwControl)
    {
    case SERVICE_CONTROL_STOP:
    {
        SERVICE_STATUS ServiceStatus = { 0 };
        ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
        ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
        ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
        ServiceStatus.dwWin32ExitCode = ERROR_SUCCESS;
        ServiceStatus.dwServiceSpecificExitCode = 0;
        ServiceStatus.dwCheckPoint = 0;
        ServiceStatus.dwWaitHint = 0;
        ::SetServiceStatus(g_ServiceStatusHandle, &ServiceStatus);

        g_ServiceIsRunning = false;

        break;
    }
    default:
        break;
    }
}

void WINAPI SynthRdpServiceMain(
    _In_ DWORD dwNumServicesArgs,
    _In_ LPWSTR* lpServiceArgVectors)
{
    UNREFERENCED_PARAMETER(dwNumServicesArgs);
    UNREFERENCED_PARAMETER(lpServiceArgVectors);

    g_ServiceStatusHandle = ::RegisterServiceCtrlHandlerW(
        g_ServiceName.c_str(),
        ::SynthRdpServiceHandler);
    if (g_ServiceStatusHandle)
    {
        SERVICE_STATUS ServiceStatus = { 0 };
        ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
        ServiceStatus.dwCurrentState = SERVICE_RUNNING;
        ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
        ServiceStatus.dwWin32ExitCode = ERROR_SUCCESS;
        ServiceStatus.dwServiceSpecificExitCode = 0;
        ServiceStatus.dwCheckPoint = 0;
        ServiceStatus.dwWaitHint = 0;
        if (::SetServiceStatus(g_ServiceStatusHandle, &ServiceStatus))
        {
            ServiceStatus.dwCurrentState = SERVICE_STOPPED;
            ServiceStatus.dwControlsAccepted = 0;
            ServiceStatus.dwWin32ExitCode = ::SynthRdpMain();
            ::SetServiceStatus(g_ServiceStatusHandle, &ServiceStatus);
        }
    }
}

int SynthRdpInstallService()
{
    DWORD Error = ERROR_SUCCESS;

    std::wstring ServiceBinaryPath =
        ::GetCurrentProcessModulePath() + L" Service";

    SC_HANDLE ServiceControlManagerHandle = ::OpenSCManagerW(
        nullptr,
        nullptr,
        SC_MANAGER_CONNECT | SC_MANAGER_CREATE_SERVICE);
    if (ServiceControlManagerHandle)
    {
        SC_HANDLE ServiceHandle = ::CreateServiceW(
            ServiceControlManagerHandle,
            g_ServiceName.c_str(),
            g_DisplayName.c_str(),
            SERVICE_QUERY_STATUS | SERVICE_START,
            SERVICE_WIN32_OWN_PROCESS,
            SERVICE_AUTO_START,
            SERVICE_ERROR_NORMAL,
            ServiceBinaryPath.c_str(),
            nullptr,
            nullptr,
            nullptr,
            nullptr,
            nullptr);
        if (ServiceHandle)
        {
            SERVICE_STATUS_PROCESS ServiceStatus = { 0 };
            if (!::MileStartServiceByHandle(
                ServiceHandle,
                0,
                nullptr,
                &ServiceStatus))
            {
                Error = ::GetLastError();
            }

            ::CloseServiceHandle(ServiceHandle);
        }
        else
        {
            Error = ::GetLastError();
        }

        ::CloseServiceHandle(ServiceControlManagerHandle);
    }
    else
    {
        Error = ::GetLastError();
    }

    if (ERROR_SUCCESS == Error)
    {
        std::printf("[Success] SynthRdpInstallService\n");
    }
    else
    {
        std::printf("[Error] SynthRdpInstallService (%d)\n", Error);
    }

    return Error;
}

int SynthRdpUninstallService()
{
    DWORD Error = ERROR_SUCCESS;

    SC_HANDLE ServiceControlManagerHandle = ::OpenSCManagerW(
        nullptr,
        nullptr,
        SC_MANAGER_CONNECT);
    if (ServiceControlManagerHandle)
    {
        SC_HANDLE ServiceHandle = ::OpenServiceW(
            ServiceControlManagerHandle,
            g_ServiceName.c_str(),
            SERVICE_QUERY_STATUS | SERVICE_STOP | DELETE);
        if (ServiceHandle)
        {
            SERVICE_STATUS_PROCESS ServiceStatus = { 0 };
            if (::MileStopServiceByHandle(ServiceHandle, &ServiceStatus))
            {
                if (!::DeleteService(ServiceHandle))
                {
                    Error = ::GetLastError();
                }
            }
            else
            {
                Error = ::GetLastError();
            }

            ::CloseServiceHandle(ServiceHandle);
        }
        else
        {
            Error = ::GetLastError();
        }

        ::CloseServiceHandle(ServiceControlManagerHandle);
    }
    else
    {
        Error = ::GetLastError();
    }

    if (ERROR_SUCCESS == Error)
    {
        std::printf("[Success] SynthRdpUninstallService\n");
    }
    else
    {
        std::printf("[Error] SynthRdpUninstallService (%d)\n", Error);
    }

    return Error;
}

int SynthRdpStartService()
{
    DWORD Error = ERROR_SUCCESS;

    SERVICE_STATUS_PROCESS ServiceStatus = { 0 };
    if (!::MileStartService(g_ServiceName.c_str(), &ServiceStatus))
    {
        Error = ::GetLastError();
    }

    if (ERROR_SUCCESS == Error)
    {
        std::printf("[Success] SynthRdpStartService\n");
    }
    else
    {
        std::printf("[Error] SynthRdpStartService (%d)\n", Error);
    }

    return Error;
}

int SynthRdpStopService()
{
    DWORD Error = ERROR_SUCCESS;

    SERVICE_STATUS_PROCESS ServiceStatus = { 0 };
    if (!::MileStopService(g_ServiceName.c_str(), &ServiceStatus))
    {
        Error = ::GetLastError();
    }

    if (ERROR_SUCCESS == Error)
    {
        std::printf("[Success] SynthRdpStopService\n");
    }
    else
    {
        std::printf("[Error] SynthRdpStopService (%d)\n", Error);
    }

    return Error;
}

int SynthRdpListConfigurations()
{
    DWORD Error = ERROR_SUCCESS;

    DWORD Data = 0;
    DWORD Length = 0;

    bool DisableRemoteDesktop = false;
    {
        Data = 0;
        Length = sizeof(DWORD);
        Error = ::RegGetValueW(
            HKEY_LOCAL_MACHINE,
            L"SYSTEM\\CurrentControlSet\\Control\\Terminal Server",
            L"fDenyTSConnections",
            RRF_RT_REG_DWORD | RRF_SUBKEY_WOW6464KEY,
            nullptr,
            &Data,
            &Length);
        if (ERROR_SUCCESS == Error)
        {
            DisableRemoteDesktop = Data;
        }
    }

    bool EnableUserAuthentication = true;
    {
        Data = 0;
        Length = sizeof(DWORD);
        Error = ::RegGetValueW(
            HKEY_LOCAL_MACHINE,
            L"SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\"
            L"WinStations\\RDP-Tcp",
            L"UserAuthentication",
            RRF_RT_REG_DWORD | RRF_SUBKEY_WOW6464KEY,
            nullptr,
            &Data,
            &Length);
        if (ERROR_SUCCESS == Error)
        {
            EnableUserAuthentication = Data;
        }
    }

    bool DisableBlankPassword = false;
    {
        Data = 0;
        Length = sizeof(DWORD);
        Error = ::RegGetValueW(
            HKEY_LOCAL_MACHINE,
            L"SYSTEM\\CurrentControlSet\\Control\\Lsa",
            L"LimitBlankPasswordUse",
            RRF_RT_REG_DWORD | RRF_SUBKEY_WOW6464KEY,
            nullptr,
            &Data,
            &Length);
        if (ERROR_SUCCESS == Error)
        {
            DisableBlankPassword = Data;
        }
    }

    bool OverrideSystemImplementation = false;
    {
        Data = 0;
        Length = sizeof(DWORD);
        Error = ::RegGetValueW(
            HKEY_LOCAL_MACHINE,
            L"SOFTWARE\\Microsoft\\Virtual Machine\\Guest",
            L"DisableEnhancedSessionConsoleConnection",
            RRF_RT_REG_DWORD | RRF_SUBKEY_WOW6464KEY,
            nullptr,
            &Data,
            &Length);
        if (ERROR_SUCCESS == Error)
        {
            OverrideSystemImplementation = Data;
        }
    }

    std::string ServerHost = "127.0.0.1";
    {
        std::wstring Buffer(32767, L'\0');

        Length = static_cast<DWORD>(Buffer.size());
        Error = ::RegGetValueW(
            HKEY_LOCAL_MACHINE,
            L"SYSTEM\\CurrentControlSet\\Services\\"
            L"SynthRdp\\Configurations",
            L"ServerHost",
            RRF_RT_REG_SZ | RRF_SUBKEY_WOW6464KEY,
            nullptr,
            const_cast<wchar_t*>(Buffer.c_str()),
            &Length);
        if (ERROR_SUCCESS == Error)
        {
            Buffer.resize(std::wcslen(Buffer.c_str()));
            ServerHost = Mile::ToString(CP_UTF8, Buffer);
        }
    }

    std::uint16_t ServerPort = 3389;
    {
        Data = 0;
        Length = sizeof(DWORD);
        Error = ::RegGetValueW(
            HKEY_LOCAL_MACHINE,
            L"SYSTEM\\CurrentControlSet\\Services\\"
            L"SynthRdp\\Configurations",
            L"ServerPort",
            RRF_RT_REG_DWORD | RRF_SUBKEY_WOW6464KEY,
            nullptr,
            &Data,
            &Length);
        if (ERROR_SUCCESS == Error)
        {
            ServerPort = static_cast<std::uint16_t>(Data);
        }
    }

    std::printf(
        "Configurations:\n"
        "\n"
        "DisableRemoteDesktop: %s\n"
        "EnableUserAuthentication: %s\n"
        "DisableBlankPassword: %s\n"
        "OverrideSystemImplementation: %s\n"
        "ServerHost: %s\n"
        "ServerPort: %hu\n"
        "\n",
        DisableRemoteDesktop ? "True" : "False",
        EnableUserAuthentication ? "True" : "False",
        DisableBlankPassword ? "True" : "False",
        OverrideSystemImplementation ? "True" : "False",
        ServerHost.c_str(),
        ServerPort);

    return Error;
}

int SynthRdpUpdateConfiguration(
    std::string const& Key,
    std::string const& Value)
{
    DWORD Error = ERROR_SUCCESS;

    if (0 == ::_stricmp(Key.c_str(), "DisableRemoteDesktop"))
    {
        DWORD Data = 1;
        if (Value.empty() ||
            0 == ::_stricmp(Value.c_str(), "True"))
        {
            // Use the default value.
        }
        else if (0 == ::_stricmp(Value.c_str(), "False"))
        {
            Data = 0;
        }
        else
        {
            Error = ERROR_INVALID_PARAMETER;
        }

        if (ERROR_SUCCESS == Error)
        {
            Error = ::RegSetKeyValueW(
                HKEY_LOCAL_MACHINE,
                L"SYSTEM\\CurrentControlSet\\Control\\Terminal Server",
                L"fDenyTSConnections",
                REG_DWORD,
                &Data,
                sizeof(DWORD));
        }
    }
    else if (0 == ::_stricmp(Key.c_str(), "EnableUserAuthentication"))
    {
        DWORD Data = 1;
        if (Value.empty() ||
            0 == ::_stricmp(Value.c_str(), "True"))
        {
            // Use the default value.
        }
        else if (0 == ::_stricmp(Value.c_str(), "False"))
        {
            Data = 0;
        }
        else
        {
            Error = ERROR_INVALID_PARAMETER;
        }

        if (ERROR_SUCCESS == Error)
        {
            Error = ::RegSetKeyValueW(
                HKEY_LOCAL_MACHINE,
                L"SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\"
                L"WinStations\\RDP-Tcp",
                L"UserAuthentication",
                REG_DWORD,
                &Data,
                sizeof(DWORD));
        }
    }
    else if (0 == ::_stricmp(Key.c_str(), "DisableBlankPassword"))
    {
        DWORD Data = 1;
        if (Value.empty() ||
            0 == ::_stricmp(Value.c_str(), "True"))
        {
            // Use the default value.
        }
        else if (0 == ::_stricmp(Value.c_str(), "False"))
        {
            Data = 0;
        }
        else
        {
            Error = ERROR_INVALID_PARAMETER;
        }

        if (ERROR_SUCCESS == Error)
        {
            Error = ::RegSetKeyValueW(
                HKEY_LOCAL_MACHINE,
                L"SYSTEM\\CurrentControlSet\\Control\\Lsa",
                L"LimitBlankPasswordUse",
                REG_DWORD,
                &Data,
                sizeof(DWORD));
        }
    }
    else if (0 == ::_stricmp(Key.c_str(), "OverrideSystemImplementation"))
    {
        if (Value.empty() ||
            0 == ::_stricmp(Value.c_str(), "False"))
        {
            Error = ::RegDeleteKeyValueW(
                HKEY_LOCAL_MACHINE,
                L"SOFTWARE\\Microsoft\\Virtual Machine\\Guest",
                L"DisableEnhancedSessionConsoleConnection");
        }
        else if (0 == ::_stricmp(Value.c_str(), "True"))
        {
            DWORD Data = 1;
            Error = ::RegSetKeyValueW(
                HKEY_LOCAL_MACHINE,
                L"SOFTWARE\\Microsoft\\Virtual Machine\\Guest",
                L"DisableEnhancedSessionConsoleConnection",
                REG_DWORD,
                &Data,
                sizeof(DWORD));
        }
        else
        {
            Error = ERROR_INVALID_PARAMETER;
        }
    }
    else if (0 == ::_stricmp(Key.c_str(), "ServerHost"))
    {
        if (Value.empty())
        {
            Error = ::RegDeleteKeyValueW(
                HKEY_LOCAL_MACHINE,
                L"SYSTEM\\CurrentControlSet\\Services\\"
                L"SynthRdp\\Configurations",
                L"ServerHost");
        }
        else
        {
            std::wstring ServerHost = Mile::ToWideString(CP_UTF8, Value);

            Error = ::RegSetKeyValueW(
                HKEY_LOCAL_MACHINE,
                L"SYSTEM\\CurrentControlSet\\Services\\"
                L"SynthRdp\\Configurations",
                L"ServerHost",
                REG_SZ,
                ServerHost.c_str(),
                static_cast<DWORD>((ServerHost.size() + 1) * sizeof(wchar_t)));
        }
    }
    else if (0 == ::_stricmp(Key.c_str(), "ServerPort"))
    {
        if (Value.empty())
        {
            Error = ::RegDeleteKeyValueW(
                HKEY_LOCAL_MACHINE,
                L"SYSTEM\\CurrentControlSet\\Services\\SynthRdp\\Configurations",
                L"ServerPort");
        }
        else
        {
            DWORD Data = static_cast<std::uint16_t>(Mile::ToUInt32(Value));
            Error = ::RegSetKeyValueW(
                HKEY_LOCAL_MACHINE,
                L"SYSTEM\\CurrentControlSet\\Services\\SynthRdp\\Configurations",
                L"ServerPort",
                REG_DWORD,
                &Data,
                sizeof(DWORD));
        }
    }
    else
    {
        Error = ERROR_INVALID_PARAMETER;
    }

    if (ERROR_SUCCESS == Error)
    {
        std::printf(
            "[Success] SynthRdpUpdateConfiguration %s\n",
            Key.c_str());
    }
    else
    {
        std::printf(
            "[Error] SynthRdpUpdateConfiguration %s (%d)\n",
            Key.c_str(),
            Error);
    }

    return Error;
}

int main()
{
    ::std::printf(
        "SynthRdp " MILE_PROJECT_VERSION_UTF8_STRING " (Build "
        MILE_PROJECT_MACRO_TO_UTF8_STRING(MILE_PROJECT_VERSION_BUILD) ")" "\n"
        "(c) M2-Team and Contributors. All rights reserved.\n"
        "\n");

    std::vector<std::string> Arguments = Mile::SplitCommandLineString(
        Mile::ToString(CP_UTF8, ::GetCommandLineW()));

    bool NeedParse = (Arguments.size() > 1);

    if (!NeedParse)
    {
        g_InteractiveMode = true;

        std::printf(
            "[Info] SynthRdp will run as a console application instead of "
            "service.\n"
            "[Info] Use \"SynthRdp Help\" for more commands.\n"
            "\n");

        return ::SynthRdpMain();
    }

    int Result = 0;

    bool ParseError = false;
    bool ShowHelp = false;

    if (0 == ::_stricmp(Arguments[1].c_str(), "Help"))
    {
        ShowHelp = true;
    }
    else if (0 == ::_stricmp(Arguments[1].c_str(), "Service"))
    {
        ::FreeConsole();

        SERVICE_TABLE_ENTRYW ServiceStartTable[] =
        {
            {
                const_cast<wchar_t*>(g_ServiceName.c_str()),
                ::SynthRdpServiceMain
            }
        };

        return ::StartServiceCtrlDispatcherW(ServiceStartTable)
            ? ERROR_SUCCESS :
            ::GetLastError();
    }
    else if (0 == ::_stricmp(Arguments[1].c_str(), "Install"))
    {
        Result = ::SynthRdpInstallService();
    }
    else if (0 == ::_stricmp(Arguments[1].c_str(), "Uninstall"))
    {
        Result = ::SynthRdpUninstallService();
    }
    else if (0 == ::_stricmp(Arguments[1].c_str(), "Start"))
    {
        Result = ::SynthRdpStartService();
    }
    else if (0 == ::_stricmp(Arguments[1].c_str(), "Stop"))
    {
        Result = ::SynthRdpStopService();
    }
    else if (0 == ::_stricmp(Arguments[1].c_str(), "Config"))
    {
        ParseError = !(Arguments.size() > 2);
        if (!ParseError)
        {
            if (0 == ::_stricmp(Arguments[2].c_str(), "List"))
            {
                Result = ::SynthRdpListConfigurations();
            }
            else if (0 == ::_stricmp(Arguments[2].c_str(), "Set"))
            {
                ParseError = !(Arguments.size() > 3);
                if (!ParseError)
                {
                    Result = ::SynthRdpUpdateConfiguration(
                        Arguments[3],
                        (Arguments.size() > 4) ? Arguments[4] : std::string());
                }
            }
        }
    }
    else
    {
        ParseError = true;
    }

    if (ParseError)
    {
        std::printf(
            "[Error] Unrecognized command.\n"
            "\n");
    }

    if (ParseError || ShowHelp)
    {
        std::printf(
            "Format: SynthRdp [Command] <Option1> <Option2> ...\n"
            "\n"
            "Commands:\n"
            "\n"
            "  Help - Show this content.\n"
            "\n"
            "  Install - Install SynthRdp service.\n"
            "  Uninstall - Uninstall SynthRdp service.\n"
            "  Start - Start SynthRdp service.\n"
            "  Stop - Stop SynthRdp service.\n"
            "\n"
            "  Config List - List all configurations related to SynthRdp.\n"
            "  Config Set [Key] <Value> - Set the specific configuration\n"
            "                             with the specific value, or reset\n"
            "                             the specific configuration if you\n"
            "                             don't specify the value.\n"
            "\n"
            "Configuration Keys:\n"
            "\n"
            "  DisableRemoteDesktop <True|False>\n"
            "    Set False to enable the remote desktop for this virtual\n"
            "    machine. The default setting is True. Remote Desktop is\n"
            "    necessary for the Hyper-V Enhanced Session because it is\n"
            "    actually the RDP connection over the VMBus pipe.\n"
            "  EnableUserAuthentication <True|False>\n"
            "    Set False to allow connections without Network Level\n"
            "    Authentication. The default setting is True. Set this\n"
            "    configuration option False is necessary for using the\n"
            "    Hyper-V Enhanced Session via the SynthRdp service.\n"
            "  DisableBlankPassword <True|False>\n"
            "    Set False to enable the usage of logging on this virtual\n"
            "    machine as the account with the blank password via remote\n"
            "    desktop. The default setting is True. Set this\n"
            "    configuration option False will make you use the Hyper-V\n"
            "    Enhanced Session via the SynthRdp service happier, but\n"
            "    compromise the security.\n"
            "  OverrideSystemImplementation <True|False>\n"
            "    Set True to use the Hyper-V Enhanced Session via the\n"
            "    SynthRdp service on Windows 8.1 / Server 2012 R2 or later\n"
            "    guests which have the built-in Hyper-V Enhanced Session\n"
            "    support for this virtual machine. The default setting is\n"
            "    False. You can set this configuration option True if you\n"
            "    want to use your current virtual machine as the Hyper-V\n"
            "    Enhanced Session proxy server. You need to reboot your\n"
            "    virtual machine for applying this configuration option\n"
            "    change.\n"
            "  ServerHost <Host>\n"
            "    Set the server host for the remote desktop connection you\n"
            "    want to use in the Hyper-V Enhanced Session. The default\n"
            "    setting is 127.0.0.1.\n"
            "  ServerPort <Port>\n"
            "    Set the server port for the remote desktop connection you\n"
            "    want to use in the Hyper-V Enhanced Session. The default\n"
            "    setting is 3389.\n"
            "\n"
            "Notes:\n"
            "  - All command options are case-insensitive.\n"
            "  - SynthRdp will run as a console application instead of\n"
            "    service if you don't specify another command.\n"
            "\n"
            "Examples:\n"
            "\n"
            "  SynthRdp Install\n"
            "  SynthRdp Uninstall\n"
            "  SynthRdp Start\n"
            "  SynthRdp Stop\n"
            "\n"
            "  SynthRdp Config List\n"
            "\n"
            "  SynthRdp Config Set DisableRemoteDesktop False\n"
            "  SynthRdp Config Set EnableUserAuthentication False\n"
            "  SynthRdp Config Set DisableBlankPassword False\n"
            "  SynthRdp Config Set OverrideSystemImplementation False\n"
            "  SynthRdp Config Set ServerHost 127.0.0.1\n"
            "  SynthRdp Config Set ServerPort 3389\n"
            "\n"
            "  SynthRdp Config Set DisableRemoteDesktop\n"
            "  SynthRdp Config Set EnableUserAuthentication\n"
            "  SynthRdp Config Set DisableBlankPassword\n"
            "  SynthRdp Config Set OverrideSystemImplementation\n"
            "  SynthRdp Config Set ServerHost\n"
            "  SynthRdp Config Set ServerPort\n"
            "\n");
    }

    return Result;
}


================================================
FILE: SynthRdp/SynthRdp.iss
================================================
; -- 64BitThreeArch.iss --
; Demonstrates how to install a program built for three different
; architectures (x86, x64, Arm64) using a single installer.

; SEE THE DOCUMENTATION FOR DETAILS ON CREATING .ISS SCRIPT FILES!

[Setup]
AppName=Hyper-V Enhanced Session Proxy Service (SynthRdp)
AppVersion=1.0.92.0
AppPublisher=M2-Team
AppPublisherURL=https://github.com/M2Team/NanaRun
WizardStyle=modern
DefaultDirName={autopf}\M2-Team\NanaRun
DefaultGroupName=NanaRun
UninstallDisplayIcon={app}\SynthRdp.exe
Compression=lzma2
SolidCompression=yes
OutputDir=..\Output\SynthRdpInstallationImage
; "ArchitecturesInstallIn64BitMode=x64compatible or arm64" instructs
; Setup to use "64-bit install mode" on x64-compatible systems and
; Arm64 systems, meaning Setup should use the native 64-bit Program
; Files directory and the 64-bit view of the registry. On all other
; OS architectures (e.g., 32-bit x86), Setup will use "32-bit
; install mode".
ArchitecturesInstallIn64BitMode=x64compatible or arm64
SetupLogging=yes
OutputBaseFilename=SynthRdpInstaller

[Files]
; In order of preference, we want to install:
; - Arm64 binaries on Arm64 systems
; - else, x64 binaries on x64-compatible systems
; - else, x86 binaries

; Place all Arm64-specific files here, using 'Check: PreferArm64Files' on each entry.
Source: "..\Output\Binaries\Release\ARM64\SynthRdp.exe"; DestDir: "{sysnative}"; DestName: "SynthRdp.exe"; Check: PreferArm64Files

; Place all x64-specific files here, using 'Check: PreferX64Files' on each entry.
; Only the first entry should include the 'solidbreak' flag.
Source: "..\Output\Binaries\Release\x64\SynthRdp.exe"; DestDir: "{sysnative}"; DestName: "SynthRdp.exe"; Check: PreferX64Files; Flags: solidbreak

; Place all x86-specific files here, using 'Check: PreferX86Files' on each entry.
; Only the first entry should include the 'solidbreak' flag.
Source: "..\Output\Binaries\Release\Win32\SynthRdp.exe"; DestDir: "{sysnative}"; DestName: "SynthRdp.exe"; Check: PreferX86Files; Flags: solidbreak

; Place all common files here.
; Only the first entry should include the 'solidbreak' flag.
;Source: "MyProg.chm"; DestDir: "{app}"; Flags: solidbreak
;Source: "Readme.txt"; DestDir: "{app}"; Flags: isreadme

[Code]

function PreferArm64Files: Boolean;
begin
  Result := IsArm64;
end;

function PreferX64Files: Boolean;
begin
  Result := not PreferArm64Files and IsX64Compatible;
end;

function PreferX86Files: Boolean;
begin
  Result := not PreferArm64Files and not PreferX64Files;
end;

[Run]

Filename: "{sysnative}\SynthRdp.exe"; Parameters: "Uninstall"; Flags: runhidden logoutput
Filename: "{sysnative}\SynthRdp.exe"; Parameters: "Install"; Flags: runhidden logoutput
Filename: "{sysnative}\SynthRdp.exe"; Parameters: "Config Set DisableRemoteDesktop False"; Flags: runhidden logoutput
Filename: "{sysnative}\SynthRdp.exe"; Parameters: "Config Set EnableUserAuthentication False"; Flags: runhidden logoutput
Filename: "{sysnative}\SynthRdp.exe"; Parameters: "Config Set DisableBlankPassword False"; Flags: runhidden logoutput

[UninstallRun]

Filename: "{sysnative}\SynthRdp.exe"; Parameters: "Uninstall"; Flags: runhidden logoutput; RunOnceId: RemoveService

================================================
FILE: SynthRdp/SynthRdp.manifest
================================================
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
	<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
		<application>
			<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
			<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
			<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
			<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
			<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
		</application>
	</compatibility>
</assembly>


================================================
FILE: SynthRdp/SynthRdp.vcxproj
================================================
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup Label="Globals">
    <ProjectGuid>{ABFD05C2-4673-49EC-A23E-9CA53223EEC2}</ProjectGuid>
    <RootNamespace>SynthRdp</RootNamespace>
    <MileProjectType>ConsoleApplication</MileProjectType>
    <MileProjectManifestFile>SynthRdp.manifest</MileProjectManifestFile>
    <MileProjectEnableVCLTLSupport>true</MileProjectEnableVCLTLSupport>
    <MileProjectUseProjectProperties>true</MileProjectUseProjectProperties>
    <MileProjectCompanyName>M2-Team</MileProjectCompanyName>
    <MileProjectFileDescription>Hyper-V Enhanced Session Proxy Service</MileProjectFileDescription>
    <MileProjectInternalName>SynthRdp</MileProjectInternalName>
    <MileProjectLegalCopyright>© M2-Team and Contributors. All rights reserved.</MileProjectLegalCopyright>
    <MileProjectOriginalFilename>SynthRdp.exe</MileProjectOriginalFilename>
    <MileProjectProductName>NanaRun</MileProjectProductName>
    <MileProjectVersion>1.0.$([System.DateTime]::Today.Subtract($([System.DateTime]::Parse('2024-05-01'))).TotalDays).0</MileProjectVersion>
    <MileProjectVersionTag>Preview 3</MileProjectVersionTag>
    <MileHyperVEnableWindowsPlatformSupport>true</MileHyperVEnableWindowsPlatformSupport>
    <WindowsTargetPlatformMinVersion>5.1.2600.0</WindowsTargetPlatformMinVersion>
    <MileWindowsHelpersNoCppWinRTHelpers>true</MileWindowsHelpersNoCppWinRTHelpers>
  </PropertyGroup>
  <Import Sdk="Mile.Project.Configurations" Version="1.0.1917" Project="Mile.Project.Platform.x86.props" />
  <Import Sdk="Mile.Project.Configurations" Version="1.0.1917" Project="Mile.Project.Platform.x64.props" />
  <Import Sdk="Mile.Project.Configurations" Version="1.0.1917" Project="Mile.Project.Platform.ARM64.props" />
  <Import Sdk="Mile.Project.Configurations" Version="1.0.1917" Project="Mile.Project.Cpp.Default.props" />
  <Import Sdk="Mile.Project.Configurations" Version="1.0.1917" Project="Mile.Project.Cpp.props" />
  <Import Project="..\NanaRun.IconResource\NanaRun.IconResource.props" />
  <ItemDefinitionGroup>
    <ClCompile>
      <EnableEnhancedInstructionSet Condition="'$(Platform)'=='Win32'">NoExtensions</EnableEnhancedInstructionSet>
    </ClCompile>
  </ItemDefinitionGroup>
  <ItemGroup>
    <ClCompile Include="SynthRdp.cpp" />
  </ItemGroup>
  <ItemGroup>
    <Manifest Include="SynthRdp.manifest" />
  </ItemGroup>
  <ItemGroup>
    <PackageReference Include="Mile.Windows.Helpers">
      <Version>1.0.1171</Version>
    </PackageReference>
    <PackageReference Include="Mile.HyperV">
      <Version>1.2.907</Version>
    </PackageReference>
  </ItemGroup>
  <ItemGroup>
    <None Include="AutoRun.inf" />
    <None Include="SynthRdp.iss" />
  </ItemGroup>
  <Import Sdk="Mile.Project.Configurations" Version="1.0.1917" Project="Mile.Project.Cpp.targets" />
</Project>

================================================
FILE: Tools/Default.isl
================================================
; *** Inno Setup version 6.1.0+ English messages ***
;
; To download user-contributed translations of this file, go to:
;   https://jrsoftware.org/files/istrans/
;
; Note: When translating this text, do not add periods (.) to the end of
; messages that didn't have them already, because on those messages Inno
; Setup adds the periods automatically (appending a period would result in
; two periods being displayed).

[LangOptions]
; The following three entries are very important. Be sure to read and 
; understand the '[LangOptions] section' topic in the help file.
LanguageName=English
LanguageID=$0409
LanguageCodePage=0
; If the language you are translating to requires special font faces or
; sizes, uncomment any of the following entries and change them accordingly.
;DialogFontName=
;DialogFontSize=8
;WelcomeFontName=Verdana
;WelcomeFontSize=12
;TitleFontName=Arial
;TitleFontSize=29
;CopyrightFontName=Arial
;CopyrightFontSize=8

[Messages]

; *** Application titles
SetupAppTitle=Setup
SetupWindowTitle=Setup - %1
UninstallAppTitle=Uninstall
UninstallAppFullTitle=%1 Uninstall

; *** Misc. common
InformationTitle=Information
ConfirmTitle=Confirm
ErrorTitle=Error

; *** SetupLdr messages
SetupLdrStartupMessage=This will install %1. Do you wish to continue?
LdrCannotCreateTemp=Unable to create a temporary file. Setup aborted
LdrCannotExecTemp=Unable to execute file in the temporary directory. Setup aborted
HelpTextNote=

; *** Startup error messages
LastErrorMessage=%1.%n%nError %2: %3
SetupFileMissing=The file %1 is missing from the installation directory. Please correct the problem or obtain a new copy of the program.
SetupFileCorrupt=The setup files are corrupted. Please obtain a new copy of the program.
SetupFileCorruptOrWrongVer=The setup files are corrupted, or are incompatible with this version of Setup. Please correct the problem or obtain a new copy of the program.
InvalidParameter=An invalid parameter was passed on the command line:%n%n%1
SetupAlreadyRunning=Setup is already running.
WindowsVersionNotSupported=This program does not support the version of Windows your computer is running.
WindowsServicePackRequired=This program requires %1 Service Pack %2 or later.
NotOnThisPlatform=This program will not run on %1.
OnlyOnThisPlatform=This program must be run on %1.
OnlyOnTheseArchitectures=This program can only be installed on versions of Windows designed for the following processor architectures:%n%n%1
WinVersionTooLowError=This program requires %1 version %2 or later.
WinVersionTooHighError=This program cannot be installed on %1 version %2 or later.
AdminPrivilegesRequired=You must be logged in as an administrator when installing this program.
PowerUserPrivilegesRequired=You must be logged in as an administrator or as a member of the Power Users group when installing this program.
SetupAppRunningError=Setup has detected that %1 is currently running.%n%nPlease close all instances of it now, then click OK to continue, or Cancel to exit.
UninstallAppRunningError=Uninstall has detected that %1 is currently running.%n%nPlease close all instances of it now, then click OK to continue, or Cancel to exit.

; *** Startup questions
PrivilegesRequiredOverrideTitle=Select Setup Install Mode
PrivilegesRequiredOverrideInstruction=Select install mode
PrivilegesRequiredOverrideText1=%1 can be installed for all users (requires administrative privileges), or for you only.
PrivilegesRequiredOverrideText2=%1 can be installed for you only, or for all users (requires administrative privileges).
PrivilegesRequiredOverrideAllUsers=Install for &all users
PrivilegesRequiredOverrideAllUsersRecommended=Install for &all users (recommended)
PrivilegesRequiredOverrideCurrentUser=Install for &me only
PrivilegesRequiredOverrideCurrentUserRecommended=Install for &me only (recommended)

; *** Misc. errors
ErrorCreatingDir=Setup was unable to create the directory "%1"
ErrorTooManyFilesInDir=Unable to create a file in the directory "%1" because it contains too many files

; *** Setup common messages
ExitSetupTitle=Exit Setup
ExitSetupMessage=Setup is not complete. If you exit now, the program will not be installed.%n%nYou may run Setup again at another time to complete the installation.%n%nExit Setup?
AboutSetupMenuItem=&About Setup...
AboutSetupTitle=About Setup
AboutSetupMessage=%1 version %2%n%3%n%n%1 home page:%n%4
AboutSetupNote=
TranslatorNote=

; *** Buttons
ButtonBack=< &Back
ButtonNext=&Next >
ButtonInstall=&Install
ButtonOK=OK
ButtonCancel=Cancel
ButtonYes=&Yes
ButtonYesToAll=Yes to &All
ButtonNo=&No
ButtonNoToAll=N&o to All
ButtonFinish=&Finish
ButtonBrowse=&Browse...
ButtonWizardBrowse=B&rowse...
ButtonNewFolder=&Make New Folder

; *** "Select Language" dialog messages
SelectLanguageTitle=Select Setup Language
SelectLanguageLabel=Select the language to use during the installation.

; *** Common wizard text
ClickNext=Click Next to continue, or Cancel to exit Setup.
BeveledLabel=
BrowseDialogTitle=Browse For Folder
BrowseDialogLabel=Select a folder in the list below, then click OK.
NewFolderName=New Folder

; *** "Welcome" wizard page
WelcomeLabel1=Welcome to the [name] Setup Wizard
WelcomeLabel2=This will install [name/ver] on your computer.%n%nIt is recommended that you close all other applications before continuing.

; *** "Password" wizard page
WizardPassword=Password
PasswordLabel1=This installation is password protected.
PasswordLabel3=Please provide the password, then click Next to continue. Passwords are case-sensitive.
PasswordEditLabel=&Password:
IncorrectPassword=The password you entered is not correct. Please try again.

; *** "License Agreement" wizard page
WizardLicense=License Agreement
LicenseLabel=Please read the following important information before continuing.
LicenseLabel3=Please read the following License Agreement. You must accept the terms of this agreement before continuing with the installation.
LicenseAccepted=I &accept the agreement
LicenseNotAccepted=I &do not accept the agreement

; *** "Information" wizard pages
WizardInfoBefore=Information
InfoBeforeLabel=Please read the following important information before continuing.
InfoBeforeClickLabel=When you are ready to continue with Setup, click Next.
WizardInfoAfter=Information
InfoAfterLabel=Please read the following important information before continuing.
InfoAfterClickLabel=When you are ready to continue with Setup, click Next.

; *** "User Information" wizard page
WizardUserInfo=User Information
UserInfoDesc=Please enter your information.
UserInfoName=&User Name:
UserInfoOrg=&Organization:
UserInfoSerial=&Serial Number:
UserInfoNameRequired=You must enter a name.

; *** "Select Destination Location" wizard page
WizardSelectDir=Select Destination Location
SelectDirDesc=Where should [name] be installed?
SelectDirLabel3=Setup will install [name] into the following folder.
SelectDirBrowseLabel=To continue, click Next. If you would like to select a different folder, click Browse.
DiskSpaceGBLabel=At least [gb] GB of free disk space is required.
DiskSpaceMBLabel=At least [mb] MB of free disk space is required.
CannotInstallToNetworkDrive=Setup cannot install to a network drive.
CannotInstallToUNCPath=Setup cannot install to a UNC path.
InvalidPath=You must enter a full path with drive letter; for example:%n%nC:\APP%n%nor a UNC path in the form:%n%n\\server\share
InvalidDrive=The drive or UNC share you selected does not exist or is not accessible. Please select another.
DiskSpaceWarningTitle=Not Enough Disk Space
DiskSpaceWarning=Setup requires at least %1 KB of free space to install, but the selected drive only has %2 KB available.%n%nDo you want to continue anyway?
DirNameTooLong=The folder name or path is too long.
InvalidDirName=The folder name is not valid.
BadDirName32=Folder names cannot include any of the following characters:%n%n%1
DirExistsTitle=Folder Exists
DirExists=The folder:%n%n%1%n%nalready exists. Would you like to install to that folder anyway?
DirDoesntExistTitle=Folder Does Not Exist
DirDoesntExist=The folder:%n%n%1%n%ndoes not exist. Would you like the folder to be created?

; *** "Select Components" wizard page
WizardSelectComponents=Select Components
SelectComponentsDesc=Which components should be installed?
SelectComponentsLabel2=Select the components you want to install; clear the components you do not want to install. Click Next when you are ready to continue.
FullInstallation=Full installation
; if possible don't translate 'Compact' as 'Minimal' (I mean 'Minimal' in your language)
CompactInstallation=Compact installation
CustomInstallation=Custom installation
NoUninstallWarningTitle=Components Exist
NoUninstallWarning=Setup has detected that the following components are already installed on your computer:%n%n%1%n%nDeselecting these components will not uninstall them.%n%nWould you like to continue anyway?
ComponentSize1=%1 KB
ComponentSize2=%1 MB
ComponentsDiskSpaceGBLabel=Current selection requires at least [gb] GB of disk space.
ComponentsDiskSpaceMBLabel=Current selection requires at least [mb] MB of disk space.

; *** "Select Additional Tasks" wizard page
WizardSelectTasks=Select Additional Tasks
SelectTasksDesc=Which additional tasks should be performed?
SelectTasksLabel2=Select the additional tasks you would like Setup to perform while installing [name], then click Next.

; *** "Select Start Menu Folder" wizard page
WizardSelectProgramGroup=Select Start Menu Folder
SelectStartMenuFolderDesc=Where should Setup place the program's shortcuts?
SelectStartMenuFolderLabel3=Setup will create the program's shortcuts in the following Start Menu folder.
SelectStartMenuFolderBrowseLabel=To continue, click Next. If you would like to select a different folder, click Browse.
MustEnterGroupName=You must enter a folder name.
GroupNameTooLong=The folder name or path is too long.
InvalidGroupName=The folder name is not valid.
BadGroupName=The folder name cannot include any of the following characters:%n%n%1
NoProgramGroupCheck2=&Don't create a Start Menu folder

; *** "Ready to Install" wizard page
WizardReady=Ready to Install
ReadyLabel1=Setup is now ready to begin installing [name] on your computer.
ReadyLabel2a=Click Install to continue with the installation, or click Back if you want to review or change any settings.
ReadyLabel2b=Click Install to continue with the installation.
ReadyMemoUserInfo=User information:
ReadyMemoDir=Destination location:
ReadyMemoType=Setup type:
ReadyMemoComponents=Selected components:
ReadyMemoGroup=Start Menu folder:
ReadyMemoTasks=Additional tasks:

; *** TDownloadWizardPage wizard page and DownloadTemporaryFile
DownloadingLabel=Downloading additional files...
ButtonStopDownload=&Stop download
StopDownload=Are you sure you want to stop the download?
ErrorDownloadAborted=Download aborted
ErrorDownloadFailed=Download failed: %1 %2
ErrorDownloadSizeFailed=Getting size failed: %1 %2
ErrorFileHash1=File hash failed: %1
ErrorFileHash2=Invalid file hash: expected %1, found %2
ErrorProgress=Invalid progress: %1 of %2
ErrorFileSize=Invalid file size: expected %1, found %2

; *** "Preparing to Install" wizard page
WizardPreparing=Preparing to Install
PreparingDesc=Setup is preparing to install [name] on your computer.
PreviousInstallNotCompleted=The installation/removal of a previous program was not completed. You will need to restart your computer to complete that installation.%n%nAfter restarting your computer, run Setup again to complete the installation of [name].
CannotContinue=Setup cannot continue. Please click Cancel to exit.
ApplicationsFound=The following applications are using files that need to be updated by Setup. It is recommended that you allow Setup to automatically close these applications.
ApplicationsFound2=The following applications are using files that need to be updated by Setup. It is recommended that you allow Setup to automatically close these applications. After the installation has completed, Setup will attempt to restart the applications.
CloseApplications=&Automatically close the applications
DontCloseApplications=&Do not close the applications
ErrorCloseApplications=Setup was unable to automatically close all applications. It is recommended that you close all applications using files that need to be updated by Setup before continuing.
PrepareToInstallNeedsRestart=Setup must restart your computer. After restarting your computer, run Setup again to complete the installation of [name].%n%nWould you like to restart now?

; *** "Installing" wizard page
WizardInstalling=Installing
InstallingLabel=Please wait while Setup installs [name] on your computer.

; *** "Setup Completed" wizard page
FinishedHeadingLabel=Completing the [name] Setup Wizard
FinishedLabelNoIcons=Setup has finished installing [name] on your computer.
FinishedLabel=Setup has finished installing [name] on your computer. The application may be launched by selecting the installed shortcuts.
ClickFinish=Click Finish to exit Setup.
FinishedRestartLabel=To complete the installation of [name], Setup must restart your computer. Would you like to restart now?
FinishedRestartMessage=To complete the installation of [name], Setup must restart your computer.%n%nWould you like to restart now?
ShowReadmeCheck=Yes, I would like to view the README file
YesRadio=&Yes, restart the computer now
NoRadio=&No, I will restart the computer later
; used for example as 'Run MyProg.exe'
RunEntryExec=Run %1
; used for example as 'View Readme.txt'
RunEntryShellExec=View %1

; *** "Setup Needs the Next Disk" stuff
ChangeDiskTitle=Setup Needs the Next Disk
SelectDiskLabel2=Please insert Disk %1 and click OK.%n%nIf the files on this disk can be found in a folder other than the one displayed below, enter the correct path or click Browse.
PathLabel=&Path:
FileNotInDir2=The file "%1" could not be located in "%2". Please insert the correct disk or select another folder.
SelectDirectoryLabel=Please specify the location of the next disk.

; *** Installation phase messages
SetupAborted=Setup was not completed.%n%nPlease correct the problem and run Setup again.
AbortRetryIgnoreSelectAction=Select action
AbortRetryIgnoreRetry=&Try again
AbortRetryIgnoreIgnore=&Ignore the error and continue
AbortRetryIgnoreCancel=Cancel installation

; *** Installation status messages
StatusClosingApplications=Closing applications...
StatusCreateDirs=Creating directories...
StatusExtractFiles=Extracting files...
StatusCreateIcons=Creating shortcuts...
StatusCreateIniEntries=Creating INI entries...
StatusCreateRegistryEntries=Creating registry entries...
StatusRegisterFiles=Registering files...
StatusSavingUninstall=Saving uninstall information...
StatusRunProgram=Finishing installation...
StatusRestartingApplications=Restarting applications...
StatusRollback=Rolling back changes...

; *** Misc. errors
ErrorInternal2=Internal error: %1
ErrorFunctionFailedNoCode=%1 failed
ErrorFunctionFailed=%1 failed; code %2
ErrorFunctionFailedWithMessage=%1 failed; code %2.%n%3
ErrorExecutingProgram=Unable to execute file:%n%1

; *** Registry errors
ErrorRegOpenKey=Error opening registry key:%n%1\%2
ErrorRegCreateKey=Error creating registry key:%n%1\%2
ErrorRegWriteKey=Error writing to registry key:%n%1\%2

; *** INI errors
ErrorIniEntry=Error creating INI entry in file "%1".

; *** File copying errors
FileAbortRetryIgnoreSkipNotRecommended=&Skip this file (not recommended)
FileAbortRetryIgnoreIgnoreNotRecommended=&Ignore the error and continue (not recommended)
SourceIsCorrupted=The source file is corrupted
SourceDoesntExist=The source file "%1" does not exist
ExistingFileReadOnly2=The existing file could not be replaced because it is marked read-only.
ExistingFileReadOnlyRetry=&Remove the read-only attribute and try again
ExistingFileReadOnlyKeepExisting=&Keep the existing file
ErrorReadingExistingDest=An error occurred while trying to read the existing file:
FileExistsSelectAction=Select action
FileExists2=The file already exists.
FileExistsOverwriteExisting=&Overwrite the existing file
FileExistsKeepExisting=&Keep the existing file
FileExistsOverwriteOrKeepAll=&Do this for the next conflicts
ExistingFileNewerSelectAction=Select action
ExistingFileNewer2=The existing file is newer than the one Setup is trying to install.
ExistingFileNewerOverwriteExisting=&Overwrite the existing file
ExistingFileNewerKeepExisting=&Keep the existing file (recommended)
ExistingFileNewerOverwriteOrKeepAll=&Do this for the next conflicts
ErrorChangingAttr=An error occurred while trying to change the attributes of the existing file:
ErrorCreatingTemp=An error occurred while trying to create a file in the destination directory:
ErrorReadingSource=An error occurred while trying to read the source file:
ErrorCopying=An error occurred while trying to copy a file:
ErrorReplacingExistingFile=An error occurred while trying to replace the existing file:
ErrorRestartReplace=RestartReplace failed:
ErrorRenamingTemp=An error occurred while trying to rename a file in the destination directory:
ErrorRegisterServer=Unable to register the DLL/OCX: %1
ErrorRegSvr32Failed=RegSvr32 failed with exit code %1
ErrorRegisterTypeLib=Unable to register the type library: %1

; *** Uninstall display name markings
; used for example as 'My Program (32-bit)'
UninstallDisplayNameMark=%1 (%2)
; used for example as 'My Program (32-bit, All users)'
UninstallDisplayNameMarks=%1 (%2, %3)
UninstallDisplayNameMark32Bit=32-bit
UninstallDisplayNameMark64Bit=64-bit
UninstallDisplayNameMarkAllUsers=All users
UninstallDisplayNameMarkCurrentUser=Current user

; *** Post-installation errors
ErrorOpeningReadme=An error occurred while trying to open the README file.
ErrorRestartingComputer=Setup was unable to restart the computer. Please do this manually.

; *** Uninstaller messages
UninstallNotFound=File "%1" does not exist. Cannot uninstall.
UninstallOpenError=File "%1" could not be opened. Cannot uninstall
UninstallUnsupportedVer=The uninstall log file "%1" is in a format not recognized by this version of the uninstaller. Cannot uninstall
UninstallUnknownEntry=An unknown entry (%1) was encountered in the uninstall log
ConfirmUninstall=Are you sure you want to completely remove %1 and all of its components?
UninstallOnlyOnWin64=This installation can only be uninstalled on 64-bit Windows.
OnlyAdminCanUninstall=This installation can only be uninstalled by a user with administrative privileges.
UninstallStatusLabel=Please wait while %1 is removed from your computer.
UninstalledAll=%1 was successfully removed from your computer.
UninstalledMost=%1 uninstall complete.%n%nSome elements could not be removed. These can be removed manually.
UninstalledAndNeedsRestart=To complete the uninstallation of %1, your computer must be restarted.%n%nWould you like to restart now?
UninstallDataCorrupted="%1" file is corrupted. Cannot uninstall

; *** Uninstallation phase messages
ConfirmDeleteSharedFileTitle=Remove Shared File?
ConfirmDeleteSharedFile2=The system indicates that the following shared file is no longer in use by any programs. Would you like for Uninstall to remove this shared file?%n%nIf any programs are still using this file and it is removed, those programs may not function properly. If you are unsure, choose No. Leaving the file on your system will not cause any harm.
SharedFileNameLabel=File name:
SharedFileLocationLabel=Location:
WizardUninstalling=Uninstall Status
StatusUninstalling=Uninstalling %1...

; *** Shutdown block reasons
ShutdownBlockReasonInstallingApp=Installing %1.
ShutdownBlockReasonUninstallingApp=Uninstalling %1.

; The custom messages below aren't used by Setup itself, but if you make
; use of them in your scripts, you'll want to translate them.

[CustomMessages]

NameAndVersion=%1 version %2
AdditionalIcons=Additional shortcuts:
CreateDesktopIcon=Create a &desktop shortcut
CreateQuickLaunchIcon=Create a &Quick Launch shortcut
ProgramOnTheWeb=%1 on the Web
UninstallProgram=Uninstall %1
LaunchProgram=Launch %1
AssocFileExtension=&Associate %1 with the %2 file extension
AssocingFileExtension=Associating %1 with the %2 file extension...
AutoStartProgramGroupDescription=Startup:
AutoStartProgram=Automatically start %1
AddonHostProgramNotFound=%1 could not be located in the folder you selected.%n%nDo you want to continue anyway?


================================================
FILE: VirtualSmb/VirtualSmb.cpp
================================================
/*
 * PROJECT:    SynthRdp
 * FILE:       VirtualSmb.cpp
 * PURPOSE:    Implementation for Hyper-V Virtual SMB Guest Utility
 *
 * LICENSE:    The MIT License
 *
 * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)
 */

#include <Mile.Internal.h>

#include <cstdio>
#include <cstring>

// Reference: https://github.com/microsoft/hcsshim
//            /blob/ed5784127999cfd4c08c254626cc964cb20d7948
//            /internal/gcs-sidecar/vsmb.go

typedef struct _SMB2_INSTANCE_CONFIGURATION_17134
{
    UINT32 DormantDirectoryTimeout;
    UINT32 DormantFileTimeout;
    UINT32 DormantFileLimit;
    UINT32 FileInfoCacheLifetime;
    UINT32 FileNotFoundCacheLifetime;
    UINT32 DirectoryCacheLifetime;
    UINT32 FileInfoCacheEntriesMax;
    UINT32 FileNotFoundCacheEntriesMax;
    UINT32 DirectoryCacheEntriesMax;
    UINT32 DirectoryCacheSizeMax;
    UINT8 RequireSecuritySignature;
    UINT8 RequireEncryption;
    UINT8 Padding[2];
} SMB2_INSTANCE_CONFIGURATION_17134, *PSMB2_INSTANCE_CONFIGURATION_17134;

typedef struct _SMB2_INSTANCE_CONFIGURATION_20348
{
    UINT32 DormantDirectoryTimeout;
    UINT32 DormantFileTimeout;
    UINT32 DormantFileLimit;
    UINT32 FileInfoCacheLifetime;
    UINT32 FileNotFoundCacheLifetime;
    UINT32 DirectoryCacheLifetime;
    UINT32 FileInfoCacheEntriesMax;
    UINT32 FileNotFoundCacheEntriesMax;
    UINT32 DirectoryCacheEntriesMax;
    UINT32 DirectoryCacheSizeMax;
    UINT32 ReadAheadGranularity;
    UINT8 RequireSecuritySignature;
    UINT8 RequireEncryption;
    UINT8 Padding[2];
} SMB2_INSTANCE_CONFIGURATION_20348, *PSMB2_INSTANCE_CONFIGURATION_20348;

typedef struct _SMB2_INSTANCE_CONFIGURATION_25398
{
    UINT32 DormantDirectoryTimeout;
    UINT32 DormantFileTimeout;
    UINT32 DormantFileLimit;
    UINT32 FileInfoCacheLifetime;
    UINT32 FileNotFoundCacheLifetime;
    UINT32 DirectoryCacheLifetime;
    UINT32 FileInfoCacheEntriesMax;
    UINT32 FileNotFoundCacheEntriesMax;
    UINT32 DirectoryCacheEntriesMax;
    UINT32 DirectoryCacheSizeMax;
    UINT32 ReadAheadGranularity;
    UINT32 VolumeFeatureSupportCacheLifetime;
    UINT32 VolumeFeatureSupportCacheEntriesMax;
    UINT8 RequireSecuritySignature;
    UINT8 RequireEncryption;
    UINT8 Padding[2];
} SMB2_INSTANCE_CONFIGURATION_25398, *PSMB2_INSTANCE_CONFIGURATION_25398;

// Since 26100.xxxx
typedef struct _SMB2_INSTANCE_CONFIGURATION
{
    UINT32 DormantDirectoryTimeout;
    UINT32 DormantFileTimeout;
    UINT32 DormantFileLimit;
    UINT32 FileInfoCacheLifetime;
    UINT32 FileNotFoundCacheLifetime;
    UINT32 DirectoryCacheLifetime;
    UINT32 FileInfoCacheEntriesMax;
    UINT32 FileNotFoundCacheEntriesMax;
    UINT32 DirectoryCacheEntriesMax;
    UINT32 DirectoryCacheSizeMax;
    UINT32 ReadAheadGranularity;
    UINT32 VolumeFeatureSupportCacheLifetime;
    UINT32 VolumeFeatureSupportCacheEntriesMax;
    UINT32 FileAbeStatusCacheLifetime;
    UINT8 RequireSecuritySignature;
    UINT8 RequireEncryption;
    UINT8 Padding[2];
} SMB2_INSTANCE_CONFIGURATION, *PSMB2_INSTANCE_CONFIGURATION;

typedef struct _LMR_CONNECTION_PROPERTIES_10586
{
    union
    {
        UINT8 Value;
        struct
        {
            UINT8 StatusCodeFiltering : 1; // Symbol
            UINT8 FileInfoCache : 1; // Symbol
            UINT8 FileNotFoundCache : 1; // Symbol
            UINT8 DirectoryCache : 1; // Symbol
            UINT8 Leasing : 1; // Symbol
            UINT8 SuppressRenames : 1; // Symbol
            UINT8 ForceMultiChannel : 1; // Symbol
            UINT8 ForceKeepalive : 1; // Symbol
        } Fields;
    } Flags1;
    union
    {
        UINT8 Value;
        struct
        {
            UINT8 DisableBandwidthThrottling : 1; // Symbol
            UINT8 Reserved : 7;
        } Fields;
    } Flags2;
    UINT8 Padding[2];
    UINT32 SessionTimeoutInterval;
    UINT32 CAHandleKeepaliveInterval;
    UINT32 NonCAHandleKeepaliveInterval;
    UINT32 ActiveIOKeepaliveInterval;
} LMR_CONNECTION_PROPERTIES_10586, *PLMR_CONNECTION_PROPERTIES_10586;

typedef struct _LMR_CONNECTION_PROPERTIES_25398
{
    union
    {
        UINT8 Value;
        struct
        {
            UINT8 StatusCodeFiltering : 1; // Symbol
            UINT8 FileInfoCache : 1; // Symbol
            UINT8 FileNotFoundCache : 1; // Symbol
            UINT8 DirectoryCache : 1; // Symbol
            UINT8 Leasing : 1; // Symbol
            UINT8 SuppressRenames : 1; // Symbol
            UINT8 ForceMultiChannel : 1; // Symbol
            UINT8 ForceKeepalive : 1; // Symbol
        } Fields;
    } Flags1;
    union
    {
        UINT8 Value;
        struct
        {
            UINT8 DisableBandwidthThrottling : 1; // Symbol
            UINT8 Reserved : 7;
        } Fields;
    } Flags2;
    UINT8 Padding[2];
    UINT32 SessionTimeoutInterval;
    UINT32 CAHandleKeepaliveInterval;
    UINT32 NonCAHandleKeepaliveInterval;
    UINT32 ActiveIOKeepaliveInterval;
    UINT32 DisableRdma;
    UINT32 ConnectionCountPerRdmaInterface;
} LMR_CONNECTION_PROPERTIES_25398, *PLMR_CONNECTION_PROPERTIES_25398;

// Since 26100.1
typedef struct _LMR_CONNECTION_PROPERTIES
{
    union
    {
        UINT8 Value;
        struct
        {
            UINT8 StatusCodeFiltering : 1; // Symbol
            UINT8 FileInfoCache : 1; // Symbol
            UINT8 FileNotFoundCache : 1; // Symbol
            UINT8 DirectoryCache : 1; // Symbol
            UINT8 Leasing : 1; // Symbol
            UINT8 SuppressRenames : 1; // Symbol
            UINT8 ForceMultiChannel : 1; // Symbol
            UINT8 ForceKeepalive : 1; // Symbol
        } Fields;
    } Flags1;
    union
    {
        UINT8 Value;
        struct
        {
            UINT8 DisableBandwidthThrottling : 1; // Symbol
            UINT8 Reserved : 7;
        } Fields;
    } Flags2;
    UINT8 Padding[2];
    UINT32 SessionTimeoutInterval;
    UINT32 CAHandleKeepaliveInterval;
    UINT32 NonCAHandleKeepaliveInterval;
    UINT32 ActiveIOKeepaliveInterval;
    UINT32 DisableRdma;
    UINT32 ConnectionCountPerRdmaInterface;
    UINT16 AlternateTCPPort;
    UINT16 AlternateQuicPort;
    UINT16 AlternateRdmaPort;
    UINT8 Padding2[2];
} LMR_CONNECTION_PROPERTIES, *PLMR_CONNECTION_PROPERTIES;

#define LMR_INSTANCE_FLAG_REGISTER_FILESYSTEM 0x2
#define LMR_INSTANCE_FLAG_USE_CUSTOM_TRANSPORTS 0x4
#define LMR_INSTANCE_FLAG_ALLOW_GUEST_AUTH 0x8
#define LMR_INSTANCE_FLAG_SUPPORTS_DIRECTMAPPED_IO 0x10

typedef struct _LMR_START_INSTANCE_REQUEST_10586
{
    UINT32 StructureSize;
    UINT32 IoTimeout;
    UINT32 IoRetryCount;
    UINT16 Flags; // LMR_INSTANCE_FLAG_*
    UINT16 AlternatePort; // Symbol
    UINT32 Reserved1;
    LMR_CONNECTION_PROPERTIES_10586 DefaultConnectionProperties;
    UINT8 InstanceId;
    UINT8 Reserved2;
    UINT16 DeviceNameLength;
    WCHAR DeviceName[ANYSIZE_ARRAY]; // Symbol
} LMR_START_INSTANCE_REQUEST_10586, *PLMR_START_INSTANCE_REQUEST_10586;

typedef struct _LMR_START_INSTANCE_REQUEST_17134
{
    UINT32 StructureSize;
    UINT32 IoTimeout;
    UINT32 IoRetryCount;
    UINT16 Flags; // LMR_INSTANCE_FLAG_*
    UINT16 AlternatePort; // Symbol
    UINT32 Reserved1;
    SMB2_INSTANCE_CONFIGURATION_17134 InstanceConfig;
    LMR_CONNECTION_PROPERTIES_10586 DefaultConnectionProperties;
    UINT8 InstanceId;
    UINT8 Reserved2;
    UINT16 DeviceNameLength;
    WCHAR DeviceName[ANYSIZE_ARRAY]; // Symbol
} LMR_START_INSTANCE_REQUEST_17134, *PLMR_START_INSTANCE_REQUEST_17134;

typedef struct _LMR_START_INSTANCE_REQUEST_20348
{
    UINT32 StructureSize;
    UINT32 IoTimeout;
    UINT32 IoRetryCount;
    UINT16 Flags; // LMR_INSTANCE_FLAG_*
    UINT16 AlternatePort; // Symbol
    UINT32 Reserved1;
    SMB2_INSTANCE_CONFIGURATION_20348 InstanceConfig;
    LMR_CONNECTION_PROPERTIES_10586 DefaultConnectionProperties;
    UINT8 InstanceId;
    UINT8 Reserved2;
    UINT16 DeviceNameLength;
    WCHAR DeviceName[ANYSIZE_ARRAY]; // Symbol
} LMR_START_INSTANCE_REQUEST_20348, *PLMR_START_INSTANCE_REQUEST_20348;

typedef struct _LMR_START_INSTANCE_REQUEST_25398
{
    UINT32 StructureSize;
    UINT32 IoTimeout;
    UINT32 IoRetryCount;
    UINT16 Flags; // LMR_INSTANCE_FLAG_*
    UINT16 AlternatePort; // Symbol
    UINT32 Reserved1;
    SMB2_INSTANCE_CONFIGURATION_25398 InstanceConfig;
    LMR_CONNECTION_PROPERTIES_25398 DefaultConnectionProperties;
    UINT8 InstanceId;
    UINT8 Reserved2;
    UINT16 DeviceNameLength;
    WCHAR DeviceName[ANYSIZE_ARRAY]; // Symbol
} LMR_START_INSTANCE_REQUEST_25398, *PLMR_START_INSTANCE_REQUEST_25398;

typedef struct _LMR_START_INSTANCE_REQUEST_26100
{
    UINT32 StructureSize;
    UINT32 IoTimeout;
    UINT32 IoRetryCount;
    UINT16 Flags; // LMR_INSTANCE_FLAG_*
    UINT16 AlternatePort; // Symbol
    UINT32 Reserved1;
    SMB2_INSTANCE_CONFIGURATION_25398 InstanceConfig;
    LMR_CONNECTION_PROPERTIES DefaultConnectionProperties;
    UINT8 InstanceId;
    UINT8 Reserved2;
    UINT16 DeviceNameLength;
    WCHAR DeviceName[ANYSIZE_ARRAY]; // Symbol
} LMR_START_INSTANCE_REQUEST_26100, *PLMR_START_INSTANCE_REQUEST_26100;

typedef struct _LMR_START_INSTANCE_REQUEST
{
    UINT32 StructureSize;
    UINT32 IoTimeout;
    UINT32 IoRetryCount;
    UINT16 Flags; // LMR_INSTANCE_FLAG_*
    UINT16 AlternatePort; // Symbol
    UINT32 Reserved1;
    SMB2_INSTANCE_CONFIGURATION InstanceConfig;
    LMR_CONNECTION_PROPERTIES DefaultConnectionProperties;
    UINT8 InstanceId;
    UINT8 Reserved2;
    UINT16 DeviceNameLength;
    WCHAR DeviceName[ANYSIZE_ARRAY]; // Symbol
} LMR_START_INSTANCE_REQUEST, *PLMR_START_INSTANCE_REQUEST;

#ifndef FSCTL_LMR_START_INSTANCE
#define FSCTL_LMR_START_INSTANCE CTL_CODE( \
    FILE_DEVICE_NETWORK_FILE_SYSTEM, \
    232, \
    METHOD_BUFFERED, \
    FILE_ANY_ACCESS)
#endif // !FSCTL_LMR_START_INSTANCE

typedef enum _LMR_TRANSPORT_TYPE
{
    SmbCeTransportTypeTdi = 0x0,
    SmbCeTransportTypeTcpIp = 0x1,
    SmbCeTransportTypeVmbus = 0x2,
} LMR_TRANSPORT_TYPE, *PLMR_TRANSPORT_TYPE;

typedef struct _LMR_BIND_UNBIND_TRANSPORT_REQUEST
{
    UINT16 StructureSize;
    UINT16 Flags;
    LMR_TRANSPORT_TYPE Type;
    UINT TransportIdLength;
    WCHAR TransportId[ANYSIZE_ARRAY];
} LMR_BIND_UNBIND_TRANSPORT_REQUEST, *PLMR_BIND_UNBIND_TRANSPORT_REQUEST;

#ifndef FSCTL_LMR_BIND_TO_TRANSPORT
#define FSCTL_LMR_BIND_TO_TRANSPORT CTL_CODE( \
    FILE_DEVICE_NETWORK_FILE_SYSTEM, \
    108, \
    METHOD_BUFFERED, \
    FILE_ANY_ACCESS)
#endif // !FSCTL_LMR_BIND_TO_TRANSPORT

template <typename RequestType>
NTSTATUS LanmanRedirectorStartInstance(
    _In_ HANDLE Handle)
{
    const WCHAR DeviceName[] = L"\\Device\\vmsmb";
    const std::size_t DeviceNameLength =
        (sizeof(DeviceName) / sizeof(WCHAR)) - 1;

    const std::size_t RequestBufferSize =
        FIELD_OFFSET(RequestType, DeviceName) +
        sizeof(WCHAR) * DeviceNameLength;
    UINT8 RequestBuffer[RequestBufferSize] = {};

    RequestType* Request = reinterpret_cast<RequestType*>(RequestBuffer);
    Request->StructureSize =
        FIELD_OFFSET(LMR_START_INSTANCE_REQUEST, DeviceName);
    Request->IoTimeout = 30;
    Request->IoRetryCount = 3;
    Request->Flags =
        LMR_INSTANCE_FLAG_REGISTER_FILESYSTEM |
        LMR_INSTANCE_FLAG_USE_CUSTOM_TRANSPORTS |
        LMR_INSTANCE_FLAG_ALLOW_GUEST_AUTH |
        LMR_INSTANCE_FLAG_SUPPORTS_DIRECTMAPPED_IO;
    Request->Reserved1 = 0;
    Request->DefaultConnectionProperties.Flags1.Value = 0x1F;
    Request->DefaultConnectionProperties.SessionTimeoutInterval = 55;
    Request->DefaultConnectionProperties.CAHandleKeepaliveInterval = 10;
    Request->DefaultConnectionProperties.NonCAHandleKeepaliveInterval = 30;
    Request->DefaultConnectionProperties.ActiveIOKeepaliveInterval = 30;
    Request->InstanceId = 1;
    Request->DeviceNameLength = DeviceNameLength * sizeof(WCHAR);
    std::memcpy(
        Request->DeviceName,
        DeviceName,
        sizeof(DeviceName) - sizeof(WCHAR));
    IO_STATUS_BLOCK IoStatusBlock = {};
    return ::NtFsControlFile(
        Handle,
        nullptr,
        nullptr,
        nullptr,
        &IoStatusBlock,
        FSCTL_LMR_START_INSTANCE,
        RequestBuffer,
        RequestBufferSize,
        nullptr,
        0);
}

int main()
{
    NTSTATUS Status = STATUS_SUCCESS;

    HANDLE LanmanRedirectorHandle = INVALID_HANDLE_VALUE;
    {
        UNICODE_STRING LanmanRedirectorDevicePath = RTL_CONSTANT_STRING(
            L"\\Device\\LanmanRedirector");
        OBJECT_ATTRIBUTES ObjectAttributes = {};
        ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
        ObjectAttributes.ObjectName = &LanmanRedirectorDevicePath;
        ObjectAttributes.Attributes = OBJ_CASE_INSENSITIVE;
        IO_STATUS_BLOCK IoStatusBlock = {};
        Status = ::NtCreateFile(
            &LanmanRedirectorHandle,
            FILE_LIST_DIRECTORY | FILE_TRAVERSE | SYNCHRONIZE,
            &ObjectAttributes,
            &IoStatusBlock,
            0,
            0,
            FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
            FILE_OPEN,
            0,
            nullptr,
            0);
    }
    if (NT_SUCCESS(Status))
    {
        do
        {
            // 120: 26100.xxxx 28000
            {
                using RequestType = LMR_START_INSTANCE_REQUEST;
                Status = ::LanmanRedirectorStartInstance<RequestType>(
                    LanmanRedirectorHandle);
                if (NT_SUCCESS(Status) ||
                    STATUS_OBJECT_NAME_COLLISION == Status)
                {
                    break;
                }
                std::printf(
                    "%s with %s failed: 0x%08X, trying to fallback...\n",
                    "LanmanRedirectorStartInstance",
                    "LMR_START_INSTANCE_REQUEST",
                    Status);
            }

            // 116: 26100
            {
                using RequestType = LMR_START_INSTANCE_REQUEST_26100;
                Status = ::LanmanRedirectorStartInstance<RequestType>(
                    LanmanRedirectorHandle);
                if (NT_SUCCESS(Status) ||
                    STATUS_OBJECT_NAME_COLLISION == Status)
                {
                    break;
                }
                std::printf(
                    "%s with %s failed: 0x%08X, trying to fallback...\n",
                    "LanmanRedirectorStartInstance",
                    "LMR_START_INSTANCE_REQUEST_26100",
                    Status);
            }

            // 108: 25398
            {
                using RequestType = LMR_START_INSTANCE_REQUEST_25398;
                Status = ::LanmanRedirectorStartInstance<RequestType>(
                    LanmanRedirectorHandle);
                if (NT_SUCCESS(Status) ||
                    STATUS_OBJECT_NAME_COLLISION == Status)
                {
                    break;
                }
                std::printf(
                    "%s with %s failed: 0x%08X, trying to fallback...\n",
                    "LanmanRedirectorStartInstance",
                    "LMR_START_INSTANCE_REQUEST_25398",
                    Status);
            }

            // 92: 20348 22000 22621
            {
                using RequestType = LMR_START_INSTANCE_REQUEST_20348;
                Status = ::LanmanRedirectorStartInstance<RequestType>(
                    LanmanRedirectorHandle);
                if (NT_SUCCESS(Status) ||
                    STATUS_OBJECT_NAME_COLLISION == Status)
                {
                    break;
                }
                std::printf(
                    "%s with %s failed: 0x%08X, trying to fallback...\n",
                    "LanmanRedirectorStartInstance",
                    "LMR_START_INSTANCE_REQUEST_20348",
                    Status);
            }

            // 88: 17134 17763 18362 19041
            {
                using RequestType = LMR_START_INSTANCE_REQUEST_17134;
                Status = ::LanmanRedirectorStartInstance<RequestType>(
                    LanmanRedirectorHandle);
                if (NT_SUCCESS(Status) ||
                    STATUS_OBJECT_NAME_COLLISION == Status)
                {
                    break;
                }
                std::printf(
                    "%s with %s failed: 0x%08X, trying to fallback...\n",
                    "LanmanRedirectorStartInstance",
                    "LMR_START_INSTANCE_REQUEST_17134",
                    Status);
            }

            // 44: 10586 14393 15063 16299
            {
                using RequestType = LMR_START_INSTANCE_REQUEST_10586;
                Status = ::LanmanRedirectorStartInstance<RequestType>(
                    LanmanRedirectorHandle);
                if (NT_SUCCESS(Status) ||
                    STATUS_OBJECT_NAME_COLLISION == Status)
                {
                    break;
                }
                std::printf(
                    "%s with %s failed: 0x%08X, trying to fallback...\n",
                    "LanmanRedirectorStartInstance",
                    "LMR_START_INSTANCE_REQUEST_10586",
                    Status);
            }

            // 0: 10240 and earlier
            {
                Status = STATUS_NOT_SUPPORTED;
            }

        } while (false);

        if (NT_SUCCESS(Status))
        {
            std::printf("SMB redirector instance started successfully.\n");
        }
        else if (STATUS_OBJECT_NAME_COLLISION == Status)
        {
            std::printf(
                "SMB redirector instance already started.\n");
        }
        else
        {
            std::printf(
                "LanmanRedirectorStartInstance failed with all known request "
                "structures, cannot start SMB redirector instance.");
        }

        ::CloseHandle(LanmanRedirectorHandle);
    }

    HANDLE VmSmbHandle = INVALID_HANDLE_VALUE;
    {
        UNICODE_STRING VmSmbDevicePath = RTL_CONSTANT_STRING(
            L"\\Device\\vmsmb");
        OBJECT_ATTRIBUTES ObjectAttributes = {};
        ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
        ObjectAttributes.ObjectName = &VmSmbDevicePath;
        ObjectAttributes.Attributes = OBJ_CASE_INSENSITIVE;
        IO_STATUS_BLOCK IoStatusBlock = {};
        Status = ::NtCreateFile(
            &VmSmbHandle,
            FILE_LIST_DIRECTORY | FILE_TRAVERSE | SYNCHRONIZE,
            &ObjectAttributes,
            &IoStatusBlock,
            0,
            0,
            FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
            FILE_OPEN,
            0,
            nullptr,
            0);
    }
    if (NT_SUCCESS(Status))
    {
        const WCHAR DeviceName[] =
            L"\\Device\\VMBus\\{4d12e519-17a0-4ae4-8eaa-5270fc6abdb7}-{dcc079ae-60ba-4d07-847c-3493609c0870}-0000";
        const std::size_t DeviceNameLength =
            (sizeof(DeviceName) / sizeof(WCHAR)) - 1;

        const std::size_t RequestBufferSize =
            FIELD_OFFSET(LMR_BIND_UNBIND_TRANSPORT_REQUEST, TransportId) +
            sizeof(WCHAR) * DeviceNameLength;
        UINT8 RequestBuffer[RequestBufferSize] = {};

        PLMR_BIND_UNBIND_TRANSPORT_REQUEST Request =
            reinterpret_cast<PLMR_BIND_UNBIND_TRANSPORT_REQUEST>(RequestBuffer);
        Request->StructureSize = sizeof(LMR_BIND_UNBIND_TRANSPORT_REQUEST);
        Request->Flags = 0;
        Request->Type = SmbCeTransportTypeVmbus;
        Request->TransportIdLength = DeviceNameLength * sizeof(WCHAR);
        std::memcpy(
            Request->TransportId,
            DeviceName,
            sizeof(DeviceName) - sizeof(WCHAR));
        IO_STATUS_BLOCK IoStatusBlock = {};
        Status = ::NtFsControlFile(
            VmSmbHandle,
            nullptr,
            nullptr,
            nullptr,
            &IoStatusBlock,
            FSCTL_LMR_BIND_TO_TRANSPORT,
            RequestBuffer,
            RequestBufferSize,
            nullptr,
            0);
        if (NT_SUCCESS(Status))
        {
            std::printf("VMBUS transport bound to SMB redirector instance.\n");
        }
        else
        {
            std::printf(
                "Failed to bind VMBUS transport to SMB redirector instance: "
                "0x%08X\n",
                Status);
        }
    }

    {
        HANDLE Handle = INVALID_HANDLE_VALUE;
        {
            UNICODE_STRING VmSmbDevicePath = RTL_CONSTANT_STRING(
                L"\\Device\\vmsmb\\VSMB-{dcc079ae-60ba-4d07-847c-3493609c0870}\\NanaBox.HostDrivers");
            OBJECT_ATTRIBUTES ObjectAttributes = {};
            ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
            ObjectAttributes.ObjectName = &VmSmbDevicePath;
            ObjectAttributes.Attributes = OBJ_CASE_INSENSITIVE;
            IO_STATUS_BLOCK IoStatusBlock = {};
            Status = ::NtCreateFile(
                &Handle,
                FILE_LIST_DIRECTORY | FILE_TRAVERSE | SYNCHRONIZE,
                &ObjectAttributes,
                &IoStatusBlock,
                0,
                0,
                FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
                FILE_OPEN,
                0,
                nullptr,
                0);
        }
    }

    std::getchar();

    return 0;
}


================================================
FILE: VirtualSmb/VirtualSmb.manifest
================================================
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
	<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
		<application>
			<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
		</application>
	</compatibility>
</assembly>


================================================
FILE: VirtualSmb/VirtualSmb.vcxproj
================================================
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup Label="Globals">
    <ProjectGuid>{0A6FBD98-1210-4B36-A031-3E2D57E89DE3}</ProjectGuid>
    <RootNamespace>VirtualSmb</RootNamespace>
    <MileProjectType>ConsoleApplication</MileProjectType>
    <MileProjectManifestFile>VirtualSmb.manifest</MileProjectManifestFile>
    <MileProjectUseProjectProperties>true</MileProjectUseProjectProperties>
    <MileProjectCompanyName>Project Mile</MileProjectCompanyName>
    <MileProjectFileDescription>Hyper-V Virtual SMB Guest Utility</MileProjectFileDescription>
    <MileProjectInternalName>VirtualSmb</MileProjectInternalName>
    <MileProjectLegalCopyright>© M2-Team and Contributors. All rights reserved.</MileProjectLegalCopyright>
    <MileProjectOriginalFilename>VirtualSmb.exe</MileProjectOriginalFilename>
    <MileProjectProductName>NanaRun</MileProjectProductName>
    <MileProjectVersion>1.0.$([System.DateTime]::Today.Subtract($([System.DateTime]::Parse('2024-05-01'))).TotalDays).0</MileProjectVersion>
    <MileProjectVersionTag>Preview 3</MileProjectVersionTag>
    <MileUniCrtDisableRuntimeDebuggingFeature>true</MileUniCrtDisableRuntimeDebuggingFeature>
    <MileUniCrtEnableVcRuntimeWrapper>false</MileUniCrtEnableVcRuntimeWrapper>
    <MileWindowsHelpersNoCppWinRTHelpers>true</MileWindowsHelpersNoCppWinRTHelpers>
  </PropertyGroup>
  <Import Sdk="Mile.Project.Configurations" Version="1.0.1917" Project="Mile.Project.Platform.x86.props" />
  <Import Sdk="Mile.Project.Configurations" Version="1.0.1917" Project="Mile.Project.Platform.x64.props" />
  <Import Sdk="Mile.Project.Configurations" Version="1.0.1917" Project="Mile.Project.Platform.ARM64.props" />
  <Import Sdk="Mile.Project.Configurations" Version="1.0.1917" Project="Mile.Project.Cpp.Default.props" />
  <Import Sdk="Mile.Project.Configurations" Version="1.0.1917" Project="Mile.Project.Cpp.props" />
  <Import Project="..\NanaRun.IconResource\NanaRun.IconResource.props" />
  <ItemDefinitionGroup>
    <ClCompile>
      <RuntimeLibrary Condition="'$(Configuration)' == 'Debug'">MultiThreadedDebug</RuntimeLibrary>
      <RuntimeLibrary Condition="'$(Configuration)' == 'Release'">MultiThreaded</RuntimeLibrary>
    </ClCompile>
  </ItemDefinitionGroup>
  <ItemGroup>
    <ClCompile Include="VirtualSmb.cpp" />
  </ItemGroup>
  <ItemGroup>
    <Manifest Include="VirtualSmb.manifest" />
  </ItemGroup>
  <ItemGroup>
    <PackageReference Include="Mile.Windows.UniCrt">
      <Version>1.2.410</Version>
    </PackageReference>
    <PackageReference Include="Mile.Windows.Internal">
      <Version>1.0.3550</Version>
    </PackageReference>
    <PackageReference Include="Mile.Windows.Helpers">
      <Version>1.0.1171</Version>
    </PackageReference>
  </ItemGroup>
  <Import Sdk="Mile.Project.Configurations" Version="1.0.1917" Project="Mile.Project.Cpp.targets" />
</Project>
Download .txt
gitextract_8fdsknjd/

├── .editorconfig
├── .github/
│   ├── FUNDING.yml
│   └── workflows/
│       └── BuildBinaries.yml
├── .gitignore
├── BuildAllTargets.cmd
├── BuildAllTargets.proj
├── BuildInstallers.cmd
├── Directory.Build.props
├── Documents/
│   ├── People.md
│   ├── ReleaseNotes.md
│   ├── ReleaseNotesPreview.md
│   └── Versioning.md
├── License.md
├── MinSudo/
│   ├── MinSudo.cpp
│   ├── MinSudo.manifest
│   ├── MinSudo.rc
│   ├── MinSudo.vcxproj
│   ├── MinSudo.vcxproj.filters
│   ├── Resources/
│   │   ├── en/
│   │   │   └── Translations.md
│   │   └── zh-Hans/
│   │       └── Translations.md
│   └── resource.h
├── NanaRun/
│   ├── NanaRun.cpp
│   ├── NanaRun.manifest
│   ├── NanaRun.vcxproj
│   └── NanaRun.vcxproj.filters
├── NanaRun.IconResource/
│   ├── NanaRun.IconResource.h
│   ├── NanaRun.IconResource.props
│   └── NanaRun.IconResource.rc
├── NanaRun.slnx
├── ReadMe.md
├── SynthRdp/
│   ├── AutoRun.inf
│   ├── SynthRdp.cpp
│   ├── SynthRdp.iss
│   ├── SynthRdp.manifest
│   └── SynthRdp.vcxproj
├── Tools/
│   ├── Default.isl
│   ├── Setup.e32
│   └── SetupLdr.e32
└── VirtualSmb/
    ├── VirtualSmb.cpp
    ├── VirtualSmb.manifest
    └── VirtualSmb.vcxproj
Download .txt
SYMBOL INDEX (53 symbols across 4 files)

FILE: MinSudo/MinSudo.cpp
  function SplitCommandLineEx (line 34) | void SplitCommandLineEx(
  function GetCurrentProcessModulePath (line 139) | std::wstring GetCurrentProcessModulePath()
  function GetWorkingDirectory (line 148) | std::wstring GetWorkingDirectory()
  function WriteToConsole (line 157) | void WriteToConsole(
  function ParseStringDictionary (line 183) | std::map<std::string, std::wstring> ParseStringDictionary(
  function DWORD (line 242) | DWORD GetActiveSessionID()
  function BOOL (line 268) | BOOL CreateSystemToken(
  function BOOL (line 372) | BOOL OpenProcessTokenByProcessId(
  function BOOL (line 396) | BOOL OpenServiceProcessToken(
  function BOOL (line 417) | BOOL AdjustTokenPrivilegesSimple(
  function BOOL (line 464) | BOOL GetTokenInformationWithMemory(
  function BOOL (line 512) | BOOL AdjustTokenAllPrivileges(
  type TargetProcessTokenLevel (line 540) | enum class TargetProcessTokenLevel : std::uint32_t
  function BOOL (line 547) | BOOL SimpleCreateProcess(
  function main (line 804) | int main()

FILE: NanaRun/NanaRun.cpp
  type AccessTokenSourceType (line 16) | enum class AccessTokenSourceType : std::int32_t
  type MandatoryLabelType (line 27) | enum class MandatoryLabelType : std::int32_t
  type ProcessPriorityType (line 39) | enum class ProcessPriorityType : std::int32_t
  type ShowWindowModeType (line 50) | enum class ShowWindowModeType : std::int32_t
  type EnvironmentConfiguration (line 59) | struct EnvironmentConfiguration
  function main (line 93) | int main()

FILE: SynthRdp/SynthRdp.cpp
  function EXTERN_C (line 25) | EXTERN_C HANDLE WINAPI VmbusPipeClientTryOpenChannel(
  function SOCKET (line 53) | SOCKET SynthRdpConnectToServer()
  type SynthRdpServiceConnectionContext (line 153) | struct SynthRdpServiceConnectionContext
  function SynthRdpRedirectionWorker (line 159) | void SynthRdpRedirectionWorker(
  function DWORD (line 378) | DWORD SynthRdpMain()
  function GetCurrentProcessModulePath (line 528) | std::wstring GetCurrentProcessModulePath()
  function SynthRdpServiceHandler (line 544) | void WINAPI SynthRdpServiceHandler(
  function SynthRdpServiceMain (line 570) | void WINAPI SynthRdpServiceMain(
  function SynthRdpInstallService (line 600) | int SynthRdpInstallService()
  function SynthRdpUninstallService (line 665) | int SynthRdpUninstallService()
  function SynthRdpStartService (line 720) | int SynthRdpStartService()
  function SynthRdpStopService (line 742) | int SynthRdpStopService()
  function SynthRdpListConfigurations (line 764) | int SynthRdpListConfigurations()
  function SynthRdpUpdateConfiguration (line 904) | int SynthRdpUpdateConfiguration(
  function main (line 1088) | int main()

FILE: VirtualSmb/VirtualSmb.cpp
  type _SMB2_INSTANCE_CONFIGURATION_17134 (line 20) | struct _SMB2_INSTANCE_CONFIGURATION_17134
  type _SMB2_INSTANCE_CONFIGURATION_20348 (line 37) | struct _SMB2_INSTANCE_CONFIGURATION_20348
  type _SMB2_INSTANCE_CONFIGURATION_25398 (line 55) | struct _SMB2_INSTANCE_CONFIGURATION_25398
  type _SMB2_INSTANCE_CONFIGURATION (line 76) | struct _SMB2_INSTANCE_CONFIGURATION
  type _LMR_CONNECTION_PROPERTIES_10586 (line 97) | struct _LMR_CONNECTION_PROPERTIES_10586
  type _LMR_CONNECTION_PROPERTIES_25398 (line 130) | struct _LMR_CONNECTION_PROPERTIES_25398
  type _LMR_CONNECTION_PROPERTIES (line 166) | struct _LMR_CONNECTION_PROPERTIES
  type _LMR_START_INSTANCE_REQUEST_10586 (line 210) | struct _LMR_START_INSTANCE_REQUEST_10586
  type _LMR_START_INSTANCE_REQUEST_17134 (line 225) | struct _LMR_START_INSTANCE_REQUEST_17134
  type _LMR_START_INSTANCE_REQUEST_20348 (line 241) | struct _LMR_START_INSTANCE_REQUEST_20348
  type _LMR_START_INSTANCE_REQUEST_25398 (line 257) | struct _LMR_START_INSTANCE_REQUEST_25398
  type _LMR_START_INSTANCE_REQUEST_26100 (line 273) | struct _LMR_START_INSTANCE_REQUEST_26100
  type _LMR_START_INSTANCE_REQUEST (line 289) | struct _LMR_START_INSTANCE_REQUEST
  type _LMR_TRANSPORT_TYPE (line 313) | enum _LMR_TRANSPORT_TYPE
  type _LMR_BIND_UNBIND_TRANSPORT_REQUEST (line 320) | struct _LMR_BIND_UNBIND_TRANSPORT_REQUEST
  function NTSTATUS (line 338) | NTSTATUS LanmanRedirectorStartInstance(
  function main (line 386) | int main()
Condensed preview — 41 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (187K chars).
[
  {
    "path": ".editorconfig",
    "chars": 1107,
    "preview": "## \n## PROJECT:    Mouri Internal Library Essentials\n## FILE:       .editorconfig\n## PURPOSE:    The root .editorconfig"
  },
  {
    "path": ".github/FUNDING.yml",
    "chars": 251,
    "preview": "patreon: MouriNaruto\ncustom: [\n  \"https://paypal.me/MouriNaruto\",\n  \"https://afdian.net/a/MouriNaruto\",\n  \"https://githu"
  },
  {
    "path": ".github/workflows/BuildBinaries.yml",
    "chars": 850,
    "preview": "name: Build Binaries\n\non:\n  push:\n    paths-ignore:\n      - '.github/*'\n      - '*.md'\n  pull_request:\n    paths-ignore"
  },
  {
    "path": ".gitignore",
    "chars": 7158,
    "preview": "## \n## PROJECT:    Mouri Internal Library Essentials\n## FILE:       .gitignore\n## PURPOSE:    The root .gitignore file f"
  },
  {
    "path": "BuildAllTargets.cmd",
    "chars": 791,
    "preview": "@setlocal\n@echo off\n\nrem Change to the current folder.\ncd \"%~dp0\"\n\nrem Remove the output folder for a fresh compile.\nrd "
  },
  {
    "path": "BuildAllTargets.proj",
    "chars": 1682,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project \n  DefaultTargets=\"Restore;Build\"\n  xmlns=\"http://schemas.microsoft.com"
  },
  {
    "path": "BuildInstallers.cmd",
    "chars": 496,
    "preview": "@setlocal\n@echo off\n\nrem Change to the current folder.\ncd \"%~dp0\"\n\nrem Remove the SynthRdp installation image output fol"
  },
  {
    "path": "Directory.Build.props",
    "chars": 284,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project>\n  <PropertyGroup>\n    <MileProjectOutputPath>$(MSBuildThisFileDirector"
  },
  {
    "path": "Documents/People.md",
    "chars": 388,
    "preview": "# Relevant People\n\n## Notice\n\n- This list sort in alphabetical order.\n\n## Development Team\n\n- Kenji Mouri ([https://git"
  },
  {
    "path": "Documents/ReleaseNotes.md",
    "chars": 118,
    "preview": "# NanaRun Release Notes\n\nFor preview versions, please read \n[NanaRun Preview Release Notes](ReleaseNotesPreview.md).\n"
  },
  {
    "path": "Documents/ReleaseNotesPreview.md",
    "chars": 893,
    "preview": "# NanaRun Preview Release Notes\n\nFor stable versions, please read [NanaRun Release Notes](ReleaseNotes.md).\n\n**NanaRun "
  },
  {
    "path": "Documents/Versioning.md",
    "chars": 766,
    "preview": "# NanaRun Versioning\n\nThis document applies to all versions of NanaRun.\n\n## Version Format\n\n- Simple Version: `<Major>."
  },
  {
    "path": "License.md",
    "chars": 21710,
    "preview": "# NanaRun License\n\nFor giving the maximum respect for the upstream projects and following the \nphilosophy about open-so"
  },
  {
    "path": "MinSudo/MinSudo.cpp",
    "chars": 31254,
    "preview": "/*\n * PROJECT:    NanaRun\n * FILE:       MinSudo.cpp\n * PURPOSE:    Implementation for MinSudo\n *\n * LICENSE:    The MI"
  },
  {
    "path": "MinSudo/MinSudo.manifest",
    "chars": 784,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<assembly manifestVersion=\"1.0\" xmlns=\"urn:schemas-microsoft-co"
  },
  {
    "path": "MinSudo/MinSudo.vcxproj",
    "chars": 2834,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msb"
  },
  {
    "path": "MinSudo/MinSudo.vcxproj.filters",
    "chars": 1085,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuil"
  },
  {
    "path": "MinSudo/Resources/en/Translations.md",
    "chars": 1612,
    "preview": "```\n* PROJECT:    NanaRun\n* FILE:       Translations.md\n* PURPOSE:    The English translation for MinSudo\n*\n* LICENSE: "
  },
  {
    "path": "MinSudo/Resources/zh-Hans/Translations.md",
    "chars": 1129,
    "preview": "```\n* PROJECT:    NanaRun\n* FILE:       Translations.md\n* PURPOSE:    The Chinese (Simplified) translation for MinSudo\n"
  },
  {
    "path": "MinSudo/resource.h",
    "chars": 416,
    "preview": "//{{NO_DEPENDENCIES}}\n// Microsoft Visual C++ 生成的包含文件。\n// 供 MinSudo.rc 使用\n//\n#define IDR_TRANSLATIONS                10"
  },
  {
    "path": "NanaRun/NanaRun.cpp",
    "chars": 1995,
    "preview": "/*\n * PROJECT:    NanaRun\n * FILE:       NanaRun.cpp\n * PURPOSE:    Implementation for NanaRun\n *\n * LICENSE:    The MI"
  },
  {
    "path": "NanaRun/NanaRun.manifest",
    "chars": 784,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<assembly manifestVersion=\"1.0\" xmlns=\"urn:schemas-microsoft-co"
  },
  {
    "path": "NanaRun/NanaRun.vcxproj",
    "chars": 2619,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msb"
  },
  {
    "path": "NanaRun/NanaRun.vcxproj.filters",
    "chars": 281,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuil"
  },
  {
    "path": "NanaRun.IconResource/NanaRun.IconResource.h",
    "chars": 255,
    "preview": "/*\n * PROJECT:    NanaRun\n * FILE:       NanaRun.IconResource.h\n * PURPOSE:    Windows icon resource for NanaRun\n *\n * "
  },
  {
    "path": "NanaRun.IconResource/NanaRun.IconResource.props",
    "chars": 667,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  PROJECT:    NanaRun\n  FILE:       NanaRun.IconResource.props\n  PURPOSE:  "
  },
  {
    "path": "NanaRun.slnx",
    "chars": 504,
    "preview": "<Solution>\n  <Configurations>\n    <Platform Name=\"ARM64\" />\n    <Platform Name=\"x64\" />\n    <Platform Name=\"x86\" />\n  </"
  },
  {
    "path": "ReadMe.md",
    "chars": 6136,
    "preview": "# ![NanaRun](Assets/NanaRun.png) NanaRun\n\nApplication runtime environment customization utility\n\n## Development Status "
  },
  {
    "path": "SynthRdp/AutoRun.inf",
    "chars": 119,
    "preview": "[autorun]\nopen=SynthRdpInstaller.exe\nicon=SynthRdpInstaller.exe\nlabel=Hyper-V Enhanced Session Proxy Service (SynthRdp)"
  },
  {
    "path": "SynthRdp/SynthRdp.cpp",
    "chars": 36745,
    "preview": "/*\n * PROJECT:    NanaRun\n * FILE:       SynthRdp.cpp\n * PURPOSE:    Implementation for Hyper-V Enhanced Session Proxy "
  },
  {
    "path": "SynthRdp/SynthRdp.iss",
    "chars": 3176,
    "preview": "; -- 64BitThreeArch.iss --\n; Demonstrates how to install a program built for three different\n; architectures (x86, x64, "
  },
  {
    "path": "SynthRdp/SynthRdp.manifest",
    "chars": 572,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<assembly manifestVersion=\"1.0\" xmlns=\"urn:schemas-microsoft-co"
  },
  {
    "path": "SynthRdp/SynthRdp.vcxproj",
    "chars": 2908,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/ms"
  },
  {
    "path": "Tools/Default.isl",
    "chars": 20279,
    "preview": "; *** Inno Setup version 6.1.0+ English messages ***\n;\n; To download user-contributed translations of this file, go to:"
  },
  {
    "path": "VirtualSmb/VirtualSmb.cpp",
    "chars": 21050,
    "preview": "/*\n * PROJECT:    SynthRdp\n * FILE:       VirtualSmb.cpp\n * PURPOSE:    Implementation for Hyper-V Virtual SMB Guest Ut"
  },
  {
    "path": "VirtualSmb/VirtualSmb.manifest",
    "chars": 324,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<assembly manifestVersion=\"1.0\" xmlns=\"urn:schemas-microsoft-co"
  },
  {
    "path": "VirtualSmb/VirtualSmb.vcxproj",
    "chars": 2952,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/ms"
  }
]

// ... and 4 more files (download for full content)

About this extraction

This page contains the full source code of the M2Team/NanaRun GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 41 files (172.8 KB), approximately 42.4k tokens, and a symbol index with 53 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!