Port to netstandard.

Nit fixes.
Fixed e2e tests.
Added MIT license.
This commit is contained in:
Alexandru Macocian
2021-03-26 11:58:07 +01:00
parent f6069bd3aa
commit f39e8cf89e
26 changed files with 112 additions and 1034 deletions
@@ -1,8 +1,6 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Generic;
namespace SystemExtensions.Collections
namespace System.Collections.Generic
{
/// <summary>
/// AVL tree implementation.
@@ -27,7 +25,7 @@ namespace SystemExtensions.Collections
}
AVLNode<T> root;
private int count = 0;
private bool isReadOnly = false;
private readonly bool isReadOnly = false;
#endregion
#region Properties
/// <summary>
@@ -387,7 +385,5 @@ namespace SystemExtensions.Collections
}
}
#endregion
}
}
@@ -1,9 +1,6 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq;
namespace SystemExtensions.Collections
namespace System.Collections.Generic
{
/// <summary>
/// Binary heap implementation.
@@ -14,7 +11,9 @@ namespace SystemExtensions.Collections
{
#region Fields
T[] items;
int capacity, count, initialCapacity;
private int capacity;
private int count;
private readonly int initialCapacity;
#endregion
#region Properties
/// <summary>
@@ -90,7 +89,7 @@ namespace SystemExtensions.Collections
Capacity = 2 * Capacity;
}
int position = ++count;
for (; position > 1 && value.CompareTo(items[position / 2]) < 0; position = position / 2)
for (; position > 1 && value.CompareTo(items[position / 2]) < 0; position /= 2)
{
items[position] = items[position / 2];
}
@@ -157,8 +156,11 @@ namespace SystemExtensions.Collections
public void Clear(bool completeClear)
{
count = 0;
capacity = initialCapacity;
items = new T[initialCapacity];
if (completeClear)
{
capacity = initialCapacity;
items = new T[initialCapacity];
}
}
/// <summary>
/// Returns an enumerator that iterates over the heap.
@@ -180,7 +182,7 @@ namespace SystemExtensions.Collections
private void BubbleDown(int index)
{
T temp = items[index];
int childIndex = 0;
int childIndex;
for (; 2 * index <= count; index = childIndex)
{
childIndex = 2 * index;
@@ -200,16 +202,6 @@ namespace SystemExtensions.Collections
items[index] = temp;
}
/// <summary>
/// Build heap from unordered array
/// </summary>
private void BuildHeap()
{
for (int i = count / 2; i > 0; i--)
{
BubbleDown(i);
}
}
/// <summary>
/// Implementation of IEnumerator.
/// </summary>
/// <returns>Enumerator over the array.</returns>
@@ -1,8 +1,4 @@
using System;
using System.Collections;
using System.Collections.Generic;
namespace SystemExtensions.Collections
namespace System.Collections.Generic
{
/// <summary>
/// Fibonacci Heap implementation.
@@ -53,14 +49,16 @@ namespace SystemExtensions.Collections
/// <param name="value">Value to be added.</param>
public void Add(T value)
{
FibonacciNode<T> node = new FibonacciNode<T>();
node.Value = value;
FibonacciNode<T> node = new FibonacciNode<T>
{
Value = value,
Marked = false,
Child = null,
Parent = null,
Degree = 0
};
node.Previous = node.Next = node;
node.Degree = 0;
node.Marked = false;
node.Child = null;
node.Parent = null;
root = Merge(root, node);
root = this.Merge(root, node);
count++;
}
/// <summary>
@@ -1,6 +1,4 @@
using System.Collections.Generic;
namespace SystemExtensions.Collections
namespace System.Collections.Generic
{
/// <summary>
/// Interface for queue implementations.
@@ -1,8 +1,4 @@
using System;
using System.Collections;
using System.Collections.Generic;
namespace SystemExtensions.Collections
namespace System.Collections.Generic
{
/// <summary>
/// Priority Queue data structure. The implementation is based on an array-based implementation of Binary Heap.
@@ -13,7 +9,7 @@ namespace SystemExtensions.Collections
public sealed class PriorityQueue<T> : IQueue<T> where T : IComparable<T>
{
#region Fields
private BinaryHeap<T> binaryHeap;
private readonly BinaryHeap<T> binaryHeap;
#endregion
#region Properties
/// <summary>
@@ -1,8 +1,4 @@
using System;
using System.Collections;
using System.Collections.Generic;
namespace SystemExtensions.Collections
namespace System.Collections.Generic
{
/// <summary>
/// Skip list implementation.
@@ -27,10 +23,10 @@ namespace SystemExtensions.Collections
}
}
private int count;
private Random random;
private NodeSet<T> head;
private NodeSet<T> end;
private int maxLevel = 10;
private readonly Random random;
private readonly NodeSet<T> head;
private readonly NodeSet<T> end;
private readonly int maxLevel = 10;
private int level;
#endregion
#region Properties
@@ -52,7 +48,7 @@ namespace SystemExtensions.Collections
{
this.maxLevel = maxLevel;
random = new Random();
head = new NodeSet<T>(default(T), maxLevel);
head = new NodeSet<T>(default, maxLevel);
end = head;
for (int i = 0; i <= maxLevel; i++)
{
@@ -1,8 +1,4 @@
using System;
using System.Collections;
using System.Collections.Generic;
namespace SystemExtensions.Collections
namespace System.Collections.Generic
{
/// <summary>
/// Treap implementation.
@@ -26,7 +22,7 @@ namespace SystemExtensions.Collections
Right = null;
}
}
private Random randomGen;
private readonly Random randomGen;
private Node<T> root;
private int count;
#endregion
+22
View File
@@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright © 2021
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the “Software”), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
@@ -1,6 +1,6 @@
using System;
namespace SystemExtensions.Structures.BitStructures
namespace System.Structures.BitStructures
{
public struct Int32BitStruct : IEquatable<Int32BitStruct>
{
@@ -1,6 +1,6 @@
using System;
namespace SystemExtensions.Structures.BitStructures
namespace System.Structures.BitStructures
{
public struct Int64BitStruct : IEquatable<Int64BitStruct>
{
@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0</TargetFrameworks>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageLicenseFile>License.txt</PackageLicenseFile>
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
</PropertyGroup>
<ItemGroup>
<None Include="License.txt">
<Pack>True</Pack>
<PackagePath></PackagePath>
</None>
</ItemGroup>
</Project>
@@ -1,9 +1,6 @@
using System;
using System.Collections.Generic;
using System.Threading;
using SystemExtensions.Collections;
using System.Collections.Generic;
namespace SystemExtensions.Threading
namespace System.Threading
{
/// <summary>
/// Threadpool implementation that uses a priority queue as the queue for the tasks to execute.
@@ -14,9 +11,9 @@ namespace SystemExtensions.Threading
{
private class QueueEntry : IComparable<QueueEntry>
{
public TaskPriority TaskPriority;
public WaitCallback WaitCallback;
public Object Object;
public TaskPriority TaskPriority { get; }
public WaitCallback WaitCallback { get; }
public object Object { get; }
public QueueEntry(TaskPriority priority, WaitCallback callback, object obj)
{
this.TaskPriority = priority;
@@ -114,7 +111,7 @@ namespace SystemExtensions.Threading
private volatile PriorityQueue<QueueEntry> tasks;
private Thread observer;
private int maxThreads;
private object tasksLock = new object();
private readonly object tasksLock = new object();
private struct WorkerThread
{
public Thread thread;
+8 -8
View File
@@ -1,26 +1,26 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.28307.572
# Visual Studio Version 16
VisualStudioVersion = 16.0.31005.135
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SystemExtensions", "SystemExtensions\SystemExtensions.csproj", "{55850FF3-70E4-4828-BEEE-39837AC0D24C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SystemExtensionsTests", "SystemExtensionsTests\SystemExtensionsTests.csproj", "{F9B61261-0A08-4B53-BAEA-44E05DBBBFE5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SystemExtensions.NetStandard", "SystemExtensions.NetStandard\SystemExtensions.NetStandard.csproj", "{4CE9E55C-6016-4631-B8D4-4D763DD05F23}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{55850FF3-70E4-4828-BEEE-39837AC0D24C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{55850FF3-70E4-4828-BEEE-39837AC0D24C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{55850FF3-70E4-4828-BEEE-39837AC0D24C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{55850FF3-70E4-4828-BEEE-39837AC0D24C}.Release|Any CPU.Build.0 = Release|Any CPU
{F9B61261-0A08-4B53-BAEA-44E05DBBBFE5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F9B61261-0A08-4B53-BAEA-44E05DBBBFE5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F9B61261-0A08-4B53-BAEA-44E05DBBBFE5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F9B61261-0A08-4B53-BAEA-44E05DBBBFE5}.Release|Any CPU.Build.0 = Release|Any CPU
{4CE9E55C-6016-4631-B8D4-4D763DD05F23}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4CE9E55C-6016-4631-B8D4-4D763DD05F23}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4CE9E55C-6016-4631-B8D4-4D763DD05F23}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4CE9E55C-6016-4631-B8D4-4D763DD05F23}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
-36
View File
@@ -1,36 +0,0 @@
using System;
namespace SystemExtensions
{
/// <summary>
/// Custom implementation of an exception.
/// </summary>
[Serializable]
public class ItemNotFoundException : Exception
{
/// <summary>
/// Initializes a new instance of ItemNotFoundException.
/// </summary>
public ItemNotFoundException()
{
}
/// <summary>
/// Initializes a new instance of ItemNotFoundException with a specified error.
/// </summary>
/// <param name="message">The message that describes the error.</param>
public ItemNotFoundException(string message) : base(message)
{
}
/// <summary>
/// Initializes a new instance of ItemNotFoundException with a specified error and a reference to the inner exception that is the cause of this exception.
/// </summary>
/// <param name="message">The message that describes the error.</param>
/// <param name="innerException">The exception that is the cause of the current exception, or null in case there is no inner exception.</param>
public ItemNotFoundException(string message, Exception innerException) : base(message, innerException)
{
}
}
}
@@ -1,35 +0,0 @@
using System.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("SystemExtensions")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("SystemExtensions")]
[assembly: AssemblyCopyright("Copyright © 2019")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("55850ff3-70e4-4828-beee-39837ac0d24c")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
@@ -1,793 +0,0 @@
using Microsoft.Win32.SafeHandles;
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Text.RegularExpressions;
namespace SystemExtensions.Security
{
/// <summary>
/// Helper class to obtain admin privileges and elevation status.
/// </summary>
/// <remarks>Source code provided on https://code.msdn.microsoft.com/windowsapps/CSUACSelfElevation-644673d3 </remarks>
public static class ProcessInformation
{
/// <summary>
/// The function checks whether the primary access token of the process belongs
/// to user account that is a member of the local Administrators group, even if
/// it currently is not elevated.
/// </summary>
/// <returns>
/// Returns true if the primary access token of the process belongs to user
/// account that is a member of the local Administrators group. Returns false
/// if the token does not.
/// </returns>
/// <exception cref="System.ComponentModel.Win32Exception">
/// When any native Windows API call fails, the function throws a Win32Exception
/// with the last error code.
/// </exception>
public static bool IsUserInAdminGroup()
{
bool fInAdminGroup = false;
SafeTokenHandle hToken = null;
SafeTokenHandle hTokenToCheck = null;
IntPtr pElevationType = IntPtr.Zero;
IntPtr pLinkedToken = IntPtr.Zero;
int cbSize = 0;
try
{
// Open the access token of the current process for query and duplicate.
if (!NativeMethods.OpenProcessToken(Process.GetCurrentProcess().Handle,
NativeMethods.TOKEN_QUERY | NativeMethods.TOKEN_DUPLICATE, out hToken))
{
throw new Win32Exception();
}
// Determine whether system is running Windows Vista or later operating
// systems (major version >= 6) because they support linked tokens, but
// previous versions (major version < 6) do not.
if (Environment.OSVersion.Version.Major >= 6)
{
// Running Windows Vista or later (major version >= 6).
// Determine token type: limited, elevated, or default.
// Allocate a buffer for the elevation type information.
cbSize = sizeof(TOKEN_ELEVATION_TYPE);
pElevationType = Marshal.AllocHGlobal(cbSize);
if (pElevationType == IntPtr.Zero)
{
throw new Win32Exception();
}
// Retrieve token elevation type information.
if (!NativeMethods.GetTokenInformation(hToken,
TOKEN_INFORMATION_CLASS.TokenElevationType, pElevationType,
cbSize, out cbSize))
{
throw new Win32Exception();
}
// Marshal the TOKEN_ELEVATION_TYPE enum from native to .NET.
TOKEN_ELEVATION_TYPE elevType = (TOKEN_ELEVATION_TYPE)
Marshal.ReadInt32(pElevationType);
// If limited, get the linked elevated token for further check.
if (elevType == TOKEN_ELEVATION_TYPE.TokenElevationTypeLimited)
{
// Allocate a buffer for the linked token.
cbSize = IntPtr.Size;
pLinkedToken = Marshal.AllocHGlobal(cbSize);
if (pLinkedToken == IntPtr.Zero)
{
throw new Win32Exception();
}
// Get the linked token.
if (!NativeMethods.GetTokenInformation(hToken,
TOKEN_INFORMATION_CLASS.TokenLinkedToken, pLinkedToken,
cbSize, out cbSize))
{
throw new Win32Exception();
}
// Marshal the linked token value from native to .NET.
IntPtr hLinkedToken = Marshal.ReadIntPtr(pLinkedToken);
hTokenToCheck = new SafeTokenHandle(hLinkedToken);
}
}
// CheckTokenMembership requires an impersonation token. If we just got
// a linked token, it already is an impersonation token. If we did not
// get a linked token, duplicate the original into an impersonation
// token for CheckTokenMembership.
if (hTokenToCheck == null)
{
if (!NativeMethods.DuplicateToken(hToken,
SECURITY_IMPERSONATION_LEVEL.SecurityIdentification,
out hTokenToCheck))
{
throw new Win32Exception();
}
}
// Check if the token to be checked contains admin SID.
WindowsIdentity id = new WindowsIdentity(hTokenToCheck.DangerousGetHandle());
WindowsPrincipal principal = new WindowsPrincipal(id);
fInAdminGroup = principal.IsInRole(WindowsBuiltInRole.Administrator);
}
finally
{
// Centralized cleanup for all allocated resources.
if (hToken != null)
{
hToken.Close();
hToken = null;
}
if (hTokenToCheck != null)
{
hTokenToCheck.Close();
hTokenToCheck = null;
}
if (pElevationType != IntPtr.Zero)
{
Marshal.FreeHGlobal(pElevationType);
pElevationType = IntPtr.Zero;
}
if (pLinkedToken != IntPtr.Zero)
{
Marshal.FreeHGlobal(pLinkedToken);
pLinkedToken = IntPtr.Zero;
}
}
return fInAdminGroup;
}
/// <summary>
/// The function checks whether the current process is run as administrator.
/// In other words, it dictates whether the primary access token of the
/// process belongs to user account that is a member of the local
/// Administrators group and it is elevated.
/// </summary>
/// <returns>
/// Returns true if the primary access token of the process belongs to user
/// account that is a member of the local Administrators group and it is
/// elevated. Returns false if the token does not.
/// </returns>
public static bool IsRunAsAdmin()
{
WindowsIdentity id = WindowsIdentity.GetCurrent();
WindowsPrincipal principal = new WindowsPrincipal(id);
return principal.IsInRole(WindowsBuiltInRole.Administrator);
}
/// <summary>
/// The function gets the elevation information of the current process. It
/// dictates whether the process is elevated or not. Token elevation is only
/// available on Windows Vista and newer operating systems, thus
/// IsProcessElevated throws a C++ exception if it is called on systems prior
/// to Windows Vista. It is not appropriate to use this function to determine
/// whether a process is run as administartor.
/// </summary>
/// <returns>
/// Returns true if the process is elevated. Returns false if it is not.
/// </returns>
/// <exception cref="System.ComponentModel.Win32Exception">
/// When any native Windows API call fails, the function throws a Win32Exception
/// with the last error code.
/// </exception>
/// <remarks>
/// TOKEN_INFORMATION_CLASS provides TokenElevationType to check the elevation
/// type (TokenElevationTypeDefault / TokenElevationTypeLimited /
/// TokenElevationTypeFull) of the process. It is different from TokenElevation
/// in that, when UAC is turned off, elevation type always returns
/// TokenElevationTypeDefault even though the process is elevated (Integrity
/// Level == High). In other words, it is not safe to say if the process is
/// elevated based on elevation type. Instead, we should use TokenElevation.
/// </remarks>
public static bool IsProcessElevated()
{
bool fIsElevated = false;
SafeTokenHandle hToken = null;
int cbTokenElevation = 0;
IntPtr pTokenElevation = IntPtr.Zero;
try
{
// Open the access token of the current process with TOKEN_QUERY.
if (!NativeMethods.OpenProcessToken(Process.GetCurrentProcess().Handle,
NativeMethods.TOKEN_QUERY, out hToken))
{
throw new Win32Exception();
}
// Allocate a buffer for the elevation information.
cbTokenElevation = Marshal.SizeOf(typeof(TOKEN_ELEVATION));
pTokenElevation = Marshal.AllocHGlobal(cbTokenElevation);
if (pTokenElevation == IntPtr.Zero)
{
throw new Win32Exception();
}
// Retrieve token elevation information.
if (!NativeMethods.GetTokenInformation(hToken,
TOKEN_INFORMATION_CLASS.TokenElevation, pTokenElevation,
cbTokenElevation, out cbTokenElevation))
{
// When the process is run on operating systems prior to Windows
// Vista, GetTokenInformation returns false with the error code
// ERROR_INVALID_PARAMETER because TokenElevation is not supported
// on those operating systems.
throw new Win32Exception();
}
// Marshal the TOKEN_ELEVATION struct from native to .NET object.
TOKEN_ELEVATION elevation = (TOKEN_ELEVATION)Marshal.PtrToStructure(
pTokenElevation, typeof(TOKEN_ELEVATION));
// TOKEN_ELEVATION.TokenIsElevated is a non-zero value if the token
// has elevated privileges; otherwise, a zero value.
fIsElevated = (elevation.TokenIsElevated != 0);
}
finally
{
// Centralized cleanup for all allocated resources.
if (hToken != null)
{
hToken.Close();
hToken = null;
}
if (pTokenElevation != IntPtr.Zero)
{
Marshal.FreeHGlobal(pTokenElevation);
pTokenElevation = IntPtr.Zero;
cbTokenElevation = 0;
}
}
return fIsElevated;
}
/// <summary>
/// The function gets the integrity level of the current process. Integrity
/// level is only available on Windows Vista and newer operating systems, thus
/// GetProcessIntegrityLevel throws a C++ exception if it is called on systems
/// prior to Windows Vista.
/// </summary>
/// <returns>
/// Returns the integrity level of the current process. It is usually one of
/// these values:
///
/// SECURITY_MANDATORY_UNTRUSTED_RID - means untrusted level. It is used
/// by processes started by the Anonymous group. Blocks most write access.
/// (SID: S-1-16-0x0)
///
/// SECURITY_MANDATORY_LOW_RID - means low integrity level. It is used by
/// Protected Mode Internet Explorer. Blocks write acess to most objects
/// (such as files and registry keys) on the system. (SID: S-1-16-0x1000)
///
/// SECURITY_MANDATORY_MEDIUM_RID - means medium integrity level. It is
/// used by normal applications being launched while UAC is enabled.
/// (SID: S-1-16-0x2000)
///
/// SECURITY_MANDATORY_HIGH_RID - means high integrity level. It is used
/// by administrative applications launched through elevation when UAC is
/// enabled, or normal applications if UAC is disabled and the user is an
/// administrator. (SID: S-1-16-0x3000)
///
/// SECURITY_MANDATORY_SYSTEM_RID - means system integrity level. It is
/// used by services and other system-level applications (such as Wininit,
/// Winlogon, Smss, etc.) (SID: S-1-16-0x4000)
///
/// </returns>
/// <exception cref="System.ComponentModel.Win32Exception">
/// When any native Windows API call fails, the function throws a Win32Exception
/// with the last error code.
/// </exception>
public static int GetProcessIntegrityLevel()
{
int IL = -1;
SafeTokenHandle hToken = null;
int cbTokenIL = 0;
IntPtr pTokenIL = IntPtr.Zero;
try
{
// Open the access token of the current process with TOKEN_QUERY.
if (!NativeMethods.OpenProcessToken(Process.GetCurrentProcess().Handle,
NativeMethods.TOKEN_QUERY, out hToken))
{
throw new Win32Exception();
}
// Then we must query the size of the integrity level information
// associated with the token. Note that we expect GetTokenInformation
// to return false with the ERROR_INSUFFICIENT_BUFFER error code
// because we've given it a null buffer. On exit cbTokenIL will tell
// the size of the group information.
if (!NativeMethods.GetTokenInformation(hToken,
TOKEN_INFORMATION_CLASS.TokenIntegrityLevel, IntPtr.Zero, 0,
out cbTokenIL))
{
int error = Marshal.GetLastWin32Error();
if (error != NativeMethods.ERROR_INSUFFICIENT_BUFFER)
{
// When the process is run on operating systems prior to
// Windows Vista, GetTokenInformation returns false with the
// ERROR_INVALID_PARAMETER error code because
// TokenIntegrityLevel is not supported on those OS's.
throw new Win32Exception(error);
}
}
// Now we allocate a buffer for the integrity level information.
pTokenIL = Marshal.AllocHGlobal(cbTokenIL);
if (pTokenIL == IntPtr.Zero)
{
throw new Win32Exception();
}
// Now we ask for the integrity level information again. This may fail
// if an administrator has added this account to an additional group
// between our first call to GetTokenInformation and this one.
if (!NativeMethods.GetTokenInformation(hToken,
TOKEN_INFORMATION_CLASS.TokenIntegrityLevel, pTokenIL, cbTokenIL,
out cbTokenIL))
{
throw new Win32Exception();
}
// Marshal the TOKEN_MANDATORY_LABEL struct from native to .NET object.
TOKEN_MANDATORY_LABEL tokenIL = (TOKEN_MANDATORY_LABEL)
Marshal.PtrToStructure(pTokenIL, typeof(TOKEN_MANDATORY_LABEL));
// Integrity Level SIDs are in the form of S-1-16-0xXXXX. (e.g.
// S-1-16-0x1000 stands for low integrity level SID). There is one
// and only one subauthority.
IntPtr pIL = NativeMethods.GetSidSubAuthority(tokenIL.Label.Sid, 0);
IL = Marshal.ReadInt32(pIL);
}
finally
{
// Centralized cleanup for all allocated resources.
if (hToken != null)
{
hToken.Close();
hToken = null;
}
if (pTokenIL != IntPtr.Zero)
{
Marshal.FreeHGlobal(pTokenIL);
pTokenIL = IntPtr.Zero;
cbTokenIL = 0;
}
}
return IL;
}
/// <summary>
/// Elevate process to administration rights.
/// </summary>
/// <returns>True if the elevation succeeded or false if it failed.</returns>
public static bool ElevateProcess()
{
if (!IsRunAsAdmin())
{
// Launch itself as administrator
ProcessStartInfo proc = new ProcessStartInfo();
proc.UseShellExecute = true;
proc.WorkingDirectory = Environment.CurrentDirectory;
proc.FileName = Process.GetCurrentProcess().MainModule.FileName;
proc.Verb = "runas";
try
{
Process.Start(proc);
Process.GetCurrentProcess().Close(); // Quit itself
return true;
}
catch
{
// The user refused the elevation.
// Do nothing and return directly ...
return false;
}
}
else
{
return true;
}
}
/// <summary>
/// Gets the application path of the running assembly.
/// </summary>
/// <returns>String containing the path to the executing assembly.</returns>
public static string GetApplicationPath()
{
var exePath = Path.GetDirectoryName(System.Reflection
.Assembly.GetExecutingAssembly().CodeBase);
Regex appPathMatcher = new Regex(@"(?<!fil)[A-Za-z]:\\+[\S\s]*?(?=\\+bin)");
var appRoot = appPathMatcher.Match(exePath).Value;
return appRoot;
}
/// <summary>
/// The TOKEN_INFORMATION_CLASS enumeration type contains values that
/// specify the type of information being assigned to or retrieved from
/// an access token.
/// </summary>
internal enum TOKEN_INFORMATION_CLASS
{
TokenUser = 1,
TokenGroups,
TokenPrivileges,
TokenOwner,
TokenPrimaryGroup,
TokenDefaultDacl,
TokenSource,
TokenType,
TokenImpersonationLevel,
TokenStatistics,
TokenRestrictedSids,
TokenSessionId,
TokenGroupsAndPrivileges,
TokenSessionReference,
TokenSandBoxInert,
TokenAuditPolicy,
TokenOrigin,
TokenElevationType,
TokenLinkedToken,
TokenElevation,
TokenHasRestrictions,
TokenAccessInformation,
TokenVirtualizationAllowed,
TokenVirtualizationEnabled,
TokenIntegrityLevel,
TokenUIAccess,
TokenMandatoryPolicy,
TokenLogonSid,
MaxTokenInfoClass
}
/// <summary>
/// The WELL_KNOWN_SID_TYPE enumeration type is a list of commonly used
/// security identifiers (SIDs). Programs can pass these values to the
/// CreateWellKnownSid function to create a SID from this list.
/// </summary>
internal enum WELL_KNOWN_SID_TYPE
{
WinNullSid = 0,
WinWorldSid = 1,
WinLocalSid = 2,
WinCreatorOwnerSid = 3,
WinCreatorGroupSid = 4,
WinCreatorOwnerServerSid = 5,
WinCreatorGroupServerSid = 6,
WinNtAuthoritySid = 7,
WinDialupSid = 8,
WinNetworkSid = 9,
WinBatchSid = 10,
WinInteractiveSid = 11,
WinServiceSid = 12,
WinAnonymousSid = 13,
WinProxySid = 14,
WinEnterpriseControllersSid = 15,
WinSelfSid = 16,
WinAuthenticatedUserSid = 17,
WinRestrictedCodeSid = 18,
WinTerminalServerSid = 19,
WinRemoteLogonIdSid = 20,
WinLogonIdsSid = 21,
WinLocalSystemSid = 22,
WinLocalServiceSid = 23,
WinNetworkServiceSid = 24,
WinBuiltinDomainSid = 25,
WinBuiltinAdministratorsSid = 26,
WinBuiltinUsersSid = 27,
WinBuiltinGuestsSid = 28,
WinBuiltinPowerUsersSid = 29,
WinBuiltinAccountOperatorsSid = 30,
WinBuiltinSystemOperatorsSid = 31,
WinBuiltinPrintOperatorsSid = 32,
WinBuiltinBackupOperatorsSid = 33,
WinBuiltinReplicatorSid = 34,
WinBuiltinPreWindows2000CompatibleAccessSid = 35,
WinBuiltinRemoteDesktopUsersSid = 36,
WinBuiltinNetworkConfigurationOperatorsSid = 37,
WinAccountAdministratorSid = 38,
WinAccountGuestSid = 39,
WinAccountKrbtgtSid = 40,
WinAccountDomainAdminsSid = 41,
WinAccountDomainUsersSid = 42,
WinAccountDomainGuestsSid = 43,
WinAccountComputersSid = 44,
WinAccountControllersSid = 45,
WinAccountCertAdminsSid = 46,
WinAccountSchemaAdminsSid = 47,
WinAccountEnterpriseAdminsSid = 48,
WinAccountPolicyAdminsSid = 49,
WinAccountRasAndIasServersSid = 50,
WinNTLMAuthenticationSid = 51,
WinDigestAuthenticationSid = 52,
WinSChannelAuthenticationSid = 53,
WinThisOrganizationSid = 54,
WinOtherOrganizationSid = 55,
WinBuiltinIncomingForestTrustBuildersSid = 56,
WinBuiltinPerfMonitoringUsersSid = 57,
WinBuiltinPerfLoggingUsersSid = 58,
WinBuiltinAuthorizationAccessSid = 59,
WinBuiltinTerminalServerLicenseServersSid = 60,
WinBuiltinDCOMUsersSid = 61,
WinBuiltinIUsersSid = 62,
WinIUserSid = 63,
WinBuiltinCryptoOperatorsSid = 64,
WinUntrustedLabelSid = 65,
WinLowLabelSid = 66,
WinMediumLabelSid = 67,
WinHighLabelSid = 68,
WinSystemLabelSid = 69,
WinWriteRestrictedCodeSid = 70,
WinCreatorOwnerRightsSid = 71,
WinCacheablePrincipalsGroupSid = 72,
WinNonCacheablePrincipalsGroupSid = 73,
WinEnterpriseReadonlyControllersSid = 74,
WinAccountReadonlyControllersSid = 75,
WinBuiltinEventLogReadersGroup = 76,
WinNewEnterpriseReadonlyControllersSid = 77,
WinBuiltinCertSvcDComAccessGroup = 78
}
/// <summary>
/// The SECURITY_IMPERSONATION_LEVEL enumeration type contains values
/// that specify security impersonation levels. Security impersonation
/// levels govern the degree to which a server process can act on behalf
/// of a client process.
/// </summary>
internal enum SECURITY_IMPERSONATION_LEVEL
{
SecurityAnonymous,
SecurityIdentification,
SecurityImpersonation,
SecurityDelegation
}
/// <summary>
/// The TOKEN_ELEVATION_TYPE enumeration indicates the elevation type of
/// token being queried by the GetTokenInformation function or set by
/// the SetTokenInformation function.
/// </summary>
internal enum TOKEN_ELEVATION_TYPE
{
TokenElevationTypeDefault = 1,
TokenElevationTypeFull,
TokenElevationTypeLimited
}
/// <summary>
/// The structure represents a security identifier (SID) and its
/// attributes. SIDs are used to uniquely identify users or groups.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
internal struct SID_AND_ATTRIBUTES
{
public IntPtr Sid;
public UInt32 Attributes;
}
/// <summary>
/// The structure indicates whether a token has elevated privileges.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
internal struct TOKEN_ELEVATION
{
public Int32 TokenIsElevated;
}
/// <summary>
/// The structure specifies the mandatory integrity level for a token.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
internal struct TOKEN_MANDATORY_LABEL
{
public SID_AND_ATTRIBUTES Label;
}
/// <summary>
/// Represents a wrapper class for a token handle.
/// </summary>
internal class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid
{
private SafeTokenHandle() : base(true)
{
}
internal SafeTokenHandle(IntPtr handle) : base(true)
{
base.SetHandle(handle);
}
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern bool CloseHandle(IntPtr handle);
protected override bool ReleaseHandle()
{
return CloseHandle(base.handle);
}
}
internal class NativeMethods
{
// Token Specific Access Rights
public const UInt32 STANDARD_RIGHTS_REQUIRED = 0x000F0000;
public const UInt32 STANDARD_RIGHTS_READ = 0x00020000;
public const UInt32 TOKEN_ASSIGN_PRIMARY = 0x0001;
public const UInt32 TOKEN_DUPLICATE = 0x0002;
public const UInt32 TOKEN_IMPERSONATE = 0x0004;
public const UInt32 TOKEN_QUERY = 0x0008;
public const UInt32 TOKEN_QUERY_SOURCE = 0x0010;
public const UInt32 TOKEN_ADJUST_PRIVILEGES = 0x0020;
public const UInt32 TOKEN_ADJUST_GROUPS = 0x0040;
public const UInt32 TOKEN_ADJUST_DEFAULT = 0x0080;
public const UInt32 TOKEN_ADJUST_SESSIONID = 0x0100;
public const UInt32 TOKEN_READ = (STANDARD_RIGHTS_READ | TOKEN_QUERY);
public const UInt32 TOKEN_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED |
TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_IMPERSONATE |
TOKEN_QUERY | TOKEN_QUERY_SOURCE | TOKEN_ADJUST_PRIVILEGES |
TOKEN_ADJUST_GROUPS | TOKEN_ADJUST_DEFAULT | TOKEN_ADJUST_SESSIONID);
public const Int32 ERROR_INSUFFICIENT_BUFFER = 122;
// Integrity Levels
public const Int32 SECURITY_MANDATORY_UNTRUSTED_RID = 0x00000000;
public const Int32 SECURITY_MANDATORY_LOW_RID = 0x00001000;
public const Int32 SECURITY_MANDATORY_MEDIUM_RID = 0x00002000;
public const Int32 SECURITY_MANDATORY_HIGH_RID = 0x00003000;
public const Int32 SECURITY_MANDATORY_SYSTEM_RID = 0x00004000;
/// <summary>
/// The function opens the access token associated with a process.
/// </summary>
/// <param name="hProcess">
/// A handle to the process whose access token is opened.
/// </param>
/// <param name="desiredAccess">
/// Specifies an access mask that specifies the requested types of
/// access to the access token.
/// </param>
/// <param name="hToken">
/// Outputs a handle that identifies the newly opened access token
/// when the function returns.
/// </param>
/// <returns></returns>
[DllImport("advapi32", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool OpenProcessToken(IntPtr hProcess,
UInt32 desiredAccess, out SafeTokenHandle hToken);
/// <summary>
/// The function creates a new access token that duplicates one
/// already in existence.
/// </summary>
/// <param name="ExistingTokenHandle">
/// A handle to an access token opened with TOKEN_DUPLICATE access.
/// </param>
/// <param name="ImpersonationLevel">
/// Specifies a SECURITY_IMPERSONATION_LEVEL enumerated type that
/// supplies the impersonation level of the new token.
/// </param>
/// <param name="DuplicateTokenHandle">
/// Outputs a handle to the duplicate token.
/// </param>
/// <returns></returns>
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public extern static bool DuplicateToken(
SafeTokenHandle ExistingTokenHandle,
SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
out SafeTokenHandle DuplicateTokenHandle);
/// <summary>
/// The function retrieves a specified type of information about an
/// access token. The calling process must have appropriate access
/// rights to obtain the information.
/// </summary>
/// <param name="hToken">
/// A handle to an access token from which information is retrieved.
/// </param>
/// <param name="tokenInfoClass">
/// Specifies a value from the TOKEN_INFORMATION_CLASS enumerated
/// type to identify the type of information the function retrieves.
/// </param>
/// <param name="pTokenInfo">
/// A pointer to a buffer the function fills with the requested
/// information.
/// </param>
/// <param name="tokenInfoLength">
/// Specifies the size, in bytes, of the buffer pointed to by the
/// TokenInformation parameter.
/// </param>
/// <param name="returnLength">
/// A pointer to a variable that receives the number of bytes needed
/// for the buffer pointed to by the TokenInformation parameter.
/// </param>
/// <returns></returns>
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetTokenInformation(
SafeTokenHandle hToken,
TOKEN_INFORMATION_CLASS tokenInfoClass,
IntPtr pTokenInfo,
Int32 tokenInfoLength,
out Int32 returnLength);
/// <summary>
/// Sets the elevation required state for a specified button or
/// command link to display an elevated icon.
/// </summary>
public const UInt32 BCM_SETSHIELD = 0x160C;
/// <summary>
/// Sends the specified message to a window or windows. The function
/// calls the window procedure for the specified window and does not
/// return until the window procedure has processed the message.
/// </summary>
/// <param name="hWnd">
/// Handle to the window whose window procedure will receive the
/// message.
/// </param>
/// <param name="Msg">Specifies the message to be sent.</param>
/// <param name="wParam">
/// Specifies additional message-specific information.
/// </param>
/// <param name="lParam">
/// Specifies additional message-specific information.
/// </param>
/// <returns></returns>
[DllImport("user32", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int SendMessage(IntPtr hWnd, UInt32 Msg, int wParam, IntPtr lParam);
/// <summary>
/// The function returns a pointer to a specified subauthority in a
/// security identifier (SID). The subauthority value is a relative
/// identifier (RID).
/// </summary>
/// <param name="pSid">
/// A pointer to the SID structure from which a pointer to a
/// subauthority is to be returned.
/// </param>
/// <param name="nSubAuthority">
/// Specifies an index value identifying the subauthority array
/// element whose address the function will return.
/// </param>
/// <returns>
/// If the function succeeds, the return value is a pointer to the
/// specified SID subauthority. To get extended error information,
/// call GetLastError. If the function fails, the return value is
/// undefined. The function fails if the specified SID structure is
/// not valid or if the index value specified by the nSubAuthority
/// parameter is out of bounds.
/// </returns>
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr GetSidSubAuthority(IntPtr pSid, UInt32 nSubAuthority);
}
}
}
-66
View File
@@ -1,66 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{55850FF3-70E4-4828-BEEE-39837AC0D24C}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>SystemExtensions</RootNamespace>
<AssemblyName>SystemExtensions</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>bin\Debug\SystemExtensions.xml</DocumentationFile>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
<DocumentationFile>
</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Collections\AVLTree.cs" />
<Compile Include="Collections\BinaryHeap.cs" />
<Compile Include="Collections\FibonacciHeap.cs" />
<Compile Include="Collections\IQueue.cs" />
<Compile Include="Collections\PriorityQueue.cs" />
<Compile Include="Collections\SkipList.cs" />
<Compile Include="Collections\Treap.cs" />
<Compile Include="ItemNotFoundException.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Security\ProcessInformation.cs" />
<Compile Include="Structures\BitStructures\Int32BitStruct.cs" />
<Compile Include="Structures\BitStructures\Int64BitStruct.cs" />
<Compile Include="Threading\PriorityThreadPool.cs" />
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
@@ -1,16 +1,16 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SystemExtensions.Collections;
using System.Collections;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SystemExtensions;
using System;
using System.Runtime.Serialization.Formatters.Binary;
using System.Xml.Serialization;
using System.IO;
namespace SystemExtensions.Collections.Tests
namespace System.Collections.Tests
{
[TestClass()]
public class BinaryHeapTests
@@ -112,7 +112,7 @@ namespace SystemExtensions.Collections.Tests
}
binaryHeap.Clear(false);
int[] array = binaryHeap.ToArray();
if (binaryHeap.Count > 0 || binaryHeap.Capacity != 10)
if (binaryHeap.Count > 0 || binaryHeap.Capacity == 10)
{
Assert.Fail();
}
@@ -1,5 +1,5 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SystemExtensions.Collections;
using System.Collections;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -9,7 +9,7 @@ using System.Threading;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
namespace SystemExtensions.Collections.Tests
namespace System.Collections.Tests
{
[TestClass()]
public class FibonacciHeapTests
@@ -1,15 +1,15 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SystemExtensions.Collections;
using System.Collections;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SystemExtensions;
using System;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
namespace SystemExtensions.Collections.Tests
namespace System.Collections.Tests
{
[TestClass()]
public class PriorityQueueTests
@@ -1,5 +1,5 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SystemExtensions.Collections;
using System.Collections;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -8,7 +8,7 @@ using System.Threading.Tasks;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
namespace SystemExtensions.Collections.Tests
namespace System.Collections.Tests
{
[TestClass()]
public class SkipListTests
@@ -1,5 +1,5 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SystemExtensions.Collections;
using System.Collections;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -8,7 +8,7 @@ using System.Threading.Tasks;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
namespace SystemExtensions.Collections.Tests
namespace System.Collections.Tests
{
[TestClass()]
public class TreapTests
@@ -1,5 +1,5 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SystemExtensions.Structures.BitStructures;
using System.Structures.BitStructures;
namespace SystemExtensionsTests.Structures
{
@@ -1,5 +1,5 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SystemExtensions.Structures.BitStructures;
using System.Structures.BitStructures;
namespace SystemExtensionsTests.Structures
{
@@ -72,9 +72,9 @@
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SystemExtensions\SystemExtensions.csproj">
<Project>{55850ff3-70e4-4828-beee-39837ac0d24c}</Project>
<Name>SystemExtensions</Name>
<ProjectReference Include="..\SystemExtensions.NetStandard\SystemExtensions.NetStandard.csproj">
<Project>{4ce9e55c-6016-4631-b8d4-4d763dd05f23}</Project>
<Name>SystemExtensions.NetStandard</Name>
</ProjectReference>
</ItemGroup>
<Choose>
@@ -1,5 +1,5 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SystemExtensions.Threading;
using System.Threading;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -7,9 +7,9 @@ using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Diagnostics;
using static SystemExtensions.Threading.PriorityThreadPool;
using static System.Threading.PriorityThreadPool;
namespace SystemExtensions.Threading.Tests
namespace System.Threading.Tests
{
[TestClass()]
public class PriorityThreadPoolTests