Update Reference Sources to .NET Framework 4.6.1
[mono.git] / mcs / class / referencesource / System.Data / System / Data / OleDb / SafeHandles.cs
1 //------------------------------------------------------------------------------
2 // <copyright file="SafeHandles.cs" company="Microsoft">
3 //      Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 // <owner current="true" primary="true">[....]</owner>
6 // <owner current="true" primary="false">[....]</owner>
7 //------------------------------------------------------------------------------
8
9 namespace System.Data.OleDb {
10
11     using System;
12     using System.Data.Common;
13     using System.Data.ProviderBase;
14     using System.Diagnostics;
15     using System.Globalization;
16     using System.Runtime.CompilerServices;
17     using System.Runtime.InteropServices;
18     using System.Security;
19     using System.Security.Permissions;
20     using System.Threading;
21     using System.Runtime.ConstrainedExecution;
22
23     internal sealed class DualCoTaskMem : SafeHandle {
24
25         private IntPtr handle2;   // this must be protected so derived classes can use out params.
26
27         private DualCoTaskMem() : base(IntPtr.Zero, true) {
28             this.handle2 = IntPtr.Zero;
29         }
30
31         // IDBInfo.GetLiteralInfo
32         internal DualCoTaskMem(UnsafeNativeMethods.IDBInfo dbInfo, int[] literals, out int literalCount, out IntPtr literalInfo, out OleDbHResult hr) : this() {
33             int count = (null != literals) ? literals.Length : 0;
34
35             Bid.Trace("<oledb.IDBInfo.GetLiteralInfo|API|OLEDB>\n");
36             hr = dbInfo.GetLiteralInfo(count, literals, out literalCount, out base.handle, out this.handle2);
37             literalInfo = base.handle;
38             Bid.Trace("<oledb.IDBInfo.GetLiteralInfo|API|OLEDB|RET> %08X{HRESULT}\n", hr);
39         }
40
41         // IColumnsInfo.GetColumnInfo
42         internal DualCoTaskMem(UnsafeNativeMethods.IColumnsInfo columnsInfo, out IntPtr columnCount, out IntPtr columnInfos, out OleDbHResult hr) : this() {
43             Bid.Trace("<oledb.IColumnsInfo.GetColumnInfo|API|OLEDB>\n");
44             hr = columnsInfo.GetColumnInfo(out columnCount, out base.handle, out this.handle2);
45             columnInfos = base.handle;
46             Bid.Trace("<oledb.IColumnsInfo.GetColumnInfo|API|OLEDB|RET> %08X{HRESULT}\n", hr);
47         }
48
49         // IDBSchemaRowset.GetSchemas
50         internal DualCoTaskMem(UnsafeNativeMethods.IDBSchemaRowset dbSchemaRowset, out int schemaCount, out IntPtr schemaGuids, out IntPtr schemaRestrictions, out OleDbHResult hr) : this() {
51             Bid.Trace("<oledb.IDBSchemaRowset.GetSchemas|API|OLEDB>\n");
52             hr = dbSchemaRowset.GetSchemas(out schemaCount, out base.handle, out this.handle2);
53             schemaGuids = base.handle;
54             schemaRestrictions = this.handle2;
55             Bid.Trace("<oledb.IDBSchemaRowset.GetSchemas|API|OLEDB|RET> %08X{HRESULT}\n", hr);
56         }
57
58         internal DualCoTaskMem(UnsafeNativeMethods.IColumnsRowset icolumnsRowset, out IntPtr cOptColumns, out OleDbHResult hr) : base(IntPtr.Zero, true) {
59             Bid.Trace("<oledb.IColumnsRowset.GetAvailableColumns|API|OLEDB>\n");
60             hr = icolumnsRowset.GetAvailableColumns(out cOptColumns, out base.handle);
61             Bid.Trace("<oledb.IColumnsRowset.GetAvailableColumns|API|OLEDB|RET> %08X{HRESULT}\n", hr);
62         }
63
64
65         public override bool IsInvalid {
66             get {
67                 return (((IntPtr.Zero == base.handle)) && (IntPtr.Zero == this.handle2));
68             }
69         }
70
71         protected override bool ReleaseHandle() {
72             // NOTE: The SafeHandle class guarantees this will be called exactly once.
73
74             IntPtr ptr = base.handle;
75             base.handle = IntPtr.Zero;
76             if (IntPtr.Zero != ptr) {
77                 SafeNativeMethods.CoTaskMemFree(ptr);
78             }
79
80             ptr = this.handle2;
81             this.handle2 = IntPtr.Zero;
82             if (IntPtr.Zero != ptr) {
83                 SafeNativeMethods.CoTaskMemFree(ptr);
84             }
85             return true;
86         }
87     }
88
89     internal sealed class RowHandleBuffer : DbBuffer {
90
91         internal RowHandleBuffer(IntPtr rowHandleFetchCount) : base((int)rowHandleFetchCount*ADP.PtrSize) {
92         }
93
94         internal IntPtr GetRowHandle(int index) {
95             IntPtr value = ReadIntPtr( index * ADP.PtrSize);
96             Debug.Assert(ODB.DB_NULL_HROW != value, "bad rowHandle");
97             return value;
98         }
99     }
100
101     internal sealed class StringMemHandle : DbBuffer {
102
103         internal StringMemHandle(string value) : base((null != value) ? checked(2+2*value.Length) : 0) {
104             if (null != value) {
105                 // null-termination exists because of the extra 2+ which is zero'd during on allocation
106                 WriteCharArray(0, value.ToCharArray(), 0, value.Length);
107             }
108         }
109     }
110
111     internal sealed class ChapterHandle : WrappedIUnknown {
112
113         internal static readonly ChapterHandle DB_NULL_HCHAPTER = new ChapterHandle(IntPtr.Zero);
114         private IntPtr _chapterHandle;
115
116         internal static ChapterHandle CreateChapterHandle(object chapteredRowset, RowBinding binding, int valueOffset) {
117             if ((null == chapteredRowset) || (IntPtr.Zero == binding.ReadIntPtr(valueOffset))) {
118                 return ChapterHandle.DB_NULL_HCHAPTER;
119             }
120             return new ChapterHandle(chapteredRowset, binding, valueOffset);
121         }
122
123          // from ADODBRecordSetConstruction we do not want to release the initial chapter handle
124         internal static ChapterHandle CreateChapterHandle(IntPtr chapter) {
125             if (IntPtr.Zero == chapter) {
126                 return ChapterHandle.DB_NULL_HCHAPTER;
127             }
128             return new ChapterHandle(chapter);
129         }
130
131         // from ADODBRecordSetConstruction we do not want to release the initial chapter handle
132         private ChapterHandle(IntPtr chapter) : base((object)null) {
133             _chapterHandle = chapter;
134         }
135
136         private ChapterHandle(object chapteredRowset, RowBinding binding, int valueOffset) : base(chapteredRowset) {
137             RuntimeHelpers.PrepareConstrainedRegions();
138             try {} finally {
139                 _chapterHandle = binding.InterlockedExchangePointer(valueOffset);
140             }
141         }
142
143         internal IntPtr HChapter {
144             get {
145                 return _chapterHandle;
146             }
147         }
148
149         protected override bool ReleaseHandle() {
150             // NOTE: The SafeHandle class guarantees this will be called exactly once and is non-interrutible.
151             IntPtr chapter = _chapterHandle;
152             _chapterHandle = IntPtr.Zero;
153
154             if ((IntPtr.Zero != base.handle) && (IntPtr.Zero != chapter)) {
155                 Bid.Trace("<oledb.IChapteredRowset.ReleaseChapter|API|OLEDB> Chapter=%Id\n", chapter);
156                 OleDbHResult hr = (OleDbHResult)NativeOledbWrapper.IChapteredRowsetReleaseChapter(base.handle, chapter);
157                 Bid.Trace("<oledb.IChapteredRowset.ReleaseChapter|API|OLEDB|RET> %08X{HRESULT}\n", hr);
158             }
159             return base.ReleaseHandle();
160         }
161     }
162 }