1 //------------------------------------------------------------------------------
2 // <copyright file="SafeHandles.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 // <owner current="true" primary="true">[....]</owner>
6 // <owner current="true" primary="false">[....]</owner>
7 //------------------------------------------------------------------------------
9 namespace System.Data.OleDb {
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;
23 internal sealed class DualCoTaskMem : SafeHandle {
25 private IntPtr handle2; // this must be protected so derived classes can use out params.
27 private DualCoTaskMem() : base(IntPtr.Zero, true) {
28 this.handle2 = IntPtr.Zero;
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;
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);
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);
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);
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);
65 public override bool IsInvalid {
67 return (((IntPtr.Zero == base.handle)) && (IntPtr.Zero == this.handle2));
71 protected override bool ReleaseHandle() {
72 // NOTE: The SafeHandle class guarantees this will be called exactly once.
74 IntPtr ptr = base.handle;
75 base.handle = IntPtr.Zero;
76 if (IntPtr.Zero != ptr) {
77 SafeNativeMethods.CoTaskMemFree(ptr);
81 this.handle2 = IntPtr.Zero;
82 if (IntPtr.Zero != ptr) {
83 SafeNativeMethods.CoTaskMemFree(ptr);
89 internal sealed class RowHandleBuffer : DbBuffer {
91 internal RowHandleBuffer(IntPtr rowHandleFetchCount) : base((int)rowHandleFetchCount*ADP.PtrSize) {
94 internal IntPtr GetRowHandle(int index) {
95 IntPtr value = ReadIntPtr( index * ADP.PtrSize);
96 Debug.Assert(ODB.DB_NULL_HROW != value, "bad rowHandle");
101 internal sealed class StringMemHandle : DbBuffer {
103 internal StringMemHandle(string value) : base((null != value) ? checked(2+2*value.Length) : 0) {
105 // null-termination exists because of the extra 2+ which is zero'd during on allocation
106 WriteCharArray(0, value.ToCharArray(), 0, value.Length);
111 internal sealed class ChapterHandle : WrappedIUnknown {
113 internal static readonly ChapterHandle DB_NULL_HCHAPTER = new ChapterHandle(IntPtr.Zero);
114 private IntPtr _chapterHandle;
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;
120 return new ChapterHandle(chapteredRowset, binding, valueOffset);
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;
128 return new ChapterHandle(chapter);
131 // from ADODBRecordSetConstruction we do not want to release the initial chapter handle
132 private ChapterHandle(IntPtr chapter) : base((object)null) {
133 _chapterHandle = chapter;
136 private ChapterHandle(object chapteredRowset, RowBinding binding, int valueOffset) : base(chapteredRowset) {
137 RuntimeHelpers.PrepareConstrainedRegions();
139 _chapterHandle = binding.InterlockedExchangePointer(valueOffset);
143 internal IntPtr HChapter {
145 return _chapterHandle;
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;
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);
159 return base.ReleaseHandle();