Removed code and conditionals for obsolete target frameworks.

pull/279/head
dahall 2022-02-07 14:58:09 -07:00
parent d9f00186b0
commit b669932c57
24 changed files with 16 additions and 2368 deletions

View File

@ -1,448 +0,0 @@
#if NET20 || NET35
// Sourced from
// https://github.com/dotnet/corefx/blob/a6f76f4f620cbe74821c6445af3f13e048361658/src/System.Security.AccessControl/src/System/Security/AccessControl/ObjectSecurityT.cs.
// Only additions are preprocessor directives for conditional compilation and XML comments pulled from Microsoft documentation.
// Licensed to the .NET Foundation under one or more agreements. The .NET Foundation licenses this file to you under the MIT license. See the
// LICENSE file in the project root for more information.
/*============================================================
**
** Class: ObjectSecurity
**
** Purpose: Generic Managed ACL wrapper
**
** Date: February 7, 2007
**
===========================================================*/
using System.Runtime.InteropServices;
using System.Security.Principal;
using ResourceType = System.Security.AccessControl.ResourceType;
namespace System.Security.AccessControl
{
/// <summary>
/// Represents a combination of a user's identity, an access mask, and an access control type (allow or deny). An AccessRule`1 object
/// also contains information about the how the rule is inherited by child objects and how that inheritance is propagated.
/// </summary>
/// <typeparam name="T">The access rights type for the access rule.</typeparam>
/// <seealso cref="System.Security.AccessControl.AccessRule"/>
public class AccessRule<T> : AccessRule where T : struct
{
// Constructors for creating access rules for file objects
/// <summary>Initializes a new instance of the <see cref="AccessRule{T}"/> class by using the specified values.</summary>
/// <param name="identity">The identity to which the access rule applies.</param>
/// <param name="rights">The rights of the access rule.</param>
/// <param name="type">The valid access control type.</param>
public AccessRule(IdentityReference identity, T rights, AccessControlType type) :
this(identity, (int)(object)rights, false, InheritanceFlags.None, PropagationFlags.None, type)
{ }
/// <summary>Initializes a new instance of the <see cref="AccessRule{T}"/> class by using the specified values.</summary>
/// <param name="identity">The identity to which the access rule applies.</param>
/// <param name="rights">The rights of the access rule.</param>
/// <param name="type">The valid access control type.</param>
public AccessRule(string identity, T rights, AccessControlType type) :
this(new NTAccount(identity), (int)(object)rights, false, InheritanceFlags.None, PropagationFlags.None, type)
{ }
// Constructor for creating access rules for folder objects
/// <summary>Initializes a new instance of the <see cref="AccessRule{T}"/> class by using the specified values.</summary>
/// <param name="identity">The identity to which the access rule applies.</param>
/// <param name="rights">The rights of the access rule.</param>
/// <param name="inheritanceFlags">The inheritance properties of the access rule.</param>
/// <param name="propagationFlags">
/// Whether inherited access rules are automatically propagated. The propagation flags are ignored if inheritanceFlags is set to None.
/// </param>
/// <param name="type">The valid access control type.</param>
public AccessRule(IdentityReference identity, T rights, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, AccessControlType type) :
this(identity, (int)(object)rights, false, inheritanceFlags, propagationFlags, type)
{ }
/// <summary>Initializes a new instance of the <see cref="AccessRule{T}"/> class by using the specified values.</summary>
/// <param name="identity">The identity to which the access rule applies.</param>
/// <param name="rights">The rights of the access rule.</param>
/// <param name="inheritanceFlags">The inheritance properties of the access rule.</param>
/// <param name="propagationFlags">
/// Whether inherited access rules are automatically propagated. The propagation flags are ignored if inheritanceFlags is set to None.
/// </param>
/// <param name="type">The valid access control type.</param>
public AccessRule(string identity, T rights, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, AccessControlType type) :
this(new NTAccount(identity), (int)(object)rights, false, inheritanceFlags, propagationFlags, type)
{ }
internal AccessRule(IdentityReference identity, int accessMask, bool isInherited, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, AccessControlType type) :
base(identity, accessMask, isInherited, inheritanceFlags, propagationFlags, type)
{ }
/// <summary>Gets the rights of the current instance.</summary>
/// <value>The rights, cast as type <typeparamref name="T"/>, of the current instance.</value>
public T Rights => (T)(object)AccessMask;
}
/// <summary>Represents a combination of a user's identity and an access mask.</summary>
/// <typeparam name="T">The type of the audit rule.</typeparam>
/// <seealso cref="System.Security.AccessControl.AuditRule"/>
public class AuditRule<T> : AuditRule where T : struct
{
/// <summary>Initializes a new instance of the <see cref="AuditRule{T}"/> class by using the specified values.</summary>
/// <param name="identity">The identity to which this audit rule applies.</param>
/// <param name="rights">The rights of the audit rule.</param>
/// <param name="flags">The conditions for which the rule is audited.</param>
public AuditRule(IdentityReference identity, T rights, AuditFlags flags) :
this(identity, rights, InheritanceFlags.None, PropagationFlags.None, flags)
{
}
/// <summary>Initializes a new instance of the <see cref="AuditRule{T}"/> class by using the specified values.</summary>
/// <param name="identity">The identity to which this audit rule applies.</param>
/// <param name="rights">The rights of the audit rule.</param>
/// <param name="inheritanceFlags">The inheritance properties of the audit rule.</param>
/// <param name="propagationFlags">Whether inherited audit rules are automatically propagated.</param>
/// <param name="flags">The conditions for which the rule is audited.</param>
public AuditRule(IdentityReference identity, T rights, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, AuditFlags flags) :
this(identity, (int)(object)rights, false, inheritanceFlags, propagationFlags, flags)
{
}
/// <summary>Initializes a new instance of the <see cref="AuditRule{T}"/> class by using the specified values.</summary>
/// <param name="identity">The identity to which this audit rule applies.</param>
/// <param name="rights">The rights of the audit rule.</param>
/// <param name="flags">The conditions for which the rule is audited.</param>
public AuditRule(string identity, T rights, AuditFlags flags) :
this(new NTAccount(identity), rights, InheritanceFlags.None, PropagationFlags.None, flags)
{
}
/// <summary>Initializes a new instance of the <see cref="AuditRule{T}"/> class by using the specified values.</summary>
/// <param name="identity">The identity to which this audit rule applies.</param>
/// <param name="rights">The rights of the audit rule.</param>
/// <param name="inheritanceFlags">The inheritance properties of the audit rule.</param>
/// <param name="propagationFlags">Whether inherited audit rules are automatically propagated.</param>
/// <param name="flags">The conditions for which the rule is audited.</param>
public AuditRule(string identity, T rights, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, AuditFlags flags) :
this(new NTAccount(identity), (int)(object)rights, false, inheritanceFlags, propagationFlags, flags)
{
}
internal AuditRule(IdentityReference identity, int accessMask, bool isInherited, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, AuditFlags flags) :
base(identity, accessMask, isInherited, inheritanceFlags, propagationFlags, flags)
{
}
/// <summary>Gets the rights of the audit rule.</summary>
/// <value>The rights, cast as type <typeparamref name="T"/>, of the audit rule.</value>
public T Rights => (T)(object)AccessMask;
}
/// <summary>
/// Provides the ability to control access to objects without direct manipulation of Access Control Lists (ACLs); also grants the ability
/// to type-cast access rights.
/// </summary>
/// <typeparam name="T">The access rights for the object.</typeparam>
/// <seealso cref="System.Security.AccessControl.NativeObjectSecurity"/>
public abstract class ObjectSecurity<T> : NativeObjectSecurity where T : struct
{
/// <summary>Initializes a new instance of the <see cref="ObjectSecurity{T}"/> class.</summary>
/// <param name="isContainer">
/// <see langword="true"/> if the new <see cref="T:System.Security.AccessControl.NativeObjectSecurity"/> object is a container object.
/// </param>
/// <param name="resourceType">
/// The type of securable object with which the new <see cref="T:System.Security.AccessControl.NativeObjectSecurity"/> object is associated.
/// </param>
protected ObjectSecurity(bool isContainer, ResourceType resourceType)
: base(isContainer, resourceType, null, null)
{ }
/// <summary>Initializes a new instance of the <see cref="ObjectSecurity{T}"/> class.</summary>
/// <param name="isContainer">
/// <see langword="true"/> if the new <see cref="T:System.Security.AccessControl.NativObjectSecurity"/> object is a container object.
/// </param>
/// <param name="resourceType">
/// The type of securable object with which the new <see cref="T:System.Security.AccessControl.NativeObjectSecurity"/> object is associated.
/// </param>
/// <param name="name">
/// The name of the securable object with which the new <see cref="T:System.Security.AccessControl.NativeObjectSecurity"/> object is associated.
/// </param>
/// <param name="includeSections">
/// One of the <see cref="T:System.Security.AccessControl.AccessControlSections"/> enumeration values that specifies the sections of
/// the security descriptor (access rules, audit rules, owner, primary group) of the securable object to include in this
/// <see cref="T:System.Security.AccessControl.NativeObjectSecurity"/> object.
/// </param>
protected ObjectSecurity(bool isContainer, ResourceType resourceType, string name, AccessControlSections includeSections)
: base(isContainer, resourceType, name, includeSections, null, null)
{ }
/// <summary>Initializes a new instance of the <see cref="ObjectSecurity{T}"/> class.</summary>
/// <param name="isContainer">
/// <see langword="true"/> if the new <see cref="T:System.Security.AccessControl.NativeObjectSecurity"/> object is a container object.
/// </param>
/// <param name="resourceType">
/// The type of securable object with which the new <see cref="T:System.Security.AccessControl.NativeObjectSecurity"/> object is associated.
/// </param>
/// <param name="name">
/// The name of the securable object with which the new <see cref="T:System.Security.AccessControl.NativeObjectSecurity"/> object is associated.
/// </param>
/// <param name="includeSections">
/// One of the <see cref="T:System.Security.AccessControl.AccessControlSections"/> enumeration values that specifies the sections of
/// the security descriptor (access rules, audit rules, owner, primary group) of the securable object to include in this
/// <see cref="T:System.Security.AccessControl.NativeObjectSecurity"/> object.
/// </param>
/// <param name="exceptionFromErrorCode">A delegate implemented by integrators that provides custom exceptions.</param>
/// <param name="exceptionContext">An object that contains contextual information about the source or destination of the exception.</param>
protected ObjectSecurity(bool isContainer, ResourceType resourceType, string name, AccessControlSections includeSections, ExceptionFromErrorCode exceptionFromErrorCode, object exceptionContext)
: base(isContainer, resourceType, name, includeSections, exceptionFromErrorCode, exceptionContext)
{ }
/// <summary>Initializes a new instance of the <see cref="ObjectSecurity{T}"/> class.</summary>
/// <param name="isContainer">
/// <see langword="true"/> if the new <see cref="T:System.Security.AccessControl.NativeObjectSecurity"/> object is a container object.
/// </param>
/// <param name="resourceType">
/// The type of securable object with which the new <see cref="T:System.Security.AccessControl.NativeObjectSecurity"/> object is associated.
/// </param>
/// <param name="safeHandle">A handle.</param>
/// <param name="includeSections">
/// One of the <see cref="T:System.Security.AccessControl.AccessControlSections"/> enumeration values that specifies the sections of
/// the security descriptor (access rules, audit rules, owner, primary group) of the securable object to include in this
/// <see cref="T:System.Security.AccessControl.NativeObjectSecurity"/> object.
/// </param>
protected ObjectSecurity(bool isContainer, ResourceType resourceType, SafeHandle safeHandle, AccessControlSections includeSections)
: base(isContainer, resourceType, safeHandle, includeSections, null, null)
{ }
/// <summary>Initializes a new instance of the <see cref="ObjectSecurity{T}"/> class.</summary>
/// <param name="isContainer">
/// <see langword="true"/> if the new <see cref="T:System.Security.AccessControl.NativeObjectSecurity"/> object is a container object.
/// </param>
/// <param name="resourceType">
/// The type of securable object with which the new <see cref="T:System.Security.AccessControl.NativeObjectSecurity"/> object is associated.
/// </param>
/// <param name="safeHandle">A handle.</param>
/// <param name="includeSections">
/// One of the <see cref="T:System.Security.AccessControl.AccessControlSections"/> enumeration values that specifies the sections of
/// the security descriptor (access rules, audit rules, owner, primary group) of the securable object to include in this
/// <see cref="T:System.Security.AccessControl.NativeObjectSecurity"/> object.
/// </param>
/// <param name="exceptionFromErrorCode">A delegate implemented by integrators that provides custom exceptions.</param>
/// <param name="exceptionContext">An object that contains contextual information about the source or destination of the exception.</param>
protected ObjectSecurity(bool isContainer, ResourceType resourceType, SafeHandle safeHandle, AccessControlSections includeSections,
ExceptionFromErrorCode exceptionFromErrorCode, object exceptionContext)
: base(isContainer, resourceType, safeHandle, includeSections, exceptionFromErrorCode, exceptionContext)
{ }
/// <summary>
/// Gets the <see cref="T:System.Type"/> of the securable object associated with this
/// <see cref="T:System.Security.AccessControl.ObjectSecurity"/> object.
/// </summary>
public override Type AccessRightType => typeof(T);
/// <summary>
/// Gets the <see cref="T:System.Type"/> of the object associated with the access rules of this
/// <see cref="T:System.Security.AccessControl.ObjectSecurity"/> object. The <see cref="T:System.Type"/> object must be an object
/// that can be cast as a <see cref="T:System.Security.Principal.SecurityIdentifier"/> object.
/// </summary>
public override Type AccessRuleType => typeof(AccessRule<T>);
/// <summary>
/// Gets the <see cref="T:System.Type"/> object associated with the audit rules of this
/// <see cref="T:System.Security.AccessControl.ObjectSecurity"/> object. The <see cref="T:System.Type"/> object must be an object
/// that can be cast as a <see cref="T:System.Security.Principal.SecurityIdentifier"/> object.
/// </summary>
public override Type AuditRuleType => typeof(AuditRule<T>);
/// <summary>
/// Initializes a new instance of the <see cref="T:System.Security.AccessControl.AccessRule"/> class with the specified values.
/// </summary>
/// <param name="identityReference">The identity to which the access rule applies. It must be an object that can be cast as a <see cref="T:System.Security.Principal.SecurityIdentifier"/>.</param>
/// <param name="accessMask">
/// The access mask of this rule. The access mask is a 32-bit collection of anonymous bits, the meaning of which is defined by the
/// individual integrators.
/// </param>
/// <param name="isInherited">true if this rule is inherited from a parent container.</param>
/// <param name="inheritanceFlags">Specifies the inheritance properties of the access rule.</param>
/// <param name="propagationFlags">
/// Specifies whether inherited access rules are automatically propagated. The propagation flags are ignored if
/// <paramref name="inheritanceFlags"/> is set to <see cref="F:System.Security.AccessControl.InheritanceFlags.None"/>.
/// </param>
/// <param name="type">Specifies the valid access control type.</param>
/// <returns>The <see cref="T:System.Security.AccessControl.AccessRule"/> object that this method creates.</returns>
public override AccessRule AccessRuleFactory(IdentityReference identityReference, int accessMask, bool isInherited, InheritanceFlags inheritanceFlags,
PropagationFlags propagationFlags, AccessControlType type) =>
new AccessRule<T>(identityReference, accessMask, isInherited, inheritanceFlags, propagationFlags, type);
// Override these if you need to do some custom bit remapping to hide any complexity from the user.
/// <summary>
/// Adds the specified access rule to the Discretionary Access Control List (DACL) associated with this
/// <see cref="ObjectSecurity{T}"/> object.
/// </summary>
/// <param name="rule">The rule to add.</param>
public virtual void AddAccessRule(AccessRule<T> rule) => base.AddAccessRule(rule);
/// <summary>
/// Adds the specified audit rule to the System Access Control List (SACL) associated with this <see cref="ObjectSecurity{T}"/> object.
/// </summary>
/// <param name="rule">The audit rule to add.</param>
public virtual void AddAuditRule(AuditRule<T> rule) => base.AddAuditRule(rule);
/// <summary>
/// Initializes a new instance of the <see cref="T:System.Security.AccessControl.AuditRule"/> class with the specified values.
/// </summary>
/// <param name="identityReference">The identity to which the audit rule applies. It must be an object that can be cast as a <see cref="T:System.Security.Principal.SecurityIdentifier"/>.</param>
/// <param name="accessMask">
/// The access mask of this rule. The access mask is a 32-bit collection of anonymous bits, the meaning of which is defined by the
/// individual integrators.
/// </param>
/// <param name="isInherited">true if this rule is inherited from a parent container.</param>
/// <param name="inheritanceFlags">Specifies the inheritance properties of the audit rule.</param>
/// <param name="propagationFlags">
/// Specifies whether inherited audit rules are automatically propagated. The propagation flags are ignored if
/// <paramref name="inheritanceFlags"/> is set to <see cref="F:System.Security.AccessControl.InheritanceFlags.None"/>.
/// </param>
/// <param name="flags">Specifies the conditions for which the rule is audited.</param>
/// <returns>The <see cref="T:System.Security.AccessControl.AuditRule"/> object that this method creates.</returns>
public override AuditRule AuditRuleFactory(IdentityReference identityReference, int accessMask, bool isInherited, InheritanceFlags inheritanceFlags,
PropagationFlags propagationFlags, AuditFlags flags) =>
new AuditRule<T>(identityReference, accessMask, isInherited, inheritanceFlags, propagationFlags, flags);
/// <summary>
/// Removes access rules that contain the same security identifier and access mask as the specified access rule from the
/// Discretionary Access Control List (DACL) associated with this <see cref="ObjectSecurity{T}"/> object.
/// </summary>
/// <param name="rule">The rule to remove.</param>
/// <returns><see langword="true"/> if the access rule was successfully removed; otherwise, <see langword="false"/>.</returns>
public virtual bool RemoveAccessRule(AccessRule<T> rule) => base.RemoveAccessRule(rule);
/// <summary>
/// Removes all access rules that have the same security identifier as the specified access rule from the Discretionary Access
/// Control List (DACL) associated with this <see cref="ObjectSecurity{T}"/> object.
/// </summary>
/// <param name="rule">The access rule to remove.</param>
public virtual void RemoveAccessRuleAll(AccessRule<T> rule) => base.RemoveAccessRuleAll(rule);
/// <summary>
/// Removes all access rules that exactly match the specified access rule from the Discretionary Access Control List (DACL)
/// associated with this <see cref="ObjectSecurity{T}"/> object
/// </summary>
/// <param name="rule">The access rule to remove.</param>
public virtual void RemoveAccessRuleSpecific(AccessRule<T> rule) => base.RemoveAccessRuleSpecific(rule);
/// <summary>
/// Removes audit rules that contain the same security identifier and access mask as the specified audit rule from the System Access
/// Control List (SACL) associated with this <see cref="ObjectSecurity{T}"/> object.
/// </summary>
/// <param name="rule">The audit rule to remove.</param>
/// <returns><see langword="true"/> if the object was removed; otherwise, <see langword="false"/>.</returns>
public virtual bool RemoveAuditRule(AuditRule<T> rule) => base.RemoveAuditRule(rule);
/// <summary>
/// Removes all audit rules that have the same security identifier as the specified audit rule from the System Access Control List
/// (SACL) associated with this <see cref="ObjectSecurity{T}"/> object.
/// </summary>
/// <param name="rule">The audit rule to remove.</param>
public virtual void RemoveAuditRuleAll(AuditRule<T> rule) => base.RemoveAuditRuleAll(rule);
/// <summary>
/// Removes all audit rules that exactly match the specified audit rule from the System Access Control List (SACL) associated with
/// this <see cref="ObjectSecurity{T}"/> object.
/// </summary>
/// <param name="rule">The audit rule to remove.</param>
public virtual void RemoveAuditRuleSpecific(AuditRule<T> rule) => base.RemoveAuditRuleSpecific(rule);
/// <summary>
/// Removes all access rules in the Discretionary Access Control List (DACL) associated with this <see cref="ObjectSecurity{T}"/>
/// object and then adds the specified access rule.
/// </summary>
/// <param name="rule">The access rule to reset.</param>
public virtual void ResetAccessRule(AccessRule<T> rule) => base.ResetAccessRule(rule);
/// <summary>
/// Removes all access rules that contain the same security identifier and qualifier as the specified access rule in the
/// Discretionary Access Control List (DACL) associated with this <see cref="ObjectSecurity{T}"/> object and then adds the specified
/// access rule.
/// </summary>
/// <param name="rule">The access rule to set.</param>
public virtual void SetAccessRule(AccessRule<T> rule) => base.SetAccessRule(rule);
/// <summary>
/// Removes all audit rules that contain the same security identifier and qualifier as the specified audit rule in the System Access
/// Control List (SACL) associated with this <see cref="ObjectSecurity{T}"/> object and then adds the specified audit rule.
/// </summary>
/// <param name="rule">The audit rule to set.</param>
public virtual void SetAuditRule(AuditRule<T> rule) => base.SetAuditRule(rule);
// Use this in your own Persist after you have demanded any appropriate CAS permissions. Note that you will want your version to be
// internal and use a specialized Safe Handle.
/// <summary>
/// Saves the security descriptor associated with this <see cref="ObjectSecurity{T}"/> object to permanent storage, using the
/// specified handle.
/// </summary>
/// <param name="handle">The handle of the securable object with which this <see cref="ObjectSecurity{T}"/> object is associated.</param>
protected internal void Persist(SafeHandle handle)
{
WriteLock();
try
{
var persistRules = GetAccessControlSectionsFromChanges();
Persist(handle, persistRules);
OwnerModified = GroupModified = AuditRulesModified = AccessRulesModified = false;
}
finally
{
WriteUnlock();
}
}
// Use this in your own Persist after you have demanded any appropriate CAS permissions. Note that you will want your version to be internal.
/// <summary>
/// Saves the security descriptor associated with this <see cref="ObjectSecurity{T}"/> object to permanent storage, using the
/// specified name.
/// </summary>
/// <param name="name">The name of the securable object with which this <see cref="ObjectSecurity{T}"/> object is associated.</param>
protected internal void Persist(string name)
{
WriteLock();
try
{
var persistRules = GetAccessControlSectionsFromChanges();
Persist(name, persistRules);
OwnerModified = GroupModified = AuditRulesModified = AccessRulesModified = false;
}
finally
{
WriteUnlock();
}
}
private AccessControlSections GetAccessControlSectionsFromChanges()
{
var persistRules = AccessControlSections.None;
if (AccessRulesModified)
{
persistRules = AccessControlSections.Access;
}
if (AuditRulesModified)
{
persistRules |= AccessControlSections.Audit;
}
if (OwnerModified)
{
persistRules |= AccessControlSections.Owner;
}
if (GroupModified)
{
persistRules |= AccessControlSections.Group;
}
return persistRules;
}
}
}
#endif

View File

@ -1,193 +0,0 @@
#if NET20 || NET35
using Microsoft.Win32.SafeHandles;
using System.Linq;
using System.Runtime.ConstrainedExecution;
using Vanara.Extensions;
namespace System.Runtime.InteropServices
{
/// <summary>
/// Provides a controlled memory buffer that can be used for reading and writing. Attempts to access memory outside the controlled buffer
/// (under-runs and overruns) raise exceptions.
/// </summary>
/// <seealso cref="Microsoft.Win32.SafeHandles.SafeHandleZeroOrMinusOneIsInvalid"/>
[Security.SecurityCritical]
public abstract unsafe class SafeBuffer : SafeHandleZeroOrMinusOneIsInvalid
{
private static readonly UIntPtr Uninitialized = UIntPtr.Size == 4 ? (UIntPtr)uint.MaxValue : (UIntPtr)ulong.MaxValue;
private UIntPtr numBytes;
/// <inheritdoc/>
/// <summary>
/// Creates a new instance of the <see cref="T:System.Runtime.InteropServices.SafeBuffer"/> class, and specifies whether the buffer
/// handle is to be reliably released.
/// </summary>
/// <param name="ownsHandle">
/// <see langword="true"/> to reliably release the handle during the finalization phase; <see langword="false"/> to prevent reliable
/// release (not recommended).
/// </param>
protected SafeBuffer(bool ownsHandle) : base(ownsHandle) => numBytes = Uninitialized;
/// <summary>Gets the size of the buffer, in bytes.</summary>
public ulong ByteLength
{
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
get => numBytes != Uninitialized ? (ulong)numBytes : throw NotInitialized();
}
/// <summary>Obtains a pointer from a <see cref="SafeBuffer"/> object for a block of memory.</summary>
/// <param name="pointer">
/// A byte pointer, passed by reference, to receive the pointer from within the <see cref="SafeBuffer"/> object. You must set this
/// pointer to <see langword="null"/> before you call this method.
/// </param>
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
public void AcquirePointer(ref byte* pointer)
{
if (numBytes == Uninitialized)
throw NotInitialized();
pointer = null;
var junk = false;
DangerousAddRef(ref junk);
pointer = (byte*)handle;
}
/// <summary>
/// Defines the allocation size of the memory region in bytes. You must call this method before you use the SafeBuffer instance.
/// </summary>
/// <param name="numBytes">The number of bytes in the buffer.</param>
public void Initialize(ulong numBytes)
{
if (IntPtr.Size == 4 && numBytes > uint.MaxValue)
throw new ArgumentOutOfRangeException(nameof(numBytes), ResourceHelper.GetString("ArgumentOutOfRange_AddressSpace"));
if (numBytes >= (ulong)Uninitialized)
throw new ArgumentOutOfRangeException(nameof(numBytes), ResourceHelper.GetString("ArgumentOutOfRange_UIntPtrMax-1"));
this.numBytes = (UIntPtr)numBytes;
}
/// <summary>
/// Specifies the allocation size of the memory buffer by using the specified number of elements and element size. You must call this
/// method before you use the SafeBuffer instance.
/// </summary>
/// <param name="numElements">The number of elements in the buffer.</param>
/// <param name="sizeOfEachElement">The size of each element in the buffer.</param>
public void Initialize(uint numElements, uint sizeOfEachElement) => Initialize((ulong)numElements * sizeOfEachElement);
/// <summary>
/// Defines the allocation size of the memory region by specifying the number of value types. You must call this method before you
/// use the SafeBuffer instance.
/// </summary>
/// <typeparam name="T">The value type to allocate memory for.</typeparam>
/// <param name="numElements">The number of elements of the value type to allocate memory for.</param>
public void Initialize<T>(uint numElements) where T : struct => Initialize(numElements, AlignedSizeOf<T>());
/// <summary>Reads a value type from memory at the specified offset.</summary>
/// <typeparam name="T">The value type to read.</typeparam>
/// <param name="byteOffset">The location from which to read the value type. You may have to consider alignment issues.</param>
/// <returns>The value type that was read from memory.</returns>
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
public T Read<T>(ulong byteOffset) where T : struct => handle.ToStructure<T>(numBytes.ToUInt64(), (int)byteOffset);
/// <summary>
/// Reads the specified number of value types from memory starting at the offset, and writes them into an array starting at the index.
/// </summary>
/// <typeparam name="T">The value type to read.</typeparam>
/// <param name="byteOffset">The location from which to start reading.</param>
/// <param name="array">The output array to write to.</param>
/// <param name="index">The location in the output array to begin writing to.</param>
/// <param name="count">The number of value types to read from the input array and to write to the output array.</param>
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
public void ReadArray<T>(ulong byteOffset, T[] array, int index, int count) where T : struct
{
if (array == null)
throw new ArgumentNullException(nameof(array), ResourceHelper.GetString("ArgumentNull_Buffer"));
if (index < 0)
throw new ArgumentOutOfRangeException(nameof(index), ResourceHelper.GetString("ArgumentOutOfRange_NeedNonNegNum"));
if (count < 0)
throw new ArgumentOutOfRangeException(nameof(count), ResourceHelper.GetString("ArgumentOutOfRange_NeedNonNegNum"));
if (array.Length - index < count)
throw new ArgumentException(ResourceHelper.GetString("Argument_InvalidOffLen"));
if (numBytes == Uninitialized)
throw NotInitialized();
Array.Copy(handle.ToArray<T>(count, (int)byteOffset, numBytes.ToUInt64()), 0, array, index, count);
}
/// <summary>Releases a pointer that was obtained by the <see cref="AcquirePointer(ref byte*)"/> method.</summary>
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
public void ReleasePointer()
{
if (numBytes == Uninitialized)
throw NotInitialized();
DangerousRelease();
}
/// <summary>Writes a value type to memory at the given location.</summary>
/// <typeparam name="T">The value type to write.</typeparam>
/// <param name="byteOffset">The location at which to start writing. You may have to consider alignment issues.</param>
/// <param name="value">The value to write.</param>
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
public void Write<T>(ulong byteOffset, T value) where T : struct
{
if (numBytes == Uninitialized)
throw NotInitialized();
handle.Write(value, (int)byteOffset, numBytes.ToUInt64());
}
/// <summary>
/// Writes the specified number of value types to a memory location by reading bytes starting from the specified location in the
/// input array.
/// </summary>
/// <typeparam name="T">The value type to write.</typeparam>
/// <param name="byteOffset">The location in memory to write to.</param>
/// <param name="array">The input array.</param>
/// <param name="index">The offset in the array to start reading from.</param>
/// <param name="count">The number of value types to write.</param>
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
public void WriteArray<T>(ulong byteOffset, T[] array, int index, int count) where T : struct
{
if (array == null)
throw new ArgumentNullException(nameof(array), ResourceHelper.GetString("ArgumentNull_Buffer"));
if (index < 0)
throw new ArgumentOutOfRangeException(nameof(index), ResourceHelper.GetString("ArgumentOutOfRange_NeedNonNegNum"));
if (count < 0)
throw new ArgumentOutOfRangeException(nameof(count), ResourceHelper.GetString("ArgumentOutOfRange_NeedNonNegNum"));
if (array.Length - index < count)
throw new ArgumentException(ResourceHelper.GetString("Argument_InvalidOffLen"));
if (numBytes == Uninitialized)
throw NotInitialized();
handle.Write(array, (int)byteOffset, numBytes.ToUInt64());
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
private static void NotEnoughRoom() => throw new ArgumentException(ResourceHelper.GetString("Arg_BufferTooSmall"));
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
private static InvalidOperationException NotInitialized() => new InvalidOperationException(ResourceHelper.GetString("InvalidOperation_MustCallInitialize"));
internal static uint AlignedSizeOf<T>()
{
var size = SizeOf<T>();
return (size == 1 || size == 2) ? size : (uint)((size + 3) & (~3));
}
internal static uint SizeOf<T>() => (uint)Marshal.SizeOf(typeof(T));
}
internal static class ResourceHelper
{
public static string GetString(string value, params object[] vars) => string.Format(Vanara.Properties.Resources.ResourceManager.GetString(value) ?? throw new InvalidOperationException(), vars);
}
}
#endif

View File

@ -1,794 +0,0 @@
#if NET20 || NET35
using System.Diagnostics.Contracts;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
namespace System.IO
{
/// <inheritdoc />
/// <summary>Provides random access to unmanaged blocks of memory from managed code.</summary>
/// <seealso cref="T:System.IDisposable" />
public class UnmanagedMemoryAccessor : IDisposable
{
private FileAccess access;
[SecurityCritical]
private SafeBuffer buffer;
private bool canRead;
private bool canWrite;
private long offset;
/// <summary>
/// Initializes a new instance of the <see cref="UnmanagedMemoryAccessor"/> class with a specified buffer, offset, and capacity.
/// </summary>
/// <param name="buffer">The buffer to contain the accessor.</param>
/// <param name="offset">The byte at which to start the accessor.</param>
/// <param name="capacity">The size, in bytes, of memory to allocate.</param>
[SecuritySafeCritical]
public UnmanagedMemoryAccessor(SafeBuffer buffer, long offset, long capacity) => Initialize(buffer, offset, capacity, FileAccess.Read);
/// <summary>
/// Initializes a new instance of the <see cref="UnmanagedMemoryAccessor"/> class with a specified buffer, offset, capacity, and
/// access right.
/// </summary>
/// <param name="buffer">The buffer to contain the accessor.</param>
/// <param name="offset">The byte at which to start the accessor.</param>
/// <param name="capacity">The size, in bytes, of memory to allocate.</param>
/// <param name="access">The type of access allowed to the memory. The default is ReadWrite.</param>
[SecuritySafeCritical]
public UnmanagedMemoryAccessor(SafeBuffer buffer, long offset, long capacity, FileAccess access) => Initialize(buffer, offset, capacity, access);
/// <summary>Initializes a new instance of the <see cref="UnmanagedMemoryAccessor"/> class.</summary>
protected UnmanagedMemoryAccessor() => IsOpen = false;
private unsafe delegate T AlignedPtrReadFunc<out T>(byte* ptr) where T : unmanaged;
private unsafe delegate void AlignedPtrWriteFunc(byte* ptr);
/// <summary>Determines whether the accessor is readable.</summary>
/// <value><see langword="true"/> if the accessor is readable; otherwise, <see langword="false"/>.</value>
public bool CanRead => IsOpen && canRead;
/// <summary>Determines whether the accessory is writable.</summary>
/// <value><see langword="true"/> if the accessor is writable; otherwise, <see langword="false"/>.</value>
public bool CanWrite => IsOpen && canWrite;
/// <summary>Gets the capacity of the accessor.</summary>
/// <value>The capacity of the accessor.</value>
[field: ContractPublicPropertyName("Capacity")]
public long Capacity { get; private set; }
/// <summary>Determines whether the accessor is currently open by a process.</summary>
/// <value><see langword="true"/> if the accessor is open; otherwise, <see langword="false"/>.</value>
protected bool IsOpen { get; private set; }
/// <summary>Releases all resources used by the UnmanagedMemoryAccessor.</summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>Reads a structure of type <typeparamref name="T"/> from the accessor into a provided reference.</summary>
/// <typeparam name="T">The type of structure.</typeparam>
/// <param name="position">The position in the accessor at which to begin reading.</param>
/// <param name="structure">The structure to contain the read data.</param>
[SecurityCritical]
public void Read<T>(long position, out T structure) where T : struct
{
if (position < 0)
throw new ArgumentOutOfRangeException(nameof(position), ResourceHelper.GetString("ArgumentOutOfRange_NeedNonNegNum"));
Contract.EndContractBlock();
if (!IsOpen)
throw new ObjectDisposedException("UnmanagedMemoryAccessor", ResourceHelper.GetString("ObjectDisposed_ViewAccessorClosed"));
if (!CanRead)
throw new NotSupportedException(ResourceHelper.GetString("NotSupported_Reading"));
var sizeOfT = (uint)Marshal.SizeOf(typeof(T));
if (position > Capacity - sizeOfT)
{
if (position >= Capacity)
throw new ArgumentOutOfRangeException(nameof(position), ResourceHelper.GetString("ArgumentOutOfRange_PositionLessThanCapacityRequired"));
throw new ArgumentException(ResourceHelper.GetString("Argument_NotEnoughBytesToRead", typeof(T).FullName), nameof(position));
}
structure = buffer.Read<T>((ulong)(offset + position));
}
/// <summary>Reads structures of type <typeparamref name="T"/> from the accessor into an array of type <typeparamref name="T"/>.</summary>
/// <typeparam name="T">The type of structure.</typeparam>
/// <param name="position">The number of bytes in the accessor at which to begin reading.</param>
/// <param name="array">The array to contain the structures read from the accessor.</param>
/// <param name="offset">The index in <paramref name="array"/> in which to place the first copied structure.</param>
/// <param name="count">The number of structures of type <typeparamref name="T"/> to read from the accessor.</param>
/// <returns>
/// The number of structures read into <paramref name="array"/>. This value can be less than <paramref name="count"/> if there are
/// fewer structures available, or zero if the end of the accessor is reached.
/// </returns>
[SecurityCritical]
public int ReadArray<T>(long position, T[] array, int offset, int count) where T : struct
{
if (array == null)
throw new ArgumentNullException(nameof(array), ResourceHelper.GetString("ArgumentNull_Buffer"));
if (offset < 0)
throw new ArgumentOutOfRangeException(nameof(offset), ResourceHelper.GetString("ArgumentOutOfRange_NeedNonNegNum"));
if (count < 0)
throw new ArgumentOutOfRangeException(nameof(count), ResourceHelper.GetString("ArgumentOutOfRange_NeedNonNegNum"));
if (array.Length - offset < count)
throw new ArgumentException(ResourceHelper.GetString("Argument_OffsetAndLengthOutOfBounds"));
Contract.EndContractBlock();
if (!CanRead)
{
if (!IsOpen)
throw new ObjectDisposedException("UnmanagedMemoryAccessor", ResourceHelper.GetString("ObjectDisposed_ViewAccessorClosed"));
throw new NotSupportedException(ResourceHelper.GetString("NotSupported_Reading"));
}
if (position < 0)
throw new ArgumentOutOfRangeException(nameof(position), ResourceHelper.GetString("ArgumentOutOfRange_NeedNonNegNum"));
var sizeOfT = (uint)Marshal.SizeOf(typeof(T));
// only check position and ask for fewer Ts if count is too big
if (position >= Capacity)
throw new ArgumentOutOfRangeException(nameof(position), ResourceHelper.GetString("ArgumentOutOfRange_PositionLessThanCapacityRequired"));
var n = count;
var spaceLeft = Capacity - position;
if (spaceLeft < 0)
{
n = 0;
}
else
{
var spaceNeeded = (ulong)(sizeOfT * count);
if ((ulong)spaceLeft < spaceNeeded)
{
n = (int)(spaceLeft / sizeOfT);
}
}
buffer.ReadArray((ulong)(this.offset + position), array, offset, n);
return n;
}
/// <summary>Reads a Boolean value from the accessor.</summary>
/// <param name="position">The number of bytes into the accessor at which to begin reading.</param>
/// <returns><see langword="true"/> or <see langword="false"/>.</returns>
public bool ReadBoolean(long position) => ReadByte(position) != 0;
/// <summary>Reads a byte value from the accessor.</summary>
/// <param name="position">The number of bytes into the accessor at which to begin reading.</param>
/// <returns>The value that was read.</returns>
public byte ReadByte(long position)
{
const int sizeOfType = sizeof(byte);
EnsureSafeToRead(position, sizeOfType);
return InternalReadByte(position);
}
/// <summary>Reads a character from the accessor.</summary>
/// <param name="position">The number of bytes into the accessor at which to begin reading.</param>
/// <returns>The value that was read.</returns>
[SecuritySafeCritical]
public char ReadChar(long position) { unsafe { return InternalRead(position, pointer => (char)(*pointer | *(pointer + 1) << 8)); } }
/// <summary>Reads a decimal value from the accessor.</summary>
/// <param name="position">The number of bytes into the accessor at which to begin reading.</param>
/// <returns>The value that was read.</returns>
[SecuritySafeCritical]
public decimal ReadDecimal(long position)
{
const int sizeOfType = sizeof(decimal);
EnsureSafeToRead(position, sizeOfType);
var decimalArray = new int[4];
ReadArray(position, decimalArray, 0, decimalArray.Length);
return new decimal(decimalArray);
}
/// <summary>Reads a double-precision floating-point value from the accessor.</summary>
/// <param name="position">The number of bytes into the accessor at which to begin reading.</param>
/// <returns>The value that was read.</returns>
[SecuritySafeCritical]
public double ReadDouble(long position)
{
unsafe
{
return InternalRead(position, pointer =>
{
var lo = (uint) (*pointer | *(pointer + 1) << 8 | *(pointer + 2) << 16 | *(pointer + 3) << 24);
var hi = (uint) (*(pointer + 4) | *(pointer + 5) << 8 | *(pointer + 6) << 16 | *(pointer + 7) << 24);
var tempResult = (ulong)hi << 32 | lo;
return *(double*) &tempResult;
});
}
}
/// <summary>Reads a 16-bit integer from the accessor.</summary>
/// <param name="position">The number of bytes into the accessor at which to begin reading.</param>
/// <returns>The value that was read.</returns>
[SecuritySafeCritical]
public short ReadInt16(long position) { unsafe { return InternalRead(position, pointer => (short)(*pointer | *(pointer + 1) << 8)); } }
/// <summary>Reads a 32-bit integer from the accessor.</summary>
/// <param name="position">The number of bytes into the accessor at which to begin reading.</param>
/// <returns>The value that was read.</returns>
[SecuritySafeCritical]
public int ReadInt32(long position) { unsafe { return InternalRead(position, pointer => *pointer | *(pointer + 1) << 8 | *(pointer + 2) << 16 | *(pointer + 3) << 24); } }
/// <summary>Reads a 64-bit integer from the accessor.</summary>
/// <param name="position">The number of bytes into the accessor at which to begin reading.</param>
/// <returns>The value that was read.</returns>
[SecuritySafeCritical]
public long ReadInt64(long position)
{
unsafe
{
return InternalRead(position, pointer =>
{
var lo = *pointer | *(pointer + 1) << 8 | *(pointer + 2) << 16 | *(pointer + 3) << 24;
var hi = *(pointer + 4) | *(pointer + 5) << 8 | *(pointer + 6) << 16 | *(pointer + 7) << 24;
return ((long)hi << 32) | (uint)lo;
});
}
}
/// <summary>Reads an 8-bit integer from the accessor.</summary>
/// <param name="position">The number of bytes into the accessor at which to begin reading.</param>
/// <returns>The value that was read.</returns>
[SecuritySafeCritical]
public sbyte ReadSByte(long position) => unchecked((sbyte)ReadByte(position));
/// <summary>Reads a single-precision floating-point value from the accessor.</summary>
/// <param name="position">The number of bytes into the accessor at which to begin reading.</param>
/// <returns>The value that was read.</returns>
[SecuritySafeCritical]
public float ReadSingle(long position)
{
unsafe
{
return InternalRead(position, pointer =>
{
var tempResult = (uint)(*pointer | *(pointer + 1) << 8 | *(pointer + 2) << 16 | *(pointer + 3) << 24);
return *(float*)&tempResult;
});
}
}
/// <summary>Reads an unsigned 16-bit integer from the accessor.</summary>
/// <param name="position">The number of bytes into the accessor at which to begin reading.</param>
/// <returns>The value that was read.</returns>
[SecuritySafeCritical]
public ushort ReadUInt16(long position) { unsafe { return InternalRead(position, pointer => (ushort)(*pointer | *(pointer + 1) << 8)); } }
/// <summary>Reads an unsigned 32-bit integer from the accessor.</summary>
/// <param name="position">The number of bytes into the accessor at which to begin reading.</param>
/// <returns>The value that was read.</returns>
[SecuritySafeCritical]
public uint ReadUInt32(long position) { unsafe { return InternalRead(position, pointer => (uint)(*pointer | *(pointer + 1) << 8 | *(pointer + 2) << 16 | *(pointer + 3) << 24)); } }
/// <summary>Reads an unsigned 64-bit integer from the accessor.</summary>
/// <param name="position">The number of bytes into the accessor at which to begin reading.</param>
/// <returns>The value that was read.</returns>
[SecuritySafeCritical]
public ulong ReadUInt64(long position)
{
unsafe
{
return InternalRead(position, pointer =>
{
var lo = (uint)(*pointer | *(pointer + 1) << 8 | *(pointer + 2) << 16 | *(pointer + 3) << 24);
var hi = (uint)(*(pointer + 4) | *(pointer + 5) << 8 | *(pointer + 6) << 16 | *(pointer + 7) << 24);
return ((ulong)hi << 32) | lo;
});
}
}
/// <summary>Writes a Boolean value into the accessor.</summary>
/// <param name="position">The number of bytes into the accessor at which to begin writing.</param>
/// <param name="value">The value to write.</param>
public void Write(long position, bool value) => Write(position, (byte)(value ? 1 : 0));
/// <summary>Writes a byte value into the accessor.</summary>
/// <param name="position">The number of bytes into the accessor at which to begin writing.</param>
/// <param name="value">The value to write.</param>
public void Write(long position, byte value)
{
const int sizeOfType = sizeof(byte);
EnsureSafeToWrite(position, sizeOfType);
InternalWriteByte(position, value);
}
/// <summary>Writes a character into the accessor.</summary>
/// <param name="position">The number of bytes into the accessor at which to begin writing.</param>
/// <param name="value">The value to write.</param>
[SecuritySafeCritical]
public void Write(long position, char value)
{
unsafe
{
InternalWrite(position, value, pointer =>
{
*pointer = (byte)value;
*(pointer + 1) = (byte)(value >> 8);
});
}
}
/// <summary>Writes a 16-bit integer into the accessor.</summary>
/// <param name="position">The number of bytes into the accessor at which to begin writing.</param>
/// <param name="value">The value to write.</param>
[SecuritySafeCritical]
public void Write(long position, short value)
{
unsafe
{
InternalWrite(position, value, pointer =>
{
*pointer = (byte)value;
*(pointer + 1) = (byte)(value >> 8);
});
}
}
/// <summary>Writes a 32-bit integer into the accessor.</summary>
/// <param name="position">The number of bytes into the accessor at which to begin writing.</param>
/// <param name="value">The value to write.</param>
[SecuritySafeCritical]
public void Write(long position, int value)
{
unsafe
{
InternalWrite(position, value, pointer =>
{
*pointer = (byte)value;
*(pointer + 1) = (byte)(value >> 8);
*(pointer + 2) = (byte)(value >> 16);
*(pointer + 3) = (byte)(value >> 24);
});
}
}
/// <summary>Writes a 64-bit integer into the accessor.</summary>
/// <param name="position">The number of bytes into the accessor at which to begin writing.</param>
/// <param name="value">The value to write.</param>
[SecuritySafeCritical]
public void Write(long position, long value)
{
unsafe
{
InternalWrite(position, value, pointer =>
{
*pointer = (byte)value;
*(pointer + 1) = (byte)(value >> 8);
*(pointer + 2) = (byte)(value >> 16);
*(pointer + 3) = (byte)(value >> 24);
*(pointer + 4) = (byte)(value >> 32);
*(pointer + 5) = (byte)(value >> 40);
*(pointer + 6) = (byte)(value >> 48);
*(pointer + 7) = (byte)(value >> 56);
});
}
}
/// <summary>Writes a decimal value into the accessor.</summary>
/// <param name="position">The number of bytes into the accessor at which to begin writing.</param>
/// <param name="value">The value to write.</param>
[SecuritySafeCritical]
public void Write(long position, decimal value)
{
const int sizeOfType = sizeof(decimal);
EnsureSafeToWrite(position, sizeOfType);
var decimalArray = new byte[16];
GetDecimalBytes(value, decimalArray);
var bits = new int[4];
var flags = decimalArray[12] | (decimalArray[13] << 8) | (decimalArray[14] << 16) | (decimalArray[15] << 24);
var lo = decimalArray[0] | (decimalArray[1] << 8) | (decimalArray[2] << 16) | (decimalArray[3] << 24);
var mid = decimalArray[4] | (decimalArray[5] << 8) | (decimalArray[6] << 16) | (decimalArray[7] << 24);
var hi = decimalArray[8] | (decimalArray[9] << 8) | (decimalArray[10] << 16) | (decimalArray[11] << 24);
bits[0] = lo;
bits[1] = mid;
bits[2] = hi;
bits[3] = flags;
WriteArray(position, bits, 0, bits.Length);
}
/// <summary>Writes a Single into the accessor.</summary>
/// <param name="position">The number of bytes into the accessor at which to begin writing.</param>
/// <param name="value">The value to write.</param>
[SecuritySafeCritical]
public void Write(long position, float value)
{
unsafe
{
InternalWrite(position, value, pointer =>
{
var lValue = value;
var tmpValue = *(uint*)&lValue;
*pointer = (byte)tmpValue;
*(pointer + 1) = (byte)(tmpValue >> 8);
*(pointer + 2) = (byte)(tmpValue >> 16);
*(pointer + 3) = (byte)(tmpValue >> 24);
});
}
}
/// <summary>Writes a Double into the accessor.</summary>
/// <param name="position">The number of bytes into the accessor at which to begin writing.</param>
/// <param name="value">The value to write.</param>
[SecuritySafeCritical]
public void Write(long position, double value)
{
unsafe
{
InternalWrite(position, value, pointer =>
{
var lValue = value;
var tmpValue = *(ulong*)&lValue;
*pointer = (byte)tmpValue;
*(pointer + 1) = (byte)(tmpValue >> 8);
*(pointer + 2) = (byte)(tmpValue >> 16);
*(pointer + 3) = (byte)(tmpValue >> 24);
*(pointer + 4) = (byte)(tmpValue >> 32);
*(pointer + 5) = (byte)(tmpValue >> 40);
*(pointer + 6) = (byte)(tmpValue >> 48);
*(pointer + 7) = (byte)(tmpValue >> 56);
});
}
}
/// <summary>Writes an unsigned 8-bit integer into the accessor.</summary>
/// <param name="position">The number of bytes into the accessor at which to begin writing.</param>
/// <param name="value">The value to write.</param>
[SecuritySafeCritical]
public void Write(long position, sbyte value) => Write(position, unchecked((byte)value));
/// <summary>Writes an unsigned 16-bit integer into the accessor.</summary>
/// <param name="position">The number of bytes into the accessor at which to begin writing.</param>
/// <param name="value">The value to write.</param>
[SecuritySafeCritical]
public void Write(long position, ushort value)
{
unsafe
{
InternalWrite(position, value, pointer =>
{
*pointer = (byte)value;
*(pointer + 1) = (byte)(value >> 8);
});
}
}
/// <summary>Writes an unsigned 32-bit integer into the accessor.</summary>
/// <param name="position">The number of bytes into the accessor at which to begin writing.</param>
/// <param name="value">The value to write.</param>
[SecuritySafeCritical]
public void Write(long position, uint value)
{
unsafe
{
InternalWrite(position, value, pointer =>
{
*pointer = (byte)value;
*(pointer + 1) = (byte)(value >> 8);
*(pointer + 2) = (byte)(value >> 16);
*(pointer + 3) = (byte)(value >> 24);
});
}
}
/// <summary>Writes an unsigned 64-bit integer into the accessor.</summary>
/// <param name="position">The number of bytes into the accessor at which to begin writing.</param>
/// <param name="value">The value to write.</param>
[SecuritySafeCritical]
public void Write(long position, ulong value)
{
unsafe
{
InternalWrite(position, value, pointer =>
{
*pointer = (byte)value;
*(pointer + 1) = (byte)(value >> 8);
*(pointer + 2) = (byte)(value >> 16);
*(pointer + 3) = (byte)(value >> 24);
*(pointer + 4) = (byte)(value >> 32);
*(pointer + 5) = (byte)(value >> 40);
*(pointer + 6) = (byte)(value >> 48);
*(pointer + 7) = (byte)(value >> 56);
});
}
}
/// <summary>Writes a structure into the accessor.</summary>
/// <param name="position">The number of bytes into the accessor at which to begin writing.</param>
/// <param name="structure">The structure to write.</param>
[SecurityCritical]
public void Write<T>(long position, ref T structure) where T : struct
{
if (position < 0)
throw new ArgumentOutOfRangeException(nameof(position), ResourceHelper.GetString("ArgumentOutOfRange_NeedNonNegNum"));
Contract.EndContractBlock();
if (!IsOpen)
throw new ObjectDisposedException("UnmanagedMemoryAccessor", ResourceHelper.GetString("ObjectDisposed_ViewAccessorClosed"));
if (!CanWrite)
throw new NotSupportedException(ResourceHelper.GetString("NotSupported_Writing"));
var sizeOfT = (uint)Marshal.SizeOf(typeof(T));
if (position > Capacity - sizeOfT)
{
if (position >= Capacity)
throw new ArgumentOutOfRangeException(nameof(position), ResourceHelper.GetString("ArgumentOutOfRange_PositionLessThanCapacityRequired"));
throw new ArgumentException(ResourceHelper.GetString("Argument_NotEnoughBytesToWrite", typeof(T).FullName), nameof(position));
}
buffer.Write((ulong)(offset + position), structure);
}
/// <summary>Writes structures from an array of type <typeparamref name="T"/> into the accessor.</summary>
/// <typeparam name="T">The type of structure.</typeparam>
/// <param name="position">The number of bytes into the accessor at which to begin writing.</param>
/// <param name="array">The array to write into the accessor.</param>
/// <param name="offset">The index in <paramref name="array"/> to start writing from.</param>
/// <param name="count">The number of structures in <paramref name="array"/> to write.</param>
[SecurityCritical]
public void WriteArray<T>(long position, T[] array, int offset, int count) where T : struct
{
if (array == null)
throw new ArgumentNullException(nameof(array), ResourceHelper.GetString("ArgumentNull_Buffer"));
if (offset < 0)
throw new ArgumentOutOfRangeException(nameof(offset), ResourceHelper.GetString("ArgumentOutOfRange_NeedNonNegNum"));
if (count < 0)
throw new ArgumentOutOfRangeException(nameof(count), ResourceHelper.GetString("ArgumentOutOfRange_NeedNonNegNum"));
if (array.Length - offset < count)
throw new ArgumentException(ResourceHelper.GetString("Argument_OffsetAndLengthOutOfBounds"));
if (position < 0)
throw new ArgumentOutOfRangeException(nameof(position), ResourceHelper.GetString("ArgumentOutOfRange_NeedNonNegNum"));
if (position >= Capacity)
throw new ArgumentOutOfRangeException(nameof(position), ResourceHelper.GetString("ArgumentOutOfRange_PositionLessThanCapacityRequired"));
Contract.EndContractBlock();
if (!IsOpen)
throw new ObjectDisposedException("UnmanagedMemoryAccessor", ResourceHelper.GetString("ObjectDisposed_ViewAccessorClosed"));
if (!CanWrite)
throw new NotSupportedException(ResourceHelper.GetString("NotSupported_Writing"));
buffer.WriteArray((ulong)(this.offset + position), array, offset, count);
}
internal static void GetDecimalBytes(decimal d, byte[] buffer)
{
Contract.Requires(buffer != null && buffer.Length >= 16, "[GetBytes]buffer != null && buffer.Length >= 16");
Buffer.BlockCopy(decimal.GetBits(d), 0, buffer, 0, buffer.Length);
}
/// <summary>Releases the unmanaged resources used by the UnmanagedMemoryAccessor and optionally releases the managed resources.</summary>
/// <param name="disposing">
/// <see langword="true"/> to release both managed and unmanaged resources; <see langword="false"/> to release only unmanaged resources.
/// </param>
protected virtual void Dispose(bool disposing) => IsOpen = false;
/// <summary>Sets the initial values for the accessor.</summary>
/// <param name="buffer">The buffer to contain the accessor.</param>
/// <param name="offset">The byte at which to start the accessor.</param>
/// <param name="capacity">The size, in bytes, of memory to allocate.</param>
/// <param name="access">The type of access allowed to the memory. The default is ReadWrite.</param>
[SecuritySafeCritical]
[SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
protected void Initialize(SafeBuffer buffer, long offset, long capacity, FileAccess access)
{
if (buffer == null)
throw new ArgumentNullException(nameof(buffer));
if (offset < 0)
throw new ArgumentOutOfRangeException(nameof(offset), ResourceHelper.GetString("ArgumentOutOfRange_NeedNonNegNum"));
if (capacity < 0)
throw new ArgumentOutOfRangeException(nameof(capacity), ResourceHelper.GetString("ArgumentOutOfRange_NeedNonNegNum"));
if (buffer.ByteLength < (ulong)(offset + capacity))
throw new ArgumentException(ResourceHelper.GetString("Argument_OffsetAndCapacityOutOfBounds"));
if (access < FileAccess.Read || access > FileAccess.ReadWrite)
throw new ArgumentOutOfRangeException(nameof(access));
Contract.EndContractBlock();
if (IsOpen)
throw new InvalidOperationException(ResourceHelper.GetString("InvalidOperation_CalledTwice"));
unsafe
{
byte* pointer = null;
RuntimeHelpers.PrepareConstrainedRegions();
try
{
buffer.AcquirePointer(ref pointer);
if ((byte*)((long)pointer + offset + capacity) < pointer)
{
throw new ArgumentException(ResourceHelper.GetString("Argument_UnmanagedMemAccessorWrapAround"));
}
}
finally
{
if (pointer != null)
{
buffer.ReleasePointer();
}
}
}
this.offset = offset;
this.buffer = buffer;
this.Capacity = capacity;
this.access = access;
IsOpen = true;
canRead = (this.access & FileAccess.Read) != 0;
canWrite = (this.access & FileAccess.Write) != 0;
}
private void EnsureSafeToRead(long position, int sizeOfType)
{
if (!IsOpen)
throw new ObjectDisposedException("UnmanagedMemoryAccessor", ResourceHelper.GetString("ObjectDisposed_ViewAccessorClosed"));
if (!CanRead)
throw new NotSupportedException(ResourceHelper.GetString("NotSupported_Reading"));
if (position < 0)
throw new ArgumentOutOfRangeException(nameof(position), ResourceHelper.GetString("ArgumentOutOfRange_NeedNonNegNum"));
Contract.EndContractBlock();
if (position <= Capacity - sizeOfType) return;
if (position >= Capacity)
throw new ArgumentOutOfRangeException(nameof(position), ResourceHelper.GetString("ArgumentOutOfRange_PositionLessThanCapacityRequired"));
throw new ArgumentException(ResourceHelper.GetString("Argument_NotEnoughBytesToRead"), nameof(position));
}
private void EnsureSafeToWrite(long position, int sizeOfType)
{
if (!IsOpen)
throw new ObjectDisposedException("UnmanagedMemoryAccessor", ResourceHelper.GetString("ObjectDisposed_ViewAccessorClosed"));
if (!CanWrite)
throw new NotSupportedException(ResourceHelper.GetString("NotSupported_Writing"));
if (position < 0)
throw new ArgumentOutOfRangeException(nameof(position), ResourceHelper.GetString("ArgumentOutOfRange_NeedNonNegNum"));
Contract.EndContractBlock();
if (position > Capacity - sizeOfType)
{
if (position >= Capacity)
throw new ArgumentOutOfRangeException(nameof(position), ResourceHelper.GetString("ArgumentOutOfRange_PositionLessThanCapacityRequired"));
throw new ArgumentException(ResourceHelper.GetString("Argument_NotEnoughBytesToWrite", "Byte"), nameof(position));
}
}
private unsafe T InternalRead<T>(long position, AlignedPtrReadFunc<T> func) where T : unmanaged, IConvertible
{
var sizeOfType = sizeof(T);
EnsureSafeToRead(position, sizeOfType);
T result;
byte* pointer = null;
RuntimeHelpers.PrepareConstrainedRegions();
try
{
buffer.AcquirePointer(ref pointer);
pointer += offset + position;
#if ALIGN_ACCESS
// check if pointer is aligned
if (((int)pointer & (sizeOfType - 1)) == 0)
{
#endif
result = *(T*)pointer;
#if ALIGN_ACCESS
}
else
{
result = func(pointer);
}
#endif
}
finally
{
if (pointer != null)
{
buffer.ReleasePointer();
}
}
return result;
}
[SecuritySafeCritical]
private byte InternalReadByte(long position)
{
Contract.Assert(CanRead, "UMA not readable");
Contract.Assert(position >= 0, "position less than 0");
Contract.Assert(position <= Capacity - sizeof(byte), "position is greater than capacity - sizeof(byte)");
byte result;
unsafe
{
byte* pointer = null;
RuntimeHelpers.PrepareConstrainedRegions();
try
{
buffer.AcquirePointer(ref pointer);
result = *(pointer + offset + position);
}
finally
{
if (pointer != null)
{
buffer.ReleasePointer();
}
}
}
return result;
}
[SecuritySafeCritical]
private unsafe void InternalWrite<T>(long position, T value, AlignedPtrWriteFunc func) where T : unmanaged, IConvertible
{
var sizeOfType = sizeof(T);
EnsureSafeToWrite(position, sizeOfType);
byte* pointer = null;
RuntimeHelpers.PrepareConstrainedRegions();
try
{
buffer.AcquirePointer(ref pointer);
pointer += offset + position;
#if ALIGN_ACCESS
// check if pointer is aligned
if (((int)pointer & (sizeOfType - 1)) == 0)
{
#endif
*(T*)pointer = value;
#if ALIGN_ACCESS
}
else
{
func(pointer);
}
#endif
}
finally
{
if (pointer != null)
{
buffer.ReleasePointer();
}
}
}
[SecuritySafeCritical]
private void InternalWriteByte(long position, byte value)
{
Contract.Assert(CanWrite, "UMA not writable");
Contract.Assert(position >= 0, "position less than 0");
Contract.Assert(position <= Capacity - sizeof(byte), "position is greater than capacity - sizeof(byte)");
unsafe
{
byte* pointer = null;
RuntimeHelpers.PrepareConstrainedRegions();
try
{
buffer.AcquirePointer(ref pointer);
*(pointer + offset + position) = value;
}
finally
{
if (pointer != null)
{
buffer.ReleasePointer();
}
}
}
}
}
}
#endif

View File

@ -1,804 +0,0 @@
#if NET20 || NET35
using System.Diagnostics.Contracts;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.Threading;
using System.Threading.Tasks;
using Vanara.Extensions;
namespace System.IO
{
/// <summary>Provides access to unmanaged blocks of memory from managed code.</summary>
/// <seealso cref="System.IO.Stream"/>
public class UnmanagedMemoryStream : Stream
{
internal bool _isOpen;
private FileAccess _access;
[SecurityCritical]
private SafeBuffer _buffer;
private long _capacity;
[NonSerialized]
private Task<int> _lastReadTask;
private long _length;
[SecurityCritical]
private unsafe byte* _mem;
private long _offset;
private long _position;
/// <summary>
/// Initializes a new instance of the <see cref="UnmanagedMemoryStream"/> class in a safe buffer with a specified offset and length..
/// </summary>
/// <param name="buffer">The buffer to contain the unmanaged memory stream.</param>
/// <param name="offset">The byte position in the buffer at which to start the unmanaged memory stream.</param>
/// <param name="length">The length of the unmanaged memory stream.</param>
[SecuritySafeCritical]
public UnmanagedMemoryStream(SafeBuffer buffer, long offset, long length) => Initialize(buffer, offset, length, FileAccess.Read, false);
/// <summary>
/// Initializes a new instance of the <see cref="UnmanagedMemoryStream"/> class in a safe buffer with a specified offset, length, and
/// file access.
/// </summary>
/// <param name="buffer">The buffer to contain the unmanaged memory stream.</param>
/// <param name="offset">The byte position in the buffer at which to start the unmanaged memory stream.</param>
/// <param name="length">The length of the unmanaged memory stream.</param>
/// <param name="access">The mode of file access to the unmanaged memory stream.</param>
[SecuritySafeCritical]
public UnmanagedMemoryStream(SafeBuffer buffer, long offset, long length, FileAccess access) => Initialize(buffer, offset, length, access, false);
/// <summary>
/// Initializes a new instance of the <see cref="UnmanagedMemoryStream"/> class using the specified location and memory length.
/// </summary>
/// <param name="pointer">A pointer to an unmanaged memory location.</param>
/// <param name="length">The length of the memory to use.</param>
[SecurityCritical]
public unsafe UnmanagedMemoryStream(byte* pointer, long length) => Initialize(pointer, length, length, FileAccess.Read, false);
/// <summary>
/// Initializes a new instance of the <see cref="UnmanagedMemoryStream"/> class using the specified location, memory length, total
/// amount of memory, and file access values.
/// </summary>
/// <param name="pointer">A pointer to an unmanaged memory location.</param>
/// <param name="length">The length of the memory to use.</param>
/// <param name="capacity">The total amount of memory assigned to the stream.</param>
/// <param name="access">One of the <see cref="FileAccess"/> values.</param>
[SecurityCritical]
public unsafe UnmanagedMemoryStream(byte* pointer, long length, long capacity, FileAccess access) => Initialize(pointer, length, capacity, access, false);
[SecurityCritical]
internal UnmanagedMemoryStream(SafeBuffer buffer, long offset, long length, FileAccess access, bool skipSecurityCheck) => Initialize(buffer, offset, length, access, skipSecurityCheck);
[SecurityCritical]
internal unsafe UnmanagedMemoryStream(byte* pointer, long length, long capacity, FileAccess access, bool skipSecurityCheck) => Initialize(pointer, length, capacity, access, skipSecurityCheck);
/// <summary>Initializes a new instance of the <see cref="UnmanagedMemoryStream"/> class.</summary>
[SecuritySafeCritical]
protected UnmanagedMemoryStream()
{
unsafe
{
_mem = null;
}
_isOpen = false;
}
/// <summary>Gets a value indicating whether a stream supports reading.</summary>
public override bool CanRead
{
[Pure]
get => _isOpen && (_access & FileAccess.Read) != 0;
}
/// <summary>Gets a value indicating whether a stream supports seeking.</summary>
public override bool CanSeek
{
[Pure]
get => _isOpen;
}
/// <summary>Gets a value indicating whether a stream supports writing.</summary>
public override bool CanWrite
{
[Pure]
get => _isOpen && (_access & FileAccess.Write) != 0;
}
/// <summary>Gets the stream length (size) or the total amount of memory assigned to a stream (capacity).</summary>
/// <value>The size or capacity of the stream.</value>
public long Capacity
{
get
{
if (!_isOpen) ErrorStreamIsClosed();
return _capacity;
}
}
/// <summary>Gets the length of the data in a stream.</summary>
/// <value>The length of the data in the stream.</value>
public override long Length
{
get
{
if (!_isOpen) ErrorStreamIsClosed();
return Interlocked.Read(ref _length);
}
}
/// <summary>Gets or sets the position within the current stream.</summary>
public override long Position
{
get
{
if (!CanSeek) ErrorStreamIsClosed();
Contract.EndContractBlock();
return Interlocked.Read(ref _position);
}
[SecuritySafeCritical]
set
{
if (value < 0)
throw new ArgumentOutOfRangeException(nameof(value), ResourceHelper.GetString("ArgumentOutOfRange_NeedNonNegNum"));
Contract.EndContractBlock();
if (!CanSeek) ErrorStreamIsClosed();
unsafe
{
// On 32 bit machines, ensure we don't wrap around.
if (value > int.MaxValue || _mem + value < _mem)
throw new ArgumentOutOfRangeException(nameof(value), ResourceHelper.GetString("ArgumentOutOfRange_StreamLength"));
}
Interlocked.Exchange(ref _position, value);
}
}
/// <summary>Gets or sets a byte pointer to a stream based on the current position in the stream.</summary>
/// <value>A byte pointer.</value>
public unsafe byte* PositionPointer
{
[SecurityCritical] // auto-generated_required
get
{
if (_buffer != null)
throw new NotSupportedException(ResourceHelper.GetString("NotSupported_UmsSafeBuffer"));
// Use a temp to avoid a race
var pos = Interlocked.Read(ref _position);
if (pos > _capacity)
throw new IndexOutOfRangeException(ResourceHelper.GetString("IndexOutOfRange_UMSPosition"));
var ptr = _mem + pos;
if (!_isOpen) ErrorStreamIsClosed();
return ptr;
}
[SecurityCritical] // auto-generated_required
set
{
if (_buffer != null)
throw new NotSupportedException(ResourceHelper.GetString("NotSupported_UmsSafeBuffer"));
if (!_isOpen)
ErrorStreamIsClosed();
if (value < _mem)
throw new IOException(ResourceHelper.GetString("IO.IO_SeekBeforeBegin"));
Interlocked.Exchange(ref _position, value - _mem);
}
}
internal unsafe byte* Pointer
{
[SecurityCritical]
get => _buffer == null ? _mem : throw new NotSupportedException(ResourceHelper.GetString("NotSupported_UmsSafeBuffer"));
}
/// <summary>Clears all buffers for this stream and causes any buffered data to be written to the underlying device.</summary>
public override void Flush()
{
if (!_isOpen) ErrorStreamIsClosed();
}
/// <summary>
/// Asynchronously clears all buffers for this stream, causes any buffered data to be written to the underlying device, and monitors
/// cancellation requests.
/// </summary>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is None.</param>
/// <returns>A task that represents the asynchronous flush operation.</returns>
[HostProtection(ExternalThreading = true)]
[ComVisible(false)]
public virtual Task FlushAsync(CancellationToken cancellationToken)
{
if (cancellationToken.IsCancellationRequested)
return Task.FromCanceled(cancellationToken);
try
{
Flush();
return Task.CompletedTask;
}
catch (Exception ex)
{
return Task.FromException(ex);
}
}
/// <summary>
/// When overridden in a derived class, reads a sequence of bytes from the current stream and advances the position within the stream
/// by the number of bytes read.
/// </summary>
/// <param name="buffer">
/// An array of bytes. When this method returns, the buffer contains the specified byte array with the values between
/// <paramref name="offset"/> and ( <paramref name="offset"/> + <paramref name="count"/> - 1) replaced by the bytes read from the
/// current source.
/// </param>
/// <param name="offset">
/// The zero-based byte offset in <paramref name="buffer"/> at which to begin storing the data read from the current stream.
/// </param>
/// <param name="count">The maximum number of bytes to be read from the current stream.</param>
/// <returns>
/// The total number of bytes read into the buffer. This can be less than the number of bytes requested if that many bytes are not
/// currently available, or zero (0) if the end of the stream has been reached.
/// </returns>
[SecuritySafeCritical]
public override int Read([In, Out] byte[] buffer, int offset, int count)
{
if (buffer == null)
throw new ArgumentNullException(nameof(buffer), ResourceHelper.GetString("ArgumentNull_Buffer"));
if (offset < 0)
throw new ArgumentOutOfRangeException(nameof(offset), ResourceHelper.GetString("ArgumentOutOfRange_NeedNonNegNum"));
if (count < 0)
throw new ArgumentOutOfRangeException(nameof(count), ResourceHelper.GetString("ArgumentOutOfRange_NeedNonNegNum"));
if (buffer.Length - offset < count)
throw new ArgumentException(ResourceHelper.GetString("Argument_InvalidOffLen"));
Contract.EndContractBlock(); // Keep this in sync with contract validation in ReadAsync
if (!_isOpen) ErrorStreamIsClosed();
if (!CanRead) ErrorReadNotSupported();
// Use a local variable to avoid a race where another thread changes our position after we decide we can read some bytes.
var pos = Interlocked.Read(ref _position);
var len = Interlocked.Read(ref _length);
var n = len - pos;
if (n > count)
n = count;
if (n <= 0)
return 0;
var nInt = (int)n; // Safe because n <= count, which is an Int32
if (nInt < 0)
nInt = 0; // _position could be beyond EOF
Contract.Assert(pos + nInt >= 0, "_position + n >= 0"); // len is less than 2^63 -1.
if (_buffer != null)
{
unsafe
{
byte* pointer = null;
RuntimeHelpers.PrepareConstrainedRegions();
try
{
_buffer.AcquirePointer(ref pointer);
BufferMemcpy(buffer, offset, pointer + pos + _offset, 0, nInt);
}
finally
{
if (pointer != null)
{
_buffer.ReleasePointer();
}
}
}
}
else
{
unsafe
{
BufferMemcpy(buffer, offset, _mem + pos, 0, nInt);
}
}
Interlocked.Exchange(ref _position, pos + n);
return nInt;
}
/// <summary>
/// Asynchronously reads a sequence of bytes from the current stream and advances the position within the stream by the number of
/// bytes read.
/// </summary>
/// <param name="buffer">The buffer to write the data into.</param>
/// <param name="offset">The byte offset in buffer at which to begin writing data from the stream.</param>
/// <param name="count">The maximum number of bytes to read.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is None.</param>
/// <returns>
/// A task that represents the asynchronous read operation. The value of the TResult parameter contains the total number of bytes
/// read into the buffer. The result value can be less than the number of bytes requested if the number of bytes currently available
/// is less than the requested number, or it can be 0 (zero) if the end of the stream has been reached.
/// </returns>
[HostProtection(ExternalThreading = true)]
[ComVisible(false)]
public virtual Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
if (buffer == null)
throw new ArgumentNullException(nameof(buffer), ResourceHelper.GetString("ArgumentNull_Buffer"));
if (offset < 0)
throw new ArgumentOutOfRangeException(nameof(offset), ResourceHelper.GetString("ArgumentOutOfRange_NeedNonNegNum"));
if (count < 0)
throw new ArgumentOutOfRangeException(nameof(count), ResourceHelper.GetString("ArgumentOutOfRange_NeedNonNegNum"));
if (buffer.Length - offset < count)
throw new ArgumentException(ResourceHelper.GetString("Argument_InvalidOffLen"));
Contract.EndContractBlock(); // contract validation copied from Read(...)
if (cancellationToken.IsCancellationRequested)
return Task.FromCanceled<int>(cancellationToken);
try
{
var n = Read(buffer, offset, count);
var t = _lastReadTask;
return t != null && t.Result == n ? t : _lastReadTask = Task.FromResult(n);
}
catch (Exception ex)
{
Contract.Assert(!(ex is OperationCanceledException));
return Task.FromException<int>(ex);
}
}
/// <summary>
/// Reads a byte from the stream and advances the position within the stream by one byte, or returns -1 if at the end of the stream.
/// </summary>
/// <returns>The unsigned byte cast to an Int32, or -1 if at the end of the stream.</returns>
[SecuritySafeCritical]
public override int ReadByte()
{
if (!_isOpen) ErrorStreamIsClosed();
if (!CanRead) ErrorReadNotSupported();
var pos = Interlocked.Read(ref _position); // Use a local to avoid a race condition
var len = Interlocked.Read(ref _length);
if (pos >= len)
return -1;
Interlocked.Exchange(ref _position, pos + 1);
int result;
if (_buffer != null)
{
unsafe
{
byte* pointer = null;
RuntimeHelpers.PrepareConstrainedRegions();
try
{
_buffer.AcquirePointer(ref pointer);
result = *(pointer + pos + _offset);
}
finally
{
if (pointer != null)
{
_buffer.ReleasePointer();
}
}
}
}
else
{
unsafe
{
result = _mem[pos];
}
}
return result;
}
/// <summary>When overridden in a derived class, sets the position within the current stream.</summary>
/// <param name="offset">A byte offset relative to the origin parameter.</param>
/// <param name="loc">A value of type SeekOrigin indicating the reference point used to obtain the new position.</param>
/// <returns>The new position within the current stream.</returns>
public override long Seek(long offset, SeekOrigin loc)
{
if (!_isOpen) ErrorStreamIsClosed();
switch (loc)
{
case SeekOrigin.Begin:
if (offset < 0)
throw new IOException(ResourceHelper.GetString("IO.IO_SeekBeforeBegin"));
Interlocked.Exchange(ref _position, offset);
break;
case SeekOrigin.Current:
var pos = Interlocked.Read(ref _position);
if (offset + pos < 0)
throw new IOException(ResourceHelper.GetString("IO.IO_SeekBeforeBegin"));
Interlocked.Exchange(ref _position, offset + pos);
break;
case SeekOrigin.End:
var len = Interlocked.Read(ref _length);
if (len + offset < 0)
throw new IOException(ResourceHelper.GetString("IO.IO_SeekBeforeBegin"));
Interlocked.Exchange(ref _position, len + offset);
break;
default:
throw new ArgumentException(ResourceHelper.GetString("Argument_InvalidSeekOrigin"));
}
var finalPos = Interlocked.Read(ref _position);
Contract.Assert(finalPos >= 0, "_position >= 0");
return finalPos;
}
/// <summary>When overridden in a derived class, sets the length of the current stream.</summary>
/// <param name="value">The desired length of the current stream in bytes.</param>
[SecuritySafeCritical]
public override void SetLength(long value)
{
if (value < 0)
throw new ArgumentOutOfRangeException(nameof(value), ResourceHelper.GetString("ArgumentOutOfRange_NeedNonNegNum"));
Contract.EndContractBlock();
if (_buffer != null)
throw new NotSupportedException(ResourceHelper.GetString("NotSupported_UmsSafeBuffer"));
if (!_isOpen) ErrorStreamIsClosed();
if (!CanWrite) ErrorWriteNotSupported();
if (value > _capacity)
throw new IOException(ResourceHelper.GetString("IO.IO_FixedCapacity"));
var pos = Interlocked.Read(ref _position);
var len = Interlocked.Read(ref _length);
if (value > len)
{
unsafe
{
BufferZeroMemory(_mem + len, value - len);
}
}
Interlocked.Exchange(ref _length, value);
if (pos > value)
{
Interlocked.Exchange(ref _position, value);
}
}
/// <summary>
/// When overridden in a derived class, writes a sequence of bytes to the current stream and advances the current position within
/// this stream by the number of bytes written.
/// </summary>
/// <param name="buffer">
/// An array of bytes. This method copies <paramref name="count"/> bytes from <paramref name="buffer"/> to the current stream.
/// </param>
/// <param name="offset">
/// The zero-based byte offset in <paramref name="buffer"/> at which to begin copying bytes to the current stream.
/// </param>
/// <param name="count">The number of bytes to be written to the current stream.</param>
[SecuritySafeCritical]
public override void Write(byte[] buffer, int offset, int count)
{
if (buffer == null)
throw new ArgumentNullException(nameof(buffer), ResourceHelper.GetString("ArgumentNull_Buffer"));
if (offset < 0)
throw new ArgumentOutOfRangeException(nameof(offset), ResourceHelper.GetString("ArgumentOutOfRange_NeedNonNegNum"));
if (count < 0)
throw new ArgumentOutOfRangeException(nameof(count), ResourceHelper.GetString("ArgumentOutOfRange_NeedNonNegNum"));
if (buffer.Length - offset < count)
throw new ArgumentException(ResourceHelper.GetString("Argument_InvalidOffLen"));
Contract.EndContractBlock(); // Keep contract validation in sync with WriteAsync(..)
if (!_isOpen) ErrorStreamIsClosed();
if (!CanWrite) ErrorWriteNotSupported();
var pos = Interlocked.Read(ref _position); // Use a local to avoid a race condition
var len = Interlocked.Read(ref _length);
var n = pos + count;
// Check for overflow
if (n < 0)
throw new IOException(ResourceHelper.GetString("IO.IO_StreamTooLong"));
if (n > _capacity)
{
throw new NotSupportedException(ResourceHelper.GetString("IO.IO_FixedCapacity"));
}
if (_buffer == null)
{
// Check to see whether we are now expanding the stream and must zero any memory in the middle.
if (pos > len)
{
unsafe
{
BufferZeroMemory(_mem + len, pos - len);
}
}
// set length after zeroing memory to avoid race condition of accessing unzeroed memory
if (n > len)
{
Interlocked.Exchange(ref _length, n);
}
}
if (_buffer != null)
{
var bytesLeft = _capacity - pos;
if (bytesLeft < count)
{
throw new ArgumentException(ResourceHelper.GetString("Arg_BufferTooSmall"));
}
unsafe
{
byte* pointer = null;
RuntimeHelpers.PrepareConstrainedRegions();
try
{
_buffer.AcquirePointer(ref pointer);
BufferMemcpy(pointer + pos + _offset, 0, buffer, offset, count);
}
finally
{
if (pointer != null)
{
_buffer.ReleasePointer();
}
}
}
}
else
{
unsafe
{
BufferMemcpy(_mem + pos, 0, buffer, offset, count);
}
}
Interlocked.Exchange(ref _position, n);
}
/// <summary>
/// Asynchronously writes a sequence of bytes to the current stream, advances the current position within this stream by the number
/// of bytes written, and monitors cancellation requests.
/// </summary>
/// <param name="buffer">The buffer to write data from.</param>
/// <param name="offset">The zero-based byte offset in buffer from which to begin copying bytes to the stream.</param>
/// <param name="count">The maximum number of bytes to write.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is None.</param>
/// <returns>A task that represents the asynchronous write operation.</returns>
[HostProtection(ExternalThreading = true)]
[ComVisible(false)]
public virtual Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
if (buffer == null)
throw new ArgumentNullException(nameof(buffer), ResourceHelper.GetString("ArgumentNull_Buffer"));
if (offset < 0)
throw new ArgumentOutOfRangeException(nameof(offset), ResourceHelper.GetString("ArgumentOutOfRange_NeedNonNegNum"));
if (count < 0)
throw new ArgumentOutOfRangeException(nameof(count), ResourceHelper.GetString("ArgumentOutOfRange_NeedNonNegNum"));
if (buffer.Length - offset < count)
throw new ArgumentException(ResourceHelper.GetString("Argument_InvalidOffLen"));
Contract.EndContractBlock(); // contract validation copied from Write(..)
if (cancellationToken.IsCancellationRequested)
return Task.FromCanceled(cancellationToken);
try
{
Write(buffer, offset, count);
return Task.CompletedTask;
}
catch (Exception ex)
{
Contract.Assert(!(ex is OperationCanceledException));
return Task.FromException<int>(ex);
}
}
/// <summary>Writes a byte to the current position in the stream and advances the position within the stream by one byte.</summary>
/// <param name="value">The byte to write to the stream.</param>
[SecuritySafeCritical]
public override void WriteByte(byte value)
{
if (!_isOpen) ErrorStreamIsClosed();
if (!CanWrite) ErrorWriteNotSupported();
var pos = Interlocked.Read(ref _position); // Use a local to avoid a race condition
var len = Interlocked.Read(ref _length);
var n = pos + 1;
if (pos >= len)
{
// Check for overflow
if (n < 0)
throw new IOException(ResourceHelper.GetString("IO.IO_StreamTooLong"));
if (n > _capacity)
throw new NotSupportedException(ResourceHelper.GetString("IO.IO_FixedCapacity"));
// Check to see whether we are now expanding the stream and must zero any memory in the middle. don't do if created from SafeBuffer
if (_buffer == null)
{
if (pos > len)
{
unsafe
{
BufferZeroMemory(_mem + len, pos - len);
}
}
// set length after zeroing memory to avoid race condition of accessing unzeroed memory
Interlocked.Exchange(ref _length, n);
}
}
if (_buffer != null)
{
unsafe
{
byte* pointer = null;
RuntimeHelpers.PrepareConstrainedRegions();
try
{
_buffer.AcquirePointer(ref pointer);
*(pointer + pos + _offset) = value;
}
finally
{
if (pointer != null)
{
_buffer.ReleasePointer();
}
}
}
}
else
{
unsafe
{
_mem[pos] = value;
}
}
Interlocked.Exchange(ref _position, n);
}
[SecurityCritical]
internal void Initialize(SafeBuffer buffer, long offset, long length, FileAccess access, bool skipSecurityCheck)
{
if (buffer == null)
throw new ArgumentNullException(nameof(buffer));
if (offset < 0)
throw new ArgumentOutOfRangeException(nameof(offset), ResourceHelper.GetString("ArgumentOutOfRange_NeedNonNegNum"));
if (length < 0)
throw new ArgumentOutOfRangeException(nameof(length), ResourceHelper.GetString("ArgumentOutOfRange_NeedNonNegNum"));
if (buffer.ByteLength < (ulong)(offset + length))
throw new ArgumentException(ResourceHelper.GetString("Argument_InvalidSafeBufferOffLen"));
if (access < FileAccess.Read || access > FileAccess.ReadWrite)
throw new ArgumentOutOfRangeException(nameof(access));
Contract.EndContractBlock();
if (_isOpen)
throw new InvalidOperationException(ResourceHelper.GetString("InvalidOperation_CalledTwice"));
if (!skipSecurityCheck)
#pragma warning disable 618
new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand();
#pragma warning restore 618
// check for wraparound
unsafe
{
byte* pointer = null;
RuntimeHelpers.PrepareConstrainedRegions();
try
{
buffer.AcquirePointer(ref pointer);
if (pointer + offset + length < pointer)
{
throw new ArgumentException(ResourceHelper.GetString("ArgumentOutOfRange_UnmanagedMemStreamWrapAround"));
}
}
finally
{
if (pointer != null)
{
buffer.ReleasePointer();
}
}
}
_offset = offset;
_buffer = buffer;
_length = length;
_capacity = length;
_access = access;
_isOpen = true;
}
[SecurityCritical]
internal unsafe void Initialize(byte* pointer, long length, long capacity, FileAccess access, bool skipSecurityCheck)
{
if (pointer == null)
throw new ArgumentNullException(nameof(pointer));
if (length < 0 || capacity < 0)
throw new ArgumentOutOfRangeException(length < 0 ? "length" : "capacity", ResourceHelper.GetString("ArgumentOutOfRange_NeedNonNegNum"));
if (length > capacity)
throw new ArgumentOutOfRangeException(nameof(length), ResourceHelper.GetString("ArgumentOutOfRange_LengthGreaterThanCapacity"));
Contract.EndContractBlock();
// Check for wraparound.
if ((byte*)((long)pointer + capacity) < pointer)
throw new ArgumentOutOfRangeException(nameof(capacity), ResourceHelper.GetString("ArgumentOutOfRange_UnmanagedMemStreamWrapAround"));
if (access < FileAccess.Read || access > FileAccess.ReadWrite)
throw new ArgumentOutOfRangeException(nameof(access), ResourceHelper.GetString("ArgumentOutOfRange_Enum"));
if (_isOpen)
throw new InvalidOperationException(ResourceHelper.GetString("InvalidOperation_CalledTwice"));
if (!skipSecurityCheck)
#pragma warning disable 618
new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand();
#pragma warning restore 618
_mem = pointer;
_offset = 0;
_length = length;
_capacity = capacity;
_access = access;
_isOpen = true;
}
/// <summary>
/// Releases the unmanaged resources used by the <see cref="T:System.IO.Stream"/> and optionally releases the managed resources.
/// </summary>
/// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param>
[SecuritySafeCritical]
protected override void Dispose(bool disposing)
{
_isOpen = false;
unsafe { _mem = null; }
// Stream allocates WaitHandles for async calls. So for correctness call base.Dispose(disposing) for better perf, avoiding
// waiting for the finalizers to run on those types.
base.Dispose(disposing);
}
/// <summary>
/// Initializes a new instance of the UnmanagedMemoryStream class in a safe buffer with a specified offset, length, and file access.
/// </summary>
/// <param name="buffer">The buffer to contain the unmanaged memory stream.</param>
/// <param name="offset">The byte position in the buffer at which to start the unmanaged memory stream.</param>
/// <param name="length">The length of the unmanaged memory stream.</param>
/// <param name="access">The mode of file access to the unmanaged memory stream.</param>
[SecuritySafeCritical]
protected void Initialize(SafeBuffer buffer, long offset, long length, FileAccess access) => Initialize(buffer, offset, length, access, false);
/// <summary>Initializes a new instance of the UnmanagedMemoryStream class by using a pointer to an unmanaged memory location.</summary>
/// <param name="pointer">A pointer to an unmanaged memory location.</param>
/// <param name="length">The length of the memory to use.</param>
/// <param name="capacity">The total amount of memory assigned to the stream.</param>
/// <param name="access">One of the <see cref="FileAccess"/> values.</param>
[SecurityCritical]
protected unsafe void Initialize(byte* pointer, long length, long capacity, FileAccess access) => Initialize(pointer, length, capacity, access, false);
[SecurityCritical]
private static unsafe void BufferMemcpy(byte[] dest, int destIndex, byte* src, int srcIndex, int len)
{
Contract.Assert(srcIndex >= 0 && destIndex >= 0 && len >= 0, "Index and length must be non-negative!");
Contract.Assert(dest.Length - destIndex >= len, "not enough bytes in dest");
if (len == 0)
return;
Marshal.Copy((IntPtr)src, dest, srcIndex, len);
}
[SecurityCritical]
private static unsafe void BufferMemcpy(byte* dest, int destIndex, byte[] src, int srcIndex, int len)
{
Contract.Assert(srcIndex >= 0 && destIndex >= 0 && len >= 0, "Index and length must be non-negative!");
Contract.Assert(src.Length - srcIndex >= len, "not enough bytes in src");
if (len == 0)
return;
Marshal.Copy(src, srcIndex, (IntPtr)dest, len);
}
private static unsafe void BufferZeroMemory(byte* src, long len) => ((IntPtr)src).FillMemory(0, len);
private static void ErrorReadNotSupported() => throw new NotSupportedException(ResourceHelper.GetString("NotSupported_UnreadableStream"));
private static void ErrorStreamIsClosed() => throw new ObjectDisposedException(null, ResourceHelper.GetString("ObjectDisposed_StreamClosed"));
private static void ErrorWriteNotSupported() => throw new NotSupportedException(ResourceHelper.GetString("NotSupported_UnwritableStream"));
}
}
#endif

View File

@ -53,4 +53,7 @@ CorrespondingAction, FileAttributeConstant, FileOpConstant, FilePermissionConsta
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<Folder Include="BkwdComp\" />
</ItemGroup>
</Project>

View File

@ -1,4 +1,3 @@
#if !(NET20 || NET35)
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
@ -346,5 +345,4 @@ namespace Vanara.PInvoke
}
}
}
}
#endif
}

View File

@ -14,13 +14,7 @@ namespace Vanara.PInvoke
private static readonly uint AutoChSz = (uint)StringHelper.GetCharSize();
private static readonly uint PageSize =
#if NET20 || NET35
new Func<uint>(() => { GetSystemInfo(out var si); return si.dwPageSize; })();
#else
(uint)System.Environment.SystemPageSize;
#endif
private static readonly uint PageSize = (uint)System.Environment.SystemPageSize;
/// <summary>Retrieves an integer associated with a key in the specified section of an initialization file.</summary>
/// <param name="lpAppName">The name of the section in the initialization file.</param>

View File

@ -1622,9 +1622,7 @@ namespace Vanara.PInvoke
// dwFlags, LPBITMAPINFOHEADER lpbiSrc, LPVOID lpSrc, int xSrc, int ySrc, int dxSrc, int dySrc, LPBITMAPINFOHEADER lpbiDst, LPVOID
// lpDst, int xDst, int yDst, int dxDst, int dyDst );
[PInvokeData("vfw.h", MSDNShortId = "NF:vfw.ICDecompressEx")]
#if !(NET20 || NET35 || NET40)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
public static ICERR ICDecompressEx([In] HIC hic, ICDECOMPRESSF dwFlags, in BITMAPINFOHEADER lpbiSrc, [In] IntPtr lpSrc, int xSrc, int ySrc,
int dxSrc, int dySrc, in BITMAPINFOHEADER lpbiDst, [Out] IntPtr lpDst, int xDst, int yDst, int dxDst, int dyDst)
{
@ -1706,9 +1704,7 @@ namespace Vanara.PInvoke
// hic, DWORD dwFlags, LPBITMAPINFOHEADER lpbiSrc, LPVOID lpSrc, int xSrc, int ySrc, int dxSrc, int dySrc, LPBITMAPINFOHEADER
// lpbiDst, LPVOID lpDst, int xDst, int yDst, int dxDst, int dyDst );
[PInvokeData("vfw.h", MSDNShortId = "NF:vfw.ICDecompressExBegin")]
#if !(NET20 || NET35 || NET40)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
public static ICERR ICDecompressExBegin([In] HIC hic, ICDECOMPRESSF dwFlags, in BITMAPINFOHEADER lpbiSrc, [In] IntPtr lpSrc, int xSrc, int ySrc,
int dxSrc, int dySrc, in BITMAPINFOHEADER lpbiDst, [Out] IntPtr lpDst, int xDst, int yDst, int dxDst, int dyDst)
{

View File

@ -1,33 +0,0 @@
#if (NET20 || NET35)
namespace Microsoft.Win32.SafeHandles
{
using System;
using System.Runtime.InteropServices;
using System.Security;
/// <summary>Represents a safe handle to the Windows registry.</summary>
[SecurityCritical]
public sealed class SafeRegistryHandle : SafeHandleZeroOrMinusOneIsInvalid
{
/// <summary>Initializes a new instance of the <see cref="SafeRegistryHandle"/> class.</summary>
/// <param name="preexistingHandle">An object that represents the pre-existing handle to use.</param>
/// <param name="ownsHandle">
/// <see langword="true"/> to reliably release the handle during the finalization phase; <see langword="false"/> to prevent reliable release.
/// </param>
[SecurityCritical]
public SafeRegistryHandle(IntPtr preexistingHandle, bool ownsHandle) : base(ownsHandle) => SetHandle(preexistingHandle);
[SecurityCritical]
internal SafeRegistryHandle() : base(true) { }
/// <inheritdoc/>
[SecurityCritical]
protected override bool ReleaseHandle() => RegCloseKey(handle).Succeeded;
[DllImport(Vanara.PInvoke.Lib.AdvApi32, SetLastError = true, ExactSpelling = true)]
private static extern Vanara.PInvoke.Win32Error RegCloseKey(IntPtr hKey);
}
}
#endif

View File

@ -54,17 +54,13 @@ namespace Vanara.InteropServices
/// <summary>Performs an implicit conversion from <typeparamref name="T"/> to <see cref="SafeAnysizeStructBase{T}"/>.</summary>
/// <param name="s">The <typeparamref name="T"/> instance.</param>
/// <returns>The result of the conversion.</returns>
#if !(NET20 || NET35 || NET40)
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
#endif
public static implicit operator SafeAnysizeStruct<T>(in T s) => new(s);
/// <summary>Gets the length of the array from the structure.</summary>
/// <param name="local">The local, system marshaled, structure instance extracted from the pointer.</param>
/// <returns>The element length of the 'anysize' array.</returns>
#if !(NET20 || NET35 || NET40)
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
#endif
protected override int GetArrayLength(in T local) => fiCount is null ? GetArrLenFromSz() : (fiCount.FieldType == typeof(IntPtr) ? ((IntPtr)fiCount.GetValue(local)).ToInt32() : Convert.ToInt32(fiCount.GetValue(local)));
private int GetArrLenFromSz() => 1 + (Size - baseSz) / Marshal.SizeOf(elemType);

View File

@ -34,9 +34,7 @@ namespace Vanara.PInvoke
/// Properties defined with this can only be safely used when the structure has been marshaled via a dynamic memory block and not
/// when marshaled directly.
/// </remarks>
#if !(NET20 || NET35 || NET40)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
public unsafe static T[] FieldToArray<T>(ref T fieldReference, int count, int offset = 0) where T : unmanaged
{
if (count == 0) return new T[0];

View File

@ -509,12 +509,10 @@ namespace Vanara.PInvoke
return new Win32Error(unchecked((uint)we.NativeErrorCode)).ToHRESULT();
if (exception.InnerException is Win32Exception iwe)
return new Win32Error(unchecked((uint)iwe.NativeErrorCode)).ToHRESULT();
#if !(NET20 || NET35 || NET40)
if (exception.HResult != 0)
return new HRESULT(exception.HResult);
else if (exception.InnerException != null && exception.InnerException.HResult != 0)
return new HRESULT(exception.InnerException.HResult);
#endif
return E_FAIL;
}

View File

@ -46,11 +46,9 @@ namespace Vanara.PInvoke
return unchecked((uint)we.NativeErrorCode);
if (exception.InnerException is Win32Exception iwe)
return unchecked((uint)iwe.NativeErrorCode);
#if !(NET20 || NET35 || NET40)
var hr = new HRESULT(exception.HResult);
if (hr.Facility == HRESULT.FacilityCode.FACILITY_WIN32)
return unchecked((uint)hr.Code);
#endif
return ERROR_UNIDENTIFIED_ERROR;
}

View File

@ -1257,7 +1257,7 @@ namespace Vanara.PInvoke
public static extern uint PrivateExtractIcons(string szFileName, int nIconIndex, int cxIcon, int cyIcon,
[In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 6)] SafeHICON[] phicon, out uint piconid, uint nIcons, LoadImageOptions flags);
#if WPF && !NET20 && !NETSTANDARD2_0 && !NETCOREAPP2_0 && !NETCOREAPP2_1
#if WPF && !NETSTANDARD2_0
/// <summary>Creates a <see cref="System.Windows.Media.Imaging.BitmapSource"/> from an <see cref="HICON"/>.</summary>
/// <param name="hIcon">The HICON value.</param>
/// <returns>The BitmapSource instance. If <paramref name="hIcon"/> is a <c>NULL</c> handle, <see langword="null"/> is returned.</returns>
@ -1391,7 +1391,7 @@ namespace Vanara.PInvoke
/// <returns>The result of the conversion.</returns>
public static implicit operator HICON(SafeHICON h) => h.handle;
#if WPF && !NET20 && !NETSTANDARD2_0 && !NETCOREAPP2_0 && !NETCOREAPP2_1
#if WPF && !NETSTANDARD2_0
/// <summary>Creates a <see cref="System.Windows.Media.Imaging.BitmapSource"/> from an <see cref="SafeHICON"/>.</summary>
/// <returns>The BitmapSource instance. If this is a <c>NULL</c> handle, <see langword="null"/> is returned.</returns>
public System.Windows.Media.Imaging.BitmapSource ToBitmapSource() => ((HICON)this).ToBitmapSource();

View File

@ -12,23 +12,6 @@ using Vanara.InteropServices;
using Vanara.PInvoke;
using static Vanara.PInvoke.Kernel32;
#if NET20
namespace System.IO
{
/// <summary>Specifies whether the underlying handle is inheritable by child processes.</summary>
public enum HandleInheritability
{
/// <summary>Specifies that the handle is not inheritable by child processes.</summary>
None = 0,
/// <summary>Specifies that the handle is inheritable by child processes.</summary>
Inheritable = 1,
}
}
#endif
namespace Vanara.Diagnostics
{
/// <summary>The job limit type exceeded as communicated by a <see cref="JobNotificationEventArgs"/>.</summary>

View File

@ -1,11 +1,7 @@
using System;
using System.ComponentModel;
using System.IO;
#if !(NET20 || NET35)
using System.Threading.Tasks;
#endif
using Vanara.PInvoke;
using static Vanara.PInvoke.Kernel32;
@ -70,7 +66,6 @@ namespace Vanara.Extensions
throw new Win32Exception();
}
#if !(NET20 || NET35)
/// <summary>Asynchronously gets whether NTFS compression is enabled for this file.</summary>
/// <param name="fi">The file information.</param>
/// <returns><see langword="true"/> if the specified files is compressed under NTFS; otherwise <see langword="false"/>.</returns>
@ -103,6 +98,5 @@ namespace Vanara.Extensions
}
return tret.Task;
}
#endif
}
}

View File

@ -4,7 +4,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
#if (NET20 || NET35 || NET40 || NET45)
#if NET20_OR_GREATER
using System.Management;
#endif
using System.Runtime.InteropServices;
@ -41,7 +41,7 @@ namespace Vanara.Extensions
hObj.AdjustPrivilege(privilege, PrivilegeAttributes.SE_PRIVILEGE_ENABLED);
}
#if (NET35 || NET40 || NET45)
#if NET35_OR_GREATER
/// <summary>Gets the child processes.</summary>
/// <param name="p">The process.</param>
/// <param name="includeDescendants">if set to <c>true</c> include descendants of child processes as well.</param>
@ -130,7 +130,7 @@ namespace Vanara.Extensions
return sb.ToString();
}
#if (NET20 || NET35 || NET40 || NET45)
#if NET20_OR_GREATER
/// <summary>
/// Gets the parent process.
/// </summary>
@ -200,11 +200,7 @@ namespace Vanara.Extensions
/// TRUE if the process is running under WOW64. If the process is running under 32-bit Windows, the value is set to FALSE. If the
/// process is a 64-bit application running under 64-bit Windows, the value is also set to FALSE.
/// </returns>
public static bool Is64Bit(this Process process) =>
#if !(NET20 || NET35)
Environment.Is64BitOperatingSystem &&
#endif
process.IsWow64();
public static bool Is64Bit(this Process process) => Environment.Is64BitOperatingSystem && process.IsWow64();
/// <summary>
/// The function gets the elevation information of the current process. It dictates whether the process is elevated or not. Token elevation is only

View File

@ -1,4 +1,4 @@
#if (NET20 || NET35 || NET40 || NET45)
#if NET20_OR_GREATER
using System;
using System.ComponentModel;

View File

@ -63,7 +63,7 @@ namespace Vanara.IO
/// <returns>The altered, compacted path string.</returns>
public static string Compact(string path, int maxChars) => SBAllocCallRet((s, sz) => PathCompactPathEx(s, path, (uint)maxChars + 1));
#if (NET20 || NET35 || NET40 || NET45)
#if NET20_OR_GREATER
/// <summary>
/// Truncates a file path to fit within a given pixel width by replacing path components with ellipses.
/// </summary>

View File

@ -311,7 +311,7 @@ namespace Vanara.Registry
case "HKEY_CURRENT_CONFIG":
hive = RegistryHive.CurrentConfig;
break;
#if (NET20 || NET35 || NET40 || NET45)
#if NET20_OR_GREATER
case "HKEY_DYN_DATA":
hive = RegistryHive.DynData;
break;

View File

@ -663,11 +663,7 @@ namespace Vanara.IO
return err;
}
);
#if (NET20 || NET35)
if (!b) throw new OperationCanceledExceptionEx(cancellationToken);
#else
if (!b) throw new OperationCanceledException(cancellationToken);
#endif
return new VirtualDisk(new SafeVIRTUAL_DISK_HANDLE(h), (OPEN_VIRTUAL_DISK_VERSION)param.Version);
}
@ -698,11 +694,7 @@ namespace Vanara.IO
break;
}
if (prog.CurrentValue == prog.CompletionValue) return true;
#if NET40
await TaskEx.Delay(250, cancellationToken);
#else
await Task.Delay(250, cancellationToken);
#endif
}
}

View File

@ -170,7 +170,7 @@ namespace Vanara.PInvoke
//}
#if WPF && !NET20 && !NETSTANDARD2_0 && !NETCOREAPP2_0 && !NETCOREAPP2_1
#if WPF && !NETSTANDARD2_0
/// <summary>
/// Creates a <see cref="System.Windows.Media.Imaging.BitmapSource"/> from an <see cref="HBITMAP"/> preserving transparency, if possible.
/// </summary>

View File

@ -7,43 +7,21 @@ namespace Vanara.Windows.Shell
{
internal static class TaskAgg
{
public static Task CompletedTask
{
get
{
#if NET20 || NET35 || NET40 || NET45
return TaskExEx.CompletedTask;
#else
return Task.CompletedTask;
#endif
}
}
public static Task CompletedTask => Task.CompletedTask;
public static Task Run(Action action, CancellationToken cancellationToken)
{
#if NET20 || NET35 || NET40
return TaskEx.Run(action, cancellationToken);
#else
return Task.Run(action, cancellationToken);
#endif
}
public static Task<T> Run<T>(Func<T> action, CancellationToken cancellationToken)
{
#if NET20 || NET35 || NET40
return TaskEx.Run(action, cancellationToken);
#else
return Task.Run(action, cancellationToken);
#endif
}
public static Task WhenAll(IEnumerable<Task> tasks)
{
#if NET20 || NET35 || NET40
return TaskEx.WhenAll(tasks);
#else
return Task.WhenAll(tasks);
#endif
}
}
}

View File

@ -644,11 +644,7 @@ namespace Vanara.Windows.Shell
catch (Win32Exception w32ex) { return new Win32Error(unchecked((uint)w32ex.NativeErrorCode)).ToHRESULT(); }
catch (Exception e)
{
#if !(NET20 || NET35 || NET40)
return e.HResult;
#else
throw e;
#endif
}
return HRESULT.S_OK;
}