I have an external library that takes an IntPtr. Is there any safe way to do this...
int BytesWritten = 0;
Output.WriteBytes(buffer, new IntPtr(&BytesWritten));
...without having to use 'unsafe' code? I'm not that familiar with IntPtrs, but I'd like to do something like this:
fixed int BytesWritten = 0;
Output.WriteBytes(buffer, IntPtr.GetSafeIntPtr(ref BytesWritten));
...in such a way that I don't need to compile with /unsafe.
I can't change the WriteBytes function, it's an external function.
It seems like there should be some sort of cast between 'ref int' and IntPtr, but I have not had luck finding it.
I assume that Output.WriteBytes is a [DllImport] method. Can you post the declaration?
You should be able to avoid the pointer by declaring the last parameter as out int instead of IntPtr -- let the P/Invoke marshaller do the rest.
Yes, there is. You can use P/Invoke for your code. It will create the pointer for you automagically. Something like this:
[DllImport("yourlib", SetLastError=true)]
static extern bool WriteBytes(
[MarshalAs(UnmanagedType.LPArray)]
byte [] buffer,
ref int BytesWritten);
(I added the array as a bonus). More info on P/Invoke can be found, with gazillion examples, at pinvoke.net.
Each parameter above can take out, in and ref. Out and ref parameters are translated as pointers, where an ref-parameter is two-way.
Here is a class that will provide you with a safe IntPtr implementation. It derives from the SafeHandleZeroOrMinusOneIsInvalid class, provided by the .NET framework.
/// <summary>
/// IntPtr wrapper which can be used as result of
/// Marshal.AllocHGlobal operation.
/// Call Marshal.FreeHGlobal when disposed or finalized.
/// </summary>
class HGlobalSafeHandle : SafeHandleZeroOrMinusOneIsInvalid
{
/// <summary>
/// Creates new instance with given IntPtr value
/// </summary>
public HGlobalSafeHandle(IntPtr ptr) : base(ptr, true)
{
}
/// <summary>
/// Creates new instance with zero IntPtr
/// </summary>
public HGlobalSafeHandle() : base(IntPtr.Zero, true)
{
}
/// <summary>
/// Creates new instance which allocates unmanaged memory of given size
/// Can throw OutOfMemoryException
/// </summary>
public HGlobalSafeHandle(int size) :
base(Marshal.AllocHGlobal(size), true)
{
}
/// <summary>
/// Allows to assign IntPtr to HGlobalSafeHandle
/// </summary>
public static implicit operator HGlobalSafeHandle(IntPtr ptr)
{
return new HGlobalSafeHandle(ptr);
}
/// <summary>
/// Allows to use HGlobalSafeHandle as IntPtr
/// </summary>
public static implicit operator IntPtr(HGlobalSafeHandle h)
{
return h.handle;
}
/// <summary>
/// Called when object is disposed or finalized.
/// </summary>
override protected bool ReleaseHandle()
{
Marshal.FreeHGlobal(handle);
return true;
}
/// <summary>
/// Defines invalid (null) handle value.
/// </summary>
public override bool IsInvalid
{
get
{
return (handle == IntPtr.Zero);
}
}
}
Related
I use an XOR based implementation in the GetHashCode implementation of most of my equatable types.
I've read several posts explaining why it is not the best solution so I decided to implement GetHashCode as suggested by Jon Skeet:
unchecked // Overflow is fine, just wrap
{
int hash = 17;
hash = hash * 23 + field1.GetHashCode();
hash = hash * 23 + field2.GetHashCode();
hash = hash * 23 + field3.GetHashCode();
return hash;
}
Since the code is likely to be similar in most implementations, I tried to build a helper class to calculate hash codes for all my classes. It should be an easy thing to do but one of the main constraints with GetHashCode is it has to be fast. Therefore any implementation involving allocation is probably a no go (for instance, the use of a non static class).
Ideally a call to such a method would look like:
public override GetHashCode() => HashCodeCalculator.Calculate(X, Y, Z);
And have all the logic (unchecked + primes + null check...). But the use of a params parameter implicitly creates an array.
Is it best to duplicate the hashing algorithm in each class instead? Or is a class like the following as efficient?
public static class HashCalculator
{
private const int _seed = 5923;
private const int _multiplier = 7481;
public static int Add(object value) => Add(_seed, value);
public static int Add(int current, object value)
{
int valueHashCode = (value != null) ? value.GetHashCode() : 0;
unchecked
{
return (current * _multiplier) + valueHashCode;
}
}
}
which can then be used like this:
public override int GetHashCode()
{
int result = HashCalculator.Add(Prop1);
result = HashCalculator.Add(result, Prop2);
return result;
}
You can create overloads for various small fixed numbers of parameters (2, 3, 4, etc. until you decide to stop), in order to avoid the array allocation, and then have a params overload that only ever needs to be used when there is a particularly large number of operands, at which point the overhead of the array allocation is less likely to be a problem (as it'll be a smaller percentage of the work done).
I can see why it is so tempting to have some kind of helper tool to calc hashes, but in this case efficiency is in great contradiction to convenience. You are trying to have a cookie and eat it and the answer depends on how much cookie you are willing to left over :)
One additional method call? Then it should have signature simmilar to
int HashCode(params int subhashcodes)
but invoking it will be ugly because you need to provide hashcodes of fields as parameters.
One method call and boxing? Then you can change int to object in previous signature to call fields hashcodes inside your method (I'm not fully sure that there will be no boxing in first case - feel free to correct me)
Personally I will stick to writing it by hand (or by Resharper).
After benchmarking it appears that using a struct like the following is almost as efficient as XORing and nicely encapsulates hash codes calculation.
/// <summary>
/// Calculates a hash code based on multiple hash codes.
/// </summary>
public struct HashCode
{
private const int _seed = 5923;
private const int _multiplier = 7481;
/// <summary>
/// Builds a new hash code.
/// </summary>
/// <returns>The built hash code.</returns>
public static HashCode Build() => new HashCode(_seed);
/// <summary>
/// Constructor from a hash value.
/// </summary>
/// <param name="value">Hash value.</param>
private HashCode(int value)
{
_value = value;
}
/// <summary>
/// Builds a new hash code and initializes it from a hash code source.
/// </summary>
/// <param name="hashCodeSource">Item from which a hash code can be extracted (using GetHashCode).</param>
public HashCode(object hashCodeSource)
{
int sourceHashCode = GetHashCode(hashCodeSource);
_value = AddValue(_seed, sourceHashCode);
}
private readonly int _value;
/// <summary>
/// Returns the hash code for a given hash code source (0 if the source is null).
/// </summary>
/// <param name="hashCodeSource">Item from which a hash code can be extracted (using GetHashCode).</param>
/// <returns>The hash code.</returns>
private static int GetHashCode(object hashCodeSource) => (hashCodeSource != null) ? hashCodeSource.GetHashCode() : 0;
/// <summary>
/// Adds a new hash value to a hash code.
/// </summary>
/// <param name="currentValue">Current hash value.</param>
/// <param name="valueToAdd">Value to add.</param>
/// <returns>The new hash value.</returns>
private static int AddValue(int currentValue, int valueToAdd)
{
unchecked
{
return (currentValue * _multiplier) + valueToAdd;
}
}
/// <summary>
/// Adds an object's hash code.
/// </summary>
/// <param name="hashCode">Hash code to which the object's hash code has to be added.</param>
/// <param name="hashCodeSource">Item from which a hash code can be extracted (using GetHashCode).</param>
/// <returns>The updated hash instance.</returns>
public static HashCode operator +(HashCode hashCode, object hashCodeSource)
{
int sourceHashCode = GetHashCode(hashCodeSource);
int newHashValue = AddValue(hashCode._value, sourceHashCode);
return new HashCode(newHashValue);
}
/// <summary>
/// Implicit cast operator to int.
/// </summary>
/// <param name="hashCode">Hash code to convert.</param>
public static implicit operator int(HashCode hashCode) => hashCode._value;
}
which can be used like this:
public override int GetHashCode() => new HashCode(Prop1) + Prop2;
EDIT:
.net core now has such a HashCode struct.
I want to make a really generic class to save objects to a WCF service. I get an object of any type and analyse the objects properties via reflection. When saving the object into the service context, I need to know, if I have to call the SetLink(...) method of the DataServiceContext for a property or not.
Therefore I need a method to find out, if I have to call SetLink(...) or not. I already tried to doit by myself:
private bool IsLinkedProperty(PropertyInfo propertyInfo)
{
return (propertyInfo != null) && propertyInfo.PropertyType.IsClass;
}
But this function does not work for string-properties and maybe for others too. Does anybody has a fitting function for this?
I ended up with the following solution. I found a hint in the qestion of Nathan Ridley:
/// <summary>
/// Helper class for analyzing a type.
/// </summary>
public static class TypeAnalyzer
{
/// <summary>
/// Calculates if the given type is a "simple" type.
/// </summary>
/// <param name="type">Type to be checked for simplicity.</param>
/// <returns>True, if the type is "simple";false otherwise.</returns>
/// <remarks>
/// The following types are assumed to be simple:
/// <list type="*">
/// <item>string</item>
/// <item>int</item>
/// <item>decimal</item>
/// <item>float</item>
/// <item><see cref="StringComparison"/> (enum type)</item>
/// <item>int? (nullable simple types)</item>
/// </list>
/// The following types are not simple:
/// <list type="*">
/// <item>Point (struct)</item>
/// <item>Point? (nullable struct)</item>
/// <item>StringBuilder (class)</item>
/// </list>
/// </remarks>
public static bool IsSimple(this Type type)
{
if (IsNullableType(type))
return IsNestedTypeSimple(type);
return type.IsPrimitive
|| type.IsEnum
|| type.Equals(typeof(string))
|| type.Equals(typeof(decimal))
|| type.Equals(typeof(DateTime))
|| type.Equals(typeof(Guid));
}
private static bool IsNestedTypeSimple(Type type)
{
var nestedType = Nullable.GetUnderlyingType(type);
return IsSimple(nestedType);
}
private static bool IsNullableType(Type type)
{
return Nullable.GetUnderlyingType(type) != null;
}
}
Test cases written in NUnit are:
[TestFixture]
public class TypeAnalyzerTests
{
[TestCase(typeof(string), true)]
[TestCase(typeof(int), true)]
[TestCase(typeof(decimal), true)]
[TestCase(typeof(float), true)]
[TestCase(typeof(StringComparison), true)]
[TestCase(typeof(int?), true)]
[TestCase(typeof(decimal?), true)]
[TestCase(typeof(StringComparison?), true)]
[TestCase(typeof(object), false)]
[TestCase(typeof(Point), false)]
[TestCase(typeof(Point?), false)]
[TestCase(typeof(StringBuilder), false)]
[TestCase(typeof(DateTime), true)]
[TestCase(typeof(Guid), true)]
[TestCase(typeof(Guid?), true)]
public void IsSimple_WhenCalledForType_ReturnsExpectedResult(Type type, bool expectedResult)
{
var isSimple = TypeAnalyzer.IsSimple(type);
Assert.That(isSimple, Is.EqualTo(expectedResult));
}
}
Finally I changed the in the question mentioned method to:
private bool IsLinkedProperty()
{
return (_propertyInfo != null) && !_propertyInfo.PropertyType.IsSimple();
}
I'm writing a wrapper for a C dll. Various C functions are wrapped for C# applicatons. Now consider some simplified part of the wrapper below.
public enum ErrorCode
{
OK = 0,
...
...
}
public class AppException: ApplicationException
{
public AppException(ErrorCode errorCode) : base()
{
error = errorCode;
}
public ErrorCode error { get; private set; }
}
public class A
{
public ErrorCode last_ret;
private IntPtr datap;
public A(string filename)
{
last_ret = (ErrorCode)ClibDllFunc1(filename, out datap);
if (last_ret != ErrorCode.OK)
throw new AppException(last_ret);
// go on processing
last_ret = (ErrorCode)ClibDllFunc2(datap);
if (last_ret != ErrorCode.OK)
throw new AppException(last_ret);
}
public void getSize(out int sz)
{
last_ret = (ErrorCode)ClibDllFunc3(datap, out sz);
if (last_ret != ErrorCode.OK)
throw new AppException(last_ret);
}
// ...
// many functions like these, all working by calling c/c++ dll functions
// with different number and types of parameters
}
[DllImport("clibrary.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
static extern internal int ClibDllFunc1(string filename, out IntPtr data);
// ... other C function declarations follow similarly
As you can see, the wrapper calls various C functions. All C functions return integer as the status code (an ErrorCode), and the wrapper has to check this return code and throw an application defined exception if the C function fails. This has to be done exactly the same way for all C function calls. Only the function name and parameters change but the 3 line calling-block is the same. It looks really cheap in this form as copy/pasted 3-line blocks of function calls.
In C#, is there a way to simplify and encapsulate the "call, check return code, throw exception" cycle in a simpler and more compact way?
For reference (actually this is what I'd like to do to simplify the calls); in C/C++ we can define a macro like this one:
#define SAFE_CALL(call) do{ if((last_ret = (ErrorCode)call) != OK) throw AppException(last_ret); }while(0)
and call like this:
SAFE_CALL(ClibDllFunc1(filename, &datap));
SAFE_CALL(ClibDllFunc2(datap));
SAFE_CALL(ClibDllFunc3(datap, &sz));
Edit
Rereading your problem, I answered the wrong question. What you really want is a function CheckErrorCode that takes an int, and then simply pass the result of the native call.
/// <summary>
/// Takes the result code from invoking a native function. If the result is
/// not ErrorCode.OK, throws an AppException with that error code.
/// </summary>
/// <param name="returnCodeInt">
/// The return code of a native method call, as an integer.
/// Will be cast to ErrorCode.
/// </param>
private static void CheckErrorCode(int returnCodeInt)
{
ErrorCode returnCode = (ErrorCode)returnCodeInt;
if(returnCode != ErrorCode.OK)
{
throw new AppException(returnCode);
}
}
public void getSize(out int sz)
{
CheckErrorCode(ClibDllFunc3(datap, out sz));
}
Original text (how to simulate macros with lambdas)
The fact that lambda syntax in C# is so terse means you can use a Func<T> in a similar way to macros. Try something like this:
/// <summary>
/// Calls a function's native implementation, then checks if the error code
/// is not ErrorCode.Ok. If it is, throws an AppException.
/// </summary>
/// <param name="nativeCall">
/// A function that returns the status code as an int.
/// </param>
private static void CheckErrorCode(Func<int> nativeCall)
{
var returnCode = (ErrorCode)nativeCall();
if(returnCode != ErrorCode.OK)
{
throw new AppException(returnCode);
}
}
You can then call it with:
public void getSize(out int sz)
{
// drawback: compiler can't check that sz is always written.
sz = 0;
CheckErrorCode(() => ClibDllFunc3(datap, out sz));
}
The lambda creates what's known as a closure. This is a way to pull the logic of calling ClibDllFunc3 (specific to this function) away from the logic of handling its results (which is standard across all your DLL functions). Unlike many closures, this one is called immediately.
This is from the midi-dot-net http://code.google.com/p/midi-dot-net/ library:
static class Win32API
{ ...
#region Non-Typesafe Bindings
// The bindings in this section are not typesafe, so we make them private
// and provide typesafe variants
[DllImport("winmm.dll", SetLastError = true)]
private static extern MMRESULT midiOutOpen(out HMIDIOUT lphmo,
UIntPtr uDeviceID, MidiOutProc dwCallback, UIntPtr dwCallbackInstance,
MidiOpenFlags dwFlags);
...
/// <summary>
/// Opens a MIDI output device.
/// </summary>
/// NOTE: This is adapted from the original Win32 function in order
/// to make it typesafe.
///
/// Win32 docs: http://msdn.microsoft.com/en-us/library/ms711632(VS.85).aspx
public static MMRESULT midiOutOpen(out HMIDIOUT lphmo,
UIntPtr uDeviceID, MidiOutProc dwCallback, UIntPtr dwCallbackInstance)
{
return midiOutOpen(out lphmo, uDeviceID, dwCallback, dwCallbackInstance,
dwCallback == null ? MidiOpenFlags.CALLBACK_NULL :
MidiOpenFlags.CALLBACK_FUNCTION);
}
How does this last function make the win32 call type-safe?
Adapting my comment as an answer...
I don't know what makes the revised version type safe, but it is a safer (less error-prone) call.
It is possible to call dll function midiOutOpen parameter with a null dwCallbackInstance with MidiOpenFlags = MidiOpenFlags.CALLBACK_FUNCTION. If the dll function does not check for null then it will cause some disturbance.
With the adopted function the midiOutOpen parameter is derived so no danger.
I don't know what SetLastError = true is but I would think the wrapper might have checked the LastError and acted appropriately (throw exception?)
What is SafeHandle? how does it differ from IntPtr? When should I use one? What are its advantages?
You should use a derivative of SafeHandle whenever possible where managed code is receiving an IntPtr from unmanaged code. While the name, general use, and even documentation of the SafeHandle class implies that it is only supposed to be used to contain Windows operating system handles, a few internal .NET framework classes such as Microsoft.Win32.SafeHandles.SafeLocalAllocHandle and those that derive from the publicly available abstract class System.Runtime.InteropServices.SafeBuffer also use it to guarantee that other unmanaged resources such as dynamically allocated structs and arrays are freed. In general, I believe that it is good practice to create a derivative of this class whenever an IntPtr is returned to managed code from unmanaged code even if it doesn't require cleanup.
The established purpose of a SafeHandle is to guarantee that even if the world is ending (e.g. an AppDomain is being unloaded or a StackOverflowException occurs) the .NET framework should make absolutely sure that the finalizer for the SafeHandle is called to close or deallocate the unmanaged entity being referred to by the wrapped IntPtr. The SafeHandle class achieves this by inheriting from the CriticalFinalizerObject class. Inheriting from this class does, however, place upon the inheritor the obligation of not totally screwing up the state of the process when the finalizer is called, which is likely why it is not often used for entities other than Windows operating system handles. The .NET framework also provides some weak finalization ordering so that it is safe to interact with a SafeHandle object in the finalizer of any class that does not inherit from CriticalFinalizerObject, but circumstances in which that is necessary should be few and far between.
Ideally, a SafeHandle-derived class should also be used to more safely interact with an unmanaged entity reference by encapsulating expected functionality within the derived class. A well-written class that inherits from SafeHandle should have a specific purpose in mind and should provide methods that are sufficient to prevent any developer using it for that purpose from ever needing to interact directly with the IntPtr it contains. Adding such methods also provides other developers with a clear idea of what the result of an unmanaged method call is to be used for in a managed context. A class that inherits from SafeHandle can be used for this even if no cleanup is required on the pointer that the unmanaged method returns by calling base(false) in the constructor for the class.
Two examples that use classes which derive from SafeHandle to safely clean up a reference to an unmanaged entity and encapsulate functionality related to the unmanaged entity are below. The first example is a more traditional scenario in which a user token returned by LogonUser is wrapped by an instance of the SafeTokenHandle class. This class will call CloseHandle on the token when the object is disposed or finalized. It also includes a method called GetWindowsIdentity that returns a WindowsIdentity object for the user represented by the user token. The second example uses Windows built-in function CommandLineToArgvW to parse a command line. This function returns a pointer to an array contained a contiguous block of memory that can be freed by a single call to LocalFree. The SafeLocalAllocWStrArray class (which inherits from class SafeLocalAllocArray which is also defined in this example) will call LocalFree on the array when object is disposed or finalized. It also includes a function that will copy the contents of the unmanaged array to a managed array.
static class Examples
{
static void Example1_SafeUserToken()
{
const string user = "SomeLocalUser";
const string domain = null;
const string password = "ExamplePassword";
NativeMethods.SafeTokenHandle userToken;
WindowsIdentity identity;
NativeMethods.LogonUser(user, domain, password, NativeMethods.LogonType.LOGON32_LOGON_INTERACTIVE, NativeMethods.LogonProvider.LOGON32_PROVIDER_DEFAULT, out userToken);
using (userToken)
{
// get a WindowsIdentity object for the user
// WindowsIdentity will duplicate the token, so it is safe to free the original token after this is called
identity = userToken.GetWindowsIdentity();
}
// impersonate the user
using (identity)
using (WindowsImpersonationContext impersonationContext = identity.Impersonate())
{
Console.WriteLine("I'm running as {0}!", Thread.CurrentPrincipal.Identity.Name);
}
}
static void Example2_SafeLocalAllocWStrArray()
{
const string commandLine = "/example /command";
int argc;
string[] args;
using (NativeMethods.SafeLocalAllocWStrArray argv = NativeMethods.CommandLineToArgvW(commandLine, out argc))
{
// CommandLineToArgvW returns NULL on failure; since SafeLocalAllocWStrArray inherits from
// SafeHandleZeroOrMinusOneIsInvalid, it will see this value as invalid
// if that happens, throw an exception containing the last Win32 error that occurred
if (argv.IsInvalid)
{
int lastError = Marshal.GetHRForLastWin32Error();
throw new Win32Exception(lastError, "An error occurred when calling CommandLineToArgvW.");
}
// the one unsafe aspect of this is that the developer calling this function must be trusted to
// pass in an array of length argc or specify the length of the copy as the value of argc
// if the developer does not do this, the array may end up containing some garbage or an
// AccessViolationException could be thrown
args = new string[argc];
argv.CopyTo(args);
}
for (int i = 0; i < args.Length; ++i)
{
Console.WriteLine("Argument {0}: {1}", i, args[i]);
}
}
}
/// <summary>
/// P/Invoke methods and helper classes used by this example.
/// </summary>
internal static class NativeMethods
{
// documentation: http://msdn.microsoft.com/en-us/library/windows/desktop/aa378184(v=vs.85).aspx
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool LogonUser(string lpszUsername, string lpszDomain, string lpszPassword, LogonType dwLogonType, LogonProvider dwLogonProvider, out SafeTokenHandle phToken);
// documentation: http://msdn.microsoft.com/en-us/library/windows/desktop/ms724211(v=vs.85).aspx
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool CloseHandle(IntPtr handle);
// documentation: http://msdn.microsoft.com/en-us/library/windows/desktop/bb776391(v=vs.85).aspx
[DllImport("shell32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern SafeLocalAllocWStrArray CommandLineToArgvW(string lpCmdLine, out int pNumArgs);
// documentation: http://msdn.microsoft.com/en-us/library/windows/desktop/aa366730(v=vs.85).aspx
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr LocalFree(IntPtr hLocal);
/// <summary>
/// Wraps a handle to a user token.
/// </summary>
public class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid
{
/// <summary>
/// Creates a new SafeTokenHandle. This constructor should only be called by P/Invoke.
/// </summary>
private SafeTokenHandle()
: base(true)
{
}
/// <summary>
/// Creates a new SafeTokenHandle to wrap the specified user token.
/// </summary>
/// <param name="arrayPointer">The user token to wrap.</param>
/// <param name="ownHandle"><c>true</c> to close the token when this object is disposed or finalized,
/// <c>false</c> otherwise.</param>
public SafeTokenHandle(IntPtr handle, bool ownHandle)
: base(ownHandle)
{
this.SetHandle(handle);
}
/// <summary>
/// Provides a <see cref="WindowsIdentity" /> object created from this user token. Depending
/// on the type of token, this can be used to impersonate the user. The WindowsIdentity
/// class will duplicate the token, so it is safe to use the WindowsIdentity object created by
/// this method after disposing this object.
/// </summary>
/// <returns>a <see cref="WindowsIdentity" /> for the user that this token represents.</returns>
/// <exception cref="InvalidOperationException">This object does not contain a valid handle.</exception>
/// <exception cref="ObjectDisposedException">This object has been disposed and its token has
/// been released.</exception>
public WindowsIdentity GetWindowsIdentity()
{
if (this.IsClosed)
{
throw new ObjectDisposedException("The user token has been released.");
}
if (this.IsInvalid)
{
throw new InvalidOperationException("The user token is invalid.");
}
return new WindowsIdentity(this.handle);
}
/// <summary>
/// Calls <see cref="NativeMethods.CloseHandle" /> to release this user token.
/// </summary>
/// <returns><c>true</c> if the function succeeds, <c>false otherwise</c>. To get extended
/// error information, call <see cref="Marshal.GetLastWin32Error"/>.</returns>
protected override bool ReleaseHandle()
{
return NativeMethods.CloseHandle(this.handle);
}
}
/// <summary>
/// A wrapper around a pointer to an array of Unicode strings (LPWSTR*) using a contiguous block of
/// memory that can be freed by a single call to LocalFree.
/// </summary>
public sealed class SafeLocalAllocWStrArray : SafeLocalAllocArray<string>
{
/// <summary>
/// Creates a new SafeLocalAllocWStrArray. This constructor should only be called by P/Invoke.
/// </summary>
private SafeLocalAllocWStrArray()
: base(true)
{
}
/// <summary>
/// Creates a new SafeLocalallocWStrArray to wrap the specified array.
/// </summary>
/// <param name="handle">The pointer to the unmanaged array to wrap.</param>
/// <param name="ownHandle"><c>true</c> to release the array when this object
/// is disposed or finalized, <c>false</c> otherwise.</param>
public SafeLocalAllocWStrArray(IntPtr handle, bool ownHandle)
: base(ownHandle)
{
this.SetHandle(handle);
}
/// <summary>
/// Returns the Unicode string referred to by an unmanaged pointer in the wrapped array.
/// </summary>
/// <param name="index">The index of the value to retrieve.</param>
/// <returns>the value at the position specified by <paramref name="index" /> as a string.</returns>
protected override string GetArrayValue(int index)
{
return Marshal.PtrToStringUni(Marshal.ReadIntPtr(this.handle + IntPtr.Size * index));
}
}
// This class is similar to the built-in SafeBuffer class. Major differences are:
// 1. This class is less safe because it does not implicitly know the length of the array it wraps.
// 2. The array is read-only.
// 3. The type parameter is not limited to value types.
/// <summary>
/// Wraps a pointer to an unmanaged array of objects that can be freed by calling LocalFree.
/// </summary>
/// <typeparam name="T">The type of the objects in the array.</typeparam>
public abstract class SafeLocalAllocArray<T> : SafeHandleZeroOrMinusOneIsInvalid
{
/// <summary>
/// Creates a new SafeLocalArray which specifies that the array should be freed when this
/// object is disposed or finalized.
/// <param name="ownsHandle"><c>true</c> to reliably release the handle during the finalization phase;
/// <c>false</c> to prevent reliable release (not recommended).</param>
/// </summary>
protected SafeLocalAllocArray(bool ownsHandle)
: base(ownsHandle)
{
}
/// <summary>
/// Converts the unmanaged object referred to by <paramref name="valuePointer" /> to a managed object
/// of type T.
/// </summary>
/// <param name="index">The index of the value to retrieve.</param>
/// <returns>the value at the position specified by <paramref name="index" /> as a managed object of
/// type T.</returns>
protected abstract T GetArrayValue(int index);
//
/// <summary>
/// Frees the wrapped array by calling LocalFree.
/// </summary>
/// <returns><c>true</c> if the call to LocalFree succeeds, <c>false</c> if the call fails.</returns>
protected override bool ReleaseHandle()
{
return (NativeMethods.LocalFree(this.handle) == IntPtr.Zero);
}
/// <summary>
/// Copies the unmanaged array to the specified managed array.
///
/// It is important that the length of <paramref name="array"/> be less than or equal to the length of
/// the unmanaged array wrapped by this object. If it is not, at best garbage will be read and at worst
/// an exception of type <see cref="AccessViolationException" /> will be thrown.
/// </summary>
/// <param name="array">The managed array to copy the unmanaged values to.</param>
/// <exception cref="ObjectDisposedException">The unmanaged array wrapped by this object has been
/// freed.</exception>
/// <exception cref="InvalidOperationException">The pointer to the unmanaged array wrapped by this object
/// is invalid.</exception>
/// <exception cref="ArgumentNullException"><paramref name="array"/> is null.</exception>
public void CopyTo(T[] array)
{
if (array == null)
{
throw new ArgumentNullException("array");
}
this.CopyTo(array, 0, array.Length);
}
/// <summary>
/// Copies the unmanaged array to the specified managed array.
///
/// It is important that <paramref name="length" /> be less than or equal to the length of
/// the array wrapped by this object. If it is not, at best garbage will be read and at worst
/// an exception of type <see cref="AccessViolationException" /> will be thrown.
/// </summary>
/// <param name="array">The managed array to copy the unmanaged values to.</param>
/// <param name="index">The index to start at when copying to <paramref name="array" />.</param>
/// <param name="length">The number of items to copy to <paramref name="array" /></param>
/// <exception cref="ObjectDisposedException">The unmanaged array wrapped by this object has been
/// freed.</exception>
/// <exception cref="InvalidOperationException">The pointer to the unmanaged array wrapped by this object
/// is invalid.</exception>
/// <exception cref="ArgumentNullException"><paramref name="array"/> is null.</exception>
/// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is less than zero.-or-
/// <paramref name="index" /> is greater than the length of <paramref name="array"/>.-or-
/// <paramref name="length"/> is less than zero.</exception>
/// <exception cref="ArgumentException">The sum of <paramref name="index" /> and <paramref name="length" />
/// is greater than the length of <paramref name="array" />.</exception>
public void CopyTo(T[] array, int index, int length)
{
if (this.IsClosed)
{
throw new ObjectDisposedException(this.ToString());
}
if (this.IsInvalid)
{
throw new InvalidOperationException("This object's buffer is invalid.");
}
if (array == null)
{
throw new ArgumentNullException("array");
}
if (index < 0 || array.Length < index)
{
throw new ArgumentOutOfRangeException("index", "index must be a nonnegative integer that is less than array's length.");
}
if (length < 0)
{
throw new ArgumentOutOfRangeException("length", "length must be a nonnegative integer.");
}
if (array.Length < index + length)
{
throw new ArgumentException("length", "length is greater than the number of elements from index to the end of array.");
}
for (int i = 0; i < length; ++i)
{
array[index + i] = this.GetArrayValue(i);
}
}
}
/// <summary>
/// The type of logon operation to perform.
/// </summary>
internal enum LogonType : uint
{
LOGON32_LOGON_BATCH = 1,
LOGON32_LOGON_INTERACTIVE = 2,
LOGON32_LOGON_NETWORK = 3,
LOGON32_LOGON_NETWORK_CLEARTEXT = 4,
LOGON32_LOGON_NEW_CREDENTIALS = 5,
LOGON32_LOGON_SERVICE = 6,
LOGON32_LOGON_UNLOCK = 7
}
/// <summary>
/// The logon provider to use.
/// </summary>
internal enum LogonProvider : uint
{
LOGON32_PROVIDER_DEFAULT = 0,
LOGON32_PROVIDER_WINNT50 = 1,
LOGON32_PROVIDER_WINNT40 = 2
}
}
Another way of looking at it: with SafeHandle, you should almost never need to write another finalizer.
I think MSDN is pretty clear in definition:
The SafeHandle class provides critical
finalization of handle resources,
preventing handles from being
reclaimed prematurely by garbage
collection and from being recycled by
Windows to reference unintended
unmanaged objects. Before the .NET
Framework version 2.0, all operating
system handles could only be
encapsulated in the IntPtr managed
wrapper object.
The SafeHandle class contains a
finalizer that ensures that the handle
is closed and is guaranteed to run,
even during unexpected AppDomain
unloads when a host may not trust the
consistency of the state of the
AppDomain.
For more information about the
benefits of using a SafeHandle, see
Safe Handles and Critical
Finalization.
This class is abstract because you
cannot create a generic handle. To
implement SafeHandle, you must create
a derived class. To create SafeHandle
derived classes, you must know how to
create and free an operating system
handle. This process is different for
different handle types because some
use CloseHandle, while others use more
specific methods such as
UnmapViewOfFile or FindClose. For this
reason, you must create a derived
class of SafeHandle for each operating
system handle type; such as
MySafeRegistryHandle,
MySafeFileHandle, and
MySpecialSafeFileHandle. Some of these
derived classes are prewritten and
provided for you in the
Microsoft.Win32.SafeHandles namespace.