kopia lustrzana https://github.com/dl2alf/AirScout
206 wiersze
7.5 KiB
C#
206 wiersze
7.5 KiB
C#
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
|
|
namespace System.Runtime.InteropServices
|
|
{
|
|
internal class SafeHGlobalHandle : SafeHandle
|
|
{
|
|
/// <summary>
|
|
/// Maintains reference to other SafeHGlobalHandle objects, the pointer
|
|
/// to which are referred to by this object. This is to ensure that such
|
|
/// objects being referred to wouldn't be unreferenced until this object
|
|
/// is active.
|
|
/// </summary>
|
|
List<SafeHGlobalHandle> references;
|
|
|
|
public SafeHGlobalHandle() : this(IntPtr.Zero, 0, false) { }
|
|
|
|
public SafeHGlobalHandle(IntPtr handle, int size, bool ownsHandle = true) :
|
|
base(IntPtr.Zero, ownsHandle)
|
|
{
|
|
if (handle != IntPtr.Zero)
|
|
SetHandle(handle);
|
|
Size = size;
|
|
}
|
|
|
|
public SafeHGlobalHandle(int size) : this()
|
|
{
|
|
if (size < 0)
|
|
throw new ArgumentOutOfRangeException(nameof(size), "The value of this argument must be non-negative");
|
|
System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions();
|
|
SetHandle(Marshal.AllocHGlobal(size));
|
|
Size = size;
|
|
}
|
|
|
|
public SafeHGlobalHandle(object value) : this(Marshal.SizeOf(value))
|
|
{
|
|
Marshal.StructureToPtr(value, handle, false);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Allocates from unmanaged memory to represent an array of pointers
|
|
/// and marshals the unmanaged pointers (IntPtr) to the native array
|
|
/// equivalent.
|
|
/// </summary>
|
|
/// <param name="values">Array of unmanaged pointers</param>
|
|
/// <returns>SafeHGlobalHandle object to an native (unmanaged) array of pointers</returns>
|
|
public SafeHGlobalHandle(IntPtr[] values) : this(IntPtr.Size * values.Length)
|
|
{
|
|
Marshal.Copy(values, 0, handle, values.Length);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Allocates from unmanaged memory to represent a Unicode string (WSTR)
|
|
/// and marshal this to a native PWSTR.
|
|
/// </summary>
|
|
/// <param name="s">String</param>
|
|
/// <returns>SafeHGlobalHandle object to an native (unmanaged) Unicode string</returns>
|
|
public SafeHGlobalHandle(string s) : this(s == null ? IntPtr.Zero : Marshal.StringToHGlobalUni(s), (s?.Length + 1) * 2 ?? 0)
|
|
{
|
|
}
|
|
|
|
/*
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="SafeHGlobalHandle"/> class.
|
|
/// </summary>
|
|
/// <param name="s">The secure string.</param>
|
|
public SafeHGlobalHandle(Security.SecureString s) :
|
|
base(IntPtr.Zero, p => { Marshal.ZeroFreeGlobalAllocUnicode(p); return true; }, true)
|
|
{
|
|
if (s != null)
|
|
{
|
|
s.MakeReadOnly();
|
|
SetHandle(Marshal.SecureStringToGlobalAllocUnicode(s));
|
|
Size = s.Length;
|
|
}
|
|
}
|
|
*/
|
|
|
|
/// <summary>
|
|
/// Allocates from unmanaged memory sufficient memory to hold an object of type T.
|
|
/// </summary>
|
|
/// <typeparam name="T">Native type</typeparam>
|
|
/// <returns>SafeHGlobalHandle object to an native (unmanaged) memory block the size of T.</returns>
|
|
public static SafeHGlobalHandle AllocHGlobal<T>() => new SafeHGlobalHandle(Marshal.SizeOf(typeof(T)));
|
|
|
|
/// <summary>
|
|
/// Allocates from unmanaged memory to represent an array of structures
|
|
/// and marshals the structure elements to the native array of
|
|
/// structures. ONLY structures with attribute StructLayout of
|
|
/// LayoutKind.Sequential are supported.
|
|
/// </summary>
|
|
/// <typeparam name="T">Native structure type</typeparam>
|
|
/// <param name="values">Collection of structure objects</param>
|
|
/// <returns>SafeHGlobalHandle object to an native (unmanaged) array of structures</returns>
|
|
public static SafeHGlobalHandle AllocHGlobal<T>(ICollection<T> values) where T : struct
|
|
{
|
|
Debug.Assert(typeof(T).StructLayoutAttribute?.Value == LayoutKind.Sequential);
|
|
|
|
return AllocHGlobal(0, values, values.Count);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Allocates from unmanaged memory to represent a structure with a
|
|
/// variable length array at the end and marshal these structure
|
|
/// elements. It is the callers responsibility to marshal what precedes
|
|
/// the trailing array into the unmanaged memory. ONLY structures with
|
|
/// attribute StructLayout of LayoutKind.Sequential are supported.
|
|
/// </summary>
|
|
/// <typeparam name="T">Type of the trailing array of structures</typeparam>
|
|
/// <param name="prefixBytes">Number of bytes preceding the trailing array of structures</param>
|
|
/// <param name="values">Collection of structure objects</param>
|
|
/// <param name="count">Number of items in <paramref name="values"/>.</param>
|
|
/// <returns>SafeHGlobalHandle object to an native (unmanaged) structure with a trail array of structures</returns>
|
|
public static SafeHGlobalHandle AllocHGlobal<T>(int prefixBytes, IEnumerable<T> values, int count) where T : struct
|
|
{
|
|
Debug.Assert(typeof(T).StructLayoutAttribute?.Value == LayoutKind.Sequential);
|
|
|
|
var result = new SafeHGlobalHandle(prefixBytes + Marshal.SizeOf(typeof(T)) * count);
|
|
var ptr = new IntPtr(result.handle.ToInt32() + prefixBytes);
|
|
foreach (var value in values)
|
|
{
|
|
Marshal.StructureToPtr(value, ptr, false);
|
|
ptr = new IntPtr(ptr.ToInt32() + Marshal.SizeOf(typeof(T)));
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Allocates from unmanaged memory to hold a copy of a structure.
|
|
/// </summary>
|
|
/// <typeparam name="T">Type of the structure.</typeparam>
|
|
/// <param name="obj">The object.</param>
|
|
/// <returns>SafeHGlobalHandle object to an native (unmanaged) structure</returns>
|
|
public static SafeHGlobalHandle AllocHGlobalStruct<T>(T obj) where T : struct
|
|
{
|
|
Debug.Assert(typeof(T).StructLayoutAttribute?.Value == LayoutKind.Sequential);
|
|
|
|
var result = new SafeHGlobalHandle(Marshal.SizeOf(typeof(T)));
|
|
Marshal.StructureToPtr(obj, result.handle, false);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the size of the allocated memory block.
|
|
/// </summary>
|
|
/// <value>
|
|
/// The sizeof the allocated memory block.
|
|
/// </value>
|
|
public int Size { get; }
|
|
|
|
/// <summary>
|
|
/// Allows to assign IntPtr to SafeHGlobalHandle
|
|
/// </summary>
|
|
public static implicit operator SafeHGlobalHandle(IntPtr ptr) => new SafeHGlobalHandle(ptr, 0, true);
|
|
|
|
/// <summary>
|
|
/// Allows to use SafeHGlobalHandle as IntPtr
|
|
/// </summary>
|
|
public static implicit operator IntPtr(SafeHGlobalHandle h) => h.DangerousGetHandle();
|
|
|
|
/// <summary>
|
|
/// Adds reference to other SafeHGlobalHandle objects, the pointer to
|
|
/// which are referred to by this object. This is to ensure that such
|
|
/// objects being referred to wouldn't be unreferenced until this object
|
|
/// is active.
|
|
///
|
|
/// For e.g. when this object is an array of pointers to other objects
|
|
/// </summary>
|
|
/// <param name="children">Collection of SafeHGlobalHandle objects referred to by this object.</param>
|
|
public void AddSubReference(IEnumerable<SafeHGlobalHandle> children)
|
|
{
|
|
if (references == null)
|
|
references = new List<SafeHGlobalHandle>();
|
|
references.AddRange(children);
|
|
}
|
|
|
|
public T ToStructure<T>() where T : struct
|
|
{
|
|
if (IsInvalid)
|
|
return default(T);
|
|
if (Size < Marshal.SizeOf(typeof(T)))
|
|
throw new InsufficientMemoryException("Requested structure is larger than the memory allocated.");
|
|
return handle.ToStructure<T>();
|
|
}
|
|
|
|
public T[] ToArray<T>(int count, int prefixBytes = 0) where T : struct
|
|
{
|
|
if (IsInvalid)
|
|
return null;
|
|
if (Size < Marshal.SizeOf(typeof(T)) * count + prefixBytes)
|
|
throw new InsufficientMemoryException("Requested array is larger than the memory allocated.");
|
|
Debug.Assert(typeof(T).StructLayoutAttribute?.Value == LayoutKind.Sequential);
|
|
return handle.ToArray<T>(count, prefixBytes);
|
|
}
|
|
|
|
protected override bool ReleaseHandle()
|
|
{
|
|
if (!IsInvalid)
|
|
Marshal.FreeHGlobal(handle);
|
|
return true;
|
|
}
|
|
|
|
public override bool IsInvalid => handle == IntPtr.Zero;
|
|
}
|
|
}
|