Update Reference Sources to .NET Framework 4.6.1
[mono.git] / mcs / class / referencesource / mscorlib / system / runtime / interopservices / windowsruntime / bindablevectortolistadapter.cs
1 // ==++==
2 // 
3 //   Copyright (c) Microsoft Corporation.  All rights reserved.
4 // 
5 // ==--==
6 //
7 // <OWNER>GPaperin</OWNER>
8 // <OWNER>[....]</OWNER>
9
10 using System;
11 using System.Runtime;
12 using System.Security;
13 using System.Collections;
14 using System.Collections.Generic;
15 using System.Diagnostics.Contracts;
16 using System.Runtime.InteropServices;
17 using System.Runtime.CompilerServices;
18
19 namespace System.Runtime.InteropServices.WindowsRuntime
20 {
21     // This is a set of stub methods implementing the support for the IList interface on WinRT
22     // objects that support IBindableVector. Used by the interop mashaling infrastructure.
23     //
24     // The methods on this class must be written VERY carefully to avoid introducing security holes.
25     // That's because they are invoked with special "this"! The "this" object
26     // for all of these methods are not BindableVectorToListAdapter objects. Rather, they are
27     // of type IBindableVector. No actual BindableVectorToListAdapter object is ever instantiated.
28     // Thus, you will see a lot of expressions that cast "this" to "IBindableVector".
29     internal sealed class BindableVectorToListAdapter
30     {
31         private BindableVectorToListAdapter()
32         {
33             Contract.Assert(false, "This class is never instantiated");
34         }
35
36         // object this[int index] { get }
37         [SecurityCritical]
38         internal object Indexer_Get(int index)
39         {
40             if (index < 0)
41                 throw new ArgumentOutOfRangeException("index");
42
43             IBindableVector _this = JitHelpers.UnsafeCast<IBindableVector>(this);
44             return GetAt(_this, (uint)index);
45         }
46
47         // object this[int index] { set }
48         [SecurityCritical]
49         internal void Indexer_Set(int index, object value)
50         {
51             if (index < 0)
52                 throw new ArgumentOutOfRangeException("index");
53
54             IBindableVector _this = JitHelpers.UnsafeCast<IBindableVector>(this);
55             SetAt(_this, (uint)index, value);
56         }
57
58         // int Add(object value)
59         [SecurityCritical]
60         internal int Add(object value)
61         {
62             IBindableVector _this = JitHelpers.UnsafeCast<IBindableVector>(this);
63             _this.Append(value);
64
65             uint size = _this.Size;
66             if (((uint)Int32.MaxValue) < size)
67             {
68                 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CollectionBackingListTooLarge"));
69             }
70
71             return (int)(size - 1);
72         }
73
74         // bool Contains(object item)
75         [SecurityCritical]
76         internal bool Contains(object item)
77         {
78             IBindableVector _this = JitHelpers.UnsafeCast<IBindableVector>(this);
79
80             uint index;
81             return _this.IndexOf(item, out index);
82         }
83
84         // void Clear()
85         [SecurityCritical]
86         internal void Clear()
87         {
88             IBindableVector _this = JitHelpers.UnsafeCast<IBindableVector>(this);
89             _this.Clear();
90         }
91
92         // bool IsFixedSize { get }
93         [Pure]
94         [SecurityCritical]
95         internal bool IsFixedSize()
96         {
97             return false;
98         }
99
100         // bool IsReadOnly { get }
101         [Pure]
102         [SecurityCritical]
103         internal bool IsReadOnly()
104         {
105             return false;
106         }
107
108         // int IndexOf(object item)
109         [SecurityCritical]
110         internal int IndexOf(object item)
111         {
112             IBindableVector _this = JitHelpers.UnsafeCast<IBindableVector>(this);
113
114             uint index;
115             bool exists = _this.IndexOf(item, out index);
116
117             if (!exists)
118                 return -1;
119
120             if (((uint)Int32.MaxValue) < index)
121             {
122                 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CollectionBackingListTooLarge"));
123             }
124
125             return (int)index;
126         }
127
128         // void Insert(int index, object item)
129         [SecurityCritical]
130         internal void Insert(int index, object item)
131         {
132             if (index < 0)
133                 throw new ArgumentOutOfRangeException("index");
134
135             IBindableVector _this = JitHelpers.UnsafeCast<IBindableVector>(this);
136             InsertAtHelper(_this, (uint)index, item);
137         }
138
139         // bool Remove(object item)
140         [SecurityCritical]
141         internal void Remove(object item)
142         {
143             IBindableVector _this = JitHelpers.UnsafeCast<IBindableVector>(this);
144
145             uint index;
146             bool exists = _this.IndexOf(item, out index);
147
148             if (exists)
149             {
150                 if (((uint)Int32.MaxValue) < index)
151                 {
152                     throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CollectionBackingListTooLarge"));
153                 }
154
155                 RemoveAtHelper(_this, index);
156             }
157         }
158
159         // void RemoveAt(int index)
160         [SecurityCritical]
161         internal void RemoveAt(int index)
162         {
163             if (index < 0)
164                 throw new ArgumentOutOfRangeException("index");
165
166             IBindableVector _this = JitHelpers.UnsafeCast<IBindableVector>(this);
167             RemoveAtHelper(_this, (uint)index);
168         }
169
170         // Helpers:
171
172         private static object GetAt(IBindableVector _this, uint index)
173         {
174             try
175             {
176                 return _this.GetAt(index);
177
178                 // We delegate bounds checking to the underlying collection and if it detected a fault,
179                 // we translate it to the right exception:
180             }
181             catch (Exception ex)
182             {
183                 if (__HResults.E_BOUNDS == ex._HResult)
184                     throw new ArgumentOutOfRangeException("index");
185
186                 throw;
187             }
188         }
189
190         private static void SetAt(IBindableVector _this, uint index, object value)
191         {
192             try
193             {
194                 _this.SetAt(index, value);
195
196                 // We delegate bounds checking to the underlying collection and if it detected a fault,
197                 // we translate it to the right exception:
198             }
199             catch (Exception ex)
200             {
201                 if (__HResults.E_BOUNDS == ex._HResult)
202                     throw new ArgumentOutOfRangeException("index");
203
204                 throw;
205             }
206         }
207
208         private static void InsertAtHelper(IBindableVector _this, uint index, object item)
209         {
210             try
211             {
212                 _this.InsertAt(index, item);
213
214                 // We delegate bounds checking to the underlying collection and if it detected a fault,
215                 // we translate it to the right exception:
216             }
217             catch (Exception ex)
218             {
219                 if (__HResults.E_BOUNDS == ex._HResult)
220                     throw new ArgumentOutOfRangeException("index");
221
222                 throw;
223             }
224         }
225
226         private static void RemoveAtHelper(IBindableVector _this, uint index)
227         {
228             try
229             {
230                 _this.RemoveAt(index);
231
232                 // We delegate bounds checking to the underlying collection and if it detected a fault,
233                 // we translate it to the right exception:
234             }
235             catch (Exception ex)
236             {
237                 if (__HResults.E_BOUNDS == ex._HResult)
238                     throw new ArgumentOutOfRangeException("index");
239
240                 throw;
241             }
242         }
243     }
244 }