// Copyright (c) 2010-2014 SharpDX - Alexandre Mutel // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.Runtime.InteropServices; using System.Security; using System.Text; using System.Threading; using SharpDX.Direct3D; using System.Reflection; using System.Linq; using System.Linq.Expressions; using SharpDX.Text; using SharpDX.Mathematics.Interop; namespace SharpDX { /// /// A Delegate to get a property value from an object. /// /// Type of the getter. /// The obj to get the property from. /// The value to get. public delegate void GetValueFastDelegate(object obj, out T value); /// /// A Delegate to set a property value to an object. /// /// Type of the setter. /// The obj to set the property from. /// The value to set. public delegate void SetValueFastDelegate(object obj, ref T value); /// /// Utility class. /// public static class Utilities { ///// ///// Native memcpy. ///// ///// The destination memory location. ///// The source memory location. ///// The count. ///// //[DllImport("msvcrt.dll", EntryPoint = "memcpy", CallingConvention = CallingConvention.Cdecl, // SetLastError = false), SuppressUnmanagedCodeSecurity] //public static extern IntPtr CopyMemory(IntPtr dest, IntPtr src, ulong sizeInBytesToCopy); /// /// Native memcpy. /// /// The destination memory location. /// The source memory location. /// The byte count. public static void CopyMemory(IntPtr dest, IntPtr src, int sizeInBytesToCopy) { unsafe { // TODO plug in Interop a pluggable CopyMemory using cpblk or memcpy based on architecture Interop.memcpy((void*)dest, (void*)src, sizeInBytesToCopy); } } /// /// Compares two block of memory. /// /// The pointer to compare from. /// The pointer to compare against. /// The size in bytes to compare. /// true if the buffers are equivalent; otherwise, false. public unsafe static bool CompareMemory(IntPtr from, IntPtr against, int sizeToCompare) { var pSrc = (byte*)@from; var pDst = (byte*)against; // Compare 8 bytes. int numberOf = sizeToCompare >> 3; while (numberOf > 0) { if (*(long*)pSrc != *(long*)pDst) return false; pSrc += 8; pDst += 8; numberOf--; } // Compare remaining bytes. numberOf = sizeToCompare & 7; while (numberOf > 0) { if (*pSrc != *pDst) return false; pSrc++; pDst++; numberOf--; } return true; } /// /// Clears the memory. /// /// The dest. /// The value. /// The size in bytes to clear. public static void ClearMemory(IntPtr dest, byte value, int sizeInBytesToClear) { unsafe { Interop.memset((void*)dest, value, sizeInBytesToClear); } } /// /// Return the sizeof a struct from a CLR. Equivalent to sizeof operator but works on generics too. /// /// A struct to evaluate. /// Size of this struct. public static int SizeOf() where T : struct { return Interop.SizeOf(); } /// /// Return the sizeof an array of struct. Equivalent to sizeof operator but works on generics too. /// /// A struct. /// The array of struct to evaluate. /// Size in bytes of this array of struct. public static int SizeOf(T[] array) where T : struct { return array == null ? 0 : array.Length * Interop.SizeOf(); } /// /// Pins the specified source and call an action with the pinned pointer. /// /// The type of the structure to pin. /// The source. /// The pin action to perform on the pinned pointer. public static void Pin(ref T source, Action pinAction) where T : struct { unsafe { pinAction((IntPtr)Interop.Fixed(ref source)); } } /// /// Pins the specified source and call an action with the pinned pointer. /// /// The type of the structure to pin. /// The source array. /// The pin action to perform on the pinned pointer. public static void Pin(T[] source, Action pinAction) where T : struct { unsafe { pinAction(source == null ? IntPtr.Zero : (IntPtr)Interop.Fixed(source)); } } /// /// Converts a structured array to an equivalent byte array. /// /// The type of source array. /// The source array. /// Converted byte array. public static byte[] ToByteArray(T[] source) where T : struct { if (source == null) return null; var buffer = new byte[SizeOf() * source.Length]; if (source.Length == 0) return buffer; unsafe { fixed (void* pBuffer = buffer) Interop.Write(pBuffer, source, 0, source.Length); } return buffer; } /// /// Swaps the value between two references. /// /// Type of a data to swap. /// The left value. /// The right value. public static void Swap(ref T left, ref T right) { var temp = left; left = right; right = temp; } /// /// Reads the specified T data from a memory location. /// /// Type of a data to read. /// Memory location to read from. /// The data read from the memory location. public static T Read(IntPtr source) where T : struct { unsafe { return Interop.ReadInline((void*)source); } } /// /// Reads the specified T data from a memory location. /// /// Type of a data to read. /// Memory location to read from. /// The data write to. /// source pointer + sizeof(T). public static void Read(IntPtr source, ref T data) where T : struct { unsafe { Interop.CopyInline(ref data, (void*)source); } } /// /// Reads the specified T data from a memory location. /// /// Type of a data to read. /// Memory location to read from. /// The data write to. /// source pointer + sizeof(T). public static void ReadOut(IntPtr source, out T data) where T : struct { unsafe { Interop.CopyInlineOut(out data, (void*)source); } } /// /// Reads the specified T data from a memory location. /// /// Type of a data to read. /// Memory location to read from. /// The data write to. /// source pointer + sizeof(T). public static IntPtr ReadAndPosition(IntPtr source, ref T data) where T : struct { unsafe { return (IntPtr)Interop.Read((void*)source, ref data); } } /// /// Reads the specified array T[] data from a memory location. /// /// Type of a data to read. /// Memory location to read from. /// The data write to. /// The offset in the array to write to. /// The number of T element to read from the memory location. /// source pointer + sizeof(T) * count. public static IntPtr Read(IntPtr source, T[] data, int offset, int count) where T : struct { unsafe { return (IntPtr)Interop.Read((void*)source, data, offset, count); } } /// /// Writes the specified T data to a memory location. /// /// Type of a data to write. /// Memory location to write to. /// The data to write. /// destination pointer + sizeof(T). public static void Write(IntPtr destination, ref T data) where T : struct { unsafe { Interop.CopyInline((void*)destination, ref data); } } /// /// Writes the specified T data to a memory location. /// /// Type of a data to write. /// Memory location to write to. /// The data to write. /// destination pointer + sizeof(T). public static IntPtr WriteAndPosition(IntPtr destination, ref T data) where T : struct { unsafe { return (IntPtr)Interop.Write((void*)destination, ref data); } } /// /// Writes the specified array T[] data to a memory location. /// /// Type of a data to write. /// Memory location to write to. /// The array of T data to write. /// The offset in the array to read from. /// The number of T element to write to the memory location. /// destination pointer + sizeof(T) * count. public static IntPtr Write(IntPtr destination, T[] data, int offset, int count) where T : struct { unsafe { return (IntPtr)Interop.Write((void*)destination, data, offset, count); } } /// /// Converts bool array to integer pointers array. /// /// The bool array. /// The destination array of int pointers. public unsafe static void ConvertToIntArray(bool[] array, int* dest) { for (int i = 0; i < array.Length; i++) dest[i] = array[i] ? 1 : 0; } /// /// Converts bool array to array. /// /// The bool array. /// Converted array of . public static RawBool[] ConvertToIntArray(bool[] array) { var temp = new RawBool[array.Length]; for (int i = 0; i < temp.Length; i++) temp[i] = array[i]; return temp; } /// /// Converts integer pointer array to bool array. /// /// The array of integer pointers. /// Array size. /// Converted array of bool. public static unsafe bool[] ConvertToBoolArray(int* array, int length) { var temp = new bool[length]; for(int i = 0; i < temp.Length; i++) temp[i] = array[i] != 0; return temp; } /// /// Converts array to bool array. /// /// The array. /// Converted array of bool. public static bool[] ConvertToBoolArray(RawBool[] array) { var temp = new bool[array.Length]; for(int i = 0; i < temp.Length; i++) temp[i] = array[i]; return temp; } /// /// Gets the from a type. /// /// The type. /// The guid associated with this type. public static Guid GetGuidFromType(Type type) { return type.GetTypeInfo().GUID; } /// /// Determines whether a given type inherits from a generic type. /// /// Type of the class to check if it inherits from generic type. /// Type of the generic. /// true if [is assignable to generic type] [the specified given type]; otherwise, false. public static bool IsAssignableToGenericType(Type givenType, Type genericType) { // from http://stackoverflow.com/a/1075059/1356325 #if BEFORE_NET45 var interfaceTypes = givenType.GetTypeInfo().GetInterfaces(); #else var interfaceTypes = givenType.GetTypeInfo().ImplementedInterfaces; #endif foreach (var it in interfaceTypes) { if (it.GetTypeInfo().IsGenericType && it.GetGenericTypeDefinition() == genericType) return true; } if (givenType.GetTypeInfo().IsGenericType && givenType.GetGenericTypeDefinition() == genericType) return true; Type baseType = givenType.GetTypeInfo().BaseType; if (baseType == null) return false; return IsAssignableToGenericType(baseType, genericType); } /// /// Allocate an aligned memory buffer. /// /// Size of the buffer to allocate. /// Alignment, 16 bytes by default. /// A pointer to a buffer aligned. /// /// To free this buffer, call . /// public unsafe static IntPtr AllocateMemory(int sizeInBytes, int align = 16) { int mask = align - 1; var memPtr = Marshal.AllocHGlobal(sizeInBytes + mask + IntPtr.Size); var ptr = (long)((byte*)memPtr + sizeof(void*) + mask) & ~mask; ((IntPtr*)ptr)[-1] = memPtr; return new IntPtr((void*)ptr); } /// /// Allocate an aligned memory buffer and clear it with a specified value (0 by default). /// /// Size of the buffer to allocate. /// Default value used to clear the buffer. /// Alignment, 16 bytes by default. /// A pointer to a buffer aligned. /// /// To free this buffer, call . /// public static IntPtr AllocateClearedMemory(int sizeInBytes, byte clearValue = 0, int align = 16) { var ptr = AllocateMemory(sizeInBytes, align); ClearMemory(ptr, clearValue, sizeInBytes); return ptr; } /// /// Determines whether the specified memory pointer is aligned in memory. /// /// The memory pointer. /// The align. /// true if the specified memory pointer is aligned in memory; otherwise, false. public static bool IsMemoryAligned(IntPtr memoryPtr, int align = 16) { return ((memoryPtr.ToInt64() & (align-1)) == 0); } /// /// Allocate an aligned memory buffer. /// /// A pointer to a buffer aligned. /// /// The buffer must have been allocated with . /// public unsafe static void FreeMemory(IntPtr alignedBuffer) { if (alignedBuffer == IntPtr.Zero) return; Marshal.FreeHGlobal(((IntPtr*) alignedBuffer)[-1]); } /// /// Converts a pointer to a null-terminating string up to maxLength characters to a .Net string. /// /// The pointer to an ANSI null string. /// Maximum length of the string. /// The converted string. public static string PtrToStringAnsi(IntPtr pointer, int maxLength) { string managedString = Marshal.PtrToStringAnsi(pointer); // copy null-terminating unmanaged text from pointer to a managed string if (managedString != null && managedString.Length > maxLength) managedString = managedString.Substring(0, maxLength); return managedString; } /// /// Converts a pointer to a null-terminating string up to maxLength characters to a .Net string. /// /// The pointer to an Unicode null string. /// Maximum length of the string. /// The converted string. public static string PtrToStringUni(IntPtr pointer, int maxLength) { string managedString = Marshal.PtrToStringUni(pointer); // copy null-terminating unmanaged text from pointer to a managed string if (managedString != null && managedString.Length > maxLength) managedString = managedString.Substring(0, maxLength); return managedString; } /// /// Copies the contents of a managed String into unmanaged memory, converting into ANSI format as it copies. /// /// A managed string to be copied. /// The address, in unmanaged memory, to where s was copied, or IntPtr.Zero if s is null. public static unsafe IntPtr StringToHGlobalAnsi(string s) { return Marshal.StringToHGlobalAnsi(s); } /// /// Copies the contents of a managed String into unmanaged memory. /// /// A managed string to be copied. /// The address, in unmanaged memory, to where s was copied, or IntPtr.Zero if s is null. public static unsafe IntPtr StringToHGlobalUni(string s) { return Marshal.StringToHGlobalUni(s); } /// /// Copies the contents of a managed String into unmanaged memory using /// /// A managed string to be copied. /// The address, in unmanaged memory, to where s was copied, or IntPtr.Zero if s is null. public static unsafe IntPtr StringToCoTaskMemUni(string s) { if (s == null) { return IntPtr.Zero; } int num = (s.Length + 1) * 2; if (num < s.Length) { throw new ArgumentOutOfRangeException("s"); } IntPtr ptr2 = Marshal.AllocCoTaskMem(num); if (ptr2 == IntPtr.Zero) { throw new OutOfMemoryException(); } CopyStringToUnmanaged(ptr2, s); return ptr2; } private unsafe static void CopyStringToUnmanaged(IntPtr ptr, string str) { fixed (char* pStr = str) { CopyMemory(ptr, new IntPtr(pStr), (str.Length + 1 ) * 2); } } /// /// Gets the IUnknown from object. Similar to but accept null object /// by returning an IntPtr.Zero IUnknown pointer. /// /// The managed object. /// An IUnknown pointer to a managed object. public static IntPtr GetIUnknownForObject(object obj) { IntPtr objPtr = obj == null ? IntPtr.Zero : Marshal.GetIUnknownForObject(obj); //if (obj is ComObject && ((ComObject)obj).NativePointer == IntPtr.Zero) // (((ComObject)obj).NativePointer) = objPtr; return objPtr; } /// /// Gets an object from an IUnknown pointer. Similar to but accept IntPtr.Zero /// by returning a null object. /// /// an IUnknown pointer to a managed object. /// The managed object. public static object GetObjectForIUnknown(IntPtr iunknownPtr) { return iunknownPtr == IntPtr.Zero ? null : Marshal.GetObjectForIUnknown(iunknownPtr); } /// /// String helper join method to display an array of object as a single string. /// /// The separator. /// The array. /// A string with array elements separated by the separator. public static string Join(string separator, T[] array) { var text = new StringBuilder(); if (array != null) { for (int i = 0; i < array.Length; i++) { if (i > 0) text.Append(separator); text.Append(array[i]); } } return text.ToString(); } /// /// String helper join method to display an enumerable of object as a single string. /// /// The separator. /// The enumerable. /// A string with array elements separated by the separator. public static string Join(string separator, IEnumerable elements) { var elementList = new List(); foreach (var element in elements) elementList.Add(element.ToString()); var text = new StringBuilder(); for (int i = 0; i < elementList.Count; i++) { var element = elementList[i]; if (i > 0) text.Append(separator); text.Append(element); } return text.ToString(); } /// /// String helper join method to display an enumerable of object as a single string. /// /// The separator. /// The enumerable. /// A string with array elements separated by the separator. public static string Join(string separator, IEnumerator elements) { var elementList = new List(); while (elements.MoveNext()) elementList.Add(elements.Current.ToString()); var text = new StringBuilder(); for (int i = 0; i < elementList.Count; i++) { var element = elementList[i]; if (i > 0) text.Append(separator); text.Append(element); } return text.ToString(); } /// /// Converts a blob to a string. /// /// A blob. /// A string extracted from a blob. public static string BlobToString(Blob blob) { if (blob == null) return null; string output; output = Marshal.PtrToStringAnsi(blob.BufferPointer); blob.Dispose(); return output; } /// /// Equivalent to IntPtr.Add method from 3.5+ .NET Framework. /// Adds an offset to the value of a pointer. /// /// A native pointer. /// The offset to add (number of bytes). /// A new pointer that reflects the addition of offset to pointer. public unsafe static IntPtr IntPtrAdd(IntPtr ptr, int offset) { return new IntPtr(((byte*) ptr) + offset); } /// /// Read stream to a byte[] buffer. /// /// Input stream. /// A byte[] buffer. public static byte[] ReadStream(Stream stream) { int readLength = 0; return ReadStream(stream, ref readLength); } /// /// Read stream to a byte[] buffer. /// /// Input stream. /// Length to read. /// A byte[] buffer. public static byte[] ReadStream(Stream stream, ref int readLength) { Debug.Assert(stream != null); Debug.Assert(stream.CanRead); int num = readLength; Debug.Assert(num <= (stream.Length - stream.Position)); if (num == 0) readLength = (int) (stream.Length - stream.Position); num = readLength; Debug.Assert(num >= 0); if (num == 0) return new byte[0]; byte[] buffer = new byte[num]; int bytesRead = 0; if (num > 0) { do { bytesRead += stream.Read(buffer, bytesRead, readLength - bytesRead); } while (bytesRead < readLength); } return buffer; } /// /// Compares two collection, element by elements. /// /// A "from" enumerator. /// A "to" enumerator. /// true if lists are identical, false otherwise. public static bool Compare(IEnumerable left, IEnumerable right) { if (ReferenceEquals(left, right)) return true; if (ReferenceEquals(left, null) || ReferenceEquals(right, null)) return false; return Compare(left.GetEnumerator(), right.GetEnumerator()); } /// /// Compares two collection, element by elements. /// /// A "from" enumerator. /// A "to" enumerator. /// true if lists are identical; otherwise, false. public static bool Compare(IEnumerator leftIt, IEnumerator rightIt) { if (ReferenceEquals(leftIt, rightIt)) return true; if (ReferenceEquals(leftIt, null) || ReferenceEquals(rightIt, null)) return false; bool hasLeftNext; bool hasRightNext; while (true) { hasLeftNext = leftIt.MoveNext(); hasRightNext = rightIt.MoveNext(); if (!hasLeftNext || !hasRightNext) break; if (!Equals(leftIt.Current, rightIt.Current)) return false; } // If there is any left element if (hasLeftNext != hasRightNext) return false; return true; } /// /// Compares two collection, element by elements. /// /// The collection to compare from. /// The collection to compare to. /// true if lists are identical (but not necessarily of the same time); otherwise , false. public static bool Compare(ICollection left, ICollection right) { if (ReferenceEquals(left, right)) return true; if (ReferenceEquals(left, null) || ReferenceEquals(right, null)) return false; if (left.Count != right.Count) return false; int count = 0; var leftIt = left.GetEnumerator(); var rightIt = right.GetEnumerator(); while (leftIt.MoveNext() && rightIt.MoveNext()) { if (!Equals(leftIt.Current, rightIt.Current)) return false; count++; } // Just double check to make sure that the iterator actually returns // the exact number of elements if (count != left.Count) return false; return true; } /// /// Gets the custom attribute. /// /// Type of the custom attribute. /// The member info. /// if set to true [inherited]. /// The custom attribute or null if not found. public static T GetCustomAttribute(MemberInfo memberInfo, bool inherited = false) where T : Attribute { return memberInfo.GetCustomAttribute(inherited); } /// /// Gets the custom attributes. /// /// Type of the custom attribute. /// The member info. /// if set to true [inherited]. /// The custom attribute or null if not found. public static IEnumerable GetCustomAttributes(MemberInfo memberInfo, bool inherited = false) where T : Attribute { return memberInfo.GetCustomAttributes(inherited); } /// /// Determines whether fromType can be assigned to toType. /// /// To type. /// From type. /// /// true if [is assignable from] [the specified to type]; otherwise, false. /// public static bool IsAssignableFrom(Type toType, Type fromType) { return toType.GetTypeInfo().IsAssignableFrom(fromType.GetTypeInfo()); } /// /// Determines whether the specified type to test is an enum. /// /// The type to test. /// /// true if the specified type to test is an enum; otherwise, false. /// public static bool IsEnum(Type typeToTest) { return typeToTest.GetTypeInfo().IsEnum; } /// /// Determines whether the specified type to test is a value type. /// /// The type to test. /// /// true if the specified type to test is a value type; otherwise, false. /// public static bool IsValueType(Type typeToTest) { return typeToTest.GetTypeInfo().IsValueType; } private static MethodInfo GetMethod(Type type, string name, Type[] typeArgs) { #if BEFORE_NET45 foreach( var method in type.GetTypeInfo().GetMethods(BindingFlags.Public|BindingFlags.Instance)) { if(method.Name != name) { continue; } #else foreach( var method in type.GetTypeInfo().GetDeclaredMethods(name)) { #endif if ( method.GetParameters().Length == typeArgs.Length) { var parameters = method.GetParameters(); bool methodFound = true; for (int i = 0; i < typeArgs.Length; i++) { if (parameters[i].ParameterType != typeArgs[i]) { methodFound = false; break; } } if (methodFound) { return method; } } } return null; } /// /// Builds a fast property getter from a type and a property info. /// /// Type of the getter. /// Type of the custom effect. /// The property info to get the value from. /// A compiled delegate. public static GetValueFastDelegate BuildPropertyGetter(Type customEffectType, PropertyInfo propertyInfo) { var valueParam = Expression.Parameter(typeof(T).MakeByRefType()); var objectParam = Expression.Parameter(typeof(object)); var castParam = Expression.Convert(objectParam, customEffectType); var propertyAccessor = Expression.Property(castParam, propertyInfo); Expression convertExpression; if (propertyInfo.PropertyType == typeof(bool)) { // Convert bool to int: effect.Property ? 1 : 0 convertExpression = Expression.Condition(propertyAccessor, Expression.Constant(1), Expression.Constant(0)); } else { convertExpression = Expression.Convert(propertyAccessor, typeof(T)); } return Expression.Lambda>(Expression.Assign(valueParam, convertExpression), objectParam, valueParam).Compile(); } /// /// Builds a fast property setter from a type and a property info. /// /// Type of the setter. /// Type of the custom effect. /// The property info to set the value to. /// A compiled delegate. public static SetValueFastDelegate BuildPropertySetter(Type customEffectType, PropertyInfo propertyInfo) { var valueParam = Expression.Parameter(typeof(T).MakeByRefType()); var objectParam = Expression.Parameter(typeof(object)); var castParam = Expression.Convert(objectParam, customEffectType); var propertyAccessor = Expression.Property(castParam, propertyInfo); Expression convertExpression; if (propertyInfo.PropertyType == typeof(bool)) { // Convert int to bool: value != 0 convertExpression = Expression.NotEqual(valueParam, Expression.Constant(0)); } else { convertExpression = Expression.Convert(valueParam, propertyInfo.PropertyType); } return Expression.Lambda>(Expression.Assign(propertyAccessor, convertExpression), objectParam, valueParam).Compile(); } /// /// Finds an explicit conversion between a source type and a target type. /// /// Type of the source. /// Type of the target. /// The method to perform the conversion. null if not found. private static MethodInfo FindExplicitConverstion(Type sourceType, Type targetType) { // No need for cast for similar source and target type if (sourceType == targetType) return null; var methods = new List(); var tempType = sourceType; while (tempType != null) { #if BEFORE_NET45 methods.AddRange(tempType.GetTypeInfo().GetMethods(BindingFlags.Public)); //target methods will be favored in the search #else methods.AddRange(tempType.GetTypeInfo().DeclaredMethods); //target methods will be favored in the search #endif tempType = tempType.GetTypeInfo().BaseType; } tempType = targetType; while (tempType != null) { #if BEFORE_NET45 methods.AddRange(tempType.GetTypeInfo().GetMethods(BindingFlags.Public)); //target methods will be favored in the search #else methods.AddRange(tempType.GetTypeInfo().DeclaredMethods); //target methods will be favored in the search #endif tempType = tempType.GetTypeInfo().BaseType; } foreach (MethodInfo mi in methods) { if (mi.Name == "op_Explicit") //will return target and take one parameter if (mi.ReturnType == targetType) if (IsAssignableFrom(mi.GetParameters()[0].ParameterType, sourceType)) return mi; } return null; } [Flags] public enum CLSCTX : uint { ClsctxInprocServer = 0x1, ClsctxInprocHandler = 0x2, ClsctxLocalServer = 0x4, ClsctxInprocServer16 = 0x8, ClsctxRemoteServer = 0x10, ClsctxInprocHandler16 = 0x20, ClsctxReserved1 = 0x40, ClsctxReserved2 = 0x80, ClsctxReserved3 = 0x100, ClsctxReserved4 = 0x200, ClsctxNoCodeDownload = 0x400, ClsctxReserved5 = 0x800, ClsctxNoCustomMarshal = 0x1000, ClsctxEnableCodeDownload = 0x2000, ClsctxNoFailureLog = 0x4000, ClsctxDisableAaa = 0x8000, ClsctxEnableAaa = 0x10000, ClsctxFromDefaultContext = 0x20000, ClsctxInproc = ClsctxInprocServer | ClsctxInprocHandler, ClsctxServer = ClsctxInprocServer | ClsctxLocalServer | ClsctxRemoteServer, ClsctxAll = ClsctxServer | ClsctxInprocHandler } #if WINDOWS_UWP [StructLayout(LayoutKind.Sequential)] public struct MultiQueryInterface { public IntPtr InterfaceIID; public IntPtr IUnknownPointer; public Result ResultCode; }; [DllImport("api-ms-win-core-com-l1-1-0.dll", ExactSpelling = true, EntryPoint = "CoCreateInstanceFromApp", PreserveSig = true)] private static extern Result CoCreateInstanceFromApp([In, MarshalAs(UnmanagedType.LPStruct)] Guid rclsid, IntPtr pUnkOuter, CLSCTX dwClsContext, IntPtr reserved, int countMultiQuery, ref MultiQueryInterface query); internal unsafe static void CreateComInstance(Guid clsid, CLSCTX clsctx, Guid riid, ComObject comObject) { MultiQueryInterface localQuery = new MultiQueryInterface() { InterfaceIID = new IntPtr(&riid), IUnknownPointer = IntPtr.Zero, ResultCode = 0, }; var result = CoCreateInstanceFromApp(clsid, IntPtr.Zero, clsctx, IntPtr.Zero, 1, ref localQuery); result.CheckError(); localQuery.ResultCode.CheckError(); comObject.NativePointer = localQuery.IUnknownPointer; } internal unsafe static bool TryCreateComInstance(Guid clsid, CLSCTX clsctx, Guid riid, ComObject comObject) { MultiQueryInterface localQuery = new MultiQueryInterface() { InterfaceIID = new IntPtr(&riid), IUnknownPointer = IntPtr.Zero, ResultCode = 0, }; var result = CoCreateInstanceFromApp(clsid, IntPtr.Zero, clsctx, IntPtr.Zero, 1, ref localQuery); comObject.NativePointer = localQuery.IUnknownPointer; return result.Success && localQuery.ResultCode.Success; } #else [DllImport("ole32.dll", ExactSpelling = true, EntryPoint = "CoCreateInstance", PreserveSig = true)] private static extern Result CoCreateInstance([In, MarshalAs(UnmanagedType.LPStruct)] Guid rclsid, IntPtr pUnkOuter, CLSCTX dwClsContext, [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid, out IntPtr comObject); internal static void CreateComInstance(Guid clsid, CLSCTX clsctx, Guid riid, ComObject comObject) { IntPtr pointer; var result = CoCreateInstance(clsid, IntPtr.Zero, clsctx, riid, out pointer); result.CheckError(); comObject.NativePointer = pointer; } internal static bool TryCreateComInstance(Guid clsid, CLSCTX clsctx, Guid riid, ComObject comObject) { IntPtr pointer; var result = CoCreateInstance(clsid, IntPtr.Zero, clsctx, riid, out pointer); comObject.NativePointer = pointer; return result.Success; } #endif /// Determines the concurrency model used for incoming calls to objects created by this thread. This concurrency model can be either apartment-threaded or multi-threaded. public enum CoInit { /// /// Initializes the thread for apartment-threaded object concurrency. /// MultiThreaded = 0x0, /// /// Initializes the thread for multi-threaded object concurrency. /// ApartmentThreaded = 0x2, /// /// Disables DDE for OLE1 support. /// DisableOle1Dde = 0x4, /// /// Trade memory for speed. /// SpeedOverMemory = 0x8 } #if WINDOWS_UWP [DllImport("api-ms-win-core-handle-l1-1-0.dll", EntryPoint = "CloseHandle", SetLastError = true)] internal static extern bool CloseHandle(IntPtr handle); #else [DllImport("kernel32.dll", EntryPoint = "CloseHandle", SetLastError = true)] internal static extern bool CloseHandle(IntPtr handle); #endif /// /// Gets the proc address of a DLL. /// /// The handle. /// The DLL function to import. /// If the function was not found. /// Pointer to address of the exported function or variable. public static IntPtr GetProcAddress(IntPtr handle, string dllFunctionToImport) { IntPtr result = GetProcAddress_(handle, dllFunctionToImport); if (result == IntPtr.Zero) throw new SharpDXException(dllFunctionToImport); return result; } #if WINDOWS_UWP [DllImport("api-ms-win-core-libraryloader-l1-1-1.dll", EntryPoint = "GetProcAddress", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] static extern IntPtr GetProcAddress_(IntPtr hModule, string procName); #else // http://www.pinvoke.net/default.aspx/kernel32.getprocaddress // http://stackoverflow.com/questions/3754264/c-sharp-getprocaddress-returns-zero [DllImport("kernel32", EntryPoint = "GetProcAddress", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] static extern IntPtr GetProcAddress_(IntPtr hModule, string procName); #endif /// /// Compute a FNV1-modified Hash from Fowler/Noll/Vo Hash improved version. /// /// Data to compute the hash from. /// A hash value. public static int ComputeHashFNVModified(byte[] data) { const uint p = 16777619; uint hash = 2166136261; foreach (byte b in data) hash = (hash ^ b) * p; hash += hash << 13; hash ^= hash >> 7; hash += hash << 3; hash ^= hash >> 17; hash += hash << 5; return unchecked((int)hash); } /// /// Safely dispose a reference if not null, and set it to null after dispose. /// /// The type of COM interface to dispose. /// Object to dispose. /// /// The reference will be set to null after dispose. /// public static void Dispose(ref T comObject) where T : class, IDisposable { if (comObject != null) { comObject.Dispose(); comObject = null; } } /// /// Transforms an to an array of T. /// /// Type of the element /// The enumerable source. /// an array of T public static T[] ToArray(IEnumerable source) { return new Buffer(source).ToArray(); } /// /// Test if there is an element in this enumeration. /// /// Type of the element /// The enumerable source. /// true if there is an element in this enumeration, false otherwise public static bool Any(IEnumerable source) { return source.GetEnumerator().MoveNext(); } /// /// Select elements from an enumeration. /// /// The type of the T source. /// The type of the T result. /// The source. /// The selector. /// A enumeration of selected values public static IEnumerable SelectMany(IEnumerable source, Func> selector) { foreach (TSource sourceItem in source) { foreach (TResult result in selector(sourceItem)) yield return result; } } /// /// Selects distinct elements from an enumeration. /// /// The type of the T source. /// The source. /// The comparer. /// A enumeration of selected values public static IEnumerable Distinct(IEnumerable source, IEqualityComparer comparer = null) { if (comparer == null) comparer = EqualityComparer.Default; // using Dictionary is not really efficient but easy to implement var values = new Dictionary(comparer); foreach (TSource sourceItem in source) { if (!values.ContainsKey(sourceItem)) { values.Add(sourceItem, null); yield return sourceItem; } } } internal struct Buffer { internal TElement[] items; internal int count; internal Buffer(IEnumerable source) { var array = (TElement[])null; int length = 0; var collection = source as ICollection; if (collection != null) { length = collection.Count; if (length > 0) { array = new TElement[length]; collection.CopyTo(array, 0); } } else { foreach (TElement element in source) { if (array == null) array = new TElement[4]; else if (array.Length == length) { var elementArray = new TElement[checked(length * 2)]; Array.Copy(array, 0, elementArray, 0, length); array = elementArray; } array[length] = element; ++length; } } items = array; count = length; } internal TElement[] ToArray() { if (count == 0) return new TElement[0]; if (items.Length == count) return items; var elementArray = new TElement[count]; Array.Copy(items, 0, elementArray, 0, count); return elementArray; } } /// /// Determines whether the type inherits from the specified type (used to determine a type without using an explicit type instance). /// /// The type. /// Name of the parent type to find in inheritance hierarchy of type. /// true if the type inherits from the specified type; otherwise, false. public static bool IsTypeInheritFrom(Type type, string parentType) { while (type != null) { if (type.FullName == parentType) { return true; } type = type.GetTypeInfo().BaseType; } return false; } } }