@ -0,0 +1,559 @@ | |||||
!*.gitkeep | |||||
# 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 | |||||
# Nuget personal access tokens and Credentials | |||||
nuget.config | |||||
# 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 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/ | |||||
# 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 | |||||
.idea/ | |||||
*.sln.iml | |||||
### Git ### | |||||
# Created by git for backups. To disable backups in Git: | |||||
# $ git config --global mergetool.keepBackup false | |||||
*.orig | |||||
# Created by git when using merge tools for conflicts | |||||
*.BACKUP.* | |||||
*.BASE.* | |||||
*.LOCAL.* | |||||
*.REMOTE.* | |||||
*_BACKUP_*.txt | |||||
*_BASE_*.txt | |||||
*_LOCAL_*.txt | |||||
*_REMOTE_*.txt | |||||
### vs ### | |||||
# User-specific files | |||||
# User-specific files (MonoDevelop/Xamarin Studio) | |||||
# Mono auto generated files | |||||
# Build results | |||||
# Visual Studio 2015/2017 cache/options directory | |||||
# Uncomment if you have tasks that create the project's static files in wwwroot | |||||
# Visual Studio 2017 auto generated files | |||||
# MSTest test Results | |||||
# NUnit | |||||
# Build Results of an ATL Project | |||||
# Benchmark Results | |||||
# .NET Core | |||||
# StyleCop | |||||
# Files built by Visual Studio | |||||
# Chutzpah Test files | |||||
# Visual C++ cache files | |||||
# Visual Studio profiler | |||||
# Visual Studio Trace Files | |||||
# TFS 2012 Local Workspace | |||||
# Guidance Automation Toolkit | |||||
# ReSharper is a .NET coding add-in | |||||
# TeamCity is a build add-in | |||||
# DotCover is a Code Coverage Tool | |||||
# AxoCover is a Code Coverage Tool | |||||
# Coverlet is a free, cross platform Code Coverage Tool | |||||
coverage*[.json, .xml, .info] | |||||
# Visual Studio code coverage results | |||||
# NCrunch | |||||
# MightyMoose | |||||
# Web workbench (sass) | |||||
# Installshield output folder | |||||
# DocProject is a documentation generator add-in | |||||
# Click-Once directory | |||||
# Publish Web Output | |||||
# Note: Comment the next line if you want to checkin your web deploy settings, | |||||
# but database connection strings (with potential passwords) will be unencrypted | |||||
# 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 | |||||
# NuGet Packages | |||||
# NuGet Symbol Packages | |||||
# The packages folder can be ignored because of Package Restore | |||||
# except build/, which is used as an MSBuild target. | |||||
# Uncomment if necessary however generally it will be regenerated when needed | |||||
# NuGet v3's project.json files produces more ignorable files | |||||
# Microsoft Azure Build Output | |||||
# Microsoft Azure Emulator | |||||
# Windows Store app package directories and files | |||||
# Visual Studio cache files | |||||
# files ending in .cache can be ignored | |||||
# but keep track of directories ending in .cache | |||||
# Others | |||||
# Including strong name files can present a security risk | |||||
# (https://github.com/github/gitignore/pull/2483#issue-259490424) | |||||
# Since there are multiple workflows, uncomment next line to ignore bower_components | |||||
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) | |||||
# RIA/Silverlight projects | |||||
# Backup & report files from converting an old project file | |||||
# to a newer Visual Studio version. Backup files are not needed, | |||||
# because we have git ;-) | |||||
# SQL Server files | |||||
# Business Intelligence projects | |||||
# Microsoft Fakes | |||||
# GhostDoc plugin setting file | |||||
# Node.js Tools for Visual Studio | |||||
# Visual Studio 6 build log | |||||
# Visual Studio 6 workspace options file | |||||
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) | |||||
# Visual Studio LightSwitch build output | |||||
# Paket dependency manager | |||||
# FAKE - F# Make | |||||
# CodeRush personal settings | |||||
# Python Tools for Visual Studio (PTVS) | |||||
# Cake - Uncomment if you are using it | |||||
# tools/** | |||||
# !tools/packages.config | |||||
# Tabs Studio | |||||
# Telerik's JustMock configuration file | |||||
# BizTalk build output | |||||
# OpenCover UI analysis results | |||||
# Azure Stream Analytics local run output | |||||
# MSBuild Binary and Structured Log | |||||
# NVidia Nsight GPU debugger configuration file | |||||
# MFractors (Xamarin productivity tool) working folder | |||||
# Local History for Visual Studio | |||||
# BeatPulse healthcheck temp database | |||||
# Backup folder for Package Reference Convert tool in Visual Studio 2017 | |||||
# Ionide (cross platform F# VS Code tools) working folder |
@ -0,0 +1,132 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Diagnostics; | |||||
using System.IO; | |||||
using System.Linq; | |||||
using System.Runtime.InteropServices; | |||||
using System.Security; | |||||
using System.Text; | |||||
using System.Threading; | |||||
using amecs.Misc; | |||||
using Ameliorated.ConsoleUtils; | |||||
using Microsoft.Dism; | |||||
namespace amecs.Actions | |||||
{ | |||||
public class _NET | |||||
{ | |||||
private static string _mountedPath; | |||||
private static string _isoPath; | |||||
private static void Unmount() | |||||
{ | |||||
if (_isoPath == "none") | |||||
return; | |||||
SelectWindowsImage.DismountIso(_isoPath); | |||||
} | |||||
public static bool Install() | |||||
{ | |||||
(_mountedPath, _isoPath, _, _, _) = SelectWindowsImage.GetMediaPath(true); | |||||
if (_mountedPath == null) return false; | |||||
if (!Directory.Exists(_mountedPath + @"\sources\sxs") || !Directory.GetFiles(_mountedPath + @"\sources\sxs", "*netfx3*").Any()) | |||||
{ | |||||
Unmount(); | |||||
Console.WriteLine(); | |||||
ConsoleTUI.OpenFrame.Close("ISO/USB/folder does not contain the required files.", | |||||
ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt() { AnyKey = true, Text = "Press any key to return to the Menu: " }); | |||||
return false; | |||||
} | |||||
ConsoleTUI.OpenFrame.WriteCentered("\r\nInstalling .NET 3.5"); | |||||
var topCache = Console.CursorTop; | |||||
var leftCache = Console.CursorLeft; | |||||
Console.WriteLine(); | |||||
var inProgress = false; | |||||
try | |||||
{ | |||||
using var indicator = new ConsoleUtils.LoadingIndicator(); | |||||
DismApi.Initialize(DismLogLevel.LogErrors); | |||||
using (var session = DismApi.OpenOnlineSession()) | |||||
{ | |||||
var stdout = GetStdHandle(-11); | |||||
var indicatorStopped = false; | |||||
var maxHashTags = (ConsoleTUI.OpenFrame.DisplayWidth - 5); | |||||
DismApi.EnableFeatureByPackagePath(session, "NetFX3", null, true, true, new List<string>() { _mountedPath + @"\sources\sxs" }, delegate(DismProgress progress) | |||||
{ | |||||
inProgress = true; | |||||
if (!indicatorStopped) | |||||
{ | |||||
indicator.Stop(); | |||||
Console.SetCursorPosition(leftCache, topCache); | |||||
Console.WriteLine(" "); | |||||
} | |||||
indicatorStopped = true; | |||||
var progressPercentage = progress.Current / 10; | |||||
var currentHashTags = (int)Math.Ceiling(Math.Min(((double)progressPercentage / 100) * maxHashTags, maxHashTags)); | |||||
var spaces = maxHashTags - currentHashTags + (4 - progressPercentage.ToString().Length); | |||||
var sb = new StringBuilder(new string('#', currentHashTags) + new string(' ', spaces) + progressPercentage + "%"); | |||||
WriteConsoleOutputCharacter(stdout, sb, (uint)sb.Length, new Languages.COORD((short)ConsoleTUI.OpenFrame.DisplayOffset, (short)Console.CursorTop), out _); | |||||
inProgress = false; | |||||
}); | |||||
session.Close(); | |||||
Thread.Sleep(100); | |||||
var sb = new StringBuilder(new string('#', maxHashTags) + " 100%"); | |||||
uint throwaway; | |||||
WriteConsoleOutputCharacter(stdout, sb, (uint)sb.Length, new Languages.COORD((short)ConsoleTUI.OpenFrame.DisplayOffset, (short)Console.CursorTop), out throwaway); | |||||
} | |||||
DismApi.Shutdown(); | |||||
Unmount(); | |||||
} catch (Exception e) | |||||
{ | |||||
while (inProgress) | |||||
{ | |||||
Thread.Sleep(50); | |||||
} | |||||
Unmount(); | |||||
Console.WriteLine(); | |||||
Console.WriteLine(); | |||||
ConsoleTUI.OpenFrame.Close("DISM error: " + e.Message, ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt() | |||||
{ | |||||
AnyKey = true, | |||||
Text = "Press any key to return to the Menu: " | |||||
}); | |||||
return false; | |||||
} | |||||
Console.WriteLine(); | |||||
Console.WriteLine(); | |||||
ConsoleTUI.OpenFrame.Close(".NET 3.5 installed successfully", ConsoleColor.Green, Console.BackgroundColor, new ChoicePrompt() | |||||
{ | |||||
AnyKey = true, | |||||
Text = "Press any key to return to the Menu: " | |||||
}); | |||||
return true; | |||||
} | |||||
[StructLayout(LayoutKind.Sequential)] | |||||
public struct COORD | |||||
{ | |||||
public short X; | |||||
public short Y; | |||||
public COORD(short X, short Y) | |||||
{ | |||||
this.X = X; | |||||
this.Y = Y; | |||||
} | |||||
}; | |||||
[DllImport("kernel32.dll", SetLastError = true)] | |||||
internal static extern bool WriteConsoleOutputCharacter(IntPtr hConsoleOutput, StringBuilder lpCharacter, uint nLength, Languages.COORD dwWriteCoord, out uint lpNumberOfCharsWritten); | |||||
[DllImport("kernel32.dll", SetLastError = true)] | |||||
static extern IntPtr GetStdHandle(int nStdHandle); | |||||
} | |||||
} |
@ -0,0 +1,313 @@ | |||||
using System; | |||||
using System.DirectoryServices.AccountManagement; | |||||
using System.Runtime.InteropServices; | |||||
using System.Text; | |||||
using System.Threading; | |||||
using Ameliorated.ConsoleUtils; | |||||
namespace amecs.Actions | |||||
{ | |||||
public class AutoLogon | |||||
{ | |||||
internal static class SafeNativeMethods | |||||
{ | |||||
#region Structures | |||||
[StructLayout(LayoutKind.Sequential)] | |||||
public struct LSA_UNICODE_STRING : IDisposable | |||||
{ | |||||
public UInt16 Length; | |||||
public UInt16 MaximumLength; | |||||
public IntPtr Buffer; | |||||
public void Dispose() | |||||
{ | |||||
this = new LSA_UNICODE_STRING(); | |||||
} | |||||
} | |||||
public struct LSA_OBJECT_ATTRIBUTES | |||||
{ | |||||
public int Length; | |||||
public IntPtr RootDirectory; | |||||
public LSA_UNICODE_STRING ObjectName; | |||||
public UInt32 Attributes; | |||||
public IntPtr SecurityDescriptor; | |||||
public IntPtr SecurityQualityOfService; | |||||
} | |||||
public enum LSA_AccessPolicy : long | |||||
{ | |||||
POLICY_VIEW_LOCAL_INFORMATION = 0x00000001L, | |||||
POLICY_VIEW_AUDIT_INFORMATION = 0x00000002L, | |||||
POLICY_GET_PRIVATE_INFORMATION = 0x00000004L, | |||||
POLICY_TRUST_ADMIN = 0x00000008L, | |||||
POLICY_CREATE_ACCOUNT = 0x00000010L, | |||||
POLICY_CREATE_SECRET = 0x00000020L, | |||||
POLICY_CREATE_PRIVILEGE = 0x00000040L, | |||||
POLICY_SET_DEFAULT_QUOTA_LIMITS = 0x00000080L, | |||||
POLICY_SET_AUDIT_REQUIREMENTS = 0x00000100L, | |||||
POLICY_AUDIT_LOG_ADMIN = 0x00000200L, | |||||
POLICY_SERVER_ADMIN = 0x00000400L, | |||||
POLICY_LOOKUP_NAMES = 0x00000800L, | |||||
POLICY_NOTIFICATION = 0x00001000L | |||||
} | |||||
#endregion | |||||
#region DLL Imports | |||||
[DllImport("advapi32")] | |||||
public static extern IntPtr FreeSid(IntPtr pSid); | |||||
[DllImport("advapi32.dll", PreserveSig = true)] | |||||
public static extern UInt32 LsaOpenPolicy( | |||||
ref LSA_UNICODE_STRING SystemName, | |||||
ref LSA_OBJECT_ATTRIBUTES ObjectAttributes, | |||||
Int32 DesiredAccess, | |||||
out IntPtr PolicyHandle); | |||||
[DllImport("advapi32.dll", SetLastError = true, PreserveSig = true)] | |||||
public static extern uint LsaStorePrivateData( | |||||
IntPtr PolicyHandle, | |||||
LSA_UNICODE_STRING[] KeyName, | |||||
LSA_UNICODE_STRING[] PrivateData); | |||||
[DllImport("advapi32.dll", PreserveSig = true)] | |||||
public static extern uint LsaRetrievePrivateData( | |||||
IntPtr PolicyHandle, | |||||
LSA_UNICODE_STRING[] KeyName, | |||||
out IntPtr PrivateData); | |||||
[DllImport("advapi32.dll", PreserveSig = true)] | |||||
public static extern uint LsaNtStatusToWinError(uint status); | |||||
[DllImport("advapi32.dll")] | |||||
public static extern uint LsaClose(IntPtr ObjectHandle); | |||||
#endregion | |||||
} | |||||
#region Functions | |||||
/// <summary> | |||||
/// Store Encrypted Data | |||||
/// </summary> | |||||
/// <param name="keyName"></param> | |||||
/// <param name="Data"></param> | |||||
/// <returns></returns> | |||||
public static long StoreData(String keyName, String Data) | |||||
{ | |||||
long winErrorCode = 0; | |||||
IntPtr sid = IntPtr.Zero; | |||||
int sidSize = 0; | |||||
//allocate buffers | |||||
sid = Marshal.AllocHGlobal(sidSize); | |||||
//initialize an empty unicode-string | |||||
SafeNativeMethods.LSA_UNICODE_STRING systemName = new SafeNativeMethods.LSA_UNICODE_STRING(); | |||||
//Set desired access rights (requested rights) | |||||
int access = (int)(SafeNativeMethods.LSA_AccessPolicy.POLICY_CREATE_SECRET); | |||||
//initialize a pointer for the policy handle | |||||
IntPtr policyHandle = IntPtr.Zero; | |||||
//these attributes are not used, but LsaOpenPolicy wants them to exists | |||||
SafeNativeMethods.LSA_OBJECT_ATTRIBUTES ObjectAttributes = new SafeNativeMethods.LSA_OBJECT_ATTRIBUTES(); | |||||
ObjectAttributes.Length = 0; | |||||
ObjectAttributes.RootDirectory = IntPtr.Zero; | |||||
ObjectAttributes.Attributes = 0; | |||||
ObjectAttributes.SecurityDescriptor = IntPtr.Zero; | |||||
ObjectAttributes.SecurityQualityOfService = IntPtr.Zero; | |||||
//get a policy handle | |||||
uint resultPolicy = SafeNativeMethods.LsaOpenPolicy(ref systemName, ref ObjectAttributes, access, out policyHandle); | |||||
winErrorCode = SafeNativeMethods.LsaNtStatusToWinError(resultPolicy); | |||||
if (winErrorCode != 0) | |||||
{ | |||||
ConsoleTUI.OpenFrame.WriteCenteredLine("OpenPolicy failed: " + winErrorCode); | |||||
} | |||||
else | |||||
{ | |||||
//initialize an unicode-string for the keyName | |||||
SafeNativeMethods.LSA_UNICODE_STRING[] uKeyName = new SafeNativeMethods.LSA_UNICODE_STRING[1]; | |||||
uKeyName[0] = new SafeNativeMethods.LSA_UNICODE_STRING(); | |||||
uKeyName[0].Buffer = Marshal.StringToHGlobalUni(keyName); | |||||
uKeyName[0].Length = (UInt16)(keyName.Length * UnicodeEncoding.CharSize); | |||||
uKeyName[0].MaximumLength = (UInt16)((keyName.Length + 1) * UnicodeEncoding.CharSize); | |||||
//initialize an unicode-string for the Data to encrypt | |||||
SafeNativeMethods.LSA_UNICODE_STRING[] uData = new SafeNativeMethods.LSA_UNICODE_STRING[1]; | |||||
uData[0] = new SafeNativeMethods.LSA_UNICODE_STRING(); | |||||
uData[0].Buffer = Marshal.StringToHGlobalUni(Data); | |||||
uData[0].Length = (UInt16)(Data.Length * UnicodeEncoding.CharSize); | |||||
uData[0].MaximumLength = (UInt16)((Data.Length + 1) * UnicodeEncoding.CharSize); | |||||
//Store Encrypted Data: | |||||
SafeNativeMethods.LsaStorePrivateData(policyHandle, uKeyName, uData); | |||||
//winErrorCode = LsaNtStatusToWinError(res); | |||||
if (winErrorCode != 0) | |||||
{ | |||||
ConsoleTUI.OpenFrame.WriteCenteredLine("LsaStorePrivateData failed: " + winErrorCode); | |||||
} | |||||
SafeNativeMethods.LsaClose(policyHandle); | |||||
} | |||||
SafeNativeMethods.FreeSid(sid); | |||||
return winErrorCode; | |||||
} | |||||
/// <summary> | |||||
/// Retrieve Encrypted Data | |||||
/// </summary> | |||||
/// <param name="keyName"></param> | |||||
/// <returns></returns> | |||||
public static string RetrieveData(String keyName) | |||||
{ | |||||
string sout = ""; | |||||
long winErrorCode = 0; | |||||
IntPtr sid = IntPtr.Zero; | |||||
int sidSize = 0; | |||||
//allocate buffers | |||||
sid = Marshal.AllocHGlobal(sidSize); | |||||
//initialize an empty unicode-string | |||||
SafeNativeMethods.LSA_UNICODE_STRING systemName = new SafeNativeMethods.LSA_UNICODE_STRING(); | |||||
//Set desired access rights (requested rights) | |||||
int access = (int)(SafeNativeMethods.LSA_AccessPolicy.POLICY_CREATE_SECRET); | |||||
//initialize a pointer for the policy handle | |||||
IntPtr policyHandle = IntPtr.Zero; | |||||
//these attributes are not used, but LsaOpenPolicy wants them to exists | |||||
SafeNativeMethods.LSA_OBJECT_ATTRIBUTES ObjectAttributes = new SafeNativeMethods.LSA_OBJECT_ATTRIBUTES(); | |||||
ObjectAttributes.Length = 0; | |||||
ObjectAttributes.RootDirectory = IntPtr.Zero; | |||||
ObjectAttributes.Attributes = 0; | |||||
ObjectAttributes.SecurityDescriptor = IntPtr.Zero; | |||||
ObjectAttributes.SecurityQualityOfService = IntPtr.Zero; | |||||
//get a policy handle | |||||
uint resultPolicy = SafeNativeMethods.LsaOpenPolicy(ref systemName, ref ObjectAttributes, access, out policyHandle); | |||||
winErrorCode = SafeNativeMethods.LsaNtStatusToWinError(resultPolicy); | |||||
if (winErrorCode != 0) | |||||
{ | |||||
ConsoleTUI.OpenFrame.WriteCenteredLine("OpenPolicy failed: " + winErrorCode); | |||||
} | |||||
else | |||||
{ | |||||
//initialize an unicode-string for the keyName | |||||
SafeNativeMethods.LSA_UNICODE_STRING[] uKeyName = new SafeNativeMethods.LSA_UNICODE_STRING[1]; | |||||
uKeyName[0] = new SafeNativeMethods.LSA_UNICODE_STRING(); | |||||
uKeyName[0].Buffer = Marshal.StringToHGlobalUni(keyName); | |||||
uKeyName[0].Length = (UInt16)(keyName.Length * UnicodeEncoding.CharSize); | |||||
uKeyName[0].MaximumLength = (UInt16)((keyName.Length + 1) * UnicodeEncoding.CharSize); | |||||
//Store Encrypted Data: | |||||
IntPtr pData; | |||||
long result = SafeNativeMethods.LsaRetrievePrivateData(policyHandle, uKeyName, out pData); | |||||
//winErrorCode = LsaNtStatusToWinError(res); | |||||
if (winErrorCode != 0) | |||||
{ | |||||
ConsoleTUI.OpenFrame.WriteCenteredLine("LsaStorePrivateData failed: " + winErrorCode); | |||||
} | |||||
SafeNativeMethods.LSA_UNICODE_STRING ss = (SafeNativeMethods.LSA_UNICODE_STRING)Marshal.PtrToStructure(pData, typeof(SafeNativeMethods.LSA_UNICODE_STRING)); | |||||
sout = Marshal.PtrToStringAuto(ss.Buffer); | |||||
SafeNativeMethods.LsaClose(policyHandle); | |||||
} | |||||
SafeNativeMethods.FreeSid(sid); | |||||
return sout; | |||||
} | |||||
#endregion | |||||
private const string LogonKey = @"HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"; | |||||
public static bool Disable() => amecs.RunBasicAction("Disabling AutoLogon", "AutoLogon disabled successfully", new Action(() => | |||||
{ | |||||
new Reg.Value() { KeyName = LogonKey, ValueName = "DefaultUserName", Data = "", Type = Reg.RegistryValueType.REG_SZ}.Apply(); | |||||
new Reg.Value() { KeyName = LogonKey, ValueName = "AutoAdminLogon", Operation = Reg.RegistryValueOperation.Delete}.Apply(); | |||||
new Reg.Value() { KeyName = LogonKey, ValueName = "AutoLogonCount", Operation = Reg.RegistryValueOperation.Delete}.Apply(); | |||||
new Reg.Value() { KeyName = LogonKey, ValueName = "ForceAutoLogon", Operation = Reg.RegistryValueOperation.Delete}.Apply(); | |||||
new Reg.Value() { KeyName = LogonKey, ValueName = "DisableCAD", Operation = Reg.RegistryValueOperation.Delete}.Apply(); | |||||
new Reg.Value() { KeyName = LogonKey, ValueName = "DefaultPassword", Operation = Reg.RegistryValueOperation.Delete}.Apply(); | |||||
StoreData("DefaultPassword", ""); | |||||
Thread.Sleep(1700); | |||||
})); | |||||
public static bool Enable() | |||||
{ | |||||
PrincipalContext context = new PrincipalContext(ContextType.Machine); | |||||
string password = ""; | |||||
while (true) | |||||
{ | |||||
password = new InputPrompt() { MaskInput = true, Text = "Enter your password, or press escape to quit: " }.Start(); | |||||
if (password == null) | |||||
return true; | |||||
if (String.IsNullOrEmpty(password)) | |||||
{ | |||||
try | |||||
{ | |||||
Globals.User.ChangePassword("", ""); | |||||
break; | |||||
} catch {} | |||||
} | |||||
else if (context.ValidateCredentials(Globals.Username, password)) | |||||
break; | |||||
ConsoleTUI.OpenFrame.WriteLine("Incorrect password."); | |||||
Console.WriteLine(); | |||||
} | |||||
try | |||||
{ | |||||
ConsoleTUI.OpenFrame.WriteCentered("\r\nEnabling AutoLogon"); | |||||
using (new ConsoleUtils.LoadingIndicator(true)) | |||||
{ | |||||
new Reg.Value() { KeyName = LogonKey, ValueName = "DefaultUserName", Data = Globals.Username, Type = Reg.RegistryValueType.REG_SZ}.Apply(); | |||||
new Reg.Value() { KeyName = LogonKey, ValueName = "DefaultDomainName", Data = Environment.MachineName, Type = Reg.RegistryValueType.REG_SZ}.Apply(); | |||||
new Reg.Value() { KeyName = LogonKey, ValueName = "AutoAdminLogon", Data = 1, Type = Reg.RegistryValueType.REG_DWORD}.Apply(); | |||||
new Reg.Value() { KeyName = LogonKey, ValueName = "AutoLogonCount", Operation = Reg.RegistryValueOperation.Delete}.Apply(); | |||||
new Reg.Value() { KeyName = LogonKey, ValueName = "DisableCAD", Data = 1, Type = Reg.RegistryValueType.REG_DWORD}.Apply(); | |||||
new Reg.Value() { KeyName = LogonKey, ValueName = "DefaultPassword", Operation = Reg.RegistryValueOperation.Delete}.Apply(); | |||||
StoreData("DefaultPassword", password); | |||||
Thread.Sleep(1700); | |||||
} | |||||
} catch (Exception e) | |||||
{ | |||||
Console.WriteLine(); | |||||
ConsoleTUI.OpenFrame.Close("Error: " + e.Message.TrimEnd('\n').TrimEnd('\r'), ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt() | |||||
{ | |||||
AnyKey = true, | |||||
Text = "Press any key to return to the Menu: " | |||||
}); | |||||
return false; | |||||
} | |||||
Console.WriteLine(); | |||||
ConsoleTUI.OpenFrame.Close($"AutoLogon enabled successfully", ConsoleColor.Green, Console.BackgroundColor, new ChoicePrompt() | |||||
{ | |||||
AnyKey = true, | |||||
Text = "Press any key to return to the Menu: " | |||||
}); | |||||
return true; | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,239 @@ | |||||
using System; | |||||
using System.Diagnostics; | |||||
using System.IO; | |||||
using System.Security.Principal; | |||||
using System.Threading; | |||||
using amecs.Misc; | |||||
using Ameliorated.ConsoleUtils; | |||||
using Microsoft.Win32; | |||||
namespace amecs.Actions | |||||
{ | |||||
public class Deameliorate | |||||
{ | |||||
private static string _mountedPath; | |||||
private static string _winVer; | |||||
private static string _win11Setup = ""; | |||||
private static bool _win11 = Environment.OSVersion.Version.Build >= 22000; | |||||
private const string ExplorerPatcherId = "D17F1E1A-5919-4427-8F89-A1A8503CA3EB"; | |||||
public static bool DeAme() | |||||
{ | |||||
if (new ChoicePrompt() | |||||
{ | |||||
Text = @" | |||||
This will de-ameliorate by reinstalling Windows. | |||||
Although user data should be kept, we strongly recommend | |||||
making backups of any important user data. | |||||
Continue? (Y/N): " | |||||
}.Start().Value == 1) return true; | |||||
Program.Frame.Clear(); | |||||
(_mountedPath, _, _winVer, _, _) = SelectWindowsImage.GetMediaPath(); | |||||
if (_mountedPath == null) return false; | |||||
if (new ChoicePrompt {Text = $"\r\nYour Windows image is {_winVer}. Continue? (Y/N): "}.Start().Value == 1) | |||||
return true; | |||||
var fc = Console.ForegroundColor; | |||||
Console.ForegroundColor = ConsoleColor.Yellow; | |||||
string userSid = null; | |||||
try | |||||
{ | |||||
NSudo.GetSystemPrivilege(); | |||||
NSudo.RunAsUser(() => | |||||
{ | |||||
userSid = WindowsIdentity.GetCurrent().User.ToString(); | |||||
}); | |||||
} | |||||
catch | |||||
{ | |||||
// do nothing | |||||
} | |||||
try | |||||
{ | |||||
ConsoleTUI.OpenFrame.WriteCentered("\r\nUninstalling AME-installed UI software..."); | |||||
string openShellId = null; | |||||
var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"); | |||||
foreach (var item in key.GetSubKeyNames()) | |||||
{ | |||||
try | |||||
{ | |||||
if (((string)key.OpenSubKey(item).GetValue("DisplayName")).Equals("Open-Shell")) | |||||
openShellId = item; | |||||
} | |||||
catch | |||||
{ | |||||
// do nothing | |||||
} | |||||
} | |||||
if (openShellId != null) | |||||
{ | |||||
ConsoleTUI.OpenFrame.WriteCentered("\r\nUninstalling Open-Shell..."); | |||||
Process.Start("MsiExec.exe", $"/X{openShellId} /quiet")?.WaitForExit(); | |||||
if (userSid != null) | |||||
{ | |||||
var appData = (string)Registry.Users.OpenSubKey(userSid + @"\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders").GetValue("AppData"); | |||||
if (Directory.Exists(Path.Combine(appData, "OpenShell"))) | |||||
Directory.Delete(Path.Combine(appData, "OpenShell"), true); | |||||
} | |||||
} | |||||
var epSetupPath = $@"{Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles)}\ExplorerPatcher\ep_setup.exe"; | |||||
if (File.Exists(epSetupPath)) | |||||
{ | |||||
ConsoleTUI.OpenFrame.WriteCentered("\r\nUninstalling ExplorerPatcher..."); | |||||
var winlogon = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon", true); | |||||
winlogon?.SetValue("AutoRestartShell", 0); | |||||
// kill processes that the files use | |||||
foreach (var processName in new[] {"explorer.exe", "rundll32.exe", "dllhost.exe", "ShellExperienceHost.exe", "StartMenuExperienceHost.exe"}) | |||||
{ | |||||
foreach (var process in Process.GetProcessesByName(Path.GetFileNameWithoutExtension(processName))) | |||||
{ | |||||
process.Kill(); | |||||
process.WaitForExit(); | |||||
} | |||||
} | |||||
// delete DWM service that removes rounded corners | |||||
Process.Start("sc", $"stop \"ep_dwm_{ExplorerPatcherId}\"")?.WaitForExit(); | |||||
Process.Start("sc", $"delete \"ep_dwm_{ExplorerPatcherId}\"")?.WaitForExit(); | |||||
// remove registered DLL | |||||
var explorerPatcherDllPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "ExplorerPatcher", "ExplorerPatcher.amd64.dll"); | |||||
Process.Start("regsvr32.exe", $"/s /u \"{explorerPatcherDllPath}\"")?.WaitForExit(); | |||||
// delete files | |||||
foreach (var file in new[] | |||||
{ | |||||
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), | |||||
@"SystemApps\ShellExperienceHost_cw5n1h2txyewy\dxgi.dll"), | |||||
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), | |||||
@"SystemApps\ShellExperienceHost_cw5n1h2txyewy\wincorlib.dll"), | |||||
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), | |||||
@"SystemApps\ShellExperienceHost_cw5n1h2txyewy\wincorlib_orig.dll"), | |||||
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), | |||||
@"SystemApps\Microsoft.Windows.StartMenuExperienceHost_cw5n1h2txyewy\dxgi.dll"), | |||||
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), | |||||
@"SystemApps\Microsoft.Windows.StartMenuExperienceHost_cw5n1h2txyewy\wincorlib.dll"), | |||||
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), | |||||
@"SystemApps\Microsoft.Windows.StartMenuExperienceHost_cw5n1h2txyewy\wincorlib_orig.dll"), | |||||
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), | |||||
"dxgi.dll") | |||||
}) | |||||
{ | |||||
if (File.Exists(file)) File.Delete(file); | |||||
} | |||||
foreach (var folder in new[] | |||||
{ | |||||
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), | |||||
"ExplorerPatcher"), | |||||
Path.Combine( | |||||
Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), | |||||
@"Microsoft\Windows\Start Menu\Programs\ExplorerPatcher") | |||||
}) | |||||
{ | |||||
if (Directory.Exists(folder)) Directory.Delete(folder, true); | |||||
} | |||||
winlogon?.SetValue("AutoRestartShell", 1); | |||||
} | |||||
Program.Frame.Clear(); | |||||
} catch (Exception e) | |||||
{ | |||||
ConsoleTUI.OpenFrame.Close( | |||||
"Error when uninstalling software: " + e.Message, | |||||
ConsoleColor.Red, Console.BackgroundColor, | |||||
new ChoicePrompt { AnyKey = true, Text = "Press any key to continue anyways: " }); | |||||
Program.Frame.Clear(); | |||||
ConsoleTUI.OpenFrame.WriteCentered("\r\nContinuing without uninstalling software...\r\n"); | |||||
} | |||||
// restart Explorer | |||||
if (Process.GetProcessesByName("explorer").Length == 0) | |||||
NSudo.RunProcessAsUser(NSudo.GetUserToken(), "explorer.exe", "", 0); | |||||
// all policies are cleared as a user that's de-ameliorating is unlikely to have their own policies in the first place | |||||
// also clear ExplorerPatcher Registry entries | |||||
ConsoleTUI.OpenFrame.WriteCentered("\r\nClearing policies..."); | |||||
foreach (var keyPath in new[] { | |||||
$@"HKU\{userSid}\Software\Microsoft\Windows\CurrentVersion\Policies", | |||||
$@"HKU\{userSid}\Software\Policies", | |||||
$@"HKU\{userSid}\Software\ExplorerPatcher", | |||||
$@"HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{{{ExplorerPatcherId}}}_ExplorerPatcher", | |||||
@"HKLM\Software\Microsoft\Windows\CurrentVersion\Policies", | |||||
@"HKLM\Software\Policies", | |||||
@"HKLM\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Policies" | |||||
}) | |||||
{ | |||||
var hive = RegistryHive.LocalMachine; | |||||
if (keyPath.StartsWith("HKU")) | |||||
hive = RegistryHive.Users; | |||||
var baseKey = RegistryKey.OpenBaseKey(hive, RegistryView.Default); | |||||
var subKeyPath = keyPath.Substring(keyPath.IndexOf('\\') + 1); | |||||
var key = baseKey.OpenSubKey(subKeyPath, true); | |||||
if (key == null) continue; | |||||
try | |||||
{ | |||||
baseKey.DeleteSubKeyTree(subKeyPath); | |||||
} | |||||
catch | |||||
{ | |||||
// do nothing - some values might fail, but almost all are deleted | |||||
} | |||||
key.Close(); | |||||
} | |||||
Thread.Sleep(3000); | |||||
Program.Frame.Clear(); | |||||
ConsoleTUI.OpenFrame.WriteCentered("\r\nCompleted initial setup!", ConsoleColor.Green); | |||||
if (_win11) | |||||
{ | |||||
ConsoleTUI.OpenFrame.WriteCentered("\r\nWindows Setup will display as 'Windows Server,' but it's not actually installing Windows Server and is only set as such to bypass hardware requirements."); | |||||
Console.WriteLine(); | |||||
} | |||||
ConsoleTUI.OpenFrame.WriteCentered("\r\nWaiting 10 seconds and starting Windows Setup..."); | |||||
Console.ForegroundColor = fc; | |||||
Thread.Sleep(10000); | |||||
Console.WriteLine(); | |||||
try | |||||
{ | |||||
if (_win11) _win11Setup = "/Product Server"; | |||||
Process.Start(Path.Combine(_mountedPath, "setup.exe"), $"/Auto Upgrade /DynamicUpdate Disable {_win11Setup}"); | |||||
} catch (Exception e) | |||||
{ | |||||
ConsoleTUI.OpenFrame.Close( | |||||
$"There was an error when trying to run the Windows Setup: {e}\r\nTry running the Windows Setup manually from File Explorer.", | |||||
ConsoleColor.Red, Console.BackgroundColor, | |||||
new ChoicePrompt { AnyKey = true, Text = $"Press any key to exit: " }); | |||||
return false; | |||||
} | |||||
ConsoleTUI.OpenFrame.Close( | |||||
"Completed, Windows Setup should have started.", | |||||
ConsoleColor.Cyan, Console.BackgroundColor, | |||||
new ChoicePrompt { AnyKey = true, Text = $"Press any key to go back: " }); | |||||
return true; | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,21 @@ | |||||
using System; | |||||
using System.Threading; | |||||
namespace amecs.Actions | |||||
{ | |||||
public class Elevation | |||||
{ | |||||
public static bool Elevate() => amecs.RunBasicAction("Elevating user to Administrator", "The current user is now an Administrator", new Action(() => | |||||
{ | |||||
Globals.Administrators.Members.Add(Globals.User); | |||||
Globals.Administrators.Save(); | |||||
Thread.Sleep(1000); | |||||
}), true); | |||||
public static bool DeElevate() => amecs.RunBasicAction("Revoking Admin rights from the current user", "Admin rights have been revoked for the current user", new Action(() => | |||||
{ | |||||
Globals.Administrators.Members.Remove(Globals.User); | |||||
Globals.Administrators.Save(); | |||||
Thread.Sleep(1000); | |||||
}), true); | |||||
} | |||||
} |
@ -0,0 +1,113 @@ | |||||
using System; | |||||
using System.Diagnostics; | |||||
using System.IO; | |||||
using System.Linq; | |||||
using System.Security; | |||||
using System.Threading; | |||||
using Ameliorated.ConsoleUtils; | |||||
using Microsoft.Win32; | |||||
using System.Windows.Forms; | |||||
namespace amecs.Actions | |||||
{ | |||||
public class Lockscreen | |||||
{ | |||||
public static bool ChangeImage() | |||||
{ | |||||
ConsoleTUI.OpenFrame.WriteCenteredLine("Select an image"); | |||||
Thread.Sleep(1000); | |||||
var dialog = new System.Windows.Forms.OpenFileDialog(); | |||||
dialog.Filter = "Image Files (*.jpg; *.jpeg; *.png; *.bmp; *.jfif)| *.jpg; *.jpeg; *.png; *.bmp; *.jfif"; // Filter files by extension | |||||
dialog.Multiselect = false; | |||||
dialog.InitialDirectory = Globals.UserFolder; | |||||
NativeWindow window = new NativeWindow(); | |||||
window.AssignHandle(Process.GetCurrentProcess().MainWindowHandle); | |||||
if (dialog.ShowDialog(window) == DialogResult.OK) | |||||
{ | |||||
string file; | |||||
try | |||||
{ | |||||
file = dialog.FileName; | |||||
} | |||||
catch (SecurityException e) | |||||
{ | |||||
Console.WriteLine(); | |||||
ConsoleTUI.OpenFrame.Close("Security error: " + e.Message, ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt() {AnyKey = true, Text = "Press any key to return to the Menu: "}); | |||||
return false; | |||||
} | |||||
Console.WriteLine(); | |||||
var choice = new ChoicePrompt() { Text = "Remove lockscreen blur? (Y/N): " }.Start(); | |||||
if (!choice.HasValue) return true; | |||||
bool blur = choice == 0; | |||||
ConsoleTUI.OpenFrame.WriteCentered("\r\nSetting lockscreen image"); | |||||
using (new ConsoleUtils.LoadingIndicator(true)) | |||||
{ | |||||
Thread.Sleep(500); | |||||
try | |||||
{ | |||||
if (blur) | |||||
new Reg.Value() | |||||
{ | |||||
KeyName = @"HKLM\SOFTWARE\Policies\Microsoft\Windows\System", | |||||
ValueName = "DisableAcrylicBackgroundOnLogon", | |||||
Type = Reg.RegistryValueType.REG_DWORD, | |||||
Data = 1, | |||||
}.Apply(); | |||||
else | |||||
new Reg.Value() | |||||
{ | |||||
KeyName = @"HKLM\SOFTWARE\Policies\Microsoft\Windows\System", | |||||
ValueName = "DisableAcrylicBackgroundOnLogon", | |||||
Type = Reg.RegistryValueType.REG_DWORD, | |||||
Data = 0, | |||||
}.Apply(); | |||||
} catch { } | |||||
new Reg.Value() | |||||
{ | |||||
KeyName = @"HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI\Creative\" + Globals.UserSID, | |||||
ValueName = "RotatingLockScreenEnabled", | |||||
Type = Reg.RegistryValueType.REG_DWORD, | |||||
Data = 0, | |||||
}.Apply(); | |||||
new Reg.Value() | |||||
{ | |||||
KeyName = @$"HKU\{Globals.UserSID}\SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager", | |||||
ValueName = "RotatingLockScreenEnabled", | |||||
Type = Reg.RegistryValueType.REG_DWORD, | |||||
Data = 0, | |||||
}.Apply(); | |||||
File.Delete(Environment.ExpandEnvironmentVariables(@"%WINDIR%\Web\Screen\img100.jpg")); | |||||
File.Copy(file, Environment.ExpandEnvironmentVariables(@"%WINDIR%\Web\Screen\img100.jpg")); | |||||
foreach (var dataDir in Directory.EnumerateDirectories(Environment.ExpandEnvironmentVariables(@"%PROGRAMDATA%\Microsoft\Windows\SystemData"))) | |||||
{ | |||||
var subDir = Path.Combine(dataDir, "ReadOnly"); | |||||
if (!Directory.Exists(subDir)) | |||||
continue; | |||||
Directory.GetDirectories(subDir, "Lockscreen_*").ToList().ForEach(x => Directory.Delete(x, true)); | |||||
} | |||||
} | |||||
Console.WriteLine(); | |||||
ConsoleTUI.OpenFrame.Close("Lockscreen image changed successfully", ConsoleColor.Green, Console.BackgroundColor, new ChoicePrompt() {AnyKey = true, Text = "Press any key to return to the Menu: "}); | |||||
return true; | |||||
} | |||||
else | |||||
{ | |||||
Console.WriteLine(); | |||||
ConsoleTUI.OpenFrame.Close("You must select an image.", new ChoicePrompt() {AnyKey = true, Text = "Press any key to return to the Menu: "}); | |||||
return true; | |||||
} | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,124 @@ | |||||
using System; | |||||
using System.Diagnostics; | |||||
using System.IO; | |||||
using System.Linq; | |||||
using System.Security; | |||||
using System.Threading; | |||||
using System.Windows.Forms; | |||||
using Ameliorated.ConsoleUtils; | |||||
using System.Drawing; | |||||
using System.Security.AccessControl; | |||||
using System.Security.Principal; | |||||
namespace amecs.Actions | |||||
{ | |||||
public class Profile | |||||
{ | |||||
public static bool ChangeImage() | |||||
{ | |||||
ConsoleTUI.OpenFrame.WriteCenteredLine("Select an image"); | |||||
Thread.Sleep(1000); | |||||
var dialog = new System.Windows.Forms.OpenFileDialog(); | |||||
dialog.Filter = "Image Files (*.jpg; *.jpeg; *.png; *.bmp; *.jfif)| *.jpg; *.jpeg; *.png; *.bmp; *.jfif"; // Filter files by extension | |||||
dialog.Multiselect = false; | |||||
dialog.InitialDirectory = Globals.UserFolder; | |||||
NativeWindow window = new NativeWindow(); | |||||
window.AssignHandle(Process.GetCurrentProcess().MainWindowHandle); | |||||
if (dialog.ShowDialog(window) == DialogResult.OK) | |||||
{ | |||||
string file; | |||||
try | |||||
{ | |||||
file = dialog.FileName; | |||||
} | |||||
catch (SecurityException e) | |||||
{ | |||||
Console.WriteLine(); | |||||
ConsoleTUI.OpenFrame.Close("Security error: " + e.Message, ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt() {AnyKey = true, Text = "Press any key to return to the Menu: "}); | |||||
return false; | |||||
} | |||||
ConsoleTUI.OpenFrame.WriteCentered("\r\nSetting profile image"); | |||||
using (new ConsoleUtils.LoadingIndicator(true)) | |||||
{ | |||||
var pfpDir = Path.Combine(Environment.ExpandEnvironmentVariables("%PUBLIC%\\AccountPictures"), Globals.UserSID); | |||||
if (Directory.Exists(pfpDir)) | |||||
{ | |||||
try | |||||
{ | |||||
Directory.Delete(pfpDir, true); | |||||
} catch (Exception e) | |||||
{ | |||||
var logdi = new DirectoryInfo(pfpDir) { Attributes = FileAttributes.Normal }; | |||||
try | |||||
{ | |||||
NSudo.GetOwnershipPrivilege(); | |||||
var logdirsec = logdi.GetAccessControl(); | |||||
logdirsec.SetOwner(WindowsIdentity.GetCurrent().User); | |||||
logdi.SetAccessControl(logdirsec); | |||||
logdirsec = new DirectorySecurity(); | |||||
logdirsec.AddAccessRule(new FileSystemAccessRule(WindowsIdentity.GetCurrent().User, FileSystemRights.FullControl, InheritanceFlags.ObjectInherit | InheritanceFlags.ContainerInherit, PropagationFlags.NoPropagateInherit, AccessControlType.Allow)); | |||||
logdi.SetAccessControl(logdirsec); | |||||
} catch (Exception exception) | |||||
{ | |||||
} | |||||
foreach (var info in logdi.GetFileSystemInfos("*", SearchOption.AllDirectories)) | |||||
{ | |||||
info.Attributes = FileAttributes.Normal; | |||||
} | |||||
Directory.Delete(pfpDir, true); | |||||
} | |||||
} | |||||
Directory.CreateDirectory(pfpDir); | |||||
var image = Image.FromFile(file); | |||||
var pfpKey = @"HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\AccountPicture\Users\" + Globals.UserSID; | |||||
new Reg.Key() { KeyName = pfpKey, Operation = RegistryOperation.Delete }.Apply(); | |||||
foreach (var res in new [] { 32, 40, 48, 64, 96, 192, 208, 240, 424, 448, 1080 }) | |||||
{ | |||||
var bitmap = new Bitmap(res, res); | |||||
var graph = Graphics.FromImage(bitmap); | |||||
graph.DrawImage(image, 0, 0, res, res); | |||||
var saveLoc = Path.Combine(pfpDir, $"{res}x{res}.png"); | |||||
bitmap.Save(saveLoc); | |||||
new Reg.Value() { KeyName = pfpKey, ValueName = "Image" + res, Type = Reg.RegistryValueType.REG_SZ, Data = saveLoc }.Apply(); | |||||
} | |||||
new Reg.Value() { KeyName = pfpKey, ValueName = "UserPicturePath", Type = Reg.RegistryValueType.REG_SZ, Data = Path.Combine(pfpDir, $"448x448.png") }.Apply(); | |||||
try | |||||
{ | |||||
Process proc = new Process(); | |||||
proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; | |||||
proc.StartInfo.FileName = "gpupdate.exe"; | |||||
proc.StartInfo.Arguments = "/force"; | |||||
proc.Start(); | |||||
proc.WaitForExit(20000); | |||||
} catch { } | |||||
} | |||||
Console.WriteLine(); | |||||
ConsoleTUI.OpenFrame.Close("Profile image changed successfully", ConsoleColor.Green, Console.BackgroundColor, new ChoicePrompt() {AnyKey = true, Text = "Press any key to return to the Menu: "}); | |||||
return true; | |||||
} | |||||
else | |||||
{ | |||||
Console.WriteLine(); | |||||
ConsoleTUI.OpenFrame.Close("You must select an image.", new ChoicePrompt() {AnyKey = true, Text = "Press any key to return to the Menu: "}); | |||||
return true; | |||||
} | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,220 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.DirectoryServices; | |||||
using System.DirectoryServices.AccountManagement; | |||||
using Ameliorated.ConsoleUtils; | |||||
using System.Linq; | |||||
using System.Security; | |||||
using System.Text.RegularExpressions; | |||||
using System.Threading; | |||||
using System.Threading.Tasks; | |||||
namespace amecs.Actions | |||||
{ | |||||
public static class UserPass | |||||
{ | |||||
public static bool ShowMenu() | |||||
{ | |||||
var mainMenu = new Ameliorated.ConsoleUtils.Menu() | |||||
{ | |||||
Choices = | |||||
{ | |||||
new Menu.MenuItem("Change Username", new Func<bool>(ChangeUsername)), | |||||
new Menu.MenuItem("Change Password", new Func<bool>(ChangePassword)), | |||||
new Menu.MenuItem("Change Display Name", new Func<bool>(ChangeDisplayName)), | |||||
new Menu.MenuItem("Change Administrator Password", new Func<bool>(ChangeAdminPassword)), | |||||
Menu.MenuItem.Blank, | |||||
new Menu.MenuItem("Return to Menu", new Func<bool>(() => true)), | |||||
new Menu.MenuItem("Exit", new Func<bool>(Globals.Exit)), | |||||
}, | |||||
SelectionForeground = ConsoleColor.Green | |||||
}; | |||||
mainMenu.Write(); | |||||
var result = (Func<bool>)mainMenu.Load(); | |||||
return result.Invoke(); | |||||
} | |||||
public static bool ChangeUsername() | |||||
{ | |||||
try | |||||
{ | |||||
while (true) | |||||
{ | |||||
var username = new InputPrompt() { Text = "Enter new username, or press escape to quit: " }.Start(); | |||||
if (username == null) | |||||
return true; | |||||
if (String.IsNullOrEmpty(username) || !Regex.Match(username, @"^\w[\w\.\- ]{0,19}$").Success) | |||||
{ | |||||
ConsoleTUI.OpenFrame.WriteLine("Username is invalid."); | |||||
Console.WriteLine(); | |||||
continue; | |||||
} | |||||
if (Globals.Username.Equals(username)) | |||||
{ | |||||
ConsoleTUI.OpenFrame.WriteLine("Username matches the current username."); | |||||
Console.WriteLine(); | |||||
continue; | |||||
} | |||||
try | |||||
{ | |||||
ConsoleTUI.OpenFrame.WriteCentered("\r\nSetting new username"); | |||||
using (new ConsoleUtils.LoadingIndicator(true)) | |||||
{ | |||||
DirectoryEntry entry = (DirectoryEntry)Globals.User.GetUnderlyingObject(); | |||||
entry.Rename(username); | |||||
entry.CommitChanges(); | |||||
PrincipalContext context = new PrincipalContext(ContextType.Machine); | |||||
PrincipalSearcher userPrincipalSearcher = new PrincipalSearcher(new UserPrincipal(context)); | |||||
Globals.User = userPrincipalSearcher.FindAll().FirstOrDefault(x => (x is UserPrincipal) && x.Sid.Value == Globals.UserSID) as UserPrincipal; | |||||
break; | |||||
} | |||||
} catch (System.Runtime.InteropServices.COMException e) | |||||
{ | |||||
if (e.ErrorCode != -2147022694) | |||||
throw e; | |||||
ConsoleTUI.OpenFrame.WriteLine("Username is invalid."); | |||||
Console.WriteLine(); | |||||
} | |||||
} | |||||
} catch (Exception e) | |||||
{ | |||||
Console.WriteLine(); | |||||
ConsoleTUI.OpenFrame.Close("Error: " + e.Message.TrimEnd('\n').TrimEnd('\r'), ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt() {AnyKey = true, Text = "Press any key to return to the Menu: "}); | |||||
return false; | |||||
} | |||||
Console.WriteLine(); | |||||
if ((int?)ConsoleTUI.OpenFrame.Close("Username changed successfully", ConsoleColor.Green, Console.BackgroundColor, new ChoicePrompt() | |||||
{ | |||||
TextForeground = ConsoleColor.Yellow, | |||||
Text = "Logoff to apply changes? (Y/N): " | |||||
}) == 0) amecs.RestartWindows(true); | |||||
return true; | |||||
} | |||||
public static bool ChangePassword() | |||||
{ | |||||
try | |||||
{ | |||||
while (true) | |||||
{ | |||||
var password = new InputPrompt() { MaskInput = true, Text = "Enter new password, or press escape to quit: " }.Start(); | |||||
if (password == null) | |||||
return true; | |||||
ConsoleTUI.OpenFrame.WriteCentered("\r\nSetting new password"); | |||||
try | |||||
{ | |||||
using (new ConsoleUtils.LoadingIndicator(true)) | |||||
{ | |||||
if (String.IsNullOrEmpty(password)) | |||||
{ | |||||
Globals.User.SetPassword(""); | |||||
} | |||||
else | |||||
{ | |||||
Globals.User.SetPassword(password); | |||||
} | |||||
Thread.Sleep(800); | |||||
break; | |||||
} | |||||
} catch (PasswordException e) | |||||
{ | |||||
ConsoleTUI.OpenFrame.WriteLine("Could not set password: " + e.Message); | |||||
Console.WriteLine(); | |||||
} | |||||
} | |||||
} catch (Exception e) | |||||
{ | |||||
Console.WriteLine(); | |||||
ConsoleTUI.OpenFrame.Close("Error: " + e.Message.TrimEnd('\n').TrimEnd('\r'), ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt() {AnyKey = true, Text = "Press any key to return to the Menu: "}); | |||||
return false; | |||||
} | |||||
Console.WriteLine(); | |||||
ConsoleTUI.OpenFrame.Close("Password changed successfully", ConsoleColor.Green, Console.BackgroundColor, new ChoicePrompt() {AnyKey = true, Text = "Press any key to return to the Menu: "}); | |||||
return true; | |||||
} | |||||
public static bool ChangeAdminPassword() | |||||
{ | |||||
try | |||||
{ | |||||
PrincipalContext context = new PrincipalContext(ContextType.Machine); | |||||
PrincipalSearcher userPrincipalSearcher = new PrincipalSearcher(new UserPrincipal(context)); | |||||
var administrator = userPrincipalSearcher.FindAll().FirstOrDefault(x => (x is UserPrincipal) && x.Name == "Administrator") as UserPrincipal; | |||||
while (true) | |||||
{ | |||||
var password = new InputPrompt() { MaskInput = true, Text = "Enter new Administrator password,\r\nor press escape to quit: " }.Start(); | |||||
if (password == null) | |||||
return true; | |||||
ConsoleTUI.OpenFrame.WriteCentered("\r\nSetting new password"); | |||||
try | |||||
{ | |||||
using (new ConsoleUtils.LoadingIndicator(true)) | |||||
{ | |||||
if (String.IsNullOrEmpty(password)) | |||||
{ | |||||
administrator.SetPassword(""); | |||||
} | |||||
else | |||||
{ | |||||
administrator.SetPassword(password); | |||||
} | |||||
Thread.Sleep(1000); | |||||
break; | |||||
} | |||||
} catch (PasswordException e) | |||||
{ | |||||
ConsoleTUI.OpenFrame.WriteLine("Could not set password: " + e.Message); | |||||
Console.WriteLine(); | |||||
} | |||||
} | |||||
} catch (Exception e) | |||||
{ | |||||
Console.WriteLine(); | |||||
ConsoleTUI.OpenFrame.Close("Error: " + e.Message.TrimEnd('\n').TrimEnd('\r'), ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt() {AnyKey = true, Text = "Press any key to return to the Menu: "}); | |||||
return false; | |||||
} | |||||
Console.WriteLine(); | |||||
ConsoleTUI.OpenFrame.Close("Administrator password changed successfully", ConsoleColor.Green, Console.BackgroundColor, new ChoicePrompt() {AnyKey = true, Text = "Press any key to return to the Menu: "}); | |||||
return true; | |||||
} | |||||
public static bool ChangeDisplayName() | |||||
{ | |||||
try | |||||
{ | |||||
var name = new InputPrompt() { Text = "Enter new display name, or press escape to quit: " }.Start(); | |||||
if (name == null) | |||||
return true; | |||||
ConsoleTUI.OpenFrame.WriteCentered("\r\nSetting new display name"); | |||||
using (new ConsoleUtils.LoadingIndicator(true)) | |||||
{ | |||||
Globals.User.DisplayName = name; | |||||
Globals.User.Save(); | |||||
Thread.Sleep(800); | |||||
} | |||||
} catch (Exception e) | |||||
{ | |||||
Console.WriteLine(); | |||||
ConsoleTUI.OpenFrame.Close("Error: " + e.Message.TrimEnd('\n').TrimEnd('\r'), ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt() {AnyKey = true, Text = "Press any key to return to the Menu: "}); | |||||
return false; | |||||
} | |||||
Console.WriteLine(); | |||||
ConsoleTUI.OpenFrame.Close("Display name changed successfully", ConsoleColor.Green, Console.BackgroundColor, new ChoicePrompt() {AnyKey = true, Text = "Press any key to return to the Menu: "}); | |||||
return true; | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,19 @@ | |||||
using System; | |||||
using System.Threading; | |||||
namespace amecs.Actions | |||||
{ | |||||
public class UsernameRequirement | |||||
{ | |||||
public static bool Enable() => amecs.RunBasicAction("Enabling username login requirement", "The username login requirement is now enabled", new Action(() => | |||||
{ | |||||
new Reg.Value() { KeyName = @"HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System", ValueName = "dontdisplaylastusername", Data = 1, Type = Reg.RegistryValueType.REG_DWORD }.Apply(); | |||||
Thread.Sleep(1700); | |||||
})); | |||||
public static bool Disable() => amecs.RunBasicAction("Disabling username login requirement", "The username login requirement is now disabled", new Action(() => | |||||
{ | |||||
new Reg.Value() { KeyName = @"HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System", ValueName = "dontdisplaylastusername", Operation = Reg.RegistryValueOperation.Delete }.Apply(); | |||||
Thread.Sleep(1700); | |||||
})); | |||||
} | |||||
} |
@ -0,0 +1,299 @@ | |||||
using System; | |||||
using System.DirectoryServices; | |||||
using System.DirectoryServices.AccountManagement; | |||||
using System.Linq; | |||||
using System.Security.AccessControl; | |||||
using System.Security.Principal; | |||||
using System.ServiceProcess; | |||||
using System.Text.RegularExpressions; | |||||
using System.Threading; | |||||
using Ameliorated.ConsoleUtils; | |||||
using Microsoft.Win32; | |||||
namespace amecs.Actions | |||||
{ | |||||
public class Users | |||||
{ | |||||
public static bool ShowMenu() | |||||
{ | |||||
while (true) | |||||
{ | |||||
Program.Frame.Clear(); | |||||
var mainMenu = new Ameliorated.ConsoleUtils.Menu() | |||||
{ | |||||
Choices = | |||||
{ | |||||
Globals.WinVer <= 19043 ? | |||||
new Menu.MenuItem("Create New User (Legacy)", new Func<bool>(CreateNewUserLegacy)) : | |||||
new Menu.MenuItem("Create New User", new Func<bool>(CreateNewUser)), | |||||
Menu.MenuItem.Blank, | |||||
new Menu.MenuItem("Return to Menu", null), | |||||
new Menu.MenuItem("Exit", new Func<bool>(Globals.Exit)) | |||||
}, | |||||
SelectionForeground = ConsoleColor.Green | |||||
}; | |||||
Func<bool> result; | |||||
try | |||||
{ | |||||
mainMenu.Write(); | |||||
var res = mainMenu.Load(); | |||||
if (res == null) | |||||
return true; | |||||
result = (Func<bool>)res; | |||||
} catch (Exception e) | |||||
{ | |||||
Console.WriteLine(e); | |||||
Console.ReadLine(); | |||||
return false; | |||||
} | |||||
try | |||||
{ | |||||
result.Invoke(); | |||||
} catch (Exception e) | |||||
{ | |||||
ConsoleTUI.ShowErrorBox("Error while running an action: " + e.ToString(), null); | |||||
} | |||||
} | |||||
} | |||||
private static bool CreateNewUserLegacy() | |||||
{ | |||||
var choice = new ChoicePrompt() { Text = "WARNING: This is a deprecated action, and the new user\r\nwill not be fully functional. Continue? (Y/N): ", TextForeground = ConsoleColor.Yellow}.Start(); | |||||
if (choice == null || choice == 1) | |||||
return false; | |||||
ConsoleTUI.OpenFrame.WriteLine(); | |||||
try | |||||
{ | |||||
if (CreateUser() == false) | |||||
return true; | |||||
} catch (Exception e) | |||||
{ | |||||
Console.WriteLine(); | |||||
ConsoleTUI.OpenFrame.Close("Error: " + e.Message.TrimEnd('\n').TrimEnd('\r'), ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt() {AnyKey = true, Text = "Press any key to return to the Menu: "}); | |||||
return false; | |||||
} | |||||
ConsoleTUI.OpenFrame.WriteCentered("\r\nConfiguring user"); | |||||
try | |||||
{ | |||||
using (new ConsoleUtils.LoadingIndicator(true)) | |||||
{ | |||||
try { ServiceController.GetServices().First(x => x.ServiceName.Equals("AppReadiness")).Stop(); } catch (Exception e) { } | |||||
NSudo.GetOwnershipPrivilege(); | |||||
Reg.AcquirePrivileges(); | |||||
var subKey = Registry.LocalMachine.OpenSubKey(@"SYSTEM\CurrentControlSet\Services\AppReadiness\Parameters", RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryRights.TakeOwnership); | |||||
if (subKey != null) | |||||
{ | |||||
var sec = subKey.GetAccessControl(); | |||||
sec.SetOwner(new NTAccount("SYSTEM")); | |||||
subKey.SetAccessControl(sec); | |||||
subKey.Close(); | |||||
subKey = Registry.LocalMachine.OpenSubKey(@"SYSTEM\CurrentControlSet\Services\AppReadiness\Parameters", RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryRights.ChangePermissions); | |||||
sec = subKey.GetAccessControl(); | |||||
sec.AddAccessRule(new RegistryAccessRule("SYSTEM", RegistryRights.FullControl, InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit, PropagationFlags.None, AccessControlType.Allow)); | |||||
subKey.SetAccessControl(sec); | |||||
} | |||||
new Reg.Key() { KeyName = @"HKLM\SYSTEM\CurrentControlSet\Services\AppReadiness" }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKLM\SOFTWARE\Policies\Microsoft\Windows\OOBE", ValueName = "DisablePrivacyExperience", Data = 1, Type = Reg.RegistryValueType.REG_DWORD}.Apply(); | |||||
new Reg.Value() { KeyName = @"HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System", ValueName = "EnableFirstLogonAnimation", Data = 0, Type = Reg.RegistryValueType.REG_DWORD}.Apply(); | |||||
Reg.LoadDefaultUserHive(); | |||||
try | |||||
{ | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\OpenShell", ValueName = "", Data = "", Type = Reg.RegistryValueType.REG_SZ }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\OpenShell\OpenShell", ValueName = "", Data = "", Type = Reg.RegistryValueType.REG_SZ }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\OpenShell\OpenShell\Settings", ValueName = "", Data = "", Type = Reg.RegistryValueType.REG_SZ }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\OpenShell\StartMenu", ValueName = "", Data = "", Type = Reg.RegistryValueType.REG_SZ }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\OpenShell\StartMenu\Settings", ValueName = "", Data = "", Type = Reg.RegistryValueType.REG_SZ }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\OpenShell\ClassicExplorer", ValueName = "", Data = "", Type = Reg.RegistryValueType.REG_SZ }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\OpenShell\ClassicExplorer\Settings", ValueName = "", Data = "", Type = Reg.RegistryValueType.REG_SZ }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\OpenShell\ClassicExplorer", ValueName = "ShowedToolbar", Data = 1, Type = Reg.RegistryValueType.REG_DWORD }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\OpenShell\ClassicExplorer", ValueName = "NewLine", Data = 0, Type = Reg.RegistryValueType.REG_DWORD }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\OpenShell\ClassicExplorer\Settings", ValueName = "ShowStatusBar", Data = 0, Type = Reg.RegistryValueType.REG_DWORD }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\OpenShell\StartMenu", ValueName = "ShowedStyle2", Data = 1, Type = Reg.RegistryValueType.REG_DWORD }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\OpenShell\StartMenu", ValueName = "CSettingsDlg", Data = "c80100001a0100000000000000000000360d00000100000000000000", Type = Reg.RegistryValueType.REG_BINARY }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\OpenShell\StartMenu", ValueName = "OldItems", Data = "00", Type = Reg.RegistryValueType.REG_BINARY }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\OpenShell\StartMenu", ValueName = "ItemRanks", Data = "00", Type = Reg.RegistryValueType.REG_BINARY }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\OpenShell\StartMenu\MRU", ValueName = "0", Data = @"%SYSTEMDRIVE%\Windows\regedit.exe", Type = Reg.RegistryValueType.REG_SZ }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\OpenShell\StartMenu\Settings", ValueName = "Version", Data = 04040098, Type = Reg.RegistryValueType.REG_DWORD }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\OpenShell\StartMenu\Settings", ValueName = "AllProgramsMetro", Data = 1, Type = Reg.RegistryValueType.REG_DWORD }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\OpenShell\StartMenu\Settings", ValueName = "RecentMetroApps", Data = 1, Type = Reg.RegistryValueType.REG_DWORD }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\OpenShell\StartMenu\Settings", ValueName = "StartScreenShortcut", Data = 0, Type = Reg.RegistryValueType.REG_DWORD }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\OpenShell\StartMenu\Settings", ValueName = "SearchInternet", Data = 0, Type = Reg.RegistryValueType.REG_DWORD }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\OpenShell\StartMenu\Settings", ValueName = "GlassOverride", Data = 1, Type = Reg.RegistryValueType.REG_DWORD }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\OpenShell\StartMenu\Settings", ValueName = "GlassColor", Data = 0, Type = Reg.RegistryValueType.REG_DWORD }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\OpenShell\StartMenu\Settings", ValueName = "SkinW7", Data = "Fluent-Metro", Type = Reg.RegistryValueType.REG_SZ }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\OpenShell\StartMenu\Settings", ValueName = "SkinVariationW7", Data = "", Type = Reg.RegistryValueType.REG_SZ }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\OpenShell\StartMenu\Settings", ValueName = "SkipMetro", Data = 1, Type = Reg.RegistryValueType.REG_DWORD }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\OpenShell\StartMenu\Settings", ValueName = "MenuItems7", Data = @"Item1.Command=user_files\0Item1.Settings=NOEXPAND\0Item2.Command=user_documents\0Item2.Settings=NOEXPAND\0Item3.Command=user_pictures\0Item3.Settings=NOEXPAND\0Item4.Command=user_music\0Item4.Settings=NOEXPAND\0Item5.Command=user_videos\0Item5.Settings=NOEXPAND\0Item6.Command=downloads\0Item6.Settings=NOEXPAND\0Item7.Command=homegroup\0Item7.Settings=ITEM_DISABLED\0Item8.Command=separator\0Item9.Command=games\0Item9.Settings=TRACK_RECENT|NOEXPAND|ITEM_DISABLED\0Item10.Command=favorites\0Item10.Settings=ITEM_DISABLED\0Item11.Command=recent_documents\0Item12.Command=computer\0Item12.Settings=NOEXPAND\0Item13.Command=network\0Item13.Settings=ITEM_DISABLED\0Item14.Command=network_connections\0Item14.Settings=ITEM_DISABLED\0Item15.Command=separator\0Item16.Command=control_panel\0Item16.Settings=TRACK_RECENT\0Item17.Command=pc_settings\0Item17.Settings=TRACK_RECENT\0Item18.Command=admin\0Item18.Settings=TRACK_RECENT|ITEM_DISABLED\0Item19.Command=devices\0Item19.Settings=ITEM_DISABLED\0Item20.Command=defaults\0Item20.Settings=ITEM_DISABLED\0Item21.Command=help\0Item21.Settings=ITEM_DISABLED\0Item22.Command=run\0Item23.Command=apps\0Item23.Settings=ITEM_DISABLED\0Item24.Command=windows_security\0Item24.Settings=ITEM_DISABLED\0", Type = Reg.RegistryValueType.REG_MULTI_SZ }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\OpenShell\StartMenu\Settings", ValueName = "SkinOptionsW7", Data = @"DARK_MAIN=0\0METRO_MAIN=0\0LIGHT_MAIN=0\0AUTOMODE_MAIN=1\0DARK_SUBMENU=0\0METRO_SUBMENU=0\0LIGHT_SUBMENU=0\0AUTOMODE_SUBMENU=1\0SUBMENU_SEPARATORS=1\0DARK_SEARCH=0\0METRO_SEARCH=0\0LIGHT_SEARCH=0\0AUTOMODE_SEARCH=1\0SEARCH_FRAME=1\0SEARCH_COLOR=0\0MODERN_SEARCH=1\0SEARCH_ITALICS=0\0NONE=0\0SEPARATOR=0\0TWO_TONE=1\0CLASSIC_SELECTOR=1\0HALF_SELECTOR=0\0CURVED_MENUSEL=1\0CURVED_SUBMENU=0\0SELECTOR_REVEAL=1\0TRANSPARENT=0\0OPAQUE_SUBMENU=1\0OPAQUE_MENU=0\0OPAQUE=0\0STANDARD=0\0SMALL_MAIN2=1\0SMALL_ICONS=0\0COMPACT_SUBMENU=0\0PRESERVE_MAIN2=0\0LESS_PADDING=0\0EXTRA_PADDING=1\024_PADDING=0\0LARGE_PROGRAMS=0\0TRANSPARENT_SHUTDOWN=0\0OUTLINE_SHUTDOWN=0\0BUTTON_SHUTDOWN=1\0EXPERIMENTAL_SHUTDOWN=0\0LARGE_FONT=0\0CONNECTED_BORDER=1\0FLOATING_BORDER=0\0LARGE_SUBMENU=0\0LARGE_LISTS=0\0THIN_MAIN2=0\0EXPERIMENTAL_MAIN2=1\0USER_IMAGE=1\0USER_OUTSIDE=0\0SCALING_USER=1\056=0\064=0\0TRANSPARENT_USER=0\0UWP_SCROLLBAR=0\0MODERN_SCROLLBAR=1\0SMALL_ARROWS=0\0ARROW_BACKGROUND=1\0ICON_FRAME=0\0SEARCH_SEPARATOR=0\0NO_PROGRAMS_BUTTON=0\0", Type = Reg.RegistryValueType.REG_MULTI_SZ }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Microsoft\Windows\CurrentVersion\Search", ValueName = "SearchboxTaskbarMode", Data = 0, Type = Reg.RegistryValueType.REG_DWORD }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced", ValueName = "ShowTaskViewButton", Data = 0, Type = Reg.RegistryValueType.REG_DWORD }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer", ValueName = "EnableAutoTray", Data = 0, Type = Reg.RegistryValueType.REG_DWORD }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Microsoft\Windows\CurrentVersion\AdvertisingInfo", ValueName = "Enabled", Data = 0, Type = Reg.RegistryValueType.REG_DWORD }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Microsoft\Windows\CurrentVersion\AppHost", ValueName = "EnableWebContentEvaluation", Data = 0, Type = Reg.RegistryValueType.REG_DWORD }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\Control Panel\International\User Profile", ValueName = "HttpAcceptLanguageOptOut", Data = 1, Type = Reg.RegistryValueType.REG_DWORD }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Policies\Microsoft\Windows\Explorer", ValueName = "DisableNotificationCenter", Data = 1, Type = Reg.RegistryValueType.REG_DWORD }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Microsoft\Windows\CurrentVersion\GameDVR", ValueName = "AppCaptureEnabled", Data = 0, Type = Reg.RegistryValueType.REG_DWORD }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\System\GameConfigStore", ValueName = "GameDVR_Enabled", Data = 0, Type = Reg.RegistryValueType.REG_DWORD }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Attachments", ValueName = "SaveZoneInformation", Data = 1, Type = Reg.RegistryValueType.REG_DWORD }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Microsoft\Windows\CurrentVersion\AppHost", ValueName = "ContentEvaluation", Data = 0, Type = Reg.RegistryValueType.REG_DWORD }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\Control Panel\Desktop", ValueName = "WaitToKillAppTimeOut", Data = "2000", Type = Reg.RegistryValueType.REG_SZ }.Apply(); | |||||
new Reg.Key() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Microsoft\Windows\CurrentVersion\StorageSense" }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Microsoft\Windows\CurrentVersion\Search", ValueName = "BingSearchEnabled", Data = 0, Type = Reg.RegistryValueType.REG_DWORD }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Microsoft\Windows\CurrentVersion\Search", ValueName = "CortanaConsent", Data = 0, Type = Reg.RegistryValueType.REG_DWORD }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Microsoft\Windows\CurrentVersion\Search", ValueName = "CortanaInAmbientMode", Data = 0, Type = Reg.RegistryValueType.REG_DWORD }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Microsoft\Windows\CurrentVersion\Search", ValueName = "HistoryViewEnabled", Data = 0, Type = Reg.RegistryValueType.REG_DWORD }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Microsoft\Windows\CurrentVersion\Search", ValueName = "HasAboveLockTips", Data = 0, Type = Reg.RegistryValueType.REG_DWORD }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Microsoft\Windows\CurrentVersion\Search", ValueName = "AllowSearchToUseLocation", Data = 0, Type = Reg.RegistryValueType.REG_DWORD }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Microsoft\Windows\CurrentVersion\SearchSettings", ValueName = "SafeSearchMode", Data = 0, Type = Reg.RegistryValueType.REG_DWORD }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Policies\Microsoft\Windows\Explorer", ValueName = "DisableSearchBoxSuggestions", Data = 1, Type = Reg.RegistryValueType.REG_DWORD }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Microsoft\InputPersonalization", ValueName = "RestrictImplicitTextCollection", Data = 1, Type = Reg.RegistryValueType.REG_DWORD }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Microsoft\InputPersonalization", ValueName = "RestrictImplicitInkCollection", Data = 1, Type = Reg.RegistryValueType.REG_DWORD }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Microsoft\InputPersonalization\TrainedDataStore", ValueName = "AcceptedPrivacyPolicy", Data = 0, Type = Reg.RegistryValueType.REG_DWORD }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Microsoft\InputPersonalization\TrainedDataStore", ValueName = "HarvestContacts", Data = 0, Type = Reg.RegistryValueType.REG_DWORD }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Microsoft\Personalization\Settings", ValueName = "AcceptedPrivacyPolicy", Data = 0, Type = Reg.RegistryValueType.REG_DWORD }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Policies\Microsoft\Windows\Explorer", ValueName = "DisableSearchBoxSuggestions", Data = 1, Type = Reg.RegistryValueType.REG_DWORD }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced", ValueName = "NavPaneShowAllFolders", Data = 0, Type = Reg.RegistryValueType.REG_DWORD }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced", ValueName = "LaunchTo", Data = 1, Type = Reg.RegistryValueType.REG_DWORD }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced", ValueName = "HideFileExt", Data = 0, Type = Reg.RegistryValueType.REG_DWORD }.Apply(); | |||||
new Reg.Value() { KeyName = @"HKU\DefaultUserHive\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced", ValueName = "Hidden", Data = 1, Type = Reg.RegistryValueType.REG_DWORD }.Apply(); | |||||
} catch (Exception e) | |||||
{ | |||||
Reg.UnloadDefaultUserHive(); | |||||
throw e; | |||||
} | |||||
Reg.UnloadDefaultUserHive(); | |||||
} | |||||
} catch (Exception e) | |||||
{ | |||||
Console.WriteLine(); | |||||
ConsoleTUI.OpenFrame.Close("Error: " + e.Message.TrimEnd('\n').TrimEnd('\r'), ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt() {AnyKey = true, Text = "Press any key to return to the Menu: "}); | |||||
return false; | |||||
} | |||||
Console.WriteLine(); | |||||
ConsoleTUI.OpenFrame.Close("User created successfully", ConsoleColor.Green, Console.BackgroundColor, new ChoicePrompt() {AnyKey = true, Text = "Press any key to return to the Menu: "}); | |||||
return true; | |||||
} | |||||
private static bool CreateNewUser() | |||||
{ | |||||
try | |||||
{ | |||||
if (CreateUser() == false) | |||||
return true; | |||||
} catch (Exception e) | |||||
{ | |||||
Console.WriteLine(); | |||||
ConsoleTUI.OpenFrame.Close("Error: " + e.Message.TrimEnd('\n').TrimEnd('\r'), ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt() {AnyKey = true, Text = "Press any key to return to the Menu: "}); | |||||
return false; | |||||
} | |||||
Console.WriteLine(); | |||||
ConsoleTUI.OpenFrame.Close("User created successfully", ConsoleColor.Green, Console.BackgroundColor, new ChoicePrompt() {AnyKey = true, Text = "Press any key to return to the Menu: "}); | |||||
return true; | |||||
} | |||||
private static bool CreateUser() | |||||
{ | |||||
var choice = new ChoicePrompt() { Text = "Make user an Administrator? (Y/N): " }.Start(); | |||||
if (choice == null) | |||||
return false; | |||||
bool makeAdmin = choice == 0; | |||||
Console.WriteLine(); | |||||
while (true) | |||||
{ | |||||
var username = new InputPrompt() { Text = "Enter name of new user, or press\r\nescape to quit: " }.Start(); | |||||
if (username == null) | |||||
return false; | |||||
if (String.IsNullOrEmpty(username) || !Regex.Match(username, @"^\w[\w\.\- ]{0,19}$").Success) | |||||
{ | |||||
ConsoleTUI.OpenFrame.WriteLine("Username is invalid."); | |||||
Console.WriteLine(); | |||||
continue; | |||||
} | |||||
if (Globals.Username.Equals(username)) | |||||
{ | |||||
ConsoleTUI.OpenFrame.WriteLine("Specified user already exists."); | |||||
Console.WriteLine(); | |||||
continue; | |||||
} | |||||
var password = new InputPrompt() { MaskInput = true, Text = "\r\nEnter password for new user, or press\r\nescape to quit: " }.Start(); | |||||
if (password == null) | |||||
return false; | |||||
var passwordConfirmation = new InputPrompt() { MaskInput = true, Text = "\r\nRe-enter your password, or press\r\nescape to quit: " }.Start(); | |||||
if (passwordConfirmation == null) | |||||
return false; | |||||
if (password != passwordConfirmation) | |||||
{ | |||||
ConsoleTUI.OpenFrame.WriteLine("The password re-entered does not match your original password."); | |||||
Console.WriteLine(); | |||||
continue; | |||||
} | |||||
try | |||||
{ | |||||
ConsoleTUI.OpenFrame.WriteCentered("\r\nCreating user"); | |||||
using (new ConsoleUtils.LoadingIndicator(true)) | |||||
{ | |||||
DirectoryEntry AD = new DirectoryEntry("WinNT://" + | |||||
Environment.MachineName + ",computer"); | |||||
DirectoryEntry NewUser = AD.Children.Add(username, "user"); | |||||
NewUser.Invoke("SetPassword", new object[] { password }); | |||||
NewUser.Invoke("Put", new object[] { "Description", "Normal User" }); | |||||
NewUser.CommitChanges(); | |||||
var ugrp = AD.Children.Find("Users", "group"); | |||||
ugrp.Invoke("Add", new object[] { NewUser.Path.ToString() }); | |||||
ugrp.CommitChanges(); | |||||
if (makeAdmin) | |||||
{ | |||||
var agrp = AD.Children.Find("Administrators", "group"); | |||||
agrp.Invoke("Add", new object[] { NewUser.Path.ToString() }); | |||||
agrp.CommitChanges(); | |||||
} | |||||
} | |||||
} catch (System.Runtime.InteropServices.COMException e) | |||||
{ | |||||
if (e.ErrorCode != -2147022694) | |||||
throw e; | |||||
ConsoleTUI.OpenFrame.WriteLine("Username is invalid."); | |||||
Console.WriteLine(); | |||||
} | |||||
return true; | |||||
} | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,201 @@ | |||||
using System; | |||||
using System.Diagnostics; | |||||
using System.Runtime.InteropServices; | |||||
using System.Windows.Forms; | |||||
using amecs; | |||||
namespace Ameliorated.ConsoleUtils | |||||
{ | |||||
public static partial class ConsoleTUI | |||||
{ | |||||
private const int MF_BYCOMMAND = 0x00000000; | |||||
private const int SC_CLOSE = 0xF060; | |||||
private const int SC_MINIMIZE = 0xF020; | |||||
private const int SC_MAXIMIZE = 0xF030; | |||||
private const int SC_SIZE = 0xF000; //resize | |||||
private const uint CHECK_QUICK_EDIT = 0x0040; | |||||
private const int ENABLE_QUICK_EDIT = 0x40 | 0x80; | |||||
// STD_INPUT_HANDLE (DWORD): -10 is the standard input device. | |||||
private const int STD_INPUT_HANDLE = -10; | |||||
private static string PreviousTitle; | |||||
private static int PreviousBufferHeight = 26; | |||||
private static int PreviousBufferWidth = 80; | |||||
private static int PreviousSizeHeight = 26; | |||||
private static int PreviousSizeWidth = 80; | |||||
private static bool IsInitialized; | |||||
private static int InitializedWidth = 80; | |||||
public static void ShowErrorBox(string message, string caption) | |||||
{ | |||||
NativeWindow window = new NativeWindow(); | |||||
window.AssignHandle(Process.GetCurrentProcess().MainWindowHandle); | |||||
MessageBox.Show(window, message, caption, MessageBoxButtons.OK, MessageBoxIcon.Error); | |||||
} | |||||
public enum BackdropType | |||||
{ | |||||
None = 1, | |||||
Mica = 2, | |||||
Acrylic = 3, | |||||
Tabbed = 4 | |||||
} | |||||
[DllImport("dwmapi.dll")] | |||||
private static extern int DwmSetWindowAttribute(IntPtr hwnd, int attribute, ref int pvAttribute, int cbAttribute); | |||||
public static void Initialize(string title, int width = 80, int height = 26, bool resize = false, bool quickedit = false) | |||||
{ | |||||
if (width < 2) throw new ArgumentException("Width must be greater than one."); | |||||
IsInitialized = true; | |||||
PreviousSizeHeight = Console.WindowHeight; | |||||
PreviousSizeWidth = Console.WindowWidth; | |||||
PreviousBufferHeight = Console.BufferHeight; | |||||
PreviousBufferWidth = Console.BufferWidth; | |||||
Console.SetWindowSize(width, height); | |||||
Console.SetBufferSize(width, height); | |||||
Console.SetWindowSize(width, height); | |||||
InitializedWidth = width; | |||||
Console.Clear(); | |||||
Console.CursorVisible = false; | |||||
PreviousTitle = Console.Title; | |||||
Console.Title = title; | |||||
try | |||||
{ | |||||
if ((Console.CursorLeft == 0 && Console.CursorTop == 0) || ParentProcess.ProcessName.Equals("Explorer", StringComparison.OrdinalIgnoreCase)) | |||||
{ | |||||
var bd = (int)BackdropType.Mica; | |||||
var trueA = 0x01; | |||||
if (Globals.WinVer >= 22523) | |||||
{ | |||||
var handle = Process.GetCurrentProcess().MainWindowHandle; | |||||
DwmSetWindowAttribute(handle, 38, ref bd, Marshal.SizeOf<int>()); | |||||
DwmSetWindowAttribute(handle, 20, ref trueA, Marshal.SizeOf<int>()); | |||||
} | |||||
} | |||||
} catch (Exception e) { } | |||||
if (!resize) | |||||
try | |||||
{ | |||||
DisableResize(); | |||||
} catch (Exception e) | |||||
{ | |||||
ConsoleUtils.WriteError("Error disabling window resize - " + e.Message); | |||||
} | |||||
if (!quickedit) | |||||
try | |||||
{ | |||||
DisableQuickEdit(); | |||||
} catch (Exception e) | |||||
{ | |||||
ConsoleUtils.WriteError("Error disabling quickedit - " + e.Message); | |||||
} | |||||
} | |||||
public static void Close() | |||||
{ | |||||
if (!IsInitialized) throw new MethodAccessException("Console TUI must be initialized before calling other TUI functions."); | |||||
IsInitialized = false; | |||||
var parent = ParentProcess.ProcessName; | |||||
if (parent.Equals("Explorer", StringComparison.CurrentCultureIgnoreCase)) return; | |||||
try | |||||
{ | |||||
EnableResize(); | |||||
} catch (Exception e) | |||||
{ | |||||
ConsoleUtils.WriteError("Error enabling window resize - " + e.Message); | |||||
} | |||||
try | |||||
{ | |||||
EnableQuickEdit(); | |||||
} catch (Exception e) | |||||
{ | |||||
ConsoleUtils.WriteError("Error enabling quickedit - " + e.Message); | |||||
} | |||||
Console.CursorVisible = true; | |||||
Console.Clear(); | |||||
Console.Title = PreviousTitle; | |||||
Console.SetWindowSize(PreviousSizeWidth, PreviousSizeHeight); | |||||
Console.SetBufferSize(PreviousBufferWidth, PreviousBufferHeight); | |||||
} | |||||
[DllImport("user32.dll")] | |||||
public static extern int DeleteMenu(IntPtr hMenu, int nPosition, int wFlags); | |||||
[DllImport("user32.dll")] | |||||
private static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert); | |||||
[DllImport("kernel32.dll", ExactSpelling = true)] | |||||
private static extern IntPtr GetConsoleWindow(); | |||||
private static void DisableResize() | |||||
{ | |||||
var handle = GetConsoleWindow(); | |||||
var sysMenu = GetSystemMenu(handle, false); | |||||
if (handle != IntPtr.Zero) | |||||
{ | |||||
//DeleteMenu(sysMenu, SC_CLOSE, MF_BYCOMMAND); | |||||
//DeleteMenu(sysMenu, SC_MINIMIZE, MF_BYCOMMAND); | |||||
DeleteMenu(sysMenu, SC_MAXIMIZE, MF_BYCOMMAND); | |||||
DeleteMenu(sysMenu, SC_SIZE, MF_BYCOMMAND); //resize | |||||
} | |||||
} | |||||
private static void EnableResize() | |||||
{ | |||||
var handle = GetConsoleWindow(); | |||||
GetSystemMenu(handle, true); | |||||
} | |||||
[DllImport("kernel32.dll", SetLastError = true)] | |||||
private static extern IntPtr GetStdHandle(int nStdHandle); | |||||
[DllImport("kernel32.dll")] | |||||
private static extern bool GetConsoleMode(IntPtr hConsoleHandle, out uint lpMode); | |||||
[DllImport("kernel32.dll")] | |||||
private static extern bool SetConsoleMode(IntPtr hConsoleHandle, uint dwMode); | |||||
private static void DisableQuickEdit() | |||||
{ | |||||
var consoleHandle = GetStdHandle(STD_INPUT_HANDLE); | |||||
// get current console mode | |||||
uint consoleMode; | |||||
GetConsoleMode(consoleHandle, out consoleMode); | |||||
// set the new mode | |||||
SetConsoleMode(consoleHandle, consoleMode &= ~CHECK_QUICK_EDIT); | |||||
} | |||||
private static void EnableQuickEdit() | |||||
{ | |||||
var consoleHandle = GetStdHandle(STD_INPUT_HANDLE); | |||||
// get current console mode | |||||
uint consoleMode; | |||||
GetConsoleMode(consoleHandle, out consoleMode); | |||||
// set the new mode | |||||
SetConsoleMode(consoleHandle, consoleMode | ENABLE_QUICK_EDIT); | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,198 @@ | |||||
using System; | |||||
using System.Linq; | |||||
namespace Ameliorated.ConsoleUtils | |||||
{ | |||||
public static partial class ConsoleTUI | |||||
{ | |||||
public static Frame OpenFrame; | |||||
public partial class Frame | |||||
{ | |||||
private int _displayWidth; | |||||
private int _sidePadding; | |||||
/// <summary> | |||||
/// Sets the visual "frame" to be used later. | |||||
/// </summary> | |||||
/// <param name="header">The header to be displayed just under the top of the frame.</param> | |||||
/// <param name="ignoreHeader"> | |||||
/// Indicates whether an exception should be raised if the header cannot be aligned with the | |||||
/// frame. | |||||
/// </param> | |||||
/// <exception cref="MethodAccessException">Function was called before a TUI initialization.</exception> | |||||
public Frame(string header, bool throwOnMisalignedHeader = true) | |||||
{ | |||||
if (!IsInitialized) throw new MethodAccessException("Console TUI must be initialized before calling other TUI functions."); | |||||
if (header.Split(new[] | |||||
{ "\r\n", "\n" }, StringSplitOptions.None).Any(x => x.Length > InitializedWidth)) throw new ArgumentException("Header must not be longer than the window width."); | |||||
int frameWidth; | |||||
if (InitializedWidth.IsEven()) | |||||
{ | |||||
if (!header.Length.IsEven() && throwOnMisalignedHeader) throw new ArgumentException("Header length should be even while window width is even."); | |||||
frameWidth = (.725 * InitializedWidth).RoundToEven(); | |||||
} else | |||||
{ | |||||
if (header.Length.IsEven() && throwOnMisalignedHeader) throw new ArgumentException("Header length should be odd while window width is odd."); | |||||
frameWidth = (.725 * InitializedWidth).RoundToOdd(); | |||||
} | |||||
Header = header; | |||||
FrameWidth = frameWidth; | |||||
DisplayWidth = frameWidth - SidePadding * 2; | |||||
DisplayOffset = (InitializedWidth - DisplayWidth) / 2; | |||||
} | |||||
public string Header { get; set; } | |||||
public char FrameChar { get; set; } = '_'; | |||||
public int FrameWidth { get; set; } | |||||
public int SidePadding | |||||
{ | |||||
get => _sidePadding; | |||||
set | |||||
{ | |||||
_sidePadding = value; | |||||
DisplayWidth = FrameWidth - value * 2; | |||||
DisplayOffset = (InitializedWidth - DisplayWidth) / 2; | |||||
} | |||||
} | |||||
public int DisplayWidth | |||||
{ | |||||
get => _displayWidth; | |||||
set | |||||
{ | |||||
_displayWidth = value; | |||||
DisplayOffset = (InitializedWidth - value) / 2; | |||||
} | |||||
} | |||||
internal int DisplayOffset { get; private set; } | |||||
internal int DisplayHeight { get; } = Console.WindowHeight - 13; | |||||
public void Open(bool paddingLines = true) | |||||
{ | |||||
Console.WriteLine(); | |||||
var frameOffset = (InitializedWidth - FrameWidth) / 2; | |||||
Console.WriteLine(new string(' ', frameOffset) + new string(FrameChar, FrameWidth)); | |||||
Console.WriteLine(); | |||||
WriteCenteredLine(Header); | |||||
if (paddingLines) | |||||
{ | |||||
Console.WriteLine(); | |||||
Console.WriteLine(); | |||||
} | |||||
OpenFrame = this; | |||||
} | |||||
public object Close(Prompt prompt = null, bool alignToBottom = false) | |||||
{ | |||||
OpenFrame = null; | |||||
if (alignToBottom) | |||||
Console.SetCursorPosition(0, Console.WindowHeight - 7); | |||||
Console.WriteLine(); | |||||
Console.WriteLine(); | |||||
var frameOffset = (InitializedWidth - FrameWidth) / 2; | |||||
Console.WriteLine(new string(' ', frameOffset) + new string(FrameChar, FrameWidth)); | |||||
Console.WriteLine(); | |||||
if (prompt != null) | |||||
{ | |||||
if (!prompt.MaxLength.HasValue) | |||||
prompt.MaxLength = DisplayWidth - prompt.Text.LastLine().Length; | |||||
prompt.BindToOpenFrame = false; | |||||
prompt.Text = new string(' ', frameOffset) + prompt.Text; | |||||
try { return ((ChoicePrompt)prompt).Start(); } catch (InvalidCastException) {} | |||||
try { return ((InputPrompt)prompt).Start(); } catch (InvalidCastException) {} | |||||
} | |||||
return null; | |||||
} | |||||
public object Close(string text, Prompt prompt = null, bool alignToBottom = false) | |||||
{ | |||||
OpenFrame = null; | |||||
if (alignToBottom) | |||||
Console.SetCursorPosition(0, Console.WindowHeight - 7); | |||||
Console.WriteLine(); | |||||
WriteCenteredLine(text, true); | |||||
var frameOffset = (InitializedWidth - FrameWidth) / 2; | |||||
Console.WriteLine(new string(' ', frameOffset) + new string(FrameChar, FrameWidth)); | |||||
Console.WriteLine(); | |||||
if (prompt != null) | |||||
{ | |||||
if (!prompt.MaxLength.HasValue) | |||||
prompt.MaxLength = DisplayWidth - prompt.Text.LastLine().Length; | |||||
prompt.BindToOpenFrame = false; | |||||
prompt.Text = new string(' ', frameOffset) + prompt.Text; | |||||
try { return ((ChoicePrompt)prompt).Start(); } catch (InvalidCastException) {} | |||||
try { return ((InputPrompt)prompt).Start(); } catch (InvalidCastException) {} | |||||
} | |||||
return null; | |||||
} | |||||
public object Close(string text, ConsoleColor foreground, ConsoleColor background, Prompt prompt = null, bool alignToBottom = false) | |||||
{ | |||||
OpenFrame = null; | |||||
if (alignToBottom) | |||||
Console.SetCursorPosition(0, Console.WindowHeight - 7); | |||||
Console.WriteLine(); | |||||
WriteCenteredLine(text, foreground, background, true); | |||||
var frameOffset = (InitializedWidth - FrameWidth) / 2; | |||||
Console.WriteLine(new string(' ', frameOffset) + new string(FrameChar, FrameWidth)); | |||||
Console.WriteLine(); | |||||
if (prompt != null) | |||||
{ | |||||
if (!prompt.MaxLength.HasValue) | |||||
prompt.MaxLength = DisplayWidth - prompt.Text.LastLine().Length; | |||||
prompt.BindToOpenFrame = false; | |||||
prompt.Text = new string(' ', frameOffset) + prompt.Text; | |||||
try { return ((ChoicePrompt)prompt).Start(); } catch (InvalidCastException) {} | |||||
try { return ((InputPrompt)prompt).Start(); } catch (InvalidCastException) {} | |||||
} | |||||
return null; | |||||
} | |||||
public void Clear(int bottomOffset = 2) | |||||
{ | |||||
for (int i = 0; i < Console.WindowHeight - (6 + bottomOffset); i++) | |||||
{ | |||||
Console.SetCursorPosition(DisplayOffset, i + 6); | |||||
Console.Write(new string(' ', DisplayWidth)); | |||||
} | |||||
Console.SetCursorPosition(0, 6); | |||||
OpenFrame = this; | |||||
} | |||||
public int AvailableLines() | |||||
{ | |||||
var totalLines = DisplayHeight - (Math.Max(Console.CursorTop - 6, 0)); | |||||
return totalLines; | |||||
} | |||||
public int AvailableChars() | |||||
{ | |||||
var totalChars = Math.Max(Console.CursorLeft - DisplayOffset, 0) + (AvailableLines() * DisplayWidth); | |||||
return totalChars; | |||||
} | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,397 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Diagnostics.Contracts; | |||||
using System.Linq; | |||||
namespace Ameliorated.ConsoleUtils | |||||
{ | |||||
public partial class ConsoleTUI | |||||
{ | |||||
public partial class Frame | |||||
{ | |||||
/// <summary> | |||||
/// Centered Line | |||||
/// </summary> | |||||
public enum LineCenterOptions | |||||
{ | |||||
Word = 0, | |||||
Character = 1 | |||||
} | |||||
/// <summary> | |||||
/// Normal (Indented) Line | |||||
/// </summary> | |||||
public void WriteLine() | |||||
{ | |||||
Console.WriteLine(); | |||||
} | |||||
public void Write(string text) | |||||
{ | |||||
var lines = text.SplitByLine(); | |||||
if (lines.Length > AvailableLines()) | |||||
Clear(); | |||||
foreach (var line in lines.Take(lines.Length - 1)) | |||||
{ | |||||
Console.WriteLine(line.Insert(0, new string(' ', DisplayOffset))); | |||||
} | |||||
Console.Write(lines.Last().Insert(0, new string(' ', DisplayOffset))); | |||||
} | |||||
public void WriteLine(string text) | |||||
{ | |||||
var lines = text.SplitByLine(); | |||||
if (lines.Length > AvailableLines()) | |||||
Clear(); | |||||
foreach (var line in lines) | |||||
{ | |||||
Console.WriteLine(line.Insert(0, new string(' ', DisplayOffset))); | |||||
} | |||||
} | |||||
public void WriteLine(string text, ConsoleColor? foreground) | |||||
{ | |||||
var lines = text.SplitByLine(); | |||||
if (lines.Length > AvailableLines()) | |||||
Clear(); | |||||
foreach (var line in lines) | |||||
{ | |||||
Console.Write(new string(' ', DisplayOffset)); | |||||
ConsoleUtils.SetColor(foreground); | |||||
Console.WriteLine(line); | |||||
ConsoleUtils.ResetColor(); | |||||
} | |||||
} | |||||
public void WriteLine(string text, ConsoleColor? foreground, ConsoleColor? background) | |||||
{ | |||||
var lines = text.SplitByLine(); | |||||
if (lines.Length > AvailableLines()) | |||||
Clear(); | |||||
foreach (var line in lines) | |||||
{ | |||||
Console.Write(new string(' ', DisplayOffset)); | |||||
ConsoleUtils.SetColor(foreground, background); | |||||
Console.WriteLine(text); | |||||
ConsoleUtils.ResetColor(); | |||||
} | |||||
} | |||||
public void WriteLine(string text, int offset) | |||||
{ | |||||
var lines = text.SplitByLine(); | |||||
if (lines.Length > AvailableLines()) | |||||
Clear(); | |||||
foreach (var line in lines) | |||||
{ | |||||
Console.WriteLine(line.Insert(0, new string(' ', DisplayOffset + offset))); | |||||
} | |||||
} | |||||
public void WriteLine(string text, int offset, ConsoleColor? foreground) | |||||
{ | |||||
var lines = text.SplitByLine(); | |||||
if (lines.Length > AvailableLines()) | |||||
Clear(); | |||||
foreach (var line in lines) | |||||
{ | |||||
Console.Write(new string(' ', DisplayOffset + offset)); | |||||
ConsoleUtils.SetColor(foreground); | |||||
Console.WriteLine(line); | |||||
ConsoleUtils.ResetColor(); | |||||
} | |||||
} | |||||
public void WriteLine(string text, int offset, ConsoleColor? foreground, ConsoleColor? background) | |||||
{ | |||||
var lines = text.SplitByLine(); | |||||
if (lines.Length > AvailableLines()) | |||||
Clear(); | |||||
foreach (var line in lines) | |||||
{ | |||||
Console.Write(new string(' ', DisplayOffset + offset)); | |||||
ConsoleUtils.SetColor(foreground, background); | |||||
Console.WriteLine(line); | |||||
ConsoleUtils.ResetColor(); | |||||
} | |||||
} | |||||
public void WriteCenteredLine(string text, bool ignoreDisplayHeight = false, LineCenterOptions options = LineCenterOptions.Word) | |||||
{ | |||||
var centeredLines = CenterLines(text, options); | |||||
if (centeredLines.Count > AvailableLines() && !ignoreDisplayHeight) | |||||
{ | |||||
Clear(); | |||||
centeredLines = CenterLines(text.TrimStart('\r').TrimStart('\n'), options); | |||||
} | |||||
foreach (var line in centeredLines) Console.WriteLine(line.Value); | |||||
} | |||||
public void WriteCenteredLine(string text, int maxWidth, bool ignoreDisplayHeight = false, LineCenterOptions options = LineCenterOptions.Word) | |||||
{ | |||||
Contract.Requires<ArgumentException>(maxWidth > 1); | |||||
var centeredLines = CenterLines(text, options, maxWidth); | |||||
if (centeredLines.Count >AvailableLines() && !ignoreDisplayHeight) | |||||
Clear(); | |||||
foreach (var line in centeredLines) Console.WriteLine(line.Value); | |||||
} | |||||
public void WriteCenteredLine(string text, ConsoleColor? foreground, bool ignoreDisplayHeight = false, LineCenterOptions options = LineCenterOptions.Word) | |||||
{ | |||||
var centeredLines = CenterLines(text, options); | |||||
if (centeredLines.Count >AvailableLines() && !ignoreDisplayHeight) | |||||
Clear(); | |||||
foreach (var line in centeredLines) | |||||
{ | |||||
Console.Write(new string(' ', line.LeaderLength)); | |||||
ConsoleUtils.SetColor(foreground); | |||||
Console.WriteLine(line.RawString); | |||||
ConsoleUtils.ResetColor(); | |||||
} | |||||
} | |||||
public void WriteCenteredLine(string text, int maxWidth, ConsoleColor? foreground, bool ignoreDisplayHeight = false, LineCenterOptions options = LineCenterOptions.Word) | |||||
{ | |||||
Contract.Requires<ArgumentException>(maxWidth > 1); | |||||
var centeredLines = CenterLines(text, options, maxWidth); | |||||
if (centeredLines.Count >AvailableLines() && !ignoreDisplayHeight) | |||||
Clear(); | |||||
foreach (var line in centeredLines) | |||||
{ | |||||
Console.Write(new string(' ', line.LeaderLength)); | |||||
ConsoleUtils.SetColor(foreground); | |||||
Console.WriteLine(line.RawString); | |||||
ConsoleUtils.ResetColor(); | |||||
} | |||||
} | |||||
public void WriteCenteredLine(string text, ConsoleColor? foreground, ConsoleColor? background, bool ignoreDisplayHeight = false, LineCenterOptions options = LineCenterOptions.Word) | |||||
{ | |||||
var centeredLines = CenterLines(text, options); | |||||
if (centeredLines.Count > AvailableLines() && !ignoreDisplayHeight) | |||||
{ | |||||
Clear(); | |||||
centeredLines = CenterLines(text.TrimStart('\r').TrimStart('\n'), options); | |||||
} | |||||
foreach (var line in centeredLines) | |||||
{ | |||||
Console.Write(new string(' ', line.LeaderLength)); | |||||
ConsoleUtils.SetColor(foreground, background); | |||||
Console.WriteLine(line.RawString); | |||||
ConsoleUtils.ResetColor(); | |||||
} | |||||
} | |||||
public void WriteCenteredLine(string text, int maxWidth, ConsoleColor? foreground, ConsoleColor? background, bool ignoreDisplayHeight = false, LineCenterOptions options = LineCenterOptions.Word) | |||||
{ | |||||
Contract.Requires<ArgumentException>(maxWidth > 1); | |||||
var centeredLines = CenterLines(text, options, maxWidth); | |||||
if (centeredLines.Count >AvailableLines() && !ignoreDisplayHeight) | |||||
Clear(); | |||||
foreach (var line in centeredLines) | |||||
{ | |||||
Console.Write(new string(' ', line.LeaderLength)); | |||||
ConsoleUtils.SetColor(foreground, background); | |||||
Console.WriteLine(line.RawString); | |||||
ConsoleUtils.ResetColor(); | |||||
} | |||||
} | |||||
public void WriteCentered(string text, bool ignoreDisplayHeight = false, LineCenterOptions options = LineCenterOptions.Word) | |||||
{ | |||||
var centeredLines = CenterLines(text, options); | |||||
if (centeredLines.Count > AvailableLines() && !ignoreDisplayHeight) | |||||
{ | |||||
Clear(); | |||||
centeredLines = CenterLines(text.TrimStart('\r').TrimStart('\n'), options); | |||||
} | |||||
foreach (var line in centeredLines.Take(centeredLines.Count - 1)) Console.WriteLine(line.Value); | |||||
Console.Write(centeredLines.Last().Value); | |||||
} | |||||
public void WriteCentered(string text, int maxWidth, bool ignoreDisplayHeight = false, LineCenterOptions options = LineCenterOptions.Word) | |||||
{ | |||||
Contract.Requires<ArgumentException>(maxWidth > 1); | |||||
var centeredLines = CenterLines(text, options, maxWidth); | |||||
if (centeredLines.Count >AvailableLines() && !ignoreDisplayHeight) | |||||
Clear(); | |||||
foreach (var line in centeredLines.Take(centeredLines.Count - 1)) Console.WriteLine(line.Value); | |||||
Console.Write(centeredLines.Last().Value); | |||||
} | |||||
public void WriteCentered(string text, ConsoleColor? foreground, bool ignoreDisplayHeight = false, LineCenterOptions options = LineCenterOptions.Word) | |||||
{ | |||||
var centeredLines = CenterLines(text, options); | |||||
if (centeredLines.Count >AvailableLines() && !ignoreDisplayHeight) | |||||
Clear(); | |||||
foreach (var line in centeredLines.Take(centeredLines.Count - 1)) | |||||
{ | |||||
Console.Write(new string(' ', line.LeaderLength)); | |||||
ConsoleUtils.SetColor(foreground); | |||||
Console.WriteLine(line.RawString); | |||||
ConsoleUtils.ResetColor(); | |||||
} | |||||
Console.Write(new string(' ', centeredLines.Last().LeaderLength)); | |||||
ConsoleUtils.SetColor(foreground); | |||||
Console.WriteLine(centeredLines.Last().RawString); | |||||
ConsoleUtils.ResetColor(); | |||||
} | |||||
public void WriteCentered(string text, int maxWidth, ConsoleColor? foreground, bool ignoreDisplayHeight = false, LineCenterOptions options = LineCenterOptions.Word) | |||||
{ | |||||
Contract.Requires<ArgumentException>(maxWidth > 1); | |||||
var centeredLines = CenterLines(text, options, maxWidth); | |||||
if (centeredLines.Count >AvailableLines() && !ignoreDisplayHeight) | |||||
Clear(); | |||||
foreach (var line in centeredLines.Take(centeredLines.Count - 1)) | |||||
{ | |||||
Console.Write(new string(' ', line.LeaderLength)); | |||||
ConsoleUtils.SetColor(foreground); | |||||
Console.WriteLine(line.RawString); | |||||
ConsoleUtils.ResetColor(); | |||||
} | |||||
Console.Write(new string(' ', centeredLines.Last().LeaderLength)); | |||||
ConsoleUtils.SetColor(foreground); | |||||
Console.WriteLine(centeredLines.Last().RawString); | |||||
ConsoleUtils.ResetColor(); | |||||
} | |||||
public void WriteCentered(string text, ConsoleColor? foreground, ConsoleColor? background, bool ignoreDisplayHeight = false, LineCenterOptions options = LineCenterOptions.Word) | |||||
{ | |||||
var centeredLines = CenterLines(text, options); | |||||
if (centeredLines.Count >AvailableLines() && !ignoreDisplayHeight) | |||||
Clear(); | |||||
foreach (var line in centeredLines.Take(centeredLines.Count - 1)) | |||||
{ | |||||
Console.Write(new string(' ', line.LeaderLength)); | |||||
ConsoleUtils.SetColor(foreground, background); | |||||
Console.WriteLine(line.RawString); | |||||
ConsoleUtils.ResetColor(); | |||||
} | |||||
Console.Write(new string(' ', centeredLines.Last().LeaderLength)); | |||||
ConsoleUtils.SetColor(foreground, background); | |||||
Console.WriteLine(centeredLines.Last().RawString); | |||||
ConsoleUtils.ResetColor(); | |||||
} | |||||
public void WriteCentered(string text, int maxWidth, ConsoleColor? foreground, ConsoleColor? background, bool ignoreDisplayHeight = false, LineCenterOptions options = LineCenterOptions.Word) | |||||
{ | |||||
Contract.Requires<ArgumentException>(maxWidth > 1); | |||||
var centeredLines = CenterLines(text, options, maxWidth); | |||||
if (centeredLines.Count >AvailableLines() && !ignoreDisplayHeight) | |||||
Clear(); | |||||
foreach (var line in centeredLines.Take(centeredLines.Count - 1)) | |||||
{ | |||||
Console.Write(new string(' ', line.LeaderLength)); | |||||
ConsoleUtils.SetColor(foreground, background); | |||||
Console.WriteLine(line.RawString); | |||||
ConsoleUtils.ResetColor(); | |||||
} | |||||
Console.Write(new string(' ', centeredLines.Last().LeaderLength)); | |||||
ConsoleUtils.SetColor(foreground, background); | |||||
Console.WriteLine(centeredLines.Last().RawString); | |||||
ConsoleUtils.ResetColor(); | |||||
} | |||||
// TODO: Fix this splitting lines when a piece of text can fit on one line | |||||
private List<CenteredString> CenterLines(string text, LineCenterOptions options, int maxWidth = 0) | |||||
{ | |||||
var _maxWidth = DisplayWidth; | |||||
if (maxWidth != 0) _maxWidth = maxWidth; | |||||
var list = new List<CenteredString>(); | |||||
var lines = new List<string>(); | |||||
foreach (var line in text.SplitByLine()) | |||||
{ | |||||
if (line == "") | |||||
{ | |||||
list.Add(new CenteredString | |||||
{ Value = "", LeaderLength = 0 }); | |||||
continue; | |||||
} | |||||
if (line.Length > _maxWidth) | |||||
{ | |||||
for (var index = 0; index < line.Length;) | |||||
{ | |||||
var splitLine = line.Substring(index, Math.Min(_maxWidth, line.Length - index)); | |||||
var trimmedLength = splitLine.Length - splitLine.Trim(' ').Length; | |||||
splitLine = splitLine.Trim(' '); | |||||
var wordIndex = splitLine.LastIndexOf(' '); | |||||
if (wordIndex != -1 && options == LineCenterOptions.Word) splitLine = splitLine.Substring(0, wordIndex); | |||||
index += splitLine.Length + trimmedLength; | |||||
list.Add(CenterLine(splitLine)); | |||||
} | |||||
continue; | |||||
} | |||||
list.Add(CenterLine(line)); | |||||
} | |||||
return list; | |||||
} | |||||
private CenteredString CenterLine(string text, int maxWidth = 0) | |||||
{ | |||||
var _maxWidth = DisplayWidth; | |||||
if (maxWidth != 0) _maxWidth = maxWidth; | |||||
var centeredString = new CenteredString(); | |||||
var space = ""; | |||||
if (!(text.Length % 2).Equals(0) && text.Length != _maxWidth) space = " "; | |||||
var leadingLength = (_maxWidth - text.Length) / 2; | |||||
centeredString.Value = space + text.PadLeft(text.Length + leadingLength, ' ').Insert(0, new string(' ', DisplayOffset)); | |||||
centeredString.LeaderLength = leadingLength + DisplayOffset + space.Length; | |||||
centeredString.RawString = text; | |||||
return centeredString; | |||||
} | |||||
private class CenteredString | |||||
{ | |||||
public int LeaderLength; | |||||
public string RawString; | |||||
public string Value; | |||||
} | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,433 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
using System.Threading; | |||||
using System.Windows.Forms; | |||||
using amecs; | |||||
namespace Ameliorated.ConsoleUtils | |||||
{ | |||||
public class Menu | |||||
{ | |||||
public List<MenuItem> Choices { get; set; } = new List<MenuItem>(); | |||||
private int TotalOffset = 2; | |||||
private int? _offset = null; | |||||
public int Offset | |||||
{ | |||||
get | |||||
{ | |||||
if (_offset == null) | |||||
_offset = BindToOpenFrame ? 5 : 2; | |||||
return _offset.Value; | |||||
} | |||||
set { _offset = value; } | |||||
} | |||||
public ConsoleColor? SelectionForeground { get; set; } = ConsoleColor.Green; | |||||
public ConsoleColor? SelectionBackgound { get; set; } = null; | |||||
public bool CloseFrame { get; set; } = true; | |||||
private bool _bindToOpenFrame; | |||||
public bool BindToOpenFrame { get; set; } = true; | |||||
private int menuStart; | |||||
private int pages; | |||||
private int choicesPerPage; | |||||
public void Write() | |||||
{ | |||||
if (Choices.Count < 1) throw new ArgumentException("Property Choices must have at least one choice."); | |||||
_bindToOpenFrame = ConsoleTUI.OpenFrame != null && BindToOpenFrame; | |||||
int totalStaticChoices = Choices.Count(x => x.IsStatic || x.IsNextButton || x.IsPreviousButton); | |||||
if (_bindToOpenFrame) | |||||
{ | |||||
pages = (int)Math.Ceiling(((double)Choices.Count - totalStaticChoices) / (double)(ConsoleTUI.OpenFrame.DisplayHeight - totalStaticChoices + 1)); | |||||
choicesPerPage = (ConsoleTUI.OpenFrame.DisplayHeight - totalStaticChoices + 1); | |||||
} | |||||
else | |||||
{ | |||||
pages = (int)Math.Ceiling(((double)Choices.Count - totalStaticChoices) / (double)(((Console.WindowHeight - Console.CursorTop) - totalStaticChoices))); | |||||
choicesPerPage = (Console.WindowHeight - Console.CursorTop) - totalStaticChoices; | |||||
} | |||||
if (_bindToOpenFrame) | |||||
ConsoleTUI.OpenFrame.Clear(); | |||||
TotalOffset = _bindToOpenFrame ? ConsoleTUI.OpenFrame.DisplayOffset + Offset : Offset; | |||||
menuStart = Console.CursorTop; | |||||
if (_bindToOpenFrame) | |||||
{ | |||||
Console.SetCursorPosition(TotalOffset, Console.CursorTop); | |||||
} | |||||
var fluidChoices = Choices.Where(x => !x.IsStatic && !x.IsNextButton && !x.IsPreviousButton).Take(choicesPerPage); | |||||
var staticChoices = Choices.Where(x => x.IsStatic || (pages > 1 && x.IsNextButton)); | |||||
WriteChoiceList(fluidChoices.Concat(staticChoices)); | |||||
Frame = ConsoleTUI.OpenFrame; | |||||
if (_bindToOpenFrame && CloseFrame) | |||||
{ | |||||
try | |||||
{ | |||||
var offset = ConsoleTUI.OpenFrame.DisplayOffset; | |||||
if (pages == 1) | |||||
ConsoleTUI.OpenFrame.Close(); | |||||
else | |||||
ConsoleTUI.OpenFrame.Close($"Page 1/{pages}"); | |||||
Console.WriteLine(new string(' ', offset) + "Use the arrow keys to navigate"); | |||||
} catch (Exception e) | |||||
{ | |||||
Console.WriteLine(e); | |||||
Console.ReadLine(); | |||||
} | |||||
} | |||||
} | |||||
private void WriteChoiceList(IEnumerable<MenuItem> list) | |||||
{ | |||||
bool selectedWritten = false; | |||||
Console.SetCursorPosition(0, Console.CursorTop); | |||||
foreach (MenuItem choice in list) | |||||
{ | |||||
if (_bindToOpenFrame) | |||||
{ | |||||
Console.Write( | |||||
new string(' ', TotalOffset)); | |||||
if (choice.IsEnabled && !selectedWritten) | |||||
{ | |||||
choice.WriteSelected(SelectionForeground, SelectionBackgound); | |||||
selectedWritten = true; | |||||
Console.WriteLine(); | |||||
continue; | |||||
} | |||||
choice.Write(); | |||||
} | |||||
else | |||||
{ | |||||
Console.Write( | |||||
new string(' ', TotalOffset)); | |||||
if (choice.IsEnabled && !selectedWritten) | |||||
{ | |||||
choice.WriteSelected(SelectionForeground, SelectionBackgound); | |||||
selectedWritten = true; | |||||
Console.WriteLine(); | |||||
continue; | |||||
} | |||||
choice.Write(); | |||||
} | |||||
Console.WriteLine(); | |||||
} | |||||
Console.SetCursorPosition(Console.CursorLeft, Console.CursorTop - 1); | |||||
} | |||||
private List<MenuItem> ValidChoices = new List<MenuItem>(); | |||||
private ConsoleTUI.Frame Frame; | |||||
public object Load() | |||||
{ | |||||
var visCache = Console.CursorVisible; | |||||
Console.CursorVisible = false; | |||||
int index = Math.Max(Choices.FindIndex(x => x.IsEnabled), 0); | |||||
int validIndex = 0; | |||||
ConsoleKey keyPressed; | |||||
Console.SetCursorPosition(Console.CursorLeft, menuStart + index); | |||||
var allFluidChoices = Choices.Where(x => !x.IsStatic && !x.IsNextButton && !x.IsPreviousButton).ToList(); | |||||
var allStaticChoices = Choices.Where(x => x.IsStatic || x.IsNextButton || x.IsPreviousButton).ToList(); | |||||
int pageIndex = 1; | |||||
ConsoleUtils.ClearInputBuffer(); | |||||
var currentChoices = allFluidChoices.Take(choicesPerPage).Concat(Choices.Where(x => x.IsStatic || (pages > 1 && x.IsNextButton))).ToList(); | |||||
var currentValidChoices = currentChoices.Where(x => x.IsEnabled).ToList(); | |||||
while (true) | |||||
{ | |||||
keyPressed = Console.ReadKey(true).Key; | |||||
if (keyPressed == ConsoleKey.DownArrow || keyPressed == ConsoleKey.S) | |||||
{ | |||||
if (validIndex >= currentValidChoices.Count - 1) continue; | |||||
Console.SetCursorPosition(Math.Max(TotalOffset - 2, 0), Console.CursorTop); | |||||
Console.Write(" "); | |||||
currentValidChoices[validIndex].Write(); | |||||
var fromTop = currentChoices.Skip(index + 1).TakeWhile(x => !x.IsEnabled).Count() + 1; | |||||
var choice = currentChoices.Skip(index + 1).First(x => x.IsEnabled); | |||||
Console.SetCursorPosition(TotalOffset, Console.CursorTop + fromTop); | |||||
choice.WriteSelected(SelectionForeground, SelectionBackgound); | |||||
index += fromTop; | |||||
validIndex += 1; | |||||
} | |||||
if (keyPressed == ConsoleKey.UpArrow || keyPressed == ConsoleKey.W) | |||||
{ | |||||
if (!(validIndex > 0)) continue; | |||||
Console.SetCursorPosition(Math.Max(TotalOffset - 2, 0), Console.CursorTop); | |||||
Console.Write(" "); | |||||
currentValidChoices[validIndex].Write(); | |||||
var fromTop = -currentChoices.Take(index).Reverse().TakeWhile(x => !x.IsEnabled).Count() - 1; | |||||
var choice = currentChoices.Take(index).Last(x => x.IsEnabled); | |||||
Console.SetCursorPosition(TotalOffset, Console.CursorTop + fromTop); | |||||
choice.WriteSelected(SelectionForeground, SelectionBackgound); | |||||
index += fromTop; | |||||
validIndex -= 1; | |||||
} | |||||
if (keyPressed == ConsoleKey.RightArrow || keyPressed == ConsoleKey.A || keyPressed == ConsoleKey.PageUp || | |||||
(keyPressed == ConsoleKey.Enter && currentValidChoices[validIndex].IsNextButton)) | |||||
{ | |||||
if (pageIndex == pages) | |||||
continue; | |||||
Frame.Clear(); | |||||
pageIndex++; | |||||
var pIndex = pageIndex; | |||||
var fluidChoices = allFluidChoices.Skip((pIndex - 1) * choicesPerPage).Take(choicesPerPage).ToList(); | |||||
var staticChoices = allStaticChoices.Where(x => !(pages <= pIndex && x.IsNextButton)); | |||||
Console.SetCursorPosition(Console.CursorLeft, menuStart); | |||||
currentChoices = fluidChoices.Concat(staticChoices).ToList(); | |||||
WriteChoiceList(currentChoices); | |||||
if (_bindToOpenFrame && CloseFrame) | |||||
{ | |||||
try | |||||
{ | |||||
var offset = ConsoleTUI.OpenFrame.DisplayOffset; | |||||
if (pages == 1) | |||||
ConsoleTUI.OpenFrame.Close(); | |||||
else | |||||
ConsoleTUI.OpenFrame.Close($"Page {pIndex}/{pages}"); | |||||
Console.WriteLine(new string(' ', offset) + "Use the arrow keys to navigate"); | |||||
} catch (Exception e) | |||||
{ | |||||
Console.WriteLine(e); | |||||
Console.ReadLine(); | |||||
} | |||||
} | |||||
Console.SetCursorPosition(Console.CursorLeft, menuStart); | |||||
currentValidChoices = currentChoices.Where(x => x.IsEnabled).ToList(); | |||||
index = 0; | |||||
validIndex = 0; | |||||
continue; | |||||
} | |||||
if (keyPressed == ConsoleKey.LeftArrow || keyPressed == ConsoleKey.D || keyPressed == ConsoleKey.PageDown || | |||||
(keyPressed == ConsoleKey.Enter && currentValidChoices[validIndex].IsPreviousButton)) | |||||
{ | |||||
if (pageIndex == 1) | |||||
continue; | |||||
Frame.Clear(); | |||||
pageIndex--; | |||||
var pIndex = pageIndex; | |||||
var fluidChoices = allFluidChoices.Skip((pIndex - 1) * choicesPerPage).Take(choicesPerPage).ToList(); | |||||
var staticChoices = allStaticChoices.Where(x => !(pIndex <= 1 && x.IsPreviousButton)); | |||||
Console.SetCursorPosition(Console.CursorLeft, menuStart); | |||||
currentChoices = fluidChoices.Concat(staticChoices).ToList(); | |||||
WriteChoiceList(currentChoices); | |||||
if (_bindToOpenFrame && CloseFrame) | |||||
{ | |||||
try | |||||
{ | |||||
var offset = ConsoleTUI.OpenFrame.DisplayOffset; | |||||
if (pages == 1) | |||||
ConsoleTUI.OpenFrame.Close(); | |||||
else | |||||
ConsoleTUI.OpenFrame.Close($"Page {pIndex}/{pages}"); | |||||
Console.WriteLine(new string(' ', offset) + "Use the arrow keys to navigate"); | |||||
} catch (Exception e) | |||||
{ | |||||
Console.WriteLine(e); | |||||
Console.ReadLine(); | |||||
} | |||||
} | |||||
Console.SetCursorPosition(Console.CursorLeft, menuStart); | |||||
currentValidChoices = currentChoices.Where(x => x.IsEnabled).ToList(); | |||||
index = 0; | |||||
validIndex = 0; | |||||
continue; | |||||
} | |||||
if (keyPressed == ConsoleKey.Enter) | |||||
{ | |||||
break; | |||||
} | |||||
} | |||||
if (CloseFrame) | |||||
Frame.Clear(); | |||||
Console.CursorVisible = visCache; | |||||
return currentValidChoices[validIndex].ReturnValue; | |||||
} | |||||
private bool NextButtonPresent() | |||||
{ | |||||
return Choices.Any(x => x.IsNextButton); | |||||
} | |||||
private bool PreviousButtonPresent() | |||||
{ | |||||
return Choices.Any(x => x.IsNextButton); | |||||
} | |||||
public class MenuItem | |||||
{ | |||||
public object ReturnValue { get; set; } | |||||
public static readonly MenuItem Blank = new MenuItem("", null); | |||||
public static readonly MenuItem BlankStatic = new MenuItem("", null) { IsStatic = true }; | |||||
public bool IsNextButton { get; set; } = false; | |||||
public bool IsPreviousButton { get; set; } = false; | |||||
public bool IsStatic { get; set; } = false; | |||||
public string PrimaryText { get; set; } = ""; | |||||
public string SecondaryText { get; set; } = ""; | |||||
public MenuItem(string primaryText, object returnValue) | |||||
{ | |||||
PrimaryText = primaryText; | |||||
ReturnValue = returnValue; | |||||
} | |||||
public bool AddBetweenSpace { get; set; } = true; | |||||
private ConsoleColor? _primaryTextForeground = null; | |||||
public ConsoleColor? PrimaryTextForeground | |||||
{ | |||||
get | |||||
{ | |||||
if (_primaryTextForeground.HasValue) | |||||
return _primaryTextForeground; | |||||
if (IsEnabled) return null; | |||||
if (Console.ForegroundColor == ConsoleColor.White) return ConsoleColor.DarkGray; | |||||
if (Console.ForegroundColor == ConsoleColor.White) return ConsoleColor.DarkGray; | |||||
return null; | |||||
} | |||||
set { _primaryTextForeground = value; } | |||||
} | |||||
public ConsoleColor? PrimaryTextBackground { get; set; } = null; | |||||
public ConsoleColor? SecondaryTextForeground { get; set; } = null; | |||||
public ConsoleColor? SecondaryTextBackground { get; set; } = null; | |||||
private bool? _isEnabled = null; | |||||
public bool IsEnabled | |||||
{ | |||||
get | |||||
{ | |||||
if (_isEnabled.HasValue) | |||||
return _isEnabled.Value; | |||||
if (!String.IsNullOrEmpty(PrimaryText) || !String.IsNullOrEmpty(SecondaryText)) | |||||
{ | |||||
return true; | |||||
} | |||||
return false; | |||||
} | |||||
set { _isEnabled = value; } | |||||
} | |||||
public bool StretchSelection = false; | |||||
public void Write() | |||||
{ | |||||
if (!String.IsNullOrEmpty(PrimaryText)) | |||||
{ | |||||
ConsoleUtils.SetColor(PrimaryTextForeground, PrimaryTextBackground); | |||||
Console.Write(PrimaryText); | |||||
ConsoleUtils.ResetColor(); | |||||
if (AddBetweenSpace) | |||||
Console.Write(' '); | |||||
} | |||||
if (String.IsNullOrEmpty(SecondaryText)) | |||||
return; | |||||
ConsoleUtils.SetColor(SecondaryTextForeground, SecondaryTextBackground); | |||||
Console.Write(SecondaryText); | |||||
ConsoleUtils.ResetColor(); | |||||
} | |||||
public void WriteSelected(ConsoleColor? foreground, ConsoleColor? background) | |||||
{ | |||||
Console.SetCursorPosition(Console.CursorLeft - 2, Console.CursorTop); | |||||
if (!String.IsNullOrEmpty(PrimaryText)) | |||||
{ | |||||
ConsoleUtils.SetColor(foreground, background); | |||||
Console.Write("> " + PrimaryText); | |||||
if (!StretchSelection) | |||||
ConsoleUtils.ResetColor(); | |||||
if (AddBetweenSpace) | |||||
Console.Write(' '); | |||||
} | |||||
if (String.IsNullOrEmpty(SecondaryText)) | |||||
{ | |||||
if (StretchSelection) | |||||
ConsoleUtils.ResetColor(); | |||||
return; | |||||
} | |||||
if (!String.IsNullOrEmpty(PrimaryText) && !StretchSelection) | |||||
ConsoleUtils.SetColor(SecondaryTextForeground, SecondaryTextBackground); | |||||
Console.Write(SecondaryText); | |||||
ConsoleUtils.ResetColor(); | |||||
} | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,196 @@ | |||||
using System; | |||||
using System.Runtime.InteropServices; | |||||
using System.Threading; | |||||
namespace Ameliorated.ConsoleUtils | |||||
{ | |||||
// TODO: Integrate this into ConsoleTUI.cs | |||||
// https://stackoverflow.com/questions/1944481/console-app-mouse-click-x-y-coordinate-detection-comparison | |||||
/* | |||||
public class MouseInterface | |||||
{ | |||||
public static class ConsoleListener | |||||
{ | |||||
public static event ConsoleMouseEvent MouseEvent; | |||||
public static event ConsoleKeyEvent KeyEvent; | |||||
public static event ConsoleWindowBufferSizeEvent WindowBufferSizeEvent; | |||||
private static bool Run = false; | |||||
public static void Start() | |||||
{ | |||||
if (!Run) | |||||
{ | |||||
Run = true; | |||||
IntPtr handleIn = GetStdHandle(STD_INPUT_HANDLE); | |||||
new Thread(() => | |||||
{ | |||||
while (true) | |||||
{ | |||||
uint numRead = 0; | |||||
INPUT_RECORD[] record = new INPUT_RECORD[1]; | |||||
record[0] = new INPUT_RECORD(); | |||||
ReadConsoleInput(handleIn, record, 1, ref numRead); | |||||
if (Run) | |||||
switch (record[0].EventType) | |||||
{ | |||||
case INPUT_RECORD.MOUSE_EVENT: | |||||
MouseEvent?.Invoke(record[0].MouseEvent); | |||||
break; | |||||
case INPUT_RECORD.KEY_EVENT: | |||||
KeyEvent?.Invoke(record[0].KeyEvent); | |||||
break; | |||||
case INPUT_RECORD.WINDOW_BUFFER_SIZE_EVENT: | |||||
WindowBufferSizeEvent?.Invoke(record[0].WindowBufferSizeEvent); | |||||
break; | |||||
} | |||||
else | |||||
{ | |||||
uint numWritten = 0; | |||||
WriteConsoleInput(handleIn, record, 1, ref numWritten); | |||||
return; | |||||
} | |||||
} | |||||
}).Start(); | |||||
} | |||||
} | |||||
public static void Stop() => Run = false; | |||||
public delegate void ConsoleMouseEvent(MOUSE_EVENT_RECORD r); | |||||
public delegate void ConsoleKeyEvent(KEY_EVENT_RECORD r); | |||||
public delegate void ConsoleWindowBufferSizeEvent(WINDOW_BUFFER_SIZE_RECORD r); | |||||
// NATIVE METHODS | |||||
public struct COORD | |||||
{ | |||||
public short X; | |||||
public short Y; | |||||
public COORD(short x, short y) | |||||
{ | |||||
X = x; | |||||
Y = y; | |||||
} | |||||
} | |||||
[StructLayout(LayoutKind.Explicit)] | |||||
public struct INPUT_RECORD | |||||
{ | |||||
public const ushort KEY_EVENT = 0x0001, | |||||
MOUSE_EVENT = 0x0002, | |||||
WINDOW_BUFFER_SIZE_EVENT = 0x0004; //more | |||||
[FieldOffset(0)] public ushort EventType; | |||||
[FieldOffset(4)] public KEY_EVENT_RECORD KeyEvent; | |||||
[FieldOffset(4)] public MOUSE_EVENT_RECORD MouseEvent; | |||||
[FieldOffset(4)] public WINDOW_BUFFER_SIZE_RECORD WindowBufferSizeEvent; | |||||
/* | |||||
and: | |||||
MENU_EVENT_RECORD MenuEvent; | |||||
FOCUS_EVENT_RECORD FocusEvent; | |||||
~/ <--- end comment | |||||
} | |||||
public struct MOUSE_EVENT_RECORD | |||||
{ | |||||
public COORD dwMousePosition; | |||||
public const uint FROM_LEFT_1ST_BUTTON_PRESSED = 0x0001, | |||||
FROM_LEFT_2ND_BUTTON_PRESSED = 0x0004, | |||||
FROM_LEFT_3RD_BUTTON_PRESSED = 0x0008, | |||||
FROM_LEFT_4TH_BUTTON_PRESSED = 0x0010, | |||||
RIGHTMOST_BUTTON_PRESSED = 0x0002; | |||||
public uint dwButtonState; | |||||
public const int CAPSLOCK_ON = 0x0080, | |||||
ENHANCED_KEY = 0x0100, | |||||
LEFT_ALT_PRESSED = 0x0002, | |||||
LEFT_CTRL_PRESSED = 0x0008, | |||||
NUMLOCK_ON = 0x0020, | |||||
RIGHT_ALT_PRESSED = 0x0001, | |||||
RIGHT_CTRL_PRESSED = 0x0004, | |||||
SCROLLLOCK_ON = 0x0040, | |||||
SHIFT_PRESSED = 0x0010; | |||||
public uint dwControlKeyState; | |||||
public const int DOUBLE_CLICK = 0x0002, | |||||
MOUSE_HWHEELED = 0x0008, | |||||
MOUSE_MOVED = 0x0001, | |||||
MOUSE_WHEELED = 0x0004; | |||||
public uint dwEventFlags; | |||||
} | |||||
[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode)] | |||||
public struct KEY_EVENT_RECORD | |||||
{ | |||||
[FieldOffset(0)] public bool bKeyDown; | |||||
[FieldOffset(4)] public ushort wRepeatCount; | |||||
[FieldOffset(6)] public ushort wVirtualKeyCode; | |||||
[FieldOffset(8)] public ushort wVirtualScanCode; | |||||
[FieldOffset(10)] public char UnicodeChar; | |||||
[FieldOffset(10)] public byte AsciiChar; | |||||
public const int CAPSLOCK_ON = 0x0080, | |||||
ENHANCED_KEY = 0x0100, | |||||
LEFT_ALT_PRESSED = 0x0002, | |||||
LEFT_CTRL_PRESSED = 0x0008, | |||||
NUMLOCK_ON = 0x0020, | |||||
RIGHT_ALT_PRESSED = 0x0001, | |||||
RIGHT_CTRL_PRESSED = 0x0004, | |||||
SCROLLLOCK_ON = 0x0040, | |||||
SHIFT_PRESSED = 0x0010; | |||||
[FieldOffset(12)] public uint dwControlKeyState; | |||||
} | |||||
public struct WINDOW_BUFFER_SIZE_RECORD | |||||
{ | |||||
public COORD dwSize; | |||||
} | |||||
public const uint STD_INPUT_HANDLE = unchecked((uint)-10), | |||||
STD_OUTPUT_HANDLE = unchecked((uint)-11), | |||||
STD_ERROR_HANDLE = unchecked((uint)-12); | |||||
[DllImport("kernel32.dll")] | |||||
public static extern IntPtr GetStdHandle(uint nStdHandle); | |||||
public const uint ENABLE_MOUSE_INPUT = 0x0010, | |||||
ENABLE_QUICK_EDIT_MODE = 0x0040, | |||||
ENABLE_EXTENDED_FLAGS = 0x0080, | |||||
ENABLE_ECHO_INPUT = 0x0004, | |||||
ENABLE_WINDOW_INPUT = 0x0008; //more | |||||
[DllImportAttribute("kernel32.dll")] | |||||
public static extern bool GetConsoleMode(IntPtr hConsoleInput, ref uint lpMode); | |||||
[DllImportAttribute("kernel32.dll")] | |||||
public static extern bool SetConsoleMode(IntPtr hConsoleInput, uint dwMode); | |||||
[DllImportAttribute("kernel32.dll", CharSet = CharSet.Unicode)] | |||||
public static extern bool ReadConsoleInput(IntPtr hConsoleInput, [Out] INPUT_RECORD[] lpBuffer, uint nLength, ref uint lpNumberOfEventsRead); | |||||
[DllImportAttribute("kernel32.dll", CharSet = CharSet.Unicode)] | |||||
public static extern bool WriteConsoleInput(IntPtr hConsoleInput, INPUT_RECORD[] lpBuffer, uint nLength, ref uint lpNumberOfEventsWritten); | |||||
} | |||||
} | |||||
*/ | |||||
} |
@ -0,0 +1,604 @@ | |||||
using System; | |||||
using System.Collections; | |||||
using System.Linq; | |||||
using System.Security; | |||||
using System.Text; | |||||
using System.Threading; | |||||
using System.Windows.Forms; | |||||
using JetBrains.Annotations; | |||||
namespace Ameliorated.ConsoleUtils | |||||
{ | |||||
/// <summary> | |||||
/// Represents a input prompt to be used with the Start method. | |||||
/// </summary> | |||||
public class ChoicePrompt : Prompt | |||||
{ | |||||
public string Choices { get; set; } = "YN"; | |||||
public bool BeepSound { get; set; } = true; | |||||
public bool CaseSensitive { get; set; } = false; | |||||
public bool AllowEscape { get; set; } = true; | |||||
public bool AnyKey { get; set; } = false; | |||||
public ConsoleColor? TextForeground { get; set; } | |||||
private bool _bindToOpenFrame; | |||||
[CanBeNull] | |||||
public new int? Start() | |||||
{ | |||||
if (Choices.Length < 1 && !AnyKey) throw new ArgumentException("There must be at least 1 choice."); | |||||
_bindToOpenFrame = ConsoleTUI.OpenFrame != null && BindToOpenFrame; | |||||
if (_bindToOpenFrame && ConsoleTUI.OpenFrame.AvailableLines() < 1) | |||||
ConsoleTUI.OpenFrame.Clear(); | |||||
if (TextForeground.HasValue) | |||||
ConsoleUtils.SetColor(TextForeground); | |||||
if (_bindToOpenFrame) | |||||
ConsoleTUI.OpenFrame.Write(Text); | |||||
else | |||||
Console.Write(Text); | |||||
if (TextForeground.HasValue) | |||||
ConsoleUtils.ResetColor(); | |||||
var cursorVisibility = Console.CursorVisible; | |||||
int? result; | |||||
while (true) | |||||
{ | |||||
Console.CursorVisible = true; | |||||
ConsoleUtils.ClearInputBuffer(); | |||||
var key = Console.ReadKey(true); | |||||
if (AnyKey) | |||||
{ | |||||
Console.CursorVisible = cursorVisibility; | |||||
return key.KeyChar; | |||||
} | |||||
if (key.Key == ConsoleKey.Escape && AllowEscape) | |||||
{ | |||||
Console.CursorVisible = cursorVisibility; | |||||
return null; | |||||
} | |||||
if (CaseSensitive) | |||||
result = Choices.IndexOf(key.KeyChar.ToString(), StringComparison.Ordinal); | |||||
else | |||||
result = Choices.IndexOf(key.KeyChar.ToString(), StringComparison.OrdinalIgnoreCase); | |||||
if (result >= 0) | |||||
{ | |||||
if (InputForeground.HasValue && InputBackground.HasValue) ConsoleUtils.SetColor(InputForeground.Value, InputBackground.Value); | |||||
else if (InputForeground.HasValue) ConsoleUtils.SetColor(InputForeground.Value); | |||||
else if (InputBackground.HasValue) ConsoleUtils.SetColor(Console.ForegroundColor, InputBackground.Value); | |||||
if (!CaseSensitive) Console.Write(key.KeyChar.ToString().ToUpper()); | |||||
else Console.Write(key.KeyChar.ToString()); | |||||
if (InputForeground.HasValue || InputBackground.HasValue) ConsoleUtils.ResetColor(); | |||||
break; | |||||
} | |||||
else if (BeepSound) Console.Beep(); | |||||
} | |||||
Console.CursorVisible = cursorVisibility; | |||||
Console.WriteLine(); | |||||
return result.Value; | |||||
} | |||||
} | |||||
public class InputPrompt : Prompt | |||||
{ | |||||
[Optional] public ConsoleColor? BoxBackground { get; set; } | |||||
public bool MaskInput { get; set; } = false; | |||||
public bool AlignInput { get; set; } = true; | |||||
[Optional] public int? SplitWidth { get; set; } | |||||
private bool _bindToOpenFrame; | |||||
private int? _splitWidth; | |||||
[CanBeNull] | |||||
public new string Start() | |||||
{ | |||||
if (SplitWidth.HasValue && !AlignInput) throw new ArgumentException("Property SplitWidth must not be used without property AlignInput set to true."); | |||||
_bindToOpenFrame = ConsoleTUI.OpenFrame != null && BindToOpenFrame; | |||||
if (_bindToOpenFrame && ConsoleTUI.OpenFrame.AvailableLines() < 1) | |||||
ConsoleTUI.OpenFrame.Clear(); | |||||
if (!MaxLength.HasValue) | |||||
MaxLength = AlignInput ? ConsoleTUI.OpenFrame.AvailableChars() - (Text.LastLine().Length * ConsoleTUI.OpenFrame.AvailableLines()) : ConsoleTUI.OpenFrame.AvailableChars(); | |||||
int startLeft = Console.CursorLeft + Text.LastLine().Length; | |||||
_splitWidth = null; | |||||
if (AlignInput && !_bindToOpenFrame) | |||||
{ | |||||
if (Text.LastLine().Length > Console.WindowWidth - 3) throw new ArgumentException("Last line of property Text must not be within 3 characters of the available width."); | |||||
_splitWidth = Console.WindowWidth - startLeft; | |||||
} | |||||
if (_bindToOpenFrame) | |||||
{ | |||||
if (SplitWidth.HasValue && (SplitWidth.Value + startLeft + ConsoleTUI.OpenFrame.DisplayOffset >= Console.WindowWidth)) | |||||
throw new ArgumentException($"Property SplitWidth must be less than the available width."); | |||||
// TODO: BAD WORDING | |||||
if (Text.LastLine().Length > ConsoleTUI.OpenFrame.DisplayWidth - 3) throw new ArgumentException("Last line of property Text must not be within 3 characters of the available width."); | |||||
_splitWidth = ConsoleTUI.OpenFrame.DisplayWidth - (startLeft); | |||||
if (!AlignInput) | |||||
_splitWidth = ConsoleTUI.OpenFrame.DisplayWidth; | |||||
} | |||||
if (SplitWidth.HasValue) | |||||
{ | |||||
if (SplitWidth.Value + startLeft >= Console.WindowWidth) | |||||
throw new ArgumentException($"Property SplitWidth must be less than the available width."); | |||||
if (Text.LastLine().Length > Console.WindowWidth - 3) throw new ArgumentException("Last line of property Text must not be within 3 characters of the available width."); | |||||
_splitWidth = SplitWidth.Value; | |||||
} | |||||
/* | |||||
int maxLines = Console.WindowHeight - Console.CursorTop; | |||||
if (_bindToOpenFrame) | |||||
{ | |||||
maxLines = ConsoleTUI.OpenFrame.DisplayHeight - (Console.CursorTop - 6) - Text.SplitByLine().Length; | |||||
if (maxLines < 2) | |||||
{ | |||||
ConsoleTUI.OpenFrame.Clear(); | |||||
if (_bindToOpenFrame) maxLines = ConsoleTUI.OpenFrame.DisplayHeight - (Console.CursorTop - 6) - Text.SplitByLine().Length; | |||||
} | |||||
} | |||||
*/ | |||||
ConsoleUtils.ClearInputBuffer(); | |||||
if (_bindToOpenFrame) | |||||
ConsoleTUI.OpenFrame.Write(Text); | |||||
else | |||||
Console.Write(Text); | |||||
if (BoxBackground.HasValue && _splitWidth.HasValue) | |||||
{ | |||||
if (AlignInput) | |||||
WriteBackground(_splitWidth.Value, BoxBackground.Value); | |||||
else | |||||
WriteBackground(_splitWidth.Value - Text.LastLine().Length, BoxBackground.Value); | |||||
} | |||||
if (BoxBackground.HasValue && !_splitWidth.HasValue) WriteBackground(Console.WindowWidth - Console.CursorLeft, BoxBackground.Value); | |||||
var cursorVisibility = Console.CursorVisible; | |||||
var input = new StringBuilder(); | |||||
ConsoleKeyInfo key; | |||||
do | |||||
{ | |||||
Console.CursorVisible = true; | |||||
key = Console.ReadKey(true); | |||||
if (key.Key == ConsoleKey.Backspace) | |||||
{ | |||||
if (input.Length <= 0) continue; | |||||
input.Remove(input.Length - 1, 1); | |||||
bool movedLines = false; | |||||
if (_bindToOpenFrame) | |||||
{ | |||||
if ((((input.Length + 1) - _splitWidth.Value + Text.LastLine().Length).IsDivisibleBy(ConsoleTUI.OpenFrame.DisplayWidth) || input.Length + 1 == _splitWidth.Value - Text.LastLine().Length) && !AlignInput) | |||||
{ | |||||
if (BoxBackground.HasValue) WriteBackground(_splitWidth.Value - (Console.CursorLeft - ConsoleTUI.OpenFrame.DisplayOffset), Console.BackgroundColor); | |||||
Console.SetCursorPosition((ConsoleTUI.OpenFrame.DisplayOffset) + _splitWidth.Value - 1, Console.CursorTop - 1); | |||||
movedLines = true; | |||||
} | |||||
else if ((input.Length + 1).IsDivisibleBy(_splitWidth.Value) && AlignInput) | |||||
{ | |||||
if (BoxBackground.HasValue) WriteBackground(_splitWidth.Value, Console.BackgroundColor); | |||||
Console.SetCursorPosition(ConsoleTUI.OpenFrame.DisplayOffset + startLeft + _splitWidth.Value - 1, Console.CursorTop - 1); | |||||
movedLines = true; | |||||
} | |||||
} | |||||
else if (AlignInput) | |||||
{ | |||||
if ((input.Length + 1).IsDivisibleBy(_splitWidth.Value)) | |||||
{ | |||||
if (BoxBackground.HasValue) WriteBackground(_splitWidth.Value, Console.BackgroundColor); | |||||
Console.SetCursorPosition(startLeft + _splitWidth.Value, Console.CursorTop - 1); | |||||
movedLines = true; | |||||
} | |||||
} | |||||
else | |||||
{ | |||||
if (((input.Length + 1) - (Console.WindowWidth - startLeft)).IsDivisibleBy(Console.WindowWidth) || input.Length + 1 == Console.WindowWidth - startLeft) | |||||
{ | |||||
if (BoxBackground.HasValue) WriteBackground(Console.WindowWidth, Console.BackgroundColor); | |||||
Console.SetCursorPosition(Console.WindowWidth - 1, Console.CursorTop - 1); | |||||
movedLines = true; | |||||
} | |||||
} | |||||
if (movedLines) | |||||
{ | |||||
if (BoxBackground.HasValue) ConsoleUtils.SetColor(Console.ForegroundColor, BoxBackground.Value); | |||||
Console.Write(" \b"); | |||||
if (BoxBackground.HasValue) ConsoleUtils.ResetColor(); | |||||
} | |||||
else | |||||
{ | |||||
if (BoxBackground.HasValue) ConsoleUtils.SetColor(Console.ForegroundColor, BoxBackground.Value); | |||||
Console.Write("\b \b"); | |||||
if (BoxBackground.HasValue) ConsoleUtils.ResetColor(); | |||||
} | |||||
if (MaxLength.HasValue && MaxLength.Value - 1 == input.Length) Console.CursorVisible = true; | |||||
continue; | |||||
} | |||||
if (Char.IsControl(key.KeyChar)) continue; | |||||
if (MaxLength.HasValue && MaxLength.Value <= input.Length) | |||||
{ | |||||
ConsoleUtils.SetColor(ConsoleColor.DarkRed, InputBackground); | |||||
Console.CursorVisible = false; | |||||
Console.Write("!"); | |||||
Thread.Sleep(200); | |||||
ConsoleUtils.ClearInputBuffer(); | |||||
ConsoleUtils.ResetColor(); | |||||
ConsoleUtils.SetColor(null, BoxBackground); | |||||
Console.Write("\b \b"); | |||||
ConsoleUtils.ResetColor(); | |||||
continue; | |||||
} | |||||
input.Append(key.KeyChar); | |||||
ConsoleUtils.SetColor(InputForeground, InputBackground); | |||||
if (MaskInput) Console.Write("*"); | |||||
else Console.Write(key.KeyChar); | |||||
ConsoleUtils.ResetColor(); | |||||
if (MaxLength.HasValue && MaxLength.Value <= input.Length + 1) | |||||
continue; | |||||
if (_bindToOpenFrame) | |||||
{ | |||||
if (((input.Length - _splitWidth.Value + Text.LastLine().Length).IsDivisibleBy(_splitWidth.Value) || input.Length == _splitWidth.Value - Text.LastLine().Length) && !AlignInput) | |||||
{ | |||||
Console.SetCursorPosition(ConsoleTUI.OpenFrame.DisplayOffset, Console.CursorTop + 1); | |||||
if (BoxBackground.HasValue) WriteBackground(_splitWidth.Value, BoxBackground.Value); | |||||
} | |||||
else if (input.Length.IsDivisibleBy(_splitWidth.Value) && AlignInput) | |||||
{ | |||||
Console.SetCursorPosition(startLeft + ConsoleTUI.OpenFrame.DisplayOffset, Console.CursorTop + 1); | |||||
if (BoxBackground.HasValue) WriteBackground(_splitWidth.Value, BoxBackground.Value); | |||||
} | |||||
} | |||||
else if (AlignInput) | |||||
{ | |||||
if (input.Length.IsDivisibleBy(_splitWidth.Value)) | |||||
{ | |||||
if (SplitWidth.HasValue) | |||||
Console.SetCursorPosition(startLeft, Console.CursorTop + 1); | |||||
else | |||||
// Console will have automatically moved the cursor down | |||||
Console.SetCursorPosition(startLeft, Console.CursorTop); | |||||
if (BoxBackground.HasValue) WriteBackground(_splitWidth.Value, BoxBackground.Value); | |||||
} | |||||
} | |||||
else | |||||
{ | |||||
if ((input.Length - (Console.WindowWidth - startLeft)).IsDivisibleBy(Console.WindowWidth) || input.Length == Console.WindowWidth - startLeft) | |||||
{ | |||||
// Console will have automatically moved the cursor down | |||||
Console.SetCursorPosition(startLeft - Text.LastLine().Length, Console.CursorTop); | |||||
if (BoxBackground.HasValue) WriteBackground(Console.WindowWidth - (startLeft - Text.LastLine().Length), BoxBackground.Value); | |||||
} | |||||
} | |||||
} while (key.Key != ConsoleKey.Enter && (!AllowEscape || (AllowEscape && key.Key != ConsoleKey.Escape))); | |||||
if (input.Length == 0) | |||||
{ | |||||
ConsoleUtils.SetColor(ConsoleColor.DarkGray); | |||||
Console.Write("None"); | |||||
ConsoleUtils.ResetColor(); | |||||
} | |||||
Console.CursorVisible = cursorVisibility; | |||||
Console.WriteLine(); | |||||
if (key.Key == ConsoleKey.Escape && AllowEscape) return null; | |||||
return input.ToString(); | |||||
} | |||||
} | |||||
public class SecureInputPrompt : Prompt | |||||
{ | |||||
[Optional] public ConsoleColor? BoxBackground { get; set; } | |||||
public bool MaskInput { get; set; } = true; | |||||
public bool AlignInput { get; set; } = true; | |||||
[Optional] public int? SplitWidth { get; set; } | |||||
private bool _bindToOpenFrame; | |||||
private int? _splitWidth; | |||||
[CanBeNull] | |||||
public new SecureString Start() | |||||
{if (SplitWidth.HasValue && !AlignInput) throw new ArgumentException("Property SplitWidth must not be used without property AlignInput set to true."); | |||||
_bindToOpenFrame = ConsoleTUI.OpenFrame != null && BindToOpenFrame; | |||||
if (_bindToOpenFrame && ConsoleTUI.OpenFrame.AvailableLines() < 1) | |||||
ConsoleTUI.OpenFrame.Clear(); | |||||
if (!MaxLength.HasValue) | |||||
MaxLength = AlignInput ? ConsoleTUI.OpenFrame.AvailableChars() - (Text.LastLine().Length * ConsoleTUI.OpenFrame.AvailableLines()) : ConsoleTUI.OpenFrame.AvailableChars(); | |||||
int startLeft = Console.CursorLeft + Text.LastLine().Length; | |||||
_splitWidth = null; | |||||
if (AlignInput && !_bindToOpenFrame) | |||||
{ | |||||
if (Text.LastLine().Length > Console.WindowWidth - 3) throw new ArgumentException("Last line of property Text must not be within 3 characters of the available width."); | |||||
_splitWidth = Console.WindowWidth - startLeft; | |||||
} | |||||
if (_bindToOpenFrame) | |||||
{ | |||||
if (SplitWidth.HasValue && (SplitWidth.Value + startLeft + ConsoleTUI.OpenFrame.DisplayOffset >= Console.WindowWidth)) | |||||
throw new ArgumentException($"Property SplitWidth must be less than the available width."); | |||||
// TODO: BAD WORDING | |||||
if (Text.LastLine().Length > ConsoleTUI.OpenFrame.DisplayWidth - 3) throw new ArgumentException("Last line of property Text must not be within 3 characters of the available width."); | |||||
_splitWidth = ConsoleTUI.OpenFrame.DisplayWidth - (startLeft); | |||||
if (!AlignInput) | |||||
_splitWidth = ConsoleTUI.OpenFrame.DisplayWidth; | |||||
} | |||||
if (SplitWidth.HasValue) | |||||
{ | |||||
if (SplitWidth.Value + startLeft >= Console.WindowWidth) | |||||
throw new ArgumentException($"Property SplitWidth must be less than the available width."); | |||||
if (Text.LastLine().Length > Console.WindowWidth - 3) throw new ArgumentException("Last line of property Text must not be within 3 characters of the available width."); | |||||
_splitWidth = SplitWidth.Value; | |||||
} | |||||
/* | |||||
int maxLines = Console.WindowHeight - Console.CursorTop; | |||||
if (_bindToOpenFrame) | |||||
{ | |||||
maxLines = ConsoleTUI.OpenFrame.DisplayHeight - (Console.CursorTop - 6) - Text.SplitByLine().Length; | |||||
if (maxLines < 2) | |||||
{ | |||||
ConsoleTUI.OpenFrame.Clear(); | |||||
if (_bindToOpenFrame) maxLines = ConsoleTUI.OpenFrame.DisplayHeight - (Console.CursorTop - 6) - Text.SplitByLine().Length; | |||||
} | |||||
} | |||||
*/ | |||||
ConsoleUtils.ClearInputBuffer(); | |||||
if (_bindToOpenFrame) | |||||
ConsoleTUI.OpenFrame.Write(Text); | |||||
else | |||||
Console.Write(Text); | |||||
if (BoxBackground.HasValue && _splitWidth.HasValue) | |||||
{ | |||||
if (AlignInput) | |||||
WriteBackground(_splitWidth.Value, BoxBackground.Value); | |||||
else | |||||
WriteBackground(_splitWidth.Value - Text.LastLine().Length, BoxBackground.Value); | |||||
} | |||||
if (BoxBackground.HasValue && !_splitWidth.HasValue) WriteBackground(Console.WindowWidth - Console.CursorLeft, BoxBackground.Value); | |||||
var cursorVisibility = Console.CursorVisible; | |||||
var input = new SecureString(); | |||||
ConsoleKeyInfo key; | |||||
do | |||||
{ | |||||
Console.CursorVisible = true; | |||||
key = Console.ReadKey(true); | |||||
if (key.Key == ConsoleKey.Backspace) | |||||
{ | |||||
if (input.Length <= 0) continue; | |||||
input.RemoveAt(input.Length - 1); | |||||
bool movedLines = false; | |||||
if (_bindToOpenFrame) | |||||
{ | |||||
if ((((input.Length + 1) - _splitWidth.Value + Text.LastLine().Length).IsDivisibleBy(ConsoleTUI.OpenFrame.DisplayWidth) || input.Length + 1 == _splitWidth.Value - Text.LastLine().Length) && !AlignInput) | |||||
{ | |||||
if (BoxBackground.HasValue) WriteBackground(_splitWidth.Value - (Console.CursorLeft - ConsoleTUI.OpenFrame.DisplayOffset), Console.BackgroundColor); | |||||
Console.SetCursorPosition((ConsoleTUI.OpenFrame.DisplayOffset) + _splitWidth.Value - 1, Console.CursorTop - 1); | |||||
movedLines = true; | |||||
} | |||||
else if ((input.Length + 1).IsDivisibleBy(_splitWidth.Value) && AlignInput) | |||||
{ | |||||
if (BoxBackground.HasValue) WriteBackground(_splitWidth.Value, Console.BackgroundColor); | |||||
Console.SetCursorPosition(ConsoleTUI.OpenFrame.DisplayOffset + startLeft + _splitWidth.Value - 1, Console.CursorTop - 1); | |||||
movedLines = true; | |||||
} | |||||
} | |||||
else if (AlignInput) | |||||
{ | |||||
if ((input.Length + 1).IsDivisibleBy(_splitWidth.Value)) | |||||
{ | |||||
if (BoxBackground.HasValue) WriteBackground(_splitWidth.Value, Console.BackgroundColor); | |||||
Console.SetCursorPosition(startLeft + _splitWidth.Value, Console.CursorTop - 1); | |||||
movedLines = true; | |||||
} | |||||
} | |||||
else | |||||
{ | |||||
if (((input.Length + 1) - (Console.WindowWidth - startLeft)).IsDivisibleBy(Console.WindowWidth) || input.Length + 1 == Console.WindowWidth - startLeft) | |||||
{ | |||||
if (BoxBackground.HasValue) WriteBackground(Console.WindowWidth, Console.BackgroundColor); | |||||
Console.SetCursorPosition(Console.WindowWidth - 1, Console.CursorTop - 1); | |||||
movedLines = true; | |||||
} | |||||
} | |||||
if (movedLines) | |||||
{ | |||||
if (BoxBackground.HasValue) ConsoleUtils.SetColor(Console.ForegroundColor, BoxBackground.Value); | |||||
Console.Write(" \b"); | |||||
if (BoxBackground.HasValue) ConsoleUtils.ResetColor(); | |||||
} | |||||
else | |||||
{ | |||||
if (BoxBackground.HasValue) ConsoleUtils.SetColor(Console.ForegroundColor, BoxBackground.Value); | |||||
Console.Write("\b \b"); | |||||
if (BoxBackground.HasValue) ConsoleUtils.ResetColor(); | |||||
} | |||||
if (MaxLength.HasValue && MaxLength.Value - 1 == input.Length) Console.CursorVisible = true; | |||||
} | |||||
if (Char.IsControl(key.KeyChar)) continue; | |||||
if (MaxLength.HasValue && MaxLength.Value <= input.Length) | |||||
{ | |||||
ConsoleUtils.SetColor(ConsoleColor.DarkRed, InputBackground); | |||||
Console.CursorVisible = false; | |||||
Console.Write("!"); | |||||
Thread.Sleep(200); | |||||
ConsoleUtils.ClearInputBuffer(); | |||||
ConsoleUtils.ResetColor(); | |||||
ConsoleUtils.SetColor(null, BoxBackground); | |||||
Console.Write("\b \b"); | |||||
ConsoleUtils.ResetColor(); | |||||
continue; | |||||
} | |||||
input.AppendChar(key.KeyChar); | |||||
ConsoleUtils.SetColor(InputForeground, InputBackground); | |||||
if (MaskInput) Console.Write("*"); | |||||
else Console.Write(key.KeyChar); | |||||
ConsoleUtils.ResetColor(); | |||||
if (MaxLength.HasValue && MaxLength.Value <= input.Length + 1) | |||||
continue; | |||||
if (_bindToOpenFrame) | |||||
{ | |||||
if (((input.Length - _splitWidth.Value + Text.LastLine().Length).IsDivisibleBy(_splitWidth.Value) || input.Length == _splitWidth.Value - Text.LastLine().Length) && !AlignInput) | |||||
{ | |||||
Console.SetCursorPosition(ConsoleTUI.OpenFrame.DisplayOffset, Console.CursorTop + 1); | |||||
if (BoxBackground.HasValue) WriteBackground(_splitWidth.Value, BoxBackground.Value); | |||||
} | |||||
else if (input.Length.IsDivisibleBy(_splitWidth.Value) && AlignInput) | |||||
{ | |||||
Console.SetCursorPosition(startLeft + ConsoleTUI.OpenFrame.DisplayOffset, Console.CursorTop + 1); | |||||
if (BoxBackground.HasValue) WriteBackground(_splitWidth.Value, BoxBackground.Value); | |||||
} | |||||
} | |||||
else if (AlignInput) | |||||
{ | |||||
if (input.Length.IsDivisibleBy(_splitWidth.Value)) | |||||
{ | |||||
if (SplitWidth.HasValue) | |||||
Console.SetCursorPosition(startLeft, Console.CursorTop + 1); | |||||
else | |||||
// Console will have automatically moved the cursor down | |||||
Console.SetCursorPosition(startLeft, Console.CursorTop); | |||||
if (BoxBackground.HasValue) WriteBackground(_splitWidth.Value, BoxBackground.Value); | |||||
} | |||||
} | |||||
else | |||||
{ | |||||
if ((input.Length - (Console.WindowWidth - startLeft)).IsDivisibleBy(Console.WindowWidth) || input.Length == Console.WindowWidth - startLeft) | |||||
{ | |||||
// Console will have automatically moved the cursor down | |||||
Console.SetCursorPosition(startLeft - Text.LastLine().Length, Console.CursorTop); | |||||
if (BoxBackground.HasValue) WriteBackground(Console.WindowWidth - (startLeft - Text.LastLine().Length), BoxBackground.Value); | |||||
} | |||||
} | |||||
} while (key.Key != ConsoleKey.Enter && (!AllowEscape || (AllowEscape && key.Key != ConsoleKey.Escape))); | |||||
if (input.Length == 0) | |||||
{ | |||||
ConsoleUtils.SetColor(ConsoleColor.Gray); | |||||
Console.Write("None"); | |||||
ConsoleUtils.ResetColor(); | |||||
} | |||||
Console.CursorVisible = cursorVisibility; | |||||
Console.WriteLine(); | |||||
if (key.Key == ConsoleKey.Escape && AllowEscape) return null; | |||||
return input; | |||||
} | |||||
} | |||||
public abstract class Prompt | |||||
{ | |||||
/// <summary> | |||||
/// Text to be displayed before the input. | |||||
/// </summary> | |||||
[Optional] | |||||
public string Text { get; set; } = ""; | |||||
[Optional] public int? MaxLength { get; set; } | |||||
/// <summary> | |||||
/// (Optional) | |||||
/// </summary> | |||||
[Optional] | |||||
public ConsoleColor? InputForeground { get; set; } = null; | |||||
[Optional] public ConsoleColor? InputBackground { get; set; } = null; | |||||
public bool BindToOpenFrame { get; set; } = true; | |||||
public bool AllowEscape { get; set; } = true; | |||||
internal static void WriteBackground(int length, ConsoleColor color) | |||||
{ | |||||
if (Console.CursorLeft + length > Console.WindowWidth) throw new Exception("Critical Error"); | |||||
int leftStart = Console.CursorLeft; | |||||
int topStart = Console.CursorTop; | |||||
ConsoleUtils.SetColor(Console.ForegroundColor, color); | |||||
Console.Write(new string(' ', length)); | |||||
ConsoleUtils.ResetColor(); | |||||
Console.SetCursorPosition(leftStart, topStart); | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,250 @@ | |||||
using System; | |||||
using System.Threading; | |||||
using System.Threading.Tasks; | |||||
using JetBrains.Annotations; | |||||
namespace Ameliorated.ConsoleUtils | |||||
{ | |||||
[AttributeUsage(AttributeTargets.Property)] | |||||
internal sealed class OptionalAttribute : Attribute | |||||
{ | |||||
} | |||||
public static class ConsoleUtils | |||||
{ | |||||
public class LoadingIndicator : IDisposable | |||||
{ | |||||
public LoadingIndicator() {} | |||||
public LoadingIndicator(bool start) | |||||
{ | |||||
if (start) | |||||
StartAsync(); | |||||
} | |||||
private CancellationTokenSource cts = new CancellationTokenSource(); | |||||
Task currentTask = Task.CompletedTask; | |||||
public async Task StartAsync() | |||||
{ | |||||
Console.CursorVisible = false; | |||||
cts = new CancellationTokenSource(); | |||||
currentTask = Task.Run(() => | |||||
{ | |||||
if (cts.IsCancellationRequested) | |||||
{ | |||||
Console.WriteLine("..."); | |||||
return; | |||||
} | |||||
Console.Write('.'); | |||||
while (true) | |||||
{ | |||||
Thread.Sleep(500); | |||||
Console.Write('.'); | |||||
Thread.Sleep(500); | |||||
Console.Write('.'); | |||||
Thread.Sleep(500); | |||||
if (cts.IsCancellationRequested) | |||||
{ | |||||
Console.WriteLine(); | |||||
return; | |||||
} | |||||
Console.Write("\b \b\b \b"); | |||||
} | |||||
}); | |||||
await currentTask; | |||||
} | |||||
public void Stop() | |||||
{ | |||||
cts.Cancel(); | |||||
currentTask.Wait(); | |||||
} | |||||
public void Dispose() | |||||
{ | |||||
Stop(); | |||||
this.currentTask = null; | |||||
this.cts = null; | |||||
} | |||||
} | |||||
public static bool DisplayErrors { get; set; } = true; | |||||
public static void ClearInputBuffer() | |||||
{ | |||||
while (Console.KeyAvailable) Console.ReadKey(true); | |||||
} | |||||
internal static void WriteError(string text) | |||||
{ | |||||
if (DisplayErrors) Console.WriteLine("ConsoleUtils: " + text); | |||||
} | |||||
private static ConsoleColor foregroundCache; | |||||
private static ConsoleColor backgroundCache; | |||||
private static bool? foregroundOnly; | |||||
internal static void SetColor([CanBeNull] ConsoleColor? foreground) | |||||
{ | |||||
foregroundCache = Console.ForegroundColor; | |||||
if (foreground.HasValue) | |||||
Console.ForegroundColor = foreground.Value; | |||||
foregroundOnly = true; | |||||
} | |||||
internal static void SetColor([CanBeNull] ConsoleColor? foreground, [CanBeNull] ConsoleColor? background) | |||||
{ | |||||
foregroundCache = Console.ForegroundColor; | |||||
backgroundCache = Console.BackgroundColor; | |||||
if (foreground.HasValue) | |||||
Console.ForegroundColor = foreground.Value; | |||||
if (background.HasValue) | |||||
Console.BackgroundColor = background.Value; | |||||
foregroundOnly = false; | |||||
} | |||||
internal static void ResetColor() | |||||
{ | |||||
if (!foregroundOnly.HasValue) throw new MethodAccessException("SetColor must be used before calling ResetColor."); | |||||
if (foregroundOnly.Value) | |||||
{ | |||||
Console.ForegroundColor = foregroundCache; | |||||
} else | |||||
{ | |||||
Console.ForegroundColor = foregroundCache; | |||||
Console.BackgroundColor = backgroundCache; | |||||
} | |||||
foregroundOnly = null; | |||||
} | |||||
public static void WriteLine(string text, ConsoleColor? foreground) | |||||
{ | |||||
foreach (var line in text.SplitByLine()) | |||||
{ | |||||
ConsoleUtils.SetColor(foreground); | |||||
Console.WriteLine(line); | |||||
ConsoleUtils.ResetColor(); | |||||
} | |||||
} | |||||
public static void WriteLine(string text, ConsoleColor? foreground, ConsoleColor? background) | |||||
{ | |||||
foreach (var line in text.SplitByLine()) | |||||
{ | |||||
ConsoleUtils.SetColor(foreground); | |||||
Console.WriteLine(line); | |||||
ConsoleUtils.ResetColor(); | |||||
} | |||||
} | |||||
public static void WriteLine(string text, int offset) | |||||
{ | |||||
foreach (var line in text.SplitByLine()) | |||||
{ | |||||
Console.WriteLine(line.Insert(0, new string(' ', offset))); | |||||
} | |||||
} | |||||
public static void WriteLine(string text, int offset, ConsoleColor? foreground) | |||||
{ | |||||
foreach (var line in text.SplitByLine()) | |||||
{ | |||||
Console.Write(new string(' ', offset)); | |||||
ConsoleUtils.SetColor(foreground); | |||||
Console.WriteLine(line); | |||||
ConsoleUtils.ResetColor(); | |||||
} | |||||
} | |||||
public static void WriteLine(string text, int offset, ConsoleColor? foreground, ConsoleColor? background) | |||||
{ | |||||
foreach (var line in text.SplitByLine()) | |||||
{ | |||||
Console.Write(new string(' ', offset)); | |||||
ConsoleUtils.SetColor(foreground, background); | |||||
Console.WriteLine(line); | |||||
ConsoleUtils.ResetColor(); | |||||
} | |||||
} | |||||
public static void Write(string text, ConsoleColor? foreground) | |||||
{ | |||||
foreach (var line in text.SplitByLine()) | |||||
{ | |||||
ConsoleUtils.SetColor(foreground); | |||||
Console.Write(line); | |||||
ConsoleUtils.ResetColor(); | |||||
} | |||||
} | |||||
public static void Write(string text, ConsoleColor? foreground, ConsoleColor? background) | |||||
{ | |||||
foreach (var line in text.SplitByLine()) | |||||
{ | |||||
ConsoleUtils.SetColor(foreground); | |||||
Console.Write(line); | |||||
ConsoleUtils.ResetColor(); | |||||
} | |||||
} | |||||
public static void Write(string text, int offset) | |||||
{ | |||||
foreach (var line in text.SplitByLine()) | |||||
{ | |||||
Console.Write(line.Insert(0, new string(' ', offset))); | |||||
} | |||||
} | |||||
public static void Write(string text, int offset, ConsoleColor? foreground) | |||||
{ | |||||
foreach (var line in text.SplitByLine()) | |||||
{ | |||||
Console.Write(new string(' ', offset)); | |||||
ConsoleUtils.SetColor(foreground); | |||||
Console.Write(line); | |||||
ConsoleUtils.ResetColor(); | |||||
} | |||||
} | |||||
public static void Write(string text, int offset, ConsoleColor? foreground, ConsoleColor? background) | |||||
{ | |||||
foreach (var line in text.SplitByLine()) | |||||
{ | |||||
Console.Write(new string(' ', offset)); | |||||
ConsoleUtils.SetColor(foreground, background); | |||||
Console.Write(line); | |||||
ConsoleUtils.ResetColor(); | |||||
} | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,88 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
namespace Ameliorated.ConsoleUtils | |||||
{ | |||||
public static class Extensions | |||||
{ | |||||
public static bool IsEven(this int number) | |||||
{ | |||||
return number % 2 == 0; | |||||
} | |||||
/// <summary> | |||||
/// Checks if number is divisble by a divisor. | |||||
/// <param name="divisor">Divisor.</param> | |||||
/// <param name="returnFalseOnZeroOrNegative">Indicates whether to return false on numbers that are zero or below. Default is true.</param> | |||||
/// </summary> | |||||
public static bool IsDivisibleBy(this int number, int divisor, bool returnFalseOnZeroOrNegative = true) | |||||
{ | |||||
if (returnFalseOnZeroOrNegative && number <= 0) return false; | |||||
return number % divisor == 0; | |||||
} | |||||
public static int RoundToEven(this double number) | |||||
{ | |||||
var rounded = (int)Math.Round(number); | |||||
if (!rounded.IsEven()) return rounded - 1; | |||||
return rounded; | |||||
} | |||||
public static int RoundToEven(this int number) | |||||
{ | |||||
if (!number.IsEven()) return number - 1; | |||||
return number; | |||||
} | |||||
public static int RoundToOdd(this double number) | |||||
{ | |||||
if (!((int)Math.Ceiling(number)).IsEven()) return (int)Math.Ceiling(number); | |||||
if (!((int)Math.Floor(number)).IsEven()) return (int)Math.Floor(number); | |||||
return (int)Math.Truncate(number) - 1; | |||||
} | |||||
public static int RoundToOdd(this int number) | |||||
{ | |||||
if (!number.IsEven()) return number - 1; | |||||
return number; | |||||
} | |||||
public static string[] SplitByLine(this string text, StringSplitOptions options = StringSplitOptions.None) | |||||
{ | |||||
return text.Split(new[] | |||||
{ "\r\n", "\n" }, options); | |||||
} | |||||
public static string LastLine(this string text, StringSplitOptions options = StringSplitOptions.None) | |||||
{ | |||||
return text.SplitByLine().Last(); | |||||
} | |||||
public static void ReplaceItem(this List<Menu.MenuItem> list, Menu.MenuItem oldItem, Menu.MenuItem newItem) | |||||
{ | |||||
var index = list.IndexOf(oldItem); | |||||
if (index == -1) throw new ArgumentException("Could not find item index."); | |||||
list.RemoveAt(index); | |||||
list.Insert(index, newItem); | |||||
} | |||||
public static Menu.MenuItem Clone(this Menu.MenuItem item) | |||||
{ | |||||
return new Menu.MenuItem(item.PrimaryText, item.ReturnValue) | |||||
{ | |||||
AddBetweenSpace = item.AddBetweenSpace, | |||||
IsEnabled = item.IsEnabled, | |||||
IsNextButton = item.IsNextButton, | |||||
IsPreviousButton = item.IsPreviousButton, | |||||
IsStatic = item.IsStatic, | |||||
PrimaryTextBackground = item.PrimaryTextBackground, | |||||
PrimaryTextForeground = item.PrimaryTextForeground, | |||||
SecondaryText = item.SecondaryText, | |||||
SecondaryTextBackground = item.SecondaryTextBackground, | |||||
SecondaryTextForeground = item.SecondaryTextForeground, | |||||
StretchSelection = item.StretchSelection, | |||||
}; | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,74 @@ | |||||
using System; | |||||
using System.Diagnostics; | |||||
using System.Runtime.InteropServices; | |||||
namespace Ameliorated.ConsoleUtils | |||||
{ | |||||
public static class ParentProcess | |||||
{ | |||||
private static readonly uint TH32CS_SNAPPROCESS = 2; | |||||
public static string ProcessName = Get().ProcessName; | |||||
public static Process Get() | |||||
{ | |||||
try | |||||
{ | |||||
var iParentPid = 0; | |||||
var iCurrentPid = Process.GetCurrentProcess().Id; | |||||
var oHnd = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); | |||||
if (oHnd == IntPtr.Zero) | |||||
return null; | |||||
var oProcInfo = new PROCESSENTRY32(); | |||||
oProcInfo.dwSize = | |||||
(uint)Marshal.SizeOf(typeof(PROCESSENTRY32)); | |||||
if (Process32First(oHnd, ref oProcInfo) == false) | |||||
return null; | |||||
do | |||||
{ | |||||
if (iCurrentPid == oProcInfo.th32ProcessID) | |||||
iParentPid = (int)oProcInfo.th32ParentProcessID; | |||||
} while (iParentPid == 0 && Process32Next(oHnd, ref oProcInfo)); | |||||
if (iParentPid > 0) | |||||
return Process.GetProcessById(iParentPid); | |||||
return null; | |||||
} catch (Exception e) | |||||
{ | |||||
return null; | |||||
} | |||||
} | |||||
[DllImport("kernel32.dll", SetLastError = true)] | |||||
private static extern IntPtr CreateToolhelp32Snapshot(uint dwFlags, uint th32ProcessID); | |||||
[DllImport("kernel32.dll")] | |||||
private static extern bool Process32First(IntPtr hSnapshot, ref PROCESSENTRY32 lppe); | |||||
[DllImport("kernel32.dll")] | |||||
private static extern bool Process32Next(IntPtr hSnapshot, ref PROCESSENTRY32 lppe); | |||||
[StructLayout(LayoutKind.Sequential)] | |||||
public struct PROCESSENTRY32 | |||||
{ | |||||
public uint dwSize; | |||||
public uint cntUsage; | |||||
public uint th32ProcessID; | |||||
public IntPtr th32DefaultHeapID; | |||||
public uint th32ModuleID; | |||||
public uint cntThreads; | |||||
public uint th32ParentProcessID; | |||||
public int pcPriClassBase; | |||||
public uint dwFlags; | |||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] | |||||
public string szExeFile; | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,6 @@ | |||||
namespace Ameliorated.ConsoleUtils | |||||
{ | |||||
public class Payload | |||||
{ | |||||
} | |||||
} |
@ -0,0 +1,10 @@ | |||||
<?xml version="1.0" encoding="utf-8"?><configuration> | |||||
<runtime> | |||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> | |||||
<dependentAssembly> | |||||
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" /> | |||||
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" /> | |||||
</dependentAssembly> | |||||
</assemblyBinding> | |||||
</runtime> | |||||
</configuration> |
@ -0,0 +1,342 @@ | |||||
using System; | |||||
using System.Diagnostics; | |||||
using System.IO; | |||||
using System.Linq; | |||||
using System.Management; | |||||
using System.Net.Http; | |||||
using System.ServiceProcess; | |||||
using System.Threading; | |||||
using amecs.Actions; | |||||
using Ameliorated.ConsoleUtils; | |||||
namespace amecs.Extra | |||||
{ | |||||
public static partial class Extra | |||||
{ | |||||
public static bool ShowMenu() | |||||
{ | |||||
while (true) | |||||
{ | |||||
Program.Frame.Clear(); | |||||
bool hibernation = new Reg.Value() | |||||
{ | |||||
KeyName = @"HKLM\SYSTEM\CurrentControlSet\Control\Power", | |||||
ValueName = "HibernateEnabled", | |||||
Data = 1, | |||||
}.IsEqual() | |||||
&& | |||||
new Reg.Value() | |||||
{ | |||||
KeyName = @"HKLM\SYSTEM\CurrentControlSet\Control\Power", | |||||
ValueName = "HiberFileType", | |||||
Data = 2, | |||||
}.IsEqual(); | |||||
bool notifications = new Reg.Value() | |||||
{ | |||||
KeyName = "HKU\\" + Globals.UserSID + @"\SOFTWARE\Microsoft\Windows\CurrentVersion\PushNotifications", | |||||
ValueName = "ToastEnabled", | |||||
Data = 1, | |||||
}.IsEqual(); | |||||
bool notificationCenter = !new Reg.Value() | |||||
{ | |||||
KeyName = "HKU\\" + Globals.UserSID + @"\SOFTWARE\Policies\Microsoft\Windows\Explorer", | |||||
ValueName = "DisableNotificationCenter", | |||||
Data = 1, | |||||
}.IsEqual(); | |||||
bool vbsEnabled = new Reg.Value() | |||||
{ | |||||
KeyName = @"HKCR\.vbs", | |||||
ValueName = "", | |||||
Data = "VBSFile", | |||||
Type = Reg.RegistryValueType.REG_SZ | |||||
}.IsEqual(); | |||||
bool ncsiEnabled = new Reg.Value() | |||||
{ | |||||
KeyName = @"HKLM\SYSTEM\CurrentControlSet\Services\NlaSvc\Parameters\Internet", | |||||
ValueName = "EnableActiveProbing", | |||||
Data = 1, | |||||
}.IsEqual(); | |||||
var mainMenu = new Ameliorated.ConsoleUtils.Menu() | |||||
{ | |||||
Choices = | |||||
{ | |||||
new Menu.MenuItem("Manage WSL", null) {IsEnabled = false, SecondaryText = "[Not Supported]", PrimaryTextForeground = ConsoleColor.DarkGray, SecondaryTextForeground = ConsoleColor.Red}, | |||||
hibernation ? | |||||
new Menu.MenuItem("Disable Hibernation", new Func<bool>(DisableHibernation)) : | |||||
new Menu.MenuItem("Enable Hibernation", new Func<bool>(EnableHibernation)), | |||||
notificationCenter ? | |||||
new Menu.MenuItem("Disable Notification Center", new Func<bool>(DisableNotifCen)) : | |||||
new Menu.MenuItem("Enable Notification Center", new Func<bool>(EnableNotifCen)), | |||||
notifications ? | |||||
new Menu.MenuItem("Disable Desktop Notifications", new Func<bool>(DisableNotifications)) : | |||||
new Menu.MenuItem("Enable Desktop Notifications", new Func<bool>(EnableNotifications)), | |||||
GetWSHItem(), | |||||
vbsEnabled ? | |||||
new Menu.MenuItem("Disable Visual Basic Script [VBS] (Legacy)", new Func<bool>(DisableVBS)) : | |||||
new Menu.MenuItem("Enable Visual Basic Script [VBS] (Legacy)", new Func<bool>(EnableVBS)), | |||||
ncsiEnabled ? | |||||
new Menu.MenuItem("Disable NCSI Active Probing (Legacy)", new Func<bool>(DisableNCSI)) : | |||||
new Menu.MenuItem("Enable NCSI Active Probing (Legacy)", new Func<bool>(EnableNCSI)), | |||||
GetNVCPItem(), | |||||
Menu.MenuItem.Blank, | |||||
new Menu.MenuItem("Return to Menu", null), | |||||
new Menu.MenuItem("Exit", new Func<bool>(Globals.Exit)) | |||||
}, | |||||
SelectionForeground = ConsoleColor.Green | |||||
}; | |||||
Func<bool> result; | |||||
try | |||||
{ | |||||
mainMenu.Write(); | |||||
var res = mainMenu.Load(); | |||||
if (res == null) | |||||
return true; | |||||
result = (Func<bool>)res; | |||||
} catch (Exception e) | |||||
{ | |||||
Console.WriteLine(e); | |||||
Console.ReadLine(); | |||||
return false; | |||||
} | |||||
try | |||||
{ | |||||
result.Invoke(); | |||||
} catch (Exception e) | |||||
{ | |||||
ConsoleTUI.ShowErrorBox("Error while running an action: " + e.ToString(), null); | |||||
} | |||||
} | |||||
} | |||||
private static Menu.MenuItem GetNVCPItem() | |||||
{ | |||||
if (File.Exists(Environment.ExpandEnvironmentVariables(@"%PROGRAMFILES%\NVIDIA Control Panel\nvcplui.exe"))) | |||||
return new Menu.MenuItem("Uninstall NVIDIA Control Panel", new Func<bool>(NVCP.Uninstall)); | |||||
if (Globals.WinVer > 19043) | |||||
return new Menu.MenuItem("Install NVIDIA Control Panel", null) {IsEnabled = false, PrimaryTextForeground = ConsoleColor.DarkGray, SecondaryTextForeground = ConsoleColor.Red, SecondaryText = "[Not Supported]"}; | |||||
try | |||||
{ | |||||
ManagementObjectSearcher searcher = | |||||
new ManagementObjectSearcher("SELECT NAME FROM Win32_VideoController"); | |||||
bool foundGPU = false; | |||||
foreach (ManagementObject mo in searcher.Get()) | |||||
{ | |||||
PropertyData Name = mo.Properties["Name"]; | |||||
if (Name.Value != null) | |||||
{ | |||||
var name = ((string)Name.Value); | |||||
if (name.Contains("NVIDIA") || name.Contains("GeForce") || name.Contains("GTX") || name.Contains("RTX")) | |||||
{ | |||||
foundGPU = true; | |||||
break; | |||||
} | |||||
} | |||||
} | |||||
if (!foundGPU) | |||||
{ | |||||
return new Menu.MenuItem("Install NVIDIA Control Panel", null) {IsEnabled = false, PrimaryTextForeground = ConsoleColor.DarkGray, SecondaryTextForeground = ConsoleColor.Red, SecondaryText = "[No NVIDIA GPU]"}; | |||||
} | |||||
} catch {} | |||||
try | |||||
{ | |||||
if (!ServiceController.GetServices().Any(x => x.ServiceName.Equals("NVDisplay.ContainerLocalSystem"))) | |||||
return new Menu.MenuItem("Install NVIDIA Control Panel", null) {IsEnabled = false, PrimaryTextForeground = ConsoleColor.DarkGray, SecondaryTextForeground = ConsoleColor.Red, SecondaryText = "[No NVIDIA Driver]"}; | |||||
} catch { } | |||||
try | |||||
{ | |||||
var dir = Directory.EnumerateDirectories(Environment.ExpandEnvironmentVariables(@"%PROGRAMFILES%\WindowsApps")).First(x => x.Contains("NVIDIACorp.NVIDIAControlPanel")); | |||||
if (File.Exists(Path.Combine(dir, "nvcplui.exe"))) | |||||
return new Menu.MenuItem("Install NVIDIA Control Panel", new Func<bool>(() => NVCP.Install(dir))); | |||||
} catch { } | |||||
if (!amecs.IsInternetAvailable()) | |||||
return new Menu.MenuItem("Install NVIDIA Control Panel", null) {IsEnabled = false, PrimaryTextForeground = ConsoleColor.DarkGray, SecondaryTextForeground = ConsoleColor.Red, SecondaryText = "[Internet Required]"}; | |||||
if (!amecs.InternetCheckConnection("https://store.rg-adguard.net", 1, 0)) | |||||
return new Menu.MenuItem("Install NVIDIA Control Panel", null) {IsEnabled = false, PrimaryTextForeground = ConsoleColor.DarkGray, SecondaryTextForeground = ConsoleColor.Red, SecondaryText = "[Server Unavailable]"}; | |||||
if (!amecs.InternetCheckConnection("https://git.ameliorated.info/", 1, 0)) | |||||
return new Menu.MenuItem("Install NVIDIA Control Panel", null) {IsEnabled = false, PrimaryTextForeground = ConsoleColor.DarkGray, SecondaryTextForeground = ConsoleColor.Red, SecondaryText = "[Git Unavailable]"}; | |||||
try | |||||
{ | |||||
using (HttpClient client = new HttpClient()) | |||||
{ | |||||
using (HttpResponseMessage response = client.GetAsync("https://store.rg-adguard.net/").Result) | |||||
{ | |||||
using (HttpContent content = response.Content) | |||||
{ | |||||
string result = content.ReadAsStringAsync().Result; | |||||
if (result.Contains("Cloudflare Ray ID")) | |||||
return new Menu.MenuItem("Install NVIDIA Control Panel", null) {IsEnabled = false, PrimaryTextForeground = ConsoleColor.DarkGray, SecondaryTextForeground = ConsoleColor.Red, SecondaryText = "[Server Unavailable]"}; | |||||
} | |||||
} | |||||
} | |||||
} catch { } | |||||
return new Menu.MenuItem("Install NVIDIA Control Panel", new Func<bool>(NVCP.InstallFromNetwork)); | |||||
} | |||||
private static Menu.MenuItem GetWSHItem() | |||||
{ | |||||
if (new Reg.Value() | |||||
{ | |||||
KeyName = Globals.UserHive + @"\SOFTWARE\Microsoft\Windows Script Host\Settings", | |||||
ValueName = "Enabled", | |||||
Data = 1, | |||||
}.IsEqual()) | |||||
return new Menu.MenuItem("Disable Windows Script Host [WSH] (Legacy)", new Func<bool>(WSH.Disable)); | |||||
if (new Reg.Value() | |||||
{ | |||||
KeyName = Globals.UserHive + @"\SOFTWARE\Microsoft\Windows Script Host\Settings", | |||||
ValueName = "Enabled", | |||||
Data = 0, | |||||
}.IsEqual()) | |||||
return new Menu.MenuItem("Enable Windows Script Host [WSH] (Legacy)", new Func<bool>(WSH.Enable)); | |||||
return new Reg.Value() | |||||
{ | |||||
KeyName = @"HKLM\SOFTWARE\Microsoft\Windows Script Host\Settings", | |||||
ValueName = "Enabled", | |||||
Data = 0, | |||||
}.IsEqual() ? new Menu.MenuItem("Disable Windows Script Host [WSH] (Legacy)", new Func<bool>(WSH.Enable)) : new Menu.MenuItem("Disable Windows Script Host [WSH] (Legacy)", new Func<bool>(WSH.Disable)); | |||||
} | |||||
private static bool EnableHibernation() =>amecs.RunBasicAction("Enabling hibernation","Enabled hibernation successfully",() => | |||||
{ | |||||
Thread.Sleep(1600); | |||||
Process proc = new Process(); | |||||
proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; | |||||
proc.StartInfo.FileName = "powercfg.exe"; | |||||
proc.StartInfo.Arguments = "/HIBERNATE /TYPE FULL"; | |||||
proc.Start(); | |||||
proc.WaitForExit(20000); | |||||
if (proc.ExitCode != 0) | |||||
throw new Exception("powercfg exited with a non-zero exitcode.\r\nHibernation may not be supported by your hardware."); | |||||
}); | |||||
private static bool DisableHibernation() =>amecs.RunBasicAction("Disabling hibernation","Disabled hibernation successfully",() => | |||||
{ | |||||
Thread.Sleep(1600); | |||||
Process proc = new Process(); | |||||
proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; | |||||
proc.StartInfo.FileName = "powercfg.exe"; | |||||
proc.StartInfo.Arguments = "/HIBERNATE OFF"; | |||||
proc.Start(); | |||||
proc.WaitForExit(20000); | |||||
if (proc.ExitCode != 0) | |||||
throw new Exception("powercfg exited with a non-zero exitcode."); | |||||
Thread.Sleep(1600); | |||||
}); | |||||
private static bool EnableNotifCen() =>amecs.RunBasicAction("Enabling Notification Center","Notification Center enabled successfully",() => | |||||
{ | |||||
new Reg.Value() | |||||
{ | |||||
KeyName = "HKU\\" + Globals.UserSID + @"\SOFTWARE\Policies\Microsoft\Windows\Explorer", | |||||
ValueName = "DisableNotificationCenter", | |||||
Operation = Reg.RegistryValueOperation.Delete | |||||
}.Apply(); | |||||
Thread.Sleep(1600); | |||||
}, true); | |||||
private static bool DisableNotifCen() =>amecs.RunBasicAction("Disabling Notification Center","Notification Center disabled successfully",() => | |||||
{ | |||||
new Reg.Value() | |||||
{ | |||||
KeyName = "HKU\\" + Globals.UserSID + @"\SOFTWARE\Policies\Microsoft\Windows\Explorer", | |||||
ValueName = "DisableNotificationCenter", | |||||
Data = 1, | |||||
}.Apply(); | |||||
Thread.Sleep(1600); | |||||
}, true); | |||||
private static bool EnableNotifications() =>amecs.RunBasicAction("Enabling desktop notifications","Enabled desktop notifications successfully",() => | |||||
{ | |||||
new Reg.Value() | |||||
{ | |||||
KeyName = "HKU\\" + Globals.UserSID + @"\SOFTWARE\Microsoft\Windows\CurrentVersion\PushNotifications", | |||||
ValueName = "ToastEnabled", | |||||
Data = 1, | |||||
}.Apply(); | |||||
Thread.Sleep(1600); | |||||
}, true); | |||||
private static bool DisableNotifications() =>amecs.RunBasicAction("Disabling desktop notifications","Disabled desktop notifications successfully",() => | |||||
{ | |||||
new Reg.Value() | |||||
{ | |||||
KeyName = "HKU\\" + Globals.UserSID + @"\SOFTWARE\Microsoft\Windows\CurrentVersion\PushNotifications", | |||||
ValueName = "ToastEnabled", | |||||
Data = 0, | |||||
}.Apply(); | |||||
Thread.Sleep(1600); | |||||
}, true); | |||||
private static bool EnableVBS() =>amecs.RunBasicAction("Enabling Visual Basic Script","Enabled VBS successfully",() => | |||||
{ | |||||
new Reg.Value() | |||||
{ | |||||
KeyName = @"HKCR\.vbs", | |||||
ValueName = "", | |||||
Data = "VBSFile", | |||||
Type = Reg.RegistryValueType.REG_SZ | |||||
}.Apply(); | |||||
Thread.Sleep(1600); | |||||
}); | |||||
private static bool DisableVBS() =>amecs.RunBasicAction("Disabling Visual Basic Script","Disabled VBS successfully",() => | |||||
{ | |||||
new Reg.Value() | |||||
{ | |||||
KeyName = @"HKCR\.vbs", | |||||
ValueName = "", | |||||
Data = "", | |||||
Type = Reg.RegistryValueType.REG_SZ | |||||
}.Apply(); | |||||
Thread.Sleep(1600); | |||||
}); | |||||
private static bool EnableNCSI() =>amecs.RunBasicAction("Enabling NCSI Active Probing","Enabled NCSI Active Probing successfully",() => | |||||
{ | |||||
new Reg.Value() | |||||
{ | |||||
KeyName = @"HKLM\SYSTEM\CurrentControlSet\Services\NlaSvc\Parameters\Internet", | |||||
ValueName = "EnableActiveProbing", | |||||
Data = 1, | |||||
}.Apply(); | |||||
Thread.Sleep(1600); | |||||
}, false, true); | |||||
private static bool DisableNCSI() =>amecs.RunBasicAction("Disabling NCSI Active Probing","Disabled NCSI Active Probing successfully",() => | |||||
{ | |||||
new Reg.Value() | |||||
{ | |||||
KeyName = @"HKLM\SYSTEM\CurrentControlSet\Services\NlaSvc\Parameters\Internet", | |||||
ValueName = "EnableActiveProbing", | |||||
Data = 0, | |||||
}.Apply(); | |||||
Thread.Sleep(1600); | |||||
}, false, true); | |||||
} | |||||
} |
@ -0,0 +1,281 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Diagnostics; | |||||
using System.IO; | |||||
using System.IO.Compression; | |||||
using System.Linq; | |||||
using System.Net; | |||||
using System.Net.Http; | |||||
using System.Runtime.InteropServices; | |||||
using System.Runtime.InteropServices.ComTypes; | |||||
using System.Security.AccessControl; | |||||
using System.ServiceProcess; | |||||
using System.Text; | |||||
using System.Text.RegularExpressions; | |||||
using System.Threading; | |||||
using amecs.Actions; | |||||
using Ameliorated.ConsoleUtils; | |||||
using IWshRuntimeLibrary; | |||||
using File = System.IO.File; | |||||
namespace amecs.Extra | |||||
{ | |||||
public class NVCP | |||||
{ | |||||
private static readonly string DestinationDir = Environment.ExpandEnvironmentVariables(@"%PROGRAMFILES%\NVIDIA Control Panel"); | |||||
public static bool Install(string NVCP) => amecs.RunBasicAction("Installing NVIDIA Control Panel", "NVIDIA Control Panel installed successfully", () => | |||||
{ | |||||
Thread.Sleep(4000); | |||||
try | |||||
{ | |||||
foreach (var proc in Process.GetProcessesByName("nvcplui")) | |||||
proc.Kill(); | |||||
} catch | |||||
{ | |||||
} | |||||
if (Directory.Exists(DestinationDir)) | |||||
Directory.Delete(DestinationDir, true); | |||||
Directory.Move(NVCP, DestinationDir); | |||||
var di = new DirectoryInfo(DestinationDir); | |||||
var sec = di.GetAccessControl(); | |||||
sec.AddAccessRule(new FileSystemAccessRule("Administrators", FileSystemRights.FullControl, InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit, PropagationFlags.None, AccessControlType.Allow)); | |||||
sec.AddAccessRule(new FileSystemAccessRule("Users", FileSystemRights.ReadAndExecute, InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit, PropagationFlags.None, AccessControlType.Allow)); | |||||
di.SetAccessControl(sec); | |||||
Config(); | |||||
}); | |||||
public static bool InstallFromNetwork() | |||||
{ | |||||
try | |||||
{ | |||||
foreach (var proc in Process.GetProcessesByName("nvcplui")) | |||||
proc.Kill(); | |||||
} catch | |||||
{ | |||||
} | |||||
if (Directory.Exists(DestinationDir)) | |||||
Directory.Delete(DestinationDir, true); | |||||
var choice = new ChoicePrompt() {Text = "NVIDIA Control Panel must be downloaded\r\nContinue? (Y/N): "}.Start(); | |||||
if (!choice.HasValue || choice == 1) | |||||
return false; | |||||
string link; | |||||
string filter; | |||||
string size; | |||||
ConsoleTUI.OpenFrame.WriteCentered("\r\nFetching download link"); | |||||
try | |||||
{ | |||||
using (new ConsoleUtils.LoadingIndicator(true)) | |||||
{ | |||||
using (HttpClient client = new HttpClient()) | |||||
{ | |||||
using (HttpResponseMessage response = client.GetAsync("https://git.ameliorated.info/Styris/amecs/src/branch/master/links.txt").Result) | |||||
{ | |||||
using (HttpContent content = response.Content) | |||||
{ | |||||
string result = content.ReadAsStringAsync().Result; | |||||
var line = result.SplitByLine().First(x => x.Contains("NVIDIA-Control-Panel = ")); | |||||
var split = line.Split('|'); | |||||
link = split[1]; | |||||
filter = split[3]; | |||||
if (link == "REMOVED") | |||||
throw new Exception("Link is no longer available."); | |||||
} | |||||
} | |||||
var values = new Dictionary<string, string> | |||||
{ | |||||
{ "type", "url" }, | |||||
{ "url", link }, | |||||
{ "ring", "Retail" } | |||||
}; | |||||
var request = new FormUrlEncodedContent(values); | |||||
using (HttpResponseMessage response = client.PostAsync("https://store.rg-adguard.net/api/GetFiles", request).Result) | |||||
{ | |||||
using (HttpContent content = response.Content) | |||||
{ | |||||
string result = content.ReadAsStringAsync().Result; | |||||
var regex = new Regex($".*{filter}.*"); | |||||
var match = regex.Match(result).Value; | |||||
var split = match.Split('"'); | |||||
link = split[3]; | |||||
size = split[12].Remove(0, 1).Remove(split[12].Length - 11); | |||||
if (!size.Contains("MB") && !size.Contains("KB") && !size.Contains("GB")) | |||||
size = "0 MB"; | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} catch (Exception e) | |||||
{ | |||||
Console.WriteLine(); | |||||
ConsoleTUI.OpenFrame.Close("Could not fetch link: " + e.Message, ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt() {AnyKey = true, Text = "Press any key to return to the Menu: "}); | |||||
return false; | |||||
} | |||||
var temp = Environment.ExpandEnvironmentVariables(@"%TEMP%\[amecs]-NVCP-" + new Random().Next(0, 9999) + ".zip"); | |||||
try | |||||
{ | |||||
ConsoleTUI.OpenFrame.WriteCenteredLine($"\r\nDownloading NVIDIA Control Panel ({size})"); | |||||
using (WebClient wc = new WebClient()) | |||||
{ | |||||
var stdout = GetStdHandle(-11); | |||||
var maxHashTags = (ConsoleTUI.OpenFrame.DisplayWidth - 5); | |||||
wc.DownloadProgressChanged += delegate(object sender, DownloadProgressChangedEventArgs e) | |||||
{ | |||||
var currentHashTags = (int)Math.Ceiling(Math.Min(((double)e.ProgressPercentage / 100) * maxHashTags, maxHashTags)); | |||||
var spaces = maxHashTags - currentHashTags + (4 - e.ProgressPercentage.ToString().Length); | |||||
var sb = new StringBuilder(new string('#', currentHashTags) + new string(' ', spaces) + e.ProgressPercentage + "%"); | |||||
uint throwaway; | |||||
WriteConsoleOutputCharacter(stdout, sb, (uint)sb.Length, new COORD((short)ConsoleTUI.OpenFrame.DisplayOffset, (short)Console.CursorTop), out throwaway); | |||||
}; | |||||
var task = wc.DownloadFileTaskAsync(new Uri(link), temp); | |||||
task.Wait(); | |||||
Thread.Sleep(100); | |||||
var sb = new StringBuilder(new string('#', maxHashTags) + " 100%"); | |||||
uint throwaway; | |||||
WriteConsoleOutputCharacter(stdout, sb, (uint)sb.Length, new COORD((short)ConsoleTUI.OpenFrame.DisplayOffset, (short)Console.CursorTop), out throwaway); | |||||
} | |||||
Console.WriteLine(); | |||||
ZipFile.ExtractToDirectory(temp, DestinationDir); | |||||
if (!File.Exists(Path.Combine(DestinationDir, "nvcplui.exe"))) | |||||
{ | |||||
try { Directory.Delete(DestinationDir, true);} catch {} | |||||
Console.WriteLine(); | |||||
ConsoleTUI.OpenFrame.Close("Download is missing critical executable.", ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt() {AnyKey = true, Text = "Press any key to return to the Menu: "}); | |||||
return false; | |||||
} | |||||
Config(); | |||||
} catch (Exception e) | |||||
{ | |||||
Console.WriteLine(); | |||||
ConsoleTUI.OpenFrame.Close("Error: " + e.Message.TrimEnd('\n').TrimEnd('\r'), ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt() {AnyKey = true, Text = "Press any key to return to the Menu: "}); | |||||
return false; | |||||
} | |||||
Console.WriteLine(); | |||||
ConsoleTUI.OpenFrame.Close("NVIDIA Control Panel installed successfully", ConsoleColor.Green, Console.BackgroundColor, new ChoicePrompt() {AnyKey = true, Text = "Press any key to return to the Menu: "}); | |||||
return true; | |||||
} | |||||
public static bool Uninstall() => amecs.RunBasicAction("Uninstalling NVIDIA Control Panel", "NVIDIA Control Panel uninstalled successfully", () => | |||||
{ | |||||
var linkPath = Environment.ExpandEnvironmentVariables(@"%PROGRAMDATA%\Microsoft\Windows\Start Menu\Programs\NVIDIA Control Panel.lnk"); | |||||
if (File.Exists(linkPath)) | |||||
File.Delete(linkPath); | |||||
Directory.Delete(DestinationDir, true); | |||||
Thread.Sleep(2000); | |||||
}); | |||||
public static void Config() | |||||
{ | |||||
try | |||||
{ | |||||
new Reg.Value() { KeyName = @"HKLM\System\CurrentControlSet\Services\nvlddmkm\Global\NVTweak", ValueName = "DisableStoreNvCplNotifications", Type = Reg.RegistryValueType.REG_DWORD, Data = 1 }.Apply(); | |||||
} catch (Exception e) | |||||
{ | |||||
ConsoleTUI.ShowErrorBox("Could not disable NVIDIA Microsoft Store notification: " + e.ToString(), "Error"); | |||||
} | |||||
var linkPath = Environment.ExpandEnvironmentVariables(@"%PROGRAMDATA%\Microsoft\Windows\Start Menu\Programs\NVIDIA Control Panel.lnk"); | |||||
if (File.Exists(linkPath)) | |||||
File.Delete(linkPath); | |||||
try | |||||
{ | |||||
IShellLink link = (IShellLink)new ShellLink(); | |||||
link.SetDescription("NVIDIA Control Panel"); | |||||
link.SetPath(Path.Combine(DestinationDir, "nvcplui.exe")); | |||||
IPersistFile file = (IPersistFile)link; | |||||
file.Save(linkPath, false); | |||||
} catch | |||||
{ | |||||
WshShell shell = new WshShell(); | |||||
IWshShortcut shortcut = (IWshShortcut)shell.CreateShortcut(linkPath); | |||||
shortcut.Description = "NVIDIA Control Panel"; | |||||
shortcut.TargetPath = Path.Combine(DestinationDir, "nvcplui.exe"); | |||||
shortcut.Save(); | |||||
} | |||||
new Reg.Value() { KeyName = @"HKLM\SYSTEM\CurrentControlSet\Services\NVDisplay.ContainerLocalSystem", ValueName = "Start", Type = Reg.RegistryValueType.REG_DWORD, Data = 2 }.Apply(); | |||||
try { ServiceController.GetServices().First(x => x.ServiceName.Equals("NVDisplay.ContainerLocalSystem")).Start(); } catch (Exception e) { } | |||||
} | |||||
[DllImport("kernel32.dll", SetLastError = true)] | |||||
internal static extern bool WriteConsoleOutputCharacter(IntPtr hConsoleOutput, StringBuilder lpCharacter, uint nLength, COORD dwWriteCoord, out uint lpNumberOfCharsWritten); | |||||
[DllImport("kernel32.dll", SetLastError = true)] | |||||
static extern IntPtr GetStdHandle(int nStdHandle); | |||||
[StructLayout(LayoutKind.Sequential)] | |||||
public struct COORD | |||||
{ | |||||
public short X; | |||||
public short Y; | |||||
public COORD(short X, short Y) | |||||
{ | |||||
this.X = X; | |||||
this.Y = Y; | |||||
} | |||||
}; | |||||
} | |||||
[ComImport] | |||||
[Guid("00021401-0000-0000-C000-000000000046")] | |||||
internal class ShellLink | |||||
{ | |||||
} | |||||
[ComImport] | |||||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] | |||||
[Guid("000214F9-0000-0000-C000-000000000046")] | |||||
internal interface IShellLink | |||||
{ | |||||
void GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, int cchMaxPath, out IntPtr pfd, int fFlags); | |||||
void GetIDList(out IntPtr ppidl); | |||||
void SetIDList(IntPtr pidl); | |||||
void GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName, int cchMaxName); | |||||
void SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName); | |||||
void GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, int cchMaxPath); | |||||
void SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir); | |||||
void GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, int cchMaxPath); | |||||
void SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs); | |||||
void GetHotkey(out short pwHotkey); | |||||
void SetHotkey(short wHotkey); | |||||
void GetShowCmd(out int piShowCmd); | |||||
void SetShowCmd(int iShowCmd); | |||||
void GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, int cchIconPath, out int piIcon); | |||||
void SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon); | |||||
void SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, int dwReserved); | |||||
void Resolve(IntPtr hwnd, int fFlags); | |||||
void SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile); | |||||
} | |||||
} |
@ -0,0 +1,40 @@ | |||||
namespace amecs.Extra | |||||
{ | |||||
public class WSH | |||||
{ | |||||
public static bool Enable() => amecs.RunBasicAction("Enabling Windows Script Host", "Enabled WSH successfully", i => | |||||
{ | |||||
new Reg.Value() | |||||
{ | |||||
KeyName = Globals.UserHive + @"\SOFTWARE\Microsoft\Windows Script Host\Settings", | |||||
ValueName = "Enabled", | |||||
Data = 1, | |||||
Type = Reg.RegistryValueType.REG_DWORD | |||||
}.Apply(); | |||||
new Reg.Value() | |||||
{ | |||||
KeyName = @"HKLM\SOFTWARE\Microsoft\Windows Script Host\Settings", | |||||
ValueName = "Enabled", | |||||
Data = 1, | |||||
Type = Reg.RegistryValueType.REG_DWORD | |||||
}.Apply(); | |||||
}); | |||||
public static bool Disable() => amecs.RunBasicAction("Disabling Windows Script Host", "Disabled WSH successfully", i => | |||||
{ | |||||
new Reg.Value() | |||||
{ | |||||
KeyName = Globals.UserHive + @"\SOFTWARE\Microsoft\Windows Script Host\Settings", | |||||
ValueName = "Enabled", | |||||
Data = 0, | |||||
Type = Reg.RegistryValueType.REG_DWORD | |||||
}.Apply(); | |||||
new Reg.Value() | |||||
{ | |||||
KeyName = @"HKLM\SOFTWARE\Microsoft\Windows Script Host\Settings", | |||||
ValueName = "Enabled", | |||||
Data = 0, | |||||
Type = Reg.RegistryValueType.REG_DWORD | |||||
}.Apply(); | |||||
}); | |||||
} | |||||
} |
@ -0,0 +1,3 @@ | |||||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> | |||||
<Costura /> | |||||
</Weavers> |
@ -0,0 +1,41 @@ | |||||
using System; | |||||
using System.DirectoryServices.AccountManagement; | |||||
using System.Threading.Tasks; | |||||
using Ameliorated.ConsoleUtils; | |||||
using Microsoft.Win32; | |||||
namespace amecs | |||||
{ | |||||
public static class Globals | |||||
{ | |||||
public static string Username = null; | |||||
public static string UserDomain = null; | |||||
public static string UserSID = null; | |||||
public static string UserFolder = null; | |||||
public static bool UserElevated = false; | |||||
public static string UserHive | |||||
{ | |||||
get | |||||
{ | |||||
return "HKU\\" + UserSID; | |||||
} | |||||
} | |||||
public static Task UserLoadTask = Task.CompletedTask; | |||||
public static ConsoleUtils.LoadingIndicator CurrentIndicator = new ConsoleUtils.LoadingIndicator(); | |||||
public static GroupPrincipal Administrators; | |||||
public static UserPrincipal User; | |||||
public static bool Exit() | |||||
{ | |||||
ConsoleTUI.Close(); | |||||
Environment.Exit(0); | |||||
return true; | |||||
} | |||||
public static readonly int WinVer = int.Parse(Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion").GetValue("CurrentBuildNumber").ToString()); | |||||
} | |||||
} |
@ -0,0 +1,220 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Diagnostics; | |||||
using System.Linq; | |||||
using System.Runtime.InteropServices; | |||||
using System.Runtime.InteropServices.ComTypes; | |||||
namespace amecs.Misc | |||||
{ | |||||
public class FolderPicker | |||||
{ | |||||
private readonly List<string> _resultPaths = new List<string>(); | |||||
private readonly List<string> _resultNames = new List<string>(); | |||||
public IReadOnlyList<string> ResultPaths => _resultPaths; | |||||
public IReadOnlyList<string> ResultNames => _resultNames; | |||||
public string ResultPath => ResultPaths.FirstOrDefault(); | |||||
public string ResultName => ResultNames.FirstOrDefault(); | |||||
public virtual string InputPath { get; set; } | |||||
public virtual bool ForceFileSystem { get; set; } | |||||
public virtual bool Multiselect { get; set; } | |||||
public virtual string Title { get; set; } | |||||
public virtual string OkButtonLabel { get; set; } | |||||
public virtual string FileNameLabel { get; set; } | |||||
protected virtual int SetOptions(int options) | |||||
{ | |||||
if (ForceFileSystem) | |||||
{ | |||||
options |= (int)FOS.FOS_FORCEFILESYSTEM; | |||||
} | |||||
if (Multiselect) | |||||
{ | |||||
options |= (int)FOS.FOS_ALLOWMULTISELECT; | |||||
} | |||||
return options; | |||||
} | |||||
// for all .NET | |||||
public virtual bool? ShowDialog(IntPtr owner, bool throwOnError = false) | |||||
{ | |||||
var dialog = (IFileOpenDialog)new FileOpenDialog(); | |||||
if (!string.IsNullOrEmpty(InputPath)) | |||||
{ | |||||
if (CheckHr(SHCreateItemFromParsingName(InputPath, null, typeof(IShellItem).GUID, out var item), throwOnError) != 0) | |||||
return null; | |||||
dialog.SetFolder(item); | |||||
} | |||||
var options = FOS.FOS_PICKFOLDERS; | |||||
options = (FOS)SetOptions((int)options); | |||||
dialog.SetOptions(options); | |||||
if (Title != null) | |||||
{ | |||||
dialog.SetTitle(Title); | |||||
} | |||||
if (OkButtonLabel != null) | |||||
{ | |||||
dialog.SetOkButtonLabel(OkButtonLabel); | |||||
} | |||||
if (FileNameLabel != null) | |||||
{ | |||||
dialog.SetFileName(FileNameLabel); | |||||
} | |||||
if (owner == IntPtr.Zero) | |||||
{ | |||||
owner = Process.GetCurrentProcess().MainWindowHandle; | |||||
if (owner == IntPtr.Zero) | |||||
{ | |||||
owner = GetDesktopWindow(); | |||||
} | |||||
} | |||||
var hr = dialog.Show(owner); | |||||
if (hr == ERROR_CANCELLED) | |||||
return null; | |||||
if (CheckHr(hr, throwOnError) != 0) | |||||
return null; | |||||
if (CheckHr(dialog.GetResults(out var items), throwOnError) != 0) | |||||
return null; | |||||
items.GetCount(out var count); | |||||
for (var i = 0; i < count; i++) | |||||
{ | |||||
items.GetItemAt(i, out var item); | |||||
CheckHr(item.GetDisplayName(SIGDN.SIGDN_DESKTOPABSOLUTEPARSING, out var path), throwOnError); | |||||
CheckHr(item.GetDisplayName(SIGDN.SIGDN_DESKTOPABSOLUTEEDITING, out var name), throwOnError); | |||||
if (path != null || name != null) | |||||
{ | |||||
_resultPaths.Add(path); | |||||
_resultNames.Add(name); | |||||
} | |||||
} | |||||
return true; | |||||
} | |||||
private static int CheckHr(int hr, bool throwOnError) | |||||
{ | |||||
if (hr != 0 && throwOnError) Marshal.ThrowExceptionForHR(hr); | |||||
return hr; | |||||
} | |||||
[DllImport("shell32")] | |||||
private static extern int SHCreateItemFromParsingName([MarshalAs(UnmanagedType.LPWStr)] string pszPath, IBindCtx pbc, [MarshalAs(UnmanagedType.LPStruct)] Guid riid, out IShellItem ppv); | |||||
[DllImport("user32")] | |||||
private static extern IntPtr GetDesktopWindow(); | |||||
#pragma warning disable IDE1006 // Naming Styles | |||||
private const int ERROR_CANCELLED = unchecked((int)0x800704C7); | |||||
#pragma warning restore IDE1006 // Naming Styles | |||||
[ComImport, Guid("DC1C5A9C-E88A-4dde-A5A1-60F82A20AEF7")] // CLSID_FileOpenDialog | |||||
private class FileOpenDialog { } | |||||
[ComImport, Guid("d57c7288-d4ad-4768-be02-9d969532d960"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] | |||||
private interface IFileOpenDialog | |||||
{ | |||||
[PreserveSig] int Show(IntPtr parent); // IModalWindow | |||||
[PreserveSig] int SetFileTypes(); // not fully defined | |||||
[PreserveSig] int SetFileTypeIndex(int iFileType); | |||||
[PreserveSig] int GetFileTypeIndex(out int piFileType); | |||||
[PreserveSig] int Advise(); // not fully defined | |||||
[PreserveSig] int Unadvise(); | |||||
[PreserveSig] int SetOptions(FOS fos); | |||||
[PreserveSig] int GetOptions(out FOS pfos); | |||||
[PreserveSig] int SetDefaultFolder(IShellItem psi); | |||||
[PreserveSig] int SetFolder(IShellItem psi); | |||||
[PreserveSig] int GetFolder(out IShellItem ppsi); | |||||
[PreserveSig] int GetCurrentSelection(out IShellItem ppsi); | |||||
[PreserveSig] int SetFileName([MarshalAs(UnmanagedType.LPWStr)] string pszName); | |||||
[PreserveSig] int GetFileName([MarshalAs(UnmanagedType.LPWStr)] out string pszName); | |||||
[PreserveSig] int SetTitle([MarshalAs(UnmanagedType.LPWStr)] string pszTitle); | |||||
[PreserveSig] int SetOkButtonLabel([MarshalAs(UnmanagedType.LPWStr)] string pszText); | |||||
[PreserveSig] int SetFileNameLabel([MarshalAs(UnmanagedType.LPWStr)] string pszLabel); | |||||
[PreserveSig] int GetResult(out IShellItem ppsi); | |||||
[PreserveSig] int AddPlace(IShellItem psi, int alignment); | |||||
[PreserveSig] int SetDefaultExtension([MarshalAs(UnmanagedType.LPWStr)] string pszDefaultExtension); | |||||
[PreserveSig] int Close(int hr); | |||||
[PreserveSig] int SetClientGuid(); // not fully defined | |||||
[PreserveSig] int ClearClientData(); | |||||
[PreserveSig] int SetFilter([MarshalAs(UnmanagedType.IUnknown)] object pFilter); | |||||
[PreserveSig] int GetResults(out IShellItemArray ppenum); | |||||
[PreserveSig] int GetSelectedItems([MarshalAs(UnmanagedType.IUnknown)] out object ppsai); | |||||
} | |||||
[ComImport, Guid("43826D1E-E718-42EE-BC55-A1E261C37BFE"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] | |||||
private interface IShellItem | |||||
{ | |||||
[PreserveSig] int BindToHandler(); // not fully defined | |||||
[PreserveSig] int GetParent(); // not fully defined | |||||
[PreserveSig] int GetDisplayName(SIGDN sigdnName, [MarshalAs(UnmanagedType.LPWStr)] out string ppszName); | |||||
[PreserveSig] int GetAttributes(); // not fully defined | |||||
[PreserveSig] int Compare(); // not fully defined | |||||
} | |||||
[ComImport, Guid("b63ea76d-1f85-456f-a19c-48159efa858b"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] | |||||
private interface IShellItemArray | |||||
{ | |||||
[PreserveSig] int BindToHandler(); // not fully defined | |||||
[PreserveSig] int GetPropertyStore(); // not fully defined | |||||
[PreserveSig] int GetPropertyDescriptionList(); // not fully defined | |||||
[PreserveSig] int GetAttributes(); // not fully defined | |||||
[PreserveSig] int GetCount(out int pdwNumItems); | |||||
[PreserveSig] int GetItemAt(int dwIndex, out IShellItem ppsi); | |||||
[PreserveSig] int EnumItems(); // not fully defined | |||||
} | |||||
#pragma warning disable CA1712 // Do not prefix enum values with type name | |||||
private enum SIGDN : uint | |||||
{ | |||||
SIGDN_DESKTOPABSOLUTEEDITING = 0x8004c000, | |||||
SIGDN_DESKTOPABSOLUTEPARSING = 0x80028000, | |||||
SIGDN_FILESYSPATH = 0x80058000, | |||||
SIGDN_NORMALDISPLAY = 0, | |||||
SIGDN_PARENTRELATIVE = 0x80080001, | |||||
SIGDN_PARENTRELATIVEEDITING = 0x80031001, | |||||
SIGDN_PARENTRELATIVEFORADDRESSBAR = 0x8007c001, | |||||
SIGDN_PARENTRELATIVEPARSING = 0x80018001, | |||||
SIGDN_URL = 0x80068000 | |||||
} | |||||
[Flags] | |||||
private enum FOS | |||||
{ | |||||
FOS_OVERWRITEPROMPT = 0x2, | |||||
FOS_STRICTFILETYPES = 0x4, | |||||
FOS_NOCHANGEDIR = 0x8, | |||||
FOS_PICKFOLDERS = 0x20, | |||||
FOS_FORCEFILESYSTEM = 0x40, | |||||
FOS_ALLNONSTORAGEITEMS = 0x80, | |||||
FOS_NOVALIDATE = 0x100, | |||||
FOS_ALLOWMULTISELECT = 0x200, | |||||
FOS_PATHMUSTEXIST = 0x800, | |||||
FOS_FILEMUSTEXIST = 0x1000, | |||||
FOS_CREATEPROMPT = 0x2000, | |||||
FOS_SHAREAWARE = 0x4000, | |||||
FOS_NOREADONLYRETURN = 0x8000, | |||||
FOS_NOTESTFILECREATE = 0x10000, | |||||
FOS_HIDEMRUPLACES = 0x20000, | |||||
FOS_HIDEPINNEDPLACES = 0x40000, | |||||
FOS_NODEREFERENCELINKS = 0x100000, | |||||
FOS_OKBUTTONNEEDSINTERACTION = 0x200000, | |||||
FOS_DONTADDTORECENT = 0x2000000, | |||||
FOS_FORCESHOWHIDDEN = 0x10000000, | |||||
FOS_DEFAULTNOMINIMODE = 0x20000000, | |||||
FOS_FORCEPREVIEWPANEON = 0x40000000, | |||||
FOS_SUPPORTSTREAMABLEITEMS = unchecked((int)0x80000000) | |||||
} | |||||
#pragma warning restore CA1712 // Do not prefix enum values with type name | |||||
} | |||||
} |
@ -0,0 +1,261 @@ | |||||
using System; | |||||
using System.Diagnostics; | |||||
using System.IO; | |||||
using System.Linq; | |||||
using System.Security; | |||||
using System.Windows.Forms; | |||||
using Ameliorated.ConsoleUtils; | |||||
using Microsoft.Dism; | |||||
// Asks user to select Windows installation media, and mounts it if applicable | |||||
// Returns path to where it's mounted | |||||
namespace amecs.Misc | |||||
{ | |||||
public static class SelectWindowsImage | |||||
{ | |||||
private static string _fileViolationTest; | |||||
private static bool CheckFileViolation(string inputFile) | |||||
{ | |||||
try | |||||
{ | |||||
_fileViolationTest = inputFile; | |||||
} | |||||
catch (SecurityException e) | |||||
{ | |||||
Console.WriteLine(); | |||||
ConsoleTUI.OpenFrame.Close("Security exception: " + e.Message, ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt { AnyKey = true, Text = "Press any key to return to the Menu: " }); | |||||
return true; | |||||
} | |||||
return false; | |||||
} | |||||
public static string GetWindowsVersion(float majorMinor, int isoBuild) | |||||
{ | |||||
return (majorMinor, isoBuild) switch | |||||
{ | |||||
(6, _) => "Windows Vista", | |||||
(6.1f, _) => "Windows 7", | |||||
(6.2f, _) => "Windows 8", | |||||
(6.3f, _) => "Windows 8.1", | |||||
(10, var a) when a < 19041 => "Windows 10 (Old)", | |||||
(10, var a) when a >= 22000 => "Windows 11", | |||||
(10, _) => "Windows 10", | |||||
_ => "Unknown" | |||||
}; | |||||
} | |||||
public static bool DismountIso(string imagePath) | |||||
{ | |||||
var startInfo = new ProcessStartInfo | |||||
{ | |||||
CreateNoWindow = false, | |||||
UseShellExecute = false, | |||||
FileName = "PowerShell.exe", | |||||
WindowStyle = ProcessWindowStyle.Hidden, | |||||
Arguments = $"-NoP -C \"Dismount-DiskImage '{imagePath}'\"", | |||||
RedirectStandardOutput = true | |||||
}; | |||||
var proc = Process.Start(startInfo); | |||||
if (proc == null) return false; | |||||
proc.WaitForExit(); | |||||
return true; | |||||
} | |||||
private static string _mountedPath; | |||||
private static string _isoPath; | |||||
private static string _isoWinVer; | |||||
private static int _isoBuild; | |||||
/// <summary> | |||||
/// Asks user to select Windows installation media, mounts it if applicable, and checks its version | |||||
/// </summary> | |||||
/// <param name="winVersionsMustMatch">If true when ISO and host versions mismatch, prompts user that things can break if they continue</param> | |||||
/// <param name="isoBuildMustBeReturned">If true and the ISO build can't be retrieved, prompts a user with an error</param> | |||||
public static ( | |||||
string MountedPath, string IsoPath, string Winver, int? Build, bool? VersionsMatch | |||||
) GetMediaPath(bool winVersionsMustMatch = false, bool isoBuildMustBeReturned = false) | |||||
{ | |||||
var error = ((string)null, "none", (string)null, (int?)null, (bool?)null); | |||||
var choice = | |||||
new ChoicePrompt { Text = "To continue, Windows installation media is needed.\r\nDo you have a Windows USB instead of an ISO file? (Y/N): " }.Start(); | |||||
if (!choice.HasValue) return error; | |||||
// Folder/drive chosen | |||||
var usingFolder = choice == 0; | |||||
if (usingFolder) | |||||
{ | |||||
var dlg = new FolderPicker | |||||
{ | |||||
InputPath = Globals.UserFolder | |||||
}; | |||||
if (dlg.ShowDialog(IntPtr.Zero).GetValueOrDefault()) | |||||
{ | |||||
if (CheckFileViolation(dlg.ResultPath)) | |||||
return error; | |||||
_mountedPath = dlg.ResultPath; | |||||
} | |||||
else | |||||
{ | |||||
Console.WriteLine(); | |||||
ConsoleTUI.OpenFrame.Close("\r\nYou must select a folder or drive containing Windows installation media.", | |||||
new ChoicePrompt { AnyKey = true, Text = "Press any key to return to the Menu: " }); | |||||
return error; | |||||
} | |||||
} | |||||
else | |||||
{ | |||||
// Mounting the ISO | |||||
var dialog = new OpenFileDialog(); | |||||
dialog.Filter = "ISO Files (*.ISO)| *.ISO"; | |||||
dialog.Multiselect = false; | |||||
dialog.InitialDirectory = Globals.UserFolder; | |||||
var window = new NativeWindow(); | |||||
window.AssignHandle(Process.GetCurrentProcess().MainWindowHandle); | |||||
if (dialog.ShowDialog(window) == DialogResult.OK) | |||||
{ | |||||
_isoPath = dialog.FileName; | |||||
if (CheckFileViolation(_isoPath)) return error; | |||||
Console.WriteLine(); | |||||
ConsoleTUI.OpenFrame.WriteCentered("\r\nMounting ISO"); | |||||
} | |||||
else | |||||
{ | |||||
Console.WriteLine(); | |||||
ConsoleTUI.OpenFrame.Close("\r\nYou must select an ISO.", | |||||
new ChoicePrompt { AnyKey = true, Text = "Press any key to return to the Menu: " }); | |||||
return error; | |||||
} | |||||
using (new ConsoleUtils.LoadingIndicator(true)) | |||||
{ | |||||
var startInfo = new ProcessStartInfo | |||||
{ | |||||
CreateNoWindow = false, | |||||
UseShellExecute = false, | |||||
FileName = "PowerShell.exe", | |||||
WindowStyle = ProcessWindowStyle.Hidden, | |||||
Arguments = $"-NoP -C \"(Mount-DiskImage '{_isoPath}' -PassThru | Get-Volume).DriveLetter + ':\'\"", | |||||
RedirectStandardOutput = true | |||||
}; | |||||
var proc = Process.Start(startInfo); | |||||
if (proc == null) return error; | |||||
proc.WaitForExit(); | |||||
_mountedPath = proc.StandardOutput.ReadLine(); | |||||
} | |||||
} | |||||
// Check WIM version | |||||
var wimOrEsdPath = new[] { $@"{_mountedPath}\sources\install.esd", $@"{_mountedPath}\sources\install.wim" }.FirstOrDefault(File.Exists); | |||||
if (!string.IsNullOrEmpty(wimOrEsdPath)) | |||||
{ | |||||
try | |||||
{ | |||||
DismApi.Initialize(DismLogLevel.LogErrors); | |||||
string previousIndexVersion = null; | |||||
string isoFullVersion = null; | |||||
var multiVersion = false; | |||||
var imageInfos = DismApi.GetImageInfo(wimOrEsdPath); | |||||
foreach (var imageInfo in imageInfos) | |||||
{ | |||||
isoFullVersion = imageInfo.ProductVersion.ToString(); | |||||
if (isoFullVersion != previousIndexVersion && previousIndexVersion != null) | |||||
{ | |||||
// If it's multi-version, WinVer will be "Unknown" as well | |||||
multiVersion = true; | |||||
isoFullVersion = "0.0.0.0"; | |||||
break; | |||||
} | |||||
previousIndexVersion = isoFullVersion; | |||||
} | |||||
switch (multiVersion) | |||||
{ | |||||
case true when isoBuildMustBeReturned: | |||||
ConsoleTUI.OpenFrame.Close( | |||||
"Multiple Windows versions were found in the Windows image, can't determine which Windows build it is. Please use an unmodified Windows ISO.", | |||||
ConsoleColor.Red, Console.BackgroundColor, | |||||
new ChoicePrompt { AnyKey = true, Text = "Press any key to return to the Menu: " }); | |||||
return error; | |||||
case true when winVersionsMustMatch: | |||||
ConsoleTUI.OpenFrame.Close( | |||||
"Multiple Windows versions were found in the Windows image, can't determine which Windows build it is. If your Windows version doesn't match the ISO, there will be problems.", | |||||
ConsoleColor.Red, Console.BackgroundColor, | |||||
new ChoicePrompt { AnyKey = true, Text = "Press any key to continue anyways: " }); | |||||
Program.Frame.Clear(); | |||||
ConsoleTUI.OpenFrame.WriteCentered("\r\nContinuing without version check...\r\n"); | |||||
break; | |||||
} | |||||
var buildSplit = isoFullVersion.Split('.'); | |||||
_isoBuild = int.Parse(buildSplit[2]); | |||||
_isoWinVer = GetWindowsVersion(float.Parse($"{buildSplit[0]}.{buildSplit[1]}"), _isoBuild); | |||||
} | |||||
catch (Exception e) | |||||
{ | |||||
Console.WriteLine(); | |||||
ConsoleTUI.OpenFrame.Close( | |||||
"Error checking ISO version: " + e.Message.TrimEnd('\n').TrimEnd('\r'), | |||||
ConsoleColor.Red, Console.BackgroundColor, | |||||
new ChoicePrompt { AnyKey = true, Text = "Press any key to return to the Menu: " }); | |||||
return error; | |||||
} | |||||
finally | |||||
{ | |||||
try | |||||
{ | |||||
DismApi.Shutdown(); | |||||
} | |||||
catch | |||||
{ | |||||
// do nothing | |||||
} | |||||
} | |||||
// Check the current OS version | |||||
var hostVersion = Environment.OSVersion.Version; | |||||
var hostWinver = GetWindowsVersion(float.Parse($"{hostVersion.Major}.{hostVersion.Minor}"), hostVersion.Build); | |||||
// If it all matches & winVersionsMustMatch | |||||
if (hostWinver == _isoWinVer) return (_mountedPath, _isoPath, _isoWinVer, _isoBuild, true); | |||||
// If ISO version doesn't match host version & winVersionsMustMatch | |||||
if (hostWinver != _isoWinVer && winVersionsMustMatch) | |||||
{ | |||||
if (!string.IsNullOrEmpty(_isoPath)) DismountIso(_isoPath); | |||||
ConsoleTUI.OpenFrame.Close( | |||||
$"You're on {hostWinver}, but the selected image is {_isoWinVer}. You can only use an ISO that matches your Windows version.", | |||||
ConsoleColor.Red, Console.BackgroundColor, | |||||
new ChoicePrompt { AnyKey = true, Text = "Press any key to return to the Menu: " }); | |||||
return error; | |||||
} | |||||
// If ISO version doesn't match host version, and winVersionsMustMatch is true | |||||
if (hostWinver != _isoWinVer) return (_mountedPath, _isoPath, _isoWinVer, _isoBuild, false); | |||||
} | |||||
var noWimText = isoBuildMustBeReturned | |||||
? "Press any key to return to the Menu" | |||||
: "Press any key to continue anyways"; | |||||
ConsoleTUI.OpenFrame.Close( | |||||
"No Windows installation image was found inside the selected Windows media. No version check can be done, things might break.", | |||||
ConsoleColor.Red, Console.BackgroundColor, | |||||
new ChoicePrompt { AnyKey = true, Text = $"{noWimText}: " }); | |||||
Program.Frame.Clear(); | |||||
ConsoleTUI.OpenFrame.WriteCentered("\r\nContinuing without version check\r\n"); | |||||
return isoBuildMustBeReturned ? error : (_mountedPath, _isoPath, null, null, null); | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,525 @@ | |||||
using System; | |||||
using System.Diagnostics; | |||||
using System.IO; | |||||
using System.Runtime.ConstrainedExecution; | |||||
using System.Runtime.InteropServices; | |||||
using System.Security; | |||||
using System.Security.Principal; | |||||
using System.Threading; | |||||
using System.Threading.Tasks; | |||||
using Microsoft.Win32.SafeHandles; | |||||
namespace amecs | |||||
{ | |||||
[StructLayout(LayoutKind.Sequential)] | |||||
public class NSudo | |||||
{ | |||||
private struct SECURITY_ATTRIBUTES | |||||
{ | |||||
public int nLength; | |||||
public unsafe byte* lpSecurityDescriptor; | |||||
public int bInheritHandle; | |||||
} | |||||
private enum SECURITY_IMPERSONATION_LEVEL | |||||
{ | |||||
SecurityAnonymous, | |||||
SecurityIdentification, | |||||
SecurityImpersonation, | |||||
SecurityDelegation | |||||
} | |||||
private enum TOKEN_TYPE { | |||||
TokenPrimary = 1, | |||||
TokenImpersonation | |||||
} | |||||
[StructLayout(LayoutKind.Sequential)] | |||||
private struct LUID { | |||||
public uint LowPart; | |||||
public uint HighPart; | |||||
} | |||||
[StructLayout(LayoutKind.Sequential, Pack = 4)] | |||||
private struct LUID_AND_ATTRIBUTES { | |||||
public LUID Luid; | |||||
public UInt32 Attributes; | |||||
} | |||||
private struct TOKEN_PRIVILEGES { | |||||
public int PrivilegeCount; | |||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst=1)] | |||||
public LUID_AND_ATTRIBUTES[] Privileges; | |||||
} | |||||
private static UInt32 MAXIMUM_ALLOWED = (UInt32)TokenAccessLevels.MaximumAllowed; | |||||
[DllImport("advapi32.dll", SetLastError=true)] | |||||
[return: MarshalAs(UnmanagedType.Bool)] | |||||
private static extern bool OpenProcessToken(IntPtr ProcessHandle, | |||||
UInt32 DesiredAccess, out IntPtr TokenHandle); | |||||
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)] | |||||
private static extern bool DuplicateTokenEx( | |||||
IntPtr hExistingToken, | |||||
uint dwDesiredAccess, | |||||
IntPtr lpTokenAttributes, | |||||
SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, | |||||
TOKEN_TYPE TokenType, | |||||
out IntPtr phNewToken ); | |||||
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)] | |||||
private static extern bool DuplicateTokenEx( | |||||
IntPtr hExistingToken, | |||||
uint dwDesiredAccess, | |||||
ref SECURITY_ATTRIBUTES lpTokenAttributes, | |||||
SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, | |||||
TOKEN_TYPE TokenType, | |||||
out IntPtr phNewToken ); | |||||
[DllImport("advapi32.dll")] | |||||
static extern bool LookupPrivilegeValue(IntPtr lpSystemName, string lpName, | |||||
ref LUID lpLuid); | |||||
internal const int SE_PRIVILEGE_ENABLED = 0x00000002; | |||||
// Use this signature if you do not want the previous state | |||||
[DllImport("advapi32.dll", SetLastError=true)] | |||||
[return: MarshalAs(UnmanagedType.Bool)] | |||||
static extern bool AdjustTokenPrivileges(IntPtr TokenHandle, | |||||
[MarshalAs(UnmanagedType.Bool)]bool DisableAllPrivileges, | |||||
ref TOKEN_PRIVILEGES NewState, | |||||
UInt32 Zero, | |||||
IntPtr Null1, | |||||
IntPtr Null2); | |||||
[System.Runtime.InteropServices.DllImport("advapi32.dll", SetLastError = true)] | |||||
private static extern bool SetThreadToken(IntPtr pHandle, | |||||
IntPtr hToken); | |||||
[DllImport("wtsapi32.dll", SetLastError=true)] | |||||
static extern bool WTSQueryUserToken(UInt32 sessionId, out IntPtr Token); | |||||
[DllImport("advapi32.dll", SetLastError = true)] | |||||
static extern Boolean SetTokenInformation(IntPtr TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, | |||||
ref UInt32 TokenInformation, UInt32 TokenInformationLength); | |||||
[DllImport("userenv.dll", SetLastError=true)] | |||||
static extern bool CreateEnvironmentBlock(out IntPtr lpEnvironment, IntPtr hToken, bool bInherit ); | |||||
public static bool GetUserPrivilege(IntPtr Token) | |||||
{ | |||||
IntPtr NewToken; | |||||
DuplicateTokenEx(Token, MAXIMUM_ALLOWED, IntPtr.Zero, SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, TOKEN_TYPE.TokenImpersonation, out NewToken); | |||||
SetThreadToken(IntPtr.Zero, NewToken); | |||||
return true; | |||||
} | |||||
[DllImport("advapi32.dll", SetLastError=true, CharSet=CharSet.Unicode)] | |||||
static extern bool CreateProcessAsUser( | |||||
IntPtr hToken, | |||||
string lpApplicationName, | |||||
string lpCommandLine, | |||||
ref SECURITY_ATTRIBUTES lpProcessAttributes, | |||||
ref SECURITY_ATTRIBUTES lpThreadAttributes, | |||||
bool bInheritHandles, | |||||
uint dwCreationFlags, | |||||
IntPtr lpEnvironment, | |||||
string lpCurrentDirectory, | |||||
ref STARTUPINFO lpStartupInfo, | |||||
out PROCESS_INFORMATION lpProcessInformation); | |||||
[Flags] | |||||
enum CreationFlags | |||||
{ | |||||
CREATE_SUSPENDED = 0x00000004, | |||||
CREATE_UNICODE_ENVIRONMENT = 0x00000400, | |||||
CREATE_NO_WINDOW = 0x08000000, | |||||
CREATE_NEW_CONSOLE = 0x00000010 | |||||
} | |||||
[DllImport("advapi32.dll", SetLastError = true, BestFitMapping = false, ThrowOnUnmappableChar = true)] | |||||
[return: MarshalAs(UnmanagedType.Bool)] | |||||
internal static extern bool LogonUser( | |||||
[MarshalAs(UnmanagedType.LPStr)] string pszUserName, | |||||
[MarshalAs(UnmanagedType.LPStr)] string pszDomain, | |||||
[MarshalAs(UnmanagedType.LPStr)] string pszPassword, | |||||
int dwLogonType, | |||||
int dwLogonProvider, | |||||
ref IntPtr phToken); | |||||
public static int? RunProcessAsUser(IntPtr Token, string Executable, string Arguments, uint timeout = 0xFFFFFFFF) | |||||
{ | |||||
GetAssignPrivilege(); | |||||
GetQuotaPrivilege(); | |||||
var startupInfo = new STARTUPINFO(); | |||||
startupInfo.cb = Marshal.SizeOf(startupInfo); | |||||
startupInfo.dwFlags = 0x00000001; | |||||
startupInfo.wShowWindow = 1; | |||||
var procAttrs = new SECURITY_ATTRIBUTES(); | |||||
var threadAttrs = new SECURITY_ATTRIBUTES(); | |||||
procAttrs.nLength = Marshal.SizeOf(procAttrs); | |||||
threadAttrs.nLength = Marshal.SizeOf(threadAttrs); | |||||
// Log on user temporarily in order to start console process in its security context. | |||||
var hUserTokenDuplicate = IntPtr.Zero; | |||||
var pEnvironmentBlock = IntPtr.Zero; | |||||
DuplicateTokenEx(Token, MAXIMUM_ALLOWED, IntPtr.Zero, SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, TOKEN_TYPE.TokenPrimary, out hUserTokenDuplicate); | |||||
CreateEnvironmentBlock(out pEnvironmentBlock, Token, false); | |||||
PROCESS_INFORMATION _processInfo; | |||||
if (!CreateProcessAsUser(hUserTokenDuplicate, null, String.IsNullOrEmpty(Arguments) ? $"\"{Executable}\"" : $"\"{Executable}\" {Arguments}", | |||||
ref procAttrs, ref threadAttrs, false, (uint)CreationFlags.CREATE_NO_WINDOW | | |||||
(uint)CreationFlags.CREATE_UNICODE_ENVIRONMENT, | |||||
pEnvironmentBlock, null, ref startupInfo, out _processInfo)) return null; | |||||
uint exitCode; | |||||
WaitForSingleObject(_processInfo.hProcess, timeout); | |||||
GetExitCodeProcess(_processInfo.hProcess, out exitCode); | |||||
return (int)exitCode; | |||||
/* | |||||
uint dwCreationFlags = (uint)CreationFlags.CREATE_UNICODE_ENVIRONMENT; | |||||
startupInfo.cb = Marshal.SizeOf(startupInfo); | |||||
SECURITY_ATTRIBUTES throwaway = new SECURITY_ATTRIBUTES(); | |||||
SECURITY_ATTRIBUTES throwaway2 = new SECURITY_ATTRIBUTES(); | |||||
Console.WriteLine(Marshal.GetLastWin32Error() + "-3"); | |||||
Console.WriteLine(CreateProcessAsUser(hUserToken, String.Empty, "\"C:\\Windows\\notepad.exe\"", ref throwaway, ref throwaway2, false, 0, IntPtr.Zero, String.Empty, ref StartupInfo, out ProcessInfo)); | |||||
Console.WriteLine(Marshal.GetLastWin32Error() + "-4"); | |||||
return Process.GetProcessById(ProcessInfo.dwProcessId); | |||||
*/ | |||||
} | |||||
[DllImport("kernel32.dll", SetLastError = true)] | |||||
[return: MarshalAs(UnmanagedType.Bool)] | |||||
static extern bool GetExitCodeProcess(IntPtr hProcess, out uint lpExitCode); | |||||
[DllImport("kernel32.dll", SetLastError=true)] | |||||
static extern UInt32 WaitForSingleObject(IntPtr hHandle, UInt32 dwMilliseconds); | |||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] | |||||
struct STARTUPINFO | |||||
{ | |||||
public Int32 cb; | |||||
public IntPtr lpReserved; | |||||
public IntPtr lpDesktop; | |||||
public IntPtr lpTitle; | |||||
public Int32 dwX; | |||||
public Int32 dwY; | |||||
public Int32 dwXSize; | |||||
public Int32 dwYSize; | |||||
public Int32 dwXCountChars; | |||||
public Int32 dwYCountChars; | |||||
public Int32 dwFillAttribute; | |||||
public Int32 dwFlags; | |||||
public Int16 wShowWindow; | |||||
public Int16 cbReserved2; | |||||
public IntPtr lpReserved2; | |||||
public IntPtr hStdInput; | |||||
public IntPtr hStdOutput; | |||||
public IntPtr hStdError; | |||||
} | |||||
[StructLayout(LayoutKind.Sequential)] | |||||
internal struct PROCESS_INFORMATION | |||||
{ | |||||
public IntPtr hProcess; | |||||
public IntPtr hThread; | |||||
public int dwProcessId; | |||||
public int dwThreadId; | |||||
} | |||||
public static IntPtr GetUserToken() | |||||
{ | |||||
IntPtr Token; | |||||
WTSQueryUserToken((uint)SessionID, out Token); | |||||
return Token; | |||||
} | |||||
private static int SessionID = -1; | |||||
public static bool GetSystemPrivilege() | |||||
{ | |||||
IntPtr CurrentProcessToken; | |||||
OpenProcessToken(Process.GetCurrentProcess().Handle, MAXIMUM_ALLOWED, out CurrentProcessToken); | |||||
IntPtr DuplicatedCurrentProcessToken; | |||||
DuplicateTokenEx(CurrentProcessToken, MAXIMUM_ALLOWED, IntPtr.Zero, SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, TOKEN_TYPE.TokenImpersonation, out DuplicatedCurrentProcessToken); | |||||
LUID_AND_ATTRIBUTES RawPrivilege = new LUID_AND_ATTRIBUTES(); | |||||
LookupPrivilegeValue(IntPtr.Zero, "SeDebugPrivilege", ref RawPrivilege.Luid); | |||||
RawPrivilege.Attributes = SE_PRIVILEGE_ENABLED; | |||||
TOKEN_PRIVILEGES TokenPrivilege = new TOKEN_PRIVILEGES(); | |||||
TokenPrivilege.Privileges = new LUID_AND_ATTRIBUTES[] { RawPrivilege }; | |||||
TokenPrivilege.PrivilegeCount = 1; | |||||
AdjustTokenPrivileges(DuplicatedCurrentProcessToken, false, ref TokenPrivilege, 0, IntPtr.Zero, IntPtr.Zero); | |||||
SetThreadToken(IntPtr.Zero, DuplicatedCurrentProcessToken); | |||||
SessionID = GetActiveSession(); | |||||
IntPtr OriginalProcessToken = new IntPtr(-1); | |||||
CreateSystemToken((int)MAXIMUM_ALLOWED, SessionID, ref OriginalProcessToken); | |||||
IntPtr SystemToken; | |||||
DuplicateTokenEx(OriginalProcessToken, MAXIMUM_ALLOWED, IntPtr.Zero, SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, TOKEN_TYPE.TokenImpersonation, out SystemToken); | |||||
SetThreadToken(IntPtr.Zero, SystemToken); | |||||
return true; | |||||
} | |||||
[DllImport("advapi32.dll", SetLastError=true)] | |||||
static extern bool GetTokenInformation( | |||||
IntPtr TokenHandle, | |||||
TOKEN_INFORMATION_CLASS TokenInformationClass, | |||||
IntPtr TokenInformation, | |||||
int TokenInformationLength, | |||||
out int ReturnLength); | |||||
enum TOKEN_INFORMATION_CLASS | |||||
{ | |||||
TokenUser = 1, | |||||
TokenGroups, | |||||
TokenPrivileges, | |||||
TokenOwner, | |||||
TokenPrimaryGroup, | |||||
TokenDefaultDacl, | |||||
TokenSource, | |||||
TokenType, | |||||
TokenImpersonationLevel, | |||||
TokenStatistics, | |||||
TokenRestrictedSids, | |||||
TokenSessionId, | |||||
TokenGroupsAndPrivileges, | |||||
TokenSessionReference, | |||||
TokenSandBoxInert, | |||||
TokenAuditPolicy, | |||||
TokenOrigin | |||||
} | |||||
private static int GetActiveSession() | |||||
{ | |||||
IntPtr pSessionInfo = IntPtr.Zero; | |||||
Int32 Count = 0; | |||||
var retval = WTSEnumerateSessions((IntPtr)null, 0, 1, ref pSessionInfo, ref Count); | |||||
Int32 dataSize = Marshal.SizeOf(typeof(WTS_SESSION_INFO)); | |||||
Int64 current = (Int64)pSessionInfo; | |||||
int result = -1; | |||||
if (retval != 0) | |||||
{ | |||||
for (int i = 0; i < Count; i++) | |||||
{ | |||||
WTS_SESSION_INFO si = (WTS_SESSION_INFO)Marshal.PtrToStructure((System.IntPtr)current, typeof(WTS_SESSION_INFO)); | |||||
current += dataSize; | |||||
if (si.State == WTS_CONNECTSTATE_CLASS.WTSActive) | |||||
{ | |||||
result = si.SessionID; | |||||
break; | |||||
} | |||||
} | |||||
WTSFreeMemory(pSessionInfo); | |||||
} | |||||
return result; | |||||
} | |||||
private static void CreateSystemToken(int DesiredAccess, int dwSessionID, ref IntPtr TokenHandle) | |||||
{ | |||||
int dwLsassPID = -1; | |||||
int dwWinLogonPID = -1; | |||||
WTS_PROCESS_INFO[] pProcesses; | |||||
IntPtr pProcessInfo = IntPtr.Zero; | |||||
int dwProcessCount = 0; | |||||
if (WTSEnumerateProcesses((IntPtr)null, 0, 1, ref pProcessInfo, ref dwProcessCount)) | |||||
{ | |||||
IntPtr pMemory = pProcessInfo; | |||||
pProcesses = new WTS_PROCESS_INFO[dwProcessCount]; | |||||
for (int i = 0; i < dwProcessCount; i++) | |||||
{ | |||||
pProcesses[i] = (WTS_PROCESS_INFO)Marshal.PtrToStructure(pProcessInfo, typeof(WTS_PROCESS_INFO)); | |||||
pProcessInfo = (IntPtr)((long)pProcessInfo + Marshal.SizeOf(pProcesses[i])); | |||||
var processName = Marshal.PtrToStringAnsi(pProcesses[i].ProcessName); | |||||
ConvertSidToStringSid(pProcesses[i].UserSid, out string sid); | |||||
string strSid; | |||||
if (processName == null || pProcesses[i].UserSid == default || sid != "S-1-5-18") | |||||
continue; | |||||
if ((-1 == dwLsassPID) && (0 == pProcesses[i].SessionID) && (processName == "lsass.exe")) | |||||
{ | |||||
dwLsassPID = pProcesses[i].ProcessID; | |||||
continue; | |||||
} | |||||
if ((-1 == dwWinLogonPID) && (dwSessionID == pProcesses[i].SessionID) && (processName == "winlogon.exe")) | |||||
{ | |||||
dwWinLogonPID = pProcesses[i].ProcessID; | |||||
continue; | |||||
} | |||||
} | |||||
WTSFreeMemory(pMemory); | |||||
} | |||||
bool Result = false; | |||||
IntPtr SystemProcessHandle = IntPtr.Zero; | |||||
try | |||||
{ | |||||
SystemProcessHandle = Process.GetProcessById(dwLsassPID).Handle; | |||||
} catch | |||||
{ | |||||
SystemProcessHandle = Process.GetProcessById(dwWinLogonPID).Handle; | |||||
} | |||||
IntPtr SystemTokenHandle = IntPtr.Zero; | |||||
if (OpenProcessToken(SystemProcessHandle, TOKEN_DUPLICATE, out SystemTokenHandle)) | |||||
{ | |||||
Result = DuplicateTokenEx(SystemTokenHandle, (uint)DesiredAccess, IntPtr.Zero, SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, TOKEN_TYPE.TokenPrimary, out TokenHandle); | |||||
CloseHandle(SystemTokenHandle); | |||||
} | |||||
CloseHandle(SystemProcessHandle); | |||||
// return Result; | |||||
return; | |||||
} | |||||
[DllImport("kernel32.dll", SetLastError = true)] | |||||
public static extern IntPtr OpenProcess( | |||||
uint processAccess, | |||||
bool bInheritHandle, | |||||
uint processId | |||||
); | |||||
public const UInt32 TOKEN_DUPLICATE = 0x0002; | |||||
[DllImport("advapi32", CharSet = CharSet.Auto, SetLastError = true)] | |||||
static extern bool ConvertSidToStringSid(IntPtr pSid, out string strSid); | |||||
[DllImport("kernel32.dll", SetLastError=true)] | |||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] | |||||
[SuppressUnmanagedCodeSecurity] | |||||
[return: MarshalAs(UnmanagedType.Bool)] | |||||
static extern bool CloseHandle(IntPtr hObject); | |||||
[DllImport("wtsapi32.dll", SetLastError=true)] | |||||
static extern int WTSEnumerateSessions( | |||||
System.IntPtr hServer, | |||||
int Reserved, | |||||
int Version, | |||||
ref System.IntPtr ppSessionInfo, | |||||
ref int pCount); | |||||
[StructLayout(LayoutKind.Sequential)] | |||||
private struct WTS_SESSION_INFO | |||||
{ | |||||
public Int32 SessionID; | |||||
[MarshalAs(UnmanagedType.LPStr)] | |||||
public String pWinStationName; | |||||
public WTS_CONNECTSTATE_CLASS State; | |||||
} | |||||
public enum WTS_CONNECTSTATE_CLASS | |||||
{ | |||||
WTSActive, | |||||
WTSConnected, | |||||
WTSConnectQuery, | |||||
WTSShadow, | |||||
WTSDisconnected, | |||||
WTSIdle, | |||||
WTSListen, | |||||
WTSReset, | |||||
WTSDown, | |||||
WTSInit | |||||
} | |||||
[DllImport("wtsapi32.dll")] | |||||
static extern void WTSFreeMemory(IntPtr pMemory); | |||||
[DllImport("wtsapi32.dll", SetLastError=true)] | |||||
static extern bool WTSEnumerateProcesses( | |||||
IntPtr serverHandle, // Handle to a terminal server. | |||||
Int32 reserved, // must be 0 | |||||
Int32 version, // must be 1 | |||||
ref IntPtr ppProcessInfo, // pointer to array of WTS_PROCESS_INFO | |||||
ref Int32 pCount // pointer to number of processes | |||||
); | |||||
struct WTS_PROCESS_INFO | |||||
{ | |||||
public int SessionID; | |||||
public int ProcessID; | |||||
//This is a pointer to string... | |||||
public IntPtr ProcessName; | |||||
public IntPtr UserSid; | |||||
} | |||||
[DllImport("ntdll.dll", SetLastError = true)] | |||||
static extern IntPtr RtlAdjustPrivilege(int Privilege, bool bEnablePrivilege, bool IsThreadPrivilege, out bool PreviousValue); | |||||
[DllImport("advapi32.dll")] | |||||
static extern bool LookupPrivilegeValue(IntPtr lpSystemName, string lpName, ref UInt64 lpLuid); | |||||
public static void GetOwnershipPrivilege() | |||||
{ | |||||
ulong luid = 0; | |||||
bool throwaway; | |||||
LookupPrivilegeValue(IntPtr.Zero, "SeTakeOwnershipPrivilege", ref luid); | |||||
RtlAdjustPrivilege((int)luid, true, true, out throwaway); | |||||
} | |||||
public static void GetAssignPrivilege() | |||||
{ | |||||
ulong luid = 0; | |||||
bool throwaway; | |||||
LookupPrivilegeValue(IntPtr.Zero, "SeAssignPrimaryTokenPrivilege", ref luid); | |||||
RtlAdjustPrivilege((int)luid, true, true, out throwaway); | |||||
} | |||||
public static void GetQuotaPrivilege() | |||||
{ | |||||
ulong luid = 0; | |||||
bool throwaway; | |||||
LookupPrivilegeValue(IntPtr.Zero, "SeIncreaseQuotaPrivilege", ref luid); | |||||
RtlAdjustPrivilege((int)luid, true, true, out throwaway); | |||||
} | |||||
public static void GetShutdownPrivilege() | |||||
{ | |||||
ulong luid = 0; | |||||
bool throwaway; | |||||
LookupPrivilegeValue(IntPtr.Zero, "SeShutdownPrivilege", ref luid); | |||||
RtlAdjustPrivilege((int)luid, true, true, out throwaway); | |||||
} | |||||
public static void RunAsUser(Action action) | |||||
{ | |||||
var token = NSudo.GetUserToken(); | |||||
Task.Run((Action)Delegate.Combine((Action)(() => { NSudo.GetUserPrivilege(token); }), | |||||
action)).Wait(); | |||||
Marshal.FreeHGlobal(token); | |||||
} | |||||
private static async Task RunAsUserAsync(Action action) | |||||
{ | |||||
var token = NSudo.GetUserToken(); | |||||
await Task.Run((Action)Delegate.Combine((Action)(() => { NSudo.GetUserPrivilege(token); }), | |||||
action)); | |||||
Marshal.FreeHGlobal(token); | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,141 @@ | |||||
using System; | |||||
using System.DirectoryServices.AccountManagement; | |||||
using System.Linq; | |||||
using System.Security.Principal; | |||||
using Ameliorated.ConsoleUtils; | |||||
using Microsoft.Win32; | |||||
using amecs.Actions; | |||||
using Menu = Ameliorated.ConsoleUtils.Menu; | |||||
namespace amecs | |||||
{ | |||||
internal class Program | |||||
{ | |||||
private const string Ver = "2.1"; | |||||
public static ConsoleTUI.Frame Frame; | |||||
[STAThread] | |||||
public static void Main(string[] args) | |||||
{ | |||||
ConsoleTUI.Initialize("Central AME Script"); | |||||
try | |||||
{ | |||||
NSudo.GetSystemPrivilege(); | |||||
if (!WindowsIdentity.GetCurrent().IsSystem) | |||||
throw new Exception("Identity did not change."); | |||||
NSudo.RunAsUser(() => | |||||
{ | |||||
Globals.Username = WindowsIdentity.GetCurrent().Name.Split('\\').Last(); | |||||
Globals.UserDomain = WindowsIdentity.GetCurrent().Name.Split('\\').FirstOrDefault(); | |||||
Globals.UserSID = WindowsIdentity.GetCurrent().User.ToString(); | |||||
}); | |||||
try | |||||
{ | |||||
Globals.UserFolder = Registry.Users.OpenSubKey(Globals.UserSID + "\\Volatile Environment").GetValue("USERPROFILE").ToString(); | |||||
} catch (Exception e) | |||||
{ | |||||
Console.WriteLine(Globals.Username); | |||||
ConsoleTUI.ShowErrorBox($"Could not fetch user folder information from user with SID '{Globals.UserSID}': " + e, "Central AME Script"); | |||||
Environment.Exit(1); | |||||
} | |||||
PrincipalContext context = new PrincipalContext(ContextType.Machine); | |||||
PrincipalSearcher userPrincipalSearcher = new PrincipalSearcher(new UserPrincipal(context)); | |||||
Globals.User = userPrincipalSearcher.FindAll().FirstOrDefault(x => (x is UserPrincipal) && x.Sid.Value == Globals.UserSID) as UserPrincipal; | |||||
PrincipalSearcher groupPrincipalSearcher = new PrincipalSearcher(new GroupPrincipal(context)); | |||||
Globals.Administrators = groupPrincipalSearcher.FindAll().FirstOrDefault(x => (x is GroupPrincipal) && x.Sid.IsWellKnown(WellKnownSidType.BuiltinAdministratorsSid)) as GroupPrincipal; | |||||
} catch (Exception e) | |||||
{ | |||||
ConsoleTUI.ShowErrorBox("Could not acquire System privileges: " + e, "Central AME Script"); | |||||
Environment.Exit(1); | |||||
} | |||||
Frame = new ConsoleTUI.Frame($"| Central AME Script v{Ver} |", false); | |||||
Frame.Open(); | |||||
while (true) | |||||
{ | |||||
Globals.UserElevated = Globals.User.IsMemberOf(Globals.Administrators); | |||||
Frame.Clear(); | |||||
bool usernameRequirement = new Reg.Value() | |||||
{ | |||||
KeyName = @"HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System", | |||||
ValueName = "dontdisplaylastusername", | |||||
Data = 1, | |||||
}.IsEqual(); | |||||
bool autoLogonEnabled = new Reg.Value() | |||||
{ | |||||
KeyName = @"HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon", | |||||
ValueName = "DefaultUsername", | |||||
Data = Globals.Username, | |||||
}.IsEqual() && | |||||
new Reg.Value() | |||||
{ | |||||
KeyName = @"HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon", | |||||
ValueName = "AutoAdminLogon", | |||||
Data = "1", | |||||
}.IsEqual(); | |||||
bool netInstalled = new Reg.Key() | |||||
{ | |||||
KeyName = @"HKLM\SOFTWARE\Microsoft\NET Framework Setup\NDP\v3.5", | |||||
Operation = RegistryOperation.Add | |||||
}.IsEqual(); | |||||
var mainMenu = new Ameliorated.ConsoleUtils.Menu() | |||||
{ | |||||
Choices = | |||||
{ | |||||
new Menu.MenuItem("Change Username or Password", new Func<bool>(UserPass.ShowMenu)), | |||||
new Menu.MenuItem("Change Lockscreen Image", new Func<bool>(Lockscreen.ChangeImage)), | |||||
new Menu.MenuItem("Change Profile Image", new Func<bool>(Profile.ChangeImage)), | |||||
Globals.UserElevated ? | |||||
new Menu.MenuItem( "De-elevate User", new Func<bool>(Elevation.DeElevate)) : | |||||
new Menu.MenuItem("Elevate User to Administrator", new Func<bool>(Elevation.Elevate)), | |||||
usernameRequirement ? | |||||
new Menu.MenuItem( "Disable Username Login Requirement", new Func<bool>(UsernameRequirement.Disable)) : | |||||
new Menu.MenuItem("Enable Username Login Requirement", new Func<bool>(UsernameRequirement.Enable)), | |||||
autoLogonEnabled ? | |||||
new Menu.MenuItem( "Disable AutoLogon", new Func<bool>(AutoLogon.Disable)) : | |||||
new Menu.MenuItem("Enable AutoLogon", new Func<bool>(AutoLogon.Enable)), | |||||
new Menu.MenuItem("Manage Language Settings", new Func<bool>(Languages.ShowMenu)), | |||||
new Menu.MenuItem("Manage Users", new Func<bool>(Users.ShowMenu)), | |||||
!netInstalled ? | |||||
new Menu.MenuItem("Install .NET 3.5", new Func<bool>(_NET.Install)) : | |||||
new Menu.MenuItem("Install .NET 3.5", new Func<bool>(_NET.Install)) {SecondaryText = "[Installed]", SecondaryTextForeground = ConsoleColor.Yellow, PrimaryTextForeground = ConsoleColor.DarkGray}, | |||||
Menu.MenuItem.Blank, | |||||
new Menu.MenuItem("Uninstall AME", new Func<bool>(Deameliorate.DeAme)), | |||||
new Menu.MenuItem("Extra", new Func<bool>(Extra.Extra.ShowMenu)), | |||||
new Menu.MenuItem("Exit", new Func<bool>(Globals.Exit)) | |||||
}, | |||||
SelectionForeground = ConsoleColor.Green | |||||
}; | |||||
Func<bool> result; | |||||
try | |||||
{ | |||||
mainMenu.Write(); | |||||
result = (Func<bool>)mainMenu.Load(); | |||||
} catch (Exception e) | |||||
{ | |||||
Console.WriteLine(e); | |||||
Console.ReadLine(); | |||||
return; | |||||
} | |||||
try | |||||
{ | |||||
result.Invoke(); | |||||
} catch (Exception e) | |||||
{ | |||||
ConsoleTUI.ShowErrorBox("Error while running an action: " + e.ToString(), null); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,35 @@ | |||||
using System.Reflection; | |||||
using System.Runtime.InteropServices; | |||||
// General Information about an assembly is controlled through the following | |||||
// set of attributes. Change these attribute values to modify the information | |||||
// associated with an assembly. | |||||
[assembly: AssemblyTitle("Central AME Script")] | |||||
[assembly: AssemblyDescription("Tool for automating a large assortment of AME related actions.")] | |||||
[assembly: AssemblyConfiguration("")] | |||||
[assembly: AssemblyCompany("")] | |||||
[assembly: AssemblyProduct("amecs")] | |||||
[assembly: AssemblyCopyright("MIT License")] | |||||
[assembly: AssemblyTrademark("")] | |||||
[assembly: AssemblyCulture("")] | |||||
// Setting ComVisible to false makes the types in this assembly not visible | |||||
// to COM components. If you need to access a type in this assembly from | |||||
// COM, set the ComVisible attribute to true on that type. | |||||
[assembly: ComVisible(false)] | |||||
// The following GUID is for the ID of the typelib if this project is exposed to COM | |||||
[assembly: Guid("BD020697-9E9B-4A46-8804-BC47F0FC2806")] | |||||
// Version information for an assembly consists of the following four values: | |||||
// | |||||
// Major Version | |||||
// Minor Version | |||||
// Build Number | |||||
// Revision | |||||
// | |||||
// You can specify all the values or you can default the Build and Revision Numbers | |||||
// by using the '*' as shown below: | |||||
// [assembly: AssemblyVersion("1.0.*")] | |||||
[assembly: AssemblyVersion("2.1")] | |||||
[assembly: AssemblyFileVersion("2.1")] |
@ -0,0 +1,375 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Linq; | |||||
using System.Runtime.InteropServices; | |||||
using System.Text.RegularExpressions; | |||||
using System.Threading.Tasks; | |||||
using Microsoft.Win32; | |||||
namespace amecs | |||||
{ | |||||
public enum RegistryOperation | |||||
{ | |||||
Delete = 0, | |||||
Add = 1 | |||||
} | |||||
public class Reg | |||||
{ | |||||
public class Key | |||||
{ | |||||
public string KeyName { get; set; } | |||||
//public Scope Scope { get; set; } = Scope.AllUsers; | |||||
public RegistryOperation Operation { get; set; } = RegistryOperation.Delete; | |||||
private List<RegistryKey> GetRoots() | |||||
{ | |||||
var hive = KeyName.Split('\\').GetValue(0).ToString().ToUpper(); | |||||
var list = new List<RegistryKey>(); | |||||
list.Add(hive switch | |||||
{ | |||||
"HKCU" => RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Default), | |||||
"HKEY_CURRENT_USER" => RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Default), | |||||
"HKLM" => RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Default), | |||||
"HKEY_LOCAL_MACHINE" => RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Default), | |||||
"HKCR" => RegistryKey.OpenBaseKey(RegistryHive.ClassesRoot, RegistryView.Default), | |||||
"HKEY_CLASSES_ROOT" => RegistryKey.OpenBaseKey(RegistryHive.ClassesRoot, RegistryView.Default), | |||||
"HKU" => RegistryKey.OpenBaseKey(RegistryHive.Users, RegistryView.Default), | |||||
"HKEY_USERS" => RegistryKey.OpenBaseKey(RegistryHive.Users, RegistryView.Default), | |||||
_ => throw new ArgumentException($"Key '{KeyName}' does not specify a valid registry hive.") | |||||
}); | |||||
return list; | |||||
} | |||||
public string GetSubKey() => KeyName.Substring(KeyName.IndexOf('\\') + 1); | |||||
public bool IsEqual() | |||||
{ | |||||
try | |||||
{ | |||||
var roots = GetRoots(); | |||||
foreach (var _root in roots) | |||||
{ | |||||
var root = _root; | |||||
var subKey = GetSubKey(); | |||||
var openedSubKey = root.OpenSubKey(subKey); | |||||
if (Operation == RegistryOperation.Delete && openedSubKey != null) | |||||
{ | |||||
return false; | |||||
} | |||||
if (Operation == RegistryOperation.Add && openedSubKey == null) | |||||
{ | |||||
return false; | |||||
} | |||||
} | |||||
} catch (Exception e) | |||||
{ | |||||
return false; | |||||
} | |||||
return true; | |||||
} | |||||
public bool Apply() | |||||
{ | |||||
var roots = GetRoots(); | |||||
foreach (var _root in roots) | |||||
{ | |||||
var root = _root; | |||||
var subKey = GetSubKey(); | |||||
var openedSubKey = root.OpenSubKey(subKey); | |||||
if (openedSubKey != null) openedSubKey.Close(); | |||||
if (Operation == RegistryOperation.Add && openedSubKey == null) | |||||
{ | |||||
root.CreateSubKey(subKey)?.Close(); | |||||
} | |||||
if (Operation == RegistryOperation.Delete) | |||||
{ | |||||
root.DeleteSubKeyTree(subKey, false); | |||||
} | |||||
root.Close(); | |||||
} | |||||
return true; | |||||
} | |||||
} | |||||
public enum RegistryValueOperation | |||||
{ | |||||
Delete = 0, | |||||
Add = 1, | |||||
// This indicates to skip the action if the specified value does not already exist | |||||
Set = 2 | |||||
} | |||||
public enum RegistryValueType | |||||
{ | |||||
REG_SZ = RegistryValueKind.String, | |||||
REG_MULTI_SZ = RegistryValueKind.MultiString, | |||||
REG_EXPAND_SZ = RegistryValueKind.ExpandString, | |||||
REG_DWORD = RegistryValueKind.DWord, | |||||
REG_QWORD = RegistryValueKind.QWord, | |||||
REG_BINARY = RegistryValueKind.Binary, | |||||
REG_NONE = RegistryValueKind.None, | |||||
REG_UNKNOWN = RegistryValueKind.Unknown | |||||
} | |||||
public class Value | |||||
{ | |||||
public string KeyName { get; set; } | |||||
public string ValueName { get; set; } = ""; | |||||
public object? Data { get; set; } | |||||
public RegistryValueType Type { get; set; } | |||||
//public Scope Scope { get; set; } = Scope.AllUsers; | |||||
public RegistryValueOperation Operation { get; set; } = RegistryValueOperation.Add; | |||||
private List<RegistryKey> GetRoots() | |||||
{ | |||||
var hive = KeyName.Split('\\').GetValue(0).ToString().ToUpper(); | |||||
var list = new List<RegistryKey>(); | |||||
list.Add(hive switch | |||||
{ | |||||
"HKCU" => RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Default), | |||||
"HKEY_CURRENT_USER" => RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Default), | |||||
"HKLM" => RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Default), | |||||
"HKEY_LOCAL_MACHINE" => RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Default), | |||||
"HKCR" => RegistryKey.OpenBaseKey(RegistryHive.ClassesRoot, RegistryView.Default), | |||||
"HKEY_CLASSES_ROOT" => RegistryKey.OpenBaseKey(RegistryHive.ClassesRoot, RegistryView.Default), | |||||
"HKU" => RegistryKey.OpenBaseKey(RegistryHive.Users, RegistryView.Default), | |||||
"HKEY_USERS" => RegistryKey.OpenBaseKey(RegistryHive.Users, RegistryView.Default), | |||||
_ => throw new ArgumentException($"Key '{KeyName}' does not specify a valid registry hive.") | |||||
}); | |||||
return list; | |||||
} | |||||
public string GetSubKey() => KeyName.Substring(KeyName.IndexOf('\\') + 1); | |||||
public object? GetCurrentValue(RegistryKey root) | |||||
{ | |||||
var subkey = GetSubKey(); | |||||
return Registry.GetValue(root.Name + "\\" + subkey, ValueName, null); | |||||
} | |||||
public static byte[] StringToByteArray(string hex) | |||||
{ | |||||
return Enumerable.Range(0, hex.Length) | |||||
.Where(x => x % 2 == 0) | |||||
.Select(x => Convert.ToByte(hex.Substring(x, 2), 16)) | |||||
.ToArray(); | |||||
} | |||||
public bool IsEqual() | |||||
{ | |||||
try | |||||
{ | |||||
var roots = GetRoots(); | |||||
foreach (var _root in roots) | |||||
{ | |||||
var root = _root; | |||||
var subKey = GetSubKey(); | |||||
var openedSubKey = root.OpenSubKey(subKey); | |||||
if (openedSubKey == null && (Operation == RegistryValueOperation.Set || Operation == RegistryValueOperation.Delete)) | |||||
continue; | |||||
if (openedSubKey == null) return false; | |||||
var value = openedSubKey.GetValue(ValueName); | |||||
if (value == null) | |||||
{ | |||||
if (Operation == RegistryValueOperation.Set || Operation == RegistryValueOperation.Delete) | |||||
continue; | |||||
return false; | |||||
} | |||||
if (Operation == RegistryValueOperation.Delete) return false; | |||||
if (Data == null) return false; | |||||
bool matches; | |||||
try | |||||
{ | |||||
matches = Type switch | |||||
{ | |||||
RegistryValueType.REG_SZ => | |||||
Data.ToString() == value.ToString(), | |||||
RegistryValueType.REG_EXPAND_SZ => | |||||
// RegistryValueOptions.DoNotExpandEnvironmentNames above did not seem to work. | |||||
Environment.ExpandEnvironmentVariables(Data.ToString()) == value.ToString(), | |||||
RegistryValueType.REG_MULTI_SZ => | |||||
Data.ToString() == "" ? ((string[])value).SequenceEqual(new string[] { }) : ((string[])value).SequenceEqual(Data.ToString().Split(new string[] { "\\0" }, StringSplitOptions.None)), | |||||
RegistryValueType.REG_DWORD => | |||||
unchecked((int)Convert.ToUInt32(Data)) == (int)value, | |||||
RegistryValueType.REG_QWORD => | |||||
Convert.ToUInt64(Data) == (ulong)value, | |||||
RegistryValueType.REG_BINARY => | |||||
((byte[])value).SequenceEqual(StringToByteArray(Data.ToString())), | |||||
RegistryValueType.REG_NONE => | |||||
((byte[])value).SequenceEqual(new byte[0]), | |||||
RegistryValueType.REG_UNKNOWN => | |||||
Data.ToString() == value.ToString(), | |||||
_ => throw new ArgumentException("Impossible.") | |||||
}; | |||||
} catch (InvalidCastException) | |||||
{ | |||||
matches = false; | |||||
} | |||||
if (!matches) return false; | |||||
} | |||||
} catch (Exception e) | |||||
{ | |||||
return false; | |||||
} | |||||
return true; | |||||
} | |||||
public bool Apply() | |||||
{ | |||||
var roots = GetRoots(); | |||||
foreach (var _root in roots) | |||||
{ | |||||
var root = _root; | |||||
var subKey = GetSubKey(); | |||||
if (GetCurrentValue(root) == Data) continue; | |||||
var opened = root.OpenSubKey(subKey); | |||||
if (opened == null && Operation == RegistryValueOperation.Set) continue; | |||||
if (opened == null && Operation == RegistryValueOperation.Add) root.CreateSubKey(subKey)?.Close(); | |||||
if (opened != null) opened.Close(); | |||||
if (Operation == RegistryValueOperation.Delete) | |||||
{ | |||||
var key = root.OpenSubKey(subKey, true); | |||||
key?.DeleteValue(ValueName); | |||||
key?.Close(); | |||||
root.Close(); | |||||
continue; | |||||
} | |||||
if (Type == RegistryValueType.REG_BINARY) | |||||
{ | |||||
var data = StringToByteArray(Data.ToString()); | |||||
Registry.SetValue(root.Name + "\\" + subKey, ValueName, data, (RegistryValueKind)Type); | |||||
} | |||||
else if (Type == RegistryValueType.REG_DWORD) | |||||
{ | |||||
// DWORD values using the highest bit set fail without this, for example '2962489444'. | |||||
// See https://stackoverflow.com/questions/6608400/how-to-put-a-dword-in-the-registry-with-the-highest-bit-set; | |||||
var value = unchecked((int)Convert.ToUInt32(Data)); | |||||
Registry.SetValue(root.Name + "\\" + subKey, ValueName, value, (RegistryValueKind)Type); | |||||
} | |||||
else if (Type == RegistryValueType.REG_QWORD) | |||||
{ | |||||
Registry.SetValue(root.Name + "\\" + subKey, ValueName, Convert.ToUInt64(Data), (RegistryValueKind)Type); | |||||
} | |||||
else if (Type == RegistryValueType.REG_NONE) | |||||
{ | |||||
byte[] none = new byte[0]; | |||||
Registry.SetValue(root.Name + "\\" + subKey, ValueName, none, (RegistryValueKind)Type); | |||||
} | |||||
else if (Type == RegistryValueType.REG_MULTI_SZ) | |||||
{ | |||||
string[] data; | |||||
if (Data.ToString() == "") data = new string[] { }; | |||||
else data = Data.ToString().Split(new string[] { "\\0" }, StringSplitOptions.None); | |||||
Registry.SetValue(root.Name + "\\" + subKey, ValueName, data, (RegistryValueKind)Type); | |||||
} | |||||
else | |||||
{ | |||||
Registry.SetValue(root.Name + "\\" + subKey, ValueName, Data, (RegistryValueKind)Type); | |||||
} | |||||
root.Close(); | |||||
} | |||||
return true; | |||||
} | |||||
} | |||||
[DllImport("advapi32.dll", SetLastError = true)] | |||||
static extern int RegLoadKey(IntPtr hKey, string lpSubKey, string lpFile); | |||||
[DllImport("advapi32.dll", SetLastError = true)] | |||||
static extern int RegSaveKey(IntPtr hKey, string lpFile, uint securityAttrPtr = 0); | |||||
[DllImport("advapi32.dll", SetLastError = true)] | |||||
static extern int RegUnLoadKey(IntPtr hKey, string lpSubKey); | |||||
[DllImport("ntdll.dll", SetLastError = true)] | |||||
static extern IntPtr RtlAdjustPrivilege(int Privilege, bool bEnablePrivilege, bool IsThreadPrivilege, out bool PreviousValue); | |||||
[DllImport("advapi32.dll")] | |||||
static extern bool LookupPrivilegeValue(string lpSystemName, string lpName, ref UInt64 lpLuid); | |||||
[DllImport("advapi32.dll")] | |||||
static extern bool LookupPrivilegeValue(IntPtr lpSystemName, string lpName, ref UInt64 lpLuid); | |||||
public static void LoadDefaultUserHive() | |||||
{ | |||||
var parentKey = RegistryKey.OpenBaseKey(RegistryHive.Users, RegistryView.Default); | |||||
IntPtr parentHandle = parentKey.Handle.DangerousGetHandle(); | |||||
AcquirePrivileges(); | |||||
RegLoadKey(parentHandle, "DefaultUserHive", Environment.ExpandEnvironmentVariables(@"%SYSTEMDRIVE%\Users\Default\NTUSER.dat")); | |||||
parentKey.Close(); | |||||
} | |||||
public static void UnloadDefaultUserHive() | |||||
{ | |||||
var parentKey = RegistryKey.OpenBaseKey(RegistryHive.Users, RegistryView.Default); | |||||
AcquirePrivileges(); | |||||
RegUnLoadKey(parentKey.Handle.DangerousGetHandle(), "DefaultUserHive"); | |||||
parentKey.Close(); | |||||
} | |||||
public static void AcquirePrivileges() | |||||
{ | |||||
ulong luid = 0; | |||||
bool throwaway; | |||||
LookupPrivilegeValue(IntPtr.Zero, "SeRestorePrivilege", ref luid); | |||||
RtlAdjustPrivilege((int)luid, true, true, out throwaway); | |||||
LookupPrivilegeValue(IntPtr.Zero, "SeBackupPrivilege", ref luid); | |||||
RtlAdjustPrivilege((int)luid, true, true, out throwaway); | |||||
} | |||||
public static void ReturnPrivileges() | |||||
{ | |||||
ulong luid = 0; | |||||
bool throwaway; | |||||
LookupPrivilegeValue(IntPtr.Zero, "SeRestorePrivilege", ref luid); | |||||
RtlAdjustPrivilege((int)luid, false, true, out throwaway); | |||||
LookupPrivilegeValue(IntPtr.Zero, "SeBackupPrivilege", ref luid); | |||||
RtlAdjustPrivilege((int)luid, false, true, out throwaway); | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,263 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Diagnostics; | |||||
using System.IO; | |||||
using System.Net; | |||||
using System.Runtime.InteropServices; | |||||
using System.Threading.Tasks; | |||||
using Ameliorated.ConsoleUtils; | |||||
namespace amecs | |||||
{ | |||||
public class amecs | |||||
{ | |||||
public static bool RunBasicAction(string status, string result, Action action, bool logoff = false, bool restart = false) | |||||
{ | |||||
ConsoleTUI.OpenFrame.WriteCentered(status); | |||||
try | |||||
{ | |||||
using (new ConsoleUtils.LoadingIndicator(true)) | |||||
{ | |||||
action.Invoke(); | |||||
} | |||||
} catch (Exception e) | |||||
{ | |||||
Console.WriteLine(); | |||||
ConsoleTUI.OpenFrame.Close("Error: " + e.Message.TrimEnd('\n').TrimEnd('\r'), ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt() { AnyKey = true, Text = "Press any key to return to the Menu: " }); | |||||
return false; | |||||
} | |||||
Console.WriteLine(); | |||||
if (logoff) | |||||
{ | |||||
if ((int?)ConsoleTUI.OpenFrame.Close(result, ConsoleColor.Green, Console.BackgroundColor, new ChoicePrompt() | |||||
{ | |||||
TextForeground = ConsoleColor.Yellow, | |||||
Text = "Logoff to apply changes? (Y/N): " | |||||
}) == 0) amecs.RestartWindows(true); | |||||
return true; | |||||
} | |||||
if (restart) | |||||
{ | |||||
if ((int?)ConsoleTUI.OpenFrame.Close(result, ConsoleColor.Green, Console.BackgroundColor, new ChoicePrompt() | |||||
{ | |||||
TextForeground = ConsoleColor.Yellow, | |||||
Text = "Restart to apply changes? (Y/N): " | |||||
}) == 0) amecs.RestartWindows(false); | |||||
return true; | |||||
} | |||||
ConsoleTUI.OpenFrame.Close(result, ConsoleColor.Green, Console.BackgroundColor, new ChoicePrompt() {AnyKey = true, Text = "Press any key to return to the Menu: "}); | |||||
return true; | |||||
} | |||||
public static bool RunBasicAction(string status, string result, Action<int> action, ChoicePrompt prompt = null, bool logoff = false, bool restart = false) | |||||
{ | |||||
int choice = -1; | |||||
if (prompt != null) | |||||
{ | |||||
var choiceRes = prompt.Start(); | |||||
if (!choiceRes.HasValue) | |||||
return true; | |||||
choice = choiceRes.Value; | |||||
} | |||||
ConsoleTUI.OpenFrame.WriteCentered(status); | |||||
try | |||||
{ | |||||
using (new ConsoleUtils.LoadingIndicator(true)) | |||||
{ | |||||
action.Invoke(choice); | |||||
} | |||||
} catch (Exception e) | |||||
{ | |||||
Console.WriteLine(); | |||||
ConsoleTUI.OpenFrame.Close("Error: " + e.Message.TrimEnd('\n').TrimEnd('\r'), ConsoleColor.Red, Console.BackgroundColor, new ChoicePrompt() { AnyKey = true, Text = "Press any key to return to the Menu: " }); | |||||
return false; | |||||
} | |||||
Console.WriteLine(); | |||||
if (logoff) | |||||
{ | |||||
if ((int?)ConsoleTUI.OpenFrame.Close(result, ConsoleColor.Green, Console.BackgroundColor, new ChoicePrompt() | |||||
{ | |||||
TextForeground = ConsoleColor.Yellow, | |||||
Text = "Logoff to apply changes? (Y/N): " | |||||
}) == 0) amecs.RestartWindows(true); | |||||
return true; | |||||
} | |||||
if (restart) | |||||
{ | |||||
if ((int?)ConsoleTUI.OpenFrame.Close(result, ConsoleColor.Green, Console.BackgroundColor, new ChoicePrompt() | |||||
{ | |||||
TextForeground = ConsoleColor.Yellow, | |||||
Text = "Restart to apply changes? (Y/N): " | |||||
}) == 0) amecs.RestartWindows(false); | |||||
return true; | |||||
} | |||||
ConsoleTUI.OpenFrame.Close(result, ConsoleColor.Green, Console.BackgroundColor, new ChoicePrompt() {AnyKey = true, Text = "Press any key to return to the Menu: "}); | |||||
return true; | |||||
} | |||||
[Flags] | |||||
enum ExitWindows : uint | |||||
{ | |||||
// ONE of the following five: | |||||
LogOff = 0x00, | |||||
ShutDown = 0x01, | |||||
Reboot = 0x02, | |||||
PowerOff = 0x08, | |||||
RestartApps = 0x40, | |||||
// plus AT MOST ONE of the following two: | |||||
Force = 0x04, | |||||
ForceIfHung = 0x10, | |||||
} | |||||
[Flags] | |||||
enum ShutdownReason : uint | |||||
{ | |||||
MajorApplication = 0x00040000, | |||||
MajorHardware = 0x00010000, | |||||
MajorLegacyApi = 0x00070000, | |||||
MajorOperatingSystem = 0x00020000, | |||||
MajorOther = 0x00000000, | |||||
MajorPower = 0x00060000, | |||||
MajorSoftware = 0x00030000, | |||||
MajorSystem = 0x00050000, | |||||
MinorBlueScreen = 0x0000000F, | |||||
MinorCordUnplugged = 0x0000000b, | |||||
MinorDisk = 0x00000007, | |||||
MinorEnvironment = 0x0000000c, | |||||
MinorHardwareDriver = 0x0000000d, | |||||
MinorHotfix = 0x00000011, | |||||
MinorHung = 0x00000005, | |||||
MinorInstallation = 0x00000002, | |||||
MinorMaintenance = 0x00000001, | |||||
MinorMMC = 0x00000019, | |||||
MinorNetworkConnectivity = 0x00000014, | |||||
MinorNetworkCard = 0x00000009, | |||||
MinorOther = 0x00000000, | |||||
MinorOtherDriver = 0x0000000e, | |||||
MinorPowerSupply = 0x0000000a, | |||||
MinorProcessor = 0x00000008, | |||||
MinorReconfig = 0x00000004, | |||||
MinorSecurity = 0x00000013, | |||||
MinorSecurityFix = 0x00000012, | |||||
MinorSecurityFixUninstall = 0x00000018, | |||||
MinorServicePack = 0x00000010, | |||||
MinorServicePackUninstall = 0x00000016, | |||||
MinorTermSrv = 0x00000020, | |||||
MinorUnstable = 0x00000006, | |||||
MinorUpgrade = 0x00000003, | |||||
MinorWMI = 0x00000015, | |||||
FlagUserDefined = 0x40000000, | |||||
FlagPlanned = 0x80000000 | |||||
} | |||||
[DllImport("user32.dll")] | |||||
static extern bool ExitWindowsEx(uint uFlags, uint dwReason); | |||||
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)] | |||||
private static extern bool InitiateSystemShutdownEx( | |||||
string lpMachineName, | |||||
string lpMessage, | |||||
uint dwTimeout, | |||||
bool bForceAppsClosed, | |||||
bool bRebootAfterShutdown, | |||||
ShutdownReason dwReason); | |||||
public static void RestartWindows(bool logoff, bool cmd = false) | |||||
{ | |||||
if (cmd) | |||||
{ | |||||
var psi = new ProcessStartInfo("shutdown","/r /t 0"); | |||||
psi.CreateNoWindow = true; | |||||
psi.UseShellExecute = false; | |||||
Process.Start(psi); | |||||
Environment.Exit(0); | |||||
} | |||||
if (!logoff) | |||||
{ | |||||
NSudo.GetShutdownPrivilege(); | |||||
InitiateSystemShutdownEx(null, null, 0, false, true, ShutdownReason.MinorInstallation); | |||||
} else | |||||
ExitWindowsEx((uint)ExitWindows.LogOff | (uint)ExitWindows.ForceIfHung, (uint)ShutdownReason.MinorInstallation); | |||||
Environment.Exit(0); | |||||
} | |||||
public static object ShowDefaultMenu(List<Menu.MenuItem> list) | |||||
{ | |||||
list.AddRange(new [] { | |||||
Menu.MenuItem.BlankStatic, | |||||
new Menu.MenuItem("Next Page", null) { IsNextButton = true }, | |||||
new Menu.MenuItem("Previous Page", null) { IsPreviousButton = true }, | |||||
new Menu.MenuItem("Return to Menu", new Func<bool>(() => true)) { IsStatic = true }, | |||||
new Menu.MenuItem("Exit", new Func<bool>(Globals.Exit)) { IsStatic = true }, | |||||
}); | |||||
var mainMenu = new Menu() | |||||
{ | |||||
Choices = list, | |||||
SelectionForeground = ConsoleColor.Green | |||||
}; | |||||
mainMenu.Write(); | |||||
return mainMenu.Load(); | |||||
} | |||||
[DllImport("wininet.dll", SetLastError = true)] | |||||
public static extern bool InternetCheckConnection(string lpszUrl, int dwFlags, int dwReserved); | |||||
[DllImport("wininet.dll", SetLastError=true)] | |||||
private extern static bool InternetGetConnectedState(out int lpdwFlags, int dwReserved); | |||||
public static bool IsInternetAvailable() | |||||
{ | |||||
try | |||||
{ | |||||
try | |||||
{ | |||||
if (!InternetCheckConnection("http://archlinux.org", 1, 0)) | |||||
{ | |||||
if (!InternetCheckConnection("http://google.com", 1, 0)) | |||||
return false; | |||||
} | |||||
return true; | |||||
} | |||||
catch | |||||
{ | |||||
var request = (HttpWebRequest)WebRequest.Create("http://google.com"); | |||||
request.KeepAlive = false; | |||||
request.Timeout = 5000; | |||||
using (var response = (HttpWebResponse)request.GetResponse()) | |||||
return true; | |||||
} | |||||
} | |||||
catch | |||||
{ | |||||
return false; | |||||
} | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,266 @@ | |||||
<?xml version="1.0" encoding="utf-8"?> | |||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | |||||
<Import Project="packages\Costura.Fody.5.7.0\build\Costura.Fody.props" Condition="Exists('packages\Costura.Fody.5.7.0\build\Costura.Fody.props')" /> | |||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> | |||||
<PropertyGroup> | |||||
<ApplicationManifest>app.manifest</ApplicationManifest> | |||||
<ApplicationIcon>amecs.ico</ApplicationIcon> | |||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> | |||||
</PropertyGroup> | |||||
<PropertyGroup> | |||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> | |||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> | |||||
<ProjectGuid>{BD020697-9E9B-4A46-8804-BC47F0FC2806}</ProjectGuid> | |||||
<OutputType>Exe</OutputType> | |||||
<AppDesignerFolder>Properties</AppDesignerFolder> | |||||
<RootNamespace>amecs</RootNamespace> | |||||
<AssemblyName>amecs</AssemblyName> | |||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion> | |||||
<FileAlignment>512</FileAlignment> | |||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> | |||||
<LangVersion>8</LangVersion> | |||||
</PropertyGroup> | |||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> | |||||
<PlatformTarget>x64</PlatformTarget> | |||||
<DebugSymbols>true</DebugSymbols> | |||||
<DebugType>embedded</DebugType> | |||||
<Optimize>false</Optimize> | |||||
<OutputPath>bin\Debug\</OutputPath> | |||||
<DefineConstants>DEBUG;TRACE</DefineConstants> | |||||
<ErrorReport>prompt</ErrorReport> | |||||
<WarningLevel>4</WarningLevel> | |||||
<Prefer32bit>false</Prefer32bit> | |||||
</PropertyGroup> | |||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> | |||||
<PlatformTarget>x64</PlatformTarget> | |||||
<DebugType>embedded</DebugType> | |||||
<Optimize>true</Optimize> | |||||
<OutputPath>bin\Release\</OutputPath> | |||||
<DefineConstants>RELEASE;TRACE</DefineConstants> | |||||
<ErrorReport>prompt</ErrorReport> | |||||
<WarningLevel>4</WarningLevel> | |||||
<Prefer32bit>false</Prefer32bit> | |||||
</PropertyGroup> | |||||
<ItemGroup> | |||||
<Reference Include="Costura, Version=5.7.0.0, Culture=neutral, processorArchitecture=MSIL"> | |||||
<HintPath>packages\Costura.Fody.5.7.0\lib\netstandard1.0\Costura.dll</HintPath> | |||||
</Reference> | |||||
<Reference Include="JetBrains.Annotations, Version=4242.42.42.42, Culture=neutral, PublicKeyToken=1010a0d8d6380325, processorArchitecture=MSIL"> | |||||
<HintPath>packages\JetBrains.Annotations.2023.3.0\lib\net20\JetBrains.Annotations.dll</HintPath> | |||||
</Reference> | |||||
<Reference Include="Microsoft.CSharp" /> | |||||
<Reference Include="Microsoft.Dism, Version=1.0.0.0, Culture=neutral, PublicKeyToken=5bba90053b345501, processorArchitecture=MSIL"> | |||||
<HintPath>packages\Microsoft.Dism.3.1.0\lib\net40\Microsoft.Dism.dll</HintPath> | |||||
</Reference> | |||||
<Reference Include="Microsoft.Win32.Primitives, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> | |||||
<HintPath>packages\Microsoft.Win32.Primitives.4.3.0\lib\net46\Microsoft.Win32.Primitives.dll</HintPath> | |||||
</Reference> | |||||
<Reference Include="mscorlib" /> | |||||
<Reference Include="System" /> | |||||
<Reference Include="System.AppContext, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> | |||||
<HintPath>packages\System.AppContext.4.3.0\lib\net463\System.AppContext.dll</HintPath> | |||||
</Reference> | |||||
<Reference Include="System.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL"> | |||||
<HintPath>packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll</HintPath> | |||||
</Reference> | |||||
<Reference Include="System.CodeDom, Version=8.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL"> | |||||
<HintPath>packages\System.CodeDom.8.0.0\lib\net462\System.CodeDom.dll</HintPath> | |||||
</Reference> | |||||
<Reference Include="System.ComponentModel.Composition" /> | |||||
<Reference Include="System.Configuration" /> | |||||
<Reference Include="System.Console, Version=4.0.1.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> | |||||
<HintPath>packages\System.Console.4.3.1\lib\net46\System.Console.dll</HintPath> | |||||
</Reference> | |||||
<Reference Include="System.Core" /> | |||||
<Reference Include="System.Data" /> | |||||
<Reference Include="System.Data.OracleClient" /> | |||||
<Reference Include="System.Diagnostics.DiagnosticSource, Version=8.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL"> | |||||
<HintPath>packages\System.Diagnostics.DiagnosticSource.8.0.0\lib\net462\System.Diagnostics.DiagnosticSource.dll</HintPath> | |||||
</Reference> | |||||
<Reference Include="System.Diagnostics.Tracing, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> | |||||
<HintPath>packages\System.Diagnostics.Tracing.4.3.0\lib\net462\System.Diagnostics.Tracing.dll</HintPath> | |||||
</Reference> | |||||
<Reference Include="System.DirectoryServices" /> | |||||
<Reference Include="System.DirectoryServices.AccountManagement" /> | |||||
<Reference Include="System.Drawing" /> | |||||
<Reference Include="System.Drawing.Primitives, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> | |||||
<HintPath>packages\System.Drawing.Primitives.4.3.0\lib\net45\System.Drawing.Primitives.dll</HintPath> | |||||
</Reference> | |||||
<Reference Include="System.Globalization.Calendars, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> | |||||
<HintPath>packages\System.Globalization.Calendars.4.3.0\lib\net46\System.Globalization.Calendars.dll</HintPath> | |||||
</Reference> | |||||
<Reference Include="System.IO, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> | |||||
<HintPath>packages\System.IO.4.3.0\lib\net462\System.IO.dll</HintPath> | |||||
</Reference> | |||||
<Reference Include="System.IO.Compression, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL"> | |||||
<HintPath>packages\System.IO.Compression.4.3.0\lib\net46\System.IO.Compression.dll</HintPath> | |||||
</Reference> | |||||
<Reference Include="System.IO.Compression.FileSystem" /> | |||||
<Reference Include="System.IO.Compression.ZipFile, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL"> | |||||
<HintPath>packages\System.IO.Compression.ZipFile.4.3.0\lib\net46\System.IO.Compression.ZipFile.dll</HintPath> | |||||
</Reference> | |||||
<Reference Include="System.IO.FileSystem, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> | |||||
<HintPath>packages\System.IO.FileSystem.4.3.0\lib\net46\System.IO.FileSystem.dll</HintPath> | |||||
</Reference> | |||||
<Reference Include="System.IO.FileSystem.AccessControl, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> | |||||
<HintPath>packages\System.IO.FileSystem.AccessControl.5.0.0\lib\net461\System.IO.FileSystem.AccessControl.dll</HintPath> | |||||
<Private>False</Private> | |||||
</Reference> | |||||
<Reference Include="System.IO.FileSystem.Primitives, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> | |||||
<HintPath>packages\System.IO.FileSystem.Primitives.4.3.0\lib\net46\System.IO.FileSystem.Primitives.dll</HintPath> | |||||
</Reference> | |||||
<Reference Include="System.Linq, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> | |||||
<HintPath>packages\System.Linq.4.3.0\lib\net463\System.Linq.dll</HintPath> | |||||
</Reference> | |||||
<Reference Include="System.Linq.Expressions, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> | |||||
<HintPath>packages\System.Linq.Expressions.4.3.0\lib\net463\System.Linq.Expressions.dll</HintPath> | |||||
</Reference> | |||||
<Reference Include="System.Management" /> | |||||
<Reference Include="System.Memory, Version=4.0.1.2, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL"> | |||||
<HintPath>packages\System.Memory.4.5.5\lib\net461\System.Memory.dll</HintPath> | |||||
</Reference> | |||||
<Reference Include="System.Net" /> | |||||
<Reference Include="System.Net.Http, Version=4.1.1.3, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> | |||||
<HintPath>packages\System.Net.Http.4.3.4\lib\net46\System.Net.Http.dll</HintPath> | |||||
</Reference> | |||||
<Reference Include="System.Net.Sockets, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> | |||||
<HintPath>packages\System.Net.Sockets.4.3.0\lib\net46\System.Net.Sockets.dll</HintPath> | |||||
</Reference> | |||||
<Reference Include="System.Numerics" /> | |||||
<Reference Include="System.Numerics.Vectors, Version=4.1.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> | |||||
<HintPath>packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll</HintPath> | |||||
</Reference> | |||||
<Reference Include="System.Reflection, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> | |||||
<HintPath>packages\System.Reflection.4.3.0\lib\net462\System.Reflection.dll</HintPath> | |||||
</Reference> | |||||
<Reference Include="System.Runtime, Version=4.1.1.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> | |||||
<HintPath>packages\System.Runtime.4.3.1\lib\net462\System.Runtime.dll</HintPath> | |||||
</Reference> | |||||
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> | |||||
<HintPath>packages\System.Runtime.CompilerServices.Unsafe.6.0.0\lib\net461\System.Runtime.CompilerServices.Unsafe.dll</HintPath> | |||||
</Reference> | |||||
<Reference Include="System.Runtime.Extensions, Version=4.1.1.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> | |||||
<HintPath>packages\System.Runtime.Extensions.4.3.1\lib\net462\System.Runtime.Extensions.dll</HintPath> | |||||
</Reference> | |||||
<Reference Include="System.Runtime.InteropServices, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> | |||||
<HintPath>packages\System.Runtime.InteropServices.4.3.0\lib\net463\System.Runtime.InteropServices.dll</HintPath> | |||||
</Reference> | |||||
<Reference Include="System.Runtime.InteropServices.RuntimeInformation, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> | |||||
<HintPath>packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll</HintPath> | |||||
</Reference> | |||||
<Reference Include="System.Security" /> | |||||
<Reference Include="System.Security.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> | |||||
<HintPath>packages\System.Security.AccessControl.6.0.0\lib\net461\System.Security.AccessControl.dll</HintPath> | |||||
<Private>False</Private> | |||||
</Reference> | |||||
<Reference Include="System.Security.Cryptography.Algorithms, Version=4.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> | |||||
<HintPath>packages\System.Security.Cryptography.Algorithms.4.3.1\lib\net463\System.Security.Cryptography.Algorithms.dll</HintPath> | |||||
</Reference> | |||||
<Reference Include="System.Security.Cryptography.Encoding, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> | |||||
<HintPath>packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll</HintPath> | |||||
</Reference> | |||||
<Reference Include="System.Security.Cryptography.Primitives, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> | |||||
<HintPath>packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll</HintPath> | |||||
</Reference> | |||||
<Reference Include="System.Security.Cryptography.X509Certificates, Version=4.1.1.2, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> | |||||
<HintPath>packages\System.Security.Cryptography.X509Certificates.4.3.2\lib\net461\System.Security.Cryptography.X509Certificates.dll</HintPath> | |||||
</Reference> | |||||
<Reference Include="System.Security.Permissions, Version=8.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL"> | |||||
<HintPath>packages\System.Security.Permissions.8.0.0\lib\net462\System.Security.Permissions.dll</HintPath> | |||||
</Reference> | |||||
<Reference Include="System.Security.Principal.Windows, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> | |||||
<HintPath>packages\System.Security.Principal.Windows.5.0.0\lib\net461\System.Security.Principal.Windows.dll</HintPath> | |||||
<Private>False</Private> | |||||
</Reference> | |||||
<Reference Include="System.ServiceProcess" /> | |||||
<Reference Include="System.Text.RegularExpressions, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> | |||||
<HintPath>packages\System.Text.RegularExpressions.4.3.1\lib\net463\System.Text.RegularExpressions.dll</HintPath> | |||||
</Reference> | |||||
<Reference Include="System.Transactions" /> | |||||
<Reference Include="System.Windows.Forms" /> | |||||
<Reference Include="System.Xml" /> | |||||
<Reference Include="System.Xml.Linq" /> | |||||
<Reference Include="System.Xml.ReaderWriter, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> | |||||
<HintPath>packages\System.Xml.ReaderWriter.4.3.1\lib\net46\System.Xml.ReaderWriter.dll</HintPath> | |||||
</Reference> | |||||
<Reference Include="WindowsBase" /> | |||||
</ItemGroup> | |||||
<ItemGroup> | |||||
<Compile Include="Actions\.NET.cs" /> | |||||
<Compile Include="Actions\AutoLogon.cs" /> | |||||
<Compile Include="Actions\Deameliorate.cs" /> | |||||
<Compile Include="Actions\Elevation.cs" /> | |||||
<Compile Include="Actions\Languages.cs" /> | |||||
<Compile Include="Actions\Lockscreen.cs" /> | |||||
<Compile Include="Actions\Profile.cs" /> | |||||
<Compile Include="Actions\UsernameRequirement.cs" /> | |||||
<Compile Include="Actions\UserPass.cs" /> | |||||
<Compile Include="Actions\Users.cs" /> | |||||
<Compile Include="amecs.cs" /> | |||||
<Compile Include="Ameliorated.ConsoleUtils\ConsoleTUI\ConsoleTUI.cs" /> | |||||
<Compile Include="Ameliorated.ConsoleUtils\ConsoleTUI\Frame.cs" /> | |||||
<Compile Include="Ameliorated.ConsoleUtils\ConsoleTUI\FrameWriteMethods.cs" /> | |||||
<Compile Include="Ameliorated.ConsoleUtils\ConsoleTUI\Menu.cs" /> | |||||
<Compile Include="Ameliorated.ConsoleUtils\ConsoleTUI\MouseInterface.cs" /> | |||||
<Compile Include="Ameliorated.ConsoleUtils\ConsoleTUI\Prompt.cs" /> | |||||
<Compile Include="Ameliorated.ConsoleUtils\ConsoleUtils.cs" /> | |||||
<Compile Include="Ameliorated.ConsoleUtils\Extensions.cs" /> | |||||
<Compile Include="Ameliorated.ConsoleUtils\ParentProcess.cs" /> | |||||
<Compile Include="Ameliorated.ConsoleUtils\Payload.cs" /> | |||||
<Compile Include="Extra\Extra.cs" /> | |||||
<Compile Include="Extra\NVCP.cs" /> | |||||
<Compile Include="Extra\WSH.cs" /> | |||||
<Compile Include="Globals.cs" /> | |||||
<Compile Include="Misc\FolderPicker.cs" /> | |||||
<Compile Include="Misc\SelectWindowsImage.cs" /> | |||||
<Compile Include="NSudo.cs" /> | |||||
<Compile Include="Program.cs" /> | |||||
<Compile Include="Properties\AssemblyInfo.cs" /> | |||||
<Compile Include="Registry.cs" /> | |||||
</ItemGroup> | |||||
<ItemGroup> | |||||
<None Include="amecs.ico" /> | |||||
<None Include="amecs.png" /> | |||||
<None Include="App.config" /> | |||||
<None Include="packages.config" /> | |||||
</ItemGroup> | |||||
<ItemGroup> | |||||
<Folder Include="Menus" /> | |||||
<Folder Include="NSudo" /> | |||||
</ItemGroup> | |||||
<ItemGroup> | |||||
<Content Include="app.manifest" /> | |||||
</ItemGroup> | |||||
<ItemGroup> | |||||
<COMReference Include="IWshRuntimeLibrary"> | |||||
<Guid>{F935DC20-1CF0-11D0-ADB9-00C04FD58A0B}</Guid> | |||||
<VersionMajor>1</VersionMajor> | |||||
<VersionMinor>0</VersionMinor> | |||||
<Lcid>0</Lcid> | |||||
<WrapperTool>tlbimp</WrapperTool> | |||||
<Isolated>False</Isolated> | |||||
<EmbedInteropTypes>True</EmbedInteropTypes> | |||||
</COMReference> | |||||
</ItemGroup> | |||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> | |||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> | |||||
<PropertyGroup> | |||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105.The missing file is {0}.</ErrorText> | |||||
</PropertyGroup> | |||||
<Error Condition="!Exists('packages\Costura.Fody.5.7.0\build\Costura.Fody.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Costura.Fody.5.7.0\build\Costura.Fody.props'))" /> | |||||
<Error Condition="!Exists('packages\Costura.Fody.5.7.0\build\Costura.Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Costura.Fody.5.7.0\build\Costura.Fody.targets'))" /> | |||||
<Error Condition="!Exists('packages\Fody.6.8.0\build\Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Fody.6.8.0\build\Fody.targets'))" /> | |||||
<Error Condition="!Exists('packages\NETStandard.Library.2.0.3\build\netstandard2.0\NETStandard.Library.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\NETStandard.Library.2.0.3\build\netstandard2.0\NETStandard.Library.targets'))" /> | |||||
</Target> | |||||
<Import Project="packages\Costura.Fody.5.7.0\build\Costura.Fody.targets" Condition="Exists('packages\Costura.Fody.5.7.0\build\Costura.Fody.targets')" /> | |||||
<Import Project="packages\Fody.6.8.0\build\Fody.targets" Condition="Exists('packages\Fody.6.8.0\build\Fody.targets')" /> | |||||
<Import Project="packages\NETStandard.Library.2.0.3\build\netstandard2.0\NETStandard.Library.targets" Condition="Exists('packages\NETStandard.Library.2.0.3\build\netstandard2.0\NETStandard.Library.targets')" /> | |||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. | |||||
Other similar extension points exist, see Microsoft.Common.targets. | |||||
<Target Name="BeforeBuild"> | |||||
</Target> | |||||
<Target Name="AfterBuild"> | |||||
</Target> | |||||
--> | |||||
</Project> |
@ -0,0 +1,16 @@ | |||||
| |||||
Microsoft Visual Studio Solution File, Format Version 12.00 | |||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "amecs", "amecs.csproj", "{BD020697-9E9B-4A46-8804-BC47F0FC2806}" | |||||
EndProject | |||||
Global | |||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution | |||||
Debug|Any CPU = Debug|Any CPU | |||||
Release|Any CPU = Release|Any CPU | |||||
EndGlobalSection | |||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution | |||||
{BD020697-9E9B-4A46-8804-BC47F0FC2806}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||||
{BD020697-9E9B-4A46-8804-BC47F0FC2806}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||||
{BD020697-9E9B-4A46-8804-BC47F0FC2806}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||||
{BD020697-9E9B-4A46-8804-BC47F0FC2806}.Release|Any CPU.Build.0 = Release|Any CPU | |||||
EndGlobalSection | |||||
EndGlobal |
@ -0,0 +1,17 @@ | |||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> | |||||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> | |||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3"> | |||||
<security> | |||||
<requestedPrivileges> | |||||
<requestedExecutionLevel level="requireAdministrator" uiAccess="false"/> | |||||
</requestedPrivileges> | |||||
</security> | |||||
</trustInfo> | |||||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> | |||||
<application> | |||||
<!-- Support Windows 10 and above - needed for certain functions to return | |||||
correct Windows version. https://learn.microsoft.com/en-us/windows/win32/sbscs/application-manifests#supportedOS --> | |||||
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" /> | |||||
</application> | |||||
</compatibility> | |||||
</assembly> |
@ -0,0 +1,66 @@ | |||||
<?xml version="1.0" encoding="utf-8"?> | |||||
<packages> | |||||
<package id="Costura.Fody" version="5.7.0" targetFramework="net472" developmentDependency="true" /> | |||||
<package id="Fody" version="6.8.0" targetFramework="net472" developmentDependency="true" /> | |||||
<package id="JetBrains.Annotations" version="2023.3.0" targetFramework="net472" /> | |||||
<package id="Microsoft.Dism" version="3.1.0" targetFramework="net472" /> | |||||
<package id="Microsoft.NETCore.Platforms" version="7.0.4" targetFramework="net472" /> | |||||
<package id="Microsoft.Win32.Primitives" version="4.3.0" targetFramework="net472" /> | |||||
<package id="NETStandard.Library" version="2.0.3" targetFramework="net472" /> | |||||
<package id="System.AppContext" version="4.3.0" targetFramework="net472" /> | |||||
<package id="System.CodeDom" version="8.0.0" targetFramework="net472" /> | |||||
<package id="System.Console" version="4.3.1" targetFramework="net472" /> | |||||
<package id="System.Diagnostics.DiagnosticSource" version="8.0.0" targetFramework="net472" /> | |||||
<package id="System.DirectoryServices" version="8.0.0" targetFramework="net472" /> | |||||
<package id="System.DirectoryServices.AccountManagement" version="8.0.0" targetFramework="net472" /> | |||||
<package id="System.Management" version="8.0.0" targetFramework="net472" /> | |||||
<package id="System.Net.Http" version="4.3.4" targetFramework="net472" /> | |||||
<package id="System.Runtime.Extensions" version="4.3.1" targetFramework="net472" /> | |||||
<package id="System.Security.Cryptography.Algorithms" version="4.3.1" targetFramework="net472" /> | |||||
<package id="System.Security.Cryptography.X509Certificates" version="4.3.2" targetFramework="net472" /> | |||||
<package id="System.Security.Permissions" version="8.0.0" targetFramework="net472" /> | |||||
<package id="System.Text.RegularExpressions" version="4.3.1" targetFramework="net472" /> | |||||
<package id="System.Xml.ReaderWriter" version="4.3.1" targetFramework="net472" /> | |||||
<package id="System.Memory" version="4.5.5" targetFramework="net472" /> | |||||
<package id="System.Net.Primitives" version="4.3.1" targetFramework="net472" /> | |||||
<package id="System.Runtime" version="4.3.1" targetFramework="net472" /> | |||||
<package id="System.Buffers" version="4.5.1" targetFramework="net472" /> | |||||
<package id="System.Collections" version="4.3.0" targetFramework="net472" /> | |||||
<package id="System.Collections.Concurrent" version="4.3.0" targetFramework="net472" /> | |||||
<package id="System.Diagnostics.Debug" version="4.3.0" targetFramework="net472" /> | |||||
<package id="System.Diagnostics.Tools" version="4.3.0" targetFramework="net472" /> | |||||
<package id="System.Diagnostics.Tracing" version="4.3.0" targetFramework="net472" /> | |||||
<package id="System.Drawing.Primitives" version="4.3.0" targetFramework="net472" /> | |||||
<package id="System.Globalization" version="4.3.0" targetFramework="net472" /> | |||||
<package id="System.Globalization.Calendars" version="4.3.0" targetFramework="net472" /> | |||||
<package id="System.IO" version="4.3.0" targetFramework="net472" /> | |||||
<package id="System.IO.Compression" version="4.3.0" targetFramework="net472" /> | |||||
<package id="System.IO.Compression.ZipFile" version="4.3.0" targetFramework="net472" /> | |||||
<package id="System.IO.FileSystem" version="4.3.0" targetFramework="net472" /> | |||||
<package id="System.IO.FileSystem.AccessControl" version="5.0.0" targetFramework="net472" /> | |||||
<package id="System.IO.FileSystem.Primitives" version="4.3.0" targetFramework="net472" /> | |||||
<package id="System.Linq" version="4.3.0" targetFramework="net472" /> | |||||
<package id="System.Linq.Expressions" version="4.3.0" targetFramework="net472" /> | |||||
<package id="System.Net.Sockets" version="4.3.0" targetFramework="net472" /> | |||||
<package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net472" /> | |||||
<package id="System.ObjectModel" version="4.3.0" targetFramework="net472" /> | |||||
<package id="System.Reflection" version="4.3.0" targetFramework="net472" /> | |||||
<package id="System.Reflection.Extensions" version="4.3.0" targetFramework="net472" /> | |||||
<package id="System.Reflection.Primitives" version="4.3.0" targetFramework="net472" /> | |||||
<package id="System.Resources.ResourceManager" version="4.3.0" targetFramework="net472" /> | |||||
<package id="System.Runtime.CompilerServices.Unsafe" version="6.0.0" targetFramework="net472" /> | |||||
<package id="System.Runtime.Handles" version="4.3.0" targetFramework="net472" /> | |||||
<package id="System.Runtime.InteropServices" version="4.3.0" targetFramework="net472" /> | |||||
<package id="System.Runtime.InteropServices.RuntimeInformation" version="4.3.0" targetFramework="net472" /> | |||||
<package id="System.Runtime.Numerics" version="4.3.0" targetFramework="net472" /> | |||||
<package id="System.Security.AccessControl" version="6.0.0" targetFramework="net472" /> | |||||
<package id="System.Security.Cryptography.Encoding" version="4.3.0" targetFramework="net472" /> | |||||
<package id="System.Security.Cryptography.Primitives" version="4.3.0" targetFramework="net472" /> | |||||
<package id="System.Security.Principal.Windows" version="5.0.0" targetFramework="net472" /> | |||||
<package id="System.Text.Encoding" version="4.3.0" targetFramework="net472" /> | |||||
<package id="System.Text.Encoding.Extensions" version="4.3.0" targetFramework="net472" /> | |||||
<package id="System.Threading" version="4.3.0" targetFramework="net472" /> | |||||
<package id="System.Threading.Tasks" version="4.3.0" targetFramework="net472" /> | |||||
<package id="System.Threading.Timer" version="4.3.0" targetFramework="net472" /> | |||||
<package id="System.Xml.XDocument" version="4.3.0" targetFramework="net472" /> | |||||
</packages> |