diff --git a/SystemExtensions/Collections/AVLTree.cs b/SystemExtensions/Collections/AVLTree.cs
index 638095c..ad5bb51 100644
--- a/SystemExtensions/Collections/AVLTree.cs
+++ b/SystemExtensions/Collections/AVLTree.cs
@@ -1,9 +1,6 @@
using System;
using System.Collections;
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
namespace SystemExtensions.Collections
{
@@ -14,7 +11,7 @@ namespace SystemExtensions.Collections
///
/// Provided type.
[Serializable]
- public class AVLTree : ICollection where T : IComparable
+ public sealed class AVLTree : ICollection where T : IComparable
{
#region Fields
[Serializable]
@@ -36,7 +33,8 @@ namespace SystemExtensions.Collections
///
/// Count of items currently stored in the tree.
///
- public int Count {
+ public int Count
+ {
get
{
return count;
@@ -51,7 +49,6 @@ namespace SystemExtensions.Collections
///
/// Initializes a new instance of an AVLTree collection.
///
- ///
public AVLTree()
{
@@ -83,7 +80,7 @@ namespace SystemExtensions.Collections
public bool Contains(T value)
{
AVLNode node = Find(value, root);
- if(node == null)
+ if (node == null)
{
return false;
}
@@ -113,16 +110,16 @@ namespace SystemExtensions.Collections
Queue> queue = new Queue>();
queue.Enqueue(root);
- while(queue.Count > 0)
+ while (queue.Count > 0)
{
AVLNode currentNode = queue.Dequeue();
- if(currentNode.Left != null)
+ if (currentNode.Left != null)
{
queue.Enqueue(currentNode.Left);
currentNode.Left = null;
count--;
}
- if(currentNode.Right != null)
+ if (currentNode.Right != null)
{
queue.Enqueue(currentNode.Right);
currentNode.Right = null;
@@ -293,7 +290,7 @@ namespace SystemExtensions.Collections
}
private AVLNode Find(T target, AVLNode current)
{
- if(current == null)
+ if (current == null)
{
return null;
}
diff --git a/SystemExtensions/Collections/BinaryHeap.cs b/SystemExtensions/Collections/BinaryHeap.cs
index 398588e..1b983e1 100644
--- a/SystemExtensions/Collections/BinaryHeap.cs
+++ b/SystemExtensions/Collections/BinaryHeap.cs
@@ -2,8 +2,6 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
namespace SystemExtensions.Collections
{
@@ -12,7 +10,7 @@ namespace SystemExtensions.Collections
///
/// Provided type.
[Serializable]
- public class BinaryHeap : IEnumerable where T : IComparable
+ public sealed class BinaryHeap : IEnumerable where T : IComparable
{
#region Fields
T[] items;
@@ -42,10 +40,12 @@ namespace SystemExtensions.Collections
///
/// Capacity of the heap.
///
- public int Capacity { get => capacity;
+ public int Capacity
+ {
+ get => capacity;
set
{
- if(value > capacity)
+ if (value > capacity)
{
Array.Resize(ref items, value);
capacity = value;
@@ -61,7 +61,6 @@ namespace SystemExtensions.Collections
///
/// Constructor for a binary heap data structure.
///
- /// Function used to compare the elements.
public BinaryHeap()
{
capacity = 10;
@@ -71,7 +70,6 @@ namespace SystemExtensions.Collections
///
/// Constructor for a binary heap data structure.
///
- /// Function used to compare the elements.
/// Initial capacity of the heap. Used for initial alocation of the array.
public BinaryHeap(int capacity)
{
@@ -87,7 +85,7 @@ namespace SystemExtensions.Collections
/// Value to be added.
public void Add(T value)
{
- if(count == Capacity - 1)
+ if (count == Capacity - 1)
{
Capacity = 2 * Capacity;
}
@@ -168,7 +166,7 @@ namespace SystemExtensions.Collections
/// Enumerator that iterates over the heap.
public IEnumerator GetEnumerator()
{
- for(int i = 0; i < count; i++)
+ for (int i = 0; i < count; i++)
{
yield return items[i + 1];
}
@@ -183,14 +181,14 @@ namespace SystemExtensions.Collections
{
T temp = items[index];
int childIndex = 0;
- for(; 2*index <= count; index = childIndex)
+ for (; 2 * index <= count; index = childIndex)
{
childIndex = 2 * index;
- if(childIndex != Count && items[childIndex].CompareTo(items[childIndex + 1]) > 0)
+ if (childIndex != Count && items[childIndex].CompareTo(items[childIndex + 1]) > 0)
{
childIndex++;
}
- if(temp.CompareTo(items[childIndex]) > 0)
+ if (temp.CompareTo(items[childIndex]) > 0)
{
items[index] = items[childIndex];
}
@@ -206,7 +204,7 @@ namespace SystemExtensions.Collections
///
private void BuildHeap()
{
- for(int i = count / 2; i > 0; i--)
+ for (int i = count / 2; i > 0; i--)
{
BubbleDown(i);
}
diff --git a/SystemExtensions/Collections/FibonacciHeap.cs b/SystemExtensions/Collections/FibonacciHeap.cs
index d364727..a36dce0 100644
--- a/SystemExtensions/Collections/FibonacciHeap.cs
+++ b/SystemExtensions/Collections/FibonacciHeap.cs
@@ -1,9 +1,6 @@
using System;
using System.Collections;
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
namespace SystemExtensions.Collections
{
@@ -12,7 +9,7 @@ namespace SystemExtensions.Collections
///
/// Provided type
[Serializable]
- public class FibonacciHeap : IEnumerable where T : IComparable
+ public sealed class FibonacciHeap : IEnumerable where T : IComparable
{
#region Fields
private FibonacciNode root;
@@ -44,7 +41,6 @@ namespace SystemExtensions.Collections
///
/// Constructor for Fibonacci heap data structure.
///
- /// Function used to compare the elements.
public FibonacciHeap()
{
@@ -131,7 +127,7 @@ namespace SystemExtensions.Collections
/// Array with values from the heap.
public T[] ToArray()
{
- if(count == 0)
+ if (count == 0)
{
return null;
}
@@ -186,7 +182,7 @@ namespace SystemExtensions.Collections
{
Queue> queue = new Queue>();
queue.Enqueue(currentNode);
- while(queue.Count > 0)
+ while (queue.Count > 0)
{
currentNode = queue.Dequeue();
FibonacciNode oldNode = currentNode;
@@ -199,8 +195,8 @@ namespace SystemExtensions.Collections
}
currentNode = currentNode.Previous;
} while (currentNode != oldNode);
- }
-
+ }
+
}
///
/// Recursively remove the node and its children from the heap.
@@ -208,7 +204,7 @@ namespace SystemExtensions.Collections
/// Node to be removed.
private void Remove(FibonacciNode node)
{
- if(node != null)
+ if (node != null)
{
FibonacciNode current = node;
do
@@ -230,15 +226,15 @@ namespace SystemExtensions.Collections
/// Root of second heap.
private FibonacciNode Merge(FibonacciNode node1, FibonacciNode node2)
{
- if(node1 == null)
+ if (node1 == null)
{
return node2;
}
- if(node2 == null)
+ if (node2 == null)
{
return node1;
}
- if(node1.Value.CompareTo(node2.Value) > 0)
+ if (node1.Value.CompareTo(node2.Value) > 0)
{
FibonacciNode temp = node1;
node1 = node2;
@@ -270,7 +266,7 @@ namespace SystemExtensions.Collections
/// Node to be removed from its parent.
private void RemoveParent(FibonacciNode node)
{
- if(node == null)
+ if (node == null)
{
return;
}
@@ -290,7 +286,7 @@ namespace SystemExtensions.Collections
private FibonacciNode RemoveMinimum(FibonacciNode node)
{
RemoveParent(node.Child);
- if(node.Next == node)
+ if (node.Next == node)
{
node = node.Child;
}
@@ -300,7 +296,7 @@ namespace SystemExtensions.Collections
node.Previous.Next = node.Next;
node = Merge(node.Next, node.Child);
}
- if(node == null)
+ if (node == null)
{
return node;
}
@@ -308,15 +304,15 @@ namespace SystemExtensions.Collections
FibonacciNode[] trees = new FibonacciNode[64];
while (true)
{
- if(trees[node.Degree] != null)
+ if (trees[node.Degree] != null)
{
FibonacciNode t = trees[node.Degree];
- if(t == node)
+ if (t == node)
{
break;
}
trees[node.Degree] = null;
- if(node.Value.CompareTo(t.Value) < 0)
+ if (node.Value.CompareTo(t.Value) < 0)
{
t.Previous.Next = t.Next;
t.Next.Previous = t.Previous;
@@ -326,7 +322,7 @@ namespace SystemExtensions.Collections
{
t.Previous.Next = t.Next;
t.Next.Previous = t.Previous;
- if(node.Next == node)
+ if (node.Next == node)
{
t.Next = t.Previous = t;
AddChild(t, node);
@@ -354,7 +350,7 @@ namespace SystemExtensions.Collections
FibonacciNode start = node;
do
{
- if(node.Value.CompareTo(min.Value) < 0)
+ if (node.Value.CompareTo(min.Value) < 0)
{
min = node;
}
@@ -370,7 +366,7 @@ namespace SystemExtensions.Collections
///
private FibonacciNode Cut(FibonacciNode root, FibonacciNode node)
{
- if(node.Next == node)
+ if (node.Next == node)
{
node.Parent.Child = null;
}
@@ -393,26 +389,26 @@ namespace SystemExtensions.Collections
///
private FibonacciNode DecreaseKey(FibonacciNode root, FibonacciNode node, T value)
{
- if(node.Value.CompareTo(value) < 0)
+ if (node.Value.CompareTo(value) < 0)
{
return root;
}
node.Value = value;
- if(node.Parent != null)
+ if (node.Parent != null)
{
- if(node.Value.CompareTo(node.Parent.Value) < 0)
+ if (node.Value.CompareTo(node.Parent.Value) < 0)
{
root = Cut(root, node);
FibonacciNode parent = node.Parent;
node.Parent = null;
- while(parent != null && parent.Marked)
+ while (parent != null && parent.Marked)
{
root = Cut(root, parent);
node = parent;
parent = node.Parent;
node.Parent = null;
}
- if(parent != null && parent.Parent != null)
+ if (parent != null && parent.Parent != null)
{
parent.Marked = true;
}
@@ -420,7 +416,7 @@ namespace SystemExtensions.Collections
}
else
{
- if(node.Value.CompareTo(root.Value) < 0)
+ if (node.Value.CompareTo(root.Value) < 0)
{
root = node;
}
@@ -436,18 +432,18 @@ namespace SystemExtensions.Collections
private FibonacciNode Find(FibonacciNode root, T value)
{
FibonacciNode node = root;
- if(node == null)
+ if (node == null)
{
return null;
}
do
{
- if(node.Value.CompareTo(value) == 0)
+ if (node.Value.CompareTo(value) == 0)
{
return node;
}
FibonacciNode ret = Find(node.Child, value);
- if(ret != null)
+ if (ret != null)
{
return ret;
}
@@ -462,7 +458,7 @@ namespace SystemExtensions.Collections
#endregion
}
[Serializable]
- internal class FibonacciNode
+ internal sealed class FibonacciNode
{
#region Fields
private FibonacciNode previous;
@@ -537,7 +533,7 @@ namespace SystemExtensions.Collections
}
set
{
- this.value = value;
+ this.value = value;
}
}
public int Degree
diff --git a/SystemExtensions/Collections/IQueue.cs b/SystemExtensions/Collections/IQueue.cs
index c0cbfd1..2078f77 100644
--- a/SystemExtensions/Collections/IQueue.cs
+++ b/SystemExtensions/Collections/IQueue.cs
@@ -1,8 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+using System.Collections.Generic;
namespace SystemExtensions.Collections
{
diff --git a/SystemExtensions/Collections/PriorityQueue.cs b/SystemExtensions/Collections/PriorityQueue.cs
index d4f6b21..b3b186c 100644
--- a/SystemExtensions/Collections/PriorityQueue.cs
+++ b/SystemExtensions/Collections/PriorityQueue.cs
@@ -1,9 +1,6 @@
using System;
using System.Collections;
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
namespace SystemExtensions.Collections
{
@@ -13,7 +10,7 @@ namespace SystemExtensions.Collections
///
/// Provided type.
[Serializable]
- public class PriorityQueue : IQueue where T : IComparable
+ public sealed class PriorityQueue : IQueue where T : IComparable
{
#region Fields
private BinaryHeap binaryHeap;
@@ -34,7 +31,6 @@ namespace SystemExtensions.Collections
///
/// Constructor for priority queue data structure.
///
- /// Function used to compare the elements.
public PriorityQueue()
{
binaryHeap = new BinaryHeap();
diff --git a/SystemExtensions/Collections/SkipList.cs b/SystemExtensions/Collections/SkipList.cs
index 66963cd..5ff5534 100644
--- a/SystemExtensions/Collections/SkipList.cs
+++ b/SystemExtensions/Collections/SkipList.cs
@@ -1,9 +1,6 @@
using System;
using System.Collections;
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
namespace SystemExtensions.Collections
{
@@ -12,7 +9,7 @@ namespace SystemExtensions.Collections
///
/// Provided type.
[Serializable]
- public class SkipList : ICollection where T : IComparable
+ public sealed class SkipList : ICollection where T : IComparable
{
#region Fields
[Serializable]
@@ -53,11 +50,11 @@ namespace SystemExtensions.Collections
/// Maximum level of the skip list.
public SkipList(int maxLevel = 10)
{
- this.maxLevel = maxLevel;
+ this.maxLevel = maxLevel;
random = new Random();
head = new NodeSet(default(T), maxLevel);
end = head;
- for(int i = 0; i <= maxLevel; i++)
+ for (int i = 0; i <= maxLevel; i++)
{
head.Next[i] = end;
}
@@ -84,7 +81,7 @@ namespace SystemExtensions.Collections
NodeSet newNode = new NodeSet(item, newLevel);
for (var i = 0; i <= newLevel; i++)
{
- if(i > curNode.Level)
+ if (i > curNode.Level)
{
curNode = head;
}
@@ -108,7 +105,7 @@ namespace SystemExtensions.Collections
NodeSet curNode = head;
for (var i = 0; i <= maxLevel; i++)
{
- if(i > curNode.Level)
+ if (i > curNode.Level)
{
curNode = head;
}
@@ -141,7 +138,7 @@ namespace SystemExtensions.Collections
///
public void Clear()
{
- for(int i = 0; i < maxLevel; i++)
+ for (int i = 0; i < maxLevel; i++)
{
head.Next[i] = end;
}
@@ -154,7 +151,7 @@ namespace SystemExtensions.Collections
/// True if item is present in the collection.
public bool Contains(T item)
{
- if(Find(item) != null)
+ if (Find(item) != null)
{
return true;
}
@@ -168,7 +165,7 @@ namespace SystemExtensions.Collections
public void CopyTo(T[] array, int arrayIndex)
{
NodeSet node = head.Next[0];
- while(node != end)
+ while (node != end)
{
array[arrayIndex] = node.Key;
arrayIndex++;
@@ -184,7 +181,7 @@ namespace SystemExtensions.Collections
T[] array = new T[count];
int index = 0;
NodeSet curNode = head.Next[0];
- while(curNode != end)
+ while (curNode != end)
{
array[index] = curNode.Key;
index++;
@@ -199,7 +196,7 @@ namespace SystemExtensions.Collections
public IEnumerator GetEnumerator()
{
NodeSet curNode = head.Next[0];
- while(curNode != end)
+ while (curNode != end)
{
yield return curNode.Key;
curNode = curNode.Next[0];
@@ -215,15 +212,15 @@ namespace SystemExtensions.Collections
{
NodeSet curNode = head;
- for(int i = level; i >= 0; i--)
+ for (int i = level; i >= 0; i--)
{
- while(curNode.Next[i] != end)
+ while (curNode.Next[i] != end)
{
- if(curNode.Next[i].Key.CompareTo(key) > 0)
+ if (curNode.Next[i].Key.CompareTo(key) > 0)
{
break;
}
- else if(curNode.Next[i].Key.CompareTo(key) == 0)
+ else if (curNode.Next[i].Key.CompareTo(key) == 0)
{
return curNode.Next[i];
}
@@ -232,7 +229,7 @@ namespace SystemExtensions.Collections
}
curNode = curNode.Next[0];
- if(curNode != end && curNode.Key.CompareTo(key) == 0)
+ if (curNode != end && curNode.Key.CompareTo(key) == 0)
{
return curNode;
}
diff --git a/SystemExtensions/Collections/Treap.cs b/SystemExtensions/Collections/Treap.cs
index 3615634..88c1499 100644
--- a/SystemExtensions/Collections/Treap.cs
+++ b/SystemExtensions/Collections/Treap.cs
@@ -1,9 +1,6 @@
using System;
using System.Collections;
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
namespace SystemExtensions.Collections
{
@@ -12,7 +9,7 @@ namespace SystemExtensions.Collections
///
/// Provided type.
[Serializable]
- public class Treap : ICollection where T : IComparable
+ public sealed class Treap : ICollection where T : IComparable
{
#region Fields
[Serializable]
@@ -44,14 +41,15 @@ namespace SystemExtensions.Collections
return count;
}
}
-
- public bool IsReadOnly => throw new NotImplementedException();
+ ///
+ /// Not implemented.
+ ///
+ public bool IsReadOnly => false;
#endregion
#region Constructors
///
/// Constructor for treap.
///
- /// Comparator method used to compare values.
public Treap()
{
randomGen = new Random();
@@ -134,14 +132,15 @@ namespace SystemExtensions.Collections
#region Private Methods
private Node InsertNode(Node node, T key)
{
- if(node == null) {
+ if (node == null)
+ {
node = new Node(key, randomGen.Next(0, 100));
return node;
}
else if (key.CompareTo(node.Key) <= 0)
{
node.Left = InsertNode(node.Left, key);
- if(node.Left.Priority > node.Priority)
+ if (node.Left.Priority > node.Priority)
{
node = RotateRight(node);
}
@@ -149,7 +148,7 @@ namespace SystemExtensions.Collections
else
{
node.Right = InsertNode(node.Right, key);
- if(node.Right.Priority > node.Priority)
+ if (node.Right.Priority > node.Priority)
{
node = RotateLeft(node);
}
@@ -158,27 +157,27 @@ namespace SystemExtensions.Collections
}
private Node RemoveNode(Node node, T key)
{
- if(node == null)
+ if (node == null)
{
- return node;
+ return node;
}
- if(key.CompareTo(node.Key) < 0)
+ if (key.CompareTo(node.Key) < 0)
{
node.Left = RemoveNode(node.Left, key);
}
- else if(key.CompareTo(node.Key) > 0)
+ else if (key.CompareTo(node.Key) > 0)
{
node.Right = RemoveNode(node.Right, key);
- }
+ }
else if (node.Left == null)
{
node = node.Right;
}
- else if(node.Right == null)
+ else if (node.Right == null)
{
node = node.Left;
}
- else if(node.Left.Priority < node.Right.Priority)
+ else if (node.Left.Priority < node.Right.Priority)
{
node = RotateLeft(node);
node.Left = RemoveNode(node.Left, key);
@@ -206,11 +205,11 @@ namespace SystemExtensions.Collections
}
private void Clear(Node node)
{
- if(node.Left != null)
+ if (node.Left != null)
{
Clear(node.Left);
}
- if(node.Right != null)
+ if (node.Right != null)
{
Clear(node.Right);
}
@@ -218,22 +217,22 @@ namespace SystemExtensions.Collections
}
private Node Find(Node node, T key)
{
- if(node == null)
+ if (node == null)
{
return node;
}
else
{
- if(node.Key.CompareTo(key) < 0)
+ if (node.Key.CompareTo(key) < 0)
{
Node found = Find(node.Left, key);
- if(found == null)
+ if (found == null)
{
found = Find(node.Right, key);
}
return found;
}
- else if(node.Key.CompareTo(key) > 0)
+ else if (node.Key.CompareTo(key) > 0)
{
Node found = Find(node.Right, key);
if (found == null)
@@ -250,7 +249,7 @@ namespace SystemExtensions.Collections
}
private void ToArray(Node node, ref T[] array, ref int index)
{
- if(node != null)
+ if (node != null)
{
ToArray(node.Left, ref array, ref index);
array[index] = node.Key;
@@ -262,15 +261,15 @@ namespace SystemExtensions.Collections
{
Queue> queue = new Queue>();
queue.Enqueue(currentNode);
- while(queue.Count > 0)
+ while (queue.Count > 0)
{
currentNode = queue.Dequeue();
yield return currentNode.Key;
- if(currentNode.Left != null)
+ if (currentNode.Left != null)
{
queue.Enqueue(currentNode.Left);
}
- if(currentNode.Right != null)
+ if (currentNode.Right != null)
{
queue.Enqueue(currentNode.Right);
}
diff --git a/SystemExtensions/ItemNotFoundException.cs b/SystemExtensions/ItemNotFoundException.cs
index def126c..db5a36a 100644
--- a/SystemExtensions/ItemNotFoundException.cs
+++ b/SystemExtensions/ItemNotFoundException.cs
@@ -1,14 +1,11 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
namespace SystemExtensions
{
///
/// Custom implementation of an exception.
///
+ [Serializable]
public class ItemNotFoundException : Exception
{
///
diff --git a/SystemExtensions/Properties/AssemblyInfo.cs b/SystemExtensions/Properties/AssemblyInfo.cs
index 327d7c0..493de4d 100644
--- a/SystemExtensions/Properties/AssemblyInfo.cs
+++ b/SystemExtensions/Properties/AssemblyInfo.cs
@@ -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
diff --git a/SystemExtensions/Security/ProcessInformation.cs b/SystemExtensions/Security/ProcessInformation.cs
new file mode 100644
index 0000000..1c49ea3
--- /dev/null
+++ b/SystemExtensions/Security/ProcessInformation.cs
@@ -0,0 +1,793 @@
+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
+{
+ ///
+ /// Helper class to obtain admin privileges and elevation status.
+ ///
+ /// Source code provided on https://code.msdn.microsoft.com/windowsapps/CSUACSelfElevation-644673d3
+ public static class ProcessInformation
+ {
+ ///
+ /// 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.
+ ///
+ ///
+ /// 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.
+ ///
+ ///
+ /// When any native Windows API call fails, the function throws a Win32Exception
+ /// with the last error code.
+ ///
+ 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;
+ }
+
+
+ ///
+ /// 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.
+ ///
+ ///
+ /// 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.
+ ///
+ public static bool IsRunAsAdmin()
+ {
+ WindowsIdentity id = WindowsIdentity.GetCurrent();
+ WindowsPrincipal principal = new WindowsPrincipal(id);
+ return principal.IsInRole(WindowsBuiltInRole.Administrator);
+ }
+
+
+ ///
+ /// 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.
+ ///
+ ///
+ /// Returns true if the process is elevated. Returns false if it is not.
+ ///
+ ///
+ /// When any native Windows API call fails, the function throws a Win32Exception
+ /// with the last error code.
+ ///
+ ///
+ /// 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.
+ ///
+ 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;
+ }
+
+
+ ///
+ /// 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.
+ ///
+ ///
+ /// 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)
+ ///
+ ///
+ ///
+ /// When any native Windows API call fails, the function throws a Win32Exception
+ /// with the last error code.
+ ///
+ 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;
+ }
+
+ ///
+ /// Elevate process to administration rights.
+ ///
+ /// True if the elevation succeeded or false if it failed.
+ 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;
+ }
+ }
+
+ ///
+ /// Gets the application path of the running assembly.
+ ///
+ /// String containing the path to the executing assembly.
+ public static string GetApplicationPath()
+ {
+ var exePath = Path.GetDirectoryName(System.Reflection
+ .Assembly.GetExecutingAssembly().CodeBase);
+ Regex appPathMatcher = new Regex(@"(?
+ /// The TOKEN_INFORMATION_CLASS enumeration type contains values that
+ /// specify the type of information being assigned to or retrieved from
+ /// an access token.
+ ///
+ 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
+ }
+
+ ///
+ /// 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.
+ ///
+ 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
+ }
+
+ ///
+ /// 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.
+ ///
+ internal enum SECURITY_IMPERSONATION_LEVEL
+ {
+ SecurityAnonymous,
+ SecurityIdentification,
+ SecurityImpersonation,
+ SecurityDelegation
+ }
+
+ ///
+ /// The TOKEN_ELEVATION_TYPE enumeration indicates the elevation type of
+ /// token being queried by the GetTokenInformation function or set by
+ /// the SetTokenInformation function.
+ ///
+ internal enum TOKEN_ELEVATION_TYPE
+ {
+ TokenElevationTypeDefault = 1,
+ TokenElevationTypeFull,
+ TokenElevationTypeLimited
+ }
+
+ ///
+ /// The structure represents a security identifier (SID) and its
+ /// attributes. SIDs are used to uniquely identify users or groups.
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct SID_AND_ATTRIBUTES
+ {
+ public IntPtr Sid;
+ public UInt32 Attributes;
+ }
+
+ ///
+ /// The structure indicates whether a token has elevated privileges.
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct TOKEN_ELEVATION
+ {
+ public Int32 TokenIsElevated;
+ }
+
+ ///
+ /// The structure specifies the mandatory integrity level for a token.
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct TOKEN_MANDATORY_LABEL
+ {
+ public SID_AND_ATTRIBUTES Label;
+ }
+
+ ///
+ /// Represents a wrapper class for a token handle.
+ ///
+ 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;
+
+
+ ///
+ /// The function opens the access token associated with a process.
+ ///
+ ///
+ /// A handle to the process whose access token is opened.
+ ///
+ ///
+ /// Specifies an access mask that specifies the requested types of
+ /// access to the access token.
+ ///
+ ///
+ /// Outputs a handle that identifies the newly opened access token
+ /// when the function returns.
+ ///
+ ///
+ [DllImport("advapi32", CharSet = CharSet.Auto, SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool OpenProcessToken(IntPtr hProcess,
+ UInt32 desiredAccess, out SafeTokenHandle hToken);
+
+
+ ///
+ /// The function creates a new access token that duplicates one
+ /// already in existence.
+ ///
+ ///
+ /// A handle to an access token opened with TOKEN_DUPLICATE access.
+ ///
+ ///
+ /// Specifies a SECURITY_IMPERSONATION_LEVEL enumerated type that
+ /// supplies the impersonation level of the new token.
+ ///
+ ///
+ /// Outputs a handle to the duplicate token.
+ ///
+ ///
+ [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+ public extern static bool DuplicateToken(
+ SafeTokenHandle ExistingTokenHandle,
+ SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
+ out SafeTokenHandle DuplicateTokenHandle);
+
+
+ ///
+ /// The function retrieves a specified type of information about an
+ /// access token. The calling process must have appropriate access
+ /// rights to obtain the information.
+ ///
+ ///
+ /// A handle to an access token from which information is retrieved.
+ ///
+ ///
+ /// Specifies a value from the TOKEN_INFORMATION_CLASS enumerated
+ /// type to identify the type of information the function retrieves.
+ ///
+ ///
+ /// A pointer to a buffer the function fills with the requested
+ /// information.
+ ///
+ ///
+ /// Specifies the size, in bytes, of the buffer pointed to by the
+ /// TokenInformation parameter.
+ ///
+ ///
+ /// A pointer to a variable that receives the number of bytes needed
+ /// for the buffer pointed to by the TokenInformation parameter.
+ ///
+ ///
+ [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);
+
+
+ ///
+ /// Sets the elevation required state for a specified button or
+ /// command link to display an elevated icon.
+ ///
+ public const UInt32 BCM_SETSHIELD = 0x160C;
+
+
+ ///
+ /// 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.
+ ///
+ ///
+ /// Handle to the window whose window procedure will receive the
+ /// message.
+ ///
+ /// Specifies the message to be sent.
+ ///
+ /// Specifies additional message-specific information.
+ ///
+ ///
+ /// Specifies additional message-specific information.
+ ///
+ ///
+ [DllImport("user32", CharSet = CharSet.Auto, SetLastError = true)]
+ public static extern int SendMessage(IntPtr hWnd, UInt32 Msg, int wParam, IntPtr lParam);
+
+
+ ///
+ /// The function returns a pointer to a specified subauthority in a
+ /// security identifier (SID). The subauthority value is a relative
+ /// identifier (RID).
+ ///
+ ///
+ /// A pointer to the SID structure from which a pointer to a
+ /// subauthority is to be returned.
+ ///
+ ///
+ /// Specifies an index value identifying the subauthority array
+ /// element whose address the function will return.
+ ///
+ ///
+ /// 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.
+ ///
+ [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+ public static extern IntPtr GetSidSubAuthority(IntPtr pSid, UInt32 nSubAuthority);
+ }
+ }
+}
diff --git a/SystemExtensions/SystemExtensions.csproj b/SystemExtensions/SystemExtensions.csproj
index 0fbb5c7..d28d10a 100644
--- a/SystemExtensions/SystemExtensions.csproj
+++ b/SystemExtensions/SystemExtensions.csproj
@@ -9,7 +9,7 @@
Properties
SystemExtensions
SystemExtensions
- v4.6.1
+ v4.7.2
512
true
@@ -54,6 +54,7 @@
+
diff --git a/SystemExtensions/Threading/PriorityThreadPool.cs b/SystemExtensions/Threading/PriorityThreadPool.cs
index dd9febc..02cf0af 100644
--- a/SystemExtensions/Threading/PriorityThreadPool.cs
+++ b/SystemExtensions/Threading/PriorityThreadPool.cs
@@ -1,9 +1,6 @@
using System;
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
using System.Threading;
-using System.Threading.Tasks;
using SystemExtensions.Collections;
namespace SystemExtensions.Threading
@@ -239,7 +236,7 @@ namespace SystemExtensions.Threading
{
threadpool = new List();
tasks = new PriorityQueue();
- for(int i = 0; i < lowest; i++)
+ for (int i = 0; i < lowest; i++)
{
WorkerThread worker = new WorkerThread();
worker.thread = new Thread(() =>
@@ -304,7 +301,7 @@ namespace SystemExtensions.Threading
worker.thread.Start();
threadpool.Add(worker);
}
- }
+ }
#endregion
#region Public Methods
///
@@ -315,7 +312,7 @@ namespace SystemExtensions.Threading
/// Priority of task. Affects its position into the queue.
public void QueueUserWorkItem(WaitCallback waitCallback, object callbackState, TaskPriority taskPriority)
{
- while (!Monitor.TryEnter(tasksLock));
+ while (!Monitor.TryEnter(tasksLock)) ;
tasks.Enqueue(new QueueEntry(taskPriority, waitCallback, callbackState));
Monitor.Exit(tasksLock);
}
@@ -384,7 +381,7 @@ namespace SystemExtensions.Threading
if (statistics.Initialized)
{
double loopDuration = (DateTime.Now - statistics.LastUpdate).TotalMilliseconds;
- if(statistics.LoopFrequency == 0)
+ if (statistics.LoopFrequency == 0)
{
statistics.LoopFrequency = loopDuration;
}
@@ -403,10 +400,10 @@ namespace SystemExtensions.Threading
//This part of code adjusts the performance counter. Ideally, the value should be 0.
- if(tasks.Count > 0)
+ if (tasks.Count > 0)
{
statistics.PerformanceCounter++;
- if(statistics.PerformanceCounter > 5)
+ if (statistics.PerformanceCounter > 5)
{
statistics.PerformanceCounter = 5;
}
@@ -414,18 +411,18 @@ namespace SystemExtensions.Threading
else
{
statistics.PerformanceCounter--;
- if(statistics.PerformanceCounter < -10)
+ if (statistics.PerformanceCounter < -10)
{
statistics.PerformanceCounter = -10;
}
}
//This part of code adjusts thread priorities based on the current performance of the threadpool
- if(tasks.Count > 0)
+ if (tasks.Count > 0)
{
//If there are tasks pending, find a thread with priority under Normal and upgrade its priority.
Thread t = FindThreadWithLowPriority();
- if(t != null)
+ if (t != null)
{
UpgradeThreadPriority(t);
}
@@ -434,7 +431,7 @@ namespace SystemExtensions.Threading
{
//If there are no tasks pending, find a thread with priority above Lowest and downgrade its priority.
Thread t = FindThreadWithAcceptablePriority();
- if(t != null)
+ if (t != null)
{
DowngradeThreadPriority(t);
}
@@ -460,7 +457,7 @@ namespace SystemExtensions.Threading
threadpool.Add(worker);
}
}
- else if(statistics.PerformanceCounter <= -10)
+ else if (statistics.PerformanceCounter <= -10)
{
if (threadpool.Count > maxThreads / 4)
{
@@ -489,9 +486,9 @@ namespace SystemExtensions.Threading
/// Thread with low priority.
private Thread FindThreadWithLowPriority()
{
- foreach(WorkerThread t in threadpool)
+ foreach (WorkerThread t in threadpool)
{
- if(t.thread.Priority == ThreadPriority.Lowest || t.thread.Priority == ThreadPriority.BelowNormal)
+ if (t.thread.Priority == ThreadPriority.Lowest || t.thread.Priority == ThreadPriority.BelowNormal)
{
return t.thread;
}
diff --git a/SystemExtensionsTests/SystemExtensionsTests.csproj b/SystemExtensionsTests/SystemExtensionsTests.csproj
index 74d98d4..72d2c9c 100644
--- a/SystemExtensionsTests/SystemExtensionsTests.csproj
+++ b/SystemExtensionsTests/SystemExtensionsTests.csproj
@@ -9,7 +9,7 @@
Properties
SystemExtensionsTests
SystemExtensionsTests
- v4.6.1
+ v4.7.2
512
{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
10.0