aboutsummaryrefslogtreecommitdiff
path: root/src/dtf/WixToolset.Dtf.WindowsInstaller/Handle.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/dtf/WixToolset.Dtf.WindowsInstaller/Handle.cs154
1 files changed, 154 insertions, 0 deletions
diff --git a/src/dtf/WixToolset.Dtf.WindowsInstaller/Handle.cs b/src/dtf/WixToolset.Dtf.WindowsInstaller/Handle.cs
new file mode 100644
index 00000000..c3d3625f
--- /dev/null
+++ b/src/dtf/WixToolset.Dtf.WindowsInstaller/Handle.cs
@@ -0,0 +1,154 @@
1// 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.
2
3namespace WixToolset.Dtf.WindowsInstaller
4{
5 using System;
6 using System.ComponentModel;
7 using System.Diagnostics.CodeAnalysis;
8
9 /// <summary>
10 /// Base class for Windows Installer handle types (Database, View, Record, SummaryInfo).
11 /// </summary>
12 /// <remarks><p>
13 /// These classes implement the <see cref="IDisposable"/> interface, because they
14 /// hold unmanaged resources (MSI handles) that should be properly disposed
15 /// when no longer needed.
16 /// </p></remarks>
17 public abstract class InstallerHandle : MarshalByRefObject, IDisposable
18 {
19 private NativeMethods.MsiHandle handle;
20
21 /// <summary>
22 /// Constructs a handle object from a native integer handle.
23 /// </summary>
24 /// <param name="handle">Native integer handle.</param>
25 /// <param name="ownsHandle">true to close the handle when this object is disposed or finalized</param>
26 protected InstallerHandle(IntPtr handle, bool ownsHandle)
27 {
28 if (handle == IntPtr.Zero)
29 {
30 throw new InvalidHandleException();
31 }
32
33 this.handle = new NativeMethods.MsiHandle(handle, ownsHandle);
34 }
35
36 /// <summary>
37 /// Gets the native integer handle.
38 /// </summary>
39 [SuppressMessage("Microsoft.Design", "CA1065:DoNotRaiseExceptionsInUnexpectedLocations")]
40 public IntPtr Handle
41 {
42 get
43 {
44 if (this.IsClosed)
45 {
46 throw new InvalidHandleException();
47 }
48 return this.handle;
49 }
50 }
51
52 /// <summary>
53 /// Checks if the handle is closed. When closed, method calls on the handle object may throw an <see cref="InvalidHandleException"/>.
54 /// </summary>
55 [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")]
56 public bool IsClosed
57 {
58 get
59 {
60 return this.handle.IsClosed;
61 }
62 }
63
64 /// <summary>
65 /// Closes the handle. After closing a handle, further method calls may throw an <see cref="InvalidHandleException"/>.
66 /// </summary>
67 /// <remarks><p>
68 /// The finalizer of this class will NOT close the handle if it is still open,
69 /// because finalization can run on a separate thread from the application,
70 /// resulting in potential problems if handles are closed from that thread.
71 /// It is best that the handle be closed manually as soon as it is no longer needed,
72 /// as leaving lots of unused handles open can degrade performance.
73 /// </p><p>
74 /// Win32 MSI API:
75 /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msiclosehandle.asp">MsiCloseHandle</a>
76 /// </p></remarks>
77 /// <seealso cref="Close"/>
78 public void Dispose()
79 {
80 this.Dispose(true);
81 GC.SuppressFinalize(this);
82 }
83
84 /// <summary>
85 /// Closes the handle. After closing a handle, further method calls may throw an <see cref="InvalidHandleException"/>.
86 /// </summary>
87 /// <remarks><p>
88 /// The finalizer of this class will NOT close the handle if it is still open,
89 /// because finalization can run on a separate thread from the application,
90 /// resulting in potential problems if handles are closed from that thread.
91 /// It is best that the handle be closed manually as soon as it is no longer needed,
92 /// as leaving lots of unused handles open can degrade performance.
93 /// </p><p>
94 /// This method is merely an alias for the <see cref="Dispose()"/> method.
95 /// </p><p>
96 /// Win32 MSI API:
97 /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msiclosehandle.asp">MsiCloseHandle</a>
98 /// </p></remarks>
99 public void Close()
100 {
101 this.Dispose();
102 }
103
104 /// <summary>
105 /// Tests whether this handle object is equal to another handle object. Two handle objects are equal
106 /// if their types are the same and their native integer handles are the same.
107 /// </summary>
108 /// <param name="obj">The handle object to compare with the current handle object.</param>
109 /// <returns>true if the specified handle object is equal to the current handle object; otherwise false</returns>
110 public override bool Equals(object obj)
111 {
112 return (obj != null && this.GetType() == obj.GetType() &&
113 this.Handle == ((InstallerHandle) obj).Handle);
114 }
115
116 /// <summary>
117 /// Gets a hash value for the handle object.
118 /// </summary>
119 /// <returns>A hash code for the handle object.</returns>
120 /// <remarks><p>
121 /// The hash code is derived from the native integer handle.
122 /// </p></remarks>
123 public override int GetHashCode()
124 {
125 return this.Handle.GetHashCode();
126 }
127
128 /// <summary>
129 /// Gets an object that can be used internally for safe syncronization.
130 /// </summary>
131 internal object Sync
132 {
133 get
134 {
135 return this.handle;
136 }
137 }
138
139 /// <summary>
140 /// Closes the handle. After closing a handle, further method calls may throw an <see cref="InvalidHandleException"/>.
141 /// </summary>
142 /// <param name="disposing">If true, the method has been called directly or indirectly by a user's code,
143 /// so managed and unmanaged resources will be disposed. If false, the method has been called by the
144 /// runtime from inside the finalizer, and only unmanaged resources will be disposed.</param>
145 [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")]
146 protected virtual void Dispose(bool disposing)
147 {
148 if (disposing)
149 {
150 this.handle.Dispose();
151 }
152 }
153 }
154}