Updates referencesource to .NET 4.7
[mono.git] / mcs / class / referencesource / mscorlib / system / runtime / interopservices / windowsruntime / bindablevectortocollectionadapter.cs
1 // ==++==
2 // 
3 //   Copyright (c) Microsoft Corporation.  All rights reserved.
4 // 
5 // ==--==
6 //
7 // <OWNER>GPaperin</OWNER>
8 // <OWNER>Microsoft</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 ICollection 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 BindableVectorToCollectionAdapter objects. Rather, they are
27     // of type IBindableVector. No actual BindableVectorToCollectionAdapter object is ever instantiated.
28     // Thus, you will see a lot of expressions that cast "this" to "IBindableVector".
29     internal sealed class BindableVectorToCollectionAdapter
30     {
31         private BindableVectorToCollectionAdapter()
32         {
33             Contract.Assert(false, "This class is never instantiated");
34         }
35
36         // int Count { get }
37         [Pure]
38         [SecurityCritical]
39         internal int Count()
40         {
41             IBindableVector _this = JitHelpers.UnsafeCast<IBindableVector>(this);
42             uint size = _this.Size;
43             if (((uint)Int32.MaxValue) < size)
44             {
45                 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CollectionBackingListTooLarge"));
46             }
47
48             return (int)size;
49         }
50
51         // bool IsSynchronized { get }
52         [Pure]
53         [SecurityCritical]
54         internal bool IsSynchronized()
55         {
56             return false;
57         }
58
59         // object SyncRoot { get }
60         [Pure]
61         [SecurityCritical]
62         internal object SyncRoot()
63         {
64             return this;
65         }
66
67         // void CopyTo(Array array, int index)
68         [Pure]
69         [SecurityCritical]
70         internal void CopyTo(Array array, int arrayIndex)
71         {
72             if (array == null)
73                 throw new ArgumentNullException("array");
74
75             // ICollection expects the destination array to be single-dimensional.
76             if (array.Rank != 1)
77                 throw new ArgumentException(Environment.GetResourceString("Arg_RankMultiDimNotSupported"));
78
79             int destLB = array.GetLowerBound(0);
80
81             int srcLen = Count();
82             int destLen = array.GetLength(0);
83
84             if (arrayIndex < destLB)
85                 throw new ArgumentOutOfRangeException("arrayIndex");
86
87             // Does the dimension in question have sufficient space to copy the expected number of entries?
88             // We perform this check before valid index check to ensure the exception message is in sync with
89             // the following snippet that uses regular framework code:
90             //
91             // ArrayList list = new ArrayList();
92             // list.Add(1);
93             // Array items = Array.CreateInstance(typeof(object), new int[] { 1 }, new int[] { -1 });
94             // list.CopyTo(items, 0);
95
96             if(srcLen > (destLen - (arrayIndex - destLB)))
97                 throw new ArgumentException(Environment.GetResourceString("Argument_InsufficientSpaceToCopyCollection"));
98
99             if(arrayIndex - destLB > destLen)
100                 throw new ArgumentException(Environment.GetResourceString("Argument_IndexOutOfArrayBounds"));
101
102             // We need to verify the index as we;
103             IBindableVector _this = JitHelpers.UnsafeCast<IBindableVector>(this);
104
105             for (uint i = 0; i < srcLen; i++)
106             {
107                 array.SetValue(_this.GetAt(i), i + arrayIndex);
108             }
109         }
110     }
111 }