diff options
Diffstat (limited to '')
-rw-r--r-- | src/dtf/WixToolset.Dtf.WindowsInstaller/Handle.cs | 154 |
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 | |||
3 | namespace 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 | } | ||