mirror of https://github.com/dahall/Vanara.git
Removed code and conditionals for obsolete target frameworks.
parent
d9f00186b0
commit
b669932c57
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -53,4 +53,7 @@ CorrespondingAction, FileAttributeConstant, FileOpConstant, FilePermissionConsta
|
|||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="BkwdComp\" />
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -1,4 +1,3 @@
|
|||
#if !(NET20 || NET35)
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.InteropServices;
|
||||
|
@ -346,5 +345,4 @@ namespace Vanara.PInvoke
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
|
@ -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>
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
|
@ -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);
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#if (NET20 || NET35 || NET40 || NET45)
|
||||
#if NET20_OR_GREATER
|
||||
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue