Merge pull request #329 from godylockz/master

Fix Internet Explorer Enumeration
This commit is contained in:
Carlos Polop
2022-12-31 18:37:08 +01:00
committed by GitHub
137 changed files with 16755 additions and 16800 deletions

View File

@@ -1,5 +1,4 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following

View File

@@ -27,8 +27,8 @@ namespace winPEAS.Checks
{
Beaprint.MainPrint("Current Active Window Application");
string title = ApplicationInfoHelper.GetActiveWindowTitle();
List<string> permsFile = PermissionsHelper.GetPermissionsFile(title, winPEAS.Checks.Checks.CurrentUserSiDs);
List<string> permsFolder = PermissionsHelper.GetPermissionsFolder(title, winPEAS.Checks.Checks.CurrentUserSiDs);
List<string> permsFile = PermissionsHelper.GetPermissionsFile(title, Checks.CurrentUserSiDs);
List<string> permsFolder = PermissionsHelper.GetPermissionsFolder(title, Checks.CurrentUserSiDs);
if (permsFile.Count > 0)
{
Beaprint.BadPrint(" " + title);
@@ -188,8 +188,8 @@ namespace winPEAS.Checks
foreach (Dictionary<string, string> sapp in scheduled_apps)
{
List<string> fileRights = PermissionsHelper.GetPermissionsFile(sapp["Action"], winPEAS.Checks.Checks.CurrentUserSiDs);
List<string> dirRights = PermissionsHelper.GetPermissionsFolder(sapp["Action"], winPEAS.Checks.Checks.CurrentUserSiDs);
List<string> fileRights = PermissionsHelper.GetPermissionsFile(sapp["Action"], Checks.CurrentUserSiDs);
List<string> dirRights = PermissionsHelper.GetPermissionsFolder(sapp["Action"], Checks.CurrentUserSiDs);
string formString = " ({0}) {1}: {2}";
if (fileRights.Count > 0)
@@ -238,8 +238,8 @@ namespace winPEAS.Checks
foreach (var driver in DeviceDrivers.GetDeviceDriversNoMicrosoft())
{
string pathDriver = driver.Key;
List<string> fileRights = PermissionsHelper.GetPermissionsFile(pathDriver, winPEAS.Checks.Checks.CurrentUserSiDs);
List<string> dirRights = PermissionsHelper.GetPermissionsFolder(pathDriver, winPEAS.Checks.Checks.CurrentUserSiDs);
List<string> fileRights = PermissionsHelper.GetPermissionsFile(pathDriver, Checks.CurrentUserSiDs);
List<string> dirRights = PermissionsHelper.GetPermissionsFolder(pathDriver, Checks.CurrentUserSiDs);
Dictionary<string, string> colorsD = new Dictionary<string, string>()
{

View File

@@ -363,8 +363,8 @@ namespace winPEAS.Checks
try
{
Beaprint.GrayPrint(" - Creating disabled users list...");
Checks.PaintDisabledUsers = string.Join("|", User.GetMachineUsers(false, true, false, false, false));
PaintDisabledUsersNoAdministrator = Checks.PaintDisabledUsers.Replace("|Administrator", "").Replace("Administrator|", "").Replace("Administrator", "");
PaintDisabledUsers = string.Join("|", User.GetMachineUsers(false, true, false, false, false));
PaintDisabledUsersNoAdministrator = PaintDisabledUsers.Replace("|Administrator", "").Replace("Administrator|", "").Replace("Administrator", "");
}
catch (Exception ex)
{
@@ -411,7 +411,7 @@ namespace winPEAS.Checks
try
{
if (RegistryHelper.GetRegValue("HKCU", "CONSOLE", "VirtualTerminalLevel") == "" && RegistryHelper.GetRegValue("HKCU", "CONSOLE", "VirtualTerminalLevel") == "")
System.Console.WriteLine(@"ANSI color bit for Windows is not set. If you are execcuting this from a Windows terminal inside the host you should run 'REG ADD HKCU\Console /v VirtualTerminalLevel /t REG_DWORD /d 1' and then start a new CMD");
Console.WriteLine(@"ANSI color bit for Windows is not set. If you are executing this from a Windows terminal inside the host you should run 'REG ADD HKCU\Console /v VirtualTerminalLevel /t REG_DWORD /d 1' and then start a new CMD");
}
catch (Exception ex)
{
@@ -425,7 +425,7 @@ namespace winPEAS.Checks
{
if (RegistryHelper.GetRegValue("HKLM", @"SYSTEM\CurrentControlSet\Control\FileSystem", "LongPathsEnabled") != "1")
{
System.Console.WriteLine(@"Long paths are disabled, so the maximum length of a path supported is 260chars (this may cause false negatives when looking for files). If you are admin, you can enable it with 'REG ADD HKLM\SYSTEM\CurrentControlSet\Control\FileSystem /v VirtualTerminalLevel /t REG_DWORD /d 1' and then start a new CMD");
Console.WriteLine(@"Long paths are disabled, so the maximum length of a path supported is 260 chars (this may cause false negatives when looking for files). If you are admin, you can enable it with 'REG ADD HKLM\SYSTEM\CurrentControlSet\Control\FileSystem /v VirtualTerminalLevel /t REG_DWORD /d 1' and then start a new CMD");
IsLongPath = false;
}
else

View File

@@ -27,7 +27,7 @@ namespace winPEAS.Checks
}.ForEach(action => CheckRunner.Run(action, isDebug));
}
private static List<CustomFileInfo> InitializeFileSearch(bool useProgramFiles=true)
private static List<CustomFileInfo> InitializeFileSearch(bool useProgramFiles = true)
{
var files = new List<CustomFileInfo>();
var systemDrive = $"{SearchHelper.SystemDrive}\\";
@@ -118,7 +118,8 @@ namespace winPEAS.Checks
if (isFileFound)
{
if (!somethingFound) {
if (!somethingFound)
{
Beaprint.MainPrint($"Found {searchName} Files");
somethingFound = true;
}
@@ -352,7 +353,7 @@ namespace winPEAS.Checks
try
{
string text = System.IO.File.ReadAllText(f.FullPath);
string text = File.ReadAllText(f.FullPath);
results = SearchContent(text, regex.regex, (bool)regex.caseinsensitive);
if (results.Count > 0)
@@ -451,7 +452,7 @@ namespace winPEAS.Checks
// If contains undesireable string, stop processing
if (fileSettings.remove_path != null && fileSettings.remove_path.Length > 0)
{
foreach(var rem_path in fileSettings.remove_path.Split('|'))
foreach (var rem_path in fileSettings.remove_path.Split('|'))
{
if (fileInfo.FullPath.ToLower().Contains(rem_path.ToLower()))
return false;
@@ -460,19 +461,23 @@ namespace winPEAS.Checks
if (fileSettings.type == "f")
{
var colors = new Dictionary<string, string>();
colors.Add(fileInfo.Filename, Beaprint.ansi_color_bad);
var colors = new Dictionary<string, string>
{
{ fileInfo.Filename, Beaprint.ansi_color_bad }
};
Beaprint.AnsiPrint($"File: {fileInfo.FullPath}", colors);
if (!(bool)fileSettings.just_list_file)
if (!(bool)fileSettings.just_list_file)
{
GrepResult(fileInfo, fileSettings);
}
}
else if (fileSettings.type == "d")
{
var colors = new Dictionary<string, string>();
colors.Add(fileInfo.Filename, Beaprint.ansi_color_bad);
var colors = new Dictionary<string, string>
{
{ fileInfo.Filename, Beaprint.ansi_color_bad }
};
Beaprint.AnsiPrint($"Folder: {fileInfo.FullPath}", colors);
// just list the directory
@@ -487,7 +492,7 @@ namespace winPEAS.Checks
}
else
{
// should not happen
// should not happen
}
}

View File

@@ -21,7 +21,7 @@ namespace winPEAS.Checks
internal class FilesInfo : ISystemCheck
{
static readonly string _patternsFileCredsColor = @"RDCMan.settings|.rdg|_history|httpd.conf|.htpasswd|.gitconfig|.git-credentials|Dockerfile|docker-compose.ymlaccess_tokens.db|accessTokens.json|azureProfile.json|appcmd.exe|scclient.exe|unattend.txt|access.log|error.log|credential|password|.gpg|.pgp|config.php|elasticsearch|kibana.|.p12|\.der|.csr|.crt|.cer|.pem|known_hosts|id_rsa|id_dsa|.ovpn|tomcat-users.xml|web.config|.kdbx|.key|KeePass.config|ntds.dir|Ntds.dit|sam|system|SAM|SYSTEM|security|software|SECURITY|SOFTWARE|FreeSSHDservice.ini|sysprep.inf|sysprep.xml|unattend.xml|unattended.xml|vnc|groups.xml|services.xml|scheduledtasks.xml|printers.xml|drives.xml|datasources.xml|php.ini|https.conf|https-xampp.conf|my.ini|my.cnf|access.log|error.log|server.xml|setupinfo|pagefile.sys|NetSetup.log|iis6.log|AppEvent.Evt|SecEvent.Evt|default.sav|security.sav|software.sav|system.sav|ntuser.dat|index.dat|bash.exe|wsl.exe";
// static readonly string _patternsFileCreds = @"RDCMan.settings;*.rdg;*_history*;httpd.conf;.htpasswd;.gitconfig;.git-credentials;Dockerfile;docker-compose.yml;access_tokens.db;accessTokens.json;azureProfile.json;appcmd.exe;scclient.exe;*.gpg$;*.pgp$;*config*.php;elasticsearch.y*ml;kibana.y*ml;*.p12$;*.cer$;known_hosts;*id_rsa*;*id_dsa*;*.ovpn;tomcat-users.xml;web.config;*.kdbx;KeePass.config;Ntds.dit;SAM;SYSTEM;security;software;FreeSSHDservice.ini;sysprep.inf;sysprep.xml;*vnc*.ini;*vnc*.c*nf*;*vnc*.txt;*vnc*.xml;php.ini;https.conf;https-xampp.conf;my.ini;my.cnf;access.log;error.log;server.xml;ConsoleHost_history.txt;pagefile.sys;NetSetup.log;iis6.log;AppEvent.Evt;SecEvent.Evt;default.sav;security.sav;software.sav;system.sav;ntuser.dat;index.dat;bash.exe;wsl.exe;unattend.txt;*.der$;*.csr$;unattend.xml;unattended.xml;groups.xml;services.xml;scheduledtasks.xml;printers.xml;drives.xml;datasources.xml;setupinfo;setupinfo.bak";
// static readonly string _patternsFileCreds = @"RDCMan.settings;*.rdg;*_history*;httpd.conf;.htpasswd;.gitconfig;.git-credentials;Dockerfile;docker-compose.yml;access_tokens.db;accessTokens.json;azureProfile.json;appcmd.exe;scclient.exe;*.gpg$;*.pgp$;*config*.php;elasticsearch.y*ml;kibana.y*ml;*.p12$;*.cer$;known_hosts;*id_rsa*;*id_dsa*;*.ovpn;tomcat-users.xml;web.config;*.kdbx;KeePass.config;Ntds.dit;SAM;SYSTEM;security;software;FreeSSHDservice.ini;sysprep.inf;sysprep.xml;*vnc*.ini;*vnc*.c*nf*;*vnc*.txt;*vnc*.xml;php.ini;https.conf;https-xampp.conf;my.ini;my.cnf;access.log;error.log;server.xml;ConsoleHost_history.txt;pagefile.sys;NetSetup.log;iis6.log;AppEvent.Evt;SecEvent.Evt;default.sav;security.sav;software.sav;system.sav;ntuser.dat;index.dat;bash.exe;wsl.exe;unattend.txt;*.der$;*.csr$;unattend.xml;unattended.xml;groups.xml;services.xml;scheduledtasks.xml;printers.xml;drives.xml;datasources.xml;setupinfo;setupinfo.bak";
private static readonly IList<string> patternsFileCreds = new List<string>()
{
@@ -159,7 +159,7 @@ namespace winPEAS.Checks
{
string formString = " {0} ({1})\n Accessed:{2} -- Size:{3}";
Beaprint.BadPrint(string.Format(formString, cc["file"], cc["Description"], cc["Accessed"], cc["Size"]));
System.Console.WriteLine("");
Console.WriteLine("");
}
}
else
@@ -182,7 +182,7 @@ namespace winPEAS.Checks
{
List<string> pwds = Unattended.ExtractUnattendedPwd(path);
Beaprint.BadPrint(" " + path);
System.Console.WriteLine(string.Join("\n", pwds));
Console.WriteLine(string.Join("\n", pwds));
}
}
catch (Exception ex)
@@ -233,11 +233,11 @@ namespace winPEAS.Checks
foreach (var site in sitelistFilesInfo.Sites)
{
Beaprint.NoColorPrint($" Share Name : {site.ShareName}");
PrintColored( $" User Name : {site.UserName}", !string.IsNullOrWhiteSpace(site.UserName));
PrintColored( $" Server : {site.Server}", !string.IsNullOrWhiteSpace(site.Server));
PrintColored( $" Encrypted Password : {site.EncPassword}", !string.IsNullOrWhiteSpace(site.EncPassword));
PrintColored( $" Decrypted Password : {site.DecPassword}", !string.IsNullOrWhiteSpace(site.DecPassword));
Beaprint.NoColorPrint( $" Domain Name : {site.DomainName}\n" +
PrintColored($" User Name : {site.UserName}", !string.IsNullOrWhiteSpace(site.UserName));
PrintColored($" Server : {site.Server}", !string.IsNullOrWhiteSpace(site.Server));
PrintColored($" Encrypted Password : {site.EncPassword}", !string.IsNullOrWhiteSpace(site.EncPassword));
PrintColored($" Decrypted Password : {site.DecPassword}", !string.IsNullOrWhiteSpace(site.DecPassword));
Beaprint.NoColorPrint($" Domain Name : {site.DomainName}\n" +
$" Name : {site.Name}\n" +
$" Type : {site.Type}\n" +
$" Relative Path : {site.RelativePath}\n");
@@ -480,7 +480,7 @@ namespace winPEAS.Checks
if (Regex.Match(rec_file["Name"], pattern.Replace("*", ".*"), RegexOptions.IgnoreCase).Success)
{
Beaprint.DictPrint(rec_file, colorF, true);
System.Console.WriteLine();
Console.WriteLine();
}
}
}
@@ -828,11 +828,11 @@ namespace winPEAS.Checks
Beaprint.NoColorPrint($" Issuer : {certificateInfo.Issuer}\n" +
$" Subject : {certificateInfo.Subject}\n" +
$" ValidDate : {certificateInfo.ValidDate}\n" +
$" ValidDate : {certificateInfo.ValidDate}\n" +
$" ExpiryDate : {certificateInfo.ExpiryDate}\n" +
$" HasPrivateKey : {certificateInfo.HasPrivateKey}\n" +
$" StoreLocation : {certificateInfo.StoreLocation}\n" +
$" KeyExportable : {certificateInfo.KeyExportable}\n" +
$" HasPrivateKey : {certificateInfo.HasPrivateKey}\n" +
$" StoreLocation : {certificateInfo.StoreLocation}\n" +
$" KeyExportable : {certificateInfo.KeyExportable}\n" +
$" Thumbprint : {certificateInfo.Thumbprint}\n");
if (!string.IsNullOrEmpty(certificateInfo.Template))

View File

@@ -81,7 +81,7 @@ namespace winPEAS.Checks
{
if (line.Length > 0 && line[0] != '#')
{
System.Console.WriteLine(" " + line.Replace("\t", " "));
Console.WriteLine(" " + line.Replace("\t", " "));
}
}
}
@@ -304,8 +304,8 @@ namespace winPEAS.Checks
Beaprint.GrayPrint(" DENY rules:");
foreach (Dictionary<string, string> rule in Firewall.GetFirewallRules())
{
string filePerms = string.Join(", ", PermissionsHelper.GetPermissionsFile(rule["AppName"], winPEAS.Checks.Checks.CurrentUserSiDs));
string folderPerms = string.Join(", ", PermissionsHelper.GetPermissionsFolder(rule["AppName"], winPEAS.Checks.Checks.CurrentUserSiDs));
string filePerms = string.Join(", ", PermissionsHelper.GetPermissionsFile(rule["AppName"], Checks.CurrentUserSiDs));
string folderPerms = string.Join(", ", PermissionsHelper.GetPermissionsFolder(rule["AppName"], Checks.CurrentUserSiDs));
string formString = " ({0}){1}[{2}]: {3} {4} {5} from {6} --> {7}";
if (filePerms.Length > 0)
formString += "\n File Permissions: {8}";

View File

@@ -20,7 +20,7 @@ namespace winPEAS.Checks
{
CheckRunner.Run(() =>
{
modifiableServices = ServicesInfoHelper.GetModifiableServices(winPEAS.Checks.Checks.CurrentUserSiDs);
modifiableServices = ServicesInfoHelper.GetModifiableServices(Checks.CurrentUserSiDs);
}, isDebug);
}
catch (Exception ex)
@@ -53,12 +53,12 @@ namespace winPEAS.Checks
foreach (Dictionary<string, string> serviceInfo in services_info)
{
List<string> fileRights = PermissionsHelper.GetPermissionsFile(serviceInfo["FilteredPath"], winPEAS.Checks.Checks.CurrentUserSiDs);
List<string> fileRights = PermissionsHelper.GetPermissionsFile(serviceInfo["FilteredPath"], Checks.CurrentUserSiDs);
List<string> dirRights = new List<string>();
if (serviceInfo["FilteredPath"] != null && serviceInfo["FilteredPath"] != "")
{
dirRights = PermissionsHelper.GetPermissionsFolder(Path.GetDirectoryName(serviceInfo["FilteredPath"]), winPEAS.Checks.Checks.CurrentUserSiDs);
dirRights = PermissionsHelper.GetPermissionsFolder(Path.GetDirectoryName(serviceInfo["FilteredPath"]), Checks.CurrentUserSiDs);
}
bool noQuotesAndSpace = MyUtils.CheckQuoteAndSpace(serviceInfo["PathName"]);
@@ -159,7 +159,7 @@ namespace winPEAS.Checks
{
Beaprint.MainPrint("Looking if you can modify any service registry");
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#services-registry-permissions", "Check if you can modify the registry of a service");
List<Dictionary<string, string>> regPerms = ServicesInfoHelper.GetWriteServiceRegs(winPEAS.Checks.Checks.CurrentUserSiDs);
List<Dictionary<string, string>> regPerms = ServicesInfoHelper.GetWriteServiceRegs(Checks.CurrentUserSiDs);
Dictionary<string, string> colorsWR = new Dictionary<string, string>()
{

View File

@@ -5,21 +5,21 @@ using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using winPEAS._3rdParty.Watson;
using winPEAS.Helpers;
using winPEAS.Helpers.AppLocker;
using winPEAS._3rdParty.Watson;
using winPEAS.Info.SystemInfo.Printers;
using winPEAS.Info.SystemInfo.NamedPipes;
using winPEAS.Info.SystemInfo;
using winPEAS.Info.SystemInfo.SysMon;
using winPEAS.Helpers.Extensions;
using winPEAS.Helpers.Registry;
using winPEAS.Info.SystemInfo;
using winPEAS.Info.SystemInfo.AuditPolicies;
using winPEAS.Info.SystemInfo.DotNet;
using winPEAS.Info.SystemInfo.GroupPolicy;
using winPEAS.Info.SystemInfo.WindowsDefender;
using winPEAS.Info.SystemInfo.PowerShell;
using winPEAS.Info.SystemInfo.NamedPipes;
using winPEAS.Info.SystemInfo.Ntlm;
using winPEAS.Info.SystemInfo.PowerShell;
using winPEAS.Info.SystemInfo.Printers;
using winPEAS.Info.SystemInfo.SysMon;
using winPEAS.Info.SystemInfo.WindowsDefender;
using winPEAS.Native.Enums;
namespace winPEAS.Checks
@@ -107,7 +107,7 @@ namespace winPEAS.Checks
{ Globals.StrTrue, Beaprint.ansi_color_bad },
};
Beaprint.DictPrint(basicDictSystem, colorsSI, false);
System.Console.WriteLine();
Console.WriteLine();
Watson.FindVulns();
//To update Watson, update the CVEs and add the new ones and update the main function so it uses new CVEs (becausfull with the Beaprints inside the FindVulns function)
@@ -200,7 +200,7 @@ namespace winPEAS.Checks
Beaprint.MainPrint("PS default transcripts history");
Beaprint.InfoPrint("Read the PS history inside these files (if any)");
string drive = Path.GetPathRoot(Environment.SystemDirectory);
string transcriptsPath = drive + @"transcripts\";
string transcriptsPath = drive + @"transcripts\";
string usersPath = $"{drive}users";
var users = Directory.EnumerateDirectories(usersPath, "*", SearchOption.TopDirectoryOnly);
@@ -369,12 +369,12 @@ namespace winPEAS.Checks
if (lsaCfgFlags == "1")
{
System.Console.WriteLine(" Please, note that this only checks the LsaCfgFlags key value. This is not enough to enable Credentials Guard (but it's a strong indicator).");
Console.WriteLine(" Please, note that this only checks the LsaCfgFlags key value. This is not enough to enable Credentials Guard (but it's a strong indicator).");
Beaprint.GoodPrint(" CredentialGuard is active with UEFI lock");
}
else if (lsaCfgFlags == "2")
{
System.Console.WriteLine(" Please, note that this only checks the LsaCfgFlags key value. This is not enough to enable Credentials Guard (but it's a strong indicator).");
Console.WriteLine(" Please, note that this only checks the LsaCfgFlags key value. This is not enough to enable Credentials Guard (but it's a strong indicator).");
Beaprint.GoodPrint(" CredentialGuard is active without UEFI lock");
}
else
@@ -572,7 +572,7 @@ namespace winPEAS.Checks
else if (using_HKLM_WSUS == "0")
Beaprint.GoodPrint(" But UseWUServer is equals to 0, so it is not vulnerable!");
else
System.Console.WriteLine(" But UseWUServer is equals to " + using_HKLM_WSUS + ", so it may work or not");
Console.WriteLine(" But UseWUServer is equals to " + using_HKLM_WSUS + ", so it may work or not");
}
else
{
@@ -1070,7 +1070,7 @@ namespace winPEAS.Checks
}
else if (kvp.Value.GetType().IsArray && (kvp.Value.GetType().GetElementType().ToString() == "System.Byte"))
{
val = System.BitConverter.ToString((byte[])kvp.Value);
val = BitConverter.ToString((byte[])kvp.Value);
}
else
{
@@ -1086,12 +1086,12 @@ namespace winPEAS.Checks
Beaprint.BadPrint(" [!] WDigest is enabled - plaintext password extraction is possible!");
}
if (key.Equals("RunAsPPL", System.StringComparison.InvariantCultureIgnoreCase) && val == "1")
if (key.Equals("RunAsPPL", StringComparison.InvariantCultureIgnoreCase) && val == "1")
{
Beaprint.BadPrint(" [!] LSASS Protected Mode is enabled! You will not be able to access lsass.exe's memory easily.");
}
if (key.Equals("DisableRestrictedAdmin", System.StringComparison.InvariantCultureIgnoreCase) && val == "0")
if (key.Equals("DisableRestrictedAdmin", StringComparison.InvariantCultureIgnoreCase) && val == "0")
{
Beaprint.BadPrint(" [!] RDP Restricted Admin Mode is enabled! You can use pass-the-hash to access RDP on this system.");
}
@@ -1107,7 +1107,7 @@ namespace winPEAS.Checks
{
try
{
Beaprint.MainPrint("Display Local Group Policy settings - local users/machine" );
Beaprint.MainPrint("Display Local Group Policy settings - local users/machine");
var infos = GroupPolicy.GetLocalGroupPolicyInfos();

View File

@@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Security.Principal;
using winPEAS.Helpers;
using winPEAS.Helpers.Extensions;
@@ -158,7 +156,7 @@ namespace winPEAS.Checks
try
{
Beaprint.MainPrint("RDP Sessions");
List<Dictionary<string, string>> rdp_sessions = Info.UserInfo.UserInfoHelper.GetRDPSessions();
List<Dictionary<string, string>> rdp_sessions = UserInfoHelper.GetRDPSessions();
if (rdp_sessions.Count > 0)
{
string format = " {0,-10}{1,-15}{2,-15}{3,-25}{4,-10}{5}";
@@ -263,7 +261,7 @@ namespace winPEAS.Checks
{
Beaprint.MainPrint("Password Policies");
Beaprint.LinkPrint("", "Check for a possible brute-force");
List<Dictionary<string, string>> PPy = Info.UserInfo.UserInfoHelper.GetPasswordPolicy();
List<Dictionary<string, string>> PPy = UserInfoHelper.GetPasswordPolicy();
Beaprint.DictPrint(PPy, ColorsU(), false);
}
catch (Exception ex)
@@ -282,7 +280,7 @@ namespace winPEAS.Checks
foreach (var logonSession in logonSessions)
{
Beaprint.NoColorPrint ($" Method: {logonSession.Method}\n" +
Beaprint.NoColorPrint($" Method: {logonSession.Method}\n" +
$" Logon Server: {logonSession.LogonServer}\n" +
$" Logon Server Dns Domain: {logonSession.LogonServerDnsDomain}\n" +
$" Logon Id: {logonSession.LogonId}\n" +
@@ -317,7 +315,7 @@ namespace winPEAS.Checks
if (User32.GetLastInputInfo(ref lastInputInfo))
{
var currentUser = WindowsIdentity.GetCurrent().Name;
var idleTimeMiliSeconds = (uint) Environment.TickCount - lastInputInfo.Time;
var idleTimeMiliSeconds = (uint)Environment.TickCount - lastInputInfo.Time;
var timeSpan = TimeSpan.FromMilliseconds(idleTimeMiliSeconds);
var idleTimeString = $"{timeSpan.Hours:D2}h:{timeSpan.Minutes:D2}m:{timeSpan.Seconds:D2}s:{timeSpan.Milliseconds:D3}ms";
@@ -364,7 +362,7 @@ namespace winPEAS.Checks
lastLogon = lastLogon.AddSeconds(localUser.last_logon).ToLocalTime();
}
Beaprint.AnsiPrint( $" Computer Name : {computerName}\n" +
Beaprint.AnsiPrint($" Computer Name : {computerName}\n" +
$" User Name : {localUser.name}\n" +
$" User Id : {localUser.user_id}\n" +
$" Is Enabled : {enabled}\n" +

View File

@@ -116,7 +116,7 @@ namespace winPEAS.Helpers.AppLocker
var color = GetColorBySid(filePublisherRule.UserOrGroupSid);
Beaprint.ColorPrint( $" User Or Group Sid: {filePublisherRule.UserOrGroupSid}\n", color);
Beaprint.ColorPrint($" User Or Group Sid: {filePublisherRule.UserOrGroupSid}\n", color);
Beaprint.GoodPrint($" Conditions");
@@ -153,7 +153,7 @@ namespace winPEAS.Helpers.AppLocker
var color = GetColorBySid(filePathRule.UserOrGroupSid);
Beaprint.ColorPrint( $" User Or Group Sid: {filePathRule.UserOrGroupSid}\n", color);
Beaprint.ColorPrint($" User Or Group Sid: {filePathRule.UserOrGroupSid}\n", color);
Beaprint.GoodPrint($" Conditions");
@@ -328,39 +328,42 @@ namespace winPEAS.Helpers.AppLocker
try
{
var subfolders = Directory.EnumerateDirectories(path);
var files = Directory.EnumerateFiles(path, "*", SearchOption.TopDirectoryOnly);
ruleType = ruleType.ToLower();
if (!_appLockerFileExtensionsByType.ContainsKey(ruleType))
if (Directory.Exists(path))
{
throw new ArgumentException(nameof(ruleType));
}
var subfolders = Directory.EnumerateDirectories(path);
var files = Directory.EnumerateFiles(path, "*", SearchOption.TopDirectoryOnly);
var filteredFiles =
(from file in files
let extension = Path.GetExtension(file)?.ToLower() ?? string.Empty
where _appLockerFileExtensionsByType[ruleType].Contains(extension)
select file).ToList();
ruleType = ruleType.ToLower();
// first check write access for files
if (filteredFiles.Any(CheckFileWriteAccess))
{
return true;
}
if (!_appLockerFileExtensionsByType.ContainsKey(ruleType))
{
throw new ArgumentException(nameof(ruleType));
}
// if we have not found any writable file,
// check subfolders for write access
if (subfolders.Any(subfolder => CheckDirectoryWriteAccess(subfolder, out bool _, isGoodPrint: false)))
{
return true;
}
var filteredFiles =
(from file in files
let extension = Path.GetExtension(file)?.ToLower() ?? string.Empty
where _appLockerFileExtensionsByType[ruleType].Contains(extension)
select file).ToList();
// check recursively all the subfolders for files/sub-subfolders
if (subfolders.Any(subfolder => CheckFilesAndSubfolders(subfolder, ruleType, depth + 1)))
{
return true;
// first check write access for files
if (filteredFiles.Any(CheckFileWriteAccess))
{
return true;
}
// if we have not found any writable file,
// check subfolders for write access
if (subfolders.Any(subfolder => CheckDirectoryWriteAccess(subfolder, out bool _, isGoodPrint: false)))
{
return true;
}
// check recursively all the subfolders for files/sub-subfolders
if (subfolders.Any(subfolder => CheckFilesAndSubfolders(subfolder, ruleType, depth + 1)))
{
return true;
}
}
}
catch (Exception)

View File

@@ -5,79 +5,79 @@ using System.Runtime.InteropServices;
namespace winPEAS.Helpers.AppLocker
{
[Guid("B6FEA19E-32DD-4367-B5B7-2F5DA140E87D")]
[TypeLibType(TypeLibTypeFlags.FDual | TypeLibTypeFlags.FNonExtensible | TypeLibTypeFlags.FDispatchable)]
[ComImport]
public interface IAppIdPolicyHandler
{
// Token: 0x06000001 RID: 1
[DispId(1)]
[MethodImpl(MethodImplOptions.InternalCall)]
void SetPolicy([MarshalAs(UnmanagedType.BStr)][In] string bstrLdapPath, [MarshalAs(UnmanagedType.BStr)][In] string bstrXmlPolicy);
[TypeLibType(TypeLibTypeFlags.FDual | TypeLibTypeFlags.FNonExtensible | TypeLibTypeFlags.FDispatchable)]
[ComImport]
public interface IAppIdPolicyHandler
{
// Token: 0x06000001 RID: 1
[DispId(1)]
[MethodImpl(MethodImplOptions.InternalCall)]
void SetPolicy([MarshalAs(UnmanagedType.BStr)][In] string bstrLdapPath, [MarshalAs(UnmanagedType.BStr)][In] string bstrXmlPolicy);
// Token: 0x06000002 RID: 2
[DispId(2)]
[MethodImpl(MethodImplOptions.InternalCall)]
[return: MarshalAs(UnmanagedType.BStr)]
string GetPolicy([MarshalAs(UnmanagedType.BStr)][In] string bstrLdapPath);
// Token: 0x06000002 RID: 2
[DispId(2)]
[MethodImpl(MethodImplOptions.InternalCall)]
[return: MarshalAs(UnmanagedType.BStr)]
string GetPolicy([MarshalAs(UnmanagedType.BStr)][In] string bstrLdapPath);
// Token: 0x06000003 RID: 3
[DispId(3)]
[MethodImpl(MethodImplOptions.InternalCall)]
[return: MarshalAs(UnmanagedType.BStr)]
string GetEffectivePolicy();
// Token: 0x06000003 RID: 3
[DispId(3)]
[MethodImpl(MethodImplOptions.InternalCall)]
[return: MarshalAs(UnmanagedType.BStr)]
string GetEffectivePolicy();
// Token: 0x06000004 RID: 4
[DispId(4)]
[MethodImpl(MethodImplOptions.InternalCall)]
int IsFileAllowed([MarshalAs(UnmanagedType.BStr)][In] string bstrXmlPolicy, [MarshalAs(UnmanagedType.BStr)][In] string bstrFilePath, [MarshalAs(UnmanagedType.BStr)][In] string bstrUserSid, out Guid pguidResponsibleRuleId);
// Token: 0x06000004 RID: 4
[DispId(4)]
[MethodImpl(MethodImplOptions.InternalCall)]
int IsFileAllowed([MarshalAs(UnmanagedType.BStr)][In] string bstrXmlPolicy, [MarshalAs(UnmanagedType.BStr)][In] string bstrFilePath, [MarshalAs(UnmanagedType.BStr)][In] string bstrUserSid, out Guid pguidResponsibleRuleId);
// Token: 0x06000005 RID: 5
[DispId(5)]
[MethodImpl(MethodImplOptions.InternalCall)]
int IsPackageAllowed([MarshalAs(UnmanagedType.BStr)][In] string bstrXmlPolicy, [MarshalAs(UnmanagedType.BStr)][In] string bstrPublisherName, [MarshalAs(UnmanagedType.BStr)][In] string bstrPackageName, [In] ulong ullPackageVersion, [MarshalAs(UnmanagedType.BStr)][In] string bstrUserSid, out Guid pguidResponsibleRuleId);
}
// Token: 0x06000005 RID: 5
[DispId(5)]
[MethodImpl(MethodImplOptions.InternalCall)]
int IsPackageAllowed([MarshalAs(UnmanagedType.BStr)][In] string bstrXmlPolicy, [MarshalAs(UnmanagedType.BStr)][In] string bstrPublisherName, [MarshalAs(UnmanagedType.BStr)][In] string bstrPackageName, [In] ulong ullPackageVersion, [MarshalAs(UnmanagedType.BStr)][In] string bstrUserSid, out Guid pguidResponsibleRuleId);
}
// Token: 0x02000003 RID: 3
[CoClass(typeof(AppIdPolicyHandlerClass))]
[Guid("B6FEA19E-32DD-4367-B5B7-2F5DA140E87D")]
[ComImport]
public interface AppIdPolicyHandler : IAppIdPolicyHandler
{
}
// Token: 0x02000003 RID: 3
[CoClass(typeof(AppIdPolicyHandlerClass))]
[Guid("B6FEA19E-32DD-4367-B5B7-2F5DA140E87D")]
[ComImport]
public interface AppIdPolicyHandler : IAppIdPolicyHandler
{
}
// Token: 0x02000004 RID: 4
[Guid("F1ED7D4C-F863-4DE6-A1CA-7253EFDEE1F3")]
[ClassInterface(ClassInterfaceType.None)]
[TypeLibType(TypeLibTypeFlags.FCanCreate)]
[ComImport]
public class AppIdPolicyHandlerClass : IAppIdPolicyHandler, AppIdPolicyHandler
{
// Token: 0x02000004 RID: 4
[Guid("F1ED7D4C-F863-4DE6-A1CA-7253EFDEE1F3")]
[ClassInterface(ClassInterfaceType.None)]
[TypeLibType(TypeLibTypeFlags.FCanCreate)]
[ComImport]
public class AppIdPolicyHandlerClass : IAppIdPolicyHandler, AppIdPolicyHandler
{
// Token: 0x06000007 RID: 7
[DispId(1)]
[MethodImpl(MethodImplOptions.InternalCall)]
public virtual extern void SetPolicy([MarshalAs(UnmanagedType.BStr)][In] string bstrLdapPath, [MarshalAs(UnmanagedType.BStr)][In] string bstrXmlPolicy);
// Token: 0x06000007 RID: 7
[DispId(1)]
[MethodImpl(MethodImplOptions.InternalCall)]
public virtual extern void SetPolicy([MarshalAs(UnmanagedType.BStr)][In] string bstrLdapPath, [MarshalAs(UnmanagedType.BStr)][In] string bstrXmlPolicy);
// Token: 0x06000008 RID: 8
[DispId(2)]
[MethodImpl(MethodImplOptions.InternalCall)]
[return: MarshalAs(UnmanagedType.BStr)]
public virtual extern string GetPolicy([MarshalAs(UnmanagedType.BStr)][In] string bstrLdapPath);
// Token: 0x06000008 RID: 8
[DispId(2)]
[MethodImpl(MethodImplOptions.InternalCall)]
[return: MarshalAs(UnmanagedType.BStr)]
public virtual extern string GetPolicy([MarshalAs(UnmanagedType.BStr)][In] string bstrLdapPath);
// Token: 0x06000009 RID: 9
[DispId(3)]
[MethodImpl(MethodImplOptions.InternalCall)]
[return: MarshalAs(UnmanagedType.BStr)]
public virtual extern string GetEffectivePolicy();
// Token: 0x06000009 RID: 9
[DispId(3)]
[MethodImpl(MethodImplOptions.InternalCall)]
[return: MarshalAs(UnmanagedType.BStr)]
public virtual extern string GetEffectivePolicy();
// Token: 0x0600000A RID: 10
[DispId(4)]
[MethodImpl(MethodImplOptions.InternalCall)]
public virtual extern int IsFileAllowed([MarshalAs(UnmanagedType.BStr)][In] string bstrXmlPolicy, [MarshalAs(UnmanagedType.BStr)][In] string bstrFilePath, [MarshalAs(UnmanagedType.BStr)][In] string bstrUserSid, out Guid pguidResponsibleRuleId);
// Token: 0x0600000A RID: 10
[DispId(4)]
[MethodImpl(MethodImplOptions.InternalCall)]
public virtual extern int IsFileAllowed([MarshalAs(UnmanagedType.BStr)][In] string bstrXmlPolicy, [MarshalAs(UnmanagedType.BStr)][In] string bstrFilePath, [MarshalAs(UnmanagedType.BStr)][In] string bstrUserSid, out Guid pguidResponsibleRuleId);
// Token: 0x0600000B RID: 11
[DispId(5)]
[MethodImpl(MethodImplOptions.InternalCall)]
public virtual extern int IsPackageAllowed([MarshalAs(UnmanagedType.BStr)][In] string bstrXmlPolicy, [MarshalAs(UnmanagedType.BStr)][In] string bstrPublisherName, [MarshalAs(UnmanagedType.BStr)][In] string bstrPackageName, [In] ulong ullPackageVersion, [MarshalAs(UnmanagedType.BStr)][In] string bstrUserSid, out Guid pguidResponsibleRuleId);
}
// Token: 0x0600000B RID: 11
[DispId(5)]
[MethodImpl(MethodImplOptions.InternalCall)]
public virtual extern int IsPackageAllowed([MarshalAs(UnmanagedType.BStr)][In] string bstrXmlPolicy, [MarshalAs(UnmanagedType.BStr)][In] string bstrPublisherName, [MarshalAs(UnmanagedType.BStr)][In] string bstrPackageName, [In] ulong ullPackageVersion, [MarshalAs(UnmanagedType.BStr)][In] string bstrUserSid, out Guid pguidResponsibleRuleId);
}
}

View File

@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Threading;
namespace winPEAS.Helpers
{
@@ -105,7 +104,7 @@ namespace winPEAS.Helpers
PrintLegend();
Console.WriteLine();
Console.WriteLine(BLUE + " You can find a Windows local PE Checklist here: "+YELLOW+"https://book.hacktricks.xyz/windows-hardening/checklist-windows-privilege-escalation");
Console.WriteLine(BLUE + " You can find a Windows local PE Checklist here: " + YELLOW + "https://book.hacktricks.xyz/windows-hardening/checklist-windows-privilege-escalation");
}
static void PrintLegend()

View File

@@ -4,7 +4,6 @@ using System.Linq;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.Text;
using winPEAS.Native;
using winPEAS.Native.Enums;

View File

@@ -1,9 +1,9 @@
using System;
using Microsoft.Win32.SafeHandles;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;
using winPEAS.Native;
namespace winPEAS.Helpers.CredentialManager

View File

@@ -1,5 +1,4 @@
using System;
using System.Runtime.InteropServices;
using winPEAS.Native;
using winPEAS.Native.Enums;

View File

@@ -1,11 +1,9 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Text;
using System.Threading.Tasks;
namespace winPEAS.Helpers
{
@@ -244,7 +242,7 @@ namespace winPEAS.Helpers
{
string perm = PermissionsHelper.PermInt2Str((int)h.GrantedAccess, PermissionType.WRITEABLE_OR_EQUIVALENT);
if (perm != null && perm.Length> 0)
if (perm != null && perm.Length > 0)
{
vulnHandler.isVuln = true;
vulnHandler.reason = perm;
@@ -438,9 +436,11 @@ namespace winPEAS.Helpers
// Get the owner of a process given the PID
public static Dictionary<string, string> GetProcU(Process p)
{
Dictionary<string, string> data = new Dictionary<string, string>();
data["name"] = "";
data["sid"] = "";
Dictionary<string, string> data = new Dictionary<string, string>
{
["name"] = "",
["sid"] = ""
};
IntPtr pHandle = IntPtr.Zero;
try
{
@@ -471,7 +471,7 @@ namespace winPEAS.Helpers
PT_RELEVANT_INFO pri = new PT_RELEVANT_INFO();
Process proc = Process.GetProcessById(pid);
Dictionary<string,string> user = GetProcU(proc);
Dictionary<string, string> user = GetProcU(proc);
StringBuilder fileName = new StringBuilder(2000);
Native.Psapi.GetProcessImageFileName(proc.Handle, fileName, 2000);
@@ -586,7 +586,7 @@ namespace winPEAS.Helpers
{ // This shouldn't be needed
if (path.StartsWith("\\"))
path = path.Substring(1);
hive = Helpers.Registry.RegistryHelper.CheckIfExists(path);
hive = Registry.RegistryHelper.CheckIfExists(path);
}
if (path.StartsWith("\\"))

View File

@@ -1,5 +1,4 @@
using System;
using System.Diagnostics;
using System.Diagnostics;
namespace winPEAS.Helpers
{

View File

@@ -76,7 +76,7 @@ namespace winPEAS.Helpers
}
//Check if rundll32
string[] binaryPathdll32 = binaryPath.Split(new string[] {"Rundll32.exe"}, StringSplitOptions.None);
string[] binaryPathdll32 = binaryPath.Split(new string[] { "Rundll32.exe" }, StringSplitOptions.None);
if (binaryPathdll32.Length > 1)
{
@@ -224,7 +224,7 @@ namespace winPEAS.Helpers
return strOutput;
}
private static string[] suffixes = new[] {" B", " KB", " MB", " GB", " TB", " PB"};
private static string[] suffixes = new[] { " B", " KB", " MB", " GB", " TB", " PB" };
public static string ConvertBytesToHumanReadable(double number, int precision = 2)
{

View File

@@ -1,11 +1,11 @@
using System;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.AccessControl;
using System.Security.Principal;
using System.Text.RegularExpressions;
using Microsoft.Win32;
namespace winPEAS.Helpers
{
@@ -354,14 +354,17 @@ namespace winPEAS.Helpers
results[path] = String.Join(", ", GetPermissionsFolder(path, Checks.Checks.CurrentUserSiDs));
if (string.IsNullOrEmpty(results[path]))
{
foreach (string d in Directory.EnumerateDirectories(path))
if (Directory.Exists(path))
{
foreach (string f in Directory.EnumerateFiles(d))
foreach (string d in Directory.EnumerateDirectories(path))
{
results[f] = String.Join(", ", GetPermissionsFile(f, Checks.Checks.CurrentUserSiDs));
foreach (string f in Directory.EnumerateFiles(d))
{
results[f] = String.Join(", ", GetPermissionsFile(f, Checks.Checks.CurrentUserSiDs));
}
cont += 1;
results.Concat(GetRecursivePrivs(d, cont)).ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
}
cont += 1;
results.Concat(GetRecursivePrivs(d, cont)).ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
}
}
}

View File

@@ -4,85 +4,85 @@ using System.Threading;
namespace winPEAS.Helpers
{
internal class ProgressBar : IDisposable, IProgress<double>
{
private const int blockCount = 10;
private readonly TimeSpan animationInterval = TimeSpan.FromSeconds(1.0 / 8);
private const string animation = @"|/-\";
internal class ProgressBar : IDisposable, IProgress<double>
{
private const int blockCount = 10;
private readonly TimeSpan animationInterval = TimeSpan.FromSeconds(1.0 / 8);
private const string animation = @"|/-\";
private readonly Timer timer;
private readonly Timer timer;
private double currentProgress = 0;
private string currentText = string.Empty;
private bool disposed = false;
private int animationIndex = 0;
private double currentProgress = 0;
private string currentText = string.Empty;
private bool disposed = false;
private int animationIndex = 0;
public ProgressBar()
{
timer = new Timer(TimerHandler, new object(), animationInterval, animationInterval);
}
public ProgressBar()
{
timer = new Timer(TimerHandler, new object(), animationInterval, animationInterval);
}
public void Report(double value)
{
// Make sure value is in [0..1] range
value = Math.Max(0, Math.Min(1, value));
Interlocked.Exchange(ref currentProgress, value);
}
public void Report(double value)
{
// Make sure value is in [0..1] range
value = Math.Max(0, Math.Min(1, value));
Interlocked.Exchange(ref currentProgress, value);
}
private void TimerHandler(object state)
{
lock (timer)
{
if (disposed) return;
private void TimerHandler(object state)
{
lock (timer)
{
if (disposed) return;
int progressBlockCount = (int)(currentProgress * blockCount);
int percent = (int)(currentProgress * 100);
string text = string.Format("[{0}{1}] {2,3}% {3}",
new string('#', progressBlockCount), new string('-', blockCount - progressBlockCount),
percent,
animation[animationIndex++ % animation.Length]);
UpdateText(text);
}
}
int progressBlockCount = (int)(currentProgress * blockCount);
int percent = (int)(currentProgress * 100);
string text = string.Format("[{0}{1}] {2,3}% {3}",
new string('#', progressBlockCount), new string('-', blockCount - progressBlockCount),
percent,
animation[animationIndex++ % animation.Length]);
UpdateText(text);
}
}
private void UpdateText(string text)
{
// Get length of common portion
int commonPrefixLength = 0;
int commonLength = Math.Min(currentText.Length, text.Length);
while (commonPrefixLength < commonLength && text[commonPrefixLength] == currentText[commonPrefixLength])
{
commonPrefixLength++;
}
private void UpdateText(string text)
{
// Get length of common portion
int commonPrefixLength = 0;
int commonLength = Math.Min(currentText.Length, text.Length);
while (commonPrefixLength < commonLength && text[commonPrefixLength] == currentText[commonPrefixLength])
{
commonPrefixLength++;
}
// Backtrack to the first differing character
StringBuilder outputBuilder = new StringBuilder();
outputBuilder.Append('\b', currentText.Length - commonPrefixLength);
// Backtrack to the first differing character
StringBuilder outputBuilder = new StringBuilder();
outputBuilder.Append('\b', currentText.Length - commonPrefixLength);
// Output new suffix
outputBuilder.Append(text.Substring(commonPrefixLength));
// Output new suffix
outputBuilder.Append(text.Substring(commonPrefixLength));
// If the new text is shorter than the old one: delete overlapping characters
int overlapCount = currentText.Length - text.Length;
if (overlapCount > 0)
{
outputBuilder.Append(' ', overlapCount);
outputBuilder.Append('\b', overlapCount);
}
// If the new text is shorter than the old one: delete overlapping characters
int overlapCount = currentText.Length - text.Length;
if (overlapCount > 0)
{
outputBuilder.Append(' ', overlapCount);
outputBuilder.Append('\b', overlapCount);
}
Console.Write(outputBuilder);
currentText = text;
}
Console.Write(outputBuilder);
currentText = text;
}
public void Dispose()
{
lock (timer)
{
disposed = true;
UpdateText(string.Empty);
timer.Dispose();
}
}
public void Dispose()
{
lock (timer)
{
disposed = true;
UpdateText(string.Empty);
timer.Dispose();
}
}
}
}
}

View File

@@ -1,7 +1,7 @@
using System;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Win32;
namespace winPEAS.Helpers.Registry
{
@@ -177,7 +177,7 @@ namespace winPEAS.Helpers.Registry
internal static uint? GetDwordValue(string hive, string key, string val)
{
string strValue = RegistryHelper.GetRegValue(hive, key, val);
string strValue = GetRegValue(hive, key, val);
if (uint.TryParse(strValue, out uint res))
{

View File

@@ -92,7 +92,7 @@ namespace winPEAS.Helpers.Search
Beaprint.LongPathWarning(f.FullName);
}
}
) ;
);
});
});
@@ -221,43 +221,43 @@ namespace winPEAS.Helpers.Search
{
// c:\users
string rootUsersSearchPath = $"{SystemDrive}\\Users\\";
SearchHelper.RootDirUsers = SearchHelper.GetFilesFast(rootUsersSearchPath, GlobalPattern, isFoldersIncluded: true);
RootDirUsers = GetFilesFast(rootUsersSearchPath, GlobalPattern, isFoldersIncluded: true);
// c:\users\current_user
string rootCurrentUserSearchPath = Environment.GetEnvironmentVariable("USERPROFILE");
SearchHelper.RootDirCurrentUser = SearchHelper.GetFilesFast(rootCurrentUserSearchPath, GlobalPattern, isFoldersIncluded: true);
RootDirCurrentUser = GetFilesFast(rootCurrentUserSearchPath, GlobalPattern, isFoldersIncluded: true);
// c:\Program Files\
string rootProgramFiles = $"{SystemDrive}\\Program Files\\";
SearchHelper.ProgramFiles = SearchHelper.GetFilesFast(rootProgramFiles, GlobalPattern, isFoldersIncluded: true);
ProgramFiles = GetFilesFast(rootProgramFiles, GlobalPattern, isFoldersIncluded: true);
// c:\Program Files (x86)\
string rootProgramFilesX86 = $"{SystemDrive}\\Program Files (x86)\\";
SearchHelper.ProgramFilesX86 = SearchHelper.GetFilesFast(rootProgramFilesX86, GlobalPattern, isFoldersIncluded: true);
ProgramFilesX86 = GetFilesFast(rootProgramFilesX86, GlobalPattern, isFoldersIncluded: true);
// c:\Documents and Settings\
string documentsAndSettings = $"{SystemDrive}\\Documents and Settings\\";
SearchHelper.DocumentsAndSettings = SearchHelper.GetFilesFast(documentsAndSettings, GlobalPattern, isFoldersIncluded: true);
DocumentsAndSettings = GetFilesFast(documentsAndSettings, GlobalPattern, isFoldersIncluded: true);
// c:\ProgramData\Microsoft\Group Policy\History
string groupPolicyHistory = $"{SystemDrive}\\ProgramData\\Microsoft\\Group Policy\\History";
SearchHelper.GroupPolicyHistory = SearchHelper.GetFilesFast(groupPolicyHistory, GlobalPattern, isFoldersIncluded: true);
GroupPolicyHistory = GetFilesFast(groupPolicyHistory, GlobalPattern, isFoldersIncluded: true);
// c:\Documents and Settings\All Users\Application Data\\Microsoft\\Group Policy\\History
string groupPolicyHistoryLegacy = $"{documentsAndSettings}\\All Users\\Application Data\\Microsoft\\Group Policy\\History";
//SearchHelper.GroupPolicyHistoryLegacy = SearchHelper.GetFilesFast(groupPolicyHistoryLegacy, globalPattern);
var groupPolicyHistoryLegacyFiles = SearchHelper.GetFilesFast(groupPolicyHistoryLegacy, GlobalPattern, isFoldersIncluded: true);
SearchHelper.GroupPolicyHistory.AddRange(groupPolicyHistoryLegacyFiles);
var groupPolicyHistoryLegacyFiles = GetFilesFast(groupPolicyHistoryLegacy, GlobalPattern, isFoldersIncluded: true);
GroupPolicyHistory.AddRange(groupPolicyHistoryLegacyFiles);
}
internal static void CleanLists()
{
SearchHelper.RootDirUsers = null;
SearchHelper.RootDirCurrentUser = null;
SearchHelper.ProgramFiles = null;
SearchHelper.ProgramFilesX86 = null;
SearchHelper.DocumentsAndSettings = null;
SearchHelper.GroupPolicyHistory = null;
RootDirUsers = null;
RootDirCurrentUser = null;
ProgramFiles = null;
ProgramFilesX86 = null;
DocumentsAndSettings = null;
GroupPolicyHistory = null;
GC.Collect();
}
@@ -270,7 +270,7 @@ namespace winPEAS.Helpers.Search
".*password.*"
};
foreach (var file in SearchHelper.RootDirUsers)
foreach (var file in RootDirUsers)
{
//string extLower = file.Extension.ToLower();
@@ -297,7 +297,7 @@ namespace winPEAS.Helpers.Search
{
var result = new List<string>();
foreach (var file in SearchHelper.RootDirCurrentUser)
foreach (var file in RootDirCurrentUser)
{
if (!file.IsDirectory)
{
@@ -337,7 +337,7 @@ namespace winPEAS.Helpers.Search
".xml"
};
foreach (var file in SearchHelper.GroupPolicyHistory)
foreach (var file in GroupPolicyHistory)
{
if (!file.IsDirectory)
{
@@ -361,14 +361,14 @@ namespace winPEAS.Helpers.Search
};
string programDataPath = $"{SystemDrive}\\ProgramData\\";
var programData = SearchHelper.GetFilesFast(programDataPath, GlobalPattern);
var programData = GetFilesFast(programDataPath, GlobalPattern);
var searchFiles = new List<CustomFileInfo>();
searchFiles.AddRange(SearchHelper.ProgramFiles);
searchFiles.AddRange(SearchHelper.ProgramFilesX86);
searchFiles.AddRange(ProgramFiles);
searchFiles.AddRange(ProgramFilesX86);
searchFiles.AddRange(programData);
searchFiles.AddRange(SearchHelper.DocumentsAndSettings);
searchFiles.AddRange(SearchHelper.RootDirUsers);
searchFiles.AddRange(DocumentsAndSettings);
searchFiles.AddRange(RootDirUsers);
foreach (var file in searchFiles)
{
@@ -403,7 +403,7 @@ namespace winPEAS.Helpers.Search
".pdf",
};
foreach (var file in SearchHelper.RootDirCurrentUser)
foreach (var file in RootDirCurrentUser)
{
if (!file.IsDirectory)
{
@@ -451,7 +451,7 @@ namespace winPEAS.Helpers.Search
".pdf",
};
foreach (var file in SearchHelper.RootDirUsers)
foreach (var file in RootDirUsers)
{
if (!file.IsDirectory)
{

View File

@@ -8,7 +8,8 @@ namespace winPEAS.Helpers.YamlConfig
{
public string name { get; set; }
public RegularExpression[] regexes { get; set; }
public class RegularExpression {
public class RegularExpression
{
public string name { get; set; }
public string regex { get; set; }
@@ -25,65 +26,65 @@ namespace winPEAS.Helpers.YamlConfig
public class FileParam
{
public string name { get; set; }
public FileSettings value { get; set; }
public string name { get; set; }
public FileSettings value { get; set; }
}
public class SearchParameters
{
public class FileSettings
{
public string bad_regex { get; set; }
public string bad_regex { get; set; }
// public string check_extra_path { get; set; } // not used in Winpeas
public string good_regex { get; set; }
public bool? just_list_file { get; set; }
public string line_grep { get; set; }
public bool? only_bad_lines { get; set; }
public bool? remove_empty_lines { get; set; }
public string good_regex { get; set; }
public bool? just_list_file { get; set; }
public string line_grep { get; set; }
public bool? only_bad_lines { get; set; }
public bool? remove_empty_lines { get; set; }
// public string remove_path { get; set; } // not used in Winpeas
public string remove_regex { get; set; }
public string remove_regex { get; set; }
public string remove_path { get; set; }
// public string[] search_in { get; set; } // not used in Winpeas
public string type { get; set; }
public FileParam[] files { get; set; }
public string type { get; set; }
public FileParam[] files { get; set; }
}
public class FileParameters
{
public string file { get; set; }
public FileSettings options { get; set; }
public string file { get; set; }
public FileSettings options { get; set; }
}
public class Config
{
public bool auto_check { get; set; }
public bool auto_check { get; set; }
}
public Config config { get; set; }
public string[] disable { get; set; } // disabled scripts - linpeas/winpeas
public FileParam[] files { get; set; }
public Config config { get; set; }
public string[] disable { get; set; } // disabled scripts - linpeas/winpeas
public FileParam[] files { get; set; }
}
public class SearchParams
{
public string name { get; set; }
public SearchParameters value { get; set; }
public string name { get; set; }
public SearchParameters value { get; set; }
}
public class Defaults
{
public bool auto_check { get; set; }
public string bad_regex { get; set; }
public bool auto_check { get; set; }
public string bad_regex { get; set; }
//public string check_extra_path { get; set; } not used in winpeas
public string good_regex { get; set; }
public bool just_list_file { get; set; }
public string line_grep { get; set; }
public bool only_bad_lines { get; set; }
public bool remove_empty_lines { get; set; }
public string remove_path { get; set; }
public string remove_regex { get; set; }
public string[] search_in { get; set; }
public string type { get; set; }
public string good_regex { get; set; }
public bool just_list_file { get; set; }
public string line_grep { get; set; }
public bool only_bad_lines { get; set; }
public bool remove_empty_lines { get; set; }
public string remove_path { get; set; }
public string remove_regex { get; set; }
public string[] search_in { get; set; }
public string type { get; set; }
}
public class Variable
@@ -92,9 +93,9 @@ namespace winPEAS.Helpers.YamlConfig
public string value { get; set; }
}
public SearchParams[] search { get; set; }
public SearchParams[] search { get; set; }
public Defaults defaults { get; set; }
public Defaults defaults { get; set; }
public Variable[] variables { get; set; }
}

View File

@@ -1,10 +1,9 @@
using System.Collections.Generic;
using System.Yaml.Serialization;
using System.IO;
using System.Reflection;
using System.Linq;
using System.Reflection;
using System.Yaml.Serialization;
using static winPEAS.Helpers.YamlConfig.YamlConfig;
using static winPEAS.Helpers.YamlConfig.YamlRegexConfig;
namespace winPEAS.Helpers.YamlConfig
@@ -30,7 +29,7 @@ namespace winPEAS.Helpers.YamlConfig
YamlRegexConfig yamlConfig = (YamlRegexConfig)yamlSerializer.Deserialize(configFileContent, typeof(YamlRegexConfig))[0];
// check
if (yamlConfig.regular_expresions == null || yamlConfig.regular_expresions.Length == 0)
if (yamlConfig.regular_expresions == null || yamlConfig.regular_expresions.Length == 0)
{
throw new System.Exception("No configuration was read");
}

View File

@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using winPEAS.Helpers;
using winPEAS.Native;

View File

@@ -1,10 +1,10 @@
using System;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Management;
using System.Text.RegularExpressions;
using Microsoft.Win32;
using winPEAS.Helpers;
using winPEAS.Helpers.Registry;
@@ -204,7 +204,7 @@ namespace winPEAS.Info.ApplicationInfo
{
autorunLocationKey[0], autorunLocationKey[1] + "\\" + clsid_name, autorunLocationKey[2]
}
: new List<string> {autorunLocationKey[0], autorunLocationKey[1] + "\\" + clsid_name});
: new List<string> { autorunLocationKey[0], autorunLocationKey[1] + "\\" + clsid_name });
}
}
@@ -344,15 +344,18 @@ namespace winPEAS.Info.ApplicationInfo
try
{
var userDirs = Directory.EnumerateDirectories(usersPath);
foreach (var userDir in userDirs)
if (Directory.Exists(usersPath))
{
string startupPath = $@"{userDir}\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup";
var userDirs = Directory.EnumerateDirectories(usersPath);
if (Directory.Exists(startupPath))
foreach (var userDir in userDirs)
{
autorunLocations.Add(startupPath);
string startupPath = $@"{userDir}\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup";
if (Directory.Exists(startupPath))
{
autorunLocations.Add(startupPath);
}
}
}
}
@@ -364,22 +367,25 @@ namespace winPEAS.Info.ApplicationInfo
{
try
{
var files = Directory.EnumerateFiles(path, "*", SearchOption.TopDirectoryOnly);
foreach (string filepath in files)
if (Directory.Exists(path))
{
string folder = Path.GetDirectoryName(filepath);
results.Add(new Dictionary<string, string>() {
{ "Reg", "" },
{ "RegKey", "" },
{ "RegPermissions", "" },
{ "Folder", folder },
{ "File", filepath },
{ "isWritableReg", ""},
{ "interestingFolderRights", string.Join(", ", PermissionsHelper.GetPermissionsFolder(folder, Checks.Checks.CurrentUserSiDs))},
{ "interestingFileRights", string.Join(", ", PermissionsHelper.GetPermissionsFile(filepath, Checks.Checks.CurrentUserSiDs))},
{ "isUnquotedSpaced", MyUtils.CheckQuoteAndSpace(path).ToString() }
});
var files = Directory.EnumerateFiles(path, "*", SearchOption.TopDirectoryOnly);
foreach (string filepath in files)
{
string folder = Path.GetDirectoryName(filepath);
results.Add(new Dictionary<string, string>() {
{ "Reg", "" },
{ "RegKey", "" },
{ "RegPermissions", "" },
{ "Folder", folder },
{ "File", filepath },
{ "isWritableReg", ""},
{ "interestingFolderRights", string.Join(", ", PermissionsHelper.GetPermissionsFolder(folder, Checks.Checks.CurrentUserSiDs))},
{ "interestingFileRights", string.Join(", ", PermissionsHelper.GetPermissionsFile(filepath, Checks.Checks.CurrentUserSiDs))},
{ "isUnquotedSpaced", MyUtils.CheckQuoteAndSpace(path).ToString() }
});
}
}
}
catch (Exception)

View File

@@ -71,16 +71,19 @@ namespace winPEAS.Info.ApplicationInfo
var results = new SortedDictionary<string, Dictionary<string, string>>();
try
{
foreach (string f in Directory.EnumerateFiles(fpath))
if (Directory.Exists(fpath))
{
results[f] = new Dictionary<string, string>
foreach (string f in Directory.EnumerateFiles(fpath))
{
results[f] = new Dictionary<string, string>
{
{ f, string.Join(", ", PermissionsHelper.GetPermissionsFile(f, Checks.Checks.CurrentUserSiDs)) }
};
}
foreach (string d in Directory.EnumerateDirectories(fpath))
{
results[d] = PermissionsHelper.GetRecursivePrivs(d);
}
foreach (string d in Directory.EnumerateDirectories(fpath))
{
results[d] = PermissionsHelper.GetRecursivePrivs(d);
}
}
}
catch (Exception ex)

View File

@@ -1,6 +1,5 @@
using System.Collections.Generic;
using winPEAS.Helpers;
using winPEAS.Info.EventsInfo.PowerShell;
namespace winPEAS.Info.EventsInfo.ProcessCreation
{

View File

@@ -34,19 +34,19 @@ namespace winPEAS.Info.FilesInfo.Certificates
switch (ext.Oid.FriendlyName)
{
case "Enhanced Key Usage":
{
var extUsages = ((X509EnhancedKeyUsageExtension)ext).EnhancedKeyUsages;
if (extUsages.Count == 0)
continue;
foreach (var extUsage in extUsages)
{
enhancedKeyUsages.Add(extUsage.FriendlyName);
}
var extUsages = ((X509EnhancedKeyUsageExtension)ext).EnhancedKeyUsages;
break;
}
if (extUsages.Count == 0)
continue;
foreach (var extUsage in extUsages)
{
enhancedKeyUsages.Add(extUsage.FriendlyName);
}
break;
}
case "Certificate Template Name":
case "Certificate Template Information":
template = ext.Format(false);

View File

@@ -127,7 +127,7 @@ namespace winPEAS.Info.FilesInfo.McAfee
byte[] XORKey = { 0x12, 0x15, 0x0F, 0x10, 0x11, 0x1C, 0x1A, 0x06, 0x0A, 0x1F, 0x1B, 0x18, 0x17, 0x16, 0x05, 0x19 };
// xor the input b64 string with the static XOR key
var passwordBytes = System.Convert.FromBase64String(base64password);
var passwordBytes = Convert.FromBase64String(base64password);
for (var i = 0; i < passwordBytes.Length; i++)
{
passwordBytes[i] = (byte)(passwordBytes[i] ^ XORKey[i % XORKey.Length]);

View File

@@ -1,9 +1,9 @@
using System;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text.RegularExpressions;
using Microsoft.Win32;
using winPEAS.Helpers;
using winPEAS.Helpers.Registry;
using winPEAS.Info.FilesInfo.Office.OneDrive;

View File

@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.InteropServices;
using winPEAS.Helpers;
@@ -25,7 +24,7 @@ namespace winPEAS.Info.NetworkInfo
Type firewall = Type.GetTypeFromCLSID(new Guid("E2B3C97F-6AE1-41AC-817A-F6F92166D7DD"));
object firewallObj = Activator.CreateInstance(firewall);
object types = ReflectionHelper.InvokeMemberProperty(firewallObj, "CurrentProfileTypes");
result = $"{(FirewallProfiles) int.Parse(types.ToString())}";
result = $"{(FirewallProfiles)int.Parse(types.ToString())}";
}
catch (Exception ex)
{

View File

@@ -191,12 +191,12 @@ namespace winPEAS.Info.NetworkInfo
foreach (var listener in props.GetActiveTcpListeners())
{
bool repeated = false;
foreach(List<string> inside_entry in results)
foreach (List<string> inside_entry in results)
{
if (inside_entry.SequenceEqual(new List<string>() { "TCP", listener.ToString(), "", "Listening" }))
repeated = true;
}
if (! repeated)
if (!repeated)
results.Add(new List<string>() { "TCP", listener.ToString(), "", "Listening" });
}
@@ -337,7 +337,7 @@ namespace winPEAS.Info.NetworkInfo
// Determine if IPv4 or IPv6.
if (ipVersion == IPVersion.IPv4)
{
MIB_TCPTABLE_OWNER_PID tcpRecordsTable = (MIB_TCPTABLE_OWNER_PID) Marshal.PtrToStructure(tcpTableRecordsPtr, typeof(MIB_TCPTABLE_OWNER_PID));
MIB_TCPTABLE_OWNER_PID tcpRecordsTable = (MIB_TCPTABLE_OWNER_PID)Marshal.PtrToStructure(tcpTableRecordsPtr, typeof(MIB_TCPTABLE_OWNER_PID));
IntPtr tableRowPtr = (IntPtr)((long)tcpTableRecordsPtr + Marshal.SizeOf(tcpRecordsTable.dwNumEntries));
@@ -373,7 +373,7 @@ namespace winPEAS.Info.NetworkInfo
}
else if (ipVersion == IPVersion.IPv6)
{
MIB_TCP6TABLE_OWNER_PID tcpRecordsTable = (MIB_TCP6TABLE_OWNER_PID) Marshal.PtrToStructure(tcpTableRecordsPtr, typeof(MIB_TCP6TABLE_OWNER_PID));
MIB_TCP6TABLE_OWNER_PID tcpRecordsTable = (MIB_TCP6TABLE_OWNER_PID)Marshal.PtrToStructure(tcpTableRecordsPtr, typeof(MIB_TCP6TABLE_OWNER_PID));
IntPtr tableRowPtr = (IntPtr)((long)tcpTableRecordsPtr + Marshal.SizeOf(tcpRecordsTable.dwNumEntries));
@@ -461,14 +461,14 @@ namespace winPEAS.Info.NetworkInfo
// Determine if IPv4 or IPv6.
if (ipVersion == IPVersion.IPv4)
{
MIB_UDPTABLE_OWNER_PID udpRecordsTable = (MIB_UDPTABLE_OWNER_PID) Marshal.PtrToStructure(udpTableRecordsPtr, typeof(MIB_UDPTABLE_OWNER_PID));
MIB_UDPTABLE_OWNER_PID udpRecordsTable = (MIB_UDPTABLE_OWNER_PID)Marshal.PtrToStructure(udpTableRecordsPtr, typeof(MIB_UDPTABLE_OWNER_PID));
IntPtr tableRowPtr = (IntPtr)((long)udpTableRecordsPtr + Marshal.SizeOf(udpRecordsTable.dwNumEntries));
// Read and parse the UDP records from the table and store them in list
// 'UdpConnection' structure type objects.
for (int i = 0; i < udpRecordsTable.dwNumEntries; i++)
{
MIB_UDPROW_OWNER_PID udpRow = (MIB_UDPROW_OWNER_PID) Marshal.PtrToStructure(tableRowPtr, typeof(MIB_UDPROW_OWNER_PID));
MIB_UDPROW_OWNER_PID udpRow = (MIB_UDPROW_OWNER_PID)Marshal.PtrToStructure(tableRowPtr, typeof(MIB_UDPROW_OWNER_PID));
udpTableRecords.Add(new UdpConnectionInfo(
Protocol.UDP,
new IPAddress(udpRow.localAddr),

View File

@@ -6,7 +6,7 @@ namespace winPEAS.Info.NetworkInfo.Structs
public struct MIB_UDP6TABLE_OWNER_PID
{
public uint dwNumEntries;
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct,SizeConst = 1)]
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 1)]
public MIB_UDP6ROW_OWNER_PID[] table;
}
}

View File

@@ -6,7 +6,7 @@ namespace winPEAS.Info.NetworkInfo.Structs
public struct MIB_UDPTABLE_OWNER_PID
{
public uint dwNumEntries;
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct,SizeConst = 1)]
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 1)]
public MIB_UDPROW_OWNER_PID[] table;
}
}

View File

@@ -6,7 +6,6 @@ using System.Linq;
using System.Management;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using winPEAS.Helpers;
@@ -33,7 +32,7 @@ namespace winPEAS.Info.ProcessInfo
Proc = p,
Pth = (string)mo["ExecutablePath"],
CommLine = (string)mo["CommandLine"],
Owner = Helpers.HandlesHelper.GetProcU(p)["name"], //Needed inside the next foreach
Owner = HandlesHelper.GetProcU(p)["name"], //Needed inside the next foreach
};
foreach (var itm in queRy)
@@ -54,14 +53,16 @@ namespace winPEAS.Info.ProcessInfo
}
if ((string.IsNullOrEmpty(companyName)) || (!Regex.IsMatch(companyName, @"^Microsoft.*", RegexOptions.IgnoreCase)))
{
Dictionary<string, string> to_add = new Dictionary<string, string>();
to_add["Name"] = itm.Proc.ProcessName;
to_add["ProcessID"] = itm.Proc.Id.ToString();
to_add["ExecutablePath"] = itm.Pth;
to_add["Product"] = companyName;
to_add["Owner"] = itm.Owner == null ? "" : itm.Owner;
to_add["isDotNet"] = isDotNet;
to_add["CommandLine"] = itm.CommLine;
Dictionary<string, string> to_add = new Dictionary<string, string>
{
["Name"] = itm.Proc.ProcessName,
["ProcessID"] = itm.Proc.Id.ToString(),
["ExecutablePath"] = itm.Pth,
["Product"] = companyName,
["Owner"] = itm.Owner == null ? "" : itm.Owner,
["isDotNet"] = isDotNet,
["CommandLine"] = itm.CommLine
};
f_results.Add(to_add);
}
}
@@ -123,11 +124,13 @@ namespace winPEAS.Info.ProcessInfo
string hName = HandlesHelper.GetObjectName(dupHandle);
Dictionary<string, string> to_add = new Dictionary<string, string>();
to_add["Handle Name"] = hName;
to_add["Handle"] = h.HandleValue.ToString() + "(" + typeName + ")";
to_add["Handle Owner"] = "Pid is " + h.UniqueProcessId.ToString() + "(" + origProcInfo.name + ") with owner: " + origProcInfo.userName;
to_add["Reason"] = handlerExp.reason;
Dictionary<string, string> to_add = new Dictionary<string, string>
{
["Handle Name"] = hName,
["Handle"] = h.HandleValue.ToString() + "(" + typeName + ")",
["Handle Owner"] = "Pid is " + h.UniqueProcessId.ToString() + "(" + origProcInfo.name + ") with owner: " + origProcInfo.userName,
["Reason"] = handlerExp.reason
};
if (typeName == "process" || typeName == "thread")
{
@@ -208,7 +211,7 @@ namespace winPEAS.Info.ProcessInfo
else if (typeName == "key")
{
HandlesHelper.KEY_RELEVANT_INFO kri = HandlesHelper.getKeyHandlerInfo(dupHandle);
if (kri.path.Length == 0 && kri.hive != null && kri.hive.Length> 0)
if (kri.path.Length == 0 && kri.hive != null && kri.hive.Length > 0)
continue;
RegistryKey regKey = Helpers.Registry.RegistryHelper.GetReg(kri.hive, kri.path);

View File

@@ -1,4 +1,5 @@
using System;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
@@ -8,10 +9,8 @@ using System.Runtime.InteropServices;
using System.Security.AccessControl;
using System.ServiceProcess;
using System.Text.RegularExpressions;
using Microsoft.Win32;
using winPEAS.Helpers;
using winPEAS.Helpers.Registry;
using winPEAS.KnownFileCreds;
using winPEAS.Native;
namespace winPEAS.Info.ServicesInfo
@@ -51,17 +50,18 @@ namespace winPEAS.Info.ServicesInfo
if (string.IsNullOrEmpty(companyName) || (!Regex.IsMatch(companyName, @"^Microsoft.*", RegexOptions.IgnoreCase)))
{
Dictionary<string, string> toadd = new Dictionary<string, string>();
toadd["Name"] = GetStringOrEmpty(result["Name"]);
toadd["DisplayName"] = GetStringOrEmpty(result["DisplayName"]);
toadd["CompanyName"] = companyName;
toadd["State"] = GetStringOrEmpty(result["State"]);
toadd["StartMode"] = GetStringOrEmpty(result["StartMode"]);
toadd["PathName"] = GetStringOrEmpty(result["PathName"]);
toadd["FilteredPath"] = binaryPath;
toadd["isDotNet"] = isDotNet;
toadd["Description"] = GetStringOrEmpty(result["Description"]);
Dictionary<string, string> toadd = new Dictionary<string, string>
{
["Name"] = GetStringOrEmpty(result["Name"]),
["DisplayName"] = GetStringOrEmpty(result["DisplayName"]),
["CompanyName"] = companyName,
["State"] = GetStringOrEmpty(result["State"]),
["StartMode"] = GetStringOrEmpty(result["StartMode"]),
["PathName"] = GetStringOrEmpty(result["PathName"]),
["FilteredPath"] = binaryPath,
["isDotNet"] = isDotNet,
["Description"] = GetStringOrEmpty(result["Description"])
};
results.Add(toadd);
}
@@ -232,7 +232,7 @@ namespace winPEAS.Info.ServicesInfo
if (permissions.Count > 0)
{
string perms = String.Join(", ", permissions);
if (perms.Replace("Start", "").Replace("Stop","").Length > 3) //Check if any other permissions appart from Start and Stop
if (perms.Replace("Start", "").Replace("Stop", "").Length > 3) //Check if any other permissions appart from Start and Stop
results.Add(sc.ServiceName, perms);
}
@@ -249,9 +249,9 @@ namespace winPEAS.Info.ServicesInfo
/////// Find Write reg. Services ////////
//////////////////////////////////////////
/// Find Services which Reg you have write or equivalent access
public static List<Dictionary<string, string>> GetWriteServiceRegs(Dictionary<string,string> NtAccountNames)
public static List<Dictionary<string, string>> GetWriteServiceRegs(Dictionary<string, string> NtAccountNames)
{
List<Dictionary<string,string>> results = new List<Dictionary<string, string>>();
List<Dictionary<string, string>> results = new List<Dictionary<string, string>>();
try
{
RegistryKey regKey = Registry.LocalMachine.OpenSubKey(@"system\currentcontrolset\services");

View File

@@ -1,5 +1,5 @@
using System.Collections.Generic;
using Microsoft.Win32;
using Microsoft.Win32;
using System.Collections.Generic;
using winPEAS.Helpers.Registry;
using winPEAS.Native.Enums;

View File

@@ -3,7 +3,6 @@ using System.IO;
using System.Runtime.InteropServices;
using System.Security.AccessControl;
using winPEAS.Native;
using System.Security.Principal;
namespace winPEAS.Info.SystemInfo.NamedPipes
@@ -51,7 +50,7 @@ namespace winPEAS.Info.SystemInfo.NamedPipes
{
var security = File.GetAccessControl($"\\\\.\\pipe\\{namedPipe}");
sddl = security.GetSecurityDescriptorSddlForm(AccessControlSections.All);
List<string> currentUserPermsList = winPEAS.Helpers.PermissionsHelper.GetMyPermissionsF(security, winPEAS.Checks.Checks.CurrentUserSiDs);
List<string> currentUserPermsList = Helpers.PermissionsHelper.GetMyPermissionsF(security, Checks.Checks.CurrentUserSiDs);
currentUserPerms = string.Join(", ", currentUserPermsList);
}
catch

View File

@@ -2,7 +2,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.Eventing.Reader;
using System.Text.RegularExpressions;
using winPEAS.Helpers;
using winPEAS.Helpers.Registry;

View File

@@ -9,7 +9,6 @@ using System.Net.NetworkInformation;
using System.Windows.Forms;
using winPEAS.Helpers;
using winPEAS.Helpers.Registry;
using winPEAS.KnownFileCreds;
namespace winPEAS.Info.SystemInfo
{

View File

@@ -1,7 +1,5 @@
using System;
using System.Collections.Generic;
using Microsoft.Win32;
using winPEAS.Helpers;
using winPEAS.Helpers.Registry;
namespace winPEAS.Info.SystemInfo.WindowsDefender
@@ -17,7 +15,7 @@ namespace winPEAS.Info.SystemInfo.WindowsDefender
public WindowsDefenderSettings(string defenderBaseKeyPath)
{
PathExclusions = new List<string>();
var pathExclusionData = RegistryHelper.GetRegValues("HKLM", $"{ defenderBaseKeyPath}\\Exclusions\\Paths");
var pathExclusionData = RegistryHelper.GetRegValues("HKLM", $"{defenderBaseKeyPath}\\Exclusions\\Paths");
if (pathExclusionData != null)
{
foreach (var kvp in pathExclusionData)

View File

@@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace winPEAS.Info.SystemInfo.WindowsDefender
namespace winPEAS.Info.SystemInfo.WindowsDefender
{
class WindowsDefenderSettingsInfo
{

View File

@@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Security.Principal;
using winPEAS.Helpers;
using winPEAS.Native;
using winPEAS.Native.Classes;

View File

@@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Net.NetworkInformation;
using System.Security.Principal;
using System.Text.RegularExpressions;
using winPEAS.Helpers;
namespace winPEAS.Info.UserInfo

View File

@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using winPEAS.Helpers;
using winPEAS.Native;
using winPEAS.Native.Structs;

View File

@@ -36,7 +36,7 @@ namespace winPEAS.Info.UserInfo.Token
Advapi32.LookupPrivilegeName(null, luidPointer, null, ref luidNameLen);
strBuilder.EnsureCapacity(luidNameLen + 1);
if (Advapi32.LookupPrivilegeName(null, luidPointer, strBuilder, ref luidNameLen))
results[strBuilder.ToString()] = $"{(LuidAttributes) laa.Attributes}";
results[strBuilder.ToString()] = $"{(LuidAttributes)laa.Attributes}";
Marshal.FreeHGlobal(luidPointer);
}
}

View File

@@ -7,7 +7,6 @@ using System.Management;
using System.Runtime.InteropServices;
using System.Security.Principal;
using winPEAS.Helpers;
using winPEAS.KnownFileCreds;
using winPEAS.Native;
using winPEAS.Native.Structs;

View File

@@ -6,7 +6,6 @@ using System.Windows.Forms;
using winPEAS.Helpers;
using winPEAS.Helpers.Registry;
using winPEAS.Info.UserInfo.SAM;
using winPEAS.KnownFileCreds;
using winPEAS.Native;
using winPEAS.Native.Enums;
@@ -251,14 +250,15 @@ namespace winPEAS.Info.UserInfo
public static Dictionary<string, string> GetAutoLogon()
{
Dictionary<string, string> results = new Dictionary<string, string>();
results["DefaultDomainName"] = RegistryHelper.GetRegValue("HKLM", "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", "DefaultDomainName");
results["DefaultUserName"] = RegistryHelper.GetRegValue("HKLM", "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", "DefaultUserName");
results["DefaultPassword"] = RegistryHelper.GetRegValue("HKLM", "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", "DefaultPassword");
results["AltDefaultDomainName"] = RegistryHelper.GetRegValue("HKLM", "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", "AltDefaultDomainName");
results["AltDefaultUserName"] = RegistryHelper.GetRegValue("HKLM", "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", "AltDefaultUserName");
results["AltDefaultPassword"] = RegistryHelper.GetRegValue("HKLM", "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", "AltDefaultPassword");
Dictionary<string, string> results = new Dictionary<string, string>
{
["DefaultDomainName"] = RegistryHelper.GetRegValue("HKLM", "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", "DefaultDomainName"),
["DefaultUserName"] = RegistryHelper.GetRegValue("HKLM", "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", "DefaultUserName"),
["DefaultPassword"] = RegistryHelper.GetRegValue("HKLM", "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", "DefaultPassword"),
["AltDefaultDomainName"] = RegistryHelper.GetRegValue("HKLM", "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", "AltDefaultDomainName"),
["AltDefaultUserName"] = RegistryHelper.GetRegValue("HKLM", "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", "AltDefaultUserName"),
["AltDefaultPassword"] = RegistryHelper.GetRegValue("HKLM", "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", "AltDefaultPassword")
};
return results;
}
@@ -281,7 +281,7 @@ namespace winPEAS.Info.UserInfo
c = $"{Clipboard.GetFileDropList()}";
//else if (Clipboard.ContainsImage()) //No system.Drwing import
//c = string.Format("{0}", Clipboard.GetImage());
//c = string.Format("{0}", Clipboard.GetImage());
}
catch (Exception ex)
{

View File

@@ -15,7 +15,7 @@ namespace winPEAS.InterestingFiles
try
{
string allUsers = System.Environment.GetEnvironmentVariable("ALLUSERSPROFILE");
string allUsers = Environment.GetEnvironmentVariable("ALLUSERSPROFILE");
if (!allUsers.Contains("ProgramData"))
{
@@ -225,11 +225,13 @@ namespace winPEAS.InterestingFiles
Changed = "[BLANK]";
}
results[file] = new Dictionary<string, string>();
results[file]["UserName"] = UserName;
results[file]["NewName"] = NewName;
results[file]["cPassword"] = cPassword;
results[file]["Changed"] = Changed;
results[file] = new Dictionary<string, string>
{
["UserName"] = UserName,
["NewName"] = NewName,
["cPassword"] = cPassword,
["Changed"] = Changed
};
}
}
catch (Exception ex)

View File

@@ -28,7 +28,7 @@ namespace winPEAS.InterestingFiles
$@"{systemRoot}\System32\config\RegBack\SYSTEM",
};
results.AddRange(searchLocations.Where(searchLocation => System.IO.File.Exists(searchLocation)));
results.AddRange(searchLocations.Where(searchLocation => File.Exists(searchLocation)));
}
catch (Exception ex)
{
@@ -102,7 +102,7 @@ namespace winPEAS.InterestingFiles
// Reference: https://stackoverflow.com/questions/18071412/list-filenames-in-the-recyclebin-with-c-sharp-without-using-any-external-files
int lastDays = 30;
var startTime = System.DateTime.Now.AddDays(-lastDays);
var startTime = DateTime.Now.AddDays(-lastDays);
// Shell COM object GUID
Type shell = Type.GetTypeFromCLSID(new Guid("13709620-C279-11CE-A49E-444553540000"));

View File

@@ -40,7 +40,7 @@ namespace winPEAS.InterestingFiles
try
{
var winDir = System.Environment.GetEnvironmentVariable("windir");
var winDir = Environment.GetEnvironmentVariable("windir");
string[] searchLocations =
{
$"{winDir}\\sysprep\\sysprep.xml",
@@ -56,7 +56,7 @@ namespace winPEAS.InterestingFiles
$"{winDir}\\..\\unattend.inf",
};
results.AddRange(searchLocations.Where(System.IO.File.Exists));
results.AddRange(searchLocations.Where(File.Exists));
}
catch (Exception ex)
{

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Web.Script.Serialization;
using winPEAS.Checks;
@@ -27,7 +28,7 @@ namespace winPEAS.KnownFileCreds.Browsers.Chrome
{
Beaprint.MainPrint("Looking for Chrome DBs");
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#browsers-history");
Dictionary<string, string> chromeDBs = Chrome.GetChromeDbs();
Dictionary<string, string> chromeDBs = GetChromeDbs();
if (chromeDBs.ContainsKey("userChromeCookiesPath"))
{
@@ -59,7 +60,7 @@ namespace winPEAS.KnownFileCreds.Browsers.Chrome
{
Beaprint.MainPrint("Looking for GET credentials in Chrome history");
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#browsers-history");
Dictionary<string, List<string>> chromeHistBook = Chrome.GetChromeHistBook();
Dictionary<string, List<string>> chromeHistBook = GetChromeHistBook();
List<string> history = chromeHistBook["history"];
List<string> bookmarks = chromeHistBook["bookmarks"];
@@ -77,8 +78,11 @@ namespace winPEAS.KnownFileCreds.Browsers.Chrome
Beaprint.AnsiPrint(" " + url, colorsB);
}
}
Console.WriteLine();
int limit = 50;
Beaprint.MainPrint($"Chrome history -- limit {limit}\n");
Beaprint.ListPrint(history.Take(limit).ToList());
}
else
{
@@ -130,14 +134,14 @@ namespace winPEAS.KnownFileCreds.Browsers.Chrome
else
{
string userChromeCookiesPath =
$"{System.Environment.GetEnvironmentVariable("USERPROFILE")}\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\Cookies";
$"{Environment.GetEnvironmentVariable("USERPROFILE")}\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\Cookies";
if (File.Exists(userChromeCookiesPath))
{
results["userChromeCookiesPath"] = userChromeCookiesPath;
}
string userChromeLoginDataPath =
$"{System.Environment.GetEnvironmentVariable("USERPROFILE")}\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\Login Data";
$"{Environment.GetEnvironmentVariable("USERPROFILE")}\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\Login Data";
if (File.Exists(userChromeLoginDataPath))
{
results["userChromeLoginDataPath"] = userChromeLoginDataPath;
@@ -156,7 +160,7 @@ namespace winPEAS.KnownFileCreds.Browsers.Chrome
List<string> results = new List<string>();
// parses a Chrome history file via regex
if (System.IO.File.Exists(path))
if (File.Exists(path))
{
Regex historyRegex = new Regex(@"(http|ftp|https|file)://([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:/~+#-]*[\w@?^=%&/~+#-])?");
@@ -217,10 +221,10 @@ namespace winPEAS.KnownFileCreds.Browsers.Chrome
}
else
{
string userChromeHistoryPath = string.Format("{0}\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\History", System.Environment.GetEnvironmentVariable("USERPROFILE"));
string userChromeHistoryPath = string.Format("{0}\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\History", Environment.GetEnvironmentVariable("USERPROFILE"));
results["history"] = ParseChromeHistory(userChromeHistoryPath);
string userChromeBookmarkPath = string.Format("{0}\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\Bookmarks", System.Environment.GetEnvironmentVariable("USERPROFILE"));
string userChromeBookmarkPath = string.Format("{0}\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\Bookmarks", Environment.GetEnvironmentVariable("USERPROFILE"));
results["bookmarks"] = ParseChromeBookmarks(userChromeBookmarkPath);
}
@@ -241,7 +245,7 @@ namespace winPEAS.KnownFileCreds.Browsers.Chrome
{
try
{
string contents = System.IO.File.ReadAllText(path);
string contents = File.ReadAllText(path);
// reference: http://www.tomasvera.com/programming/using-javascriptserializer-to-parse-json-objects/
JavaScriptSerializer json = new JavaScriptSerializer();

View File

@@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace winPEAS.KnownFileCreds.Browsers.Firefox
namespace winPEAS.KnownFileCreds.Browsers.Firefox
{
class FFLogins
{

View File

@@ -4,11 +4,11 @@ using System.Data;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Web.Script.Serialization;
using winPEAS._3rdParty.SQLite;
using winPEAS.Checks;
using winPEAS.Helpers;
using winPEAS.KnownFileCreds.Browsers.Models;
using winPEAS._3rdParty.SQLite;
using System.Web.Script.Serialization;
namespace winPEAS.KnownFileCreds.Browsers.Firefox
{
@@ -29,7 +29,7 @@ namespace winPEAS.KnownFileCreds.Browsers.Firefox
{
Beaprint.MainPrint("Looking for Firefox DBs");
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#browsers-history");
List<string> firefoxDBs = Firefox.GetFirefoxDbs();
List<string> firefoxDBs = GetFirefoxDbs();
if (firefoxDBs.Count > 0)
{
foreach (string firefoxDB in firefoxDBs) //No Beaprints because line needs red
@@ -56,21 +56,26 @@ namespace winPEAS.KnownFileCreds.Browsers.Firefox
{
Beaprint.MainPrint("Looking for GET credentials in Firefox history");
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#browsers-history");
List<string> firefoxHist = Firefox.GetFirefoxHistory();
if (firefoxHist.Count > 0)
List<string> history = GetFirefoxHistory();
if (history.Count > 0)
{
Dictionary<string, string> colorsB = new Dictionary<string, string>()
{
{ Globals.PrintCredStrings, Beaprint.ansi_color_bad },
};
foreach (string url in firefoxHist)
foreach (string url in history)
{
if (MyUtils.ContainsAnyRegex(url.ToUpper(), Browser.CredStringsRegex))
{
Beaprint.AnsiPrint(" " + url, colorsB);
}
}
Console.WriteLine();
int limit = 50;
Beaprint.MainPrint($"Firefox history -- limit {limit}\n");
Beaprint.ListPrint(history.Take(limit).ToList());
}
else
{
@@ -101,7 +106,7 @@ namespace winPEAS.KnownFileCreds.Browsers.Firefox
if (!(dir.EndsWith("Public") || dir.EndsWith("Default") || dir.EndsWith("Default User") || dir.EndsWith("All Users")))
{
string userFirefoxBasePath = $"{dir}\\AppData\\Roaming\\Mozilla\\Firefox\\Profiles\\";
if (System.IO.Directory.Exists(userFirefoxBasePath))
if (Directory.Exists(userFirefoxBasePath))
{
var directories = Directory.EnumerateDirectories(userFirefoxBasePath);
foreach (string directory in directories)
@@ -249,25 +254,28 @@ namespace winPEAS.KnownFileCreds.Browsers.Firefox
foreach (string dir in dirs)
{
string[] files = Directory.EnumerateFiles(dir, "signons.sqlite").ToArray();
if (files.Length > 0)
if (Directory.Exists(dir))
{
signonsFile = files[0];
signonsFound = true;
}
string[] files = Directory.EnumerateFiles(dir, "signons.sqlite").ToArray();
if (files.Length > 0)
{
signonsFile = files[0];
signonsFound = true;
}
// find &quot;logins.json"file
files = Directory.EnumerateFiles(dir, "logins.json").ToArray();
if (files.Length > 0)
{
loginsFile = files[0];
loginsFound = true;
}
// find &quot;logins.json"file
files = Directory.EnumerateFiles(dir, "logins.json").ToArray();
if (files.Length > 0)
{
loginsFile = files[0];
loginsFound = true;
}
if (loginsFound || signonsFound)
{
FFDecryptor.NSS_Init(dir);
break;
if (loginsFound || signonsFound)
{
FFDecryptor.NSS_Init(dir);
break;
}
}
}
@@ -313,8 +321,8 @@ namespace winPEAS.KnownFileCreds.Browsers.Firefox
foreach (Browsers.Firefox.LoginData loginData in ffLoginData.logins)
{
string username = Browsers.Firefox.FFDecryptor.Decrypt(loginData.encryptedUsername);
string password = Browsers.Firefox.FFDecryptor.Decrypt(loginData.encryptedPassword);
string username = FFDecryptor.Decrypt(loginData.encryptedUsername);
string password = FFDecryptor.Decrypt(loginData.encryptedPassword);
logins.Add(new CredentialModel
{
Username = username,

View File

@@ -5,7 +5,7 @@ namespace winPEAS.KnownFileCreds.Browsers
{
internal interface IBrowser
{
string Name { get; }
string Name { get; }
void PrintInfo();
IEnumerable<CredentialModel> GetSavedCredentials();
}

View File

@@ -1,11 +1,11 @@
using System;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using Microsoft.Win32;
using winPEAS.Checks;
using winPEAS.Helpers;
using winPEAS.Helpers.Registry;
@@ -30,7 +30,7 @@ namespace winPEAS.KnownFileCreds.Browsers
{
Beaprint.MainPrint("Current IE tabs");
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#browsers-history");
List<string> urls = InternetExplorer.GetCurrentIETabs();
List<string> urls = GetCurrentIETabs();
Dictionary<string, string> colorsB = new Dictionary<string, string>()
{
@@ -51,9 +51,9 @@ namespace winPEAS.KnownFileCreds.Browsers
{
Beaprint.MainPrint("Looking for GET credentials in IE history");
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#browsers-history");
Dictionary<string, List<string>> chromeHistBook = InternetExplorer.GetIEHistFav();
List<string> history = chromeHistBook["history"];
List<string> favorites = chromeHistBook["favorites"];
Dictionary<string, List<string>> ieHistoryBook = GetIEHistFav();
List<string> history = ieHistoryBook["history"];
List<string> favorites = ieHistoryBook["favorites"];
if (history.Count > 0)
{
@@ -69,8 +69,15 @@ namespace winPEAS.KnownFileCreds.Browsers
Beaprint.AnsiPrint(" " + url, colorsB);
}
}
Console.WriteLine();
int limit = 50;
Beaprint.MainPrint($"IE history -- limit {limit}\n");
Beaprint.ListPrint(history.Take(limit).ToList());
}
else
{
Beaprint.NotFoundPrint();
}
Beaprint.MainPrint("IE favorites");
@@ -91,7 +98,7 @@ namespace winPEAS.KnownFileCreds.Browsers
{ "favorites", new List<string>() },
};
DateTime startTime = System.DateTime.Now.AddDays(-lastDays);
DateTime startTime = DateTime.Now.AddDays(-lastDays);
try
{
@@ -167,39 +174,31 @@ namespace winPEAS.KnownFileCreds.Browsers
{
foreach (KeyValuePair<string, object> kvp in settings)
{
byte[] timeBytes = RegistryHelper.GetRegValueBytes("HKCU", "SOFTWARE\\Microsoft\\Internet Explorer\\TypedURLsTime", kvp.Key.ToString().Trim());
if (timeBytes != null)
{
long timeLong = (long)(BitConverter.ToInt64(timeBytes, 0));
DateTime urlTime = DateTime.FromFileTime(timeLong);
if (urlTime > startTime)
{
results["history"].Add(kvp.Value.ToString().Trim());
}
}
results["history"].Add(kvp.Value.ToString().Trim());
}
}
string userIEBookmarkPath = string.Format("{0}\\Favorites\\", System.Environment.GetEnvironmentVariable("USERPROFILE"));
string[] bookmarkPaths = Directory.EnumerateFiles(userIEBookmarkPath, "*.url", SearchOption.AllDirectories).ToArray();
foreach (string bookmarkPath in bookmarkPaths)
string userIEBookmarkPath = string.Format("{0}\\Favorites\\", Environment.GetEnvironmentVariable("USERPROFILE"));
if (Directory.Exists(userIEBookmarkPath))
{
using (StreamReader rdr = new StreamReader(bookmarkPath))
string[] bookmarkPaths = Directory.EnumerateFiles(userIEBookmarkPath, "*.url", SearchOption.AllDirectories).ToArray();
foreach (string bookmarkPath in bookmarkPaths)
{
string line;
string url = "";
while ((line = rdr.ReadLine()) != null)
using (StreamReader rdr = new StreamReader(bookmarkPath))
{
if (line.StartsWith("URL=", StringComparison.InvariantCultureIgnoreCase))
string line;
string url = "";
while ((line = rdr.ReadLine()) != null)
{
if (line.Length > 4)
url = line.Substring(4);
break;
if (line.StartsWith("URL=", StringComparison.InvariantCultureIgnoreCase))
{
if (line.Length > 4)
url = line.Substring(4);
break;
}
}
results["favorites"].Add(url.ToString().Trim());
}
results["favorites"].Add(url.ToString().Trim());
}
}
}

View File

@@ -1,4 +1,5 @@
using System;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
@@ -6,7 +7,6 @@ using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using Microsoft.Win32;
using winPEAS.Helpers;
using winPEAS.Helpers.Registry;
@@ -76,7 +76,7 @@ namespace winPEAS.KnownFileCreds
else
{
var currentUserDir = Environment.GetEnvironmentVariable("USERPROFILE");
userDirs = new List<string>{ currentUserDir };
userDirs = new List<string> { currentUserDir };
}
foreach (var userDir in userDirs)
@@ -123,7 +123,7 @@ namespace winPEAS.KnownFileCreds
// parses recent file shortcuts via COM
List<Dictionary<string, string>> results = new List<Dictionary<string, string>>();
int lastDays = 7;
DateTime startTime = System.DateTime.Now.AddDays(-lastDays);
DateTime startTime = DateTime.Now.AddDays(-lastDays);
try
{
@@ -145,31 +145,34 @@ namespace winPEAS.KnownFileCreds
string recentPath = string.Format("{0}\\AppData\\Roaming\\Microsoft\\Windows\\Recent\\", dir);
try
{
string[] recentFiles = Directory.EnumerateFiles(recentPath, "*.lnk", SearchOption.AllDirectories).ToArray();
if (recentFiles.Length != 0)
if (Directory.Exists(recentPath))
{
Console.WriteLine(" {0} :\r\n", userName);
foreach (string recentFile in recentFiles)
string[] recentFiles = Directory.EnumerateFiles(recentPath, "*.lnk", SearchOption.AllDirectories).ToArray();
if (recentFiles.Length != 0)
{
DateTime lastAccessed = System.IO.File.GetLastAccessTime(recentFile);
if (lastAccessed > startTime)
Console.WriteLine(" {0} :\r\n", userName);
foreach (string recentFile in recentFiles)
{
// invoke the WshShell com object, creating a shortcut to then extract the TargetPath from
Object shortcut = shellObj.GetType().InvokeMember("CreateShortcut", BindingFlags.InvokeMethod, null, shellObj, new object[] { recentFile });
Object TargetPath = shortcut.GetType().InvokeMember("TargetPath", BindingFlags.GetProperty, null, shortcut, new object[] { });
DateTime lastAccessed = File.GetLastAccessTime(recentFile);
if (TargetPath.ToString().Trim() != "")
if (lastAccessed > startTime)
{
results.Add(new Dictionary<string, string>()
// invoke the WshShell com object, creating a shortcut to then extract the TargetPath from
Object shortcut = shellObj.GetType().InvokeMember("CreateShortcut", BindingFlags.InvokeMethod, null, shellObj, new object[] { recentFile });
Object TargetPath = shortcut.GetType().InvokeMember("TargetPath", BindingFlags.GetProperty, null, shortcut, new object[] { });
if (TargetPath.ToString().Trim() != "")
{
results.Add(new Dictionary<string, string>()
{
{ "Target", TargetPath.ToString() },
{ "Accessed", string.Format("{0}", lastAccessed) }
});
}
Marshal.ReleaseComObject(shortcut);
shortcut = null;
}
Marshal.ReleaseComObject(shortcut);
shortcut = null;
}
}
}
@@ -180,33 +183,35 @@ namespace winPEAS.KnownFileCreds
}
else
{
string recentPath = string.Format("{0}\\Microsoft\\Windows\\Recent\\", System.Environment.GetEnvironmentVariable("APPDATA"));
var recentFiles = Directory.EnumerateFiles(recentPath, "*.lnk", SearchOption.AllDirectories);
foreach (string recentFile in recentFiles)
string recentPath = string.Format("{0}\\Microsoft\\Windows\\Recent\\", Environment.GetEnvironmentVariable("APPDATA"));
if (Directory.Exists(recentPath))
{
// old method (needed interop dll)
//WshShell shell = new WshShell();
//IWshShortcut shortcut = (IWshShortcut)shell.CreateShortcut(recentFile);
var recentFiles = Directory.EnumerateFiles(recentPath, "*.lnk", SearchOption.AllDirectories);
DateTime lastAccessed = System.IO.File.GetLastAccessTime(recentFile);
if (lastAccessed > startTime)
foreach (string recentFile in recentFiles)
{
// invoke the WshShell com object, creating a shortcut to then extract the TargetPath from
Object shortcut = shellObj.GetType().InvokeMember("CreateShortcut", BindingFlags.InvokeMethod, null, shellObj, new object[] { recentFile });
Object TargetPath = shortcut.GetType().InvokeMember("TargetPath", BindingFlags.GetProperty, null, shortcut, new object[] { });
if (TargetPath.ToString().Trim() != "")
// old method (needed interop dll)
//WshShell shell = new WshShell();
//IWshShortcut shortcut = (IWshShortcut)shell.CreateShortcut(recentFile);
DateTime lastAccessed = File.GetLastAccessTime(recentFile);
if (lastAccessed > startTime)
{
results.Add(new Dictionary<string, string>()
// invoke the WshShell com object, creating a shortcut to then extract the TargetPath from
Object shortcut = shellObj.GetType().InvokeMember("CreateShortcut", BindingFlags.InvokeMethod, null, shellObj, new object[] { recentFile });
Object TargetPath = shortcut.GetType().InvokeMember("TargetPath", BindingFlags.GetProperty, null, shortcut, new object[] { });
if (TargetPath.ToString().Trim() != "")
{
results.Add(new Dictionary<string, string>()
{
{ "Target", TargetPath.ToString() },
{ "Accessed", string.Format("{0}", lastAccessed) }
});
}
Marshal.ReleaseComObject(shortcut);
shortcut = null;
}
Marshal.ReleaseComObject(shortcut);
shortcut = null;
}
}
}
@@ -237,13 +242,15 @@ namespace winPEAS.KnownFileCreds
string userName = parts[parts.Length - 1];
if (!(dir.EndsWith("Public") || dir.EndsWith("Default") || dir.EndsWith("Default User") || dir.EndsWith("All Users")))
{
List<string> userDPAPIBasePaths = new List<string>();
userDPAPIBasePaths.Add(string.Format("{0}\\AppData\\Roaming\\Microsoft\\Protect\\", System.Environment.GetEnvironmentVariable("USERPROFILE")));
userDPAPIBasePaths.Add(string.Format("{0}\\AppData\\Local\\Microsoft\\Protect\\", System.Environment.GetEnvironmentVariable("USERPROFILE")));
List<string> userDPAPIBasePaths = new List<string>
{
string.Format("{0}\\AppData\\Roaming\\Microsoft\\Protect\\", Environment.GetEnvironmentVariable("USERPROFILE")),
string.Format("{0}\\AppData\\Local\\Microsoft\\Protect\\", Environment.GetEnvironmentVariable("USERPROFILE"))
};
foreach (string userDPAPIBasePath in userDPAPIBasePaths)
{
if (System.IO.Directory.Exists(userDPAPIBasePath))
if (Directory.Exists(userDPAPIBasePath))
{
var directories = Directory.EnumerateDirectories(userDPAPIBasePath);
foreach (string directory in directories)
@@ -254,9 +261,9 @@ namespace winPEAS.KnownFileCreds
{
if (Regex.IsMatch(file, @"[0-9A-Fa-f]{8}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{12}"))
{
DateTime lastAccessed = System.IO.File.GetLastAccessTime(file);
DateTime lastModified = System.IO.File.GetLastWriteTime(file);
string fileName = System.IO.Path.GetFileName(file);
DateTime lastAccessed = File.GetLastAccessTime(file);
DateTime lastModified = File.GetLastWriteTime(file);
string fileName = Path.GetFileName(file);
results.Add(new Dictionary<string, string>()
{
{ "MasterKey", file },
@@ -274,13 +281,15 @@ namespace winPEAS.KnownFileCreds
else
{
string userName = Environment.GetEnvironmentVariable("USERNAME");
List<string> userDPAPIBasePaths = new List<string>();
userDPAPIBasePaths.Add(string.Format("{0}\\AppData\\Roaming\\Microsoft\\Protect\\", System.Environment.GetEnvironmentVariable("USERPROFILE")));
userDPAPIBasePaths.Add(string.Format("{0}\\AppData\\Local\\Microsoft\\Protect\\", System.Environment.GetEnvironmentVariable("USERPROFILE")));
List<string> userDPAPIBasePaths = new List<string>
{
string.Format("{0}\\AppData\\Roaming\\Microsoft\\Protect\\", Environment.GetEnvironmentVariable("USERPROFILE")),
string.Format("{0}\\AppData\\Local\\Microsoft\\Protect\\", Environment.GetEnvironmentVariable("USERPROFILE"))
};
foreach (string userDPAPIBasePath in userDPAPIBasePaths)
{
if (System.IO.Directory.Exists(userDPAPIBasePath))
if (Directory.Exists(userDPAPIBasePath))
{
var directories = Directory.EnumerateDirectories(userDPAPIBasePath);
foreach (string directory in directories)
@@ -291,9 +300,9 @@ namespace winPEAS.KnownFileCreds
{
if (Regex.IsMatch(file, @"[0-9A-Fa-f]{8}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{12}"))
{
DateTime lastAccessed = System.IO.File.GetLastAccessTime(file);
DateTime lastModified = System.IO.File.GetLastWriteTime(file);
string fileName = System.IO.Path.GetFileName(file);
DateTime lastAccessed = File.GetLastAccessTime(file);
DateTime lastModified = File.GetLastWriteTime(file);
string fileName = Path.GetFileName(file);
results.Add(new Dictionary<string, string>()
{
{ "MasterKey", file },
@@ -331,23 +340,25 @@ namespace winPEAS.KnownFileCreds
string userName = parts[parts.Length - 1];
if (!(dir.EndsWith("Public") || dir.EndsWith("Default") || dir.EndsWith("Default User") || dir.EndsWith("All Users")))
{
List<string> userCredFilePaths = new List<string>();
userCredFilePaths.Add(string.Format("{0}\\AppData\\Local\\Microsoft\\Credentials\\", dir));
userCredFilePaths.Add(string.Format("{0}\\AppData\\Roaming\\Microsoft\\Credentials\\", dir));
List<string> userCredFilePaths = new List<string>
{
string.Format("{0}\\AppData\\Local\\Microsoft\\Credentials\\", dir),
string.Format("{0}\\AppData\\Roaming\\Microsoft\\Credentials\\", dir)
};
foreach (string userCredFilePath in userCredFilePaths)
{
if (System.IO.Directory.Exists(userCredFilePath))
if (Directory.Exists(userCredFilePath))
{
var systemFiles = Directory.EnumerateFiles(userCredFilePath);
if ((systemFiles != null))
{
foreach (string file in systemFiles)
{
DateTime lastAccessed = System.IO.File.GetLastAccessTime(file);
DateTime lastModified = System.IO.File.GetLastWriteTime(file);
long size = new System.IO.FileInfo(file).Length;
string fileName = System.IO.Path.GetFileName(file);
DateTime lastAccessed = File.GetLastAccessTime(file);
DateTime lastModified = File.GetLastWriteTime(file);
long size = new FileInfo(file).Length;
string fileName = Path.GetFileName(file);
// jankily parse the bytes to extract the credential type and master key GUID
// reference- https://github.com/gentilkiwi/mimikatz/blob/3d8be22fff9f7222f9590aa007629e18300cf643/modules/kull_m_dpapi.h#L24-L54
@@ -381,49 +392,54 @@ namespace winPEAS.KnownFileCreds
}
string systemFolder = string.Format("{0}\\System32\\config\\systemprofile\\AppData\\Local\\Microsoft\\Credentials", Environment.GetEnvironmentVariable("SystemRoot"));
var files = Directory.EnumerateFiles(systemFolder);
if ((files != null))
if (Directory.Exists(systemFolder))
{
foreach (string file in files)
var files = Directory.EnumerateFiles(systemFolder);
if ((files != null))
{
DateTime lastAccessed = System.IO.File.GetLastAccessTime(file);
DateTime lastModified = System.IO.File.GetLastWriteTime(file);
long size = new System.IO.FileInfo(file).Length;
string fileName = System.IO.Path.GetFileName(file);
// jankily parse the bytes to extract the credential type and master key GUID
// reference- https://github.com/gentilkiwi/mimikatz/blob/3d8be22fff9f7222f9590aa007629e18300cf643/modules/kull_m_dpapi.h#L24-L54
byte[] credentialArray = File.ReadAllBytes(file);
byte[] guidMasterKeyArray = new byte[16];
Array.Copy(credentialArray, 36, guidMasterKeyArray, 0, 16);
Guid guidMasterKey = new Guid(guidMasterKeyArray);
byte[] stringLenArray = new byte[16];
Array.Copy(credentialArray, 56, stringLenArray, 0, 4);
int descLen = BitConverter.ToInt32(stringLenArray, 0);
byte[] descBytes = new byte[descLen];
Array.Copy(credentialArray, 60, descBytes, 0, descLen - 4);
string desc = Encoding.Unicode.GetString(descBytes);
results.Add(new Dictionary<string, string>()
foreach (string file in files)
{
{ "CredFile", file },
{ "Description", desc },
{ "MasterKey", string.Format("{0}", guidMasterKey) },
{ "Accessed", string.Format("{0}", lastAccessed) },
{ "Modified", string.Format("{0}", lastModified) },
{ "Size", string.Format("{0}", size) },
});
DateTime lastAccessed = File.GetLastAccessTime(file);
DateTime lastModified = File.GetLastWriteTime(file);
long size = new System.IO.FileInfo(file).Length;
string fileName = Path.GetFileName(file);
// jankily parse the bytes to extract the credential type and master key GUID
// reference- https://github.com/gentilkiwi/mimikatz/blob/3d8be22fff9f7222f9590aa007629e18300cf643/modules/kull_m_dpapi.h#L24-L54
byte[] credentialArray = File.ReadAllBytes(file);
byte[] guidMasterKeyArray = new byte[16];
Array.Copy(credentialArray, 36, guidMasterKeyArray, 0, 16);
Guid guidMasterKey = new Guid(guidMasterKeyArray);
byte[] stringLenArray = new byte[16];
Array.Copy(credentialArray, 56, stringLenArray, 0, 4);
int descLen = BitConverter.ToInt32(stringLenArray, 0);
byte[] descBytes = new byte[descLen];
Array.Copy(credentialArray, 60, descBytes, 0, descLen - 4);
string desc = Encoding.Unicode.GetString(descBytes);
results.Add(new Dictionary<string, string>()
{
{ "CredFile", file },
{ "Description", desc },
{ "MasterKey", string.Format("{0}", guidMasterKey) },
{ "Accessed", string.Format("{0}", lastAccessed) },
{ "Modified", string.Format("{0}", lastModified) },
{ "Size", string.Format("{0}", size) },
});
}
}
}
}
else
{
string userName = Environment.GetEnvironmentVariable("USERNAME");
List<string> userCredFilePaths = new List<string>();
userCredFilePaths.Add(string.Format("{0}\\AppData\\Local\\Microsoft\\Credentials\\", System.Environment.GetEnvironmentVariable("USERPROFILE")));
userCredFilePaths.Add(string.Format("{0}\\AppData\\Roaming\\Microsoft\\Credentials\\", System.Environment.GetEnvironmentVariable("USERPROFILE")));
List<string> userCredFilePaths = new List<string>
{
string.Format("{0}\\AppData\\Local\\Microsoft\\Credentials\\", Environment.GetEnvironmentVariable("USERPROFILE")),
string.Format("{0}\\AppData\\Roaming\\Microsoft\\Credentials\\", Environment.GetEnvironmentVariable("USERPROFILE"))
};
foreach (string userCredFilePath in userCredFilePaths)
{
@@ -433,10 +449,10 @@ namespace winPEAS.KnownFileCreds
foreach (string file in files)
{
DateTime lastAccessed = System.IO.File.GetLastAccessTime(file);
DateTime lastModified = System.IO.File.GetLastWriteTime(file);
DateTime lastAccessed = File.GetLastAccessTime(file);
DateTime lastModified = File.GetLastWriteTime(file);
long size = new System.IO.FileInfo(file).Length;
string fileName = System.IO.Path.GetFileName(file);
string fileName = Path.GetFileName(file);
// jankily parse the bytes to extract the credential type and master key GUID
// reference- https://github.com/gentilkiwi/mimikatz/blob/3d8be22fff9f7222f9590aa007629e18300cf643/modules/kull_m_dpapi.h#L24-L54

View File

@@ -1,6 +1,6 @@
using System;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using Microsoft.Win32;
using winPEAS.Helpers;
using winPEAS.Helpers.Registry;
@@ -20,7 +20,7 @@ namespace winPEAS.KnownFileCreds
try
{
Beaprint.MainPrint("Putty Sessions");
List<Dictionary<string, string>> putty_sess = Putty.GetPuttySessions();
List<Dictionary<string, string>> putty_sess = GetPuttySessions();
Dictionary<string, string> colorF = new Dictionary<string, string>()
{
@@ -39,7 +39,7 @@ namespace winPEAS.KnownFileCreds
try
{
Beaprint.MainPrint("Putty SSH Host keys");
List<Dictionary<string, string>> putty_sess = Putty.ListPuttySSHHostKeys();
List<Dictionary<string, string>> putty_sess = ListPuttySSHHostKeys();
Dictionary<string, string> colorF = new Dictionary<string, string>()
{
{ ".*", Beaprint.ansi_color_bad },
@@ -182,8 +182,10 @@ namespace winPEAS.KnownFileCreds
Dictionary<string, object> hostKeys = RegistryHelper.GetRegValues("HKU", string.Format("{0}\\Software\\SimonTatham\\PuTTY\\SshHostKeys\\", SID));
if ((hostKeys != null) && (hostKeys.Count != 0))
{
Dictionary<string, string> putty_ssh = new Dictionary<string, string>();
putty_ssh["UserSID"] = SID;
Dictionary<string, string> putty_ssh = new Dictionary<string, string>
{
["UserSID"] = SID
};
foreach (KeyValuePair<string, object> kvp in hostKeys)
{
putty_ssh[kvp.Key] = ""; //Looks like only matters the key name, not the value

View File

@@ -1,8 +1,8 @@
using System;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using Microsoft.Win32;
using winPEAS.Helpers;
using winPEAS.Helpers.Registry;
@@ -77,7 +77,7 @@ namespace winPEAS.KnownFileCreds
if (!(dir.EndsWith("Public") || dir.EndsWith("Default") || dir.EndsWith("Default User") || dir.EndsWith("All Users")))
{
string userRDManFile = string.Format("{0}\\AppData\\Local\\Microsoft\\Remote Desktop Connection Manager\\RDCMan.settings", dir);
if (System.IO.File.Exists(userRDManFile))
if (File.Exists(userRDManFile))
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(userRDManFile);
@@ -87,8 +87,8 @@ namespace winPEAS.KnownFileCreds
XmlNodeList items = filesToOpen[0].ChildNodes;
XmlNode node = items[0];
DateTime lastAccessed = System.IO.File.GetLastAccessTime(userRDManFile);
DateTime lastModified = System.IO.File.GetLastWriteTime(userRDManFile);
DateTime lastAccessed = File.GetLastAccessTime(userRDManFile);
DateTime lastModified = File.GetLastWriteTime(userRDManFile);
Dictionary<string, string> rdg = new Dictionary<string, string>(){
{ "RDCManFile", userRDManFile },
{ "Accessed", string.Format("{0}", lastAccessed) },
@@ -107,9 +107,9 @@ namespace winPEAS.KnownFileCreds
else
{
string userName = Environment.GetEnvironmentVariable("USERNAME");
string userRDManFile = string.Format("{0}\\AppData\\Local\\Microsoft\\Remote Desktop Connection Manager\\RDCMan.settings", System.Environment.GetEnvironmentVariable("USERPROFILE"));
string userRDManFile = string.Format("{0}\\AppData\\Local\\Microsoft\\Remote Desktop Connection Manager\\RDCMan.settings", Environment.GetEnvironmentVariable("USERPROFILE"));
if (System.IO.File.Exists(userRDManFile))
if (File.Exists(userRDManFile))
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(userRDManFile);
@@ -119,8 +119,8 @@ namespace winPEAS.KnownFileCreds
XmlNodeList items = filesToOpen[0].ChildNodes;
XmlNode node = items[0];
DateTime lastAccessed = System.IO.File.GetLastAccessTime(userRDManFile);
DateTime lastModified = System.IO.File.GetLastWriteTime(userRDManFile);
DateTime lastAccessed = File.GetLastAccessTime(userRDManFile);
DateTime lastModified = File.GetLastWriteTime(userRDManFile);
Dictionary<string, string> rdg = new Dictionary<string, string>(){
{ "RDCManFile", userRDManFile },
{ "Accessed", string.Format("{0}", lastAccessed) },

View File

@@ -209,7 +209,7 @@ namespace winPEAS.KnownFileCreds.SecurityPackages
{
return new NtlmHashInfo(
"NetNTLMv2",
FormatNetNtlmV2Hash(challenge, user, domain, SubArray(nt_resp, 0, 16), SubArray(nt_resp,16, nt_resp.Length - 16))
FormatNetNtlmV2Hash(challenge, user, domain, SubArray(nt_resp, 0, 16), SubArray(nt_resp, 16, nt_resp.Length - 16))
);
}
else

View File

@@ -24,11 +24,14 @@ namespace winPEAS.KnownFileCreds.SuperPutty
try
{
var path = $"{dir}\\Documents\\SuperPuTTY\\";
var files = Directory.EnumerateFiles(path, filter, SearchOption.TopDirectoryOnly);
foreach (var file in files)
if (Directory.Exists(path))
{
Beaprint.BadPrint($" {file}");
var files = Directory.EnumerateFiles(path, filter, SearchOption.TopDirectoryOnly);
foreach (var file in files)
{
Beaprint.BadPrint($" {file}");
}
}
}
catch (Exception)

View File

@@ -45,16 +45,18 @@ namespace winPEAS.KnownFileCreds.Vault
// Create dictionary to translate Guids to human readable elements
IntPtr guidAddress = vaultGuidPtr;
Dictionary<Guid, string> vaultSchema = new Dictionary<Guid, string>();
vaultSchema.Add(new Guid("2F1A6504-0641-44CF-8BB5-3612D865F2E5"), "Windows Secure Note");
vaultSchema.Add(new Guid("3CCD5499-87A8-4B10-A215-608888DD3B55"), "Windows Web Password Credential");
vaultSchema.Add(new Guid("154E23D0-C644-4E6F-8CE6-5069272F999F"), "Windows Credential Picker Protector");
vaultSchema.Add(new Guid("4BF4C442-9B8A-41A0-B380-DD4A704DDB28"), "Web Credentials");
vaultSchema.Add(new Guid("77BC582B-F0A6-4E15-4E80-61736B6F3B29"), "Windows Credentials");
vaultSchema.Add(new Guid("E69D7838-91B5-4FC9-89D5-230D4D4CC2BC"), "Windows Domain Certificate Credential");
vaultSchema.Add(new Guid("3E0E35BE-1B77-43E7-B873-AED901B6275B"), "Windows Domain Password Credential");
vaultSchema.Add(new Guid("3C886FF3-2669-4AA2-A8FB-3F6759A77548"), "Windows Extended Credential");
vaultSchema.Add(new Guid("00000000-0000-0000-0000-000000000000"), null);
Dictionary<Guid, string> vaultSchema = new Dictionary<Guid, string>
{
{ new Guid("2F1A6504-0641-44CF-8BB5-3612D865F2E5"), "Windows Secure Note" },
{ new Guid("3CCD5499-87A8-4B10-A215-608888DD3B55"), "Windows Web Password Credential" },
{ new Guid("154E23D0-C644-4E6F-8CE6-5069272F999F"), "Windows Credential Picker Protector" },
{ new Guid("4BF4C442-9B8A-41A0-B380-DD4A704DDB28"), "Web Credentials" },
{ new Guid("77BC582B-F0A6-4E15-4E80-61736B6F3B29"), "Windows Credentials" },
{ new Guid("E69D7838-91B5-4FC9-89D5-230D4D4CC2BC"), "Windows Domain Certificate Credential" },
{ new Guid("3E0E35BE-1B77-43E7-B873-AED901B6275B"), "Windows Domain Password Credential" },
{ new Guid("3C886FF3-2669-4AA2-A8FB-3F6759A77548"), "Windows Extended Credential" },
{ new Guid("00000000-0000-0000-0000-000000000000"), null }
};
for (int i = 0; i < vaultCount; i++)
{
@@ -167,7 +169,7 @@ namespace winPEAS.KnownFileCreds.Vault
vault_cred["PacakgeSid"] = string.Format("{0}", packageSid);
}
vault_cred["Credential"] = string.Format("{0}", cred);
vault_cred["Last Modified"] = string.Format("{0}", System.DateTime.FromFileTimeUtc((long)lastModified));
vault_cred["Last Modified"] = string.Format("{0}", DateTime.FromFileTimeUtc((long)lastModified));
results.Add(vault_cred);
}
}

View File

@@ -1,15 +1,14 @@
using System;
using System.Runtime.InteropServices;
using winPEAS.Native.Enums;
using winPEAS.TaskScheduler.TaskEditor.Native;
namespace winPEAS.Native.Classes
{
public partial class SafeTokenHandle : Microsoft.Win32.SafeHandles.SafeHandleZeroOrMinusOneIsInvalid
{
private const Int32 ERROR_NO_TOKEN = 0x000003F0;
private const Int32 ERROR_INSUFFICIENT_BUFFER = 122;
private static SafeTokenHandle currentProcessToken = null;
public partial class SafeTokenHandle : Microsoft.Win32.SafeHandles.SafeHandleZeroOrMinusOneIsInvalid
{
private const Int32 ERROR_NO_TOKEN = 0x000003F0;
private const Int32 ERROR_INSUFFICIENT_BUFFER = 122;
private static SafeTokenHandle currentProcessToken = null;
private SafeTokenHandle() : base(true) { }
@@ -20,102 +19,102 @@ namespace winPEAS.Native.Classes
protected override bool ReleaseHandle() => Kernel32.CloseHandle(handle);
public T GetInfo<T>(TOKEN_INFORMATION_CLASS type)
{
int cbSize = Marshal.SizeOf(typeof(T));
IntPtr pType = Marshal.AllocHGlobal(cbSize);
public T GetInfo<T>(TOKEN_INFORMATION_CLASS type)
{
int cbSize = Marshal.SizeOf(typeof(T));
IntPtr pType = Marshal.AllocHGlobal(cbSize);
try
{
// Retrieve token information.
if (!Advapi32.GetTokenInformation(this, type, pType, cbSize, out cbSize))
throw new System.ComponentModel.Win32Exception();
try
{
// Retrieve token information.
if (!Advapi32.GetTokenInformation(this, type, pType, cbSize, out cbSize))
throw new System.ComponentModel.Win32Exception();
// Marshal from native to .NET.
switch (type)
{
case TOKEN_INFORMATION_CLASS.TokenType:
case TOKEN_INFORMATION_CLASS.TokenImpersonationLevel:
case TOKEN_INFORMATION_CLASS.TokenSessionId:
case TOKEN_INFORMATION_CLASS.TokenSandBoxInert:
case TOKEN_INFORMATION_CLASS.TokenOrigin:
case TOKEN_INFORMATION_CLASS.TokenElevationType:
case TOKEN_INFORMATION_CLASS.TokenHasRestrictions:
case TOKEN_INFORMATION_CLASS.TokenUIAccess:
case TOKEN_INFORMATION_CLASS.TokenVirtualizationAllowed:
case TOKEN_INFORMATION_CLASS.TokenVirtualizationEnabled:
return (T)Convert.ChangeType(Marshal.ReadInt32(pType), typeof(T));
// Marshal from native to .NET.
switch (type)
{
case TOKEN_INFORMATION_CLASS.TokenType:
case TOKEN_INFORMATION_CLASS.TokenImpersonationLevel:
case TOKEN_INFORMATION_CLASS.TokenSessionId:
case TOKEN_INFORMATION_CLASS.TokenSandBoxInert:
case TOKEN_INFORMATION_CLASS.TokenOrigin:
case TOKEN_INFORMATION_CLASS.TokenElevationType:
case TOKEN_INFORMATION_CLASS.TokenHasRestrictions:
case TOKEN_INFORMATION_CLASS.TokenUIAccess:
case TOKEN_INFORMATION_CLASS.TokenVirtualizationAllowed:
case TOKEN_INFORMATION_CLASS.TokenVirtualizationEnabled:
return (T)Convert.ChangeType(Marshal.ReadInt32(pType), typeof(T));
case TOKEN_INFORMATION_CLASS.TokenLinkedToken:
return (T)Convert.ChangeType(Marshal.ReadIntPtr(pType), typeof(T));
case TOKEN_INFORMATION_CLASS.TokenLinkedToken:
return (T)Convert.ChangeType(Marshal.ReadIntPtr(pType), typeof(T));
case TOKEN_INFORMATION_CLASS.TokenUser:
case TOKEN_INFORMATION_CLASS.TokenGroups:
case TOKEN_INFORMATION_CLASS.TokenPrivileges:
case TOKEN_INFORMATION_CLASS.TokenOwner:
case TOKEN_INFORMATION_CLASS.TokenPrimaryGroup:
case TOKEN_INFORMATION_CLASS.TokenDefaultDacl:
case TOKEN_INFORMATION_CLASS.TokenSource:
case TOKEN_INFORMATION_CLASS.TokenStatistics:
case TOKEN_INFORMATION_CLASS.TokenRestrictedSids:
case TOKEN_INFORMATION_CLASS.TokenGroupsAndPrivileges:
case TOKEN_INFORMATION_CLASS.TokenElevation:
case TOKEN_INFORMATION_CLASS.TokenAccessInformation:
case TOKEN_INFORMATION_CLASS.TokenIntegrityLevel:
case TOKEN_INFORMATION_CLASS.TokenMandatoryPolicy:
case TOKEN_INFORMATION_CLASS.TokenLogonSid:
return (T)Marshal.PtrToStructure(pType, typeof(T));
case TOKEN_INFORMATION_CLASS.TokenUser:
case TOKEN_INFORMATION_CLASS.TokenGroups:
case TOKEN_INFORMATION_CLASS.TokenPrivileges:
case TOKEN_INFORMATION_CLASS.TokenOwner:
case TOKEN_INFORMATION_CLASS.TokenPrimaryGroup:
case TOKEN_INFORMATION_CLASS.TokenDefaultDacl:
case TOKEN_INFORMATION_CLASS.TokenSource:
case TOKEN_INFORMATION_CLASS.TokenStatistics:
case TOKEN_INFORMATION_CLASS.TokenRestrictedSids:
case TOKEN_INFORMATION_CLASS.TokenGroupsAndPrivileges:
case TOKEN_INFORMATION_CLASS.TokenElevation:
case TOKEN_INFORMATION_CLASS.TokenAccessInformation:
case TOKEN_INFORMATION_CLASS.TokenIntegrityLevel:
case TOKEN_INFORMATION_CLASS.TokenMandatoryPolicy:
case TOKEN_INFORMATION_CLASS.TokenLogonSid:
return (T)Marshal.PtrToStructure(pType, typeof(T));
case TOKEN_INFORMATION_CLASS.TokenSessionReference:
case TOKEN_INFORMATION_CLASS.TokenAuditPolicy:
default:
return default(T);
}
}
finally
{
Marshal.FreeHGlobal(pType);
}
}
case TOKEN_INFORMATION_CLASS.TokenSessionReference:
case TOKEN_INFORMATION_CLASS.TokenAuditPolicy:
default:
return default(T);
}
}
finally
{
Marshal.FreeHGlobal(pType);
}
}
public static SafeTokenHandle FromCurrentProcess(AccessTypes desiredAccess = AccessTypes.TokenDuplicate)
{
lock (currentProcessToken)
{
if (currentProcessToken == null)
currentProcessToken = FromProcess(Kernel32.GetCurrentProcess(), desiredAccess);
return currentProcessToken;
}
}
public static SafeTokenHandle FromCurrentProcess(AccessTypes desiredAccess = AccessTypes.TokenDuplicate)
{
lock (currentProcessToken)
{
if (currentProcessToken == null)
currentProcessToken = FromProcess(Kernel32.GetCurrentProcess(), desiredAccess);
return currentProcessToken;
}
}
public static SafeTokenHandle FromCurrentThread(AccessTypes desiredAccess = AccessTypes.TokenDuplicate, bool openAsSelf = true)
public static SafeTokenHandle FromCurrentThread(AccessTypes desiredAccess = AccessTypes.TokenDuplicate, bool openAsSelf = true)
=> FromThread(Kernel32.GetCurrentThread(), desiredAccess, openAsSelf);
public static SafeTokenHandle FromProcess(IntPtr hProcess, AccessTypes desiredAccess = AccessTypes.TokenDuplicate)
{
SafeTokenHandle val;
if (!Advapi32.OpenProcessToken(hProcess, desiredAccess, out val))
throw new System.ComponentModel.Win32Exception();
return val;
}
public static SafeTokenHandle FromProcess(IntPtr hProcess, AccessTypes desiredAccess = AccessTypes.TokenDuplicate)
{
SafeTokenHandle val;
if (!Advapi32.OpenProcessToken(hProcess, desiredAccess, out val))
throw new System.ComponentModel.Win32Exception();
return val;
}
public static SafeTokenHandle FromThread(IntPtr hThread, AccessTypes desiredAccess = AccessTypes.TokenDuplicate, bool openAsSelf = true)
{
SafeTokenHandle val;
if (!Advapi32.OpenThreadToken(hThread, desiredAccess, openAsSelf, out val))
{
if (Marshal.GetLastWin32Error() == ERROR_NO_TOKEN)
{
SafeTokenHandle pval = FromCurrentProcess();
if (!Advapi32.DuplicateTokenEx(pval, AccessTypes.TokenImpersonate | desiredAccess, IntPtr.Zero, SECURITY_IMPERSONATION_LEVEL.Impersonation, TokenType.TokenImpersonation, ref val))
throw new System.ComponentModel.Win32Exception();
if (!Advapi32.SetThreadToken(IntPtr.Zero, val))
throw new System.ComponentModel.Win32Exception();
}
else
throw new System.ComponentModel.Win32Exception();
}
return val;
}
}
public static SafeTokenHandle FromThread(IntPtr hThread, AccessTypes desiredAccess = AccessTypes.TokenDuplicate, bool openAsSelf = true)
{
SafeTokenHandle val;
if (!Advapi32.OpenThreadToken(hThread, desiredAccess, openAsSelf, out val))
{
if (Marshal.GetLastWin32Error() == ERROR_NO_TOKEN)
{
SafeTokenHandle pval = FromCurrentProcess();
if (!Advapi32.DuplicateTokenEx(pval, AccessTypes.TokenImpersonate | desiredAccess, IntPtr.Zero, SECURITY_IMPERSONATION_LEVEL.Impersonation, TokenType.TokenImpersonation, ref val))
throw new System.ComponentModel.Win32Exception();
if (!Advapi32.SetThreadToken(IntPtr.Zero, val))
throw new System.ComponentModel.Win32Exception();
}
else
throw new System.ComponentModel.Win32Exception();
}
return val;
}
}
}

View File

@@ -1,38 +1,38 @@
namespace winPEAS.Native.Enums
{
/// <summary>
/// Provides formats to use for input and output names for the DsCrackNames function.
/// </summary>
public enum DS_NAME_FORMAT
{
///<summary>Indicates the name is using an unknown name type. This format can impact performance because it forces the server to attempt to match all possible formats. Only use this value if the input format is unknown.</summary>
DS_UNKNOWN_NAME = 0,
/// <summary>
/// Provides formats to use for input and output names for the DsCrackNames function.
/// </summary>
public enum DS_NAME_FORMAT
{
///<summary>Indicates the name is using an unknown name type. This format can impact performance because it forces the server to attempt to match all possible formats. Only use this value if the input format is unknown.</summary>
DS_UNKNOWN_NAME = 0,
///<summary>Indicates that the fully qualified distinguished name is used. For example: "CN = someone, OU = Users, DC = Engineering, DC = Fabrikam, DC = Com"</summary>
DS_FQDN_1779_NAME = 1,
///<summary>Indicates that the fully qualified distinguished name is used. For example: "CN = someone, OU = Users, DC = Engineering, DC = Fabrikam, DC = Com"</summary>
DS_FQDN_1779_NAME = 1,
///<summary>Indicates a Windows NT 4.0 account name. For example: "Engineering\someone" The domain-only version includes two trailing backslashes (\\).</summary>
DS_NT4_ACCOUNT_NAME = 2,
///<summary>Indicates a Windows NT 4.0 account name. For example: "Engineering\someone" The domain-only version includes two trailing backslashes (\\).</summary>
DS_NT4_ACCOUNT_NAME = 2,
///<summary>Indicates a user-friendly display name, for example, Jeff Smith. The display name is not necessarily the same as relative distinguished name (RDN).</summary>
DS_DISPLAY_NAME = 3,
///<summary>Indicates a user-friendly display name, for example, Jeff Smith. The display name is not necessarily the same as relative distinguished name (RDN).</summary>
DS_DISPLAY_NAME = 3,
///<summary>Indicates a GUID string that the IIDFromString function returns. For example: "{4fa050f0-f561-11cf-bdd9-00aa003a77b6}"</summary>
DS_UNIQUE_ID_NAME = 6,
///<summary>Indicates a GUID string that the IIDFromString function returns. For example: "{4fa050f0-f561-11cf-bdd9-00aa003a77b6}"</summary>
DS_UNIQUE_ID_NAME = 6,
///<summary>Indicates a complete canonical name. For example: "engineering.fabrikam.com/software/someone" The domain-only version includes a trailing forward slash (/).</summary>
DS_CANONICAL_NAME = 7,
///<summary>Indicates a complete canonical name. For example: "engineering.fabrikam.com/software/someone" The domain-only version includes a trailing forward slash (/).</summary>
DS_CANONICAL_NAME = 7,
///<summary>Indicates that it is using the user principal name (UPN). For example: "someone@engineering.fabrikam.com"</summary>
DS_USER_PRINCIPAL_NAME = 8,
///<summary>Indicates that it is using the user principal name (UPN). For example: "someone@engineering.fabrikam.com"</summary>
DS_USER_PRINCIPAL_NAME = 8,
///<summary>This element is the same as DS_CANONICAL_NAME except that the rightmost forward slash (/) is replaced with a newline character (\n), even in a domain-only case. For example: "engineering.fabrikam.com/software\nsomeone"</summary>
DS_CANONICAL_NAME_EX = 9,
///<summary>This element is the same as DS_CANONICAL_NAME except that the rightmost forward slash (/) is replaced with a newline character (\n), even in a domain-only case. For example: "engineering.fabrikam.com/software\nsomeone"</summary>
DS_CANONICAL_NAME_EX = 9,
///<summary>Indicates it is using a generalized service principal name. For example: "www/www.fabrikam.com@fabrikam.com"</summary>
DS_SERVICE_PRINCIPAL_NAME = 10,
///<summary>Indicates it is using a generalized service principal name. For example: "www/www.fabrikam.com@fabrikam.com"</summary>
DS_SERVICE_PRINCIPAL_NAME = 10,
///<summary>Indicates a Security Identifier (SID) for the object. This can be either the current SID or a SID from the object SID history. The SID string can use either the standard string representation of a SID, or one of the string constants defined in Sddl.h. For more information about converting a binary SID into a SID string, see SID Strings. The following is an example of a SID string: "S-1-5-21-397955417-626881126-188441444-501"</summary>
DS_SID_OR_SID_HISTORY_NAME = 11,
}
///<summary>Indicates a Security Identifier (SID) for the object. This can be either the current SID or a SID from the object SID history. The SID string can use either the standard string representation of a SID, or one of the string constants defined in Sddl.h. For more information about converting a binary SID into a SID string, see SID Strings. The following is an example of a SID string: "S-1-5-21-397955417-626881126-188441444-501"</summary>
DS_SID_OR_SID_HISTORY_NAME = 11,
}
}

View File

@@ -1,6 +1,6 @@
namespace winPEAS.Native.Enums
{
public enum SECURITY_IMPERSONATION_LEVEL
public enum SECURITY_IMPERSONATION_LEVEL
{
Anonymous,
Identification,

View File

@@ -2,7 +2,7 @@
namespace winPEAS.Native.Enums
{
[Flags]
[Flags]
public enum ServerTypes : uint
{
Workstation = 0x00000001,

View File

@@ -1,6 +1,6 @@
namespace winPEAS.Native.Enums
{
public enum TOKEN_ELEVATION_TYPE
public enum TOKEN_ELEVATION_TYPE
{
Default = 1,
Full,

View File

@@ -1,6 +1,6 @@
namespace winPEAS.Native.Enums
{
public enum TOKEN_INFORMATION_CLASS
public enum TOKEN_INFORMATION_CLASS
{
TokenUser = 1,
TokenGroups,

View File

@@ -1,7 +1,5 @@
using System;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using winPEAS.Info.SystemInfo.NamedPipes;
namespace winPEAS.Native
{

View File

@@ -27,5 +27,5 @@ namespace winPEAS.Native
[DllImport("ntdsapi.dll", CharSet = CharSet.Auto)]
internal static extern uint DsUnBind(ref IntPtr phDS);
}
}
}

View File

@@ -2,7 +2,7 @@
namespace winPEAS.Native.Structs
{
[StructLayout(LayoutKind.Sequential, Pack = 1)]
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct LUID
{
public uint LowPart;

View File

@@ -3,7 +3,7 @@ using System.Runtime.InteropServices;
namespace winPEAS.Native.Structs
{
[StructLayout(LayoutKind.Sequential)]
[StructLayout(LayoutKind.Sequential)]
public struct SID_AND_ATTRIBUTES
{
public IntPtr Sid;

View File

@@ -3,7 +3,7 @@ using System.Runtime.InteropServices;
namespace winPEAS.Native.Structs
{
[StructLayout(LayoutKind.Sequential)]
[StructLayout(LayoutKind.Sequential)]
public struct TOKEN_ELEVATION
{
public Int32 TokenIsElevated;

View File

@@ -1,5 +1,4 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following

View File

@@ -2,93 +2,91 @@
using System.Collections.Generic;
using System.Linq;
using System.Security.AccessControl;
using System.Text;
using System.Threading.Tasks;
namespace winPEAS.TaskScheduler
{
/// <summary>Extensions for classes in the System.Security.AccessControl namespace.</summary>
public static class AccessControlExtension
{
/// <summary>Canonicalizes the specified Access Control List.</summary>
/// <param name="acl">The Access Control List.</param>
public static void Canonicalize(this RawAcl acl)
{
if (acl == null) throw new ArgumentNullException(nameof(acl));
/// <summary>Extensions for classes in the System.Security.AccessControl namespace.</summary>
public static class AccessControlExtension
{
/// <summary>Canonicalizes the specified Access Control List.</summary>
/// <param name="acl">The Access Control List.</param>
public static void Canonicalize(this RawAcl acl)
{
if (acl == null) throw new ArgumentNullException(nameof(acl));
// Extract aces to list
var aces = new System.Collections.Generic.List<GenericAce>(acl.Cast<GenericAce>());
// Extract aces to list
var aces = new System.Collections.Generic.List<GenericAce>(acl.Cast<GenericAce>());
// Sort aces based on canonical order
aces.Sort((a, b) => System.Collections.Generic.Comparer<byte>.Default.Compare(GetComparisonValue(a), GetComparisonValue(b)));
// Sort aces based on canonical order
aces.Sort((a, b) => Comparer<byte>.Default.Compare(GetComparisonValue(a), GetComparisonValue(b)));
// Add sorted aces back to ACL
while (acl.Count > 0) acl.RemoveAce(0);
var aceIndex = 0;
aces.ForEach(ace => acl.InsertAce(aceIndex++, ace));
}
// Add sorted aces back to ACL
while (acl.Count > 0) acl.RemoveAce(0);
var aceIndex = 0;
aces.ForEach(ace => acl.InsertAce(aceIndex++, ace));
}
/// <summary>Sort ACEs according to canonical form for this <see cref="ObjectSecurity"/>.</summary>
/// <param name="objectSecurity">The object security whose DiscretionaryAcl will be made canonical.</param>
public static void CanonicalizeAccessRules(this ObjectSecurity objectSecurity)
{
if (objectSecurity == null) throw new ArgumentNullException(nameof(objectSecurity));
if (objectSecurity.AreAccessRulesCanonical) return;
/// <summary>Sort ACEs according to canonical form for this <see cref="ObjectSecurity"/>.</summary>
/// <param name="objectSecurity">The object security whose DiscretionaryAcl will be made canonical.</param>
public static void CanonicalizeAccessRules(this ObjectSecurity objectSecurity)
{
if (objectSecurity == null) throw new ArgumentNullException(nameof(objectSecurity));
if (objectSecurity.AreAccessRulesCanonical) return;
// Get raw SD from objectSecurity and canonicalize DACL
var sd = new RawSecurityDescriptor(objectSecurity.GetSecurityDescriptorBinaryForm(), 0);
sd.DiscretionaryAcl.Canonicalize();
// Get raw SD from objectSecurity and canonicalize DACL
var sd = new RawSecurityDescriptor(objectSecurity.GetSecurityDescriptorBinaryForm(), 0);
sd.DiscretionaryAcl.Canonicalize();
// Convert SD back into objectSecurity
objectSecurity.SetSecurityDescriptorBinaryForm(sd.GetBinaryForm());
}
// Convert SD back into objectSecurity
objectSecurity.SetSecurityDescriptorBinaryForm(sd.GetBinaryForm());
}
/// <summary>Returns an array of byte values that represents the information contained in this <see cref="GenericSecurityDescriptor"/> object.</summary>
/// <param name="sd">The <see cref="GenericSecurityDescriptor"/> object.</param>
/// <returns>The byte array into which the contents of the <see cref="GenericSecurityDescriptor"/> is marshaled.</returns>
public static byte[] GetBinaryForm(this GenericSecurityDescriptor sd)
{
if (sd == null) throw new ArgumentNullException(nameof(sd));
var bin = new byte[sd.BinaryLength];
sd.GetBinaryForm(bin, 0);
return bin;
}
/// <summary>Returns an array of byte values that represents the information contained in this <see cref="GenericSecurityDescriptor"/> object.</summary>
/// <param name="sd">The <see cref="GenericSecurityDescriptor"/> object.</param>
/// <returns>The byte array into which the contents of the <see cref="GenericSecurityDescriptor"/> is marshaled.</returns>
public static byte[] GetBinaryForm(this GenericSecurityDescriptor sd)
{
if (sd == null) throw new ArgumentNullException(nameof(sd));
var bin = new byte[sd.BinaryLength];
sd.GetBinaryForm(bin, 0);
return bin;
}
// A canonical ACL must have ACES sorted according to the following order:
// 1. Access-denied on the object
// 2. Access-denied on a child or property
// 3. Access-allowed on the object
// 4. Access-allowed on a child or property
// 5. All inherited ACEs
private static byte GetComparisonValue(GenericAce ace)
{
if ((ace.AceFlags & AceFlags.Inherited) != 0)
return 5;
switch (ace.AceType)
{
case AceType.AccessDenied:
case AceType.AccessDeniedCallback:
case AceType.SystemAudit:
case AceType.SystemAlarm:
case AceType.SystemAuditCallback:
case AceType.SystemAlarmCallback:
return 0;
case AceType.AccessDeniedObject:
case AceType.AccessDeniedCallbackObject:
case AceType.SystemAuditObject:
case AceType.SystemAlarmObject:
case AceType.SystemAuditCallbackObject:
case AceType.SystemAlarmCallbackObject:
return 1;
case AceType.AccessAllowed:
case AceType.AccessAllowedCallback:
return 2;
case AceType.AccessAllowedObject:
case AceType.AccessAllowedCallbackObject:
return 3;
default:
return 4;
}
}
}
// A canonical ACL must have ACES sorted according to the following order:
// 1. Access-denied on the object
// 2. Access-denied on a child or property
// 3. Access-allowed on the object
// 4. Access-allowed on a child or property
// 5. All inherited ACEs
private static byte GetComparisonValue(GenericAce ace)
{
if ((ace.AceFlags & AceFlags.Inherited) != 0)
return 5;
switch (ace.AceType)
{
case AceType.AccessDenied:
case AceType.AccessDeniedCallback:
case AceType.SystemAudit:
case AceType.SystemAlarm:
case AceType.SystemAuditCallback:
case AceType.SystemAlarmCallback:
return 0;
case AceType.AccessDeniedObject:
case AceType.AccessDeniedCallbackObject:
case AceType.SystemAuditObject:
case AceType.SystemAlarmObject:
case AceType.SystemAuditCallbackObject:
case AceType.SystemAlarmCallbackObject:
return 1;
case AceType.AccessAllowed:
case AceType.AccessAllowedCallback:
return 2;
case AceType.AccessAllowedObject:
case AceType.AccessAllowedCallbackObject:
return 3;
default:
return 4;
}
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,27 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace winPEAS.TaskScheduler
{
internal class CultureSwitcher : IDisposable
{
private readonly System.Globalization.CultureInfo cur, curUI;
internal class CultureSwitcher : IDisposable
{
private readonly System.Globalization.CultureInfo cur, curUI;
public CultureSwitcher([NotNull] System.Globalization.CultureInfo culture)
{
cur = Thread.CurrentThread.CurrentCulture;
curUI = Thread.CurrentThread.CurrentUICulture;
Thread.CurrentThread.CurrentCulture = Thread.CurrentThread.CurrentUICulture = culture;
}
public CultureSwitcher([NotNull] System.Globalization.CultureInfo culture)
{
cur = Thread.CurrentThread.CurrentCulture;
curUI = Thread.CurrentThread.CurrentUICulture;
Thread.CurrentThread.CurrentCulture = Thread.CurrentThread.CurrentUICulture = culture;
}
public void Dispose()
{
Thread.CurrentThread.CurrentCulture = cur;
Thread.CurrentThread.CurrentUICulture = curUI;
}
}
public void Dispose()
{
Thread.CurrentThread.CurrentCulture = cur;
Thread.CurrentThread.CurrentUICulture = curUI;
}
}
}

View File

@@ -8,72 +8,72 @@ namespace winPEAS.TaskScheduler
/// Functions to provide localized strings for enumerated types and values.
/// </summary>
public static class TaskEnumGlobalizer
{
/// <summary>
/// Gets a string representing the localized value of the provided enum.
/// </summary>
/// <param name="enumValue">The enum value.</param>
/// <returns>A localized string, if available.</returns>
public static string GetString(object enumValue)
{
switch (enumValue.GetType().Name)
{
case "DaysOfTheWeek":
return GetCultureEquivalentString((DaysOfTheWeek)enumValue);
case "MonthsOfTheYear":
return GetCultureEquivalentString((MonthsOfTheYear)enumValue);
case "TaskTriggerType":
return BuildEnumString("TriggerType", enumValue);
case "WhichWeek":
return BuildEnumString("WW", enumValue);
case "TaskActionType":
return BuildEnumString("ActionType", enumValue);
case "TaskState":
return BuildEnumString("TaskState", enumValue);
}
return enumValue.ToString();
}
{
/// <summary>
/// Gets a string representing the localized value of the provided enum.
/// </summary>
/// <param name="enumValue">The enum value.</param>
/// <returns>A localized string, if available.</returns>
public static string GetString(object enumValue)
{
switch (enumValue.GetType().Name)
{
case "DaysOfTheWeek":
return GetCultureEquivalentString((DaysOfTheWeek)enumValue);
case "MonthsOfTheYear":
return GetCultureEquivalentString((MonthsOfTheYear)enumValue);
case "TaskTriggerType":
return BuildEnumString("TriggerType", enumValue);
case "WhichWeek":
return BuildEnumString("WW", enumValue);
case "TaskActionType":
return BuildEnumString("ActionType", enumValue);
case "TaskState":
return BuildEnumString("TaskState", enumValue);
}
return enumValue.ToString();
}
private static string GetCultureEquivalentString(DaysOfTheWeek val)
{
if (val == DaysOfTheWeek.AllDays)
return Properties.Resources.DOWAllDays;
private static string GetCultureEquivalentString(DaysOfTheWeek val)
{
if (val == DaysOfTheWeek.AllDays)
return Properties.Resources.DOWAllDays;
var s = new List<string>(7);
var vals = Enum.GetValues(val.GetType());
for (var i = 0; i < vals.Length - 1; i++)
{
if ((val & (DaysOfTheWeek)vals.GetValue(i)) > 0)
s.Add(DateTimeFormatInfo.CurrentInfo.GetDayName((DayOfWeek)i));
}
var s = new List<string>(7);
var vals = Enum.GetValues(val.GetType());
for (var i = 0; i < vals.Length - 1; i++)
{
if ((val & (DaysOfTheWeek)vals.GetValue(i)) > 0)
s.Add(DateTimeFormatInfo.CurrentInfo.GetDayName((DayOfWeek)i));
}
return string.Join(Properties.Resources.ListSeparator, s.ToArray());
}
return string.Join(Properties.Resources.ListSeparator, s.ToArray());
}
private static string GetCultureEquivalentString(MonthsOfTheYear val)
{
if (val == MonthsOfTheYear.AllMonths)
return Properties.Resources.MOYAllMonths;
private static string GetCultureEquivalentString(MonthsOfTheYear val)
{
if (val == MonthsOfTheYear.AllMonths)
return Properties.Resources.MOYAllMonths;
var s = new List<string>(12);
var vals = Enum.GetValues(val.GetType());
for (var i = 0; i < vals.Length - 1; i++)
{
if ((val & (MonthsOfTheYear)vals.GetValue(i)) > 0)
s.Add(DateTimeFormatInfo.CurrentInfo.GetMonthName(i + 1));
}
var s = new List<string>(12);
var vals = Enum.GetValues(val.GetType());
for (var i = 0; i < vals.Length - 1; i++)
{
if ((val & (MonthsOfTheYear)vals.GetValue(i)) > 0)
s.Add(DateTimeFormatInfo.CurrentInfo.GetMonthName(i + 1));
}
return string.Join(Properties.Resources.ListSeparator, s.ToArray());
}
return string.Join(Properties.Resources.ListSeparator, s.ToArray());
}
private static string BuildEnumString(string preface, object enumValue)
{
var vals = enumValue.ToString().Split(new[] { ", " }, StringSplitOptions.None);
if (vals.Length == 0)
return string.Empty;
for (var i = 0; i < vals.Length; i++)
vals[i] = Properties.Resources.ResourceManager.GetString(preface + vals[i]);
return string.Join(Properties.Resources.ListSeparator, vals);
}
}
private static string BuildEnumString(string preface, object enumValue)
{
var vals = enumValue.ToString().Split(new[] { ", " }, StringSplitOptions.None);
if (vals.Length == 0)
return string.Empty;
for (var i = 0; i < vals.Length; i++)
vals[i] = Properties.Resources.ResourceManager.GetString(preface + vals[i]);
return string.Join(Properties.Resources.ListSeparator, vals);
}
}
}

View File

@@ -1,150 +1,147 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace winPEAS.TaskScheduler
{
internal static class EnumUtil
{
public static void CheckIsEnum<T>(bool checkHasFlags = false)
{
if (!typeof(T).IsEnum)
throw new ArgumentException($"Type '{typeof(T).FullName}' is not an enum");
if (checkHasFlags && !IsFlags<T>())
throw new ArgumentException($"Type '{typeof(T).FullName}' doesn't have the 'Flags' attribute");
}
internal static class EnumUtil
{
public static void CheckIsEnum<T>(bool checkHasFlags = false)
{
if (!typeof(T).IsEnum)
throw new ArgumentException($"Type '{typeof(T).FullName}' is not an enum");
if (checkHasFlags && !IsFlags<T>())
throw new ArgumentException($"Type '{typeof(T).FullName}' doesn't have the 'Flags' attribute");
}
public static bool IsFlags<T>() => Attribute.IsDefined(typeof(T), typeof(FlagsAttribute));
public static bool IsFlags<T>() => Attribute.IsDefined(typeof(T), typeof(FlagsAttribute));
public static void CheckHasValue<T>(T value, string argName = null)
{
CheckIsEnum<T>();
if (IsFlags<T>())
{
var allFlags = 0L;
foreach (T flag in Enum.GetValues(typeof(T)))
allFlags |= Convert.ToInt64(flag);
if ((allFlags & Convert.ToInt64(value)) != 0L)
return;
}
else if (Enum.IsDefined(typeof(T), value))
return;
throw new InvalidEnumArgumentException(argName ?? "value", Convert.ToInt32(value), typeof(T));
}
public static void CheckHasValue<T>(T value, string argName = null)
{
CheckIsEnum<T>();
if (IsFlags<T>())
{
var allFlags = 0L;
foreach (T flag in Enum.GetValues(typeof(T)))
allFlags |= Convert.ToInt64(flag);
if ((allFlags & Convert.ToInt64(value)) != 0L)
return;
}
else if (Enum.IsDefined(typeof(T), value))
return;
throw new InvalidEnumArgumentException(argName ?? "value", Convert.ToInt32(value), typeof(T));
}
public static byte BitPosition<T>(this T flags) where T : struct, IConvertible
{
CheckIsEnum<T>(true);
var flagValue = Convert.ToInt64(flags);
if (flagValue == 0) throw new ArgumentException("The flag value is zero and has no bit position.");
var r = Math.Log(flagValue, 2);
if (r % 1 > 0) throw new ArithmeticException("The flag value has more than a single bit set.");
return Convert.ToByte(r);
}
public static byte BitPosition<T>(this T flags) where T : struct, IConvertible
{
CheckIsEnum<T>(true);
var flagValue = Convert.ToInt64(flags);
if (flagValue == 0) throw new ArgumentException("The flag value is zero and has no bit position.");
var r = Math.Log(flagValue, 2);
if (r % 1 > 0) throw new ArithmeticException("The flag value has more than a single bit set.");
return Convert.ToByte(r);
}
public static bool IsFlagSet<T>(this T flags, T flag) where T : struct, IConvertible
{
CheckIsEnum<T>(true);
var flagValue = Convert.ToInt64(flag);
return (Convert.ToInt64(flags) & flagValue) == flagValue;
}
public static bool IsFlagSet<T>(this T flags, T flag) where T : struct, IConvertible
{
CheckIsEnum<T>(true);
var flagValue = Convert.ToInt64(flag);
return (Convert.ToInt64(flags) & flagValue) == flagValue;
}
public static bool IsValidFlagValue<T>(this T flags) where T : struct, IConvertible
{
CheckIsEnum<T>(true);
var found = 0L;
foreach (T flag in Enum.GetValues(typeof(T)))
{
if (flags.IsFlagSet(flag))
found |= Convert.ToInt64(flag);
}
return found == Convert.ToInt64(flags);
}
public static bool IsValidFlagValue<T>(this T flags) where T : struct, IConvertible
{
CheckIsEnum<T>(true);
var found = 0L;
foreach (T flag in Enum.GetValues(typeof(T)))
{
if (flags.IsFlagSet(flag))
found |= Convert.ToInt64(flag);
}
return found == Convert.ToInt64(flags);
}
public static void SetFlags<T>(ref T flags, T flag, bool set = true) where T : struct, IConvertible
{
CheckIsEnum<T>(true);
var flagsValue = Convert.ToInt64(flags);
var flagValue = Convert.ToInt64(flag);
if (set)
flagsValue |= flagValue;
else
flagsValue &= (~flagValue);
flags = (T)Enum.ToObject(typeof(T), flagsValue);
}
public static void SetFlags<T>(ref T flags, T flag, bool set = true) where T : struct, IConvertible
{
CheckIsEnum<T>(true);
var flagsValue = Convert.ToInt64(flags);
var flagValue = Convert.ToInt64(flag);
if (set)
flagsValue |= flagValue;
else
flagsValue &= (~flagValue);
flags = (T)Enum.ToObject(typeof(T), flagsValue);
}
public static T SetFlags<T>(this T flags, T flag, bool set = true) where T : struct, IConvertible
{
var ret = flags;
SetFlags<T>(ref ret, flag, set);
return ret;
}
public static T SetFlags<T>(this T flags, T flag, bool set = true) where T : struct, IConvertible
{
var ret = flags;
SetFlags<T>(ref ret, flag, set);
return ret;
}
public static T ClearFlags<T>(this T flags, T flag) where T : struct, IConvertible => flags.SetFlags(flag, false);
public static T ClearFlags<T>(this T flags, T flag) where T : struct, IConvertible => flags.SetFlags(flag, false);
public static IEnumerable<T> GetFlags<T>(this T value) where T : struct, IConvertible
{
CheckIsEnum<T>(true);
foreach (T flag in Enum.GetValues(typeof(T)))
{
if (value.IsFlagSet(flag))
yield return flag;
}
}
public static IEnumerable<T> GetFlags<T>(this T value) where T : struct, IConvertible
{
CheckIsEnum<T>(true);
foreach (T flag in Enum.GetValues(typeof(T)))
{
if (value.IsFlagSet(flag))
yield return flag;
}
}
public static T CombineFlags<T>(this IEnumerable<T> flags) where T : struct, IConvertible
{
CheckIsEnum<T>(true);
long lValue = 0;
foreach (var flag in flags)
{
var lFlag = Convert.ToInt64(flag);
lValue |= lFlag;
}
return (T)Enum.ToObject(typeof(T), lValue);
}
public static T CombineFlags<T>(this IEnumerable<T> flags) where T : struct, IConvertible
{
CheckIsEnum<T>(true);
long lValue = 0;
foreach (var flag in flags)
{
var lFlag = Convert.ToInt64(flag);
lValue |= lFlag;
}
return (T)Enum.ToObject(typeof(T), lValue);
}
public static string GetDescription<T>(this T value) where T : struct, IConvertible
{
CheckIsEnum<T>();
var name = Enum.GetName(typeof(T), value);
if (name != null)
{
var field = typeof(T).GetField(name);
if (field != null)
{
var attr = Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) as DescriptionAttribute;
if (attr != null)
{
return attr.Description;
}
}
}
return null;
}
public static string GetDescription<T>(this T value) where T : struct, IConvertible
{
CheckIsEnum<T>();
var name = Enum.GetName(typeof(T), value);
if (name != null)
{
var field = typeof(T).GetField(name);
if (field != null)
{
var attr = Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) as DescriptionAttribute;
if (attr != null)
{
return attr.Description;
}
}
}
return null;
}
/// <summary>
/// Converts the string representation of the name or numeric value of one or more enumerated constants to an equivalent enumerated object or returns the value of <paramref name="defaultVal"/>. If <paramref name="defaultVal"/> is undefined, it returns the first declared item in the enumerated type.
/// </summary>
/// <typeparam name="TEnum">The enumeration type to which to convert <paramref name="value"/>.</typeparam>
/// <param name="value">The string representation of the enumeration name or underlying value to convert.</param>
/// <param name="ignoreCase"><c>true</c> to ignore case; <c>false</c> to consider case.</param>
/// <param name="defaultVal">The default value.</param>
/// <returns>An object of type <typeparamref name="TEnum"/> whose value is represented by value.</returns>
public static TEnum TryParse<TEnum>(string value, bool ignoreCase = false, TEnum defaultVal = default(TEnum)) where TEnum : struct, IConvertible
{
CheckIsEnum<TEnum>();
try { return (TEnum)Enum.Parse(typeof(TEnum), value, ignoreCase); } catch { }
if (!Enum.IsDefined(typeof(TEnum), defaultVal))
{
var v = Enum.GetValues(typeof(TEnum));
if (v != null && v.Length > 0)
return (TEnum)v.GetValue(0);
}
return defaultVal;
}
}
/// <summary>
/// Converts the string representation of the name or numeric value of one or more enumerated constants to an equivalent enumerated object or returns the value of <paramref name="defaultVal"/>. If <paramref name="defaultVal"/> is undefined, it returns the first declared item in the enumerated type.
/// </summary>
/// <typeparam name="TEnum">The enumeration type to which to convert <paramref name="value"/>.</typeparam>
/// <param name="value">The string representation of the enumeration name or underlying value to convert.</param>
/// <param name="ignoreCase"><c>true</c> to ignore case; <c>false</c> to consider case.</param>
/// <param name="defaultVal">The default value.</param>
/// <returns>An object of type <typeparamref name="TEnum"/> whose value is represented by value.</returns>
public static TEnum TryParse<TEnum>(string value, bool ignoreCase = false, TEnum defaultVal = default(TEnum)) where TEnum : struct, IConvertible
{
CheckIsEnum<TEnum>();
try { return (TEnum)Enum.Parse(typeof(TEnum), value, ignoreCase); } catch { }
if (!Enum.IsDefined(typeof(TEnum), defaultVal))
{
var v = Enum.GetValues(typeof(TEnum));
if (v != null && v.Length > 0)
return (TEnum)v.GetValue(0);
}
return defaultVal;
}
}
}

View File

@@ -1,131 +1,127 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.Serialization;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Threading.Tasks;
namespace winPEAS.TaskScheduler
{
/// <summary>
/// Abstract class for throwing a method specific exception.
/// </summary>
[DebuggerStepThrough, Serializable]
[PublicAPI]
public abstract class TSNotSupportedException : Exception
{
/// <summary>Defines the minimum supported version for the action not allowed by this exception.</summary>
protected readonly TaskCompatibility min;
private readonly string myMessage;
/// <summary>
/// Abstract class for throwing a method specific exception.
/// </summary>
[DebuggerStepThrough, Serializable]
[PublicAPI]
public abstract class TSNotSupportedException : Exception
{
/// <summary>Defines the minimum supported version for the action not allowed by this exception.</summary>
protected readonly TaskCompatibility min;
private readonly string myMessage;
/// <summary>
/// Initializes a new instance of the <see cref="TSNotSupportedException"/> class.
/// </summary>
/// <param name="serializationInfo">The serialization information.</param>
/// <param name="streamingContext">The streaming context.</param>
protected TSNotSupportedException(SerializationInfo serializationInfo, StreamingContext streamingContext)
: base(serializationInfo, streamingContext)
{
try { min = (TaskCompatibility)serializationInfo.GetValue("min", typeof(TaskCompatibility)); }
catch { min = TaskCompatibility.V1; }
}
/// <summary>
/// Initializes a new instance of the <see cref="TSNotSupportedException"/> class.
/// </summary>
/// <param name="serializationInfo">The serialization information.</param>
/// <param name="streamingContext">The streaming context.</param>
protected TSNotSupportedException(SerializationInfo serializationInfo, StreamingContext streamingContext)
: base(serializationInfo, streamingContext)
{
try { min = (TaskCompatibility)serializationInfo.GetValue("min", typeof(TaskCompatibility)); }
catch { min = TaskCompatibility.V1; }
}
internal TSNotSupportedException(TaskCompatibility minComp)
{
min = minComp;
var stackTrace = new StackTrace();
var stackFrame = stackTrace.GetFrame(2);
var methodBase = stackFrame.GetMethod();
myMessage = $"{methodBase.DeclaringType?.Name}.{methodBase.Name} is not supported on {LibName}";
}
internal TSNotSupportedException(TaskCompatibility minComp)
{
min = minComp;
var stackTrace = new StackTrace();
var stackFrame = stackTrace.GetFrame(2);
var methodBase = stackFrame.GetMethod();
myMessage = $"{methodBase.DeclaringType?.Name}.{methodBase.Name} is not supported on {LibName}";
}
internal TSNotSupportedException(string message, TaskCompatibility minComp)
{
myMessage = message;
min = minComp;
}
internal TSNotSupportedException(string message, TaskCompatibility minComp)
{
myMessage = message;
min = minComp;
}
/// <summary>
/// Gets a message that describes the current exception.
/// </summary>
public override string Message => myMessage;
/// <summary>
/// Gets a message that describes the current exception.
/// </summary>
public override string Message => myMessage;
/// <summary>
/// Gets the minimum supported TaskScheduler version required for this method or property.
/// </summary>
public TaskCompatibility MinimumSupportedVersion => min;
/// <summary>
/// Gets the minimum supported TaskScheduler version required for this method or property.
/// </summary>
public TaskCompatibility MinimumSupportedVersion => min;
internal abstract string LibName { get; }
internal abstract string LibName { get; }
/// <summary>
/// Gets the object data.
/// </summary>
/// <param name="info">The information.</param>
/// <param name="context">The context.</param>
[SecurityCritical, SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
if (info == null)
throw new ArgumentNullException(nameof(info));
info.AddValue("min", min);
base.GetObjectData(info, context);
}
}
/// <summary>
/// Gets the object data.
/// </summary>
/// <param name="info">The information.</param>
/// <param name="context">The context.</param>
[SecurityCritical, SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
if (info == null)
throw new ArgumentNullException(nameof(info));
info.AddValue("min", min);
base.GetObjectData(info, context);
}
}
/// <summary>
/// Thrown when the calling method is not supported by Task Scheduler 1.0.
/// </summary>
[DebuggerStepThrough, Serializable]
public class NotV1SupportedException : TSNotSupportedException
{
/// <summary>
/// Initializes a new instance of the <see cref="NotV1SupportedException" /> class.
/// </summary>
/// <param name="serializationInfo">The serialization information.</param>
/// <param name="streamingContext">The streaming context.</param>
protected NotV1SupportedException(SerializationInfo serializationInfo, StreamingContext streamingContext) : base(serializationInfo, streamingContext) { }
internal NotV1SupportedException() : base(TaskCompatibility.V2) { }
/// <summary>
/// Initializes a new instance of the <see cref="NotV1SupportedException" /> class.
/// </summary>
/// <param name="message">The message.</param>
public NotV1SupportedException(string message) : base(message, TaskCompatibility.V2) { }
internal override string LibName => "Task Scheduler 1.0";
}
/// <summary>
/// Thrown when the calling method is not supported by Task Scheduler 1.0.
/// </summary>
[DebuggerStepThrough, Serializable]
public class NotV1SupportedException : TSNotSupportedException
{
/// <summary>
/// Initializes a new instance of the <see cref="NotV1SupportedException" /> class.
/// </summary>
/// <param name="serializationInfo">The serialization information.</param>
/// <param name="streamingContext">The streaming context.</param>
protected NotV1SupportedException(SerializationInfo serializationInfo, StreamingContext streamingContext) : base(serializationInfo, streamingContext) { }
internal NotV1SupportedException() : base(TaskCompatibility.V2) { }
/// <summary>
/// Initializes a new instance of the <see cref="NotV1SupportedException" /> class.
/// </summary>
/// <param name="message">The message.</param>
public NotV1SupportedException(string message) : base(message, TaskCompatibility.V2) { }
internal override string LibName => "Task Scheduler 1.0";
}
/// <summary>
/// Thrown when the calling method is not supported by Task Scheduler 2.0.
/// </summary>
[DebuggerStepThrough, Serializable]
public class NotV2SupportedException : TSNotSupportedException
{
/// <summary>
/// Initializes a new instance of the <see cref="NotV1SupportedException" /> class.
/// </summary>
/// <param name="serializationInfo">The serialization information.</param>
/// <param name="streamingContext">The streaming context.</param>
protected NotV2SupportedException(SerializationInfo serializationInfo, StreamingContext streamingContext) : base(serializationInfo, streamingContext) { }
internal NotV2SupportedException() : base(TaskCompatibility.V1) { }
internal NotV2SupportedException(string message) : base(message, TaskCompatibility.V1) { }
internal override string LibName => "Task Scheduler 2.0 (1.2)";
}
/// <summary>
/// Thrown when the calling method is not supported by Task Scheduler 2.0.
/// </summary>
[DebuggerStepThrough, Serializable]
public class NotV2SupportedException : TSNotSupportedException
{
/// <summary>
/// Initializes a new instance of the <see cref="NotV1SupportedException" /> class.
/// </summary>
/// <param name="serializationInfo">The serialization information.</param>
/// <param name="streamingContext">The streaming context.</param>
protected NotV2SupportedException(SerializationInfo serializationInfo, StreamingContext streamingContext) : base(serializationInfo, streamingContext) { }
internal NotV2SupportedException() : base(TaskCompatibility.V1) { }
internal NotV2SupportedException(string message) : base(message, TaskCompatibility.V1) { }
internal override string LibName => "Task Scheduler 2.0 (1.2)";
}
/// <summary>
/// Thrown when the calling method is not supported by Task Scheduler versions prior to the one specified.
/// </summary>
[DebuggerStepThrough, Serializable]
public class NotSupportedPriorToException : TSNotSupportedException
{
/// <summary>
/// Initializes a new instance of the <see cref="NotV1SupportedException" /> class.
/// </summary>
/// <param name="serializationInfo">The serialization information.</param>
/// <param name="streamingContext">The streaming context.</param>
protected NotSupportedPriorToException(SerializationInfo serializationInfo, StreamingContext streamingContext) : base(serializationInfo, streamingContext) { }
internal NotSupportedPriorToException(TaskCompatibility supportedVersion) : base(supportedVersion) { }
internal override string LibName => $"Task Scheduler versions prior to 2.{((int)min) - 2} (1.{(int)min})";
}
/// <summary>
/// Thrown when the calling method is not supported by Task Scheduler versions prior to the one specified.
/// </summary>
[DebuggerStepThrough, Serializable]
public class NotSupportedPriorToException : TSNotSupportedException
{
/// <summary>
/// Initializes a new instance of the <see cref="NotV1SupportedException" /> class.
/// </summary>
/// <param name="serializationInfo">The serialization information.</param>
/// <param name="streamingContext">The streaming context.</param>
protected NotSupportedPriorToException(SerializationInfo serializationInfo, StreamingContext streamingContext) : base(serializationInfo, streamingContext) { }
internal NotSupportedPriorToException(TaskCompatibility supportedVersion) : base(supportedVersion) { }
internal override string LibName => $"Task Scheduler versions prior to 2.{((int)min) - 2} (1.{(int)min})";
}
}

View File

@@ -1,139 +1,135 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace winPEAS.TaskScheduler
{
/// <summary>Extensions related to <c>System.Reflection</c></summary>
internal static class ReflectionHelper
{
/// <summary>Loads a type from a named assembly.</summary>
/// <param name="typeName">Name of the type.</param>
/// <param name="asmRef">The name or path of the file that contains the manifest of the assembly.</param>
/// <returns>The <see cref="Type"/> reference, or <c>null</c> if type or assembly not found.</returns>
public static Type LoadType(string typeName, string asmRef)
{
Type ret = null;
if (!TryGetType(Assembly.GetCallingAssembly(), typeName, ref ret))
if (!TryGetType(asmRef, typeName, ref ret))
if (!TryGetType(Assembly.GetExecutingAssembly(), typeName, ref ret))
TryGetType(Assembly.GetEntryAssembly(), typeName, ref ret);
return ret;
}
/// <summary>Extensions related to <c>System.Reflection</c></summary>
internal static class ReflectionHelper
{
/// <summary>Loads a type from a named assembly.</summary>
/// <param name="typeName">Name of the type.</param>
/// <param name="asmRef">The name or path of the file that contains the manifest of the assembly.</param>
/// <returns>The <see cref="Type"/> reference, or <c>null</c> if type or assembly not found.</returns>
public static Type LoadType(string typeName, string asmRef)
{
Type ret = null;
if (!TryGetType(Assembly.GetCallingAssembly(), typeName, ref ret))
if (!TryGetType(asmRef, typeName, ref ret))
if (!TryGetType(Assembly.GetExecutingAssembly(), typeName, ref ret))
TryGetType(Assembly.GetEntryAssembly(), typeName, ref ret);
return ret;
}
/// <summary>Tries the retrieve a <see cref="Type"/> reference from an assembly.</summary>
/// <param name="typeName">Name of the type.</param>
/// <param name="asmRef">The assembly reference name from which to load the type.</param>
/// <param name="type">The <see cref="Type"/> reference, if found.</param>
/// <returns><c>true</c> if the type was found in the assembly; otherwise, <c>false</c>.</returns>
private static bool TryGetType(string asmRef, string typeName, ref Type type)
{
try
{
if (System.IO.File.Exists(asmRef))
return TryGetType(Assembly.LoadFrom(asmRef), typeName, ref type);
}
catch { }
return false;
}
/// <summary>Tries the retrieve a <see cref="Type"/> reference from an assembly.</summary>
/// <param name="typeName">Name of the type.</param>
/// <param name="asmRef">The assembly reference name from which to load the type.</param>
/// <param name="type">The <see cref="Type"/> reference, if found.</param>
/// <returns><c>true</c> if the type was found in the assembly; otherwise, <c>false</c>.</returns>
private static bool TryGetType(string asmRef, string typeName, ref Type type)
{
try
{
if (System.IO.File.Exists(asmRef))
return TryGetType(Assembly.LoadFrom(asmRef), typeName, ref type);
}
catch { }
return false;
}
/// <summary>Tries the retrieve a <see cref="Type"/> reference from an assembly.</summary>
/// <param name="typeName">Name of the type.</param>
/// <param name="asm">The assembly from which to load the type.</param>
/// <param name="type">The <see cref="Type"/> reference, if found.</param>
/// <returns><c>true</c> if the type was found in the assembly; otherwise, <c>false</c>.</returns>
private static bool TryGetType(Assembly asm, string typeName, ref Type type)
{
if (asm != null)
{
try
{
type = asm.GetType(typeName, false, false);
return (type != null);
}
catch { }
}
return false;
}
/// <summary>Tries the retrieve a <see cref="Type"/> reference from an assembly.</summary>
/// <param name="typeName">Name of the type.</param>
/// <param name="asm">The assembly from which to load the type.</param>
/// <param name="type">The <see cref="Type"/> reference, if found.</param>
/// <returns><c>true</c> if the type was found in the assembly; otherwise, <c>false</c>.</returns>
private static bool TryGetType(Assembly asm, string typeName, ref Type type)
{
if (asm != null)
{
try
{
type = asm.GetType(typeName, false, false);
return (type != null);
}
catch { }
}
return false;
}
/// <summary>Invokes a named method on a created instance of a type with parameters.</summary>
/// <typeparam name="T">The expected type of the method's return value.</typeparam>
/// <param name="type">The type to be instantiated and then used to invoke the method. This method assumes the type has a default public constructor.</param>
/// <param name="methodName">Name of the method.</param>
/// <param name="args">The arguments to provide to the method invocation.</param>
/// <returns>The value returned from the method.</returns>
public static T InvokeMethod<T>(Type type, string methodName, params object[] args)
{
object o = Activator.CreateInstance(type);
return InvokeMethod<T>(o, methodName, args);
}
/// <summary>Invokes a named method on a created instance of a type with parameters.</summary>
/// <typeparam name="T">The expected type of the method's return value.</typeparam>
/// <param name="type">The type to be instantiated and then used to invoke the method. This method assumes the type has a default public constructor.</param>
/// <param name="methodName">Name of the method.</param>
/// <param name="args">The arguments to provide to the method invocation.</param>
/// <returns>The value returned from the method.</returns>
public static T InvokeMethod<T>(Type type, string methodName, params object[] args)
{
object o = Activator.CreateInstance(type);
return InvokeMethod<T>(o, methodName, args);
}
/// <summary>Invokes a named method on a created instance of a type with parameters.</summary>
/// <typeparam name="T">The expected type of the method's return value.</typeparam>
/// <param name="type">The type to be instantiated and then used to invoke the method.</param>
/// <param name="instArgs">The arguments to supply to the constructor.</param>
/// <param name="methodName">Name of the method.</param>
/// <param name="args">The arguments to provide to the method invocation.</param>
/// <returns>The value returned from the method.</returns>
public static T InvokeMethod<T>(Type type, object[] instArgs, string methodName, params object[] args)
{
object o = Activator.CreateInstance(type, instArgs);
return InvokeMethod<T>(o, methodName, args);
}
/// <summary>Invokes a named method on a created instance of a type with parameters.</summary>
/// <typeparam name="T">The expected type of the method's return value.</typeparam>
/// <param name="type">The type to be instantiated and then used to invoke the method.</param>
/// <param name="instArgs">The arguments to supply to the constructor.</param>
/// <param name="methodName">Name of the method.</param>
/// <param name="args">The arguments to provide to the method invocation.</param>
/// <returns>The value returned from the method.</returns>
public static T InvokeMethod<T>(Type type, object[] instArgs, string methodName, params object[] args)
{
object o = Activator.CreateInstance(type, instArgs);
return InvokeMethod<T>(o, methodName, args);
}
/// <summary>Invokes a named method on an object with parameters and no return value.</summary>
/// <param name="obj">The object on which to invoke the method.</param>
/// <param name="methodName">Name of the method.</param>
/// <param name="args">The arguments to provide to the method invocation.</param>
public static T InvokeMethod<T>(object obj, string methodName, params object[] args)
{
Type[] argTypes = (args == null || args.Length == 0) ? Type.EmptyTypes : Array.ConvertAll(args, delegate (object o) { return o == null ? typeof(object) : o.GetType(); });
return InvokeMethod<T>(obj, methodName, argTypes, args);
}
/// <summary>Invokes a named method on an object with parameters and no return value.</summary>
/// <param name="obj">The object on which to invoke the method.</param>
/// <param name="methodName">Name of the method.</param>
/// <param name="args">The arguments to provide to the method invocation.</param>
public static T InvokeMethod<T>(object obj, string methodName, params object[] args)
{
Type[] argTypes = (args == null || args.Length == 0) ? Type.EmptyTypes : Array.ConvertAll(args, delegate (object o) { return o == null ? typeof(object) : o.GetType(); });
return InvokeMethod<T>(obj, methodName, argTypes, args);
}
/// <summary>Invokes a named method on an object with parameters and no return value.</summary>
/// <typeparam name="T">The expected type of the method's return value.</typeparam>
/// <param name="obj">The object on which to invoke the method.</param>
/// <param name="methodName">Name of the method.</param>
/// <param name="argTypes">The types of the <paramref name="args"/>.</param>
/// <param name="args">The arguments to provide to the method invocation.</param>
/// <returns>The value returned from the method.</returns>
public static T InvokeMethod<T>(object obj, string methodName, Type[] argTypes, object[] args)
{
MethodInfo mi = obj?.GetType().GetMethod(methodName, argTypes);
if (mi != null)
return (T)Convert.ChangeType(mi.Invoke(obj, args), typeof(T));
return default(T);
}
/// <summary>Invokes a named method on an object with parameters and no return value.</summary>
/// <typeparam name="T">The expected type of the method's return value.</typeparam>
/// <param name="obj">The object on which to invoke the method.</param>
/// <param name="methodName">Name of the method.</param>
/// <param name="argTypes">The types of the <paramref name="args"/>.</param>
/// <param name="args">The arguments to provide to the method invocation.</param>
/// <returns>The value returned from the method.</returns>
public static T InvokeMethod<T>(object obj, string methodName, Type[] argTypes, object[] args)
{
MethodInfo mi = obj?.GetType().GetMethod(methodName, argTypes);
if (mi != null)
return (T)Convert.ChangeType(mi.Invoke(obj, args), typeof(T));
return default(T);
}
/// <summary>Gets a named property value from an object.</summary>
/// <typeparam name="T">The expected type of the property to be returned.</typeparam>
/// <param name="obj">The object from which to retrieve the property.</param>
/// <param name="propName">Name of the property.</param>
/// <param name="defaultValue">The default value to return in the instance that the property is not found.</param>
/// <returns>The property value, if found, or the <paramref name="defaultValue"/> if not.</returns>
public static T GetProperty<T>(object obj, string propName, T defaultValue = default(T))
{
if (obj != null)
{
try { return (T)Convert.ChangeType(obj.GetType().InvokeMember(propName, BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, obj, null, null), typeof(T)); }
catch { }
}
return defaultValue;
}
/// <summary>Gets a named property value from an object.</summary>
/// <typeparam name="T">The expected type of the property to be returned.</typeparam>
/// <param name="obj">The object from which to retrieve the property.</param>
/// <param name="propName">Name of the property.</param>
/// <param name="defaultValue">The default value to return in the instance that the property is not found.</param>
/// <returns>The property value, if found, or the <paramref name="defaultValue"/> if not.</returns>
public static T GetProperty<T>(object obj, string propName, T defaultValue = default(T))
{
if (obj != null)
{
try { return (T)Convert.ChangeType(obj.GetType().InvokeMember(propName, BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, obj, null, null), typeof(T)); }
catch { }
}
return defaultValue;
}
/// <summary>Sets a named property on an object.</summary>
/// <typeparam name="T">The type of the property to be set.</typeparam>
/// <param name="obj">The object on which to set the property.</param>
/// <param name="propName">Name of the property.</param>
/// <param name="value">The property value to set on the object.</param>
public static void SetProperty<T>(object obj, string propName, T value)
{
try { obj?.GetType().InvokeMember(propName, BindingFlags.SetProperty | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, obj, new object[] { value }, null); }
catch { }
}
}
/// <summary>Sets a named property on an object.</summary>
/// <typeparam name="T">The type of the property to be set.</typeparam>
/// <param name="obj">The object on which to set the property.</param>
/// <param name="propName">Name of the property.</param>
/// <param name="value">The property value to set on the object.</param>
public static void SetProperty<T>(object obj, string propName, T value)
{
try { obj?.GetType().InvokeMember(propName, BindingFlags.SetProperty | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, obj, new object[] { value }, null); }
catch { }
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -9,395 +9,395 @@ using winPEAS.TaskScheduler.V2;
namespace winPEAS.TaskScheduler
{
/// <summary>
/// Collection of running tasks in a <see cref="TaskService"/>. This class has no public constructor and can only be accessed via the
/// properties and functions within <see cref="TaskService"/>.
/// </summary>
public sealed class RunningTaskCollection : IReadOnlyList<RunningTask>, IDisposable
{
private readonly TaskService svc;
private readonly IRunningTaskCollection v2Coll;
/// <summary>
/// Collection of running tasks in a <see cref="TaskService"/>. This class has no public constructor and can only be accessed via the
/// properties and functions within <see cref="TaskService"/>.
/// </summary>
public sealed class RunningTaskCollection : IReadOnlyList<RunningTask>, IDisposable
{
private readonly TaskService svc;
private readonly IRunningTaskCollection v2Coll;
internal RunningTaskCollection([NotNull] TaskService svc) => this.svc = svc;
internal RunningTaskCollection([NotNull] TaskService svc) => this.svc = svc;
internal RunningTaskCollection([NotNull] TaskService svc, [NotNull] IRunningTaskCollection iTaskColl)
{
this.svc = svc;
v2Coll = iTaskColl;
}
internal RunningTaskCollection([NotNull] TaskService svc, [NotNull] IRunningTaskCollection iTaskColl)
{
this.svc = svc;
v2Coll = iTaskColl;
}
/// <summary>Gets the number of registered tasks in the collection.</summary>
public int Count
{
get
{
if (v2Coll != null)
return v2Coll.Count;
var i = 0;
var v1Enum = new V1RunningTaskEnumerator(svc);
while (v1Enum.MoveNext())
i++;
return i;
}
}
/// <summary>Gets the number of registered tasks in the collection.</summary>
public int Count
{
get
{
if (v2Coll != null)
return v2Coll.Count;
var i = 0;
var v1Enum = new V1RunningTaskEnumerator(svc);
while (v1Enum.MoveNext())
i++;
return i;
}
}
/// <summary>Gets the specified running task from the collection.</summary>
/// <param name="index">The index of the running task to be retrieved.</param>
/// <returns>A <see cref="RunningTask"/> instance.</returns>
public RunningTask this[int index]
{
get
{
if (v2Coll != null)
{
var irt = v2Coll[++index];
return new RunningTask(svc, TaskService.GetTask(svc.v2TaskService, irt.Path), irt);
}
/// <summary>Gets the specified running task from the collection.</summary>
/// <param name="index">The index of the running task to be retrieved.</param>
/// <returns>A <see cref="RunningTask"/> instance.</returns>
public RunningTask this[int index]
{
get
{
if (v2Coll != null)
{
var irt = v2Coll[++index];
return new RunningTask(svc, TaskService.GetTask(svc.v2TaskService, irt.Path), irt);
}
var i = 0;
var v1Enum = new V1RunningTaskEnumerator(svc);
while (v1Enum.MoveNext())
if (i++ == index)
return v1Enum.Current;
throw new ArgumentOutOfRangeException(nameof(index));
}
}
var i = 0;
var v1Enum = new V1RunningTaskEnumerator(svc);
while (v1Enum.MoveNext())
if (i++ == index)
return v1Enum.Current;
throw new ArgumentOutOfRangeException(nameof(index));
}
}
/// <summary>Releases all resources used by this class.</summary>
public void Dispose()
{
if (v2Coll != null)
Marshal.ReleaseComObject(v2Coll);
}
/// <summary>Releases all resources used by this class.</summary>
public void Dispose()
{
if (v2Coll != null)
Marshal.ReleaseComObject(v2Coll);
}
/// <summary>Gets an IEnumerator instance for this collection.</summary>
/// <returns>An enumerator.</returns>
public IEnumerator<RunningTask> GetEnumerator()
{
if (v2Coll != null)
return new ComEnumerator<RunningTask, IRunningTask>(() => v2Coll.Count, (object o) => v2Coll[o], o =>
{
IRegisteredTask task = null;
try { task = TaskService.GetTask(svc.v2TaskService, o.Path); } catch { }
return task == null ? null : new RunningTask(svc, task, o);
});
return new V1RunningTaskEnumerator(svc);
}
/// <summary>Gets an IEnumerator instance for this collection.</summary>
/// <returns>An enumerator.</returns>
public IEnumerator<RunningTask> GetEnumerator()
{
if (v2Coll != null)
return new ComEnumerator<RunningTask, IRunningTask>(() => v2Coll.Count, (object o) => v2Coll[o], o =>
{
IRegisteredTask task = null;
try { task = TaskService.GetTask(svc.v2TaskService, o.Path); } catch { }
return task == null ? null : new RunningTask(svc, task, o);
});
return new V1RunningTaskEnumerator(svc);
}
/// <summary>Returns a <see cref="System.String"/> that represents this instance.</summary>
/// <returns>A <see cref="System.String"/> that represents this instance.</returns>
public override string ToString() => $"RunningTaskCollection; Count: {Count}";
/// <summary>Returns a <see cref="System.String"/> that represents this instance.</summary>
/// <returns>A <see cref="System.String"/> that represents this instance.</returns>
public override string ToString() => $"RunningTaskCollection; Count: {Count}";
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator();
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator();
private class V1RunningTaskEnumerator : IEnumerator<RunningTask>
{
private readonly TaskService svc;
private readonly TaskCollection.V1TaskEnumerator tEnum;
private class V1RunningTaskEnumerator : IEnumerator<RunningTask>
{
private readonly TaskService svc;
private readonly TaskCollection.V1TaskEnumerator tEnum;
internal V1RunningTaskEnumerator([NotNull] TaskService svc)
{
this.svc = svc;
tEnum = new TaskCollection.V1TaskEnumerator(svc);
}
internal V1RunningTaskEnumerator([NotNull] TaskService svc)
{
this.svc = svc;
tEnum = new TaskCollection.V1TaskEnumerator(svc);
}
public RunningTask Current => new RunningTask(svc, tEnum.ICurrent);
public RunningTask Current => new RunningTask(svc, tEnum.ICurrent);
object System.Collections.IEnumerator.Current => Current;
object System.Collections.IEnumerator.Current => Current;
/// <summary>Releases all resources used by this class.</summary>
public void Dispose() => tEnum.Dispose();
/// <summary>Releases all resources used by this class.</summary>
public void Dispose() => tEnum.Dispose();
public bool MoveNext() => tEnum.MoveNext() && (tEnum.Current?.State == TaskState.Running || MoveNext());
public bool MoveNext() => tEnum.MoveNext() && (tEnum.Current?.State == TaskState.Running || MoveNext());
public void Reset() => tEnum.Reset();
}
}
public void Reset() => tEnum.Reset();
}
}
/// <summary>
/// Contains all the tasks that are registered within a <see cref="TaskFolder"/>. This class has no public constructor and can only be
/// accessed via the properties and functions within <see cref="TaskFolder"/>.
/// </summary>
/// <remarks>
/// Potentially breaking change in 1.6.2 and later where under V1 the list previously included the '.job' extension on the task name.
/// This has been removed so that it is consistent with V2.
/// </remarks>
/// <example>
/// <code>public class Program
/// {
/// bool RootFolderHasTask(string taskName)
/// {
/// if (TaskService.Instance.RootFolder.Tasks.Count &gt; 0)
/// {
/// return TaskService.Instance.RootFolder.Tasks.Exists(taskName);
/// }
/// return false;
/// }
///
/// TaskCollection GetRootTasksStartingWith(string value)
/// {
/// var pattern = $"^{Regex.Escape(value)}.*$";
/// return TaskService.Instance.RootFolder.GetTasks(new Regex(pattern));
/// }
///
/// public static void Main()
/// {
/// foreach (var task in GetRootTasksStartingWith("MyCo"))
/// if (RootFolderHasTask(task.Name))
/// Console.WriteLine(task.Name);
/// }
/// }</code>
/// </example>
[PublicAPI]
public sealed class TaskCollection : IReadOnlyList<Task>, IDisposable
{
private readonly TaskFolder fld;
private readonly TaskService svc;
private readonly IRegisteredTaskCollection v2Coll;
private Regex filter;
private ITaskScheduler v1TS;
/// <summary>
/// Contains all the tasks that are registered within a <see cref="TaskFolder"/>. This class has no public constructor and can only be
/// accessed via the properties and functions within <see cref="TaskFolder"/>.
/// </summary>
/// <remarks>
/// Potentially breaking change in 1.6.2 and later where under V1 the list previously included the '.job' extension on the task name.
/// This has been removed so that it is consistent with V2.
/// </remarks>
/// <example>
/// <code>public class Program
/// {
/// bool RootFolderHasTask(string taskName)
/// {
/// if (TaskService.Instance.RootFolder.Tasks.Count &gt; 0)
/// {
/// return TaskService.Instance.RootFolder.Tasks.Exists(taskName);
/// }
/// return false;
/// }
///
/// TaskCollection GetRootTasksStartingWith(string value)
/// {
/// var pattern = $"^{Regex.Escape(value)}.*$";
/// return TaskService.Instance.RootFolder.GetTasks(new Regex(pattern));
/// }
///
/// public static void Main()
/// {
/// foreach (var task in GetRootTasksStartingWith("MyCo"))
/// if (RootFolderHasTask(task.Name))
/// Console.WriteLine(task.Name);
/// }
/// }</code>
/// </example>
[PublicAPI]
public sealed class TaskCollection : IReadOnlyList<Task>, IDisposable
{
private readonly TaskFolder fld;
private readonly TaskService svc;
private readonly IRegisteredTaskCollection v2Coll;
private Regex filter;
private ITaskScheduler v1TS;
internal TaskCollection([NotNull] TaskService svc, Regex filter = null)
{
this.svc = svc;
Filter = filter;
v1TS = svc.v1TaskScheduler;
}
internal TaskCollection([NotNull] TaskService svc, Regex filter = null)
{
this.svc = svc;
Filter = filter;
v1TS = svc.v1TaskScheduler;
}
internal TaskCollection([NotNull] TaskFolder folder, [NotNull] IRegisteredTaskCollection iTaskColl, Regex filter = null)
{
svc = folder.TaskService;
Filter = filter;
fld = folder;
v2Coll = iTaskColl;
}
internal TaskCollection([NotNull] TaskFolder folder, [NotNull] IRegisteredTaskCollection iTaskColl, Regex filter = null)
{
svc = folder.TaskService;
Filter = filter;
fld = folder;
v2Coll = iTaskColl;
}
/// <summary>Gets the number of registered tasks in the collection.</summary>
public int Count
{
get
{
var i = 0;
if (v2Coll != null)
{
var v2Enum = new V2TaskEnumerator(fld, v2Coll, filter);
while (v2Enum.MoveNext())
i++;
}
else
{
var v1Enum = new V1TaskEnumerator(svc, filter);
return v1Enum.Count;
}
return i;
}
}
/// <summary>Gets the number of registered tasks in the collection.</summary>
public int Count
{
get
{
var i = 0;
if (v2Coll != null)
{
var v2Enum = new V2TaskEnumerator(fld, v2Coll, filter);
while (v2Enum.MoveNext())
i++;
}
else
{
var v1Enum = new V1TaskEnumerator(svc, filter);
return v1Enum.Count;
}
return i;
}
}
/// <summary>Gets or sets the regular expression filter for task names.</summary>
/// <value>The regular expression filter.</value>
private Regex Filter
{
get => filter;
set
{
var sfilter = value?.ToString().TrimStart('^').TrimEnd('$') ?? string.Empty;
if (sfilter == string.Empty || sfilter == "*")
filter = null;
else
{
if (value != null && value.ToString().TrimEnd('$').EndsWith("\\.job", StringComparison.InvariantCultureIgnoreCase))
filter = new Regex(value.ToString().Replace("\\.job", ""));
else
filter = value;
}
}
}
/// <summary>Gets or sets the regular expression filter for task names.</summary>
/// <value>The regular expression filter.</value>
private Regex Filter
{
get => filter;
set
{
var sfilter = value?.ToString().TrimStart('^').TrimEnd('$') ?? string.Empty;
if (sfilter == string.Empty || sfilter == "*")
filter = null;
else
{
if (value != null && value.ToString().TrimEnd('$').EndsWith("\\.job", StringComparison.InvariantCultureIgnoreCase))
filter = new Regex(value.ToString().Replace("\\.job", ""));
else
filter = value;
}
}
}
/// <summary>Gets the specified registered task from the collection.</summary>
/// <param name="index">The index of the registered task to be retrieved.</param>
/// <returns>A <see cref="Task"/> instance that contains the requested context.</returns>
public Task this[int index]
{
get
{
var i = 0;
var te = GetEnumerator();
while (te.MoveNext())
if (i++ == index)
return te.Current;
throw new ArgumentOutOfRangeException(nameof(index));
}
}
/// <summary>Gets the specified registered task from the collection.</summary>
/// <param name="index">The index of the registered task to be retrieved.</param>
/// <returns>A <see cref="Task"/> instance that contains the requested context.</returns>
public Task this[int index]
{
get
{
var i = 0;
var te = GetEnumerator();
while (te.MoveNext())
if (i++ == index)
return te.Current;
throw new ArgumentOutOfRangeException(nameof(index));
}
}
/// <summary>Gets the named registered task from the collection.</summary>
/// <param name="name">The name of the registered task to be retrieved.</param>
/// <returns>A <see cref="Task"/> instance that contains the requested context.</returns>
public Task this[string name]
{
get
{
if (v2Coll != null)
return Task.CreateTask(svc, v2Coll[name]);
/// <summary>Gets the named registered task from the collection.</summary>
/// <param name="name">The name of the registered task to be retrieved.</param>
/// <returns>A <see cref="Task"/> instance that contains the requested context.</returns>
public Task this[string name]
{
get
{
if (v2Coll != null)
return Task.CreateTask(svc, v2Coll[name]);
var v1Task = svc.GetTask(name);
if (v1Task != null)
return v1Task;
var v1Task = svc.GetTask(name);
if (v1Task != null)
return v1Task;
throw new ArgumentOutOfRangeException(nameof(name));
}
}
throw new ArgumentOutOfRangeException(nameof(name));
}
}
/// <summary>Releases all resources used by this class.</summary>
public void Dispose()
{
v1TS = null;
if (v2Coll != null)
Marshal.ReleaseComObject(v2Coll);
}
/// <summary>Releases all resources used by this class.</summary>
public void Dispose()
{
v1TS = null;
if (v2Coll != null)
Marshal.ReleaseComObject(v2Coll);
}
/// <summary>Determines whether the specified task exists.</summary>
/// <param name="taskName">The name of the task.</param>
/// <returns>true if task exists; otherwise, false.</returns>
public bool Exists([NotNull] string taskName)
{
try
{
if (v2Coll != null)
return v2Coll[taskName] != null;
/// <summary>Determines whether the specified task exists.</summary>
/// <param name="taskName">The name of the task.</param>
/// <returns>true if task exists; otherwise, false.</returns>
public bool Exists([NotNull] string taskName)
{
try
{
if (v2Coll != null)
return v2Coll[taskName] != null;
return svc.GetTask(taskName) != null;
}
catch { }
return false;
}
return svc.GetTask(taskName) != null;
}
catch { }
return false;
}
/// <summary>Gets the collection enumerator for the register task collection.</summary>
/// <returns>An <see cref="System.Collections.IEnumerator"/> for this collection.</returns>
public IEnumerator<Task> GetEnumerator()
{
if (v1TS != null)
return new V1TaskEnumerator(svc, filter);
return new V2TaskEnumerator(fld, v2Coll, filter);
}
/// <summary>Gets the collection enumerator for the register task collection.</summary>
/// <returns>An <see cref="System.Collections.IEnumerator"/> for this collection.</returns>
public IEnumerator<Task> GetEnumerator()
{
if (v1TS != null)
return new V1TaskEnumerator(svc, filter);
return new V2TaskEnumerator(fld, v2Coll, filter);
}
/// <summary>Returns a <see cref="System.String"/> that represents this instance.</summary>
/// <returns>A <see cref="System.String"/> that represents this instance.</returns>
public override string ToString() => $"TaskCollection; Count: {Count}";
/// <summary>Returns a <see cref="System.String"/> that represents this instance.</summary>
/// <returns>A <see cref="System.String"/> that represents this instance.</returns>
public override string ToString() => $"TaskCollection; Count: {Count}";
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator();
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator();
internal class V1TaskEnumerator : IEnumerator<Task>
{
private readonly Regex filter;
private readonly TaskService svc;
private readonly IEnumWorkItems wienum;
private string curItem;
private ITaskScheduler ts;
internal class V1TaskEnumerator : IEnumerator<Task>
{
private readonly Regex filter;
private readonly TaskService svc;
private readonly IEnumWorkItems wienum;
private string curItem;
private ITaskScheduler ts;
/// <summary>Internal constructor</summary>
/// <param name="svc">TaskService instance</param>
/// <param name="filter">The filter.</param>
internal V1TaskEnumerator(TaskService svc, Regex filter = null)
{
this.svc = svc;
this.filter = filter;
ts = svc.v1TaskScheduler;
wienum = ts?.Enum();
Reset();
}
/// <summary>Internal constructor</summary>
/// <param name="svc">TaskService instance</param>
/// <param name="filter">The filter.</param>
internal V1TaskEnumerator(TaskService svc, Regex filter = null)
{
this.svc = svc;
this.filter = filter;
ts = svc.v1TaskScheduler;
wienum = ts?.Enum();
Reset();
}
/// <summary>Retrieves the current task. See <see cref="System.Collections.IEnumerator.Current"/> for more information.</summary>
public Task Current => new Task(svc, ICurrent);
/// <summary>Retrieves the current task. See <see cref="System.Collections.IEnumerator.Current"/> for more information.</summary>
public Task Current => new Task(svc, ICurrent);
object System.Collections.IEnumerator.Current => Current;
object System.Collections.IEnumerator.Current => Current;
internal int Count
{
get
{
var i = 0;
Reset();
while (MoveNext())
i++;
Reset();
return i;
}
}
internal int Count
{
get
{
var i = 0;
Reset();
while (MoveNext())
i++;
Reset();
return i;
}
}
internal ITask ICurrent => TaskService.GetTask(ts, curItem);
internal ITask ICurrent => TaskService.GetTask(ts, curItem);
/// <summary>Releases all resources used by this class.</summary>
public void Dispose()
{
if (wienum != null) Marshal.ReleaseComObject(wienum);
ts = null;
}
/// <summary>Releases all resources used by this class.</summary>
public void Dispose()
{
if (wienum != null) Marshal.ReleaseComObject(wienum);
ts = null;
}
/// <summary>Moves to the next task. See MoveNext for more information.</summary>
/// <returns>true if next task found, false if no more tasks.</returns>
public bool MoveNext()
{
var names = IntPtr.Zero;
var valid = false;
do
{
curItem = null;
uint uFetched = 0;
try
{
wienum?.Next(1, out names, out uFetched);
if (uFetched != 1)
break;
using (var name = new CoTaskMemString(Marshal.ReadIntPtr(names)))
curItem = name.ToString();
if (curItem != null && curItem.EndsWith(".job", StringComparison.InvariantCultureIgnoreCase))
curItem = curItem.Remove(curItem.Length - 4);
}
catch { }
finally { Marshal.FreeCoTaskMem(names); names = IntPtr.Zero; }
/// <summary>Moves to the next task. See MoveNext for more information.</summary>
/// <returns>true if next task found, false if no more tasks.</returns>
public bool MoveNext()
{
var names = IntPtr.Zero;
var valid = false;
do
{
curItem = null;
uint uFetched = 0;
try
{
wienum?.Next(1, out names, out uFetched);
if (uFetched != 1)
break;
using (var name = new CoTaskMemString(Marshal.ReadIntPtr(names)))
curItem = name.ToString();
if (curItem != null && curItem.EndsWith(".job", StringComparison.InvariantCultureIgnoreCase))
curItem = curItem.Remove(curItem.Length - 4);
}
catch { }
finally { Marshal.FreeCoTaskMem(names); names = IntPtr.Zero; }
// If name doesn't match filter, look for next item
if (filter != null && curItem != null)
{
if (!filter.IsMatch(curItem))
continue;
}
// If name doesn't match filter, look for next item
if (filter != null && curItem != null)
{
if (!filter.IsMatch(curItem))
continue;
}
ITask itask = null;
try { itask = ICurrent; valid = true; }
catch { valid = false; }
finally { Marshal.ReleaseComObject(itask); }
} while (!valid);
ITask itask = null;
try { itask = ICurrent; valid = true; }
catch { valid = false; }
finally { Marshal.ReleaseComObject(itask); }
} while (!valid);
return (curItem != null);
}
return (curItem != null);
}
/// <summary>Reset task enumeration. See Reset for more information.</summary>
public void Reset()
{
curItem = null;
wienum?.Reset();
}
}
/// <summary>Reset task enumeration. See Reset for more information.</summary>
public void Reset()
{
curItem = null;
wienum?.Reset();
}
}
private class V2TaskEnumerator : ComEnumerator<Task, IRegisteredTask>
{
private readonly Regex filter;
private class V2TaskEnumerator : ComEnumerator<Task, IRegisteredTask>
{
private readonly Regex filter;
internal V2TaskEnumerator(TaskFolder folder, IRegisteredTaskCollection iTaskColl, Regex filter = null) :
base(() => iTaskColl.Count, (object o) => iTaskColl[o], o => Task.CreateTask(folder.TaskService, o)) => this.filter = filter;
internal V2TaskEnumerator(TaskFolder folder, IRegisteredTaskCollection iTaskColl, Regex filter = null) :
base(() => iTaskColl.Count, (object o) => iTaskColl[o], o => Task.CreateTask(folder.TaskService, o)) => this.filter = filter;
public override bool MoveNext()
{
var hasNext = base.MoveNext();
while (hasNext)
{
if (filter == null || filter.IsMatch(iEnum?.Current?.Name ?? ""))
break;
hasNext = base.MoveNext();
}
return hasNext;
}
}
}
public override bool MoveNext()
{
var hasNext = base.MoveNext();
while (hasNext)
{
if (filter == null || filter.IsMatch(iEnum?.Current?.Name ?? ""))
break;
hasNext = base.MoveNext();
}
return hasNext;
}
}
}
}

View File

@@ -1,147 +1,144 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace winPEAS.TaskScheduler.TaskEditor.Native
{
internal static class InteropUtil
{
private const int cbBuffer = 256;
internal static class InteropUtil
{
private const int cbBuffer = 256;
public static T ToStructure<T>(IntPtr ptr) => (T)Marshal.PtrToStructure(ptr, typeof(T));
public static T ToStructure<T>(IntPtr ptr) => (T)Marshal.PtrToStructure(ptr, typeof(T));
public static IntPtr StructureToPtr(object value)
{
IntPtr ret = Marshal.AllocHGlobal(Marshal.SizeOf(value));
Marshal.StructureToPtr(value, ret, false);
return ret;
}
public static IntPtr StructureToPtr(object value)
{
IntPtr ret = Marshal.AllocHGlobal(Marshal.SizeOf(value));
Marshal.StructureToPtr(value, ret, false);
return ret;
}
public static void AllocString(ref IntPtr ptr, ref uint size)
{
FreeString(ref ptr, ref size);
if (size == 0) size = cbBuffer;
ptr = Marshal.AllocHGlobal(cbBuffer);
}
public static void AllocString(ref IntPtr ptr, ref uint size)
{
FreeString(ref ptr, ref size);
if (size == 0) size = cbBuffer;
ptr = Marshal.AllocHGlobal(cbBuffer);
}
public static void FreeString(ref IntPtr ptr, ref uint size)
{
if (ptr != IntPtr.Zero)
{
Marshal.FreeHGlobal(ptr);
ptr = IntPtr.Zero;
size = 0;
}
}
public static void FreeString(ref IntPtr ptr, ref uint size)
{
if (ptr != IntPtr.Zero)
{
Marshal.FreeHGlobal(ptr);
ptr = IntPtr.Zero;
size = 0;
}
}
public static string GetString(IntPtr pString) => Marshal.PtrToStringUni(pString);
public static string GetString(IntPtr pString) => Marshal.PtrToStringUni(pString);
public static bool SetString(ref IntPtr ptr, ref uint size, string value = null)
{
string s = GetString(ptr);
if (value == string.Empty) value = null;
if (string.CompareOrdinal(s, value) != 0)
{
FreeString(ref ptr, ref size);
if (value != null)
{
ptr = Marshal.StringToHGlobalUni(value);
size = (uint)value.Length + 1;
}
return true;
}
return false;
}
public static bool SetString(ref IntPtr ptr, ref uint size, string value = null)
{
string s = GetString(ptr);
if (value == string.Empty) value = null;
if (string.CompareOrdinal(s, value) != 0)
{
FreeString(ref ptr, ref size);
if (value != null)
{
ptr = Marshal.StringToHGlobalUni(value);
size = (uint)value.Length + 1;
}
return true;
}
return false;
}
/// <summary>
/// Converts an <see cref="IntPtr"/> that points to a C-style array into a CLI array.
/// </summary>
/// <typeparam name="TS">Type of native structure used by the C-style array.</typeparam>
/// <typeparam name="T">Output type for the CLI array. <typeparamref name="TS"/> must be able to convert to <typeparamref name="T"/>.</typeparam>
/// <param name="ptr">The <see cref="IntPtr"/> pointing to the native array.</param>
/// <param name="count">The number of items in the native array.</param>
/// <returns>An array of type <typeparamref name="T"/> containing the converted elements of the native array.</returns>
public static T[] ToArray<TS, T>(IntPtr ptr, int count) where TS : IConvertible
{
var ret = new T[count];
var stSize = Marshal.SizeOf(typeof(TS));
for (var i = 0; i < count; i++)
{
var tempPtr = new IntPtr(ptr.ToInt64() + (i * stSize));
var val = ToStructure<TS>(tempPtr);
ret[i] = (T)Convert.ChangeType(val, typeof(T));
}
return ret;
}
/// <summary>
/// Converts an <see cref="IntPtr"/> that points to a C-style array into a CLI array.
/// </summary>
/// <typeparam name="TS">Type of native structure used by the C-style array.</typeparam>
/// <typeparam name="T">Output type for the CLI array. <typeparamref name="TS"/> must be able to convert to <typeparamref name="T"/>.</typeparam>
/// <param name="ptr">The <see cref="IntPtr"/> pointing to the native array.</param>
/// <param name="count">The number of items in the native array.</param>
/// <returns>An array of type <typeparamref name="T"/> containing the converted elements of the native array.</returns>
public static T[] ToArray<TS, T>(IntPtr ptr, int count) where TS : IConvertible
{
var ret = new T[count];
var stSize = Marshal.SizeOf(typeof(TS));
for (var i = 0; i < count; i++)
{
var tempPtr = new IntPtr(ptr.ToInt64() + (i * stSize));
var val = ToStructure<TS>(tempPtr);
ret[i] = (T)Convert.ChangeType(val, typeof(T));
}
return ret;
}
/// <summary>
/// Converts an <see cref="IntPtr"/> that points to a C-style array into a CLI array.
/// </summary>
/// <typeparam name="T">Type of native structure used by the C-style array.</typeparam>
/// <param name="ptr">The <see cref="IntPtr"/> pointing to the native array.</param>
/// <param name="count">The number of items in the native array.</param>
/// <returns>An array of type <typeparamref name="T"/> containing the elements of the native array.</returns>
public static T[] ToArray<T>(IntPtr ptr, int count)
{
var ret = new T[count];
var stSize = Marshal.SizeOf(typeof(T));
for (var i = 0; i < count; i++)
{
var tempPtr = new IntPtr(ptr.ToInt64() + (i * stSize));
ret[i] = ToStructure<T>(tempPtr);
}
return ret;
}
}
/// <summary>
/// Converts an <see cref="IntPtr"/> that points to a C-style array into a CLI array.
/// </summary>
/// <typeparam name="T">Type of native structure used by the C-style array.</typeparam>
/// <param name="ptr">The <see cref="IntPtr"/> pointing to the native array.</param>
/// <param name="count">The number of items in the native array.</param>
/// <returns>An array of type <typeparamref name="T"/> containing the elements of the native array.</returns>
public static T[] ToArray<T>(IntPtr ptr, int count)
{
var ret = new T[count];
var stSize = Marshal.SizeOf(typeof(T));
for (var i = 0; i < count; i++)
{
var tempPtr = new IntPtr(ptr.ToInt64() + (i * stSize));
ret[i] = ToStructure<T>(tempPtr);
}
return ret;
}
}
internal class ComEnumerator<T, TIn> : IEnumerator<T> where T : class where TIn : class
{
protected readonly Func<TIn, T> converter;
protected IEnumerator<TIn> iEnum;
internal class ComEnumerator<T, TIn> : IEnumerator<T> where T : class where TIn : class
{
protected readonly Func<TIn, T> converter;
protected IEnumerator<TIn> iEnum;
public ComEnumerator(Func<int> getCount, Func<int, TIn> indexer, Func<TIn, T> converter)
{
IEnumerator<TIn> Enumerate()
{
for (var x = 1; x <= getCount(); x++)
yield return indexer(x);
}
public ComEnumerator(Func<int> getCount, Func<int, TIn> indexer, Func<TIn, T> converter)
{
IEnumerator<TIn> Enumerate()
{
for (var x = 1; x <= getCount(); x++)
yield return indexer(x);
}
this.converter = converter;
iEnum = Enumerate();
}
this.converter = converter;
iEnum = Enumerate();
}
public ComEnumerator(Func<int> getCount, Func<object, TIn> indexer, Func<TIn, T> converter)
{
IEnumerator<TIn> Enumerate()
{
for (var x = 1; x <= getCount(); x++)
yield return indexer(x);
}
public ComEnumerator(Func<int> getCount, Func<object, TIn> indexer, Func<TIn, T> converter)
{
IEnumerator<TIn> Enumerate()
{
for (var x = 1; x <= getCount(); x++)
yield return indexer(x);
}
this.converter = converter;
iEnum = Enumerate();
}
this.converter = converter;
iEnum = Enumerate();
}
object IEnumerator.Current => Current;
object IEnumerator.Current => Current;
public virtual T Current => converter(iEnum?.Current);
public virtual T Current => converter(iEnum?.Current);
public virtual void Dispose()
{
iEnum?.Dispose();
iEnum = null;
}
public virtual void Dispose()
{
iEnum?.Dispose();
iEnum = null;
}
public virtual bool MoveNext() => iEnum?.MoveNext() ?? false;
public virtual bool MoveNext() => iEnum?.MoveNext() ?? false;
public virtual void Reset()
{
iEnum?.Reset();
}
}
public virtual void Reset()
{
iEnum?.Reset();
}
}
}

View File

@@ -8,145 +8,145 @@ using winPEAS.Native.Enums;
namespace winPEAS.TaskScheduler.TaskEditor.Native
{
internal static partial class NativeMethods
{
/// <summary>
/// Defines the errors returned by the status member of the DS_NAME_RESULT_ITEM structure. These are potential errors that may be encountered while a name is converted by the DsCrackNames function.
/// </summary>
public enum DS_NAME_ERROR : uint
{
/// <summary>The conversion was successful.</summary>
DS_NAME_NO_ERROR = 0,
{
/// <summary>
/// Defines the errors returned by the status member of the DS_NAME_RESULT_ITEM structure. These are potential errors that may be encountered while a name is converted by the DsCrackNames function.
/// </summary>
public enum DS_NAME_ERROR : uint
{
/// <summary>The conversion was successful.</summary>
DS_NAME_NO_ERROR = 0,
///<summary>Generic processing error occurred.</summary>
DS_NAME_ERROR_RESOLVING = 1,
///<summary>Generic processing error occurred.</summary>
DS_NAME_ERROR_RESOLVING = 1,
///<summary>The name cannot be found or the caller does not have permission to access the name.</summary>
DS_NAME_ERROR_NOT_FOUND = 2,
///<summary>The name cannot be found or the caller does not have permission to access the name.</summary>
DS_NAME_ERROR_NOT_FOUND = 2,
///<summary>The input name is mapped to more than one output name or the desired format did not have a single, unique value for the object found.</summary>
DS_NAME_ERROR_NOT_UNIQUE = 3,
///<summary>The input name is mapped to more than one output name or the desired format did not have a single, unique value for the object found.</summary>
DS_NAME_ERROR_NOT_UNIQUE = 3,
///<summary>The input name was found, but the associated output format cannot be found. This can occur if the object does not have all the required attributes.</summary>
DS_NAME_ERROR_NO_MAPPING = 4,
///<summary>The input name was found, but the associated output format cannot be found. This can occur if the object does not have all the required attributes.</summary>
DS_NAME_ERROR_NO_MAPPING = 4,
///<summary>Unable to resolve entire name, but was able to determine in which domain object resides. The caller is expected to retry the call at a domain controller for the specified domain. The entire name cannot be resolved, but the domain that the object resides in could be determined. The pDomain member of the DS_NAME_RESULT_ITEM contains valid data when this error is specified.</summary>
DS_NAME_ERROR_DOMAIN_ONLY = 5,
///<summary>Unable to resolve entire name, but was able to determine in which domain object resides. The caller is expected to retry the call at a domain controller for the specified domain. The entire name cannot be resolved, but the domain that the object resides in could be determined. The pDomain member of the DS_NAME_RESULT_ITEM contains valid data when this error is specified.</summary>
DS_NAME_ERROR_DOMAIN_ONLY = 5,
///<summary>A syntactical mapping cannot be performed on the client without transmitting over the network.</summary>
DS_NAME_ERROR_NO_SYNTACTICAL_MAPPING = 6,
///<summary>A syntactical mapping cannot be performed on the client without transmitting over the network.</summary>
DS_NAME_ERROR_NO_SYNTACTICAL_MAPPING = 6,
///<summary>The name is from an external trusted forest.</summary>
DS_NAME_ERROR_TRUST_REFERRAL = 7
}
///<summary>The name is from an external trusted forest.</summary>
DS_NAME_ERROR_TRUST_REFERRAL = 7
}
/// <summary>
/// Class that provides methods against a AD domain service.
/// </summary>
/// <seealso cref="System.IDisposable" />
[SuppressUnmanagedCodeSecurity, ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
public class DomainService : IDisposable
{
IntPtr handle = IntPtr.Zero;
/// <summary>
/// Class that provides methods against a AD domain service.
/// </summary>
/// <seealso cref="System.IDisposable" />
[SuppressUnmanagedCodeSecurity, ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
public class DomainService : IDisposable
{
IntPtr handle = IntPtr.Zero;
/// <summary>
/// Initializes a new instance of the <see cref="DomainService"/> class.
/// </summary>
/// <param name="domainControllerName">Name of the domain controller.</param>
/// <param name="dnsDomainName">Name of the DNS domain.</param>
/// <exception cref="System.ComponentModel.Win32Exception"></exception>
public DomainService(string domainControllerName = null, string dnsDomainName = null)
{
Ntdsapi.DsBind(domainControllerName, dnsDomainName, out handle);
}
/// <summary>
/// Initializes a new instance of the <see cref="DomainService"/> class.
/// </summary>
/// <param name="domainControllerName">Name of the domain controller.</param>
/// <param name="dnsDomainName">Name of the DNS domain.</param>
/// <exception cref="System.ComponentModel.Win32Exception"></exception>
public DomainService(string domainControllerName = null, string dnsDomainName = null)
{
Ntdsapi.DsBind(domainControllerName, dnsDomainName, out handle);
}
/// <summary>
/// Converts a directory service object name from any format to the UPN.
/// </summary>
/// <param name="name">The name to convert.</param>
/// <returns>The corresponding UPN.</returns>
/// <exception cref="System.Security.SecurityException">Unable to resolve user name.</exception>
public string CrackName(string name)
{
var res = CrackNames(new string[] { name });
if (res == null || res.Length == 0 || res[0].status != NativeMethods.DS_NAME_ERROR.DS_NAME_NO_ERROR)
throw new SecurityException("Unable to resolve user name.");
return res[0].pName;
}
/// <summary>
/// Converts a directory service object name from any format to the UPN.
/// </summary>
/// <param name="name">The name to convert.</param>
/// <returns>The corresponding UPN.</returns>
/// <exception cref="System.Security.SecurityException">Unable to resolve user name.</exception>
public string CrackName(string name)
{
var res = CrackNames(new string[] { name });
if (res == null || res.Length == 0 || res[0].status != DS_NAME_ERROR.DS_NAME_NO_ERROR)
throw new SecurityException("Unable to resolve user name.");
return res[0].pName;
}
/// <summary>
/// Converts an array of directory service object names from one format to another. Name conversion enables client applications to map between the multiple names used to identify various directory service objects.
/// </summary>
/// <param name="names">The names to convert.</param>
/// <param name="flags">Values used to determine how the name syntax will be cracked.</param>
/// <param name="formatOffered">Format of the input names.</param>
/// <param name="formatDesired">Desired format for the output names.</param>
/// <returns>An array of DS_NAME_RESULT_ITEM structures. Each element of this array represents a single converted name.</returns>
public DS_NAME_RESULT_ITEM[] CrackNames(string[] names = null, DS_NAME_FLAGS flags = DS_NAME_FLAGS.DS_NAME_NO_FLAGS, DS_NAME_FORMAT formatOffered = DS_NAME_FORMAT.DS_UNKNOWN_NAME, DS_NAME_FORMAT formatDesired = DS_NAME_FORMAT.DS_USER_PRINCIPAL_NAME)
{
IntPtr pResult;
uint err = Ntdsapi.DsCrackNames(handle, flags, formatOffered, formatDesired, (uint)(names?.Length ?? 0), names, out pResult);
if (err != (uint)DS_NAME_ERROR.DS_NAME_NO_ERROR)
throw new System.ComponentModel.Win32Exception((int)err);
try
{
// Next convert the returned structure to managed environment
DS_NAME_RESULT Result = (DS_NAME_RESULT)Marshal.PtrToStructure(pResult, typeof(DS_NAME_RESULT));
return Result.Items;
}
finally
{
/// <summary>
/// Converts an array of directory service object names from one format to another. Name conversion enables client applications to map between the multiple names used to identify various directory service objects.
/// </summary>
/// <param name="names">The names to convert.</param>
/// <param name="flags">Values used to determine how the name syntax will be cracked.</param>
/// <param name="formatOffered">Format of the input names.</param>
/// <param name="formatDesired">Desired format for the output names.</param>
/// <returns>An array of DS_NAME_RESULT_ITEM structures. Each element of this array represents a single converted name.</returns>
public DS_NAME_RESULT_ITEM[] CrackNames(string[] names = null, DS_NAME_FLAGS flags = DS_NAME_FLAGS.DS_NAME_NO_FLAGS, DS_NAME_FORMAT formatOffered = DS_NAME_FORMAT.DS_UNKNOWN_NAME, DS_NAME_FORMAT formatDesired = DS_NAME_FORMAT.DS_USER_PRINCIPAL_NAME)
{
IntPtr pResult;
uint err = Ntdsapi.DsCrackNames(handle, flags, formatOffered, formatDesired, (uint)(names?.Length ?? 0), names, out pResult);
if (err != (uint)DS_NAME_ERROR.DS_NAME_NO_ERROR)
throw new System.ComponentModel.Win32Exception((int)err);
try
{
// Next convert the returned structure to managed environment
DS_NAME_RESULT Result = (DS_NAME_RESULT)Marshal.PtrToStructure(pResult, typeof(DS_NAME_RESULT));
return Result.Items;
}
finally
{
Ntdsapi.DsFreeNameResult(pResult);
}
}
}
}
public void Dispose()
{
uint ret = Ntdsapi.DsUnBind(ref handle);
System.Diagnostics.Debug.WriteLineIf(ret != 0, "Error unbinding :\t" + ret.ToString());
}
}
public void Dispose()
{
uint ret = Ntdsapi.DsUnBind(ref handle);
System.Diagnostics.Debug.WriteLineIf(ret != 0, "Error unbinding :\t" + ret.ToString());
}
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct DS_NAME_RESULT
{
public uint cItems;
internal IntPtr rItems; // PDS_NAME_RESULT_ITEM
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct DS_NAME_RESULT
{
public uint cItems;
internal IntPtr rItems; // PDS_NAME_RESULT_ITEM
public DS_NAME_RESULT_ITEM[] Items
{
get
{
if (rItems == IntPtr.Zero)
return new DS_NAME_RESULT_ITEM[0];
var ResultArray = new DS_NAME_RESULT_ITEM[cItems];
Type strType = typeof(DS_NAME_RESULT_ITEM);
int stSize = Marshal.SizeOf(strType);
IntPtr curptr;
for (uint i = 0; i < cItems; i++)
{
curptr = new IntPtr(rItems.ToInt64() + (i * stSize));
ResultArray[i] = (DS_NAME_RESULT_ITEM)Marshal.PtrToStructure(curptr, strType);
}
return ResultArray;
}
}
}
public DS_NAME_RESULT_ITEM[] Items
{
get
{
if (rItems == IntPtr.Zero)
return new DS_NAME_RESULT_ITEM[0];
var ResultArray = new DS_NAME_RESULT_ITEM[cItems];
Type strType = typeof(DS_NAME_RESULT_ITEM);
int stSize = Marshal.SizeOf(strType);
IntPtr curptr;
for (uint i = 0; i < cItems; i++)
{
curptr = new IntPtr(rItems.ToInt64() + (i * stSize));
ResultArray[i] = (DS_NAME_RESULT_ITEM)Marshal.PtrToStructure(curptr, strType);
}
return ResultArray;
}
}
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct DS_NAME_RESULT_ITEM
{
public DS_NAME_ERROR status;
public string pDomain;
public string pName;
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct DS_NAME_RESULT_ITEM
{
public DS_NAME_ERROR status;
public string pDomain;
public string pName;
public override string ToString()
{
if (status == DS_NAME_ERROR.DS_NAME_NO_ERROR)
return pName;
return string.Empty;
}
}
}
public override string ToString()
{
if (status == DS_NAME_ERROR.DS_NAME_NO_ERROR)
return pName;
return string.Empty;
}
}
}
}

View File

@@ -7,131 +7,131 @@ using winPEAS.Native.Enums;
namespace winPEAS.TaskScheduler.TaskEditor.Native
{
internal static partial class NativeMethods
{
const int MAX_PREFERRED_LENGTH = -1;
{
const int MAX_PREFERRED_LENGTH = -1;
public enum ServerPlatform
{
DOS = 300,
OS2 = 400,
NT = 500,
OSF = 600,
VMS = 700
}
public enum ServerPlatform
{
DOS = 300,
OS2 = 400,
NT = 500,
OSF = 600,
VMS = 700
}
[StructLayout(LayoutKind.Sequential)]
public struct SERVER_INFO_100
{
public ServerPlatform PlatformId;
[MarshalAs(UnmanagedType.LPWStr)]
public string Name;
}
[StructLayout(LayoutKind.Sequential)]
public struct SERVER_INFO_100
{
public ServerPlatform PlatformId;
[MarshalAs(UnmanagedType.LPWStr)]
public string Name;
}
[StructLayout(LayoutKind.Sequential)]
public struct SERVER_INFO_101
{
public ServerPlatform PlatformId;
[MarshalAs(UnmanagedType.LPWStr)]
public string Name;
public int VersionMajor;
public int VersionMinor;
public ServerTypes Type;
[MarshalAs(UnmanagedType.LPWStr)]
public string Comment;
}
[StructLayout(LayoutKind.Sequential)]
public struct SERVER_INFO_101
{
public ServerPlatform PlatformId;
[MarshalAs(UnmanagedType.LPWStr)]
public string Name;
public int VersionMajor;
public int VersionMinor;
public ServerTypes Type;
[MarshalAs(UnmanagedType.LPWStr)]
public string Comment;
}
[StructLayout(LayoutKind.Sequential)]
public struct SERVER_INFO_102
{
public ServerPlatform PlatformId;
[MarshalAs(UnmanagedType.LPWStr)]
public string Name;
public int VersionMajor;
public int VersionMinor;
public ServerTypes Type;
[MarshalAs(UnmanagedType.LPWStr)]
public string Comment;
public int MaxUsers;
public int AutoDisconnectMinutes;
[MarshalAs(UnmanagedType.Bool)]
public bool Hidden;
public int NetworkAnnounceRate;
public int NetworkAnnounceRateDelta;
public int UsersPerLicense;
[MarshalAs(UnmanagedType.LPWStr)]
public string UserDirectoryPath;
}
[StructLayout(LayoutKind.Sequential)]
public struct SERVER_INFO_102
{
public ServerPlatform PlatformId;
[MarshalAs(UnmanagedType.LPWStr)]
public string Name;
public int VersionMajor;
public int VersionMinor;
public ServerTypes Type;
[MarshalAs(UnmanagedType.LPWStr)]
public string Comment;
public int MaxUsers;
public int AutoDisconnectMinutes;
[MarshalAs(UnmanagedType.Bool)]
public bool Hidden;
public int NetworkAnnounceRate;
public int NetworkAnnounceRateDelta;
public int UsersPerLicense;
[MarshalAs(UnmanagedType.LPWStr)]
public string UserDirectoryPath;
}
[StructLayout(LayoutKind.Sequential)]
public struct NetworkComputerInfo // SERVER_INFO_101
{
ServerPlatform sv101_platform_id;
[MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
string sv101_name;
int sv101_version_major;
int sv101_version_minor;
ServerTypes sv101_type;
[MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
string sv101_comment;
[StructLayout(LayoutKind.Sequential)]
public struct NetworkComputerInfo // SERVER_INFO_101
{
ServerPlatform sv101_platform_id;
[MarshalAs(UnmanagedType.LPWStr)]
string sv101_name;
int sv101_version_major;
int sv101_version_minor;
ServerTypes sv101_type;
[MarshalAs(UnmanagedType.LPWStr)]
string sv101_comment;
public ServerPlatform Platform => sv101_platform_id;
public string Name => sv101_name;
public string Comment => sv101_comment;
public ServerTypes ServerTypes => sv101_type;
public Version Version => new Version(sv101_version_major, sv101_version_minor);
};
public ServerPlatform Platform => sv101_platform_id;
public string Name => sv101_name;
public string Comment => sv101_comment;
public ServerTypes ServerTypes => sv101_type;
public Version Version => new Version(sv101_version_major, sv101_version_minor);
};
public static IEnumerable<string> GetNetworkComputerNames(ServerTypes serverTypes = ServerTypes.Workstation | ServerTypes.Server, string domain = null) =>
Array.ConvertAll(NetServerEnum<SERVER_INFO_100>(serverTypes, domain), si => si.Name);
public static IEnumerable<string> GetNetworkComputerNames(ServerTypes serverTypes = ServerTypes.Workstation | ServerTypes.Server, string domain = null) =>
Array.ConvertAll(NetServerEnum<SERVER_INFO_100>(serverTypes, domain), si => si.Name);
public static IEnumerable<NetworkComputerInfo> GetNetworkComputerInfo(ServerTypes serverTypes = ServerTypes.Workstation | ServerTypes.Server, string domain = null) =>
NetServerEnum<NetworkComputerInfo>(serverTypes, domain, 101);
public static IEnumerable<NetworkComputerInfo> GetNetworkComputerInfo(ServerTypes serverTypes = ServerTypes.Workstation | ServerTypes.Server, string domain = null) =>
NetServerEnum<NetworkComputerInfo>(serverTypes, domain, 101);
public static T[] NetServerEnum<T>(ServerTypes serverTypes = ServerTypes.Workstation | ServerTypes.Server, string domain = null, int level = 0) where T : struct
{
if (level == 0)
level = int.Parse(System.Text.RegularExpressions.Regex.Replace(typeof(T).Name, @"[^\d]", ""));
public static T[] NetServerEnum<T>(ServerTypes serverTypes = ServerTypes.Workstation | ServerTypes.Server, string domain = null, int level = 0) where T : struct
{
if (level == 0)
level = int.Parse(System.Text.RegularExpressions.Regex.Replace(typeof(T).Name, @"[^\d]", ""));
IntPtr bufptr = IntPtr.Zero;
try
{
int entriesRead, totalEntries;
IntPtr resumeHandle = IntPtr.Zero;
IntPtr bufptr = IntPtr.Zero;
try
{
int entriesRead, totalEntries;
IntPtr resumeHandle = IntPtr.Zero;
int ret = Netapi32.NetServerEnum(null, level, out bufptr, MAX_PREFERRED_LENGTH, out entriesRead, out totalEntries, serverTypes, domain, resumeHandle);
if (ret == 0)
return InteropUtil.ToArray<T>(bufptr, entriesRead);
throw new System.ComponentModel.Win32Exception(ret);
}
finally
{
int ret = Netapi32.NetServerEnum(null, level, out bufptr, MAX_PREFERRED_LENGTH, out entriesRead, out totalEntries, serverTypes, domain, resumeHandle);
if (ret == 0)
return InteropUtil.ToArray<T>(bufptr, entriesRead);
throw new System.ComponentModel.Win32Exception(ret);
}
finally
{
Netapi32.NetApiBufferFree(bufptr);
}
}
}
}
public static T NetServerGetInfo<T>(string serverName, int level = 0) where T : struct
{
if (level == 0)
level = int.Parse(System.Text.RegularExpressions.Regex.Replace(typeof(T).Name, @"[^\d]", ""));
public static T NetServerGetInfo<T>(string serverName, int level = 0) where T : struct
{
if (level == 0)
level = int.Parse(System.Text.RegularExpressions.Regex.Replace(typeof(T).Name, @"[^\d]", ""));
IntPtr ptr = IntPtr.Zero;
try
{
int ret = Netapi32.NetServerGetInfo(serverName, level, out ptr);
IntPtr ptr = IntPtr.Zero;
try
{
int ret = Netapi32.NetServerGetInfo(serverName, level, out ptr);
if (ret != 0)
{
throw new System.ComponentModel.Win32Exception(ret);
}
return (T)Marshal.PtrToStructure(ptr, typeof(T));
}
finally
{
return (T)Marshal.PtrToStructure(ptr, typeof(T));
}
finally
{
if (ptr != IntPtr.Zero)
{
Netapi32.NetApiBufferFree(ptr);
}
}
}
}
}
}
}
}

View File

@@ -3,114 +3,114 @@ using System.Runtime.InteropServices;
namespace winPEAS.TaskScheduler.TaskEditor.Native
{
internal static partial class NativeMethods
{
[StructLayout(LayoutKind.Sequential, Pack = 2)]
internal struct SYSTEMTIME : IConvertible
{
public ushort Year;
public ushort Month;
public ushort DayOfWeek;
public ushort Day;
public ushort Hour;
public ushort Minute;
public ushort Second;
public ushort Milliseconds;
internal static partial class NativeMethods
{
[StructLayout(LayoutKind.Sequential, Pack = 2)]
internal struct SYSTEMTIME : IConvertible
{
public ushort Year;
public ushort Month;
public ushort DayOfWeek;
public ushort Day;
public ushort Hour;
public ushort Minute;
public ushort Second;
public ushort Milliseconds;
public SYSTEMTIME(DateTime dt)
{
dt = dt.ToLocalTime();
Year = Convert.ToUInt16(dt.Year);
Month = Convert.ToUInt16(dt.Month);
DayOfWeek = Convert.ToUInt16(dt.DayOfWeek);
Day = Convert.ToUInt16(dt.Day);
Hour = Convert.ToUInt16(dt.Hour);
Minute = Convert.ToUInt16(dt.Minute);
Second = Convert.ToUInt16(dt.Second);
Milliseconds = Convert.ToUInt16(dt.Millisecond);
}
public SYSTEMTIME(DateTime dt)
{
dt = dt.ToLocalTime();
Year = Convert.ToUInt16(dt.Year);
Month = Convert.ToUInt16(dt.Month);
DayOfWeek = Convert.ToUInt16(dt.DayOfWeek);
Day = Convert.ToUInt16(dt.Day);
Hour = Convert.ToUInt16(dt.Hour);
Minute = Convert.ToUInt16(dt.Minute);
Second = Convert.ToUInt16(dt.Second);
Milliseconds = Convert.ToUInt16(dt.Millisecond);
}
public SYSTEMTIME(ushort year, ushort month, ushort day, ushort hour = 0, ushort minute = 0, ushort second = 0, ushort millisecond = 0)
{
Year = year;
Month = month;
Day = day;
Hour = hour;
Minute = minute;
Second = second;
Milliseconds = millisecond;
DayOfWeek = 0;
}
public SYSTEMTIME(ushort year, ushort month, ushort day, ushort hour = 0, ushort minute = 0, ushort second = 0, ushort millisecond = 0)
{
Year = year;
Month = month;
Day = day;
Hour = hour;
Minute = minute;
Second = second;
Milliseconds = millisecond;
DayOfWeek = 0;
}
public static implicit operator DateTime(SYSTEMTIME st)
{
if (st.Year == 0 || st == MinValue)
return DateTime.MinValue;
if (st == MaxValue)
return DateTime.MaxValue;
return new DateTime(st.Year, st.Month, st.Day, st.Hour, st.Minute, st.Second, st.Milliseconds, DateTimeKind.Local);
}
public static implicit operator DateTime(SYSTEMTIME st)
{
if (st.Year == 0 || st == MinValue)
return DateTime.MinValue;
if (st == MaxValue)
return DateTime.MaxValue;
return new DateTime(st.Year, st.Month, st.Day, st.Hour, st.Minute, st.Second, st.Milliseconds, DateTimeKind.Local);
}
public static implicit operator SYSTEMTIME(DateTime dt) => new SYSTEMTIME(dt);
public static implicit operator SYSTEMTIME(DateTime dt) => new SYSTEMTIME(dt);
public static bool operator ==(SYSTEMTIME s1, SYSTEMTIME s2) => (s1.Year == s2.Year && s1.Month == s2.Month && s1.Day == s2.Day && s1.Hour == s2.Hour && s1.Minute == s2.Minute && s1.Second == s2.Second && s1.Milliseconds == s2.Milliseconds);
public static bool operator ==(SYSTEMTIME s1, SYSTEMTIME s2) => (s1.Year == s2.Year && s1.Month == s2.Month && s1.Day == s2.Day && s1.Hour == s2.Hour && s1.Minute == s2.Minute && s1.Second == s2.Second && s1.Milliseconds == s2.Milliseconds);
public static bool operator !=(SYSTEMTIME s1, SYSTEMTIME s2) => !(s1 == s2);
public static bool operator !=(SYSTEMTIME s1, SYSTEMTIME s2) => !(s1 == s2);
public static readonly SYSTEMTIME MinValue, MaxValue;
public static readonly SYSTEMTIME MinValue, MaxValue;
static SYSTEMTIME()
{
MinValue = new SYSTEMTIME(1601, 1, 1);
MaxValue = new SYSTEMTIME(30827, 12, 31, 23, 59, 59, 999);
}
static SYSTEMTIME()
{
MinValue = new SYSTEMTIME(1601, 1, 1);
MaxValue = new SYSTEMTIME(30827, 12, 31, 23, 59, 59, 999);
}
public override bool Equals(object obj)
{
if (obj is SYSTEMTIME)
return ((SYSTEMTIME)obj) == this;
if (obj is DateTime)
return ((DateTime)this).Equals(obj);
return base.Equals(obj);
}
public override bool Equals(object obj)
{
if (obj is SYSTEMTIME)
return ((SYSTEMTIME)obj) == this;
if (obj is DateTime)
return ((DateTime)this).Equals(obj);
return base.Equals(obj);
}
public override int GetHashCode() => ((DateTime)this).GetHashCode();
public override int GetHashCode() => ((DateTime)this).GetHashCode();
public override string ToString() => ((DateTime)this).ToString();
public override string ToString() => ((DateTime)this).ToString();
TypeCode IConvertible.GetTypeCode() => ((IConvertible)(DateTime)this).GetTypeCode();
TypeCode IConvertible.GetTypeCode() => ((IConvertible)(DateTime)this).GetTypeCode();
bool IConvertible.ToBoolean(IFormatProvider provider) => ((IConvertible)(DateTime)this).ToBoolean(provider);
bool IConvertible.ToBoolean(IFormatProvider provider) => ((IConvertible)(DateTime)this).ToBoolean(provider);
byte IConvertible.ToByte(IFormatProvider provider) => ((IConvertible)(DateTime)this).ToByte(provider);
byte IConvertible.ToByte(IFormatProvider provider) => ((IConvertible)(DateTime)this).ToByte(provider);
char IConvertible.ToChar(IFormatProvider provider) => ((IConvertible)(DateTime)this).ToChar(provider);
char IConvertible.ToChar(IFormatProvider provider) => ((IConvertible)(DateTime)this).ToChar(provider);
DateTime IConvertible.ToDateTime(IFormatProvider provider) => (DateTime)this;
DateTime IConvertible.ToDateTime(IFormatProvider provider) => (DateTime)this;
decimal IConvertible.ToDecimal(IFormatProvider provider) => ((IConvertible)(DateTime)this).ToDecimal(provider);
decimal IConvertible.ToDecimal(IFormatProvider provider) => ((IConvertible)(DateTime)this).ToDecimal(provider);
double IConvertible.ToDouble(IFormatProvider provider) => ((IConvertible)(DateTime)this).ToDouble(provider);
double IConvertible.ToDouble(IFormatProvider provider) => ((IConvertible)(DateTime)this).ToDouble(provider);
short IConvertible.ToInt16(IFormatProvider provider) => ((IConvertible)(DateTime)this).ToInt16(provider);
short IConvertible.ToInt16(IFormatProvider provider) => ((IConvertible)(DateTime)this).ToInt16(provider);
int IConvertible.ToInt32(IFormatProvider provider) => ((IConvertible)(DateTime)this).ToInt32(provider);
int IConvertible.ToInt32(IFormatProvider provider) => ((IConvertible)(DateTime)this).ToInt32(provider);
long IConvertible.ToInt64(IFormatProvider provider) => ((IConvertible)(DateTime)this).ToInt64(provider);
long IConvertible.ToInt64(IFormatProvider provider) => ((IConvertible)(DateTime)this).ToInt64(provider);
sbyte IConvertible.ToSByte(IFormatProvider provider) => ((IConvertible)(DateTime)this).ToSByte(provider);
sbyte IConvertible.ToSByte(IFormatProvider provider) => ((IConvertible)(DateTime)this).ToSByte(provider);
float IConvertible.ToSingle(IFormatProvider provider) => ((IConvertible)(DateTime)this).ToSingle(provider);
float IConvertible.ToSingle(IFormatProvider provider) => ((IConvertible)(DateTime)this).ToSingle(provider);
string IConvertible.ToString(IFormatProvider provider) => ((IConvertible)(DateTime)this).ToString(provider);
string IConvertible.ToString(IFormatProvider provider) => ((IConvertible)(DateTime)this).ToString(provider);
object IConvertible.ToType(Type conversionType, IFormatProvider provider) => ((IConvertible)(DateTime)this).ToType(conversionType, provider);
object IConvertible.ToType(Type conversionType, IFormatProvider provider) => ((IConvertible)(DateTime)this).ToType(conversionType, provider);
ushort IConvertible.ToUInt16(IFormatProvider provider) => ((IConvertible)(DateTime)this).ToUInt16(provider);
ushort IConvertible.ToUInt16(IFormatProvider provider) => ((IConvertible)(DateTime)this).ToUInt16(provider);
uint IConvertible.ToUInt32(IFormatProvider provider) => ((IConvertible)(DateTime)this).ToUInt32(provider);
uint IConvertible.ToUInt32(IFormatProvider provider) => ((IConvertible)(DateTime)this).ToUInt32(provider);
ulong IConvertible.ToUInt64(IFormatProvider provider) => ((IConvertible)(DateTime)this).ToUInt64(provider);
}
}
ulong IConvertible.ToUInt64(IFormatProvider provider) => ((IConvertible)(DateTime)this).ToUInt64(provider);
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -2,173 +2,170 @@
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using winPEAS.TaskScheduler.TaskEditor.Native;
using winPEAS.TaskScheduler.V2;
namespace winPEAS.TaskScheduler
{
/// <summary>Provides information and control for a collection of folders that contain tasks.</summary>
public sealed class TaskFolderCollection : ICollection<TaskFolder>, IDisposable, INotifyCollectionChanged, INotifyPropertyChanged
{
private const string IndexerName = "Item[]";
private readonly TaskFolder parent;
private readonly TaskFolder[] v1FolderList;
private readonly ITaskFolderCollection v2FolderList;
/// <summary>Provides information and control for a collection of folders that contain tasks.</summary>
public sealed class TaskFolderCollection : ICollection<TaskFolder>, IDisposable, INotifyCollectionChanged, INotifyPropertyChanged
{
private const string IndexerName = "Item[]";
private readonly TaskFolder parent;
private readonly TaskFolder[] v1FolderList;
private readonly ITaskFolderCollection v2FolderList;
internal TaskFolderCollection() => v1FolderList = new TaskFolder[0];
internal TaskFolderCollection() => v1FolderList = new TaskFolder[0];
internal TaskFolderCollection([NotNull] TaskFolder folder, [NotNull] ITaskFolderCollection iCollection)
{
parent = folder;
v2FolderList = iCollection;
}
internal TaskFolderCollection([NotNull] TaskFolder folder, [NotNull] ITaskFolderCollection iCollection)
{
parent = folder;
v2FolderList = iCollection;
}
/// <summary>Occurs when a collection changes.</summary>
public event NotifyCollectionChangedEventHandler CollectionChanged;
/// <summary>Occurs when a collection changes.</summary>
public event NotifyCollectionChangedEventHandler CollectionChanged;
/// <summary>Occurs when a property value changes.</summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>Occurs when a property value changes.</summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>Gets the number of items in the collection.</summary>
public int Count => v2FolderList?.Count ?? v1FolderList.Length;
/// <summary>Gets the number of items in the collection.</summary>
public int Count => v2FolderList?.Count ?? v1FolderList.Length;
/// <summary>Gets a value indicating whether the <see cref="ICollection{T}"/> is read-only.</summary>
bool ICollection<TaskFolder>.IsReadOnly => false;
/// <summary>Gets a value indicating whether the <see cref="ICollection{T}"/> is read-only.</summary>
bool ICollection<TaskFolder>.IsReadOnly => false;
/// <summary>Gets the specified folder from the collection.</summary>
/// <param name="index">The index of the folder to be retrieved.</param>
/// <returns>A TaskFolder instance that represents the requested folder.</returns>
public TaskFolder this[int index]
{
get
{
if (v2FolderList != null)
return new TaskFolder(parent.TaskService, v2FolderList[++index]);
return v1FolderList[index];
}
}
/// <summary>Gets the specified folder from the collection.</summary>
/// <param name="index">The index of the folder to be retrieved.</param>
/// <returns>A TaskFolder instance that represents the requested folder.</returns>
public TaskFolder this[int index]
{
get
{
if (v2FolderList != null)
return new TaskFolder(parent.TaskService, v2FolderList[++index]);
return v1FolderList[index];
}
}
/// <summary>Gets the specified folder from the collection.</summary>
/// <param name="path">The path of the folder to be retrieved.</param>
/// <returns>A TaskFolder instance that represents the requested folder.</returns>
public TaskFolder this[[NotNull] string path]
{
get
{
try
{
if (v2FolderList != null)
return parent.GetFolder(path);
if (v1FolderList != null && v1FolderList.Length > 0 && (path == string.Empty || path == "\\"))
return v1FolderList[0];
}
catch { }
throw new ArgumentException(@"Path not found", nameof(path));
}
}
/// <summary>Gets the specified folder from the collection.</summary>
/// <param name="path">The path of the folder to be retrieved.</param>
/// <returns>A TaskFolder instance that represents the requested folder.</returns>
public TaskFolder this[[NotNull] string path]
{
get
{
try
{
if (v2FolderList != null)
return parent.GetFolder(path);
if (v1FolderList != null && v1FolderList.Length > 0 && (path == string.Empty || path == "\\"))
return v1FolderList[0];
}
catch { }
throw new ArgumentException(@"Path not found", nameof(path));
}
}
/// <summary>Adds an item to the <see cref="ICollection{T}"/>.</summary>
/// <param name="item">The object to add to the <see cref="ICollection{T}"/>.</param>
/// <exception cref="System.NotImplementedException">
/// This action is technically unfeasible due to limitations of the underlying library. Use the <see
/// cref="TaskFolder.CreateFolder(string, string, bool)"/> instead.
/// </exception>
public void Add([NotNull] TaskFolder item) => throw new NotImplementedException();
/// <summary>Adds an item to the <see cref="ICollection{T}"/>.</summary>
/// <param name="item">The object to add to the <see cref="ICollection{T}"/>.</param>
/// <exception cref="System.NotImplementedException">
/// This action is technically unfeasible due to limitations of the underlying library. Use the <see
/// cref="TaskFolder.CreateFolder(string, string, bool)"/> instead.
/// </exception>
public void Add([NotNull] TaskFolder item) => throw new NotImplementedException();
/// <summary>Removes all items from the <see cref="ICollection{T}"/>.</summary>
public void Clear()
{
if (v2FolderList != null)
{
for (var i = v2FolderList.Count; i > 0; i--)
parent.DeleteFolder(v2FolderList[i].Name, false);
OnNotifyPropertyChanged(nameof(Count));
OnNotifyPropertyChanged(IndexerName);
CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
}
/// <summary>Removes all items from the <see cref="ICollection{T}"/>.</summary>
public void Clear()
{
if (v2FolderList != null)
{
for (var i = v2FolderList.Count; i > 0; i--)
parent.DeleteFolder(v2FolderList[i].Name, false);
OnNotifyPropertyChanged(nameof(Count));
OnNotifyPropertyChanged(IndexerName);
CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
}
/// <summary>Determines whether the <see cref="ICollection{T}"/> contains a specific value.</summary>
/// <param name="item">The object to locate in the <see cref="ICollection{T}"/>.</param>
/// <returns>true if <paramref name="item"/> is found in the <see cref="ICollection{T}"/>; otherwise, false.</returns>
public bool Contains([NotNull] TaskFolder item)
{
if (v2FolderList != null)
{
for (var i = v2FolderList.Count; i > 0; i--)
if (string.Equals(item.Path, v2FolderList[i].Path, StringComparison.CurrentCultureIgnoreCase))
return true;
}
else
return item.Path == "\\";
return false;
}
/// <summary>Determines whether the <see cref="ICollection{T}"/> contains a specific value.</summary>
/// <param name="item">The object to locate in the <see cref="ICollection{T}"/>.</param>
/// <returns>true if <paramref name="item"/> is found in the <see cref="ICollection{T}"/>; otherwise, false.</returns>
public bool Contains([NotNull] TaskFolder item)
{
if (v2FolderList != null)
{
for (var i = v2FolderList.Count; i > 0; i--)
if (string.Equals(item.Path, v2FolderList[i].Path, StringComparison.CurrentCultureIgnoreCase))
return true;
}
else
return item.Path == "\\";
return false;
}
/// <summary>Copies the elements of the ICollection to an Array, starting at a particular Array index.</summary>
/// <param name="array">
/// The one-dimensional Array that is the destination of the elements copied from <see cref="ICollection{T}"/>. The Array must have
/// zero-based indexing.
/// </param>
/// <param name="arrayIndex">The zero-based index in array at which copying begins.</param>
public void CopyTo(TaskFolder[] array, int arrayIndex)
{
if (arrayIndex < 0) throw new ArgumentOutOfRangeException(nameof(arrayIndex));
if (array == null) throw new ArgumentNullException(nameof(array));
if (v2FolderList != null)
{
if (arrayIndex + Count > array.Length)
throw new ArgumentException();
foreach (var f in this)
array[arrayIndex++] = f;
}
else
{
if (arrayIndex + v1FolderList.Length > array.Length)
throw new ArgumentException();
v1FolderList.CopyTo(array, arrayIndex);
}
}
/// <summary>Copies the elements of the ICollection to an Array, starting at a particular Array index.</summary>
/// <param name="array">
/// The one-dimensional Array that is the destination of the elements copied from <see cref="ICollection{T}"/>. The Array must have
/// zero-based indexing.
/// </param>
/// <param name="arrayIndex">The zero-based index in array at which copying begins.</param>
public void CopyTo(TaskFolder[] array, int arrayIndex)
{
if (arrayIndex < 0) throw new ArgumentOutOfRangeException(nameof(arrayIndex));
if (array == null) throw new ArgumentNullException(nameof(array));
if (v2FolderList != null)
{
if (arrayIndex + Count > array.Length)
throw new ArgumentException();
foreach (var f in this)
array[arrayIndex++] = f;
}
else
{
if (arrayIndex + v1FolderList.Length > array.Length)
throw new ArgumentException();
v1FolderList.CopyTo(array, arrayIndex);
}
}
/// <summary>Releases all resources used by this class.</summary>
public void Dispose()
{
if (v1FolderList != null && v1FolderList.Length > 0)
{
v1FolderList[0].Dispose();
v1FolderList[0] = null;
}
if (v2FolderList != null)
System.Runtime.InteropServices.Marshal.ReleaseComObject(v2FolderList);
}
/// <summary>Releases all resources used by this class.</summary>
public void Dispose()
{
if (v1FolderList != null && v1FolderList.Length > 0)
{
v1FolderList[0].Dispose();
v1FolderList[0] = null;
}
if (v2FolderList != null)
System.Runtime.InteropServices.Marshal.ReleaseComObject(v2FolderList);
}
/// <summary>Determines whether the specified folder exists.</summary>
/// <param name="path">The path of the folder.</param>
/// <returns>true if folder exists; otherwise, false.</returns>
public bool Exists([NotNull] string path)
{
try
{
parent.GetFolder(path);
return true;
}
catch { }
return false;
}
/// <summary>Determines whether the specified folder exists.</summary>
/// <param name="path">The path of the folder.</param>
/// <returns>true if folder exists; otherwise, false.</returns>
public bool Exists([NotNull] string path)
{
try
{
parent.GetFolder(path);
return true;
}
catch { }
return false;
}
/// <summary>Gets a list of items in a collection.</summary>
/// <returns>Enumerated list of items in the collection.</returns>
public IEnumerator<TaskFolder> GetEnumerator()
{
if (v2FolderList != null)
return new ComEnumerator<TaskFolder, ITaskFolder>(() => v2FolderList.Count, (object o) => v2FolderList[o], o => new TaskFolder(parent.TaskService, o));
return Array.AsReadOnly(v1FolderList).GetEnumerator();
}
/// <summary>Gets a list of items in a collection.</summary>
/// <returns>Enumerated list of items in the collection.</returns>
public IEnumerator<TaskFolder> GetEnumerator()
{
if (v2FolderList != null)
return new ComEnumerator<TaskFolder, ITaskFolder>(() => v2FolderList.Count, (object o) => v2FolderList[o], o => new TaskFolder(parent.TaskService, o));
return Array.AsReadOnly(v1FolderList).GetEnumerator();
}
/*
/*
/// <summary>Returns the index of the TaskFolder within the collection.</summary>
/// <param name="item">TaskFolder to find.</param>
/// <returns>Index of the TaskFolder; -1 if not found.</returns>
@@ -196,42 +193,42 @@ namespace winPEAS.TaskScheduler
}
*/
/// <summary>Removes the first occurrence of a specific object from the <see cref="ICollection{T}"/>.</summary>
/// <param name="item">The object to remove from the <see cref="ICollection{T}"/>.</param>
/// <returns>
/// true if <paramref name="item"/> was successfully removed from the <see cref="ICollection{T}"/>; otherwise, false. This method
/// also returns false if <paramref name="item"/> is not found in the original <see cref="ICollection{T}"/>.
/// </returns>
public bool Remove([NotNull] TaskFolder item)
{
if (v2FolderList != null)
{
for (var i = v2FolderList.Count; i > 0; i--)
{
if (string.Equals(item.Path, v2FolderList[i].Path, StringComparison.CurrentCultureIgnoreCase))
{
try
{
parent.DeleteFolder(v2FolderList[i].Name);
OnNotifyPropertyChanged(nameof(Count));
OnNotifyPropertyChanged(IndexerName);
CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item, i));
}
catch
{
return false;
}
return true;
}
}
}
return false;
}
/// <summary>Removes the first occurrence of a specific object from the <see cref="ICollection{T}"/>.</summary>
/// <param name="item">The object to remove from the <see cref="ICollection{T}"/>.</param>
/// <returns>
/// true if <paramref name="item"/> was successfully removed from the <see cref="ICollection{T}"/>; otherwise, false. This method
/// also returns false if <paramref name="item"/> is not found in the original <see cref="ICollection{T}"/>.
/// </returns>
public bool Remove([NotNull] TaskFolder item)
{
if (v2FolderList != null)
{
for (var i = v2FolderList.Count; i > 0; i--)
{
if (string.Equals(item.Path, v2FolderList[i].Path, StringComparison.CurrentCultureIgnoreCase))
{
try
{
parent.DeleteFolder(v2FolderList[i].Name);
OnNotifyPropertyChanged(nameof(Count));
OnNotifyPropertyChanged(IndexerName);
CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item, i));
}
catch
{
return false;
}
return true;
}
}
}
return false;
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator();
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator();
/// <summary>Called when a property has changed to notify any attached elements.</summary>
/// <param name="propertyName">Name of the property.</param>
private void OnNotifyPropertyChanged([CallerMemberName] string propertyName = "") => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
/// <summary>Called when a property has changed to notify any attached elements.</summary>
/// <param name="propertyName">Name of the property.</param>
private void OnNotifyPropertyChanged([CallerMemberName] string propertyName = "") => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}

View File

@@ -1,58 +1,54 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace winPEAS.TaskScheduler
{
/// <summary>
/// Defines the methods that are called by the Task Scheduler service to manage a COM handler.
/// </summary>
/// <remarks>
/// This interface must be implemented for a task to perform a COM handler action. When the Task Scheduler performs a COM handler action, it creates and activates the handler and calls the methods of this interface as needed. For information on specifying a COM handler action, see the <see cref="ComHandlerAction"/> class.
/// </remarks>
[ComImport, Guid("839D7762-5121-4009-9234-4F0D19394F04"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), System.Security.SuppressUnmanagedCodeSecurity]
public interface ITaskHandler
{
/// <summary>
/// Called to start the COM handler. This method must be implemented by the handler.
/// </summary>
/// <param name="pHandlerServices">An <c>IUnkown</c> interface that is used to communicate back with the Task Scheduler.</param>
/// <param name="data">The arguments that are required by the handler. These arguments are defined in the <see cref="ComHandlerAction.Data"/> property of the COM handler action.</param>
void Start([In, MarshalAs(UnmanagedType.IUnknown)] object pHandlerServices, [In, MarshalAs(UnmanagedType.BStr)] string data);
/// <summary>
/// Called to stop the COM handler. This method must be implemented by the handler.
/// </summary>
/// <param name="pRetCode">The return code that the Task Schedule will raise as an event when the COM handler action is completed.</param>
void Stop([MarshalAs(UnmanagedType.Error)] out int pRetCode);
/// <summary>
/// Called to pause the COM handler. This method is optional and should only be implemented to give the Task Scheduler the ability to pause and restart the handler.
/// </summary>
void Pause();
/// <summary>
/// Called to resume the COM handler. This method is optional and should only be implemented to give the Task Scheduler the ability to resume the handler.
/// </summary>
void Resume();
}
/// <summary>
/// Defines the methods that are called by the Task Scheduler service to manage a COM handler.
/// </summary>
/// <remarks>
/// This interface must be implemented for a task to perform a COM handler action. When the Task Scheduler performs a COM handler action, it creates and activates the handler and calls the methods of this interface as needed. For information on specifying a COM handler action, see the <see cref="ComHandlerAction"/> class.
/// </remarks>
[ComImport, Guid("839D7762-5121-4009-9234-4F0D19394F04"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), System.Security.SuppressUnmanagedCodeSecurity]
public interface ITaskHandler
{
/// <summary>
/// Called to start the COM handler. This method must be implemented by the handler.
/// </summary>
/// <param name="pHandlerServices">An <c>IUnkown</c> interface that is used to communicate back with the Task Scheduler.</param>
/// <param name="data">The arguments that are required by the handler. These arguments are defined in the <see cref="ComHandlerAction.Data"/> property of the COM handler action.</param>
void Start([In, MarshalAs(UnmanagedType.IUnknown)] object pHandlerServices, [In, MarshalAs(UnmanagedType.BStr)] string data);
/// <summary>
/// Called to stop the COM handler. This method must be implemented by the handler.
/// </summary>
/// <param name="pRetCode">The return code that the Task Schedule will raise as an event when the COM handler action is completed.</param>
void Stop([MarshalAs(UnmanagedType.Error)] out int pRetCode);
/// <summary>
/// Called to pause the COM handler. This method is optional and should only be implemented to give the Task Scheduler the ability to pause and restart the handler.
/// </summary>
void Pause();
/// <summary>
/// Called to resume the COM handler. This method is optional and should only be implemented to give the Task Scheduler the ability to resume the handler.
/// </summary>
void Resume();
}
/// <summary>
/// Provides the methods that are used by COM handlers to notify the Task Scheduler about the status of the handler.
/// </summary>
[ComImport, Guid("EAEC7A8F-27A0-4DDC-8675-14726A01A38A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), System.Security.SuppressUnmanagedCodeSecurity]
public interface ITaskHandlerStatus
{
/// <summary>
/// Tells the Task Scheduler about the percentage of completion of the COM handler.
/// </summary>
/// <param name="percentComplete">A value that indicates the percentage of completion for the COM handler.</param>
/// <param name="statusMessage">The message that is displayed in the Task Scheduler UI.</param>
void UpdateStatus([In] short percentComplete, [In, MarshalAs(UnmanagedType.BStr)] string statusMessage);
/// <summary>
/// Tells the Task Scheduler that the COM handler is completed.
/// </summary>
/// <param name="taskErrCode">The error code that the Task Scheduler will raise as an event.</param>
void TaskCompleted([In, MarshalAs(UnmanagedType.Error)] int taskErrCode);
}
/// <summary>
/// Provides the methods that are used by COM handlers to notify the Task Scheduler about the status of the handler.
/// </summary>
[ComImport, Guid("EAEC7A8F-27A0-4DDC-8675-14726A01A38A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), System.Security.SuppressUnmanagedCodeSecurity]
public interface ITaskHandlerStatus
{
/// <summary>
/// Tells the Task Scheduler about the percentage of completion of the COM handler.
/// </summary>
/// <param name="percentComplete">A value that indicates the percentage of completion for the COM handler.</param>
/// <param name="statusMessage">The message that is displayed in the Task Scheduler UI.</param>
void UpdateStatus([In] short percentComplete, [In, MarshalAs(UnmanagedType.BStr)] string statusMessage);
/// <summary>
/// Tells the Task Scheduler that the COM handler is completed.
/// </summary>
/// <param name="taskErrCode">The error code that the Task Scheduler will raise as an event.</param>
void TaskCompleted([In, MarshalAs(UnmanagedType.Error)] int taskErrCode);
}
}

View File

@@ -9,456 +9,456 @@ namespace winPEAS.TaskScheduler
/// Specifies the access control rights that can be applied to Task Scheduler tasks.
/// </summary>
[Flags]
public enum TaskRights
{
/// <summary>Specifies the right to exert full control over a task folder or task, and to modify access control and audit rules. This value represents the right to do anything with a task and is the combination of all rights in this enumeration.</summary>
FullControl = 0x1f01ff,
/// <summary>Specifies the right to create tasks and folders, and to add or remove data from tasks. This right includes the following rights: .</summary>
Write = 0x120116,
/// <summary>Specifies the right to open and copy folders or tasks as read-only. This right includes the following rights: .</summary>
Read = 0x120089,
/// <summary>Specifies the right run tasks. This right includes the following rights: .</summary>
Execute = 0x120089,
/// <summary>The right to wait on a task.</summary>
Synchronize = 0x100000,
/// <summary>The right to change the owner of a task.</summary>
TakeOwnership = 0x80000,
/// <summary>Specifies the right to change the security and audit rules associated with a task or folder.</summary>
ChangePermissions = 0x40000,
/// <summary>The right to open and copy the access rules and audit rules for a task.</summary>
ReadPermissions = 0x20000,
/// <summary>The right to delete a folder or task.</summary>
Delete = 0x10000,
/// <summary>Specifies the right to open and write file system attributes to a folder or file. This does not include the ability to write data, extended attributes, or access and audit rules.</summary>
WriteAttributes = 0x100,
/// <summary>Specifies the right to open and copy file system attributes from a folder or task. For example, this value specifies the right to view the file creation or modified date. This does not include the right to read data, extended file system attributes, or access and audit rules.</summary>
ReadAttributes = 0x80,
/// <summary>Specifies the right to delete a folder and any tasks contained within that folder.</summary>
DeleteChild = 0x40,
/// <summary>Specifies the right to run a task.</summary>
ExecuteFile = 0x20,
/// <summary>Specifies the right to open and write extended file system attributes to a folder or file. This does not include the ability to write data, attributes, or access and audit rules.</summary>
WriteExtendedAttributes = 0x10,
/// <summary>Specifies the right to open and copy extended system attributes from a folder or task. For example, this value specifies the right to view author and content information. This does not include the right to read data, system attributes, or access and audit rules.</summary>
ReadExtendedAttributes = 8,
/// <summary>Specifies the right to append data to the end of a file.</summary>
AppendData = 4,
/// <summary>Specifies the right to open and write to a file or folder. This does not include the right to open and write file system attributes, extended file system attributes, or access and audit rules.</summary>
WriteData = 2,
/// <summary>Specifies the right to open and copy a task or folder. This does not include the right to read file system attributes, extended file system attributes, or access and audit rules.</summary>
ReadData = 1,
}
public enum TaskRights
{
/// <summary>Specifies the right to exert full control over a task folder or task, and to modify access control and audit rules. This value represents the right to do anything with a task and is the combination of all rights in this enumeration.</summary>
FullControl = 0x1f01ff,
/// <summary>Specifies the right to create tasks and folders, and to add or remove data from tasks. This right includes the following rights: .</summary>
Write = 0x120116,
/// <summary>Specifies the right to open and copy folders or tasks as read-only. This right includes the following rights: .</summary>
Read = 0x120089,
/// <summary>Specifies the right run tasks. This right includes the following rights: .</summary>
Execute = 0x120089,
/// <summary>The right to wait on a task.</summary>
Synchronize = 0x100000,
/// <summary>The right to change the owner of a task.</summary>
TakeOwnership = 0x80000,
/// <summary>Specifies the right to change the security and audit rules associated with a task or folder.</summary>
ChangePermissions = 0x40000,
/// <summary>The right to open and copy the access rules and audit rules for a task.</summary>
ReadPermissions = 0x20000,
/// <summary>The right to delete a folder or task.</summary>
Delete = 0x10000,
/// <summary>Specifies the right to open and write file system attributes to a folder or file. This does not include the ability to write data, extended attributes, or access and audit rules.</summary>
WriteAttributes = 0x100,
/// <summary>Specifies the right to open and copy file system attributes from a folder or task. For example, this value specifies the right to view the file creation or modified date. This does not include the right to read data, extended file system attributes, or access and audit rules.</summary>
ReadAttributes = 0x80,
/// <summary>Specifies the right to delete a folder and any tasks contained within that folder.</summary>
DeleteChild = 0x40,
/// <summary>Specifies the right to run a task.</summary>
ExecuteFile = 0x20,
/// <summary>Specifies the right to open and write extended file system attributes to a folder or file. This does not include the ability to write data, attributes, or access and audit rules.</summary>
WriteExtendedAttributes = 0x10,
/// <summary>Specifies the right to open and copy extended system attributes from a folder or task. For example, this value specifies the right to view author and content information. This does not include the right to read data, system attributes, or access and audit rules.</summary>
ReadExtendedAttributes = 8,
/// <summary>Specifies the right to append data to the end of a file.</summary>
AppendData = 4,
/// <summary>Specifies the right to open and write to a file or folder. This does not include the right to open and write file system attributes, extended file system attributes, or access and audit rules.</summary>
WriteData = 2,
/// <summary>Specifies the right to open and copy a task or folder. This does not include the right to read file system attributes, extended file system attributes, or access and audit rules.</summary>
ReadData = 1,
}
/// <summary>
/// Represents a set of access rights allowed or denied for a user or group. This class cannot be inherited.
/// </summary>
public sealed class TaskAccessRule : AccessRule
{
/// <summary>
/// Initializes a new instance of the <see cref="TaskAccessRule"/> class, specifying the user or group the rule applies to, the access rights, and whether the specified access rights are allowed or denied.
/// </summary>
/// <param name="identity">The user or group the rule applies to. Must be of type <see cref="SecurityIdentifier"/> or a type such as <see cref="NTAccount"/> that can be converted to type <see cref="SecurityIdentifier"/>.</param>
/// <param name="eventRights">A bitwise combination of <see cref="TaskRights"/> values specifying the rights allowed or denied.</param>
/// <param name="type">One of the <see cref="AccessControlType"/> values specifying whether the rights are allowed or denied.</param>
public TaskAccessRule([NotNull] IdentityReference identity, TaskRights eventRights, AccessControlType type)
: this(identity, (int)eventRights, false, InheritanceFlags.None, PropagationFlags.None, type)
{
}
/// <summary>
/// Represents a set of access rights allowed or denied for a user or group. This class cannot be inherited.
/// </summary>
public sealed class TaskAccessRule : AccessRule
{
/// <summary>
/// Initializes a new instance of the <see cref="TaskAccessRule"/> class, specifying the user or group the rule applies to, the access rights, and whether the specified access rights are allowed or denied.
/// </summary>
/// <param name="identity">The user or group the rule applies to. Must be of type <see cref="SecurityIdentifier"/> or a type such as <see cref="NTAccount"/> that can be converted to type <see cref="SecurityIdentifier"/>.</param>
/// <param name="eventRights">A bitwise combination of <see cref="TaskRights"/> values specifying the rights allowed or denied.</param>
/// <param name="type">One of the <see cref="AccessControlType"/> values specifying whether the rights are allowed or denied.</param>
public TaskAccessRule([NotNull] IdentityReference identity, TaskRights eventRights, AccessControlType type)
: this(identity, (int)eventRights, false, InheritanceFlags.None, PropagationFlags.None, type)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="TaskAccessRule"/> class, specifying the name of the user or group the rule applies to, the access rights, and whether the specified access rights are allowed or denied.
/// </summary>
/// <param name="identity">The name of the user or group the rule applies to.</param>
/// <param name="eventRights">A bitwise combination of <see cref="TaskRights"/> values specifying the rights allowed or denied.</param>
/// <param name="type">One of the <see cref="AccessControlType"/> values specifying whether the rights are allowed or denied.</param>
public TaskAccessRule([NotNull] string identity, TaskRights eventRights, AccessControlType type)
: this(new NTAccount(identity), (int)eventRights, false, InheritanceFlags.None, PropagationFlags.None, type)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="TaskAccessRule"/> class, specifying the name of the user or group the rule applies to, the access rights, and whether the specified access rights are allowed or denied.
/// </summary>
/// <param name="identity">The name of the user or group the rule applies to.</param>
/// <param name="eventRights">A bitwise combination of <see cref="TaskRights"/> values specifying the rights allowed or denied.</param>
/// <param name="type">One of the <see cref="AccessControlType"/> values specifying whether the rights are allowed or denied.</param>
public TaskAccessRule([NotNull] string identity, TaskRights eventRights, AccessControlType type)
: this(new NTAccount(identity), (int)eventRights, false, InheritanceFlags.None, PropagationFlags.None, type)
{
}
private TaskAccessRule([NotNull] IdentityReference identity, int accessMask, bool isInherited, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, AccessControlType type)
: base(identity, accessMask, isInherited, inheritanceFlags, propagationFlags, type)
{
}
private TaskAccessRule([NotNull] IdentityReference identity, int accessMask, bool isInherited, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, AccessControlType type)
: base(identity, accessMask, isInherited, inheritanceFlags, propagationFlags, type)
{
}
/// <summary>
/// Gets the rights allowed or denied by the access rule.
/// </summary>
/// <value>
/// A bitwise combination of <see cref="TaskRights"/> values indicating the rights allowed or denied by the access rule.
/// </value>
public TaskRights TaskRights => (TaskRights)AccessMask;
}
/// <summary>
/// Gets the rights allowed or denied by the access rule.
/// </summary>
/// <value>
/// A bitwise combination of <see cref="TaskRights"/> values indicating the rights allowed or denied by the access rule.
/// </value>
public TaskRights TaskRights => (TaskRights)AccessMask;
}
/// <summary>
/// Represents a set of access rights to be audited for a user or group. This class cannot be inherited.
/// </summary>
public sealed class TaskAuditRule : AuditRule
{
/// <summary>
/// Initializes a new instance of the <see cref="TaskAuditRule" /> class, specifying the user or group to audit, the rights to audit, and whether to audit success, failure, or both.
/// </summary>
/// <param name="identity">The user or group the rule applies to. Must be of type <see cref="SecurityIdentifier" /> or a type such as <see cref="NTAccount" /> that can be converted to type <see cref="SecurityIdentifier" />.</param>
/// <param name="eventRights">A bitwise combination of <see cref="TaskRights" /> values specifying the kinds of access to audit.</param>
/// <param name="flags">The audit flags.</param>
public TaskAuditRule([NotNull] IdentityReference identity, TaskRights eventRights, AuditFlags flags)
: this(identity, (int)eventRights, false, InheritanceFlags.None, PropagationFlags.None, flags)
{
}
/// <summary>
/// Represents a set of access rights to be audited for a user or group. This class cannot be inherited.
/// </summary>
public sealed class TaskAuditRule : AuditRule
{
/// <summary>
/// Initializes a new instance of the <see cref="TaskAuditRule" /> class, specifying the user or group to audit, the rights to audit, and whether to audit success, failure, or both.
/// </summary>
/// <param name="identity">The user or group the rule applies to. Must be of type <see cref="SecurityIdentifier" /> or a type such as <see cref="NTAccount" /> that can be converted to type <see cref="SecurityIdentifier" />.</param>
/// <param name="eventRights">A bitwise combination of <see cref="TaskRights" /> values specifying the kinds of access to audit.</param>
/// <param name="flags">The audit flags.</param>
public TaskAuditRule([NotNull] IdentityReference identity, TaskRights eventRights, AuditFlags flags)
: this(identity, (int)eventRights, false, InheritanceFlags.None, PropagationFlags.None, flags)
{
}
internal TaskAuditRule([NotNull] IdentityReference identity, int accessMask, bool isInherited, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, AuditFlags flags)
: base(identity, accessMask, isInherited, inheritanceFlags, propagationFlags, flags)
{
}
internal TaskAuditRule([NotNull] IdentityReference identity, int accessMask, bool isInherited, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, AuditFlags flags)
: base(identity, accessMask, isInherited, inheritanceFlags, propagationFlags, flags)
{
}
/// <summary>
/// Gets the access rights affected by the audit rule.
/// </summary>
/// <value>
/// A bitwise combination of <see cref="TaskRights"/> values that indicates the rights affected by the audit rule.
/// </value>
/// <remarks><see cref="TaskAuditRule"/> objects are immutable. You can create a new audit rule representing a different user, different rights, or a different combination of AuditFlags values, but you cannot modify an existing audit rule.</remarks>
public TaskRights TaskRights => (TaskRights)AccessMask;
}
/// <summary>
/// Gets the access rights affected by the audit rule.
/// </summary>
/// <value>
/// A bitwise combination of <see cref="TaskRights"/> values that indicates the rights affected by the audit rule.
/// </value>
/// <remarks><see cref="TaskAuditRule"/> objects are immutable. You can create a new audit rule representing a different user, different rights, or a different combination of AuditFlags values, but you cannot modify an existing audit rule.</remarks>
public TaskRights TaskRights => (TaskRights)AccessMask;
}
/// <summary>
/// Represents the Windows access control security for a Task Scheduler task. This class cannot be inherited.
/// </summary>
/// <remarks>
/// <para>A TaskSecurity object specifies access rights for a Task Scheduler task, and also specifies how access attempts are audited. Access rights to the task are expressed as rules, with each access rule represented by a <see cref="TaskAccessRule"/> object. Each auditing rule is represented by a <see cref="TaskAuditRule"/> object.</para>
/// <para>This mirrors the underlying Windows security system, in which each securable object has at most one discretionary access control list (DACL) that controls access to the secured object, and at most one system access control list (SACL) that specifies which access attempts are audited. The DACL and SACL are ordered lists of access control entries (ACE) that specify access and auditing for users and groups. A <see cref="TaskAccessRule"/> or <see cref="TaskAuditRule"/> object might represent more than one ACE.</para>
/// <para>Note</para>
/// <para>A <see cref="Task"/> object can represent a local task or a Task Scheduler task. Windows access control security is meaningful only for Task Scheduler tasks.</para>
/// <para>The TaskSecurity, <see cref="TaskAccessRule"/>, and <see cref="TaskAuditRule"/> classes hide the implementation details of ACLs and ACEs. They allow you to ignore the seventeen different ACE types and the complexity of correctly maintaining inheritance and propagation of access rights. These objects are also designed to prevent the following common access control errors:</para>
/// <list type="bullet">
/// <item><description>Creating a security descriptor with a null DACL. A null reference to a DACL allows any user to add access rules to an object, potentially creating a denial-of-service attack. A new TaskSecurity object always starts with an empty DACL, which denies all access for all users.</description></item>
/// <item><description>Violating the canonical ordering of ACEs. If the ACE list in the DACL is not kept in the canonical order, users might inadvertently be given access to the secured object. For example, denied access rights must always appear before allowed access rights. TaskSecurity objects maintain the correct order internally. </description></item>
/// <item><description>Manipulating security descriptor flags, which should be under resource manager control only.</description></item>
/// <item><description>Creating invalid combinations of ACE flags.</description></item>
/// <item><description>Manipulating inherited ACEs. Inheritance and propagation are handled by the resource manager, in response to changes you make to access and audit rules.</description></item>
/// <item><description>Inserting meaningless ACEs into ACLs.</description></item>
/// </list>
/// <para>The only capabilities not supported by the .NET security objects are dangerous activities that should be avoided by the majority of application developers, such as the following:</para>
/// <list type="bullet">
/// <item><description>Low-level tasks that are normally performed by the resource manager.</description></item>
/// <item><description>Adding or removing access control entries in ways that do not maintain the canonical ordering.</description></item>
/// </list>
/// <para>To modify Windows access control security for a task, use the <see cref="Task.GetAccessControl()"/> method to get the TaskSecurity object. Modify the security object by adding and removing rules, and then use the <see cref="Task.SetAccessControl"/> method to reattach it. </para>
/// <para>Important: Changes you make to a TaskSecurity object do not affect the access levels of the task until you call the <see cref="Task.SetAccessControl"/> method to assign the altered security object to the task.</para>
/// <para>To copy access control security from one task to another, use the <see cref="Task.GetAccessControl()"/> method to get a TaskSecurity object representing the access and audit rules for the first task, then use the <see cref="Task.SetAccessControl"/> method, or a constructor that accepts a TaskSecurity object, to assign those rules to the second task.</para>
/// <para>Users with an investment in the security descriptor definition language (SDDL) can use the <see cref="Task.SetSecurityDescriptorSddlForm"/> method to set access rules for a task, and the <see cref="Task.GetSecurityDescriptorSddlForm"/> method to obtain a string that represents the access rules in SDDL format. This is not recommended for new development.</para>
/// </remarks>
public sealed class TaskSecurity : CommonObjectSecurity
{
/// <summary>
/// Initializes a new instance of the <see cref="TaskSecurity"/> class with default values.
/// </summary>
public TaskSecurity()
: base(false)
{
}
/// <summary>
/// Represents the Windows access control security for a Task Scheduler task. This class cannot be inherited.
/// </summary>
/// <remarks>
/// <para>A TaskSecurity object specifies access rights for a Task Scheduler task, and also specifies how access attempts are audited. Access rights to the task are expressed as rules, with each access rule represented by a <see cref="TaskAccessRule"/> object. Each auditing rule is represented by a <see cref="TaskAuditRule"/> object.</para>
/// <para>This mirrors the underlying Windows security system, in which each securable object has at most one discretionary access control list (DACL) that controls access to the secured object, and at most one system access control list (SACL) that specifies which access attempts are audited. The DACL and SACL are ordered lists of access control entries (ACE) that specify access and auditing for users and groups. A <see cref="TaskAccessRule"/> or <see cref="TaskAuditRule"/> object might represent more than one ACE.</para>
/// <para>Note</para>
/// <para>A <see cref="Task"/> object can represent a local task or a Task Scheduler task. Windows access control security is meaningful only for Task Scheduler tasks.</para>
/// <para>The TaskSecurity, <see cref="TaskAccessRule"/>, and <see cref="TaskAuditRule"/> classes hide the implementation details of ACLs and ACEs. They allow you to ignore the seventeen different ACE types and the complexity of correctly maintaining inheritance and propagation of access rights. These objects are also designed to prevent the following common access control errors:</para>
/// <list type="bullet">
/// <item><description>Creating a security descriptor with a null DACL. A null reference to a DACL allows any user to add access rules to an object, potentially creating a denial-of-service attack. A new TaskSecurity object always starts with an empty DACL, which denies all access for all users.</description></item>
/// <item><description>Violating the canonical ordering of ACEs. If the ACE list in the DACL is not kept in the canonical order, users might inadvertently be given access to the secured object. For example, denied access rights must always appear before allowed access rights. TaskSecurity objects maintain the correct order internally. </description></item>
/// <item><description>Manipulating security descriptor flags, which should be under resource manager control only.</description></item>
/// <item><description>Creating invalid combinations of ACE flags.</description></item>
/// <item><description>Manipulating inherited ACEs. Inheritance and propagation are handled by the resource manager, in response to changes you make to access and audit rules.</description></item>
/// <item><description>Inserting meaningless ACEs into ACLs.</description></item>
/// </list>
/// <para>The only capabilities not supported by the .NET security objects are dangerous activities that should be avoided by the majority of application developers, such as the following:</para>
/// <list type="bullet">
/// <item><description>Low-level tasks that are normally performed by the resource manager.</description></item>
/// <item><description>Adding or removing access control entries in ways that do not maintain the canonical ordering.</description></item>
/// </list>
/// <para>To modify Windows access control security for a task, use the <see cref="Task.GetAccessControl()"/> method to get the TaskSecurity object. Modify the security object by adding and removing rules, and then use the <see cref="Task.SetAccessControl"/> method to reattach it. </para>
/// <para>Important: Changes you make to a TaskSecurity object do not affect the access levels of the task until you call the <see cref="Task.SetAccessControl"/> method to assign the altered security object to the task.</para>
/// <para>To copy access control security from one task to another, use the <see cref="Task.GetAccessControl()"/> method to get a TaskSecurity object representing the access and audit rules for the first task, then use the <see cref="Task.SetAccessControl"/> method, or a constructor that accepts a TaskSecurity object, to assign those rules to the second task.</para>
/// <para>Users with an investment in the security descriptor definition language (SDDL) can use the <see cref="Task.SetSecurityDescriptorSddlForm"/> method to set access rules for a task, and the <see cref="Task.GetSecurityDescriptorSddlForm"/> method to obtain a string that represents the access rules in SDDL format. This is not recommended for new development.</para>
/// </remarks>
public sealed class TaskSecurity : CommonObjectSecurity
{
/// <summary>
/// Initializes a new instance of the <see cref="TaskSecurity"/> class with default values.
/// </summary>
public TaskSecurity()
: base(false)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="TaskSecurity" /> class with the specified sections of the access control security rules from the specified task.
/// </summary>
/// <param name="task">The task.</param>
/// <param name="sections">The sections of the ACL to retrieve.</param>
public TaskSecurity([NotNull] Task task, AccessControlSections sections = Task.defaultAccessControlSections)
: base(false)
{
SetSecurityDescriptorSddlForm(task.GetSecurityDescriptorSddlForm(Convert(sections)), sections);
this.CanonicalizeAccessRules();
}
/// <summary>
/// Initializes a new instance of the <see cref="TaskSecurity" /> class with the specified sections of the access control security rules from the specified task.
/// </summary>
/// <param name="task">The task.</param>
/// <param name="sections">The sections of the ACL to retrieve.</param>
public TaskSecurity([NotNull] Task task, AccessControlSections sections = Task.defaultAccessControlSections)
: base(false)
{
SetSecurityDescriptorSddlForm(task.GetSecurityDescriptorSddlForm(Convert(sections)), sections);
this.CanonicalizeAccessRules();
}
/// <summary>
/// Initializes a new instance of the <see cref="TaskSecurity" /> class with the specified sections of the access control security rules from the specified task.
/// </summary>
/// <param name="folder">The folder.</param>
/// <param name="sections">The sections of the ACL to retrieve.</param>
public TaskSecurity([NotNull] TaskFolder folder, AccessControlSections sections = Task.defaultAccessControlSections)
: base(false)
{
SetSecurityDescriptorSddlForm(folder.GetSecurityDescriptorSddlForm(Convert(sections)), sections);
this.CanonicalizeAccessRules();
}
/// <summary>
/// Initializes a new instance of the <see cref="TaskSecurity" /> class with the specified sections of the access control security rules from the specified task.
/// </summary>
/// <param name="folder">The folder.</param>
/// <param name="sections">The sections of the ACL to retrieve.</param>
public TaskSecurity([NotNull] TaskFolder folder, AccessControlSections sections = Task.defaultAccessControlSections)
: base(false)
{
SetSecurityDescriptorSddlForm(folder.GetSecurityDescriptorSddlForm(Convert(sections)), sections);
this.CanonicalizeAccessRules();
}
/// <summary>
/// Gets the enumeration that the <see cref="TaskSecurity"/> class uses to represent access rights.
/// </summary>
/// <returns>A <see cref="Type"/> object representing the <see cref="TaskRights"/> enumeration.</returns>
public override Type AccessRightType => typeof(TaskRights);
/// <summary>
/// Gets the enumeration that the <see cref="TaskSecurity"/> class uses to represent access rights.
/// </summary>
/// <returns>A <see cref="Type"/> object representing the <see cref="TaskRights"/> enumeration.</returns>
public override Type AccessRightType => typeof(TaskRights);
/// <summary>
/// Gets the type that the TaskSecurity class uses to represent access rules.
/// </summary>
/// <returns>A <see cref="Type"/> object representing the <see cref="TaskAccessRule"/> class.</returns>
public override Type AccessRuleType => typeof(TaskAccessRule);
/// <summary>
/// Gets the type that the TaskSecurity class uses to represent access rules.
/// </summary>
/// <returns>A <see cref="Type"/> object representing the <see cref="TaskAccessRule"/> class.</returns>
public override Type AccessRuleType => typeof(TaskAccessRule);
/// <summary>
/// Gets the type that the TaskSecurity class uses to represent audit rules.
/// </summary>
/// <returns>A <see cref="Type"/> object representing the <see cref="TaskAuditRule"/> class.</returns>
public override Type AuditRuleType => typeof(TaskAuditRule);
/// <summary>
/// Gets the type that the TaskSecurity class uses to represent audit rules.
/// </summary>
/// <returns>A <see cref="Type"/> object representing the <see cref="TaskAuditRule"/> class.</returns>
public override Type AuditRuleType => typeof(TaskAuditRule);
/// <summary>
/// Gets a <see cref="TaskSecurity"/> object that represent the default access rights.
/// </summary>
/// <value>The default task security.</value>
public static TaskSecurity DefaultTaskSecurity
{
get
{
var ret = new TaskSecurity();
ret.AddAccessRule(new TaskAccessRule(new SecurityIdentifier(WellKnownSidType.LocalSystemSid, null), TaskRights.FullControl, AccessControlType.Allow));
ret.AddAccessRule(new TaskAccessRule(new SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid, null), TaskRights.Read | TaskRights.Write | TaskRights.Execute, AccessControlType.Allow));
ret.AddAccessRule(new TaskAccessRule(new SecurityIdentifier(WellKnownSidType.LocalServiceSid, null), TaskRights.Read, AccessControlType.Allow));
ret.AddAccessRule(new TaskAccessRule(new SecurityIdentifier(WellKnownSidType.AuthenticatedUserSid, null), TaskRights.Read, AccessControlType.Allow));
ret.AddAccessRule(new TaskAccessRule(new SecurityIdentifier(WellKnownSidType.NetworkServiceSid, null), TaskRights.Read, AccessControlType.Allow));
return ret;
}
}
/// <summary>
/// Gets a <see cref="TaskSecurity"/> object that represent the default access rights.
/// </summary>
/// <value>The default task security.</value>
public static TaskSecurity DefaultTaskSecurity
{
get
{
var ret = new TaskSecurity();
ret.AddAccessRule(new TaskAccessRule(new SecurityIdentifier(WellKnownSidType.LocalSystemSid, null), TaskRights.FullControl, AccessControlType.Allow));
ret.AddAccessRule(new TaskAccessRule(new SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid, null), TaskRights.Read | TaskRights.Write | TaskRights.Execute, AccessControlType.Allow));
ret.AddAccessRule(new TaskAccessRule(new SecurityIdentifier(WellKnownSidType.LocalServiceSid, null), TaskRights.Read, AccessControlType.Allow));
ret.AddAccessRule(new TaskAccessRule(new SecurityIdentifier(WellKnownSidType.AuthenticatedUserSid, null), TaskRights.Read, AccessControlType.Allow));
ret.AddAccessRule(new TaskAccessRule(new SecurityIdentifier(WellKnownSidType.NetworkServiceSid, null), TaskRights.Read, AccessControlType.Allow));
return ret;
}
}
/// <summary>
/// Creates a new access control rule for the specified user, with the specified access rights, access control, and flags.
/// </summary>
/// <param name="identityReference">An <see cref="IdentityReference"/> that identifies the user or group the rule applies to.</param>
/// <param name="accessMask">A bitwise combination of <see cref="TaskRights"/> values specifying the access rights to allow or deny, cast to an integer.</param>
/// <param name="isInherited">Meaningless for tasks, because they have no hierarchy.</param>
/// <param name="inheritanceFlags">Meaningless for tasks, because they have no hierarchy.</param>
/// <param name="propagationFlags">Meaningless for tasks, because they have no hierarchy.</param>
/// <param name="type">One of the <see cref="AccessControlType"/> values specifying whether the rights are allowed or denied.</param>
/// <returns>
/// The <see cref="T:System.Security.AccessControl.AccessRule" /> object that this method creates.
/// </returns>
public override AccessRule AccessRuleFactory(IdentityReference identityReference, int accessMask, bool isInherited, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, AccessControlType type) => new TaskAccessRule(identityReference, (TaskRights)accessMask, type);
/// <summary>
/// Creates a new access control rule for the specified user, with the specified access rights, access control, and flags.
/// </summary>
/// <param name="identityReference">An <see cref="IdentityReference"/> that identifies the user or group the rule applies to.</param>
/// <param name="accessMask">A bitwise combination of <see cref="TaskRights"/> values specifying the access rights to allow or deny, cast to an integer.</param>
/// <param name="isInherited">Meaningless for tasks, because they have no hierarchy.</param>
/// <param name="inheritanceFlags">Meaningless for tasks, because they have no hierarchy.</param>
/// <param name="propagationFlags">Meaningless for tasks, because they have no hierarchy.</param>
/// <param name="type">One of the <see cref="AccessControlType"/> values specifying whether the rights are allowed or denied.</param>
/// <returns>
/// The <see cref="T:System.Security.AccessControl.AccessRule" /> object that this method creates.
/// </returns>
public override AccessRule AccessRuleFactory(IdentityReference identityReference, int accessMask, bool isInherited, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, AccessControlType type) => new TaskAccessRule(identityReference, (TaskRights)accessMask, type);
/// <summary>
/// Searches for a matching rule with which the new rule can be merged. If none are found, adds the new rule.
/// </summary>
/// <param name="rule">The access control rule to add.</param>
public void AddAccessRule([NotNull] TaskAccessRule rule)
{
base.AddAccessRule(rule);
}
/// <summary>
/// Searches for a matching rule with which the new rule can be merged. If none are found, adds the new rule.
/// </summary>
/// <param name="rule">The access control rule to add.</param>
public void AddAccessRule([NotNull] TaskAccessRule rule)
{
base.AddAccessRule(rule);
}
/// <summary>
/// Searches for an audit rule with which the new rule can be merged. If none are found, adds the new rule.
/// </summary>
/// <param name="rule">The audit rule to add. The user specified by this rule determines the search.</param>
public void AddAuditRule([NotNull] TaskAuditRule rule)
{
base.AddAuditRule(rule);
}
/// <summary>
/// Searches for an audit rule with which the new rule can be merged. If none are found, adds the new rule.
/// </summary>
/// <param name="rule">The audit rule to add. The user specified by this rule determines the search.</param>
public void AddAuditRule([NotNull] TaskAuditRule rule)
{
base.AddAuditRule(rule);
}
/// <summary>
/// Creates a new audit rule, specifying the user the rule applies to, the access rights to audit, and the outcome that triggers the audit rule.
/// </summary>
/// <param name="identityReference">An <see cref="IdentityReference"/> that identifies the user or group the rule applies to.</param>
/// <param name="accessMask">A bitwise combination of <see cref="TaskRights"/> values specifying the access rights to audit, cast to an integer.</param>
/// <param name="isInherited">Meaningless for tasks, because they have no hierarchy.</param>
/// <param name="inheritanceFlags">Meaningless for tasks, because they have no hierarchy.</param>
/// <param name="propagationFlags">Meaningless for tasks, because they have no hierarchy.</param>
/// <param name="flags">One of the <see cref="AuditFlags"/> values specifying whether to audit successful access, failed access, or both.</param>
/// <returns>
/// A <see cref="TaskAuditRule"/> object representing the specified audit rule for the specified user. The return type of the method is the base class, <see cref="AuditRule"/>, but the return value can be cast safely to the derived class.
/// </returns>
public override AuditRule AuditRuleFactory(IdentityReference identityReference, int accessMask, bool isInherited, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, AuditFlags flags) => new TaskAuditRule(identityReference, accessMask, isInherited, inheritanceFlags, propagationFlags, flags);
/// <summary>
/// Creates a new audit rule, specifying the user the rule applies to, the access rights to audit, and the outcome that triggers the audit rule.
/// </summary>
/// <param name="identityReference">An <see cref="IdentityReference"/> that identifies the user or group the rule applies to.</param>
/// <param name="accessMask">A bitwise combination of <see cref="TaskRights"/> values specifying the access rights to audit, cast to an integer.</param>
/// <param name="isInherited">Meaningless for tasks, because they have no hierarchy.</param>
/// <param name="inheritanceFlags">Meaningless for tasks, because they have no hierarchy.</param>
/// <param name="propagationFlags">Meaningless for tasks, because they have no hierarchy.</param>
/// <param name="flags">One of the <see cref="AuditFlags"/> values specifying whether to audit successful access, failed access, or both.</param>
/// <returns>
/// A <see cref="TaskAuditRule"/> object representing the specified audit rule for the specified user. The return type of the method is the base class, <see cref="AuditRule"/>, but the return value can be cast safely to the derived class.
/// </returns>
public override AuditRule AuditRuleFactory(IdentityReference identityReference, int accessMask, bool isInherited, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, AuditFlags flags) => new TaskAuditRule(identityReference, accessMask, isInherited, inheritanceFlags, propagationFlags, flags);
/// <summary>
/// Searches for an access control rule with the same user and <see cref="AccessControlType"/> (allow or deny) as the specified rule, and with compatible inheritance and propagation flags; if such a rule is found, the rights contained in the specified access rule are removed from it.
/// </summary>
/// <param name="rule">A <see cref="TaskAccessRule"/> that specifies the user and <see cref="AccessControlType"/> to search for, and a set of inheritance and propagation flags that a matching rule, if found, must be compatible with. Specifies the rights to remove from the compatible rule, if found.</param>
/// <returns><c>true</c> if a compatible rule is found; otherwise <c>false</c>.</returns>
public bool RemoveAccessRule([NotNull] TaskAccessRule rule) => base.RemoveAccessRule(rule);
/// <summary>
/// Searches for an access control rule with the same user and <see cref="AccessControlType"/> (allow or deny) as the specified rule, and with compatible inheritance and propagation flags; if such a rule is found, the rights contained in the specified access rule are removed from it.
/// </summary>
/// <param name="rule">A <see cref="TaskAccessRule"/> that specifies the user and <see cref="AccessControlType"/> to search for, and a set of inheritance and propagation flags that a matching rule, if found, must be compatible with. Specifies the rights to remove from the compatible rule, if found.</param>
/// <returns><c>true</c> if a compatible rule is found; otherwise <c>false</c>.</returns>
public bool RemoveAccessRule([NotNull] TaskAccessRule rule) => base.RemoveAccessRule(rule);
/// <summary>
/// Searches for all access control rules with the same user and <see cref="AccessControlType"/> (allow or deny) as the specified rule and, if found, removes them.
/// </summary>
/// <param name="rule">A <see cref="TaskAccessRule"/> that specifies the user and <see cref="AccessControlType"/> to search for, and a set of inheritance and propagation flags that a matching rule, if found, must be compatible with. Any rights specified by this rule are ignored.</param>
public void RemoveAccessRuleAll([NotNull] TaskAccessRule rule)
{
base.RemoveAccessRuleAll(rule);
}
/// <summary>
/// Searches for all access control rules with the same user and <see cref="AccessControlType"/> (allow or deny) as the specified rule and, if found, removes them.
/// </summary>
/// <param name="rule">A <see cref="TaskAccessRule"/> that specifies the user and <see cref="AccessControlType"/> to search for, and a set of inheritance and propagation flags that a matching rule, if found, must be compatible with. Any rights specified by this rule are ignored.</param>
public void RemoveAccessRuleAll([NotNull] TaskAccessRule rule)
{
base.RemoveAccessRuleAll(rule);
}
/// <summary>
/// Searches for an access control rule that exactly matches the specified rule and, if found, removes it.
/// </summary>
/// <param name="rule">The <see cref="TaskAccessRule"/> to remove.</param>
public void RemoveAccessRuleSpecific([NotNull] TaskAccessRule rule)
{
base.RemoveAccessRuleSpecific(rule);
}
/// <summary>
/// Searches for an access control rule that exactly matches the specified rule and, if found, removes it.
/// </summary>
/// <param name="rule">The <see cref="TaskAccessRule"/> to remove.</param>
public void RemoveAccessRuleSpecific([NotNull] TaskAccessRule rule)
{
base.RemoveAccessRuleSpecific(rule);
}
/// <summary>
/// Searches for an audit control rule with the same user as the specified rule, and with compatible inheritance and propagation flags; if a compatible rule is found, the rights contained in the specified rule are removed from it.
/// </summary>
/// <param name="rule">A <see cref="TaskAuditRule"/> that specifies the user to search for, and a set of inheritance and propagation flags that a matching rule, if found, must be compatible with. Specifies the rights to remove from the compatible rule, if found.</param>
/// <returns><c>true</c> if a compatible rule is found; otherwise <c>false</c>.</returns>
public bool RemoveAuditRule([NotNull] TaskAuditRule rule) => base.RemoveAuditRule(rule);
/// <summary>
/// Searches for an audit control rule with the same user as the specified rule, and with compatible inheritance and propagation flags; if a compatible rule is found, the rights contained in the specified rule are removed from it.
/// </summary>
/// <param name="rule">A <see cref="TaskAuditRule"/> that specifies the user to search for, and a set of inheritance and propagation flags that a matching rule, if found, must be compatible with. Specifies the rights to remove from the compatible rule, if found.</param>
/// <returns><c>true</c> if a compatible rule is found; otherwise <c>false</c>.</returns>
public bool RemoveAuditRule([NotNull] TaskAuditRule rule) => base.RemoveAuditRule(rule);
/// <summary>
/// Searches for all audit rules with the same user as the specified rule and, if found, removes them.
/// </summary>
/// <param name="rule">A <see cref="TaskAuditRule"/> that specifies the user to search for. Any rights specified by this rule are ignored.</param>
public void RemoveAuditRuleAll(TaskAuditRule rule)
{
base.RemoveAuditRuleAll(rule);
}
/// <summary>
/// Searches for all audit rules with the same user as the specified rule and, if found, removes them.
/// </summary>
/// <param name="rule">A <see cref="TaskAuditRule"/> that specifies the user to search for. Any rights specified by this rule are ignored.</param>
public void RemoveAuditRuleAll(TaskAuditRule rule)
{
base.RemoveAuditRuleAll(rule);
}
/// <summary>
/// Searches for an audit rule that exactly matches the specified rule and, if found, removes it.
/// </summary>
/// <param name="rule">The <see cref="TaskAuditRule"/> to remove.</param>
public void RemoveAuditRuleSpecific([NotNull] TaskAuditRule rule)
{
base.RemoveAuditRuleSpecific(rule);
}
/// <summary>
/// Searches for an audit rule that exactly matches the specified rule and, if found, removes it.
/// </summary>
/// <param name="rule">The <see cref="TaskAuditRule"/> to remove.</param>
public void RemoveAuditRuleSpecific([NotNull] TaskAuditRule rule)
{
base.RemoveAuditRuleSpecific(rule);
}
/// <summary>
/// Removes all access control rules with the same user as the specified rule, regardless of <see cref="AccessControlType"/>, and then adds the specified rule.
/// </summary>
/// <param name="rule">The <see cref="TaskAccessRule"/> to add. The user specified by this rule determines the rules to remove before this rule is added.</param>
public void ResetAccessRule([NotNull] TaskAccessRule rule)
{
base.ResetAccessRule(rule);
}
/// <summary>
/// Removes all access control rules with the same user as the specified rule, regardless of <see cref="AccessControlType"/>, and then adds the specified rule.
/// </summary>
/// <param name="rule">The <see cref="TaskAccessRule"/> to add. The user specified by this rule determines the rules to remove before this rule is added.</param>
public void ResetAccessRule([NotNull] TaskAccessRule rule)
{
base.ResetAccessRule(rule);
}
/// <summary>
/// Removes all access control rules with the same user and <see cref="AccessControlType"/> (allow or deny) as the specified rule, and then adds the specified rule.
/// </summary>
/// <param name="rule">The <see cref="TaskAccessRule"/> to add. The user and <see cref="AccessControlType"/> of this rule determine the rules to remove before this rule is added.</param>
public void SetAccessRule([NotNull] TaskAccessRule rule)
{
base.SetAccessRule(rule);
}
/// <summary>
/// Removes all access control rules with the same user and <see cref="AccessControlType"/> (allow or deny) as the specified rule, and then adds the specified rule.
/// </summary>
/// <param name="rule">The <see cref="TaskAccessRule"/> to add. The user and <see cref="AccessControlType"/> of this rule determine the rules to remove before this rule is added.</param>
public void SetAccessRule([NotNull] TaskAccessRule rule)
{
base.SetAccessRule(rule);
}
/// <summary>
/// Removes all audit rules with the same user as the specified rule, regardless of the <see cref="AuditFlags"/> value, and then adds the specified rule.
/// </summary>
/// <param name="rule">The <see cref="TaskAuditRule"/> to add. The user specified by this rule determines the rules to remove before this rule is added.</param>
public void SetAuditRule([NotNull] TaskAuditRule rule)
{
base.SetAuditRule(rule);
}
/// <summary>
/// Removes all audit rules with the same user as the specified rule, regardless of the <see cref="AuditFlags"/> value, and then adds the specified rule.
/// </summary>
/// <param name="rule">The <see cref="TaskAuditRule"/> to add. The user specified by this rule determines the rules to remove before this rule is added.</param>
public void SetAuditRule([NotNull] TaskAuditRule rule)
{
base.SetAuditRule(rule);
}
/// <summary>
/// Returns a <see cref="System.String" /> that represents this instance.
/// </summary>
/// <returns>
/// A <see cref="System.String" /> that represents this instance.
/// </returns>
public override string ToString() => GetSecurityDescriptorSddlForm(Task.defaultAccessControlSections);
/// <summary>
/// Returns a <see cref="System.String" /> that represents this instance.
/// </summary>
/// <returns>
/// A <see cref="System.String" /> that represents this instance.
/// </returns>
public override string ToString() => GetSecurityDescriptorSddlForm(Task.defaultAccessControlSections);
private static SecurityInfos Convert(AccessControlSections si)
{
SecurityInfos ret = 0;
if ((si & AccessControlSections.Audit) != 0)
ret |= SecurityInfos.SystemAcl;
if ((si & AccessControlSections.Access) != 0)
ret |= SecurityInfos.DiscretionaryAcl;
if ((si & AccessControlSections.Group) != 0)
ret |= SecurityInfos.Group;
if ((si & AccessControlSections.Owner) != 0)
ret |= SecurityInfos.Owner;
return ret;
}
private static SecurityInfos Convert(AccessControlSections si)
{
SecurityInfos ret = 0;
if ((si & AccessControlSections.Audit) != 0)
ret |= SecurityInfos.SystemAcl;
if ((si & AccessControlSections.Access) != 0)
ret |= SecurityInfos.DiscretionaryAcl;
if ((si & AccessControlSections.Group) != 0)
ret |= SecurityInfos.Group;
if ((si & AccessControlSections.Owner) != 0)
ret |= SecurityInfos.Owner;
return ret;
}
private static AccessControlSections Convert(SecurityInfos si)
{
AccessControlSections ret = AccessControlSections.None;
if ((si & SecurityInfos.SystemAcl) != 0)
ret |= AccessControlSections.Audit;
if ((si & SecurityInfos.DiscretionaryAcl) != 0)
ret |= AccessControlSections.Access;
if ((si & SecurityInfos.Group) != 0)
ret |= AccessControlSections.Group;
if ((si & SecurityInfos.Owner) != 0)
ret |= AccessControlSections.Owner;
return ret;
}
private static AccessControlSections Convert(SecurityInfos si)
{
AccessControlSections ret = AccessControlSections.None;
if ((si & SecurityInfos.SystemAcl) != 0)
ret |= AccessControlSections.Audit;
if ((si & SecurityInfos.DiscretionaryAcl) != 0)
ret |= AccessControlSections.Access;
if ((si & SecurityInfos.Group) != 0)
ret |= AccessControlSections.Group;
if ((si & SecurityInfos.Owner) != 0)
ret |= AccessControlSections.Owner;
return ret;
}
private AccessControlSections GetAccessControlSectionsFromChanges()
{
AccessControlSections none = AccessControlSections.None;
if (AccessRulesModified)
{
none = AccessControlSections.Access;
}
if (AuditRulesModified)
{
none |= AccessControlSections.Audit;
}
if (OwnerModified)
{
none |= AccessControlSections.Owner;
}
if (GroupModified)
{
none |= AccessControlSections.Group;
}
return none;
}
private AccessControlSections GetAccessControlSectionsFromChanges()
{
AccessControlSections none = AccessControlSections.None;
if (AccessRulesModified)
{
none = AccessControlSections.Access;
}
if (AuditRulesModified)
{
none |= AccessControlSections.Audit;
}
if (OwnerModified)
{
none |= AccessControlSections.Owner;
}
if (GroupModified)
{
none |= AccessControlSections.Group;
}
return none;
}
/// <summary>
/// Saves the specified sections of the security descriptor associated with this <see cref="TaskSecurity"/> object to permanent storage. We recommend that the values of the <paramref name="includeSections"/> parameters passed to the constructor and persist methods be identical.
/// </summary>
/// <param name="task">The task used to retrieve the persisted information.</param>
/// <param name="includeSections">One of the <see cref="AccessControlSections"/> enumeration values that specifies the sections of the security descriptor (access rules, audit rules, owner, primary group) of the securable object to save.</param>
[SecurityCritical]
internal void Persist([NotNull] Task task, AccessControlSections includeSections = Task.defaultAccessControlSections)
{
WriteLock();
try
{
AccessControlSections accessControlSectionsFromChanges = GetAccessControlSectionsFromChanges();
if (accessControlSectionsFromChanges != AccessControlSections.None)
{
task.SetSecurityDescriptorSddlForm(GetSecurityDescriptorSddlForm(accessControlSectionsFromChanges));
OwnerModified = GroupModified = AccessRulesModified = AuditRulesModified = false;
}
}
finally
{
WriteUnlock();
}
}
/// <summary>
/// Saves the specified sections of the security descriptor associated with this <see cref="TaskSecurity"/> object to permanent storage. We recommend that the values of the <paramref name="includeSections"/> parameters passed to the constructor and persist methods be identical.
/// </summary>
/// <param name="task">The task used to retrieve the persisted information.</param>
/// <param name="includeSections">One of the <see cref="AccessControlSections"/> enumeration values that specifies the sections of the security descriptor (access rules, audit rules, owner, primary group) of the securable object to save.</param>
[SecurityCritical]
internal void Persist([NotNull] Task task, AccessControlSections includeSections = Task.defaultAccessControlSections)
{
WriteLock();
try
{
AccessControlSections accessControlSectionsFromChanges = GetAccessControlSectionsFromChanges();
if (accessControlSectionsFromChanges != AccessControlSections.None)
{
task.SetSecurityDescriptorSddlForm(GetSecurityDescriptorSddlForm(accessControlSectionsFromChanges));
OwnerModified = GroupModified = AccessRulesModified = AuditRulesModified = false;
}
}
finally
{
WriteUnlock();
}
}
/// <summary>
/// Saves the specified sections of the security descriptor associated with this <see cref="TaskSecurity" /> object to permanent storage. We recommend that the values of the <paramref name="includeSections" /> parameters passed to the constructor and persist methods be identical.
/// </summary>
/// <param name="folder">The task folder used to retrieve the persisted information.</param>
/// <param name="includeSections">One of the <see cref="AccessControlSections" /> enumeration values that specifies the sections of the security descriptor (access rules, audit rules, owner, primary group) of the securable object to save.</param>
[SecurityCritical]
internal void Persist([NotNull] TaskFolder folder, AccessControlSections includeSections = Task.defaultAccessControlSections)
{
WriteLock();
try
{
AccessControlSections accessControlSectionsFromChanges = GetAccessControlSectionsFromChanges();
if (accessControlSectionsFromChanges != AccessControlSections.None)
{
folder.SetSecurityDescriptorSddlForm(GetSecurityDescriptorSddlForm(accessControlSectionsFromChanges));
OwnerModified = GroupModified = AccessRulesModified = AuditRulesModified = false;
}
}
finally
{
WriteUnlock();
}
}
/// <summary>
/// Saves the specified sections of the security descriptor associated with this <see cref="TaskSecurity" /> object to permanent storage. We recommend that the values of the <paramref name="includeSections" /> parameters passed to the constructor and persist methods be identical.
/// </summary>
/// <param name="folder">The task folder used to retrieve the persisted information.</param>
/// <param name="includeSections">One of the <see cref="AccessControlSections" /> enumeration values that specifies the sections of the security descriptor (access rules, audit rules, owner, primary group) of the securable object to save.</param>
[SecurityCritical]
internal void Persist([NotNull] TaskFolder folder, AccessControlSections includeSections = Task.defaultAccessControlSections)
{
WriteLock();
try
{
AccessControlSections accessControlSectionsFromChanges = GetAccessControlSectionsFromChanges();
if (accessControlSectionsFromChanges != AccessControlSections.None)
{
folder.SetSecurityDescriptorSddlForm(GetSecurityDescriptorSddlForm(accessControlSectionsFromChanges));
OwnerModified = GroupModified = AccessRulesModified = AuditRulesModified = false;
}
}
finally
{
WriteUnlock();
}
}
/// <summary>
/// Saves the specified sections of the security descriptor associated with this <see cref="T:System.Security.AccessControl.ObjectSecurity" /> object to permanent storage. We recommend that the values of the <paramref name="includeSections" /> parameters passed to the constructor and persist methods be identical. For more information, see Remarks.
/// </summary>
/// <param name="name">The name used to retrieve the persisted information.</param>
/// <param name="includeSections">One of the <see cref="T:System.Security.AccessControl.AccessControlSections" /> enumeration values that specifies the sections of the security descriptor (access rules, audit rules, owner, primary group) of the securable object to save.</param>
protected override void Persist([NotNull] string name, AccessControlSections includeSections = Task.defaultAccessControlSections)
{
using (var ts = new TaskService())
{
var task = ts.GetTask(name);
Persist(task, includeSections);
}
}
}
/// <summary>
/// Saves the specified sections of the security descriptor associated with this <see cref="T:System.Security.AccessControl.ObjectSecurity" /> object to permanent storage. We recommend that the values of the <paramref name="includeSections" /> parameters passed to the constructor and persist methods be identical. For more information, see Remarks.
/// </summary>
/// <param name="name">The name used to retrieve the persisted information.</param>
/// <param name="includeSections">One of the <see cref="T:System.Security.AccessControl.AccessControlSections" /> enumeration values that specifies the sections of the security descriptor (access rules, audit rules, owner, primary group) of the securable object to save.</param>
protected override void Persist([NotNull] string name, AccessControlSections includeSections = Task.defaultAccessControlSections)
{
using (var ts = new TaskService())
{
var task = ts.GetTask(name);
Persist(task, includeSections);
}
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -3,11 +3,8 @@ using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
using winPEAS.TaskScheduler.TaskEditor.Native;
using winPEAS.TaskScheduler.V1;
@@ -15,129 +12,129 @@ using winPEAS.TaskScheduler.V2;
namespace winPEAS.TaskScheduler
{
[XmlRoot("Triggers", Namespace = TaskDefinition.tns, IsNullable = false)]
public sealed class TriggerCollection : IList<Trigger>, IDisposable, IXmlSerializable, IList, INotifyCollectionChanged, INotifyPropertyChanged
{
private const string IndexerName = "Item[]";
private readonly ITriggerCollection v2Coll;
private bool inV2set;
private ITask v1Task;
private ITaskDefinition v2Def;
[XmlRoot("Triggers", Namespace = TaskDefinition.tns, IsNullable = false)]
public sealed class TriggerCollection : IList<Trigger>, IDisposable, IXmlSerializable, IList, INotifyCollectionChanged, INotifyPropertyChanged
{
private const string IndexerName = "Item[]";
private readonly ITriggerCollection v2Coll;
private bool inV2set;
private ITask v1Task;
private ITaskDefinition v2Def;
internal TriggerCollection([NotNull] ITask iTask) => v1Task = iTask;
internal TriggerCollection([NotNull] ITask iTask) => v1Task = iTask;
internal TriggerCollection([NotNull] ITaskDefinition iTaskDef)
{
v2Def = iTaskDef;
v2Coll = v2Def.Triggers;
}
internal TriggerCollection([NotNull] ITaskDefinition iTaskDef)
{
v2Def = iTaskDef;
v2Coll = v2Def.Triggers;
}
/// <summary>Occurs when a collection changes.</summary>
public event NotifyCollectionChangedEventHandler CollectionChanged;
/// <summary>Occurs when a collection changes.</summary>
public event NotifyCollectionChangedEventHandler CollectionChanged;
/// <summary>Occurs when a property value changes.</summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>Occurs when a property value changes.</summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>Gets the number of triggers in the collection.</summary>
public int Count => v2Coll?.Count ?? v1Task.GetTriggerCount();
/// <summary>Gets the number of triggers in the collection.</summary>
public int Count => v2Coll?.Count ?? v1Task.GetTriggerCount();
bool IList.IsFixedSize => false;
bool IList.IsFixedSize => false;
bool ICollection<Trigger>.IsReadOnly => false;
bool ICollection<Trigger>.IsReadOnly => false;
bool IList.IsReadOnly => false;
bool IList.IsReadOnly => false;
bool ICollection.IsSynchronized => false;
bool ICollection.IsSynchronized => false;
object ICollection.SyncRoot => this;
object ICollection.SyncRoot => this;
/// <summary>Gets or sets a specified trigger from the collection.</summary>
/// <value>The <see cref="Trigger"/>.</value>
/// <param name="triggerId">The id ( <see cref="Trigger.Id"/>) of the trigger to be retrieved.</param>
/// <returns>Specialized <see cref="Trigger"/> instance.</returns>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="ArgumentOutOfRangeException"></exception>
/// <exception cref="NullReferenceException"></exception>
/// <exception cref="InvalidOperationException">Mismatching Id for trigger and lookup.</exception>
public Trigger this[[NotNull] string triggerId]
{
get
{
if (string.IsNullOrEmpty(triggerId))
throw new ArgumentNullException(nameof(triggerId));
foreach (var t in this)
if (string.Equals(t.Id, triggerId))
return t;
throw new ArgumentOutOfRangeException(nameof(triggerId));
}
set
{
if (value == null)
throw new NullReferenceException();
if (string.IsNullOrEmpty(triggerId))
throw new ArgumentNullException(nameof(triggerId));
if (triggerId != value.Id)
throw new InvalidOperationException("Mismatching Id for trigger and lookup.");
var index = IndexOf(triggerId);
if (index >= 0)
{
var orig = this[index].Clone();
inV2set = true;
try
{
RemoveAt(index);
Insert(index, value);
}
finally
{
inV2set = true;
}
OnNotifyPropertyChanged(IndexerName);
CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, value, orig, index));
}
else
Add(value);
}
}
/// <summary>Gets or sets a specified trigger from the collection.</summary>
/// <value>The <see cref="Trigger"/>.</value>
/// <param name="triggerId">The id ( <see cref="Trigger.Id"/>) of the trigger to be retrieved.</param>
/// <returns>Specialized <see cref="Trigger"/> instance.</returns>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="ArgumentOutOfRangeException"></exception>
/// <exception cref="NullReferenceException"></exception>
/// <exception cref="InvalidOperationException">Mismatching Id for trigger and lookup.</exception>
public Trigger this[[NotNull] string triggerId]
{
get
{
if (string.IsNullOrEmpty(triggerId))
throw new ArgumentNullException(nameof(triggerId));
foreach (var t in this)
if (string.Equals(t.Id, triggerId))
return t;
throw new ArgumentOutOfRangeException(nameof(triggerId));
}
set
{
if (value == null)
throw new NullReferenceException();
if (string.IsNullOrEmpty(triggerId))
throw new ArgumentNullException(nameof(triggerId));
if (triggerId != value.Id)
throw new InvalidOperationException("Mismatching Id for trigger and lookup.");
var index = IndexOf(triggerId);
if (index >= 0)
{
var orig = this[index].Clone();
inV2set = true;
try
{
RemoveAt(index);
Insert(index, value);
}
finally
{
inV2set = true;
}
OnNotifyPropertyChanged(IndexerName);
CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, value, orig, index));
}
else
Add(value);
}
}
/// <summary>Gets a specified trigger from the collection.</summary>
/// <param name="index">The index of the trigger to be retrieved.</param>
/// <returns>Specialized <see cref="Trigger"/> instance.</returns>
public Trigger this[int index]
{
get
{
if (v2Coll != null)
return Trigger.CreateTrigger(v2Coll[++index], v2Def);
return Trigger.CreateTrigger(v1Task.GetTrigger((ushort)index));
}
set
{
if (index < 0 || Count <= index)
throw new ArgumentOutOfRangeException(nameof(index), index, @"Index is not a valid index in the TriggerCollection");
var orig = this[index].Clone();
inV2set = true;
try
{
Insert(index, value);
RemoveAt(index + 1);
}
finally
{
inV2set = false;
}
OnNotifyPropertyChanged(IndexerName);
CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, value, orig, index));
}
}
/// <summary>Gets a specified trigger from the collection.</summary>
/// <param name="index">The index of the trigger to be retrieved.</param>
/// <returns>Specialized <see cref="Trigger"/> instance.</returns>
public Trigger this[int index]
{
get
{
if (v2Coll != null)
return Trigger.CreateTrigger(v2Coll[++index], v2Def);
return Trigger.CreateTrigger(v1Task.GetTrigger((ushort)index));
}
set
{
if (index < 0 || Count <= index)
throw new ArgumentOutOfRangeException(nameof(index), index, @"Index is not a valid index in the TriggerCollection");
var orig = this[index].Clone();
inV2set = true;
try
{
Insert(index, value);
RemoveAt(index + 1);
}
finally
{
inV2set = false;
}
OnNotifyPropertyChanged(IndexerName);
CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, value, orig, index));
}
}
object IList.this[int index]
{
get => this[index];
set => this[index] = (Trigger)value;
}
object IList.this[int index]
{
get => this[index];
set => this[index] = (Trigger)value;
}
/*/// <summary>
/*/// <summary>
/// Add an unbound <see cref="Trigger"/> to the task. </summary> <param name="unboundTrigger"><see cref="Trigger"/> derivative to
/// add to the task.</param> <returns>Bound trigger.</returns> <exception cref="System.ArgumentNullException"><c>unboundTrigger</c>
/// is <c>null</c>.</exception>
@@ -152,387 +149,387 @@ namespace winPEAS.TaskScheduler
return unboundTrigger;
}*/
/// <summary>Add an unbound <see cref="Trigger"/> to the task.</summary>
/// <typeparam name="TTrigger">A type derived from <see cref="Trigger"/>.</typeparam>
/// <param name="unboundTrigger"><see cref="Trigger"/> derivative to add to the task.</param>
/// <returns>Bound trigger.</returns>
/// <exception cref="ArgumentNullException"><c>unboundTrigger</c> is <c>null</c>.</exception>
public TTrigger Add<TTrigger>([NotNull] TTrigger unboundTrigger) where TTrigger : Trigger
{
if (unboundTrigger == null)
throw new ArgumentNullException(nameof(unboundTrigger));
if (v2Def != null)
unboundTrigger.Bind(v2Def);
else
unboundTrigger.Bind(v1Task);
OnNotifyPropertyChanged(nameof(Count));
OnNotifyPropertyChanged(IndexerName);
CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, unboundTrigger));
return unboundTrigger;
}
/// <summary>Add an unbound <see cref="Trigger"/> to the task.</summary>
/// <typeparam name="TTrigger">A type derived from <see cref="Trigger"/>.</typeparam>
/// <param name="unboundTrigger"><see cref="Trigger"/> derivative to add to the task.</param>
/// <returns>Bound trigger.</returns>
/// <exception cref="ArgumentNullException"><c>unboundTrigger</c> is <c>null</c>.</exception>
public TTrigger Add<TTrigger>([NotNull] TTrigger unboundTrigger) where TTrigger : Trigger
{
if (unboundTrigger == null)
throw new ArgumentNullException(nameof(unboundTrigger));
if (v2Def != null)
unboundTrigger.Bind(v2Def);
else
unboundTrigger.Bind(v1Task);
OnNotifyPropertyChanged(nameof(Count));
OnNotifyPropertyChanged(IndexerName);
CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, unboundTrigger));
return unboundTrigger;
}
/// <summary>Add a new trigger to the collections of triggers for the task.</summary>
/// <param name="taskTriggerType">The type of trigger to create.</param>
/// <returns>A <see cref="Trigger"/> instance of the specified type.</returns>
public Trigger AddNew(TaskTriggerType taskTriggerType)
{
if (v1Task != null)
return Trigger.CreateTrigger(v1Task.CreateTrigger(out _), Trigger.ConvertToV1TriggerType(taskTriggerType));
/// <summary>Add a new trigger to the collections of triggers for the task.</summary>
/// <param name="taskTriggerType">The type of trigger to create.</param>
/// <returns>A <see cref="Trigger"/> instance of the specified type.</returns>
public Trigger AddNew(TaskTriggerType taskTriggerType)
{
if (v1Task != null)
return Trigger.CreateTrigger(v1Task.CreateTrigger(out _), Trigger.ConvertToV1TriggerType(taskTriggerType));
return Trigger.CreateTrigger(v2Coll.Create(taskTriggerType), v2Def);
}
return Trigger.CreateTrigger(v2Coll.Create(taskTriggerType), v2Def);
}
/// <summary>Adds a collection of unbound triggers to the end of the <see cref="TriggerCollection"/>.</summary>
/// <param name="triggers">
/// The triggers to be added to the end of the <see cref="TriggerCollection"/>. The collection itself cannot be <c>null</c> and
/// cannot contain <c>null</c> elements.
/// </param>
/// <exception cref="ArgumentNullException"><paramref name="triggers"/> is <c>null</c>.</exception>
public void AddRange([NotNull] IEnumerable<Trigger> triggers)
{
if (triggers == null)
throw new ArgumentNullException(nameof(triggers));
foreach (var item in triggers)
Add(item);
}
/// <summary>Adds a collection of unbound triggers to the end of the <see cref="TriggerCollection"/>.</summary>
/// <param name="triggers">
/// The triggers to be added to the end of the <see cref="TriggerCollection"/>. The collection itself cannot be <c>null</c> and
/// cannot contain <c>null</c> elements.
/// </param>
/// <exception cref="ArgumentNullException"><paramref name="triggers"/> is <c>null</c>.</exception>
public void AddRange([NotNull] IEnumerable<Trigger> triggers)
{
if (triggers == null)
throw new ArgumentNullException(nameof(triggers));
foreach (var item in triggers)
Add(item);
}
/// <summary>Clears all triggers from the task.</summary>
public void Clear()
{
if (v2Coll != null)
v2Coll.Clear();
else
{
inV2set = true;
try
{
for (var i = Count - 1; i >= 0; i--)
RemoveAt(i);
}
finally
{
inV2set = false;
}
}
OnNotifyPropertyChanged(nameof(Count));
OnNotifyPropertyChanged(IndexerName);
CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
/// <summary>Clears all triggers from the task.</summary>
public void Clear()
{
if (v2Coll != null)
v2Coll.Clear();
else
{
inV2set = true;
try
{
for (var i = Count - 1; i >= 0; i--)
RemoveAt(i);
}
finally
{
inV2set = false;
}
}
OnNotifyPropertyChanged(nameof(Count));
OnNotifyPropertyChanged(IndexerName);
CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
/// <summary>Determines whether the <see cref="ICollection{T}"/> contains a specific value.</summary>
/// <param name="item">The object to locate in the <see cref="ICollection{T}"/>.</param>
/// <returns>true if <paramref name="item"/> is found in the <see cref="ICollection{T}"/>; otherwise, false.</returns>
public bool Contains([NotNull] Trigger item) => Find(a => a.Equals(item)) != null;
/// <summary>Determines whether the <see cref="ICollection{T}"/> contains a specific value.</summary>
/// <param name="item">The object to locate in the <see cref="ICollection{T}"/>.</param>
/// <returns>true if <paramref name="item"/> is found in the <see cref="ICollection{T}"/>; otherwise, false.</returns>
public bool Contains([NotNull] Trigger item) => Find(a => a.Equals(item)) != null;
/// <summary>Determines whether the specified trigger type is contained in this collection.</summary>
/// <param name="triggerType">Type of the trigger.</param>
/// <returns><c>true</c> if the specified trigger type is contained in this collection; otherwise, <c>false</c>.</returns>
public bool ContainsType(Type triggerType) => Find(a => a.GetType() == triggerType) != null;
/// <summary>Determines whether the specified trigger type is contained in this collection.</summary>
/// <param name="triggerType">Type of the trigger.</param>
/// <returns><c>true</c> if the specified trigger type is contained in this collection; otherwise, <c>false</c>.</returns>
public bool ContainsType(Type triggerType) => Find(a => a.GetType() == triggerType) != null;
/// <summary>
/// Copies the elements of the <see cref="ICollection{T}"/> to an <see cref="Array"/>, starting at a particular <see cref="Array"/> index.
/// </summary>
/// <param name="array">
/// The one-dimensional <see cref="Array"/> that is the destination of the elements copied from <see cref="ICollection{T}"/>. The
/// <see cref="Array"/> must have zero-based indexing.
/// </param>
/// <param name="arrayIndex">The zero-based index in <paramref name="array"/> at which copying begins.</param>
public void CopyTo(Trigger[] array, int arrayIndex) => CopyTo(0, array, arrayIndex, Count);
/// <summary>
/// Copies the elements of the <see cref="ICollection{T}"/> to an <see cref="Array"/>, starting at a particular <see cref="Array"/> index.
/// </summary>
/// <param name="array">
/// The one-dimensional <see cref="Array"/> that is the destination of the elements copied from <see cref="ICollection{T}"/>. The
/// <see cref="Array"/> must have zero-based indexing.
/// </param>
/// <param name="arrayIndex">The zero-based index in <paramref name="array"/> at which copying begins.</param>
public void CopyTo(Trigger[] array, int arrayIndex) => CopyTo(0, array, arrayIndex, Count);
/// <summary>
/// Copies the elements of the <see cref="TriggerCollection"/> to a <see cref="Trigger"/> array, starting at a particular <see
/// cref="Trigger"/> array index.
/// </summary>
/// <param name="index">The zero-based index in the source at which copying begins.</param>
/// <param name="array">
/// The <see cref="Trigger"/> array that is the destination of the elements copied from <see cref="TriggerCollection"/>. The <see
/// cref="Trigger"/> array must have zero-based indexing.
/// </param>
/// <param name="arrayIndex">The zero-based index in <see cref="Trigger"/> array at which copying begins.</param>
/// <param name="count">The number of elements to copy.</param>
/// <exception cref="ArgumentNullException"><paramref name="array"/> is null.</exception>
/// <exception cref="ArgumentOutOfRangeException"><paramref name="arrayIndex"/> is less than 0.</exception>
/// <exception cref="ArgumentException">
/// The number of elements in the source <see cref="TriggerCollection"/> is greater than the available space from <paramref
/// name="arrayIndex"/> to the end of the destination <paramref name="array"/>.
/// </exception>
public void CopyTo(int index, Trigger[] array, int arrayIndex, int count)
{
if (array == null)
throw new ArgumentNullException(nameof(array));
if (index < 0 || index >= Count)
throw new ArgumentOutOfRangeException(nameof(index));
if (arrayIndex < 0)
throw new ArgumentOutOfRangeException(nameof(arrayIndex));
if (count < 0 || count > (Count - index))
throw new ArgumentOutOfRangeException(nameof(count));
if ((Count - index) > (array.Length - arrayIndex))
throw new ArgumentOutOfRangeException(nameof(arrayIndex));
for (var i = 0; i < count; i++)
array[arrayIndex + i] = (Trigger)this[index + i].Clone();
}
/// <summary>
/// Copies the elements of the <see cref="TriggerCollection"/> to a <see cref="Trigger"/> array, starting at a particular <see
/// cref="Trigger"/> array index.
/// </summary>
/// <param name="index">The zero-based index in the source at which copying begins.</param>
/// <param name="array">
/// The <see cref="Trigger"/> array that is the destination of the elements copied from <see cref="TriggerCollection"/>. The <see
/// cref="Trigger"/> array must have zero-based indexing.
/// </param>
/// <param name="arrayIndex">The zero-based index in <see cref="Trigger"/> array at which copying begins.</param>
/// <param name="count">The number of elements to copy.</param>
/// <exception cref="ArgumentNullException"><paramref name="array"/> is null.</exception>
/// <exception cref="ArgumentOutOfRangeException"><paramref name="arrayIndex"/> is less than 0.</exception>
/// <exception cref="ArgumentException">
/// The number of elements in the source <see cref="TriggerCollection"/> is greater than the available space from <paramref
/// name="arrayIndex"/> to the end of the destination <paramref name="array"/>.
/// </exception>
public void CopyTo(int index, Trigger[] array, int arrayIndex, int count)
{
if (array == null)
throw new ArgumentNullException(nameof(array));
if (index < 0 || index >= Count)
throw new ArgumentOutOfRangeException(nameof(index));
if (arrayIndex < 0)
throw new ArgumentOutOfRangeException(nameof(arrayIndex));
if (count < 0 || count > (Count - index))
throw new ArgumentOutOfRangeException(nameof(count));
if ((Count - index) > (array.Length - arrayIndex))
throw new ArgumentOutOfRangeException(nameof(arrayIndex));
for (var i = 0; i < count; i++)
array[arrayIndex + i] = (Trigger)this[index + i].Clone();
}
/// <summary>Releases all resources used by this class.</summary>
public void Dispose()
{
if (v2Coll != null) Marshal.ReleaseComObject(v2Coll);
v2Def = null;
v1Task = null;
}
/// <summary>Releases all resources used by this class.</summary>
public void Dispose()
{
if (v2Coll != null) Marshal.ReleaseComObject(v2Coll);
v2Def = null;
v1Task = null;
}
/// <summary>
/// Searches for an <see cref="Trigger"/> that matches the conditions defined by the specified predicate, and returns the first
/// occurrence within the entire collection.
/// </summary>
/// <param name="match">
/// The <see cref="Predicate{Trigger}"/> delegate that defines the conditions of the <see cref="Trigger"/> to search for.
/// </param>
/// <returns>
/// The first <see cref="Trigger"/> that matches the conditions defined by the specified predicate, if found; otherwise, <c>null</c>.
/// </returns>
public Trigger Find([NotNull] Predicate<Trigger> match)
{
if (match == null)
throw new ArgumentNullException(nameof(match));
foreach (var item in this)
if (match(item)) return item;
return null;
}
/// <summary>
/// Searches for an <see cref="Trigger"/> that matches the conditions defined by the specified predicate, and returns the first
/// occurrence within the entire collection.
/// </summary>
/// <param name="match">
/// The <see cref="Predicate{Trigger}"/> delegate that defines the conditions of the <see cref="Trigger"/> to search for.
/// </param>
/// <returns>
/// The first <see cref="Trigger"/> that matches the conditions defined by the specified predicate, if found; otherwise, <c>null</c>.
/// </returns>
public Trigger Find([NotNull] Predicate<Trigger> match)
{
if (match == null)
throw new ArgumentNullException(nameof(match));
foreach (var item in this)
if (match(item)) return item;
return null;
}
/// <summary>
/// Searches for an <see cref="Trigger"/> that matches the conditions defined by the specified predicate, and returns the zero-based
/// index of the first occurrence within the collection that starts at the specified index and contains the specified number of elements.
/// </summary>
/// <param name="startIndex">The zero-based starting index of the search.</param>
/// <param name="count">The number of elements in the collection to search.</param>
/// <param name="match">The <see cref="Predicate{Trigger}"/> delegate that defines the conditions of the element to search for.</param>
/// <returns>
/// The zero-based index of the first occurrence of an element that matches the conditions defined by match, if found; otherwise, 1.
/// </returns>
public int FindIndexOf(int startIndex, int count, [NotNull] Predicate<Trigger> match)
{
if (startIndex < 0 || startIndex >= Count)
throw new ArgumentOutOfRangeException(nameof(startIndex));
if (startIndex + count > Count)
throw new ArgumentOutOfRangeException(nameof(count));
if (match == null)
throw new ArgumentNullException(nameof(match));
for (var i = startIndex; i < startIndex + count; i++)
if (match(this[i])) return i;
return -1;
}
/// <summary>
/// Searches for an <see cref="Trigger"/> that matches the conditions defined by the specified predicate, and returns the zero-based
/// index of the first occurrence within the collection that starts at the specified index and contains the specified number of elements.
/// </summary>
/// <param name="startIndex">The zero-based starting index of the search.</param>
/// <param name="count">The number of elements in the collection to search.</param>
/// <param name="match">The <see cref="Predicate{Trigger}"/> delegate that defines the conditions of the element to search for.</param>
/// <returns>
/// The zero-based index of the first occurrence of an element that matches the conditions defined by match, if found; otherwise, 1.
/// </returns>
public int FindIndexOf(int startIndex, int count, [NotNull] Predicate<Trigger> match)
{
if (startIndex < 0 || startIndex >= Count)
throw new ArgumentOutOfRangeException(nameof(startIndex));
if (startIndex + count > Count)
throw new ArgumentOutOfRangeException(nameof(count));
if (match == null)
throw new ArgumentNullException(nameof(match));
for (var i = startIndex; i < startIndex + count; i++)
if (match(this[i])) return i;
return -1;
}
/// <summary>
/// Searches for an <see cref="Trigger"/> that matches the conditions defined by the specified predicate, and returns the zero-based
/// index of the first occurrence within the collection.
/// </summary>
/// <param name="match">The <see cref="Predicate{Trigger}"/> delegate that defines the conditions of the element to search for.</param>
/// <returns>
/// The zero-based index of the first occurrence of an element that matches the conditions defined by match, if found; otherwise, 1.
/// </returns>
public int FindIndexOf([NotNull] Predicate<Trigger> match) => FindIndexOf(0, Count, match);
/// <summary>
/// Searches for an <see cref="Trigger"/> that matches the conditions defined by the specified predicate, and returns the zero-based
/// index of the first occurrence within the collection.
/// </summary>
/// <param name="match">The <see cref="Predicate{Trigger}"/> delegate that defines the conditions of the element to search for.</param>
/// <returns>
/// The zero-based index of the first occurrence of an element that matches the conditions defined by match, if found; otherwise, 1.
/// </returns>
public int FindIndexOf([NotNull] Predicate<Trigger> match) => FindIndexOf(0, Count, match);
/// <summary>Gets the collection enumerator for this collection.</summary>
/// <returns>The <see cref="IEnumerator{T}"/> for this collection.</returns>
public IEnumerator<Trigger> GetEnumerator()
{
if (v1Task != null)
return new V1TriggerEnumerator(v1Task);
return new ComEnumerator<Trigger, ITrigger>(() => v2Coll.Count, i => v2Coll[i], o => Trigger.CreateTrigger(o, v2Def));
}
/// <summary>Gets the collection enumerator for this collection.</summary>
/// <returns>The <see cref="IEnumerator{T}"/> for this collection.</returns>
public IEnumerator<Trigger> GetEnumerator()
{
if (v1Task != null)
return new V1TriggerEnumerator(v1Task);
return new ComEnumerator<Trigger, ITrigger>(() => v2Coll.Count, i => v2Coll[i], o => Trigger.CreateTrigger(o, v2Def));
}
/// <summary>Determines the index of a specific item in the <see cref="IList{T}"/>.</summary>
/// <param name="item">The object to locate in the <see cref="IList{T}"/>.</param>
/// <returns>The index of <paramref name="item"/> if found in the list; otherwise, -1.</returns>
public int IndexOf([NotNull] Trigger item) => FindIndexOf(a => a.Equals(item));
/// <summary>Determines the index of a specific item in the <see cref="IList{T}"/>.</summary>
/// <param name="item">The object to locate in the <see cref="IList{T}"/>.</param>
/// <returns>The index of <paramref name="item"/> if found in the list; otherwise, -1.</returns>
public int IndexOf([NotNull] Trigger item) => FindIndexOf(a => a.Equals(item));
/// <summary>Determines the index of a specific item in the <see cref="IList{T}"/>.</summary>
/// <param name="triggerId">The id ( <see cref="Trigger.Id"/>) of the trigger to be retrieved.</param>
/// <returns>The index of <paramref name="triggerId"/> if found in the list; otherwise, -1.</returns>
public int IndexOf([NotNull] string triggerId)
{
if (string.IsNullOrEmpty(triggerId))
throw new ArgumentNullException(triggerId);
return FindIndexOf(a => string.Equals(a.Id, triggerId));
}
/// <summary>Determines the index of a specific item in the <see cref="IList{T}"/>.</summary>
/// <param name="triggerId">The id ( <see cref="Trigger.Id"/>) of the trigger to be retrieved.</param>
/// <returns>The index of <paramref name="triggerId"/> if found in the list; otherwise, -1.</returns>
public int IndexOf([NotNull] string triggerId)
{
if (string.IsNullOrEmpty(triggerId))
throw new ArgumentNullException(triggerId);
return FindIndexOf(a => string.Equals(a.Id, triggerId));
}
/// <summary>Inserts an trigger at the specified index.</summary>
/// <param name="index">The zero-based index at which trigger should be inserted.</param>
/// <param name="trigger">The trigger to insert into the list.</param>
public void Insert(int index, [NotNull] Trigger trigger)
{
if (trigger == null)
throw new ArgumentNullException(nameof(trigger));
if (index >= Count)
throw new ArgumentOutOfRangeException(nameof(index));
/// <summary>Inserts an trigger at the specified index.</summary>
/// <param name="index">The zero-based index at which trigger should be inserted.</param>
/// <param name="trigger">The trigger to insert into the list.</param>
public void Insert(int index, [NotNull] Trigger trigger)
{
if (trigger == null)
throw new ArgumentNullException(nameof(trigger));
if (index >= Count)
throw new ArgumentOutOfRangeException(nameof(index));
var pushItems = new Trigger[Count - index];
CopyTo(index, pushItems, 0, Count - index);
for (var j = Count - 1; j >= index; j--)
RemoveAt(j);
Add(trigger);
foreach (var t in pushItems)
Add(t);
}
var pushItems = new Trigger[Count - index];
CopyTo(index, pushItems, 0, Count - index);
for (var j = Count - 1; j >= index; j--)
RemoveAt(j);
Add(trigger);
foreach (var t in pushItems)
Add(t);
}
/// <summary>Removes the first occurrence of a specific object from the <see cref="ICollection{T}"/>.</summary>
/// <param name="item">The object to remove from the <see cref="ICollection{T}"/>.</param>
/// <returns>
/// true if <paramref name="item"/> was successfully removed from the <see cref="ICollection{T}"/>; otherwise, false. This method
/// also returns false if <paramref name="item"/> is not found in the original <see cref="ICollection{T}"/>.
/// </returns>
public bool Remove([NotNull] Trigger item)
{
var idx = IndexOf(item);
if (idx != -1)
{
try
{
RemoveAt(idx);
return true;
}
catch { }
}
return false;
}
/// <summary>Removes the first occurrence of a specific object from the <see cref="ICollection{T}"/>.</summary>
/// <param name="item">The object to remove from the <see cref="ICollection{T}"/>.</param>
/// <returns>
/// true if <paramref name="item"/> was successfully removed from the <see cref="ICollection{T}"/>; otherwise, false. This method
/// also returns false if <paramref name="item"/> is not found in the original <see cref="ICollection{T}"/>.
/// </returns>
public bool Remove([NotNull] Trigger item)
{
var idx = IndexOf(item);
if (idx != -1)
{
try
{
RemoveAt(idx);
return true;
}
catch { }
}
return false;
}
/// <summary>Removes the trigger at a specified index.</summary>
/// <param name="index">Index of trigger to remove.</param>
/// <exception cref="ArgumentOutOfRangeException">Index out of range.</exception>
public void RemoveAt(int index)
{
if (index < 0 || index >= Count)
throw new ArgumentOutOfRangeException(nameof(index), index, @"Failed to remove Trigger. Index out of range.");
var item = this[index].Clone();
if (v2Coll != null)
v2Coll.Remove(++index);
else
v1Task.DeleteTrigger((ushort)index); //Remove the trigger from the Task Scheduler
if (!inV2set)
{
OnNotifyPropertyChanged(nameof(Count));
OnNotifyPropertyChanged(IndexerName);
CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item, index));
}
}
/// <summary>Removes the trigger at a specified index.</summary>
/// <param name="index">Index of trigger to remove.</param>
/// <exception cref="ArgumentOutOfRangeException">Index out of range.</exception>
public void RemoveAt(int index)
{
if (index < 0 || index >= Count)
throw new ArgumentOutOfRangeException(nameof(index), index, @"Failed to remove Trigger. Index out of range.");
var item = this[index].Clone();
if (v2Coll != null)
v2Coll.Remove(++index);
else
v1Task.DeleteTrigger((ushort)index); //Remove the trigger from the Task Scheduler
if (!inV2set)
{
OnNotifyPropertyChanged(nameof(Count));
OnNotifyPropertyChanged(IndexerName);
CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item, index));
}
}
/// <summary>Copies the elements of the <see cref="TriggerCollection"/> to a new array.</summary>
/// <returns>An array containing copies of the elements of the <see cref="TriggerCollection"/>.</returns>
public Trigger[] ToArray()
{
var ret = new Trigger[Count];
CopyTo(ret, 0);
return ret;
}
/// <summary>Copies the elements of the <see cref="TriggerCollection"/> to a new array.</summary>
/// <returns>An array containing copies of the elements of the <see cref="TriggerCollection"/>.</returns>
public Trigger[] ToArray()
{
var ret = new Trigger[Count];
CopyTo(ret, 0);
return ret;
}
/// <summary>Returns a <see cref="string"/> that represents the triggers in this collection.</summary>
/// <returns>A <see cref="string"/> that represents the triggers in this collection.</returns>
public override string ToString()
{
if (Count == 1)
return this[0].ToString();
if (Count > 1)
return Properties.Resources.MultipleTriggers;
return string.Empty;
}
/// <summary>Returns a <see cref="string"/> that represents the triggers in this collection.</summary>
/// <returns>A <see cref="string"/> that represents the triggers in this collection.</returns>
public override string ToString()
{
if (Count == 1)
return this[0].ToString();
if (Count > 1)
return Properties.Resources.MultipleTriggers;
return string.Empty;
}
void ICollection<Trigger>.Add(Trigger item) => Add(item);
void ICollection<Trigger>.Add(Trigger item) => Add(item);
int IList.Add(object value)
{
Add((Trigger)value);
return Count - 1;
}
int IList.Add(object value)
{
Add((Trigger)value);
return Count - 1;
}
bool IList.Contains(object value) => Contains((Trigger)value);
bool IList.Contains(object value) => Contains((Trigger)value);
void ICollection.CopyTo(Array array, int index)
{
if (array != null && array.Rank != 1)
throw new RankException("Multi-dimensional arrays are not supported.");
var src = new Trigger[Count];
CopyTo(src, 0);
Array.Copy(src, 0, array, index, Count);
}
void ICollection.CopyTo(Array array, int index)
{
if (array != null && array.Rank != 1)
throw new RankException("Multi-dimensional arrays are not supported.");
var src = new Trigger[Count];
CopyTo(src, 0);
Array.Copy(src, 0, array, index, Count);
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
System.Xml.Schema.XmlSchema IXmlSerializable.GetSchema() => null;
System.Xml.Schema.XmlSchema IXmlSerializable.GetSchema() => null;
int IList.IndexOf(object value) => IndexOf((Trigger)value);
int IList.IndexOf(object value) => IndexOf((Trigger)value);
void IList.Insert(int index, object value) => Insert(index, (Trigger)value);
void IList.Insert(int index, object value) => Insert(index, (Trigger)value);
void IXmlSerializable.ReadXml(System.Xml.XmlReader reader)
{
reader.ReadStartElement(XmlSerializationHelper.GetElementName(this), TaskDefinition.tns);
while (reader.MoveToContent() == System.Xml.XmlNodeType.Element)
{
switch (reader.LocalName)
{
case "BootTrigger":
XmlSerializationHelper.ReadObject(reader, AddNew(TaskTriggerType.Boot));
break;
void IXmlSerializable.ReadXml(System.Xml.XmlReader reader)
{
reader.ReadStartElement(XmlSerializationHelper.GetElementName(this), TaskDefinition.tns);
while (reader.MoveToContent() == System.Xml.XmlNodeType.Element)
{
switch (reader.LocalName)
{
case "BootTrigger":
XmlSerializationHelper.ReadObject(reader, AddNew(TaskTriggerType.Boot));
break;
case "IdleTrigger":
XmlSerializationHelper.ReadObject(reader, AddNew(TaskTriggerType.Idle));
break;
case "IdleTrigger":
XmlSerializationHelper.ReadObject(reader, AddNew(TaskTriggerType.Idle));
break;
case "TimeTrigger":
XmlSerializationHelper.ReadObject(reader, AddNew(TaskTriggerType.Time));
break;
case "TimeTrigger":
XmlSerializationHelper.ReadObject(reader, AddNew(TaskTriggerType.Time));
break;
case "LogonTrigger":
XmlSerializationHelper.ReadObject(reader, AddNew(TaskTriggerType.Logon));
break;
case "LogonTrigger":
XmlSerializationHelper.ReadObject(reader, AddNew(TaskTriggerType.Logon));
break;
case "CalendarTrigger":
Add(CalendarTrigger.GetTriggerFromXml(reader));
break;
case "CalendarTrigger":
Add(CalendarTrigger.GetTriggerFromXml(reader));
break;
default:
reader.Skip();
break;
}
}
reader.ReadEndElement();
}
default:
reader.Skip();
break;
}
}
reader.ReadEndElement();
}
void IList.Remove(object value) => Remove((Trigger)value);
void IList.Remove(object value) => Remove((Trigger)value);
void IXmlSerializable.WriteXml(System.Xml.XmlWriter writer)
{
foreach (var t in this)
XmlSerializationHelper.WriteObject(writer, t);
}
void IXmlSerializable.WriteXml(System.Xml.XmlWriter writer)
{
foreach (var t in this)
XmlSerializationHelper.WriteObject(writer, t);
}
internal void Bind()
{
foreach (var t in this)
t.SetV1TriggerData();
}
internal void Bind()
{
foreach (var t in this)
t.SetV1TriggerData();
}
/// <summary>Called when a property has changed to notify any attached elements.</summary>
/// <param name="propertyName">Name of the property.</param>
private void OnNotifyPropertyChanged([CallerMemberName] string propertyName = "") => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
/// <summary>Called when a property has changed to notify any attached elements.</summary>
/// <param name="propertyName">Name of the property.</param>
private void OnNotifyPropertyChanged([CallerMemberName] string propertyName = "") => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
private sealed class V1TriggerEnumerator : IEnumerator<Trigger>
{
private short curItem = -1;
private ITask iTask;
private sealed class V1TriggerEnumerator : IEnumerator<Trigger>
{
private short curItem = -1;
private ITask iTask;
internal V1TriggerEnumerator(ITask task) => iTask = task;
internal V1TriggerEnumerator(ITask task) => iTask = task;
public Trigger Current => Trigger.CreateTrigger(iTask.GetTrigger((ushort)curItem));
public Trigger Current => Trigger.CreateTrigger(iTask.GetTrigger((ushort)curItem));
object IEnumerator.Current => Current;
object IEnumerator.Current => Current;
/// <summary>Releases all resources used by this class.</summary>
public void Dispose() => iTask = null;
/// <summary>Releases all resources used by this class.</summary>
public void Dispose() => iTask = null;
public bool MoveNext() => (++curItem < iTask.GetTriggerCount());
public bool MoveNext() => (++curItem < iTask.GetTriggerCount());
public void Reset() => curItem = -1;
}
}
public void Reset() => curItem = -1;
}
}
}

View File

@@ -1,151 +1,147 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Principal;
using System.Text;
using System.Threading.Tasks;
using winPEAS.TaskScheduler.TaskEditor.Native;
namespace winPEAS.TaskScheduler
{
/// <summary>Represents a system account.</summary>
internal class User : IEquatable<User>, IDisposable
{
private static readonly WindowsIdentity cur = WindowsIdentity.GetCurrent();
private SecurityIdentifier sid;
/// <summary>Represents a system account.</summary>
internal class User : IEquatable<User>, IDisposable
{
private static readonly WindowsIdentity cur = WindowsIdentity.GetCurrent();
private SecurityIdentifier sid;
/// <summary>Initializes a new instance of the <see cref="User"/> class.</summary>
/// <param name="userName">
/// Name of the user. This can be in the format <c>DOMAIN\username</c> or <c>username@domain.com</c> or <c>username</c> or
/// <c>null</c> (for current user).
/// </param>
public User(string userName = null)
{
if (string.IsNullOrEmpty(userName)) userName = null;
// 2018-03-02: Hopefully not a breaking change, but by adding in the comparison of an account name without a domain and the
// current user, there is a chance that current implementations will break given the condition that a local account with the same
// name as a domain account exists and the intention was to prefer the local account. In such a case, the developer should
// prepend the user name in TaskDefinition.Principal.UserId with the machine name of the local machine.
if (userName == null || cur.Name.Equals(userName, StringComparison.InvariantCultureIgnoreCase) || GetUser(cur.Name).Equals(userName, StringComparison.InvariantCultureIgnoreCase))
{
Identity = cur;
sid = Identity.User;
}
else if (userName.Contains("\\") && !userName.StartsWith(@"NT AUTHORITY\"))
{
try
{
using (var ds = new NativeMethods.DomainService())
{
Identity = new WindowsIdentity(ds.CrackName(userName));
sid = Identity.User;
}
}
catch { }
}
/// <summary>Initializes a new instance of the <see cref="User"/> class.</summary>
/// <param name="userName">
/// Name of the user. This can be in the format <c>DOMAIN\username</c> or <c>username@domain.com</c> or <c>username</c> or
/// <c>null</c> (for current user).
/// </param>
public User(string userName = null)
{
if (string.IsNullOrEmpty(userName)) userName = null;
// 2018-03-02: Hopefully not a breaking change, but by adding in the comparison of an account name without a domain and the
// current user, there is a chance that current implementations will break given the condition that a local account with the same
// name as a domain account exists and the intention was to prefer the local account. In such a case, the developer should
// prepend the user name in TaskDefinition.Principal.UserId with the machine name of the local machine.
if (userName == null || cur.Name.Equals(userName, StringComparison.InvariantCultureIgnoreCase) || GetUser(cur.Name).Equals(userName, StringComparison.InvariantCultureIgnoreCase))
{
Identity = cur;
sid = Identity.User;
}
else if (userName.Contains("\\") && !userName.StartsWith(@"NT AUTHORITY\"))
{
try
{
using (var ds = new NativeMethods.DomainService())
{
Identity = new WindowsIdentity(ds.CrackName(userName));
sid = Identity.User;
}
}
catch { }
}
if (Identity == null)
{
if (userName != null && userName.Contains("@"))
{
Identity = new WindowsIdentity(userName);
sid = Identity.User;
}
if (Identity == null)
{
if (userName != null && userName.Contains("@"))
{
Identity = new WindowsIdentity(userName);
sid = Identity.User;
}
if (Identity == null && userName != null)
{
var ntacct = new NTAccount(userName);
try { sid = (SecurityIdentifier)ntacct.Translate(typeof(SecurityIdentifier)); } catch { }
}
}
if (Identity == null && userName != null)
{
var ntacct = new NTAccount(userName);
try { sid = (SecurityIdentifier)ntacct.Translate(typeof(SecurityIdentifier)); } catch { }
}
}
string GetUser(string domUser)
{
var split = domUser.Split('\\');
return split.Length == 2 ? split[1] : domUser;
}
}
string GetUser(string domUser)
{
var split = domUser.Split('\\');
return split.Length == 2 ? split[1] : domUser;
}
}
/// <summary>Initializes a new instance of the <see cref="User"/> class.</summary>
/// <param name="wid">The <see cref="WindowsIdentity"/>.</param>
internal User(WindowsIdentity wid) { Identity = wid; sid = wid.User; }
/// <summary>Initializes a new instance of the <see cref="User"/> class.</summary>
/// <param name="wid">The <see cref="WindowsIdentity"/>.</param>
internal User(WindowsIdentity wid) { Identity = wid; sid = wid.User; }
/// <summary>Gets the current user.</summary>
/// <value>The current user.</value>
public static User Current => new User(cur);
/// <summary>Gets the current user.</summary>
/// <value>The current user.</value>
public static User Current => new User(cur);
/// <summary>Gets the identity.</summary>
/// <value>The identity.</value>
public WindowsIdentity Identity { get; private set; }
/// <summary>Gets the identity.</summary>
/// <value>The identity.</value>
public WindowsIdentity Identity { get; private set; }
/// <summary>Gets a value indicating whether this instance is in an administrator role.</summary>
/// <value><c>true</c> if this instance is an admin; otherwise, <c>false</c>.</value>
public bool IsAdmin => Identity != null ? new WindowsPrincipal(Identity).IsInRole(WindowsBuiltInRole.Administrator) : false;
/// <summary>Gets a value indicating whether this instance is in an administrator role.</summary>
/// <value><c>true</c> if this instance is an admin; otherwise, <c>false</c>.</value>
public bool IsAdmin => Identity != null ? new WindowsPrincipal(Identity).IsInRole(WindowsBuiltInRole.Administrator) : false;
/// <summary>Gets a value indicating whether this instance is the interactive user.</summary>
/// <value><c>true</c> if this instance is the current user; otherwise, <c>false</c>.</value>
public bool IsCurrent => Identity?.User.Equals(cur.User) ?? false;
/// <summary>Gets a value indicating whether this instance is the interactive user.</summary>
/// <value><c>true</c> if this instance is the current user; otherwise, <c>false</c>.</value>
public bool IsCurrent => Identity?.User.Equals(cur.User) ?? false;
/// <summary>Gets a value indicating whether this instance is a service account.</summary>
/// <value><c>true</c> if this instance is a service account; otherwise, <c>false</c>.</value>
public bool IsServiceAccount
{
get
{
try
{
return (sid != null && (sid.IsWellKnown(WellKnownSidType.LocalSystemSid) || sid.IsWellKnown(WellKnownSidType.NetworkServiceSid) || sid.IsWellKnown(WellKnownSidType.LocalServiceSid)));
}
catch { }
return false;
}
}
/// <summary>Gets a value indicating whether this instance is a service account.</summary>
/// <value><c>true</c> if this instance is a service account; otherwise, <c>false</c>.</value>
public bool IsServiceAccount
{
get
{
try
{
return (sid != null && (sid.IsWellKnown(WellKnownSidType.LocalSystemSid) || sid.IsWellKnown(WellKnownSidType.NetworkServiceSid) || sid.IsWellKnown(WellKnownSidType.LocalServiceSid)));
}
catch { }
return false;
}
}
/// <summary>Gets a value indicating whether this instance is the SYSTEM account.</summary>
/// <value><c>true</c> if this instance is the SYSTEM account; otherwise, <c>false</c>.</value>
public bool IsSystem => sid != null && sid.IsWellKnown(WellKnownSidType.LocalSystemSid);
/// <summary>Gets a value indicating whether this instance is the SYSTEM account.</summary>
/// <value><c>true</c> if this instance is the SYSTEM account; otherwise, <c>false</c>.</value>
public bool IsSystem => sid != null && sid.IsWellKnown(WellKnownSidType.LocalSystemSid);
/// <summary>Gets the SID string.</summary>
/// <value>The SID string.</value>
public string SidString => sid?.ToString();
/// <summary>Gets the SID string.</summary>
/// <value>The SID string.</value>
public string SidString => sid?.ToString();
/// <summary>Gets the NT name (DOMAIN\username).</summary>
/// <value>The name of the user.</value>
public string Name => Identity?.Name ?? ((NTAccount)sid?.Translate(typeof(NTAccount)))?.Value;
/// <summary>Gets the NT name (DOMAIN\username).</summary>
/// <value>The name of the user.</value>
public string Name => Identity?.Name ?? ((NTAccount)sid?.Translate(typeof(NTAccount)))?.Value;
/// <summary>Create a <see cref="User"/> instance from a SID string.</summary>
/// <param name="sid">The SID string.</param>
/// <returns>A <see cref="User"/> instance.</returns>
public static User FromSidString(string sid) => new User(((NTAccount)new SecurityIdentifier(sid).Translate(typeof(NTAccount))).Value);
/// <summary>Create a <see cref="User"/> instance from a SID string.</summary>
/// <param name="sid">The SID string.</param>
/// <returns>A <see cref="User"/> instance.</returns>
public static User FromSidString(string sid) => new User(((NTAccount)new SecurityIdentifier(sid).Translate(typeof(NTAccount))).Value);
/// <summary>Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.</summary>
public void Dispose() => Identity?.Dispose();
/// <summary>Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.</summary>
public void Dispose() => Identity?.Dispose();
/// <summary>Determines whether the specified <see cref="System.Object"/>, is equal to this instance.</summary>
/// <param name="obj">The <see cref="System.Object"/> to compare with this instance.</param>
/// <returns><c>true</c> if the specified <see cref="System.Object"/> is equal to this instance; otherwise, <c>false</c>.</returns>
public override bool Equals(object obj)
{
if (obj is User user)
return Equals(user);
if (obj is WindowsIdentity wid && sid != null)
return sid.Equals(wid.User);
try
{
if (obj is string un)
return Equals(new User(un));
}
catch { }
return base.Equals(obj);
}
/// <summary>Determines whether the specified <see cref="System.Object"/>, is equal to this instance.</summary>
/// <param name="obj">The <see cref="System.Object"/> to compare with this instance.</param>
/// <returns><c>true</c> if the specified <see cref="System.Object"/> is equal to this instance; otherwise, <c>false</c>.</returns>
public override bool Equals(object obj)
{
if (obj is User user)
return Equals(user);
if (obj is WindowsIdentity wid && sid != null)
return sid.Equals(wid.User);
try
{
if (obj is string un)
return Equals(new User(un));
}
catch { }
return base.Equals(obj);
}
/// <summary>Indicates whether the current object is equal to another object of the same type.</summary>
/// <param name="other">An object to compare with this object.</param>
/// <returns>true if the current object is equal to the <paramref name="other"/> parameter; otherwise, false.</returns>
public bool Equals(User other) => (other != null && sid != null) ? sid.Equals(other.sid) : false;
/// <summary>Indicates whether the current object is equal to another object of the same type.</summary>
/// <param name="other">An object to compare with this object.</param>
/// <returns>true if the current object is equal to the <paramref name="other"/> parameter; otherwise, false.</returns>
public bool Equals(User other) => (other != null && sid != null) ? sid.Equals(other.sid) : false;
/// <summary>Returns a hash code for this instance.</summary>
/// <returns>A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.</returns>
public override int GetHashCode() => sid?.GetHashCode() ?? 0;
}
/// <summary>Returns a hash code for this instance.</summary>
/// <returns>A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.</returns>
public override int GetHashCode() => sid?.GetHashCode() ?? 0;
}
}

Some files were not shown because too many files have changed in this diff Show More