// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
namespace WixToolset.Dtf.WindowsInstaller
{
using System;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
///
/// Base class for Windows Installer handle types (Database, View, Record, SummaryInfo).
///
///
/// These classes implement the interface, because they
/// hold unmanaged resources (MSI handles) that should be properly disposed
/// when no longer needed.
///
public abstract class InstallerHandle : MarshalByRefObject, IDisposable
{
private NativeMethods.MsiHandle handle;
///
/// Constructs a handle object from a native integer handle.
///
/// Native integer handle.
/// true to close the handle when this object is disposed or finalized
protected InstallerHandle(IntPtr handle, bool ownsHandle)
{
if (handle == IntPtr.Zero)
{
throw new InvalidHandleException();
}
this.handle = new NativeMethods.MsiHandle(handle, ownsHandle);
}
///
/// Gets the native integer handle.
///
[SuppressMessage("Microsoft.Design", "CA1065:DoNotRaiseExceptionsInUnexpectedLocations")]
public IntPtr Handle
{
get
{
if (this.IsClosed)
{
throw new InvalidHandleException();
}
return this.handle;
}
}
///
/// Checks if the handle is closed. When closed, method calls on the handle object may throw an .
///
[SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")]
public bool IsClosed
{
get
{
return this.handle.IsClosed;
}
}
///
/// Closes the handle. After closing a handle, further method calls may throw an .
///
///
/// The finalizer of this class will NOT close the handle if it is still open,
/// because finalization can run on a separate thread from the application,
/// resulting in potential problems if handles are closed from that thread.
/// It is best that the handle be closed manually as soon as it is no longer needed,
/// as leaving lots of unused handles open can degrade performance.
///
/// Win32 MSI API:
/// MsiCloseHandle
///
///
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
///
/// Closes the handle. After closing a handle, further method calls may throw an .
///
///
/// The finalizer of this class will NOT close the handle if it is still open,
/// because finalization can run on a separate thread from the application,
/// resulting in potential problems if handles are closed from that thread.
/// It is best that the handle be closed manually as soon as it is no longer needed,
/// as leaving lots of unused handles open can degrade performance.
///
/// This method is merely an alias for the method.
///
/// Win32 MSI API:
/// MsiCloseHandle
///
public void Close()
{
this.Dispose();
}
///
/// Tests whether this handle object is equal to another handle object. Two handle objects are equal
/// if their types are the same and their native integer handles are the same.
///
/// The handle object to compare with the current handle object.
/// true if the specified handle object is equal to the current handle object; otherwise false
public override bool Equals(object obj)
{
return (obj != null && this.GetType() == obj.GetType() &&
this.Handle == ((InstallerHandle) obj).Handle);
}
///
/// Gets a hash value for the handle object.
///
/// A hash code for the handle object.
///
/// The hash code is derived from the native integer handle.
///
public override int GetHashCode()
{
return this.Handle.GetHashCode();
}
///
/// Gets an object that can be used internally for safe syncronization.
///
internal object Sync
{
get
{
return this.handle;
}
}
///
/// Closes the handle. After closing a handle, further method calls may throw an .
///
/// If true, the method has been called directly or indirectly by a user's code,
/// so managed and unmanaged resources will be disposed. If false, the method has been called by the
/// runtime from inside the finalizer, and only unmanaged resources will be disposed.
[SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")]
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
this.handle.Dispose();
}
}
}
}