Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichal Strehovský <MichalStrehovsky@users.noreply.github.com>2017-10-25 12:11:09 +0300
committerGitHub <noreply@github.com>2017-10-25 12:11:09 +0300
commit41ab3cc38c1837a4cb152fb47d5a9fe82395db79 (patch)
tree572671723d66f293771c1bc6f5d27ef7be988e00 /src/System.Private.Interop
parentba17d2e3a904d46f4973c2e31cf668fd06432aa0 (diff)
parenta4bb592487fcf5af1d9f98484de904facd8d8c39 (diff)
Merge pull request #4790 from dotnet/nmirror
Merge nmirror to master
Diffstat (limited to 'src/System.Private.Interop')
-rw-r--r--src/System.Private.Interop/src/InteropExtensions/DebugAnnotations.cs20
-rw-r--r--src/System.Private.Interop/src/InteropExtensions/DependencyReductionRootAttribute.cs2
-rw-r--r--src/System.Private.Interop/src/InteropExtensions/InteropExtensions.cs10
-rw-r--r--src/System.Private.Interop/src/InteropExtensions/PInvokeMarshal.cs5
-rw-r--r--src/System.Private.Interop/src/Shared/McgIntrinsics.cs11
-rw-r--r--src/System.Private.Interop/src/System.Private.Interop.CoreCLR.csproj2
-rw-r--r--src/System.Private.Interop/src/System.Private.Interop.Mono.csproj32
-rw-r--r--src/System.Private.Interop/src/System.Private.Interop.Shared.projitems3
-rw-r--r--src/System.Private.Interop/src/System.Private.Interop.csproj1
-rw-r--r--src/System.Private.Interop/src/System/Runtime/InteropServices/WindowsRuntime/CLRIKeyValuePairImpl.cs124
-rw-r--r--src/System.Private.Interop/src/System/Runtime/InteropServices/WindowsRuntime/IPropertyValue.cs62
-rw-r--r--src/System.Private.Interop/src/System/Runtime/InteropServices/WindowsRuntime/IReadOnlyListAdapter.cs26
-rw-r--r--src/System.Private.Interop/src/System/Runtime/InteropServices/WindowsRuntime/IReferenceArray.cs15
-rw-r--r--src/System.Private.Interop/src/System/Runtime/InteropServices/WindowsRuntime/PropertyValueImpl.cs480
-rw-r--r--src/System.Private.Interop/src/System/Runtime/InteropServices/WindowsRuntime/ReferenceArrayImpl.cs33
-rw-r--r--src/System.Private.Interop/src/System/Runtime/InteropServices/WindowsRuntime/ReferenceArrayImplBase.cs178
-rw-r--r--src/System.Private.Interop/src/System/Runtime/InteropServices/WindowsRuntime/ReferenceImpl.cs40
-rw-r--r--src/System.Private.Interop/src/System/Runtime/InteropServices/WindowsRuntime/__IUnboxInternal.cs18
-rw-r--r--src/System.Private.Interop/src/Windows/Foundation/IKeyValuePair.cs18
-rw-r--r--src/System.Private.Interop/src/Windows/Foundation/IReference.cs13
-rw-r--r--src/System.Private.Interop/src/Windows/Foundation/Point.cs120
-rw-r--r--src/System.Private.Interop/src/Windows/Foundation/PropertyType.cs51
-rw-r--r--src/System.Private.Interop/src/Windows/Foundation/Rect.cs367
-rw-r--r--src/System.Private.Interop/src/Windows/Foundation/Size.cs159
-rw-r--r--src/System.Private.Interop/src/Windows/Foundation/TokenizerHelper.cs51
25 files changed, 1829 insertions, 12 deletions
diff --git a/src/System.Private.Interop/src/InteropExtensions/DebugAnnotations.cs b/src/System.Private.Interop/src/InteropExtensions/DebugAnnotations.cs
new file mode 100644
index 000000000..ad8ad4f7f
--- /dev/null
+++ b/src/System.Private.Interop/src/InteropExtensions/DebugAnnotations.cs
@@ -0,0 +1,20 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Diagnostics
+{
+ /// <summary>
+ /// Annotations used by debugger
+ /// </summary>
+ public static class DebugAnnotations
+ {
+ /// <summary>
+ /// Informs debugger that previous line contains code that debugger needs to dive deeper inside.
+ /// </summary>
+ public static void PreviousCallContainsDebuggerStepInCode()
+ {
+ // This is a marker method and has no code in method body
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Private.Interop/src/InteropExtensions/DependencyReductionRootAttribute.cs b/src/System.Private.Interop/src/InteropExtensions/DependencyReductionRootAttribute.cs
index bb697727c..417cdb841 100644
--- a/src/System.Private.Interop/src/InteropExtensions/DependencyReductionRootAttribute.cs
+++ b/src/System.Private.Interop/src/InteropExtensions/DependencyReductionRootAttribute.cs
@@ -6,7 +6,7 @@ namespace System.Runtime.CompilerServices
{
// When applied to a type this custom attribute will cause the type to become a new dependency
// reduction root.
- [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Constructor, Inherited = false, AllowMultiple = false)]
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Interface, Inherited = false, AllowMultiple = false)]
public class DependencyReductionRootAttribute : Attribute
{
}
diff --git a/src/System.Private.Interop/src/InteropExtensions/InteropExtensions.cs b/src/System.Private.Interop/src/InteropExtensions/InteropExtensions.cs
index 5341a4554..93c46d95b 100644
--- a/src/System.Private.Interop/src/InteropExtensions/InteropExtensions.cs
+++ b/src/System.Private.Interop/src/InteropExtensions/InteropExtensions.cs
@@ -447,6 +447,16 @@ namespace System.Runtime.InteropServices
{
//Nop
}
+
+ public static IntPtr GetCriticalHandle(CriticalHandle criticalHandle)
+ {
+ throw new NotSupportedException("GetCriticalHandle");
+ }
+
+ public static void SetCriticalHandle(CriticalHandle criticalHandle, IntPtr handle)
+ {
+ throw new NotSupportedException("SetCriticalHandle");
+ }
}
public class GCHelpers
diff --git a/src/System.Private.Interop/src/InteropExtensions/PInvokeMarshal.cs b/src/System.Private.Interop/src/InteropExtensions/PInvokeMarshal.cs
index 0a88205f3..46da09e11 100644
--- a/src/System.Private.Interop/src/InteropExtensions/PInvokeMarshal.cs
+++ b/src/System.Private.Interop/src/InteropExtensions/PInvokeMarshal.cs
@@ -199,5 +199,10 @@ namespace System.Runtime.InteropServices
{
return default(String);
}
+
+ public static unsafe void CopyToNative(Array source, int startIndex, IntPtr destination, int length)
+ {
+ // nop
+ }
}
}
diff --git a/src/System.Private.Interop/src/Shared/McgIntrinsics.cs b/src/System.Private.Interop/src/Shared/McgIntrinsics.cs
index 8334feeb9..4bd120511 100644
--- a/src/System.Private.Interop/src/Shared/McgIntrinsics.cs
+++ b/src/System.Private.Interop/src/Shared/McgIntrinsics.cs
@@ -487,7 +487,7 @@ namespace System.Runtime.InteropServices
return default(T);
}
-#if ENABLE_WINRT
+#if ENABLE_MIN_WINRT
// For SharedCCW_IVector/SharedCCW_IVectorView
internal static T Call<T>(IntPtr pfn, object list, Toolbox.IList_Oper oper, int index, ref object item)
{
@@ -505,8 +505,7 @@ namespace System.Runtime.InteropServices
return default(T);
}
-#if !RHTESTCL && !CORECLR
-
+#if ENABLE_WINRT
// For SharedCcw_AsyncOperationCompletedHandler
internal static T Call<T>(IntPtr pfn, object handler, object asyncInfo, global::Windows.Foundation.AsyncStatus status)
{
@@ -518,7 +517,7 @@ namespace System.Runtime.InteropServices
{
return default(T);
}
-#endif // ENABLE_WINRT
+#endif // ENABLE_MIN_WINRT
// For ForwardDelegateCreationStub
internal static Delegate Call__Delegate(System.IntPtr pfn, System.IntPtr pStub)
{
@@ -623,7 +622,7 @@ namespace System.Runtime.InteropServices
#endif
}
-#if !CORECLR && ENABLE_WINRT
+#if ENABLE_MIN_WINRT
[McgIntrinsics]
internal class WinRTAddrOfIntrinsics
{
@@ -631,7 +630,7 @@ namespace System.Runtime.InteropServices
internal delegate int AddrOfGetIndexedProperty(System.IntPtr pComThis, HSTRING unsafe_name, TypeName unsafe_type, IntPtr __IntPtr__unsafe_customProperty);
internal delegate int AddrOfTarget19(IntPtr p0, IntPtr p1, int p2);
}
-#endif // !CORECLR && ENABLE_WINRT
+#endif // ENABLE_MIN_WINRT
public delegate IntPtr AddrOfGetCCWVtable();
public delegate int AddrOfRelease(IntPtr pComThis);
diff --git a/src/System.Private.Interop/src/System.Private.Interop.CoreCLR.csproj b/src/System.Private.Interop/src/System.Private.Interop.CoreCLR.csproj
index e8967228e..6c1648e5f 100644
--- a/src/System.Private.Interop/src/System.Private.Interop.CoreCLR.csproj
+++ b/src/System.Private.Interop/src/System.Private.Interop.CoreCLR.csproj
@@ -7,7 +7,7 @@
<OutputType>Library</OutputType>
<ProjectGuid>{A85709C9-22D5-4704-8B7A-73751BB4386A}</ProjectGuid>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
- <DefineConstants>TARGET_CORE_API_SET;CORECLR</DefineConstants>
+ <DefineConstants>$(DefineConstants);TARGET_CORE_API_SET;CORECLR</DefineConstants>
<!-- Disable warning about CLSCompliant attributes on members not being needed. -->
<NoWarn>$(NoWarn);3021</NoWarn>
<!-- Use MSFT assembly key for compatibility with uapaot targeting pack -->
diff --git a/src/System.Private.Interop/src/System.Private.Interop.Mono.csproj b/src/System.Private.Interop/src/System.Private.Interop.Mono.csproj
index b89420b88..25c4f62a6 100644
--- a/src/System.Private.Interop/src/System.Private.Interop.Mono.csproj
+++ b/src/System.Private.Interop/src/System.Private.Interop.Mono.csproj
@@ -5,7 +5,35 @@
<TargetName>$(AssemblyName)</TargetName>
<DefineConstants>$(DefineConstants);ENABLE_MIN_WINRT</DefineConstants>
<OutputPath>$(OutputPath)\mono</OutputPath>
- </PropertyGroup>
-
+ </PropertyGroup>
+
+ <ItemGroup>
+ <Compile Include="InteropExtensions\DebugAnnotations.cs" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <Compile Include="System\Runtime\InteropServices\WindowsRuntime\__IUnboxInternal.cs" />
+ <Compile Include="System\Runtime\InteropServices\WindowsRuntime\CLRIKeyValuePairImpl.cs" />
+ <Compile Include="System\Runtime\InteropServices\WindowsRuntime\IPropertyValue.cs" />
+ <Compile Include="System\Runtime\InteropServices\WindowsRuntime\IReadOnlyListAdapter.cs" />
+ <Compile Include="System\Runtime\InteropServices\WindowsRuntime\IReferenceArray.cs" />
+ <Compile Include="System\Runtime\InteropServices\WindowsRuntime\PropertyValueImpl.cs" />
+ <Compile Include="System\Runtime\InteropServices\WindowsRuntime\ReferenceArrayImpl.cs" />
+ <Compile Include="System\Runtime\InteropServices\WindowsRuntime\ReferenceArrayImplBase.cs" />
+ <Compile Include="System\Runtime\InteropServices\WindowsRuntime\ReferenceImpl.cs" />
+ <Compile Include="System\Runtime\InteropServices\WindowsRuntime\WindowsRuntimeImportAttribute.cs" />
+
+ </ItemGroup>
+
+ <ItemGroup>
+ <Compile Include="Windows\Foundation\IKeyValuePair.cs" />
+ <Compile Include="Windows\Foundation\IReference.cs" />
+ <Compile Include="Windows\Foundation\Point.cs" />
+ <Compile Include="Windows\Foundation\PropertyType.cs" />
+ <Compile Include="Windows\Foundation\Rect.cs" />
+ <Compile Include="Windows\Foundation\Size.cs" />
+ <Compile Include="Windows\Foundation\TokenizerHelper.cs" />
+ </ItemGroup>
+
<Import Project="System.Private.Interop.CoreCLR.csproj" />
</Project>
diff --git a/src/System.Private.Interop/src/System.Private.Interop.Shared.projitems b/src/System.Private.Interop/src/System.Private.Interop.Shared.projitems
index 5b104807a..cb6e6c613 100644
--- a/src/System.Private.Interop/src/System.Private.Interop.Shared.projitems
+++ b/src/System.Private.Interop/src/System.Private.Interop.Shared.projitems
@@ -32,6 +32,7 @@
<Compile Include="Shared\McgGeneratedMarshallingCodeAttribute.cs" />
<Compile Include="Shared\McgHelpers.cs" />
<Compile Include="Shared\McgIntrinsics.cs" />
+ <Compile Include="Shared\McgInternalTypeAttribute.cs" />
<Compile Include="Shared\McgMarshal.cs" />
<Compile Include="Shared\McgMethodNameAttribute.cs" />
<Compile Include="Shared\McgModule.cs" />
@@ -73,4 +74,4 @@
<Compile Include="Interop\Interop.Common.Unix.cs" />
<Compile Include="Interop\Interop.String.Unix.cs" />
</ItemGroup>
-</Project> \ No newline at end of file
+</Project>
diff --git a/src/System.Private.Interop/src/System.Private.Interop.csproj b/src/System.Private.Interop/src/System.Private.Interop.csproj
index 525f210c3..aeadd885e 100644
--- a/src/System.Private.Interop/src/System.Private.Interop.csproj
+++ b/src/System.Private.Interop/src/System.Private.Interop.csproj
@@ -41,7 +41,6 @@
</Compile>
<Compile Include="Shared\ComException.cs" />
<Compile Include="Shared\Marshal.cs" />
- <Compile Include="Shared\McgInternalTypeAttribute.cs" />
<Compile Condition="'$(EnableWinRT)'=='true'" Include="Shared\WindowsRuntimeMarshal.cs" />
<Compile Include="System\Runtime\InteropServices\AllowReversePInvokeCallsAttribute.cs" />
<Compile Include="System\Runtime\InteropServices\ArrayWithOffset.cs" />
diff --git a/src/System.Private.Interop/src/System/Runtime/InteropServices/WindowsRuntime/CLRIKeyValuePairImpl.cs b/src/System.Private.Interop/src/System/Runtime/InteropServices/WindowsRuntime/CLRIKeyValuePairImpl.cs
new file mode 100644
index 000000000..cd2f1b17e
--- /dev/null
+++ b/src/System.Private.Interop/src/System/Runtime/InteropServices/WindowsRuntime/CLRIKeyValuePairImpl.cs
@@ -0,0 +1,124 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+using Windows.Foundation.Collections;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ [System.Runtime.CompilerServices.DependencyReductionRootAttribute]
+ [McgInternalTypeAttribute]
+ public sealed class CLRIKeyValuePairImpl<K, V> :
+ global::System.Runtime.InteropServices.BoxedKeyValuePair,
+ IKeyValuePair<K, V>, // Use IKeyValuePair<K, V> from S.P.Interop instead of Windows.winmd to loose the dependency between S.P.Interop and Windows.winmd
+ __IUnboxInternal
+ {
+ private global::System.Collections.Generic.KeyValuePair<K, V> _pair;
+
+ public CLRIKeyValuePairImpl(ref global::System.Collections.Generic.KeyValuePair<K, V> pair)
+ {
+ _pair = pair;
+ }
+
+ public K get_Key()
+ {
+ return _pair.Key;
+ }
+
+ [global::System.Runtime.InteropServices.McgAccessor(global::System.Runtime.InteropServices.McgAccessorKind.PropertyGet, "Value")]
+ public V get_Value()
+ {
+ return _pair.Value;
+ }
+
+ public override object GetTarget()
+ {
+ return (object)_pair;
+ }
+
+ /// <summary>
+ /// Called by public object McgModule.Box(object obj, int boxingIndex) after allocating instance
+ /// </summary>
+ /// <param name="pair">KeyValuePair<K, V></param>
+ /// <returns>IKeyValuePair<K,V> instance</returns>
+ public override object Initialize(object pair)
+ {
+ _pair = (global::System.Collections.Generic.KeyValuePair<K, V>)pair;
+
+ return this;
+ }
+
+ /// <summary>
+ /// Get unboxed value
+ /// This method is used by dynamic interop.
+ /// The reason for adding this instance method instead of using static Unbox is to avoid reflection
+ /// </summary>
+ /// <param name="obj">native winrt object or our own boxed KeyValuePair<K,V></K></param>
+ /// <returns>unboxed value as object</returns>
+ public object get_Value(object obj)
+ {
+ return Unbox(obj);
+ }
+
+ /// <summary>
+ /// This method is called from ComInterop.cs in the Unboxing code.
+ /// </summary>
+ /// <param name="wrapper">native winrt object or our own boxed KeyValuePair<K,V></param>
+ /// <returns>unboxed value as object</returns>
+ public static object Unbox(object wrapper)
+ {
+ CLRIKeyValuePairImpl<K, V> reference = wrapper as CLRIKeyValuePairImpl<K, V>;
+
+ if (reference != null)
+ {
+ return reference._pair;
+ }
+ else
+ {
+ // We could just have the native IKeyValuePair in which case we simply return wrapper as IKeyValuePair.
+ global::Windows.Foundation.Collections.IKeyValuePair<K, V> iPair = wrapper as global::Windows.Foundation.Collections.IKeyValuePair<K, V>;
+ return new System.Collections.Generic.KeyValuePair<K, V>(iPair.get_Key(), iPair.get_Value());
+ }
+ }
+
+ public override string ToString()
+ {
+ return _pair.ToString();
+ }
+ }
+
+ [System.Runtime.CompilerServices.DependencyReductionRootAttribute]
+ [McgInternalTypeAttribute]
+ public sealed class CLRIKeyValuePairArrayImpl<K, V> : global::System.Runtime.InteropServices.BoxedKeyValuePair
+ {
+ private object _pairs;
+
+ /// <summary>
+ /// Called by public object McgModule.Box(object obj, int boxingIndex) after allocating instance
+ /// </summary>
+ /// <param name="pairs">KeyValuePair<K,V>[]</param>
+ /// <returns>IReferenceArrayImpl<K,V> instance</K></returns>
+ public override object Initialize(object pairs)
+ {
+ _pairs = pairs;
+
+ global::System.Collections.Generic.KeyValuePair<K, V>[] unboxedPairArray = pairs as global::System.Collections.Generic.KeyValuePair<K, V>[];
+
+ object[] boxedKeyValuePairs = new object[unboxedPairArray.Length];
+
+ for (int i = 0; i < unboxedPairArray.Length; i++)
+ {
+ boxedKeyValuePairs[i] = new CLRIKeyValuePairImpl<K, V>(ref unboxedPairArray[i]);
+ }
+
+ // Lets create the IReferenceArrayImpl of the type.
+ return new ReferenceArrayImpl<object>(boxedKeyValuePairs, global::Windows.Foundation.PropertyType.InspectableArray);
+ }
+
+ public override object GetTarget()
+ {
+ return (object)_pairs;
+ }
+ }
+}
diff --git a/src/System.Private.Interop/src/System/Runtime/InteropServices/WindowsRuntime/IPropertyValue.cs b/src/System.Private.Interop/src/System/Runtime/InteropServices/WindowsRuntime/IPropertyValue.cs
new file mode 100644
index 000000000..fe48ecf89
--- /dev/null
+++ b/src/System.Private.Interop/src/System/Runtime/InteropServices/WindowsRuntime/IPropertyValue.cs
@@ -0,0 +1,62 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Windows.Foundation;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ [ComImport]
+ [Guid("4bd682dd-7554-40e9-9a9b-82654ede7e62")]
+ [WindowsRuntimeImport]
+ public interface IPropertyValue
+ {
+ PropertyType Type
+ {
+ get;
+ }
+
+ bool IsNumericScalar
+ {
+ get;
+ }
+
+ Byte GetUInt8();
+ Int16 GetInt16();
+ UInt16 GetUInt16();
+ Int32 GetInt32();
+ UInt32 GetUInt32();
+ Int64 GetInt64();
+ UInt64 GetUInt64();
+ Single GetSingle();
+ Double GetDouble();
+ char GetChar16();
+ Boolean GetBoolean();
+ String GetString();
+ Guid GetGuid();
+ DateTimeOffset GetDateTime();
+ TimeSpan GetTimeSpan();
+ Point GetPoint();
+ Size GetSize();
+ Rect GetRect();
+ void GetUInt8Array(out byte[] array);
+ void GetInt16Array(out Int16[] array);
+ void GetUInt16Array(out UInt16[] array);
+ void GetInt32Array(out Int32[] array);
+ void GetUInt32Array(out UInt32[] array);
+ void GetInt64Array(out Int64[] array);
+ void GetUInt64Array(out UInt64[] array);
+ void GetSingleArray(out Single[] array);
+ void GetDoubleArray(out Double[] array);
+ void GetChar16Array(out char[] array);
+ void GetBooleanArray(out Boolean[] array);
+ void GetStringArray(out String[] array);
+ void GetInspectableArray(out object[] array);
+ void GetGuidArray(out Guid[] array);
+ void GetDateTimeArray(out DateTimeOffset[] array);
+ void GetTimeSpanArray(out TimeSpan[] array);
+ void GetPointArray(out Point[] array);
+ void GetSizeArray(out Size[] array);
+ void GetRectArray(out Rect[] array);
+ }
+}
diff --git a/src/System.Private.Interop/src/System/Runtime/InteropServices/WindowsRuntime/IReadOnlyListAdapter.cs b/src/System.Private.Interop/src/System/Runtime/InteropServices/WindowsRuntime/IReadOnlyListAdapter.cs
new file mode 100644
index 000000000..bd082361a
--- /dev/null
+++ b/src/System.Private.Interop/src/System/Runtime/InteropServices/WindowsRuntime/IReadOnlyListAdapter.cs
@@ -0,0 +1,26 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ /// <summary>
+ /// IReadOnlyCollection is generic, so we can't invoke Count without knowing T. Instead, we
+ // introduce a new non-generic interface for our adapters, so we can have a non-generic helper
+ // for the call.
+ /// </summary>
+ public interface IReadOnlyCollectionAdapter
+ {
+ int Count { get; }
+ }
+
+ public interface IReadOnlyListAdapter<out T> : IReadOnlyCollectionAdapter
+ {
+ T this[int index] { get; }
+ }
+}
diff --git a/src/System.Private.Interop/src/System/Runtime/InteropServices/WindowsRuntime/IReferenceArray.cs b/src/System.Private.Interop/src/System/Runtime/InteropServices/WindowsRuntime/IReferenceArray.cs
new file mode 100644
index 000000000..d10421bd6
--- /dev/null
+++ b/src/System.Private.Interop/src/System/Runtime/InteropServices/WindowsRuntime/IReferenceArray.cs
@@ -0,0 +1,15 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ [ComImport]
+ [Guid("61c17707-2d65-11e0-9ae8-d48564015472")]
+ [WindowsRuntimeImport]
+ // T can be any WinRT-compatible type, including reference types.
+ public interface IReferenceArray<T> : IPropertyValue
+ {
+ T[] get_Value();
+ }
+}
diff --git a/src/System.Private.Interop/src/System/Runtime/InteropServices/WindowsRuntime/PropertyValueImpl.cs b/src/System.Private.Interop/src/System/Runtime/InteropServices/WindowsRuntime/PropertyValueImpl.cs
new file mode 100644
index 000000000..e4302be2f
--- /dev/null
+++ b/src/System.Private.Interop/src/System/Runtime/InteropServices/WindowsRuntime/PropertyValueImpl.cs
@@ -0,0 +1,480 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.WindowsRuntime;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ [System.Runtime.CompilerServices.DependencyReductionRootAttribute]
+ [McgInternalTypeAttribute]
+ public class PropertyValueImpl : BoxedValue, IPropertyValue
+ {
+ internal PropertyValueImpl(object val, int type) : base(val, type)
+ {
+ }
+
+ public global::Windows.Foundation.PropertyType Type
+ {
+ get
+ {
+ return (global::Windows.Foundation.PropertyType)m_type;
+ }
+ }
+
+ public bool IsNumericScalar
+ {
+ get
+ {
+ return IsNumericScalarImpl((global::Windows.Foundation.PropertyType)m_type, m_data);
+ }
+ }
+
+ public byte GetUInt8()
+ {
+ return CoerceScalarValue<byte>(global::Windows.Foundation.PropertyType.UInt8);
+ }
+
+ public short GetInt16()
+ {
+ return CoerceScalarValue<short>(global::Windows.Foundation.PropertyType.Int16);
+ }
+
+ public ushort GetUInt16()
+ {
+ return CoerceScalarValue<ushort>(global::Windows.Foundation.PropertyType.UInt16);
+ }
+
+ public int GetInt32()
+ {
+ return CoerceScalarValue<int>(global::Windows.Foundation.PropertyType.Int32);
+ }
+
+ public uint GetUInt32()
+ {
+ return CoerceScalarValue<uint>(global::Windows.Foundation.PropertyType.UInt32);
+ }
+
+ public long GetInt64()
+ {
+ return CoerceScalarValue<long>(global::Windows.Foundation.PropertyType.Int64);
+ }
+
+ public ulong GetUInt64()
+ {
+ return CoerceScalarValue<ulong>(global::Windows.Foundation.PropertyType.UInt64);
+ }
+
+ public float GetSingle()
+ {
+ return CoerceScalarValue<float>(global::Windows.Foundation.PropertyType.Single);
+ }
+
+ public double GetDouble()
+ {
+ return CoerceScalarValue<double>(global::Windows.Foundation.PropertyType.Double);
+ }
+
+ public char GetChar16()
+ {
+ CheckType(global::Windows.Foundation.PropertyType.Char16);
+ return (char)m_data;
+ }
+
+ public bool GetBoolean()
+ {
+ CheckType(global::Windows.Foundation.PropertyType.Boolean);
+ return (bool)m_data;
+ }
+
+ public string GetString()
+ {
+ return CoerceScalarValue<string>(global::Windows.Foundation.PropertyType.String);
+ }
+
+ public object GetInspectable()
+ {
+ CheckType(global::Windows.Foundation.PropertyType.Inspectable);
+ return m_data;
+ }
+
+ public System.Guid GetGuid()
+ {
+ return CoerceScalarValue<System.Guid>(global::Windows.Foundation.PropertyType.Guid);
+ }
+
+ public System.DateTimeOffset GetDateTime()
+ {
+ CheckType(global::Windows.Foundation.PropertyType.DateTime);
+ return (System.DateTimeOffset)m_data;
+ }
+
+ public System.TimeSpan GetTimeSpan()
+ {
+ CheckType(global::Windows.Foundation.PropertyType.TimeSpan);
+ return (System.TimeSpan)m_data;
+ }
+
+ public global::Windows.Foundation.Point GetPoint()
+ {
+ CheckType(global::Windows.Foundation.PropertyType.Point);
+ return (global::Windows.Foundation.Point)m_data;
+ }
+
+ public global::Windows.Foundation.Size GetSize()
+ {
+ CheckType(global::Windows.Foundation.PropertyType.Size);
+ return (global::Windows.Foundation.Size)m_data;
+ }
+
+ public global::Windows.Foundation.Rect GetRect()
+ {
+ CheckType(global::Windows.Foundation.PropertyType.Rect);
+ return (global::Windows.Foundation.Rect)m_data;
+ }
+
+ public void GetUInt8Array(out byte[] array)
+ {
+ array = CoerceArrayValue<byte>(global::Windows.Foundation.PropertyType.UInt8Array);
+ }
+
+ public void GetInt16Array(out short[] array)
+ {
+ array = CoerceArrayValue<short>(global::Windows.Foundation.PropertyType.Int16Array);
+ }
+
+ public void GetUInt16Array(out ushort[] array)
+ {
+ array = CoerceArrayValue<ushort>(global::Windows.Foundation.PropertyType.UInt16Array);
+ }
+
+ public void GetInt32Array(out int[] array)
+ {
+ array = CoerceArrayValue<int>(global::Windows.Foundation.PropertyType.Int32Array);
+ }
+
+ public void GetUInt32Array(out uint[] array)
+ {
+ array = CoerceArrayValue<uint>(global::Windows.Foundation.PropertyType.UInt32Array);
+ }
+
+ public void GetInt64Array(out long[] array)
+ {
+ array = CoerceArrayValue<long>(global::Windows.Foundation.PropertyType.Int64Array);
+ }
+
+ public void GetUInt64Array(out ulong[] array)
+ {
+ array = CoerceArrayValue<ulong>(global::Windows.Foundation.PropertyType.UInt64Array);
+ }
+
+ public void GetSingleArray(out float[] array)
+ {
+ array = CoerceArrayValue<float>(global::Windows.Foundation.PropertyType.SingleArray);
+ }
+
+ public void GetDoubleArray(out double[] array)
+ {
+ array = CoerceArrayValue<double>(global::Windows.Foundation.PropertyType.DoubleArray);
+ }
+
+ public void GetChar16Array(out char[] array)
+ {
+ CheckType(global::Windows.Foundation.PropertyType.Char16Array);
+ array = (char[])m_data;
+ }
+
+ public void GetBooleanArray(out bool[] array)
+ {
+ CheckType(global::Windows.Foundation.PropertyType.BooleanArray);
+ array = (bool[])m_data;
+ }
+
+ public void GetStringArray(out string[] array)
+ {
+ array = CoerceArrayValue<string>(global::Windows.Foundation.PropertyType.StringArray);
+ }
+
+ public void GetInspectableArray(out object[] array)
+ {
+ CheckType(global::Windows.Foundation.PropertyType.InspectableArray);
+ array = (object[])m_data;
+ }
+
+ public void GetGuidArray(out System.Guid[] array)
+ {
+ array = CoerceArrayValue<System.Guid>(global::Windows.Foundation.PropertyType.GuidArray);
+ }
+
+ public void GetDateTimeArray(out System.DateTimeOffset[] array)
+ {
+ CheckType(global::Windows.Foundation.PropertyType.DateTimeArray);
+ array = (System.DateTimeOffset[])m_data;
+ }
+
+ public void GetTimeSpanArray(out System.TimeSpan[] array)
+ {
+ CheckType(global::Windows.Foundation.PropertyType.TimeSpanArray);
+ array = (System.TimeSpan[])m_data;
+ }
+
+ public void GetPointArray(out global::Windows.Foundation.Point[] array)
+ {
+ CheckType(global::Windows.Foundation.PropertyType.PointArray);
+ array = (global::Windows.Foundation.Point[])m_data;
+ }
+
+ public void GetSizeArray(out global::Windows.Foundation.Size[] array)
+ {
+ CheckType(global::Windows.Foundation.PropertyType.SizeArray);
+ array = (global::Windows.Foundation.Size[])m_data;
+ }
+
+ public void GetRectArray(out global::Windows.Foundation.Rect[] array)
+ {
+ CheckType(global::Windows.Foundation.PropertyType.RectArray);
+ array = (global::Windows.Foundation.Rect[])m_data;
+ }
+
+ private T[] CoerceArrayValue<T>(global::Windows.Foundation.PropertyType unboxType)
+ {
+ // If we contain the type being looked for directly, then take the fast-path
+ if (m_type == (int)unboxType)
+ {
+ return (T[])m_data;
+ }
+
+ // Make sure we have an array to begin with
+ System.Array dataArray = m_data as System.Array;
+
+ if (dataArray == null)
+ {
+ throw CreateExceptionForInvalidCast((global::Windows.Foundation.PropertyType)m_type, unboxType);
+ }
+
+ // Array types are 1024 larger than their equivilent scalar counterpart
+ if ((m_type <= 1024) || ((int)unboxType <= 1024))
+ {
+ throw CreateExceptionForInvalidCast((global::Windows.Foundation.PropertyType)m_type, unboxType);
+ }
+
+ global::Windows.Foundation.PropertyType scalarType = (global::Windows.Foundation.PropertyType)(m_type - 1024);
+ global::Windows.Foundation.PropertyType unboxTypeT = unboxType - 1024;
+
+ // If we do not have the correct array type, then we need to convert the array element-by-element
+ // to a new array of the requested type
+ T[] coercedArray = new T[dataArray.Length];
+
+ for (int i = 0; i < dataArray.Length; ++i)
+ {
+ coercedArray[i] = (T)CoerceScalarValue(scalarType, dataArray.GetValue(i), unboxTypeT);
+ }
+
+ return coercedArray;
+ }
+
+ [System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+ private T CoerceScalarValue<T>(global::Windows.Foundation.PropertyType unboxType)
+ {
+ object result = m_data;
+
+ // If we are just a boxed version of the requested type, then take the fast path out
+ if (m_type != (int)unboxType)
+ {
+ result = CoerceScalarValue((global::Windows.Foundation.PropertyType)m_type, result, unboxType);
+ }
+
+ return (T)result;
+ }
+
+ static private object CoerceScalarValue(global::Windows.Foundation.PropertyType type, object value, global::Windows.Foundation.PropertyType unboxType)
+ {
+ // If the property type is neither one of the coercable numeric types nor IInspectable, we
+ // should not attempt coersion, even if the underlying value is technically convertable
+ if ((type == global::Windows.Foundation.PropertyType.Guid) && (unboxType == global::Windows.Foundation.PropertyType.String))
+ {
+ // String <--> Guid is allowed
+ return ((System.Guid)value).ToString();
+ }
+ else if ((type == global::Windows.Foundation.PropertyType.String) && (unboxType == global::Windows.Foundation.PropertyType.Guid))
+ {
+ System.Guid result;
+
+ if (System.Guid.TryParse((string)value, out result))
+ {
+ return result;
+ }
+ }
+ else if (type == global::Windows.Foundation.PropertyType.Inspectable)
+ {
+ // If the property type is IInspectable, and we have a nested IPropertyValue, then we need
+ // to pass along the request to coerce the value.
+ IPropertyValue ipv = value as IPropertyValue;
+
+ if (ipv != null)
+ {
+ object result = ReferenceUtility.GetWellKnownScalar(ipv, unboxType);
+
+ if (result != null)
+ {
+ return result;
+ }
+
+ Debug.Assert(
+ false,
+ "T in coersion function wasn't understood as a type that can be coerced - make sure that CoerceScalarValue and NumericScalarTypes are in sync"
+ );
+ }
+ }
+ else if (type == global::Windows.Foundation.PropertyType.Boolean || type == global::Windows.Foundation.PropertyType.Char16)
+ {
+ throw CreateExceptionForInvalidCoersion(type, value, unboxType, Interop.COM.TYPE_E_TYPEMISMATCH);
+ }
+
+ //
+ // Let Convert handle all possible conversions - this include
+ // 1. string - which desktop code accidentally allowed
+ // 2. object (IInspectable)
+ //
+ try
+ {
+ switch (unboxType)
+ {
+ case global::Windows.Foundation.PropertyType.UInt8:
+ return System.Convert.ToByte(value);
+
+ case global::Windows.Foundation.PropertyType.Int16:
+ return System.Convert.ToInt16(value);
+
+ case global::Windows.Foundation.PropertyType.UInt16:
+ return System.Convert.ToUInt16(value);
+
+ case global::Windows.Foundation.PropertyType.Int32:
+ return System.Convert.ToInt32(value);
+
+ case global::Windows.Foundation.PropertyType.UInt32:
+ return System.Convert.ToUInt32(value);
+
+ case global::Windows.Foundation.PropertyType.Int64:
+ return System.Convert.ToInt64(value);
+
+ case global::Windows.Foundation.PropertyType.UInt64:
+ return System.Convert.ToUInt64(value);
+
+ case global::Windows.Foundation.PropertyType.Single:
+ return System.Convert.ToSingle(value);
+
+ case global::Windows.Foundation.PropertyType.Double:
+ return System.Convert.ToDouble(value);
+
+ default:
+ break;
+ }
+ }
+ catch (System.FormatException)
+ {
+ throw CreateExceptionForInvalidCoersion(type, value, unboxType, Interop.COM.TYPE_E_TYPEMISMATCH);
+ }
+ catch (System.InvalidCastException)
+ {
+ throw CreateExceptionForInvalidCoersion(type, value, unboxType, Interop.COM.TYPE_E_TYPEMISMATCH);
+ }
+ catch (System.OverflowException)
+ {
+ throw CreateExceptionForInvalidCoersion(type, value, unboxType, Interop.COM.DISP_E_OVERFLOW);
+ }
+
+ throw CreateExceptionForInvalidCast(type, unboxType);
+ }
+
+ private static bool IsNumericScalarImpl(global::Windows.Foundation.PropertyType type, object data)
+ {
+ switch (type)
+ {
+ case global::Windows.Foundation.PropertyType.UInt8:
+ case global::Windows.Foundation.PropertyType.Int16:
+ case global::Windows.Foundation.PropertyType.UInt16:
+ case global::Windows.Foundation.PropertyType.Int32:
+ case global::Windows.Foundation.PropertyType.UInt32:
+ case global::Windows.Foundation.PropertyType.Int64:
+ case global::Windows.Foundation.PropertyType.UInt64:
+ case global::Windows.Foundation.PropertyType.Single:
+ case global::Windows.Foundation.PropertyType.Double:
+ return true;
+
+ default:
+ return McgMarshal.IsEnum(data);
+ }
+ }
+
+ private void CheckType(global::Windows.Foundation.PropertyType unboxType)
+ {
+ if (this.Type != unboxType)
+ {
+ throw CreateExceptionForInvalidCast(this.Type, unboxType);
+ }
+ }
+
+ private static System.InvalidCastException CreateExceptionForInvalidCast(
+ global::Windows.Foundation.PropertyType type,
+ global::Windows.Foundation.PropertyType unboxType)
+ {
+ System.InvalidCastException ex = new System.InvalidCastException(SR.Format(SR.PropertyValue_InvalidCast, type, unboxType));
+ McgMarshal.SetExceptionErrorCode(ex, Interop.COM.TYPE_E_TYPEMISMATCH);
+ return ex;
+ }
+
+ private static System.InvalidCastException CreateExceptionForInvalidCoersion(
+ global::Windows.Foundation.PropertyType type,
+ object value,
+ global::Windows.Foundation.PropertyType unboxType,
+ int hr)
+ {
+ InvalidCastException ex = new InvalidCastException(SR.Format(SR.PropertyValue_InvalidCoersion, type, value, unboxType));
+ McgMarshal.SetExceptionErrorCode(ex, hr);
+ return ex;
+ }
+ }
+
+ internal class ReferenceUtility
+ {
+ internal static object GetWellKnownScalar(IPropertyValue ipv, global::Windows.Foundation.PropertyType type)
+ {
+ switch (type)
+ {
+ case global::Windows.Foundation.PropertyType.UInt8:
+ return ipv.GetUInt8();
+
+ case global::Windows.Foundation.PropertyType.Int16:
+ return ipv.GetInt16();
+
+ case global::Windows.Foundation.PropertyType.UInt16:
+ return ipv.GetUInt16();
+
+ case global::Windows.Foundation.PropertyType.Int32:
+ return ipv.GetInt32();
+
+ case global::Windows.Foundation.PropertyType.UInt32:
+ return ipv.GetUInt32();
+
+ case global::Windows.Foundation.PropertyType.Int64:
+ return ipv.GetInt64();
+
+ case global::Windows.Foundation.PropertyType.UInt64:
+ return ipv.GetUInt64();
+
+ case global::Windows.Foundation.PropertyType.Single:
+ return ipv.GetSingle();
+
+ case global::Windows.Foundation.PropertyType.Double:
+ return ipv.GetDouble();
+ }
+
+ Debug.Assert(false);
+ return null;
+ }
+ }
+}
diff --git a/src/System.Private.Interop/src/System/Runtime/InteropServices/WindowsRuntime/ReferenceArrayImpl.cs b/src/System.Private.Interop/src/System/Runtime/InteropServices/WindowsRuntime/ReferenceArrayImpl.cs
new file mode 100644
index 000000000..4542d1372
--- /dev/null
+++ b/src/System.Private.Interop/src/System/Runtime/InteropServices/WindowsRuntime/ReferenceArrayImpl.cs
@@ -0,0 +1,33 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ /// <summary>
+ /// A managed wrapper of IReferenceArray<T>
+ /// </summary>
+ [System.Runtime.CompilerServices.DependencyReductionRootAttribute]
+ [McgInternalTypeAttribute]
+ public sealed class ReferenceArrayImpl<T> : ReferenceArrayImplBase, IReferenceArray<T>
+ {
+ private T[] _value;
+
+ public ReferenceArrayImpl(T[] obj, global::Windows.Foundation.PropertyType type) : base(obj, type)
+ {
+ _value = obj;
+ m_unboxed = true;
+ }
+
+ public T[] get_Value()
+ {
+ if (!m_unboxed)
+ {
+ _value = (T[])m_data;
+ m_unboxed = true;
+ }
+
+ return _value;
+ }
+ }
+}
diff --git a/src/System.Private.Interop/src/System/Runtime/InteropServices/WindowsRuntime/ReferenceArrayImplBase.cs b/src/System.Private.Interop/src/System/Runtime/InteropServices/WindowsRuntime/ReferenceArrayImplBase.cs
new file mode 100644
index 000000000..8f0863a56
--- /dev/null
+++ b/src/System.Private.Interop/src/System/Runtime/InteropServices/WindowsRuntime/ReferenceArrayImplBase.cs
@@ -0,0 +1,178 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ [System.Runtime.CompilerServices.DependencyReductionRootAttribute]
+ [McgInternalTypeAttribute]
+ public class ReferenceArrayImplBase :
+ PropertyValueImpl,
+ System.Collections.IList,
+ System.Collections.Generic.IEnumerable<object>
+#if SUPPORTS_ICustomQueryInterface
+ ,System.Runtime.InteropServices.ICustomQueryInterface
+#endif
+ {
+ // pinterface({faa585ea-6214-4217-afda-7f46de5869b3};cinterface(IInspectable))
+ internal static System.Guid IID_IIterableOfObject =
+ new System.Guid(153846939, 24753, 21182, 0xA4, 0x4A, 0x6F, 0xE8, 0xE9, 0x33, 0xCB, 0xE4);
+
+ private System.Collections.IList _list;
+ private System.Collections.Generic.IEnumerable<object> _enumerableOfObject;
+
+ public override void Initialize(object val, int type)
+ {
+ m_data = val;
+ m_type = (short)type;
+
+ // This should not fail but I'm making a cast here anyway just in case
+ // we have a bug or there is a runtime failure
+ _list = (System.Collections.IList)val;
+
+ // Not every array implements IEnumerable<Object>
+ _enumerableOfObject = val as System.Collections.Generic.IEnumerable<object>;
+ }
+
+ internal ReferenceArrayImplBase(object data, global::Windows.Foundation.PropertyType type) : base(data, (int)type)
+ {
+ Initialize(data, (int)type);
+ }
+
+#if SUPPORTS_ICustomQueryInterface
+ //
+ // Customize QI behavior:
+ // If this array type doesn't implement IEnumerable<Object>, reject IIterable<Object>
+ //
+ System.Runtime.InteropServices.CustomQueryInterfaceResult ICustomQueryInterface.GetInterface(ref System.Guid iid, out System.IntPtr ppv)
+ {
+ ppv = default(System.IntPtr);
+
+ if (System.Runtime.InteropServices.McgMarshal.GuidEquals(ref iid, ref IID_IIterableOfObject))
+ {
+ if (_enumerableOfObject == null)
+ {
+ // This array type doesn't actually support IEnumerable<Object>
+ // Reject the QI
+ return System.Runtime.InteropServices.CustomQueryInterfaceResult.Failed;
+ }
+ }
+
+ return System.Runtime.InteropServices.CustomQueryInterfaceResult.NotHandled;
+ }
+#endif
+ //
+ // IEnumerable methods. Used by data-binding in Jupiter when you try to data bind
+ // against a managed array
+ //
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
+ {
+ return ((System.Collections.IEnumerable)_list).GetEnumerator();
+ }
+
+ //
+ // IEnumerable<object> methods. We need this because System.Array implement this (implicitly) if it is castable to object[]
+ //
+ System.Collections.Generic.IEnumerator<object> System.Collections.Generic.IEnumerable<object>.GetEnumerator()
+ {
+ return _enumerableOfObject.GetEnumerator();
+ }
+
+ //
+ // IList & ICollection methods.
+ // This enables two-way data binding and index access in Jupiter
+ //
+ object System.Collections.IList.this[int index]
+ {
+ get
+ {
+ return _list[index];
+ }
+
+ set
+ {
+ _list[index] = value;
+ }
+ }
+
+ int System.Collections.IList.Add(object value)
+ {
+ return _list.Add(value);
+ }
+
+ bool System.Collections.IList.Contains(object value)
+ {
+ return _list.Contains(value);
+ }
+
+ void System.Collections.IList.Clear()
+ {
+ _list.Clear();
+ }
+
+ bool System.Collections.IList.IsReadOnly
+ {
+ get
+ {
+ return _list.IsReadOnly;
+ }
+ }
+
+ bool System.Collections.IList.IsFixedSize
+ {
+ get
+ {
+ return _list.IsFixedSize;
+ }
+ }
+
+ int System.Collections.IList.IndexOf(object value)
+ {
+ return _list.IndexOf(value);
+ }
+
+ void System.Collections.IList.Insert(int index, object value)
+ {
+ _list.Insert(index, value);
+ }
+
+ void System.Collections.IList.Remove(object value)
+ {
+ _list.Remove(value);
+ }
+
+ void System.Collections.IList.RemoveAt(int index)
+ {
+ _list.RemoveAt(index);
+ }
+
+ void System.Collections.ICollection.CopyTo(System.Array array, int index)
+ {
+ _list.CopyTo(array, index);
+ }
+
+ int System.Collections.ICollection.Count
+ {
+ get
+ {
+ return _list.Count;
+ }
+ }
+
+ object System.Collections.ICollection.SyncRoot
+ {
+ get
+ {
+ return _list.SyncRoot;
+ }
+ }
+
+ bool System.Collections.ICollection.IsSynchronized
+ {
+ get
+ {
+ return _list.IsSynchronized;
+ }
+ }
+ }
+}
diff --git a/src/System.Private.Interop/src/System/Runtime/InteropServices/WindowsRuntime/ReferenceImpl.cs b/src/System.Private.Interop/src/System/Runtime/InteropServices/WindowsRuntime/ReferenceImpl.cs
new file mode 100644
index 000000000..a1dce0b06
--- /dev/null
+++ b/src/System.Private.Interop/src/System/Runtime/InteropServices/WindowsRuntime/ReferenceImpl.cs
@@ -0,0 +1,40 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ /// <summary>
+ /// A managed wrapper for IPropertyValue and IReference<T>
+ /// </summary>
+ [System.Runtime.CompilerServices.DependencyReductionRootAttribute]
+ [McgInternalTypeAttribute]
+ public class ReferenceImpl<T> : PropertyValueImpl, global::Windows.Foundation.IReference<T>
+ {
+ private T m_value;
+
+ public ReferenceImpl(T data, int type)
+ : base(data, type)
+ {
+ m_unboxed = true;
+ m_value = data;
+ }
+
+ internal ReferenceImpl(T data, global::Windows.Foundation.PropertyType type)
+ : base(data, (int)type)
+ {
+ m_unboxed = true;
+ m_value = data;
+ }
+
+ public T get_Value()
+ {
+ if (!m_unboxed)
+ {
+ m_value = (T)m_data;
+ m_unboxed = true;
+ }
+ return m_value;
+ }
+ }
+}
diff --git a/src/System.Private.Interop/src/System/Runtime/InteropServices/WindowsRuntime/__IUnboxInternal.cs b/src/System.Private.Interop/src/System/Runtime/InteropServices/WindowsRuntime/__IUnboxInternal.cs
new file mode 100644
index 000000000..1cad7be84
--- /dev/null
+++ b/src/System.Private.Interop/src/System/Runtime/InteropServices/WindowsRuntime/__IUnboxInternal.cs
@@ -0,0 +1,18 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ /// <summary>
+ /// Interface to help get unboxed value from IReference<T>/IReferenceArray<T>/IKeyValuePair<K,V>
+ /// </summary>
+ [System.Runtime.CompilerServices.DependencyReductionRootAttribute]
+ internal interface __IUnboxInternal
+ {
+ Object get_Value(Object obj);
+ }
+}
diff --git a/src/System.Private.Interop/src/Windows/Foundation/IKeyValuePair.cs b/src/System.Private.Interop/src/Windows/Foundation/IKeyValuePair.cs
new file mode 100644
index 000000000..88ba75437
--- /dev/null
+++ b/src/System.Private.Interop/src/Windows/Foundation/IKeyValuePair.cs
@@ -0,0 +1,18 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.WindowsRuntime;
+
+namespace Windows.Foundation.Collections
+{
+ [ComImport]
+ [Guid("02b51929-c1c4-4a7e-8940-0312b5c18500")]
+ [WindowsRuntimeImport]
+ public unsafe interface IKeyValuePair<K, V>
+ {
+ K get_Key();
+ V get_Value();
+ }
+}
diff --git a/src/System.Private.Interop/src/Windows/Foundation/IReference.cs b/src/System.Private.Interop/src/Windows/Foundation/IReference.cs
new file mode 100644
index 000000000..dc498b8f8
--- /dev/null
+++ b/src/System.Private.Interop/src/Windows/Foundation/IReference.cs
@@ -0,0 +1,13 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace Windows.Foundation
+{
+ [System.Runtime.CompilerServices.DependencyReductionRootAttribute]
+ public interface IReference<T>
+ {
+ [System.Runtime.InteropServices.McgAccessor(System.Runtime.InteropServices.McgAccessorKind.PropertyGet, "Value")]
+ T get_Value();
+ }
+}
diff --git a/src/System.Private.Interop/src/Windows/Foundation/Point.cs b/src/System.Private.Interop/src/Windows/Foundation/Point.cs
new file mode 100644
index 000000000..aa96bbd36
--- /dev/null
+++ b/src/System.Private.Interop/src/Windows/Foundation/Point.cs
@@ -0,0 +1,120 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Globalization;
+using System.Runtime.InteropServices;
+
+#if !FEATURE_SLJ_PROJECTION_COMPAT
+#pragma warning disable 436 // Redefining types from Windows.Foundation
+#endif // !FEATURE_SLJ_PROJECTION_COMPAT
+
+#if FEATURE_SLJ_PROJECTION_COMPAT
+namespace System.Windows
+#else // !FEATURE_SLJ_PROJECTION_COMPAT
+
+
+namespace Windows.Foundation
+#endif // FEATURE_SLJ_PROJECTION_COMPAT
+{
+ //
+ // Point is the managed projection of Windows.Foundation.Point. Any changes to the layout
+ // of this type must be exactly mirrored on the native WinRT side as well.
+ //
+ // Note that this type is owned by the Jupiter team. Please contact them before making any
+ // changes here.
+ //
+ [StructLayout(LayoutKind.Sequential)]
+ public struct Point : IFormattable
+ {
+ internal float _x;
+ internal float _y;
+
+ public Point(double x, double y)
+ {
+ _x = (float)x;
+ _y = (float)y;
+ }
+
+ public double X
+ {
+ get { return _x; }
+ set { _x = (float)value; }
+ }
+
+ public double Y
+ {
+ get { return _y; }
+ set { _y = (float)value; }
+ }
+
+ public override string ToString()
+ {
+ // Delegate to the internal method which implements all ToString calls.
+ return ConvertToString(null /* format string */, null /* format provider */);
+ }
+
+ public string ToString(IFormatProvider provider)
+ {
+ // Delegate to the internal method which implements all ToString calls.
+ return ConvertToString(null /* format string */, provider);
+ }
+
+ string IFormattable.ToString(string format, IFormatProvider provider)
+ {
+ // Delegate to the internal method which implements all ToString calls.
+ return ConvertToString(format, provider);
+ }
+
+ private string ConvertToString(string format, IFormatProvider provider)
+ {
+ // Helper to get the numeric list separator for a given culture.
+ char separator = TokenizerHelper.GetNumericListSeparator(provider);
+ return String.Format(provider,
+ "{1:" + format + "}{0}{2:" + format + "}",
+ separator,
+ _x,
+ _y);
+ }
+
+ public static bool operator ==(Point point1, Point point2)
+ {
+ return point1.X == point2.X &&
+ point1.Y == point2.Y;
+ }
+
+ public static bool operator !=(Point point1, Point point2)
+ {
+ return !(point1 == point2);
+ }
+
+ public override bool Equals(object o)
+ {
+ if ((null == o) || !(o is Point))
+ {
+ return false;
+ }
+
+ Point value = (Point)o;
+ return (this == value);
+ }
+
+ public bool Equals(Point value)
+ {
+ return (this == value);
+ }
+
+ public override int GetHashCode()
+ {
+ // Perform field-by-field XOR of HashCodes
+ return X.GetHashCode() ^
+ Y.GetHashCode();
+ }
+ }
+}
+
+#if !FEATURE_SLJ_PROJECTION_COMPAT
+#pragma warning restore 436
+#endif // !FEATURE_SLJ_PROJECTION_COMPAT
+
diff --git a/src/System.Private.Interop/src/Windows/Foundation/PropertyType.cs b/src/System.Private.Interop/src/Windows/Foundation/PropertyType.cs
new file mode 100644
index 000000000..141511fbc
--- /dev/null
+++ b/src/System.Private.Interop/src/Windows/Foundation/PropertyType.cs
@@ -0,0 +1,51 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace Windows.Foundation
+{
+ public enum PropertyType
+ {
+ Empty = 0,
+ UInt8 = 1,
+ Int16 = 2,
+ UInt16 = 3,
+ Int32 = 4,
+ UInt32 = 5,
+ Int64 = 6,
+ UInt64 = 7,
+ Single = 8,
+ Double = 9,
+ Char16 = 10,
+ Boolean = 11,
+ String = 12,
+ Inspectable = 13,
+ DateTime = 14,
+ TimeSpan = 15,
+ Guid = 16,
+ Point = 17,
+ Size = 18,
+ Rect = 19,
+ Other = 20,
+ UInt8Array = 1025,
+ Int16Array = 1026,
+ UInt16Array = 1027,
+ Int32Array = 1028,
+ UInt32Array = 1029,
+ Int64Array = 1030,
+ UInt64Array = 1031,
+ SingleArray = 1032,
+ DoubleArray = 1033,
+ Char16Array = 1034,
+ BooleanArray = 1035,
+ StringArray = 1036,
+ InspectableArray = 1037,
+ DateTimeArray = 1038,
+ TimeSpanArray = 1039,
+ GuidArray = 1040,
+ PointArray = 1041,
+ SizeArray = 1042,
+ RectArray = 1043,
+ OtherArray = 1044
+ }
+}
diff --git a/src/System.Private.Interop/src/Windows/Foundation/Rect.cs b/src/System.Private.Interop/src/Windows/Foundation/Rect.cs
new file mode 100644
index 000000000..91e1ca46f
--- /dev/null
+++ b/src/System.Private.Interop/src/Windows/Foundation/Rect.cs
@@ -0,0 +1,367 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Globalization;
+using System.Runtime.InteropServices;
+
+#if !FEATURE_SLJ_PROJECTION_COMPAT
+#pragma warning disable 436 // Redefining types from Windows.Foundation
+#endif // !FEATURE_SLJ_PROJECTION_COMPAT
+
+#if FEATURE_SLJ_PROJECTION_COMPAT
+namespace System.Windows
+#else // !FEATURE_SLJ_PROJECTION_COMPAT
+
+
+namespace Windows.Foundation
+#endif // FEATURE_SLJ_PROJECTION_COMPAT
+{
+ //
+ // Rect is the managed projection of Windows.Foundation.Rect. Any changes to the layout
+ // of this type must be exactly mirrored on the native WinRT side as well.
+ //
+ // Note that this type is owned by the Jupiter team. Please contact them before making any
+ // changes here.
+ //
+ [StructLayout(LayoutKind.Sequential)]
+ public struct Rect : IFormattable
+ {
+ private float _x;
+ private float _y;
+ private float _width;
+ private float _height;
+
+ private const double EmptyX = Double.PositiveInfinity;
+ private const double EmptyY = Double.PositiveInfinity;
+ private const double EmptyWidth = Double.NegativeInfinity;
+ private const double EmptyHeight = Double.NegativeInfinity;
+
+ private readonly static Rect s_empty = CreateEmptyRect();
+
+ public Rect(double x,
+ double y,
+ double width,
+ double height)
+ {
+ if (width < 0)
+ throw new ArgumentException("width");
+ if (height < 0)
+ throw new ArgumentException("height");
+
+ _x = (float)x;
+ _y = (float)y;
+ _width = (float)width;
+ _height = (float)height;
+ }
+
+ public Rect(Point point1,
+ Point point2)
+ {
+ _x = (float)Math.Min(point1.X, point2.X);
+ _y = (float)Math.Min(point1.Y, point2.Y);
+
+ _width = (float)Math.Max(Math.Max(point1.X, point2.X) - _x, 0);
+ _height = (float)Math.Max(Math.Max(point1.Y, point2.Y) - _y, 0);
+ }
+
+ public Rect(Point location, Size size)
+ {
+ if (size.IsEmpty)
+ {
+ this = s_empty;
+ }
+ else
+ {
+ _x = (float)location.X;
+ _y = (float)location.Y;
+ _width = (float)size.Width;
+ _height = (float)size.Height;
+ }
+ }
+
+ internal static Rect Create(double x,
+ double y,
+ double width,
+ double height)
+ {
+ if (x == EmptyX && y == EmptyY && width == EmptyWidth && height == EmptyHeight)
+ {
+ return Rect.Empty;
+ }
+ else
+ {
+ return new Rect(x, y, width, height);
+ }
+ }
+
+
+ public double X
+ {
+ get { return _x; }
+ set { _x = (float)value; }
+ }
+
+ public double Y
+ {
+ get { return _y; }
+ set { _y = (float)value; }
+ }
+
+ public double Width
+ {
+ get { return _width; }
+ set
+ {
+ if (value < 0)
+ throw new ArgumentException("Width");
+
+ _width = (float)value;
+ }
+ }
+
+ public double Height
+ {
+ get { return _height; }
+ set
+ {
+ if (value < 0)
+ throw new ArgumentException("Height");
+
+ _height = (float)value;
+ }
+ }
+
+ public double Left
+ {
+ get { return _x; }
+ }
+
+ public double Top
+ {
+ get { return _y; }
+ }
+
+ public double Right
+ {
+ get
+ {
+ if (IsEmpty)
+ {
+ return Double.NegativeInfinity;
+ }
+
+ return _x + _width;
+ }
+ }
+
+ public double Bottom
+ {
+ get
+ {
+ if (IsEmpty)
+ {
+ return Double.NegativeInfinity;
+ }
+
+ return _y + _height;
+ }
+ }
+
+ public static Rect Empty
+ {
+ get { return s_empty; }
+ }
+
+ public bool IsEmpty
+ {
+ get { return _width < 0; }
+ }
+
+ public bool Contains(Point point)
+ {
+ return ContainsInternal(point.X, point.Y);
+ }
+
+ public void Intersect(Rect rect)
+ {
+ if (!this.IntersectsWith(rect))
+ {
+ this = s_empty;
+ }
+ else
+ {
+ double left = Math.Max(X, rect.X);
+ double top = Math.Max(Y, rect.Y);
+
+ // Max with 0 to prevent double weirdness from causing us to be (-epsilon..0)
+ Width = Math.Max(Math.Min(X + Width, rect.X + rect.Width) - left, 0);
+ Height = Math.Max(Math.Min(Y + Height, rect.Y + rect.Height) - top, 0);
+
+ X = left;
+ Y = top;
+ }
+ }
+
+ public void Union(Rect rect)
+ {
+ if (IsEmpty)
+ {
+ this = rect;
+ }
+ else if (!rect.IsEmpty)
+ {
+ double left = Math.Min(Left, rect.Left);
+ double top = Math.Min(Top, rect.Top);
+
+
+ // We need this check so that the math does not result in NaN
+ if ((rect.Width == Double.PositiveInfinity) || (Width == Double.PositiveInfinity))
+ {
+ Width = Double.PositiveInfinity;
+ }
+ else
+ {
+ // Max with 0 to prevent double weirdness from causing us to be (-epsilon..0)
+ double maxRight = Math.Max(Right, rect.Right);
+ Width = Math.Max(maxRight - left, 0);
+ }
+
+ // We need this check so that the math does not result in NaN
+ if ((rect.Height == Double.PositiveInfinity) || (Height == Double.PositiveInfinity))
+ {
+ Height = Double.PositiveInfinity;
+ }
+ else
+ {
+ // Max with 0 to prevent double weirdness from causing us to be (-epsilon..0)
+ double maxBottom = Math.Max(Bottom, rect.Bottom);
+ Height = Math.Max(maxBottom - top, 0);
+ }
+
+ X = left;
+ Y = top;
+ }
+ }
+
+ public void Union(Point point)
+ {
+ Union(new Rect(point, point));
+ }
+
+ private bool ContainsInternal(double x, double y)
+ {
+ return ((x >= X) && (x - Width <= X) &&
+ (y >= Y) && (y - Height <= Y));
+ }
+
+ internal bool IntersectsWith(Rect rect)
+ {
+ if (Width < 0 || rect.Width < 0)
+ {
+ return false;
+ }
+
+ return (rect.X <= X + Width) &&
+ (rect.X + rect.Width >= X) &&
+ (rect.Y <= Y + Height) &&
+ (rect.Y + rect.Height >= Y);
+ }
+
+ private static Rect CreateEmptyRect()
+ {
+ Rect rect = new Rect();
+
+ // TODO: for consistency with width/height we should change these
+ // to assign directly to the backing fields.
+ rect.X = EmptyX;
+ rect.Y = EmptyY;
+
+ // the width and height properties prevent assignment of
+ // negative numbers so assign directly to the backing fields.
+ rect._width = (float)EmptyWidth;
+ rect._height = (float)EmptyHeight;
+
+ return rect;
+ }
+
+ public override string ToString()
+ {
+ // Delegate to the internal method which implements all ToString calls.
+ return ConvertToString(null /* format string */, null /* format provider */);
+ }
+
+ public string ToString(IFormatProvider provider)
+ {
+ // Delegate to the internal method which implements all ToString calls.
+ return ConvertToString(null /* format string */, provider);
+ }
+
+ string IFormattable.ToString(string format, IFormatProvider provider)
+ {
+ // Delegate to the internal method which implements all ToString calls.
+ return ConvertToString(format, provider);
+ }
+
+ internal string ConvertToString(string format, IFormatProvider provider)
+ {
+ if (IsEmpty)
+ {
+ return SR.DirectUI_Empty;
+ }
+
+ // Helper to get the numeric list separator for a given culture.
+ char separator = TokenizerHelper.GetNumericListSeparator(provider);
+ return String.Format(provider,
+ "{1:" + format + "}{0}{2:" + format + "}{0}{3:" + format + "}{0}{4:" + format + "}",
+ separator,
+ _x,
+ _y,
+ _width,
+ _height);
+ }
+
+ public bool Equals(Rect value)
+ {
+ return (this == value);
+ }
+
+ public static bool operator ==(Rect rect1, Rect rect2)
+ {
+ return rect1.X == rect2.X &&
+ rect1.Y == rect2.Y &&
+ rect1.Width == rect2.Width &&
+ rect1.Height == rect2.Height;
+ }
+
+ public static bool operator !=(Rect rect1, Rect rect2)
+ {
+ return !(rect1 == rect2);
+ }
+
+ public override bool Equals(object o)
+ {
+ if ((null == o) || !(o is Rect))
+ {
+ return false;
+ }
+
+ Rect value = (Rect)o;
+ return (this == value);
+ }
+
+ public override int GetHashCode()
+ {
+ // Perform field-by-field XOR of HashCodes
+ return X.GetHashCode() ^
+ Y.GetHashCode() ^
+ Width.GetHashCode() ^
+ Height.GetHashCode();
+ }
+ }
+}
+
+#if !FEATURE_SLJ_PROJECTION_COMPAT
+#pragma warning restore 436
+#endif // !FEATURE_SLJ_PROJECTION_COMPAT
diff --git a/src/System.Private.Interop/src/Windows/Foundation/Size.cs b/src/System.Private.Interop/src/Windows/Foundation/Size.cs
new file mode 100644
index 000000000..3e52f8036
--- /dev/null
+++ b/src/System.Private.Interop/src/Windows/Foundation/Size.cs
@@ -0,0 +1,159 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.InteropServices;
+
+#if !FEATURE_SLJ_PROJECTION_COMPAT
+#pragma warning disable 436 // Redefining types from Windows.Foundation
+#endif // !FEATURE_SLJ_PROJECTION_COMPAT
+
+#if FEATURE_SLJ_PROJECTION_COMPAT
+namespace System.Windows
+#else // !FEATURE_SLJ_PROJECTION_COMPAT
+
+
+namespace Windows.Foundation
+#endif // FEATURE_SLJ_PROJECTION_COMPAT
+{
+ //
+ // Size is the managed projection of Windows.Foundation.Size. Any changes to the layout
+ // of this type must be exactly mirrored on the native WinRT side as well.
+ //
+ // Note that this type is owned by the Jupiter team. Please contact them before making any
+ // changes here.
+ //
+ [StructLayout(LayoutKind.Sequential)]
+ public struct Size
+ {
+ private float _width;
+ private float _height;
+
+ private readonly static Size s_empty = CreateEmptySize();
+
+ public Size(double width, double height)
+ {
+ if (width < 0)
+ throw new ArgumentException("width");
+ if (height < 0)
+ throw new ArgumentException("height");
+
+ _width = (float)width;
+ _height = (float)height;
+ }
+
+ public double Width
+ {
+ get { return _width; }
+ set
+ {
+ if (value < 0)
+ throw new ArgumentException("Width");
+
+ _width = (float)value;
+ }
+ }
+
+ public double Height
+ {
+ get { return _height; }
+ set
+ {
+ if (value < 0)
+ throw new ArgumentException("Height");
+
+ _height = (float)value;
+ }
+ }
+
+ public static Size Empty
+ {
+ get { return s_empty; }
+ }
+
+
+ public bool IsEmpty
+ {
+ get { return Width < 0; }
+ }
+
+ static private Size CreateEmptySize()
+ {
+ Size size = new Size();
+ // We can't set these via the property setters because negatives widths
+ // are rejected in those APIs.
+ size._width = Single.NegativeInfinity;
+ size._height = Single.NegativeInfinity;
+ return size;
+ }
+
+ public static bool operator ==(Size size1, Size size2)
+ {
+ return size1.Width == size2.Width &&
+ size1.Height == size2.Height;
+ }
+
+ public static bool operator !=(Size size1, Size size2)
+ {
+ return !(size1 == size2);
+ }
+
+ public override bool Equals(object o)
+ {
+ if ((null == o) || !(o is Size))
+ {
+ return false;
+ }
+
+ Size value = (Size)o;
+ return Size.Equals(this, value);
+ }
+
+ public bool Equals(Size value)
+ {
+ return Size.Equals(this, value);
+ }
+
+ public override int GetHashCode()
+ {
+ if (IsEmpty)
+ {
+ return 0;
+ }
+ else
+ {
+ // Perform field-by-field XOR of HashCodes
+ return Width.GetHashCode() ^
+ Height.GetHashCode();
+ }
+ }
+
+ private static bool Equals(Size size1, Size size2)
+ {
+ if (size1.IsEmpty)
+ {
+ return size2.IsEmpty;
+ }
+ else
+ {
+ return size1.Width.Equals(size2.Width) &&
+ size1.Height.Equals(size2.Height);
+ }
+ }
+
+ public override string ToString()
+ {
+ if (IsEmpty)
+ {
+ return "Empty";
+ }
+
+ return String.Format("{0},{1}", _width, _height);
+ }
+ }
+}
+
+#if !FEATURE_SLJ_PROJECTION_COMPAT
+#pragma warning restore 436
+#endif // !FEATURE_SLJ_PROJECTION_COMPAT
diff --git a/src/System.Private.Interop/src/Windows/Foundation/TokenizerHelper.cs b/src/System.Private.Interop/src/Windows/Foundation/TokenizerHelper.cs
new file mode 100644
index 000000000..10242e5c8
--- /dev/null
+++ b/src/System.Private.Interop/src/Windows/Foundation/TokenizerHelper.cs
@@ -0,0 +1,51 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Globalization;
+using System.Runtime.InteropServices;
+
+#if !FEATURE_SLJ_PROJECTION_COMPAT
+#pragma warning disable 436 // Redefining types from Windows.Foundation
+#endif // !FEATURE_SLJ_PROJECTION_COMPAT
+
+#if FEATURE_SLJ_PROJECTION_COMPAT
+namespace System.Windows
+#else // !FEATURE_SLJ_PROJECTION_COMPAT
+
+
+namespace Windows.Foundation
+#endif // FEATURE_SLJ_PROJECTION_COMPAT
+{
+ //
+ // Note that this type is owned by the Jupiter team. Please contact them before making any
+ // changes here.
+ //
+ internal static class TokenizerHelper
+ {
+ internal static char GetNumericListSeparator(IFormatProvider provider)
+ {
+ char numericSeparator = ',';
+
+ // Get the NumberFormatInfo out of the provider, if possible
+ // If the IFormatProvider doesn't not contain a NumberFormatInfo, then
+ // this method returns the current culture's NumberFormatInfo.
+ NumberFormatInfo numberFormat = NumberFormatInfo.GetInstance(provider);
+
+ // Is the decimal separator is the same as the list separator?
+ // If so, we use the ";".
+ if ((numberFormat.NumberDecimalSeparator.Length > 0) && (numericSeparator == numberFormat.NumberDecimalSeparator[0]))
+ {
+ numericSeparator = ';';
+ }
+
+ return numericSeparator;
+ }
+ }
+}
+
+#if !FEATURE_SLJ_PROJECTION_COMPAT
+#pragma warning restore 436
+#endif // !FEATURE_SLJ_PROJECTION_COMPAT
+