From 91ec2538163a072f0c1f46456e419d0d746342d8 Mon Sep 17 00:00:00 2001 From: Scott Jones Date: Thu, 4 Jun 2020 14:58:19 -0700 Subject: [PATCH 01/38] Local definitions of geometry types in Nullable don't work (#299) --- WinRT.Runtime/Projections/Geometry.cs | 591 ++++++++++++++++++ WinRT.Runtime/Projections/IPropertyValue.cs | 36 +- .../Windows.Foundation/Windows.Foundation.cs | 586 ----------------- 3 files changed, 592 insertions(+), 621 deletions(-) create mode 100644 WinRT.Runtime/Projections/Geometry.cs diff --git a/WinRT.Runtime/Projections/Geometry.cs b/WinRT.Runtime/Projections/Geometry.cs new file mode 100644 index 000000000..1bb5cd976 --- /dev/null +++ b/WinRT.Runtime/Projections/Geometry.cs @@ -0,0 +1,591 @@ +using System; +using System.Globalization; +using System.Runtime.InteropServices; + +namespace Windows.Foundation +{ + internal class SR + { + public static string ArgumentOutOfRange_NeedNonNegNum = "Non-negative number required."; + } + + [global::WinRT.WindowsRuntimeType] + [StructLayout(LayoutKind.Sequential)] + public struct Point : IFormattable + { + public float _x; + public float _y; + + public Point(float x, float y) + { + _x = x; + _y = y; + } + + public Point(double x, double y) : this((float)x, (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() + { + return ConvertToString(null, null); + } + + public string ToString(IFormatProvider provider) + { + return ConvertToString(null, provider); + } + + string IFormattable.ToString(string format, IFormatProvider provider) + { + return ConvertToString(format, provider); + } + + private string ConvertToString(string format, IFormatProvider provider) + { + char separator = GetNumericListSeparator(provider); + return string.Format(provider, "{1:" + format + "}{0}{2:" + format + "}", separator, _x, _y); + } + + static char GetNumericListSeparator(IFormatProvider provider) + { + // If the decimal separator is a comma use ';' + char numericSeparator = ','; + var numberFormat = NumberFormatInfo.GetInstance(provider); + if ((numberFormat.NumberDecimalSeparator.Length > 0) && (numberFormat.NumberDecimalSeparator[0] == numericSeparator)) + { + numericSeparator = ';'; + } + + return numericSeparator; + } + + 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) + { + return o is Point && this == (Point)o; + } + + public bool Equals(Point value) + { + return (this == value); + } + + public override int GetHashCode() + { + return X.GetHashCode() ^ Y.GetHashCode(); + } + } + + [global::WinRT.WindowsRuntimeType] + [StructLayout(LayoutKind.Sequential)] + public struct Rect : IFormattable + { + public float _x; + public float _y; + public float _width; + public 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 static readonly Rect s_empty = CreateEmptyRect(); + + public Rect(float x, + float y, + float width, + float height) + { + if (width < 0) + throw new ArgumentOutOfRangeException(nameof(width), SR.ArgumentOutOfRange_NeedNonNegNum); + if (height < 0) + throw new ArgumentOutOfRangeException(nameof(height), SR.ArgumentOutOfRange_NeedNonNegNum); + + _x = x; + _y = y; + _width = width; + _height = height; + } + + public Rect(double x, + double y, + double width, + double height) : this((float)x, (float)y, (float)width, (float)height) { } + + public Rect(Point point1, + Point point2) + { + _x = Math.Min(point1._x, point2._x); + _y = Math.Min(point1._y, point2._y); + + _width = Math.Max(Math.Max(point1._x, point2._x) - _x, 0f); + _height = Math.Max(Math.Max(point1._y, point2._y) - _y, 0f); + } + + public Rect(Point location, Size size) + { + if (size.IsEmpty) + { + this = s_empty; + } + else + { + _x = location._x; + _y = location._y; + _width = size._width; + _height = size._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 ArgumentOutOfRangeException(nameof(Width), SR.ArgumentOutOfRange_NeedNonNegNum); + + _width = (float)value; + } + } + + public double Height + { + get { return _height; } + set + { + if (value < 0) + throw new ArgumentOutOfRangeException(nameof(Height), SR.ArgumentOutOfRange_NeedNonNegNum); + + _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(float x, float 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 = default; + + rect._x = (float)EmptyX; + rect._y = (float)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 "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) + { + return o is Rect && this == (Rect)o; + } + + public override int GetHashCode() + { + // Perform field-by-field XOR of HashCodes + return X.GetHashCode() ^ + Y.GetHashCode() ^ + Width.GetHashCode() ^ + Height.GetHashCode(); + } + } + + [global::WinRT.WindowsRuntimeType] + [StructLayout(LayoutKind.Sequential)] + public struct Size + { + public float _width; + public float _height; + + private static readonly Size s_empty = CreateEmptySize(); + + public Size(float width, float height) + { + if (width < 0) + throw new ArgumentOutOfRangeException(nameof(width), SR.ArgumentOutOfRange_NeedNonNegNum); + if (height < 0) + throw new ArgumentOutOfRangeException(nameof(height), SR.ArgumentOutOfRange_NeedNonNegNum); + _width = width; + _height = height; + } + + public Size(double width, double height) : this((float)width, (float)height) { } + + public double Width + { + get { return _width; } + set + { + if (value < 0) + throw new ArgumentOutOfRangeException(nameof(Width), SR.ArgumentOutOfRange_NeedNonNegNum); + + _width = (float)value; + } + } + + public double Height + { + get { return _height; } + set + { + if (value < 0) + throw new ArgumentOutOfRangeException(nameof(Height), SR.ArgumentOutOfRange_NeedNonNegNum); + + _height = (float)value; + } + } + + public static Size Empty + { + get { return s_empty; } + } + + + public bool IsEmpty + { + get { return Width < 0; } + } + + private static Size CreateEmptySize() + { + Size size = default; + // We can't set these via the property setters because negatives widths + // are rejected in those APIs. + size._width = float.NegativeInfinity; + size._height = float.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) + { + return o is Size && Size.Equals(this, (Size)o); + } + + 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); + } + } + + public static class TokenizerHelper + { + public 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; + } + } +} + +namespace ABI.Windows.Foundation +{ + public static class Point + { + public static string GetGuidSignature() + { + return "struct(Windows.Foundation.Point;f4;f4)"; + } + } + + public static class Rect + { + public static string GetGuidSignature() + { + return "struct(Windows.Foundation.Rect;f4;f4;f4;f4)"; + } + } + + public static class Size + { + public static string GetGuidSignature() + { + return "struct(Windows.Foundation.Size;f4;f4)"; + } + } +} \ No newline at end of file diff --git a/WinRT.Runtime/Projections/IPropertyValue.cs b/WinRT.Runtime/Projections/IPropertyValue.cs index d1137ee70..7770ff9d5 100644 --- a/WinRT.Runtime/Projections/IPropertyValue.cs +++ b/WinRT.Runtime/Projections/IPropertyValue.cs @@ -6,41 +6,7 @@ using WinRT.Interop; namespace Windows.Foundation -{ - internal struct Point - { - float _x; - float _y; - - public double X - { - get { return _x; } - set { _x = (float)value; } - } - - public double Y - { - get { return _y; } - set { _y = (float)value; } - } - } - -#pragma warning disable CS0169 - internal struct Size - { - float Width; - float Height; - } - - internal struct Rect - { - float X; - float Y; - float Width; - float Height; - } -#pragma warning restore CS0169 - +{ internal enum PropertyType : uint { Empty = 0, diff --git a/cswinrt/strings/additions/Windows.Foundation/Windows.Foundation.cs b/cswinrt/strings/additions/Windows.Foundation/Windows.Foundation.cs index 52a1717d7..d029b1a8b 100644 --- a/cswinrt/strings/additions/Windows.Foundation/Windows.Foundation.cs +++ b/cswinrt/strings/additions/Windows.Foundation/Windows.Foundation.cs @@ -1,590 +1,4 @@ -namespace Windows.Foundation -{ - using global::System; - using global::System.Globalization; - - [global::WinRT.WindowsRuntimeType] - [StructLayout(LayoutKind.Sequential)] - public struct Point : IFormattable - { - public float _x; - public float _y; - - public Point(float x, float y) - { - _x = x; - _y = y; - } - - public Point(double x, double y) : this((float)x, (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() - { - return ConvertToString(null, null); - } - - public string ToString(IFormatProvider provider) - { - return ConvertToString(null, provider); - } - - string IFormattable.ToString(string format, IFormatProvider provider) - { - return ConvertToString(format, provider); - } - - private string ConvertToString(string format, IFormatProvider provider) - { - char separator = GetNumericListSeparator(provider); - return string.Format(provider, "{1:" + format + "}{0}{2:" + format + "}", separator, _x, _y); - } - - static char GetNumericListSeparator(IFormatProvider provider) - { - // If the decimal separator is a comma use ';' - char numericSeparator = ','; - var numberFormat = NumberFormatInfo.GetInstance(provider); - if ((numberFormat.NumberDecimalSeparator.Length > 0) && (numberFormat.NumberDecimalSeparator[0] == numericSeparator)) - { - numericSeparator = ';'; - } - - return numericSeparator; - } - - 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) - { - return o is Point && this == (Point)o; - } - - public bool Equals(Point value) - { - return (this == value); - } - - public override int GetHashCode() - { - return X.GetHashCode() ^ Y.GetHashCode(); - } - } - - [global::WinRT.WindowsRuntimeType] - [StructLayout(LayoutKind.Sequential)] - public struct Rect : IFormattable - { - public float _x; - public float _y; - public float _width; - public 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 static readonly Rect s_empty = CreateEmptyRect(); - - public Rect(float x, - float y, - float width, - float height) - { - if (width < 0) - throw new ArgumentOutOfRangeException(nameof(width), SR.ArgumentOutOfRange_NeedNonNegNum); - if (height < 0) - throw new ArgumentOutOfRangeException(nameof(height), SR.ArgumentOutOfRange_NeedNonNegNum); - - _x = x; - _y = y; - _width = width; - _height = height; - } - - public Rect(double x, - double y, - double width, - double height) : this((float)x, (float)y, (float)width, (float)height){} - - public Rect(Point point1, - Point point2) - { - _x = Math.Min(point1._x, point2._x); - _y = Math.Min(point1._y, point2._y); - - _width = Math.Max(Math.Max(point1._x, point2._x) - _x, 0f); - _height = Math.Max(Math.Max(point1._y, point2._y) - _y, 0f); - } - - public Rect(Point location, Size size) - { - if (size.IsEmpty) - { - this = s_empty; - } - else - { - _x = location._x; - _y = location._y; - _width = size._width; - _height = size._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 ArgumentOutOfRangeException(nameof(Width), SR.ArgumentOutOfRange_NeedNonNegNum); - - _width = (float)value; - } - } - - public double Height - { - get { return _height; } - set - { - if (value < 0) - throw new ArgumentOutOfRangeException(nameof(Height), SR.ArgumentOutOfRange_NeedNonNegNum); - - _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(float x, float 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 = default; - - rect._x = (float)EmptyX; - rect._y = (float)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 "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) - { - return o is Rect && this == (Rect)o; - } - - public override int GetHashCode() - { - // Perform field-by-field XOR of HashCodes - return X.GetHashCode() ^ - Y.GetHashCode() ^ - Width.GetHashCode() ^ - Height.GetHashCode(); - } - } - - [global::WinRT.WindowsRuntimeType] - [StructLayout(LayoutKind.Sequential)] - public struct Size - { - public float _width; - public float _height; - - private static readonly Size s_empty = CreateEmptySize(); - - public Size(float width, float height) - { - if (width < 0) - throw new ArgumentOutOfRangeException(nameof(width), SR.ArgumentOutOfRange_NeedNonNegNum); - if (height < 0) - throw new ArgumentOutOfRangeException(nameof(height), SR.ArgumentOutOfRange_NeedNonNegNum); - _width = width; - _height = height; - } - - public Size(double width, double height) : this((float)width, (float)height){} - - public double Width - { - get { return _width; } - set - { - if (value < 0) - throw new ArgumentOutOfRangeException(nameof(Width), SR.ArgumentOutOfRange_NeedNonNegNum); - - _width = (float)value; - } - } - - public double Height - { - get { return _height; } - set - { - if (value < 0) - throw new ArgumentOutOfRangeException(nameof(Height), SR.ArgumentOutOfRange_NeedNonNegNum); - - _height = (float)value; - } - } - - public static Size Empty - { - get { return s_empty; } - } - - - public bool IsEmpty - { - get { return Width < 0; } - } - - private static Size CreateEmptySize() - { - Size size = default; - // We can't set these via the property setters because negatives widths - // are rejected in those APIs. - size._width = float.NegativeInfinity; - size._height = float.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) - { - return o is Size && Size.Equals(this, (Size)o); - } - - 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); - } - } - - public static class TokenizerHelper - { - public 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; - } - } -} - -namespace ABI.Windows.Foundation -{ - public static class Point - { - public static string GetGuidSignature() - { - return "struct(Windows.Foundation.Point;f4;f4)"; - } - } - - public static class Rect - { - public static string GetGuidSignature() - { - return "struct(Windows.Foundation.Rect;f4;f4;f4;f4)"; - } - } - - public static class Size - { - public static string GetGuidSignature() - { - return "struct(Windows.Foundation.Size;f4;f4)"; - } - } -} - namespace System { using global::System.Diagnostics; From 5bfa7f1c5157d59a67635bd33964d57d3f050905 Mon Sep 17 00:00:00 2001 From: Scott Jones Date: Sat, 6 Jun 2020 08:57:17 -0700 Subject: [PATCH 02/38] update regex package due to security vuln (#300) --- UnitTest/UnitTest.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/UnitTest/UnitTest.csproj b/UnitTest/UnitTest.csproj index 797312273..e1b7762e9 100644 --- a/UnitTest/UnitTest.csproj +++ b/UnitTest/UnitTest.csproj @@ -28,6 +28,7 @@ + From 08e89908c80d829875015caf2f1070ee1212f6a6 Mon Sep 17 00:00:00 2001 From: Manodasan Wignarajah Date: Mon, 8 Jun 2020 20:31:43 -0700 Subject: [PATCH 03/38] Support for agile references. --- TestComponentCSharp/NonAgileClass.cpp | 125 ++++++++++++++++ TestComponentCSharp/NonAgileClass.h | 19 +++ TestComponentCSharp/TestComponentCSharp.idl | 7 + .../TestComponentCSharp.vcxproj | 2 + .../TestComponentCSharp.vcxproj.filters | 2 + UnitTest/Directory.Build.targets | 1 + UnitTest/TestComponentCSharp_Tests.cs | 105 ++++++++++++-- WinRT.Runtime/AgileReference.cs | 47 ++++++ WinRT.Runtime/CastExtensions.cs | 17 +++ WinRT.Runtime/Interop/IAgileReference.cs | 137 ++++++++++++++++++ WinRT.Runtime/Projections/EventHandler.cs | 21 ++- WinRT.Runtime/Projections/ICommand.cs | 21 ++- .../NotifyCollectionChangedEventHandler.cs | 21 ++- .../PropertyChangedEventHandler.cs | 21 ++- cswinrt/code_writers.h | 17 ++- cswinrt/strings/WinRT.cs | 9 ++ 16 files changed, 539 insertions(+), 33 deletions(-) create mode 100644 TestComponentCSharp/NonAgileClass.cpp create mode 100644 TestComponentCSharp/NonAgileClass.h create mode 100644 WinRT.Runtime/AgileReference.cs create mode 100644 WinRT.Runtime/Interop/IAgileReference.cs diff --git a/TestComponentCSharp/NonAgileClass.cpp b/TestComponentCSharp/NonAgileClass.cpp new file mode 100644 index 000000000..c1bedb3b5 --- /dev/null +++ b/TestComponentCSharp/NonAgileClass.cpp @@ -0,0 +1,125 @@ +#include "pch.h" +#include "NonAgileClass.h" +#include "NonAgileClass.g.cpp" + +using namespace winrt; + +namespace +{ + struct __declspec(uuid("624cd4e1-d007-43b1-9c03-af4d3e6258c4")) __declspec(novtable) + INonAgileBindableVectorChangedEventHandler : ::IUnknown + { + virtual int32_t __stdcall Invoke(void*, void*) noexcept = 0; + }; + + struct NonAgileDelegate : implements + { + NonAgileDelegate() + { + } + + int32_t __stdcall Invoke(void* p1, void* p2) noexcept override + { + VectorChanged(*reinterpret_cast(&p1), + *reinterpret_cast(&p2)); + return S_OK; + } + + HRESULT __stdcall GetUnmarshalClass(REFIID riid, void* pv, DWORD dwDestContext, void* pvDestContext, DWORD mshlflags, CLSID* pCid) noexcept final + { + if (m_marshaler) + { + return m_marshaler->GetUnmarshalClass(riid, pv, dwDestContext, pvDestContext, mshlflags, pCid); + } + + return E_OUTOFMEMORY; + } + + HRESULT __stdcall GetMarshalSizeMax(REFIID riid, void* pv, DWORD dwDestContext, void* pvDestContext, DWORD mshlflags, DWORD* pSize) noexcept final + { + if (m_marshaler) + { + return m_marshaler->GetMarshalSizeMax(riid, pv, dwDestContext, pvDestContext, mshlflags, pSize); + } + + return E_OUTOFMEMORY; + } + + HRESULT __stdcall MarshalInterface(IStream* pStm, REFIID riid, void* pv, DWORD dwDestContext, void* pvDestContext, DWORD mshlflags) noexcept final + { + if (m_marshaler) + { + return m_marshaler->MarshalInterface(pStm, riid, pv, dwDestContext, pvDestContext, mshlflags); + } + + return E_OUTOFMEMORY; + } + + HRESULT __stdcall UnmarshalInterface(IStream* pStm, REFIID riid, void** ppv) noexcept final + { + if (m_marshaler) + { + return m_marshaler->UnmarshalInterface(pStm, riid, ppv); + } + + *ppv = nullptr; + return E_OUTOFMEMORY; + } + + HRESULT __stdcall ReleaseMarshalData(IStream* pStm) noexcept final + { + if (m_marshaler) + { + return m_marshaler->ReleaseMarshalData(pStm); + } + + return E_OUTOFMEMORY; + } + + HRESULT __stdcall DisconnectObject(DWORD dwReserved) noexcept final + { + if (m_marshaler) + { + return m_marshaler->DisconnectObject(dwReserved); + } + + return E_OUTOFMEMORY; + } + + void VectorChanged(Microsoft::UI::Xaml::Interop::IBindableObservableVector vector, Windows::Foundation::IInspectable e) + { + int32_t sum = 0; + auto view = vector.GetView(); + for (uint32_t i = 0; i < view.Size(); i++) + { + sum += winrt::unbox_value(view.GetAt(i)); + } + e.as().ReadWriteProperty(sum); + } + + private: + + static com_ptr<::IMarshal> get_marshaler() noexcept + { + com_ptr<::IUnknown> unknown; + WINRT_VERIFY_(S_OK, CoCreateFreeThreadedMarshaler(nullptr, unknown.put())); + return unknown ? unknown.try_as<::IMarshal>() : nullptr; + } + + com_ptr<::IMarshal> m_marshaler{ get_marshaler() }; + }; +} + +namespace winrt::TestComponentCSharp::implementation +{ + NonAgileClass::NonAgileClass() + { + } + + void NonAgileClass::Observe(Microsoft::UI::Xaml::Interop::IBindableObservableVector vector) + { + Microsoft::UI::Xaml::Interop::BindableVectorChangedEventHandler handler; + *put_abi(handler) = make().detach(); + vector.VectorChanged(handler); + } +} diff --git a/TestComponentCSharp/NonAgileClass.h b/TestComponentCSharp/NonAgileClass.h new file mode 100644 index 000000000..add4fbb69 --- /dev/null +++ b/TestComponentCSharp/NonAgileClass.h @@ -0,0 +1,19 @@ +#pragma once +#include "NonAgileClass.g.h" + +namespace winrt::TestComponentCSharp::implementation +{ + struct NonAgileClass : NonAgileClassT + { + public: + NonAgileClass(); + void Observe(Microsoft::UI::Xaml::Interop::IBindableObservableVector vector); + void VectorChanged(Microsoft::UI::Xaml::Interop::IBindableObservableVector vector, Windows::Foundation::IInspectable e); + }; +} +namespace winrt::TestComponentCSharp::factory_implementation +{ + struct NonAgileClass : NonAgileClassT + { + }; +} diff --git a/TestComponentCSharp/TestComponentCSharp.idl b/TestComponentCSharp/TestComponentCSharp.idl index ed742659f..20a16661d 100644 --- a/TestComponentCSharp/TestComponentCSharp.idl +++ b/TestComponentCSharp/TestComponentCSharp.idl @@ -307,4 +307,11 @@ namespace TestComponentCSharp // Keyword escapes String Catch(String params, out String lock); } + + [threading(sta), marshaling_behavior(standard)] + runtimeclass NonAgileClass + { + NonAgileClass(); + void Observe(Microsoft.UI.Xaml.Interop.IBindableObservableVector vector); + } } diff --git a/TestComponentCSharp/TestComponentCSharp.vcxproj b/TestComponentCSharp/TestComponentCSharp.vcxproj index 2c4bf1e7b..b5d127766 100644 --- a/TestComponentCSharp/TestComponentCSharp.vcxproj +++ b/TestComponentCSharp/TestComponentCSharp.vcxproj @@ -69,6 +69,7 @@ TestComponentCSharp.idl + @@ -79,6 +80,7 @@ TestComponentCSharp.idl + diff --git a/TestComponentCSharp/TestComponentCSharp.vcxproj.filters b/TestComponentCSharp/TestComponentCSharp.vcxproj.filters index decb517e3..9c0351ae0 100644 --- a/TestComponentCSharp/TestComponentCSharp.vcxproj.filters +++ b/TestComponentCSharp/TestComponentCSharp.vcxproj.filters @@ -11,11 +11,13 @@ + + diff --git a/UnitTest/Directory.Build.targets b/UnitTest/Directory.Build.targets index be38a19f5..aeeac76f4 100644 --- a/UnitTest/Directory.Build.targets +++ b/UnitTest/Directory.Build.targets @@ -48,6 +48,7 @@ -include TestComponentCSharp -include TestComponent -include Windows.Foundation +-include Windows.UI.Popups -include Windows.UI.Color -include Microsoft.UI.Xaml.CornerRadius -include Microsoft.UI.Xaml.Duration diff --git a/UnitTest/TestComponentCSharp_Tests.cs b/UnitTest/TestComponentCSharp_Tests.cs index 743957447..c8e39e322 100644 --- a/UnitTest/TestComponentCSharp_Tests.cs +++ b/UnitTest/TestComponentCSharp_Tests.cs @@ -19,6 +19,8 @@ using TestComponentCSharp; using System.Collections.Generic; using System.Collections; +using TestComponent; +using WinRT.Interop; namespace UnitTest { @@ -651,14 +653,14 @@ public class TObservation : IProperties2 private void OnChanged() { VectorChanged.Invoke(this, _observation = new TObservation()); - } + } public event BindableVectorChangedEventHandler VectorChanged; - public object this[int index] - { - get => _list[index]; - set{ _list[index] = value; OnChanged(); } + public object this[int index] + { + get => _list[index]; + set { _list[index] = value; OnChanged(); } } public bool IsFixedSize => false; @@ -1116,7 +1118,7 @@ public void TestDurationTypeMapping() [Fact] public void TestGridLengthTypeMapping() { - var gridLength = new GridLength( 42, GridUnitType.Pixel ); + var gridLength = new GridLength(42, GridUnitType.Pixel); TestObject.GridLengthProperty = gridLength; Assert.Equal(gridLength.GridUnitType, TestObject.GridLengthProperty.GridUnitType); Assert.Equal(gridLength.Value, TestObject.GridLengthProperty.Value); @@ -1171,8 +1173,12 @@ public void TestKeyTimeTypeMapping() [Fact] public void TestRepeatBehaviorTypeMapping() { - var repeatBehavior = new RepeatBehavior { - Count = 1, Duration = TimeSpan.FromTicks(42), Type = RepeatBehaviorType.Forever }; + var repeatBehavior = new RepeatBehavior + { + Count = 1, + Duration = TimeSpan.FromTicks(42), + Type = RepeatBehaviorType.Forever + }; TestObject.RepeatBehaviorProperty = repeatBehavior; Assert.Equal(repeatBehavior.Count, TestObject.RepeatBehaviorProperty.Count); Assert.Equal(repeatBehavior.Duration, TestObject.RepeatBehaviorProperty.Duration); @@ -1183,11 +1189,12 @@ public void TestRepeatBehaviorTypeMapping() [Fact] public void TestMatrix3DTypeMapping() { - var matrix3D = new Matrix3D { + var matrix3D = new Matrix3D { M11 = 11, M12 = 12, M13 = 13, M14 = 14, M21 = 21, M22 = 22, M23 = 23, M24 = 24, M31 = 31, M32 = 32, M33 = 33, M34 = 34, OffsetX = 41, OffsetY = 42, OffsetZ = 43,M44 = 44 }; + TestObject.Matrix3DProperty = matrix3D; Assert.Equal(matrix3D.M11, TestObject.Matrix3DProperty.M11); Assert.Equal(matrix3D.M12, TestObject.Matrix3DProperty.M12); @@ -1503,5 +1510,81 @@ public void TestUnwrapInspectable() var inspectable = IInspectable.FromAbi(TestObject.ThisPtr); Assert.True(ComWrappersSupport.TryUnwrapObject(inspectable, out _)); } - } -} + + [Fact] + public void TestManagedAgileObject() + { + var testObjectAgileRef = TestObject.AsAgile(); + var agileTestObject = testObjectAgileRef.Get(); + Assert.Equal(TestObject, agileTestObject); + + IProperties1 properties = new ManagedProperties(42); + var propertiesAgileRef = properties.AsAgile(); + var agileProperties = propertiesAgileRef.Get(); + Assert.Equal(properties.ReadWriteProperty, agileProperties.ReadWriteProperty); + + var agileObject = TestObject.As(); + Assert.NotNull(agileObject); + } + + class NonAgileClassCaller + { + public void AcquireObject() + { + Assert.Equal(ApartmentState.STA, Thread.CurrentThread.GetApartmentState()); + nonAgileObject = new Windows.UI.Popups.PopupMenu(); + nonAgileObject.Commands.Add(new Windows.UI.Popups.UICommand("test")); + nonAgileObject.Commands.Add(new Windows.UI.Popups.UICommand("test2")); + Assert.ThrowsAny(() => nonAgileObject.As()); + + agileReference = nonAgileObject.AsAgile(); + objectAcquired.Set(); + valueAcquired.WaitOne(); + Assert.ThrowsAny(() => proxyObject.Commands.Count); + } + + public void CheckValue() + { + objectAcquired.WaitOne(); + + Assert.Equal(ApartmentState.MTA, Thread.CurrentThread.GetApartmentState()); + proxyObject = agileReference.Get(); + Assert.Equal(2, proxyObject.Commands.Count); + valueAcquired.Set(); + } + + private Windows.UI.Popups.PopupMenu nonAgileObject; + private Windows.UI.Popups.PopupMenu proxyObject; + private AgileReference agileReference; + private readonly AutoResetEvent objectAcquired = new AutoResetEvent(false); + private readonly AutoResetEvent valueAcquired = new AutoResetEvent(false); + } + + + [Fact] + public void TestNonAgileObjectCall() + { + NonAgileClassCaller caller = new NonAgileClassCaller(); + Thread staThread = new Thread(new ThreadStart(caller.AcquireObject)); + staThread.SetApartmentState(ApartmentState.STA); + staThread.Start(); + + Thread mtaThread = new Thread(new ThreadStart(caller.CheckValue)); + mtaThread.SetApartmentState(ApartmentState.MTA); + mtaThread.Start(); + mtaThread.Join(); + staThread.Join(); + } + + [Fact] + public void TestNonAgileDelegateCall() + { + var expected = new int[] { 0, 1, 2 }; + var observable = new ManagedBindableObservable(expected); + var nonAgileClass = new NonAgileClass(); + nonAgileClass.Observe(observable); + observable.Add(3); + Assert.Equal(6, observable.Observation); + } + } +} \ No newline at end of file diff --git a/WinRT.Runtime/AgileReference.cs b/WinRT.Runtime/AgileReference.cs new file mode 100644 index 000000000..7bf0249ba --- /dev/null +++ b/WinRT.Runtime/AgileReference.cs @@ -0,0 +1,47 @@ +using System; +using System.Runtime.InteropServices; +using WinRT.Interop; + +namespace WinRT +{ + public class AgileReference + { + private readonly IAgileReference _agileReference; + + public unsafe AgileReference(IObjectReference instance) + { + Guid iid = typeof(IUnknownVftbl).GUID; + IntPtr agileReference = IntPtr.Zero; + try + { + Marshal.ThrowExceptionForHR(Platform.RoGetAgileReference( + Platform.AgileReferenceOptions.AGILEREFERENCE_DEFAULT, + ref iid, + instance.ThisPtr, + &agileReference)); + _agileReference = ABI.WinRT.Interop.IAgileReference.FromAbi(agileReference).AsType(); + } + finally + { + MarshalInterface.DisposeAbi(agileReference); + } + } + + public IObjectReference Get() => _agileReference?.Resolve(typeof(IUnknownVftbl).GUID); + } + + public sealed class AgileReference : AgileReference + where T : class + { + public unsafe AgileReference(IObjectReference instance) + : base(instance) + { + } + + public new T Get() + { + using var objRef = base.Get(); + return (T) ComWrappersSupport.CreateRcwForComObject(objRef?.ThisPtr ?? IntPtr.Zero); + } + } +} \ No newline at end of file diff --git a/WinRT.Runtime/CastExtensions.cs b/WinRT.Runtime/CastExtensions.cs index c07821ac0..e2ff90093 100644 --- a/WinRT.Runtime/CastExtensions.cs +++ b/WinRT.Runtime/CastExtensions.cs @@ -44,6 +44,23 @@ public static TInterface As(this object value) } } + public static AgileReference AsAgile(this T value) where T : class + { + var marshal = Marshaler.CreateMarshaler(value); + try + { + if (marshal is IObjectReference objref) + { + return new AgileReference(objref); + } + } + finally + { + Marshaler.DisposeMarshaler(marshal); + } + return null; + } + private static bool TryGetRefForObject(object value, bool allowComposed, out IObjectReference reference) { if (ComWrappersSupport.TryUnwrapObject(value, out var objRef)) diff --git a/WinRT.Runtime/Interop/IAgileReference.cs b/WinRT.Runtime/Interop/IAgileReference.cs new file mode 100644 index 000000000..601c11d99 --- /dev/null +++ b/WinRT.Runtime/Interop/IAgileReference.cs @@ -0,0 +1,137 @@ +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Text; + +namespace WinRT.Interop +{ + [WindowsRuntimeType] + [Guid("C03F6A43-65A4-9818-987E-E0B810D2A6F2")] + internal interface IAgileReference + { + IObjectReference Resolve(Guid riid); + } + + [WindowsRuntimeType] + [Guid("94ea2b94-e9cc-49e0-c0ff-ee64ca8f5b90")] + public interface IAgileObject + { + } +} + +namespace ABI.WinRT.Interop +{ + using global::WinRT; + using WinRT.Interop; + + [Guid("C03F6A43-65A4-9818-987E-E0B810D2A6F2")] + internal class IAgileReference : global::WinRT.Interop.IAgileReference + { + [Guid("C03F6A43-65A4-9818-987E-E0B810D2A6F2")] + public struct Vftbl + { + public delegate int _Resolve(IntPtr thisPtr, ref Guid riid, out IntPtr objectReference); + + public global::WinRT.Interop.IUnknownVftbl IUnknownVftbl; + public _Resolve Resolve; + + public static readonly Vftbl AbiToProjectionVftable; + public static readonly IntPtr AbiToProjectionVftablePtr; + + static Vftbl() + { + AbiToProjectionVftable = new Vftbl + { + IUnknownVftbl = global::WinRT.Interop.IUnknownVftbl.AbiToProjectionVftbl, + Resolve = Do_Abi_Resolve + }; + AbiToProjectionVftablePtr = Marshal.AllocHGlobal(Marshal.SizeOf()); + Marshal.StructureToPtr(AbiToProjectionVftable, AbiToProjectionVftablePtr, false); + } + + private static int Do_Abi_Resolve(IntPtr thisPtr, ref Guid riid, out IntPtr objectReference) + { + IObjectReference _objectReference = default; + + objectReference = default; + + try + { + _objectReference = global::WinRT.ComWrappersSupport.FindObject(thisPtr).Resolve(riid); + objectReference = _objectReference?.GetRef() ?? IntPtr.Zero; + } + catch (Exception __exception__) + { + return __exception__.HResult; + } + return 0; + } + } + + public static ObjectReference FromAbi(IntPtr thisPtr) => ObjectReference.FromAbi(thisPtr); + + public static implicit operator IAgileReference(IObjectReference obj) => (obj != null) ? new IAgileReference(obj) : null; + public static implicit operator IAgileReference(ObjectReference obj) => (obj != null) ? new IAgileReference(obj) : null; + protected readonly ObjectReference _obj; + public IntPtr ThisPtr => _obj.ThisPtr; + public ObjectReference AsInterface() => _obj.As(); + public A As() => _obj.AsType(); + + public IAgileReference(IObjectReference obj) : this(obj.As()) { } + public IAgileReference(ObjectReference obj) + { + _obj = obj; + } + + public IObjectReference Resolve(Guid riid) + { + ExceptionHelpers.ThrowExceptionForHR(_obj.Vftbl.Resolve(ThisPtr, ref riid, out IntPtr ptr)); + try + { + return ComWrappersSupport.GetObjectReferenceForInterface(ptr); + } + finally + { + MarshalInspectable.DisposeAbi(ptr); + } + } + } + + [Guid("94ea2b94-e9cc-49e0-c0ff-ee64ca8f5b90")] + public class IAgileObject : global::WinRT.Interop.IAgileObject + { + [Guid("94ea2b94-e9cc-49e0-c0ff-ee64ca8f5b90")] + public struct Vftbl + { + public global::WinRT.Interop.IUnknownVftbl IUnknownVftbl; + + public static readonly Vftbl AbiToProjectionVftable; + public static readonly IntPtr AbiToProjectionVftablePtr; + + static Vftbl() + { + AbiToProjectionVftable = new Vftbl + { + IUnknownVftbl = global::WinRT.Interop.IUnknownVftbl.AbiToProjectionVftbl, + }; + AbiToProjectionVftablePtr = Marshal.AllocHGlobal(Marshal.SizeOf()); + Marshal.StructureToPtr(AbiToProjectionVftable, AbiToProjectionVftablePtr, false); + } + } + + public static ObjectReference FromAbi(IntPtr thisPtr) => ObjectReference.FromAbi(thisPtr); + + public static implicit operator IAgileObject(IObjectReference obj) => (obj != null) ? new IAgileObject(obj) : null; + public static implicit operator IAgileObject(ObjectReference obj) => (obj != null) ? new IAgileObject(obj) : null; + protected readonly ObjectReference _obj; + public IntPtr ThisPtr => _obj.ThisPtr; + public ObjectReference AsInterface() => _obj.As(); + public A As() => _obj.AsType(); + + public IAgileObject(IObjectReference obj) : this(obj.As()) { } + public IAgileObject(ObjectReference obj) + { + _obj = obj; + } + } +} diff --git a/WinRT.Runtime/Projections/EventHandler.cs b/WinRT.Runtime/Projections/EventHandler.cs index 9eedc7ca6..0fe73563e 100644 --- a/WinRT.Runtime/Projections/EventHandler.cs +++ b/WinRT.Runtime/Projections/EventHandler.cs @@ -50,17 +50,28 @@ public static IntPtr GetAbi(IObjectReference value) => [global::WinRT.ObjectReferenceWrapper(nameof(_nativeDelegate))] private class NativeDelegateWrapper { - private readonly ObjectReference _nativeDelegate; + private readonly ObjectReference _nativeDelegate; + private readonly AgileReference _agileReference = default; public NativeDelegateWrapper(ObjectReference nativeDelegate) { - _nativeDelegate = nativeDelegate; + _nativeDelegate = nativeDelegate; + if (_nativeDelegate.TryAs(out var objRef) < 0) + { + _agileReference = new AgileReference(_nativeDelegate); + } + else + { + objRef.Dispose(); + } } public void Invoke(object sender, T args) - { - IntPtr ThisPtr = _nativeDelegate.ThisPtr; - var abiInvoke = Marshal.GetDelegateForFunctionPointer(_nativeDelegate.Vftbl.Invoke, Abi_Invoke_Type); + { + using var agileDelegate = _agileReference?.Get()?.As(GuidGenerator.GetIID(typeof(EventHandler))); + var delegateToInvoke = agileDelegate ?? _nativeDelegate; + IntPtr ThisPtr = delegateToInvoke.ThisPtr; + var abiInvoke = Marshal.GetDelegateForFunctionPointer(delegateToInvoke.Vftbl.Invoke, Abi_Invoke_Type); IObjectReference __sender = default; object __args = default; var __params = new object[] { ThisPtr, null, null }; diff --git a/WinRT.Runtime/Projections/ICommand.cs b/WinRT.Runtime/Projections/ICommand.cs index 51a108062..0fff79ea1 100644 --- a/WinRT.Runtime/Projections/ICommand.cs +++ b/WinRT.Runtime/Projections/ICommand.cs @@ -49,17 +49,28 @@ public static IntPtr GetAbi(IObjectReference value) => [global::WinRT.ObjectReferenceWrapper(nameof(_nativeDelegate))] private class NativeDelegateWrapper { - private readonly ObjectReference _nativeDelegate; + private readonly ObjectReference _nativeDelegate; + private readonly AgileReference _agileReference = default; public NativeDelegateWrapper(ObjectReference nativeDelegate) { - _nativeDelegate = nativeDelegate; + _nativeDelegate = nativeDelegate; + if (_nativeDelegate.TryAs(out var objRef) < 0) + { + _agileReference = new AgileReference(_nativeDelegate); + } + else + { + objRef.Dispose(); + } } public void Invoke(object sender, EventArgs args) - { - IntPtr ThisPtr = _nativeDelegate.ThisPtr; - var abiInvoke = Marshal.GetDelegateForFunctionPointer(_nativeDelegate.Vftbl.Invoke); + { + using var agileDelegate = _agileReference?.Get()?.As(GuidGenerator.GetIID(typeof(CanExecuteChangedEventHandler))); + var delegateToInvoke = agileDelegate ?? _nativeDelegate; + IntPtr ThisPtr = delegateToInvoke.ThisPtr; + var abiInvoke = Marshal.GetDelegateForFunctionPointer(delegateToInvoke.Vftbl.Invoke); IObjectReference __sender = default; IObjectReference __args = default; var __params = new object[] { ThisPtr, null, null }; diff --git a/WinRT.Runtime/Projections/NotifyCollectionChangedEventHandler.cs b/WinRT.Runtime/Projections/NotifyCollectionChangedEventHandler.cs index ad67db685..69a016d6c 100644 --- a/WinRT.Runtime/Projections/NotifyCollectionChangedEventHandler.cs +++ b/WinRT.Runtime/Projections/NotifyCollectionChangedEventHandler.cs @@ -46,17 +46,28 @@ public static unsafe IObjectReference CreateMarshaler(global::System.Collections [global::WinRT.ObjectReferenceWrapper(nameof(_nativeDelegate))] private class NativeDelegateWrapper { - private readonly ObjectReference _nativeDelegate; + private readonly ObjectReference _nativeDelegate; + private readonly AgileReference _agileReference = default; public NativeDelegateWrapper(ObjectReference nativeDelegate) { - _nativeDelegate = nativeDelegate; + _nativeDelegate = nativeDelegate; + if (_nativeDelegate.TryAs(out var objRef) < 0) + { + _agileReference = new AgileReference(_nativeDelegate); + } + else + { + objRef.Dispose(); + } } public void Invoke(object sender, global::System.Collections.Specialized.NotifyCollectionChangedEventArgs e) - { - IntPtr ThisPtr = _nativeDelegate.ThisPtr; - var abiInvoke = Marshal.GetDelegateForFunctionPointer(_nativeDelegate.Vftbl.Invoke); + { + using var agileDelegate = _agileReference?.Get()?.As(GuidGenerator.GetIID(typeof(NotifyCollectionChangedEventHandler))); + var delegateToInvoke = agileDelegate ?? _nativeDelegate; + IntPtr ThisPtr = delegateToInvoke.ThisPtr; + var abiInvoke = Marshal.GetDelegateForFunctionPointer(delegateToInvoke.Vftbl.Invoke); IObjectReference __sender = default; IObjectReference __e = default; try diff --git a/WinRT.Runtime/Projections/PropertyChangedEventHandler.cs b/WinRT.Runtime/Projections/PropertyChangedEventHandler.cs index 733dbabbb..5171381d7 100644 --- a/WinRT.Runtime/Projections/PropertyChangedEventHandler.cs +++ b/WinRT.Runtime/Projections/PropertyChangedEventHandler.cs @@ -45,17 +45,28 @@ public static unsafe IObjectReference CreateMarshaler(global::System.ComponentMo [global::WinRT.ObjectReferenceWrapper(nameof(_nativeDelegate))] private class NativeDelegateWrapper { - private readonly ObjectReference _nativeDelegate; + private readonly ObjectReference _nativeDelegate; + private readonly AgileReference _agileReference = default; public NativeDelegateWrapper(ObjectReference nativeDelegate) { - _nativeDelegate = nativeDelegate; + _nativeDelegate = nativeDelegate; + if (_nativeDelegate.TryAs(out var objRef) < 0) + { + _agileReference = new AgileReference(_nativeDelegate); + } + else + { + objRef.Dispose(); + } } public void Invoke(object sender, global::System.ComponentModel.PropertyChangedEventArgs e) - { - IntPtr ThisPtr = _nativeDelegate.ThisPtr; - var abiInvoke = Marshal.GetDelegateForFunctionPointer(_nativeDelegate.Vftbl.Invoke); + { + using var agileDelegate = _agileReference?.Get()?.As(GuidGenerator.GetIID(typeof(PropertyChangedEventHandler))); + var delegateToInvoke = agileDelegate ?? _nativeDelegate; + IntPtr ThisPtr = delegateToInvoke.ThisPtr; + var abiInvoke = Marshal.GetDelegateForFunctionPointer(delegateToInvoke.Vftbl.Invoke); IObjectReference __sender = default; IObjectReference __e = default; try diff --git a/cswinrt/code_writers.h b/cswinrt/code_writers.h index 302c46985..abc0dce30 100644 --- a/cswinrt/code_writers.h +++ b/cswinrt/code_writers.h @@ -4175,16 +4175,27 @@ return abiDelegate is null ? null : (%)ComWrappersSupport.TryRegisterObjectForIn private class NativeDelegateWrapper { private readonly ObjectReference _nativeDelegate; +private readonly AgileReference _agileReference = default; public NativeDelegateWrapper(ObjectReference nativeDelegate) { _nativeDelegate = nativeDelegate; +if (_nativeDelegate.TryAs(out var objRef) < 0) +{ +_agileReference = new AgileReference(_nativeDelegate); +} +else +{ +objRef.Dispose(); +} } public % Invoke(%) { -IntPtr ThisPtr = _nativeDelegate.ThisPtr; -var abiInvoke = Marshal.GetDelegateForFunctionPointer%(_nativeDelegate.Vftbl.Invoke%);% +using var agileDelegate = _agileReference?.Get()?.As(GuidGenerator.GetIID(typeof(@%))); +var delegateToInvoke = agileDelegate ?? _nativeDelegate; +IntPtr ThisPtr = delegateToInvoke.ThisPtr; +var abiInvoke = Marshal.GetDelegateForFunctionPointer%(delegateToInvoke.Vftbl.Invoke%);% } } @@ -4265,6 +4276,8 @@ public static Guid PIID = GuidGenerator.CreateIID(typeof(%));)", // NativeDelegateWrapper.Invoke bind(signature), bind_list(", ", signature.params()), + type.TypeName(), + type_params, is_generic ? "" : "", is_generic ? ", Abi_Invoke_Type" : "", bind(signature, "abiInvoke", is_generic, false), diff --git a/cswinrt/strings/WinRT.cs b/cswinrt/strings/WinRT.cs index 154345ee2..340544821 100644 --- a/cswinrt/strings/WinRT.cs +++ b/cswinrt/strings/WinRT.cs @@ -85,6 +85,15 @@ internal static extern unsafe int WindowsDuplicateString(IntPtr sourceString, [DllImport("api-ms-win-core-winrt-string-l1-1-0.dll", CallingConvention = CallingConvention.StdCall)] internal static extern unsafe char* WindowsGetStringRawBuffer(IntPtr hstring, uint* length); + + internal enum AgileReferenceOptions : uint + { + AGILEREFERENCE_DEFAULT = 0x0, + AGILEREFERENCE_DELAYEDMARSHAL = 0x1 + } + + [DllImport("api-ms-win-core-com-l1-1-1.dll", CallingConvention = CallingConvention.StdCall)] + internal static extern unsafe int RoGetAgileReference(AgileReferenceOptions options, ref Guid iid, IntPtr unknown, IntPtr* agileReference); } internal struct VftblPtr From e2fefd8a1a8ddbfe46716fa711400f5e4607cd67 Mon Sep 17 00:00:00 2001 From: Manodasan Wignarajah Date: Mon, 8 Jun 2020 22:57:58 -0700 Subject: [PATCH 04/38] Adding comments --- UnitTest/TestComponentCSharp_Tests.cs | 2 ++ WinRT.Runtime/CastExtensions.cs | 17 ++++++++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/UnitTest/TestComponentCSharp_Tests.cs b/UnitTest/TestComponentCSharp_Tests.cs index c8e39e322..b143a2561 100644 --- a/UnitTest/TestComponentCSharp_Tests.cs +++ b/UnitTest/TestComponentCSharp_Tests.cs @@ -1540,6 +1540,8 @@ public void AcquireObject() agileReference = nonAgileObject.AsAgile(); objectAcquired.Set(); valueAcquired.WaitOne(); + + // Call to proxy object acquired from MTA which should throw Assert.ThrowsAny(() => proxyObject.Commands.Count); } diff --git a/WinRT.Runtime/CastExtensions.cs b/WinRT.Runtime/CastExtensions.cs index e2ff90093..a845fdc9d 100644 --- a/WinRT.Runtime/CastExtensions.cs +++ b/WinRT.Runtime/CastExtensions.cs @@ -42,8 +42,19 @@ public static TInterface As(this object value) { return (TInterface)typeof(TInterface).GetHelperType().GetConstructor(new[] { typeof(IObjectReference) }).Invoke(new object[] { objRef }); } - } - + } + + /// + /// Create an agile reference for a given WinRT object. The agile reference can be passed to another apartment + /// within the process from which the original object can be retrieved even if it wasn't agile. + /// + /// Type of WinRT object. + /// The object. + /// + /// If is a WinRT object, returns a AgileReference for it. + /// Otherwise, returns null. + /// + /// Thrown if the runtime type of is not a projected type. public static AgileReference AsAgile(this T value) where T : class { var marshal = Marshaler.CreateMarshaler(value); @@ -58,7 +69,7 @@ public static AgileReference AsAgile(this T value) where T : class { Marshaler.DisposeMarshaler(marshal); } - return null; + throw new InvalidOperationException($"Object type is not a projected type: {nameof(value)}."); } private static bool TryGetRefForObject(object value, bool allowComposed, out IObjectReference reference) From 0a5a609940d313b2a50cb4b4e1f24c3a740188e2 Mon Sep 17 00:00:00 2001 From: Manodasan Wignarajah Date: Tue, 9 Jun 2020 09:04:49 -0700 Subject: [PATCH 05/38] Fallback for RoGetAgileReference when it isn't available. --- UnitTest/TestComponentCSharp_Tests.cs | 5 +- WinRT.Runtime/AgileReference.cs | 56 ++++++++++++++++++-- WinRT.Runtime/Interop/IAgileReference.cs | 66 ++++++++++++++++++++++++ cswinrt/strings/WinRT.cs | 3 ++ 4 files changed, 125 insertions(+), 5 deletions(-) diff --git a/UnitTest/TestComponentCSharp_Tests.cs b/UnitTest/TestComponentCSharp_Tests.cs index b143a2561..d6f411c26 100644 --- a/UnitTest/TestComponentCSharp_Tests.cs +++ b/UnitTest/TestComponentCSharp_Tests.cs @@ -1514,12 +1514,12 @@ public void TestUnwrapInspectable() [Fact] public void TestManagedAgileObject() { - var testObjectAgileRef = TestObject.AsAgile(); + using var testObjectAgileRef = TestObject.AsAgile(); var agileTestObject = testObjectAgileRef.Get(); Assert.Equal(TestObject, agileTestObject); IProperties1 properties = new ManagedProperties(42); - var propertiesAgileRef = properties.AsAgile(); + using var propertiesAgileRef = properties.AsAgile(); var agileProperties = propertiesAgileRef.Get(); Assert.Equal(properties.ReadWriteProperty, agileProperties.ReadWriteProperty); @@ -1543,6 +1543,7 @@ public void AcquireObject() // Call to proxy object acquired from MTA which should throw Assert.ThrowsAny(() => proxyObject.Commands.Count); + agileReference.Dispose(); } public void CheckValue() diff --git a/WinRT.Runtime/AgileReference.cs b/WinRT.Runtime/AgileReference.cs index 7bf0249ba..ec5206b9b 100644 --- a/WinRT.Runtime/AgileReference.cs +++ b/WinRT.Runtime/AgileReference.cs @@ -4,14 +4,19 @@ namespace WinRT { - public class AgileReference + public class AgileReference : IDisposable { + private readonly static Guid CLSID_StdGlobalInterfaceTable = Guid.Parse("00000323-0000-0000-c000-000000000046"); private readonly IAgileReference _agileReference; + private readonly IGlobalInterfaceTable _git; + private readonly IntPtr _cookie; + private bool disposed; public unsafe AgileReference(IObjectReference instance) { + IntPtr agileReference = default; + IntPtr gitPtr = default; Guid iid = typeof(IUnknownVftbl).GUID; - IntPtr agileReference = IntPtr.Zero; try { Marshal.ThrowExceptionForHR(Platform.RoGetAgileReference( @@ -21,13 +26,58 @@ public unsafe AgileReference(IObjectReference instance) &agileReference)); _agileReference = ABI.WinRT.Interop.IAgileReference.FromAbi(agileReference).AsType(); } + catch(TypeLoadException) + { + Guid gitClsid = CLSID_StdGlobalInterfaceTable; + Guid gitIid = typeof(IGlobalInterfaceTable).GUID; + Marshal.ThrowExceptionForHR(Platform.CoCreateInstance( + ref gitClsid, + IntPtr.Zero, + 1 /*CLSCTX_INPROC_SERVER*/, + ref gitIid, + &gitPtr)); + _git = ABI.WinRT.Interop.IGlobalInterfaceTable.FromAbi(gitPtr).AsType(); + _cookie = _git.RegisterInterfaceInGlobal(instance, iid); + + } finally { MarshalInterface.DisposeAbi(agileReference); + MarshalInterface.DisposeAbi(gitPtr); + } + } + + public IObjectReference Get() => _agileReference?.Resolve(typeof(IUnknownVftbl).GUID) ?? _git?.GetInterfaceFromGlobal(_cookie, typeof(IUnknownVftbl).GUID); + + protected virtual void Dispose(bool disposing) + { + if (!disposed) + { + try + { + if (_git != null && _cookie != IntPtr.Zero) + { + _git.RevokeInterfaceFromGlobal(_cookie); + } + } + catch(ObjectDisposedException) + { + // TODO: How to handle removing from git when it has already been disposed. + } + disposed = true; } } - public IObjectReference Get() => _agileReference?.Resolve(typeof(IUnknownVftbl).GUID); + ~AgileReference() + { + Dispose(false); + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } } public sealed class AgileReference : AgileReference diff --git a/WinRT.Runtime/Interop/IAgileReference.cs b/WinRT.Runtime/Interop/IAgileReference.cs index 601c11d99..852d9fe1d 100644 --- a/WinRT.Runtime/Interop/IAgileReference.cs +++ b/WinRT.Runtime/Interop/IAgileReference.cs @@ -17,6 +17,15 @@ internal interface IAgileReference public interface IAgileObject { } + + [WindowsRuntimeType] + [Guid("00000146-0000-0000-C000-000000000046")] + internal interface IGlobalInterfaceTable + { + IntPtr RegisterInterfaceInGlobal(IObjectReference objRef, Guid riid); + void RevokeInterfaceFromGlobal(IntPtr cookie); + IObjectReference GetInterfaceFromGlobal(IntPtr cookie, Guid riid); + } } namespace ABI.WinRT.Interop @@ -134,4 +143,61 @@ public IAgileObject(ObjectReference obj) _obj = obj; } } + + [Guid("00000146-0000-0000-C000-000000000046")] + internal class IGlobalInterfaceTable : global::WinRT.Interop.IGlobalInterfaceTable + { + [Guid("00000146-0000-0000-C000-000000000046")] + public struct Vftbl + { + public delegate int _RegisterInterfaceInGlobal(IntPtr thisPtr, IntPtr objRef, ref Guid riid, out IntPtr cookie); + public delegate int _RevokeInterfaceFromGlobal(IntPtr thisPtr, IntPtr cookie); + public delegate int _GetInterfaceFromGlobal(IntPtr thisPtr, IntPtr cookie, ref Guid riid, out IntPtr objectReference); + + public global::WinRT.Interop.IUnknownVftbl IUnknownVftbl; + public _RegisterInterfaceInGlobal RegisterInterfaceInGlobal; + public _RevokeInterfaceFromGlobal RevokeInterfaceFromGlobal; + public _GetInterfaceFromGlobal GetInterfaceFromGlobal; + } + + public static ObjectReference FromAbi(IntPtr thisPtr) => ObjectReference.FromAbi(thisPtr); + + public static implicit operator IGlobalInterfaceTable(IObjectReference obj) => (obj != null) ? new IGlobalInterfaceTable(obj) : null; + public static implicit operator IGlobalInterfaceTable(ObjectReference obj) => (obj != null) ? new IGlobalInterfaceTable(obj) : null; + protected readonly ObjectReference _obj; + public IntPtr ThisPtr => _obj.ThisPtr; + public ObjectReference AsInterface() => _obj.As(); + public A As() => _obj.AsType(); + + public IGlobalInterfaceTable(IObjectReference obj) : this(obj.As()) { } + public IGlobalInterfaceTable(ObjectReference obj) + { + _obj = obj; + } + + public IntPtr RegisterInterfaceInGlobal(IObjectReference objRef, Guid riid) + { + ExceptionHelpers.ThrowExceptionForHR(_obj.Vftbl.RegisterInterfaceInGlobal(ThisPtr, objRef.ThisPtr, ref riid, out IntPtr cookie)); + return cookie; + + } + + public void RevokeInterfaceFromGlobal(IntPtr cookie) + { + ExceptionHelpers.ThrowExceptionForHR(_obj.Vftbl.RevokeInterfaceFromGlobal(ThisPtr, cookie)); + } + + public IObjectReference GetInterfaceFromGlobal(IntPtr cookie, Guid riid) + { + ExceptionHelpers.ThrowExceptionForHR(_obj.Vftbl.GetInterfaceFromGlobal(ThisPtr, cookie, ref riid, out IntPtr ptr)); + try + { + return ComWrappersSupport.GetObjectReferenceForInterface(ptr); + } + finally + { + MarshalInspectable.DisposeAbi(ptr); + } + } + } } diff --git a/cswinrt/strings/WinRT.cs b/cswinrt/strings/WinRT.cs index 340544821..23bf0f03c 100644 --- a/cswinrt/strings/WinRT.cs +++ b/cswinrt/strings/WinRT.cs @@ -36,6 +36,9 @@ public static T AsDelegate(this MulticastDelegate del) internal class Platform { + [DllImport("api-ms-win-core-com-l1-1-0.dll")] + internal static extern unsafe int CoCreateInstance(ref Guid clsid, IntPtr outer, uint clsContext, ref Guid iid, IntPtr* instance); + [DllImport("api-ms-win-core-com-l1-1-0.dll")] internal static extern int CoDecrementMTAUsage(IntPtr cookie); From 1e33cadf20bb0c7684d79bda5db861a2f6a9e5ed Mon Sep 17 00:00:00 2001 From: Scott Jones Date: Wed, 10 Jun 2020 18:17:21 -0700 Subject: [PATCH 06/38] Switch to net5.0 TFM - requires VS 16.6 or updated nuget.exe (#234) * Initial attempt to target net5 tfm - requires VS 16.6 * nuget preview can handle net5 tfm, now just need msbuild targets support in VS 16.6 * allow fallback to netcoreapp5.0 tfm for winui * nuget tweaks --- Directory.Build.props | 2 ++ SignConfig.xml | 2 +- UnitTest/Directory.Build.props | 2 +- UnitTest/UnitTest.csproj | 3 ++- WinRT.Runtime/WinRT.Runtime.csproj | 4 ++-- WinUI/WinUIDesktopSample/WinUIDesktopSample.csproj | 2 +- WinUI/WinUIProjection/Directory.Build.props | 2 +- WinUI/WinUIProjection/WinUIProjection.csproj | 2 +- WinUI/WinUITest/WinUITest.csproj | 2 +- build.cmd | 11 +++++++---- nuget/Microsoft.Windows.CsWinRT.nuspec | 4 ++-- nuget/readme.txt | 2 +- 12 files changed, 22 insertions(+), 16 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index a0d327689..a2ca87195 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -7,6 +7,8 @@ 15.0 high 3.0.0-preview1.200419.0-CI + + netcoreapp5.0 diff --git a/SignConfig.xml b/SignConfig.xml index 7dd416e2c..7b72f7532 100644 --- a/SignConfig.xml +++ b/SignConfig.xml @@ -3,6 +3,6 @@ - + \ No newline at end of file diff --git a/UnitTest/Directory.Build.props b/UnitTest/Directory.Build.props index 70204f425..faa4c5964 100644 --- a/UnitTest/Directory.Build.props +++ b/UnitTest/Directory.Build.props @@ -3,7 +3,7 @@ - + $(DefineConstants);MANUAL_IUNKNOWN diff --git a/UnitTest/UnitTest.csproj b/UnitTest/UnitTest.csproj index e1b7762e9..d1a73f6f7 100644 --- a/UnitTest/UnitTest.csproj +++ b/UnitTest/UnitTest.csproj @@ -2,7 +2,7 @@ - netcoreapp2.0;netcoreapp5.0 + netcoreapp2.0;net5.0 false AnyCPU;x64;x86 Always @@ -11,6 +11,7 @@ true 1701;1702;0436;1658 10.0.18362.0 + netcoreapp5.0 diff --git a/WinRT.Runtime/WinRT.Runtime.csproj b/WinRT.Runtime/WinRT.Runtime.csproj index c9f6a9aae..fd849df76 100644 --- a/WinRT.Runtime/WinRT.Runtime.csproj +++ b/WinRT.Runtime/WinRT.Runtime.csproj @@ -1,7 +1,7 @@  - netstandard2.0;netcoreapp5.0 + netstandard2.0;net5.0 WinRT true 8 @@ -36,7 +36,7 @@ - + diff --git a/WinUI/WinUIDesktopSample/WinUIDesktopSample.csproj b/WinUI/WinUIDesktopSample/WinUIDesktopSample.csproj index 4b251444a..f7c27e9b0 100644 --- a/WinUI/WinUIDesktopSample/WinUIDesktopSample.csproj +++ b/WinUI/WinUIDesktopSample/WinUIDesktopSample.csproj @@ -2,7 +2,7 @@ WinExe - netcoreapp5.0 + net5.0 10.0.18362.0 DISABLE_XAML_GENERATED_MAIN WinUIDesktopSample.exe.manifest diff --git a/WinUI/WinUIProjection/Directory.Build.props b/WinUI/WinUIProjection/Directory.Build.props index 70204f425..faa4c5964 100644 --- a/WinUI/WinUIProjection/Directory.Build.props +++ b/WinUI/WinUIProjection/Directory.Build.props @@ -3,7 +3,7 @@ - + $(DefineConstants);MANUAL_IUNKNOWN diff --git a/WinUI/WinUIProjection/WinUIProjection.csproj b/WinUI/WinUIProjection/WinUIProjection.csproj index a01ac0af7..b69151cbb 100644 --- a/WinUI/WinUIProjection/WinUIProjection.csproj +++ b/WinUI/WinUIProjection/WinUIProjection.csproj @@ -1,7 +1,7 @@  - netcoreapp5.0 + net5.0 x64;x86 10.0.18362.0 $(CsWinrtPath)cswinrt.exe diff --git a/WinUI/WinUITest/WinUITest.csproj b/WinUI/WinUITest/WinUITest.csproj index 860d13a5b..bc1310a22 100644 --- a/WinUI/WinUITest/WinUITest.csproj +++ b/WinUI/WinUITest/WinUITest.csproj @@ -1,7 +1,7 @@  - netcoreapp5.0 + net5.0 false x64;x86 Always diff --git a/build.cmd b/build.cmd index 6176f6022..7e1718afe 100644 --- a/build.cmd +++ b/build.cmd @@ -1,7 +1,8 @@ @echo off -set Net5SdkVersion=5.0.100-preview.4.20217.5 +set Net5SdkVersion=5.0.100-preview.4.20227.10 +:dotnet rem Install required .NET 5 SDK version and add to environment set DOTNET_ROOT=%LocalAppData%\Microsoft\dotnet set DOTNET_ROOT(86)=%LocalAppData%\Microsoft\dotnet\x86 @@ -17,6 +18,7 @@ powershell -NoProfile -ExecutionPolicy unrestricted -Command ^ -Version '%Net5SdkVersion%' -InstallDir "%DOTNET_ROOT(86)%" -Architecture 'x86' ^ -AzureFeed 'https://dotnetcli.blob.core.windows.net/dotnet' " +:globaljson rem User expected to provide global.json with allowPrerelease=true if not exist %~dp0global.json ( echo global.json not found, creating one to allowPrelease for unit test project builds @@ -32,6 +34,7 @@ if not exist %~dp0global.json ( rem Preserve above for Visual Studio launch inheritance setlocal ENABLEDELAYEDEXPANSION +:params set cswinrt_platform=%1 set cswinrt_configuration=%2 set cswinrt_version_number=%3 @@ -68,7 +71,7 @@ if not "%cswinrt_label%"=="" goto %cswinrt_label% :restore if not exist .nuget md .nuget -if not exist .nuget\nuget.exe powershell -Command "Invoke-WebRequest https://dist.nuget.org/win-x86-commandline/latest/nuget.exe -OutFile .nuget\nuget.exe" +if not exist .nuget\nuget.exe powershell -Command "Invoke-WebRequest https://dist.nuget.org/win-x86-commandline/v5.6.0/nuget.exe -OutFile .nuget\nuget.exe" .nuget\nuget update -self .nuget\nuget.exe restore @@ -105,5 +108,5 @@ if ErrorLevel 1 ( set cswinrt_bin_dir=%~dp0_build\%cswinrt_platform%\%cswinrt_configuration%\cswinrt\bin\ set cswinrt_exe=%cswinrt_bin_dir%cswinrt.exe set netstandard2_runtime=%~dp0WinRT.Runtime\bin\%cswinrt_configuration%\netstandard2.0\WinRT.Runtime.dll -set netcoreapp5_runtime=%~dp0WinRT.Runtime\bin\%cswinrt_configuration%\netcoreapp5.0\WinRT.Runtime.dll -.nuget\nuget pack nuget/Microsoft.Windows.CsWinRT.nuspec -Properties cswinrt_exe=%cswinrt_exe%;netstandard2_runtime=%netstandard2_runtime%;netcoreapp5_runtime=%netcoreapp5_runtime%;cswinrt_nuget_version=%cswinrt_version_string% -OutputDirectory %cswinrt_bin_dir% -NonInteractive -Verbosity Detailed -NoPackageAnalysis +set net5_runtime=%~dp0WinRT.Runtime\bin\%cswinrt_configuration%\net5.0\WinRT.Runtime.dll +.nuget\nuget pack nuget/Microsoft.Windows.CsWinRT.nuspec -Properties cswinrt_exe=%cswinrt_exe%;netstandard2_runtime=%netstandard2_runtime%;net5_runtime=%net5_runtime%;cswinrt_nuget_version=%cswinrt_version_string% -OutputDirectory %cswinrt_bin_dir% -NonInteractive -Verbosity Detailed -NoPackageAnalysis diff --git a/nuget/Microsoft.Windows.CsWinRT.nuspec b/nuget/Microsoft.Windows.CsWinRT.nuspec index 4a2ed5d5d..6e7ba1617 100644 --- a/nuget/Microsoft.Windows.CsWinRT.nuspec +++ b/nuget/Microsoft.Windows.CsWinRT.nuspec @@ -15,7 +15,7 @@ https://github.com/microsoft/cswinrt/tree/master/ - + @@ -25,6 +25,6 @@ - + diff --git a/nuget/readme.txt b/nuget/readme.txt index 1b5703e28..1c1db6e4a 100644 --- a/nuget/readme.txt +++ b/nuget/readme.txt @@ -3,7 +3,7 @@ Microsoft.Windows.CsWinRT C#/WinRT Projection Tool ======================================================================== C#/WinRT provides packaged WinRT projection support for the C# language. -It is compatible with .NET Standard 2.2 and later and does not require +It is compatible with .NET Standard 2.0 and later and does not require any built-in knowledge of WinRT by the C# compiler. C#/WinRT is part of the xlang family of projects that help developers create From 0ff0203560e183339e4b86f61459e20cd80e8686 Mon Sep 17 00:00:00 2001 From: Manodasan Wignarajah Date: Wed, 10 Jun 2020 18:31:34 -0700 Subject: [PATCH 07/38] Address PR feedback. --- TestComponentCSharp/NonAgileClass.cpp | 43 +++------------------ WinRT.Runtime/AgileReference.cs | 55 ++++++++++++++++----------- WinRT.Runtime/ComWrappersSupport.cs | 6 +-- cswinrt/strings/WinRT.cs | 8 +--- 4 files changed, 42 insertions(+), 70 deletions(-) diff --git a/TestComponentCSharp/NonAgileClass.cpp b/TestComponentCSharp/NonAgileClass.cpp index c1bedb3b5..510532fdd 100644 --- a/TestComponentCSharp/NonAgileClass.cpp +++ b/TestComponentCSharp/NonAgileClass.cpp @@ -27,63 +27,32 @@ namespace HRESULT __stdcall GetUnmarshalClass(REFIID riid, void* pv, DWORD dwDestContext, void* pvDestContext, DWORD mshlflags, CLSID* pCid) noexcept final { - if (m_marshaler) - { - return m_marshaler->GetUnmarshalClass(riid, pv, dwDestContext, pvDestContext, mshlflags, pCid); - } - - return E_OUTOFMEMORY; + return m_marshaler->GetUnmarshalClass(riid, pv, dwDestContext, pvDestContext, mshlflags, pCid); } HRESULT __stdcall GetMarshalSizeMax(REFIID riid, void* pv, DWORD dwDestContext, void* pvDestContext, DWORD mshlflags, DWORD* pSize) noexcept final { - if (m_marshaler) - { - return m_marshaler->GetMarshalSizeMax(riid, pv, dwDestContext, pvDestContext, mshlflags, pSize); - } - - return E_OUTOFMEMORY; + return m_marshaler->GetMarshalSizeMax(riid, pv, dwDestContext, pvDestContext, mshlflags, pSize); } HRESULT __stdcall MarshalInterface(IStream* pStm, REFIID riid, void* pv, DWORD dwDestContext, void* pvDestContext, DWORD mshlflags) noexcept final { - if (m_marshaler) - { - return m_marshaler->MarshalInterface(pStm, riid, pv, dwDestContext, pvDestContext, mshlflags); - } - - return E_OUTOFMEMORY; + return m_marshaler->MarshalInterface(pStm, riid, pv, dwDestContext, pvDestContext, mshlflags); } HRESULT __stdcall UnmarshalInterface(IStream* pStm, REFIID riid, void** ppv) noexcept final { - if (m_marshaler) - { - return m_marshaler->UnmarshalInterface(pStm, riid, ppv); - } - - *ppv = nullptr; - return E_OUTOFMEMORY; + return m_marshaler->UnmarshalInterface(pStm, riid, ppv); } HRESULT __stdcall ReleaseMarshalData(IStream* pStm) noexcept final { - if (m_marshaler) - { - return m_marshaler->ReleaseMarshalData(pStm); - } - - return E_OUTOFMEMORY; + return m_marshaler->ReleaseMarshalData(pStm); } HRESULT __stdcall DisconnectObject(DWORD dwReserved) noexcept final { - if (m_marshaler) - { - return m_marshaler->DisconnectObject(dwReserved); - } - - return E_OUTOFMEMORY; + return m_marshaler->DisconnectObject(dwReserved); } void VectorChanged(Microsoft::UI::Xaml::Interop::IBindableObservableVector vector, Windows::Foundation::IInspectable e) diff --git a/WinRT.Runtime/AgileReference.cs b/WinRT.Runtime/AgileReference.cs index ec5206b9b..08ef8244e 100644 --- a/WinRT.Runtime/AgileReference.cs +++ b/WinRT.Runtime/AgileReference.cs @@ -14,13 +14,17 @@ public class AgileReference : IDisposable public unsafe AgileReference(IObjectReference instance) { + if(instance?.ThisPtr == null) + { + return; + } + IntPtr agileReference = default; - IntPtr gitPtr = default; Guid iid = typeof(IUnknownVftbl).GUID; try { Marshal.ThrowExceptionForHR(Platform.RoGetAgileReference( - Platform.AgileReferenceOptions.AGILEREFERENCE_DEFAULT, + 0 /*AGILEREFERENCE_DEFAULT*/, ref iid, instance.ThisPtr, &agileReference)); @@ -28,22 +32,12 @@ public unsafe AgileReference(IObjectReference instance) } catch(TypeLoadException) { - Guid gitClsid = CLSID_StdGlobalInterfaceTable; - Guid gitIid = typeof(IGlobalInterfaceTable).GUID; - Marshal.ThrowExceptionForHR(Platform.CoCreateInstance( - ref gitClsid, - IntPtr.Zero, - 1 /*CLSCTX_INPROC_SERVER*/, - ref gitIid, - &gitPtr)); - _git = ABI.WinRT.Interop.IGlobalInterfaceTable.FromAbi(gitPtr).AsType(); + _git = GetGitTable(); _cookie = _git.RegisterInterfaceInGlobal(instance, iid); - } finally { MarshalInterface.DisposeAbi(agileReference); - MarshalInterface.DisposeAbi(gitPtr); } } @@ -53,21 +47,38 @@ protected virtual void Dispose(bool disposing) { if (!disposed) { - try - { - if (_git != null && _cookie != IntPtr.Zero) - { - _git.RevokeInterfaceFromGlobal(_cookie); - } - } - catch(ObjectDisposedException) + if (_cookie != IntPtr.Zero) { - // TODO: How to handle removing from git when it has already been disposed. + // Obtaining new reference to git table in finalizer case to avoid race with finalizer cleaning up instance variables. + var git = disposing ? _git : GetGitTable(); + git.RevokeInterfaceFromGlobal(_cookie); } disposed = true; } } + private unsafe IGlobalInterfaceTable GetGitTable() + { + Guid gitClsid = CLSID_StdGlobalInterfaceTable; + Guid gitIid = typeof(IGlobalInterfaceTable).GUID; + IntPtr gitPtr = default; + + try + { + Marshal.ThrowExceptionForHR(Platform.CoCreateInstance( + ref gitClsid, + IntPtr.Zero, + 1 /*CLSCTX_INPROC_SERVER*/, + ref gitIid, + &gitPtr)); + return ABI.WinRT.Interop.IGlobalInterfaceTable.FromAbi(gitPtr).AsType(); + } + finally + { + MarshalInterface.DisposeAbi(gitPtr); + } + } + ~AgileReference() { Dispose(false); diff --git a/WinRT.Runtime/ComWrappersSupport.cs b/WinRT.Runtime/ComWrappersSupport.cs index 3707e8dbc..ebddffbce 100644 --- a/WinRT.Runtime/ComWrappersSupport.cs +++ b/WinRT.Runtime/ComWrappersSupport.cs @@ -28,8 +28,6 @@ public static partial class ComWrappersSupport { private readonly static ConcurrentDictionary> TypedObjectFactoryCache = new ConcurrentDictionary>(); - private readonly static Guid IID_IAgileObject = Guid.Parse("94ea2b94-e9cc-49e0-c0ff-ee64ca8f5b90"); - static ComWrappersSupport() { PlatformSpecificInitialize(); @@ -100,7 +98,7 @@ public static IObjectReference GetObjectReferenceForInterface(IntPtr externalCom { using var unknownRef = ObjectReference.FromAbi(externalComObject); - if (unknownRef.TryAs(IID_IAgileObject, out var agileRef) >= 0) + if (unknownRef.TryAs(typeof(ABI.WinRT.Interop.IAgileObject.Vftbl).GUID, out var agileRef) >= 0) { agileRef.Dispose(); return unknownRef.As(); @@ -192,7 +190,7 @@ internal static List GetInterfaceTableEntries(object obj) // Add IAgileObject to all CCWs entries.Add(new ComInterfaceEntry { - IID = IID_IAgileObject, + IID = typeof(ABI.WinRT.Interop.IAgileObject.Vftbl).GUID, Vtable = IUnknownVftbl.AbiToProjectionVftblPtr }); return entries; diff --git a/cswinrt/strings/WinRT.cs b/cswinrt/strings/WinRT.cs index 23bf0f03c..54b1d4b43 100644 --- a/cswinrt/strings/WinRT.cs +++ b/cswinrt/strings/WinRT.cs @@ -89,14 +89,8 @@ internal static extern unsafe int WindowsDuplicateString(IntPtr sourceString, [DllImport("api-ms-win-core-winrt-string-l1-1-0.dll", CallingConvention = CallingConvention.StdCall)] internal static extern unsafe char* WindowsGetStringRawBuffer(IntPtr hstring, uint* length); - internal enum AgileReferenceOptions : uint - { - AGILEREFERENCE_DEFAULT = 0x0, - AGILEREFERENCE_DELAYEDMARSHAL = 0x1 - } - [DllImport("api-ms-win-core-com-l1-1-1.dll", CallingConvention = CallingConvention.StdCall)] - internal static extern unsafe int RoGetAgileReference(AgileReferenceOptions options, ref Guid iid, IntPtr unknown, IntPtr* agileReference); + internal static extern unsafe int RoGetAgileReference(uint options, ref Guid iid, IntPtr unknown, IntPtr* agileReference); } internal struct VftblPtr From a13c31fcd10b590e5dc5fd15346c46d2033b9f14 Mon Sep 17 00:00:00 2001 From: Manodasan Wignarajah Date: Wed, 10 Jun 2020 22:57:21 -0700 Subject: [PATCH 08/38] Move git to static lazy reference and fix null case. --- UnitTest/TestComponentCSharp_Tests.cs | 7 ++++++- WinRT.Runtime/AgileReference.cs | 13 +++++-------- WinRT.Runtime/CastExtensions.cs | 5 +++++ WinRT.Runtime/ComWrappersSupport.net5.cs | 7 ++++++- 4 files changed, 22 insertions(+), 10 deletions(-) diff --git a/UnitTest/TestComponentCSharp_Tests.cs b/UnitTest/TestComponentCSharp_Tests.cs index d6f411c26..4607cac37 100644 --- a/UnitTest/TestComponentCSharp_Tests.cs +++ b/UnitTest/TestComponentCSharp_Tests.cs @@ -1524,7 +1524,12 @@ public void TestManagedAgileObject() Assert.Equal(properties.ReadWriteProperty, agileProperties.ReadWriteProperty); var agileObject = TestObject.As(); - Assert.NotNull(agileObject); + Assert.NotNull(agileObject); + + IProperties1 properties2 = null; + using var properties2AgileRef = properties2.AsAgile(); + var agileProperties2 = properties2AgileRef.Get(); + Assert.Null(agileProperties2); } class NonAgileClassCaller diff --git a/WinRT.Runtime/AgileReference.cs b/WinRT.Runtime/AgileReference.cs index 08ef8244e..f2d772486 100644 --- a/WinRT.Runtime/AgileReference.cs +++ b/WinRT.Runtime/AgileReference.cs @@ -7,8 +7,8 @@ namespace WinRT public class AgileReference : IDisposable { private readonly static Guid CLSID_StdGlobalInterfaceTable = Guid.Parse("00000323-0000-0000-c000-000000000046"); + private readonly static Lazy Git = new Lazy(() => GetGitTable()); private readonly IAgileReference _agileReference; - private readonly IGlobalInterfaceTable _git; private readonly IntPtr _cookie; private bool disposed; @@ -32,8 +32,7 @@ public unsafe AgileReference(IObjectReference instance) } catch(TypeLoadException) { - _git = GetGitTable(); - _cookie = _git.RegisterInterfaceInGlobal(instance, iid); + _cookie = Git.Value.RegisterInterfaceInGlobal(instance, iid); } finally { @@ -41,7 +40,7 @@ public unsafe AgileReference(IObjectReference instance) } } - public IObjectReference Get() => _agileReference?.Resolve(typeof(IUnknownVftbl).GUID) ?? _git?.GetInterfaceFromGlobal(_cookie, typeof(IUnknownVftbl).GUID); + public IObjectReference Get() => _cookie == IntPtr.Zero ? _agileReference?.Resolve(typeof(IUnknownVftbl).GUID) : Git.Value?.GetInterfaceFromGlobal(_cookie, typeof(IUnknownVftbl).GUID); protected virtual void Dispose(bool disposing) { @@ -49,15 +48,13 @@ protected virtual void Dispose(bool disposing) { if (_cookie != IntPtr.Zero) { - // Obtaining new reference to git table in finalizer case to avoid race with finalizer cleaning up instance variables. - var git = disposing ? _git : GetGitTable(); - git.RevokeInterfaceFromGlobal(_cookie); + Git.Value.RevokeInterfaceFromGlobal(_cookie); } disposed = true; } } - private unsafe IGlobalInterfaceTable GetGitTable() + private static unsafe IGlobalInterfaceTable GetGitTable() { Guid gitClsid = CLSID_StdGlobalInterfaceTable; Guid gitIid = typeof(IGlobalInterfaceTable).GUID; diff --git a/WinRT.Runtime/CastExtensions.cs b/WinRT.Runtime/CastExtensions.cs index a845fdc9d..09510ee59 100644 --- a/WinRT.Runtime/CastExtensions.cs +++ b/WinRT.Runtime/CastExtensions.cs @@ -57,6 +57,11 @@ public static TInterface As(this object value) /// Thrown if the runtime type of is not a projected type. public static AgileReference AsAgile(this T value) where T : class { + if(value == null) + { + return new AgileReference(null); + } + var marshal = Marshaler.CreateMarshaler(value); try { diff --git a/WinRT.Runtime/ComWrappersSupport.net5.cs b/WinRT.Runtime/ComWrappersSupport.net5.cs index 96be942ad..3f37c64e5 100644 --- a/WinRT.Runtime/ComWrappersSupport.net5.cs +++ b/WinRT.Runtime/ComWrappersSupport.net5.cs @@ -40,7 +40,12 @@ internal static unsafe InspectableInfo GetInspectableInfo(IntPtr pThis) } public static object CreateRcwForComObject(IntPtr ptr) - { + { + if (ptr == IntPtr.Zero) + { + return null; + } + var rcw = ComWrappers.GetOrCreateObjectForComInstance(ptr, CreateObjectFlags.TrackerObject); // Because .NET will de-duplicate strings and WinRT doesn't, // our RCW factory returns a wrapper of our string instance. From 7659cde6a4058f9f3bf56303478a9eee405a11eb Mon Sep 17 00:00:00 2001 From: William Kent Date: Thu, 11 Jun 2020 17:12:16 -0400 Subject: [PATCH 09/38] Fix error in README MSBuild sample (#305) * Fix MSBuild errors in README sample * Use $(IntermediateOutputPath) in README sample --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 462b7a6a2..b6583df55 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ An application project adds NuGet references to both the component interop assem The following msbuild project fragment demonstrates a simple invocation of cswinrt to generate projection sources for types in the Contoso namespace. These sources are then included in the project build. ``` - + # This sample demonstrates using a response file for cswinrt execution. @@ -51,7 +51,7 @@ The following msbuild project fragment demonstrates a simple invocation of cswin -include Contoso # Write projection sources to the "Generated Files" folder, # which should be excluded from checkin (e.g., .gitignored). --out "$(ProjectDir)Generated Files" +-out "$(IntermediateOutputPath)/Generated Files" - + - + ``` From ede4a473a22d4e263cdf49eb25ac2be4bf8c1dba Mon Sep 17 00:00:00 2001 From: Scott Jones Date: Fri, 12 Jun 2020 14:45:28 -0700 Subject: [PATCH 10/38] Restructure solution for better validation of projections (#313) * Initial restructure to exercise nuget package references instead of project references. Builds, but doesn't run. Some issues with how to manage the nuget cache while building/restoring. May need to ditch the nuget packaging, but keep the interop assemblies. * remove project refs * Remove nuget-based structure * fix tests, sample, remove nuspecs * winui tweak * post rebase fixups * post rebase fixup * cleanup * swallow RPC_E_DISCONNECTED in ContextCallback when apartment lost (this is better than try/catch which still causes test runs to fail in VS) * removed nuget-related cruft --- .gitignore | 1 + Directory.Build.props | 11 +- Directory.Build.targets | 13 +- Projections/Test/Test.csproj | 81 +++++++++++ .../WinUI/WinUI.csproj | 63 ++++----- Projections/Windows/Windows.csproj | 76 ++++++++++ .../TestComponentCSharp.vcxproj | 2 +- UnitTest/Directory.Build.props | 9 -- UnitTest/Directory.Build.targets | 96 ------------- UnitTest/TestComponentCSharp_Tests.cs | 4 +- UnitTest/TestComponent_Tests.cs | 4 +- UnitTest/UnitTest.csproj | 30 ++-- .../WinUITest.net5.cs | 13 +- WinRT.Runtime/Interop/IContextCallback.cs | 8 +- WinUI/WinUIProjection/Directory.Build.props | 9 -- WinUI/WinUIProjection/readme.txt | 14 -- WinUI/WinUITest/Directory.Build.targets | 10 -- .../WinUITest/Properties/launchSettings.json | 8 -- WinUI/WinUITest/WinUITest.csproj | 39 ------ WinUI/WinUITest/xunit.runner.json | 4 - .../App.xaml | 0 .../App.xaml.cs | 0 .../MainPage.xaml | 2 +- .../MainPage.xaml.cs | 0 .../WinUIDesktopSample.csproj | 9 +- .../WinUIDesktopSample.exe.manifest | 0 build.cmd | 1 + cswinrt.sln | 130 +++++++++++------- cswinrt/Directory.Build.targets | 5 + cswinrt/cswinrt.vcxproj | 7 +- cswinrt/cswinrt.vcxproj.filters | 1 + nuget.config | 3 + nuget/Microsoft.Windows.CsWinRT.props | 7 +- nuget/Microsoft.Windows.CsWinRT.targets | 10 +- 34 files changed, 338 insertions(+), 332 deletions(-) create mode 100644 Projections/Test/Test.csproj rename WinUI/WinUIProjection/WinUIProjection.csproj => Projections/WinUI/WinUI.csproj (53%) create mode 100644 Projections/Windows/Windows.csproj delete mode 100644 UnitTest/Directory.Build.props delete mode 100644 UnitTest/Directory.Build.targets rename WinUI/WinUITest/WinUITest.cs => UnitTest/WinUITest.net5.cs (63%) delete mode 100644 WinUI/WinUIProjection/Directory.Build.props delete mode 100644 WinUI/WinUIProjection/readme.txt delete mode 100644 WinUI/WinUITest/Directory.Build.targets delete mode 100644 WinUI/WinUITest/Properties/launchSettings.json delete mode 100644 WinUI/WinUITest/WinUITest.csproj delete mode 100644 WinUI/WinUITest/xunit.runner.json rename {WinUI/WinUIDesktopSample => WinUIDesktopSample}/App.xaml (100%) rename {WinUI/WinUIDesktopSample => WinUIDesktopSample}/App.xaml.cs (100%) rename {WinUI/WinUIDesktopSample => WinUIDesktopSample}/MainPage.xaml (92%) rename {WinUI/WinUIDesktopSample => WinUIDesktopSample}/MainPage.xaml.cs (100%) rename {WinUI/WinUIDesktopSample => WinUIDesktopSample}/WinUIDesktopSample.csproj (89%) rename {WinUI/WinUIDesktopSample => WinUIDesktopSample}/WinUIDesktopSample.exe.manifest (100%) create mode 100644 cswinrt/Directory.Build.targets diff --git a/.gitignore b/.gitignore index c251e5ae6..d57e2d16d 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,4 @@ TestWinRT _build/ global.json .nuget +.nupkg diff --git a/Directory.Build.props b/Directory.Build.props index a2ca87195..7b3b40496 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -11,6 +11,10 @@ netcoreapp5.0 + + $(DefineConstants);MANUAL_IUNKNOWN + + v141 10.0.17763.0 @@ -27,9 +31,8 @@ $(Platform) x86 $([MSBuild]::NormalizeDirectory('$(SolutionDir)_build', '$(BuildPlatform)', '$(Configuration)')) - $([MSBuild]::NormalizeDirectory('$(BuildOutDir)', 'cswinrt', 'bin')) - $([MSBuild]::NormalizeDirectory('$(SolutionDir)_build', 'x86', '$(Configuration)', 'cswinrt', 'bin')) - $(CsWinRTDir)cswinrt.exe + $([MSBuild]::NormalizeDirectory('$(BuildOutDir)', 'cswinrt', 'bin')) + $([MSBuild]::NormalizeDirectory('$(SolutionDir)_build', 'x86', '$(Configuration)', 'cswinrt', 'bin')) @@ -81,4 +84,6 @@ + + diff --git a/Directory.Build.targets b/Directory.Build.targets index 3fdf3bff0..4d90f8d5b 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -1,14 +1,5 @@ - - - $(ResolveAssemblyReferencesDependsOn);RemoveWindowsReference - - - - - - - - + + diff --git a/Projections/Test/Test.csproj b/Projections/Test/Test.csproj new file mode 100644 index 000000000..224c1001f --- /dev/null +++ b/Projections/Test/Test.csproj @@ -0,0 +1,81 @@ + + + + netstandard2.0;net5.0 + x64;x86 + 10.0.18362.0 + 8 + + + + true + true + 8305;0618 + + + + full + true + + + + + + + + + + + + + + + + + $([MSBuild]::NormalizeDirectory('$(NuGetPackageRoot)', 'microsoft.winui', '$(MicrosoftWinUIVersion)')) + + + + + + + + + + + high + $(IntermediateOutputPath)cswinrt_test.rsp + $(CsWinRTExe) %40"$(CsWinRTResponseFile)" + + + +-verbose +-in 10.0.18362.0 +-in @(ReferenceWinMDs->'"%(FullPath)"', ' ') +-out "$(ProjectDir)Generated Files" +-exclude Windows +-exclude Microsoft +-include TestComponent +-include TestComponentCSharp + + + + + + + + + + + + $([MSBuild]::NormalizeDirectory('$(NuGetPackageRoot)', 'microsoft.winui', '$(MicrosoftWinUIVersion)')) + + + + + + + + + + diff --git a/WinUI/WinUIProjection/WinUIProjection.csproj b/Projections/WinUI/WinUI.csproj similarity index 53% rename from WinUI/WinUIProjection/WinUIProjection.csproj rename to Projections/WinUI/WinUI.csproj index b69151cbb..03340e93e 100644 --- a/WinUI/WinUIProjection/WinUIProjection.csproj +++ b/Projections/WinUI/WinUI.csproj @@ -1,10 +1,10 @@  - net5.0 + netstandard2.0;net5.0 x64;x86 10.0.18362.0 - $(CsWinrtPath)cswinrt.exe + 8 @@ -12,53 +12,45 @@ true 8305;0618 - + + + full + true + + + - - - - compile; build + + + compile; build; runtime - - - - + + + + $([MSBuild]::NormalizeDirectory('$(NuGetPackageRoot)', 'microsoft.winui', '$(MicrosoftWinUIVersion)')) + - - + + + high - $(IntermediateOutputPath)cswinrt_platform.rsp + $(IntermediateOutputPath)cswinrt_winui.rsp $(CsWinrtExe) %40"$(CsWinRTResponseFile)" -verbose -in 10.0.18362.0 --in @(WinUIWinMDs->'"%(FullPath)"', ' ') +-in @(ReferenceWinMDs->'"%(FullPath)"', ' ') -out "$(ProjectDir)Generated Files" +-exclude Windows -include Microsoft --include Windows -# Exclude causality types colliding with those in System.Private.CoreLib.dll --exclude Windows.Foundation.Diagnostics -# Exclude Windows.UI, Windows.UI.Text, Windows.UI.Xaml per Microsoft.Windows.SDK.WinUI.Contracts NuGet --exclude Windows.UI.Colors --exclude Windows.UI.IColors --exclude Windows.UI.ColorHelper --exclude Windows.UI.IColorHelper -#-exclude Windows.UI.Text (see below: must include Windows.UI.Text to workaround WinUI nuget issues) --exclude Windows.UI.Xaml --exclude Windows.ApplicationModel.Store.Preview -# Allow Windows.UI.Text, Windows.UI.Xaml types used in other namespaces --include Windows.UI.Text.FontStretch --include Windows.UI.Text.FontStyle --include Windows.UI.Text.FontWeight --include Windows.UI.Text.UnderlineType # The current WinUI nuget incorrectly references several Windows.* types that should be # Microsoft.* types instead. Temporarily include these to enable the build -include Windows.UI.Xaml.Interop.Type @@ -82,15 +74,10 @@ - - - - %(RecursiveDir) - - - + + diff --git a/Projections/Windows/Windows.csproj b/Projections/Windows/Windows.csproj new file mode 100644 index 000000000..f17350fda --- /dev/null +++ b/Projections/Windows/Windows.csproj @@ -0,0 +1,76 @@ + + + + netstandard2.0;net5.0 + x64;x86 + 10.0.18362.0 + 8 + + + + true + true + 8305;0618 + + + + full + true + + + + full + true + + + + + + + + + + + + high + $(IntermediateOutputPath)cswinrt_windows.rsp + $(CsWinrtExe) %40"$(CsWinRTResponseFile)" + + + +-verbose +-in 10.0.18362.0 +-out "$(ProjectDir)Generated Files" +-include Windows +# Exclude causality types colliding with those in System.Private.CoreLib.dll +-exclude Windows.Foundation.Diagnostics +# Exclude Windows.UI, Windows.UI.Text, Windows.UI.Xaml per Microsoft.Windows.SDK.WinUI.Contracts NuGet +-include Windows.UI.Popups +-exclude Windows.UI.Colors +-exclude Windows.UI.IColors +-exclude Windows.UI.ColorHelper +-exclude Windows.UI.IColorHelper +#-exclude Windows.UI.Text (must include Windows.UI.Text to work around WinUI nuget issues) +-exclude Windows.UI.Xaml +-exclude Windows.ApplicationModel.Store.Preview +# Allow Windows.UI.Text, Windows.UI.Xaml types used in other namespaces +-include Windows.UI.Text.FontStretch +-include Windows.UI.Text.FontStyle +-include Windows.UI.Text.FontWeight +-include Windows.UI.Text.UnderlineType +-include Windows.UI.Xaml.Media.Animation.ConditionallyIndependentlyAnimatableAttribute + + + + + + + + + + + + + + + diff --git a/TestComponentCSharp/TestComponentCSharp.vcxproj b/TestComponentCSharp/TestComponentCSharp.vcxproj index b5d127766..3f7998ec1 100644 --- a/TestComponentCSharp/TestComponentCSharp.vcxproj +++ b/TestComponentCSharp/TestComponentCSharp.vcxproj @@ -73,7 +73,7 @@ - + Create diff --git a/UnitTest/Directory.Build.props b/UnitTest/Directory.Build.props deleted file mode 100644 index faa4c5964..000000000 --- a/UnitTest/Directory.Build.props +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - $(DefineConstants);MANUAL_IUNKNOWN - - diff --git a/UnitTest/Directory.Build.targets b/UnitTest/Directory.Build.targets deleted file mode 100644 index aeeac76f4..000000000 --- a/UnitTest/Directory.Build.targets +++ /dev/null @@ -1,96 +0,0 @@ - - - - - $(IsCrossTargetingBuild) - - - - - - - - - - - - - - - - $([MSBuild]::NormalizeDirectory('$(NuGetPackageRoot)', 'microsoft.winui', '$(MicrosoftWinUIVersion)')) - - - - - - - - - - - high - $(IntermediateOutputPath)cswinrt_unittest.rsp - $(CsWinrtExe) %40"$(CsWinRTResponseFile)" - - - --verbose --in 10.0.18362.0 --in @(WinUIWinMDs->'"%(FullPath)"', ' ') --in @(UnitTestWinMDs->'"%(FullPath)"', ' ') --out "$(ProjectDir)Generated Files" --include TestComponentCSharp --include TestComponent --include Windows.Foundation --include Windows.UI.Popups --include Windows.UI.Color --include Microsoft.UI.Xaml.CornerRadius --include Microsoft.UI.Xaml.Duration --include Microsoft.UI.Xaml.DurationType --include Microsoft.UI.Xaml.GridLength --include Microsoft.UI.Xaml.GridUnitType --include Microsoft.UI.Xaml.Thickness --include Microsoft.UI.Xaml.Controls.Primitives.GeneratorPosition --include Microsoft.UI.Xaml.Interop --include Microsoft.UI.Xaml.Media.Matrix --exclude Microsoft.UI.Xaml.Media.MatrixTransform --exclude Microsoft.UI.Xaml.Media.Matrix3DProjection --include Microsoft.UI.Xaml.Media.Animation.KeyTime --include Microsoft.UI.Xaml.Media.Animation.RepeatBehavior --include Microsoft.UI.Xaml.Media.Animation.RepeatBehaviorType --include Microsoft.UI.Xaml.Media.Media3D.Matrix3D --include Microsoft.UI.Xaml.WinUIContract -# Exclude causality types colliding with those in System.Private.CoreLib.dll --exclude Windows.Foundation.Diagnostics -# Exclude types per Microsoft.Windows.SDK.WinUI.Contracts NuGet --exclude Windows.UI.Colors --exclude Windows.UI.IColors --exclude Windows.UI.ColorHelper --exclude Windows.UI.IColorHelper -# The current WinUI nuget incorrectly references several Windows.* types that should be -# Microsoft.* types instead. Temporarily include these to enable the build --include Windows.UI.Xaml.Interop.NotifyCollectionChangedAction - - - - - - - - - - - - - - - - diff --git a/UnitTest/TestComponentCSharp_Tests.cs b/UnitTest/TestComponentCSharp_Tests.cs index 5a7fcfeea..c6ac128f3 100644 --- a/UnitTest/TestComponentCSharp_Tests.cs +++ b/UnitTest/TestComponentCSharp_Tests.cs @@ -24,11 +24,11 @@ namespace UnitTest { - public class TestComp + public class TestCSharp { public Class TestObject { get; private set; } - public TestComp() + public TestCSharp() { TestObject = new Class(); } diff --git a/UnitTest/TestComponent_Tests.cs b/UnitTest/TestComponent_Tests.cs index 76ff76c1e..bbf46082d 100644 --- a/UnitTest/TestComponent_Tests.cs +++ b/UnitTest/TestComponent_Tests.cs @@ -9,11 +9,11 @@ namespace UnitTest { - public class TestComponent + public class TestWinRT { public ITests Tests { get; private set; } - public TestComponent() + public TestWinRT() { Tests = TestRunner.MakeTests(); } diff --git a/UnitTest/UnitTest.csproj b/UnitTest/UnitTest.csproj index d1a73f6f7..7fb23a253 100644 --- a/UnitTest/UnitTest.csproj +++ b/UnitTest/UnitTest.csproj @@ -15,12 +15,11 @@ + + + - - - - compile; build - + @@ -44,15 +43,22 @@ - - - - - + + + - - + + + + + + + + + + + diff --git a/WinUI/WinUITest/WinUITest.cs b/UnitTest/WinUITest.net5.cs similarity index 63% rename from WinUI/WinUITest/WinUITest.cs rename to UnitTest/WinUITest.net5.cs index fb7e24713..7abd9d2c0 100644 --- a/WinUI/WinUITest/WinUITest.cs +++ b/UnitTest/WinUITest.net5.cs @@ -1,4 +1,3 @@ -// WinUI projection smoke test (compile only) using System; using System.Diagnostics; using System.Linq; @@ -10,25 +9,25 @@ using Windows.Foundation; using Windows.Foundation.Collections; -namespace WinUITest +namespace UnitTest { - public class TestProjection + public class TestWinUI { - public TestProjection() + public TestWinUI() { } - public class TestApp : Microsoft.UI.Xaml.Application + public class App : Microsoft.UI.Xaml.Application { } [Fact] - public void TestSomeWinUI() + public void TestApp() { WinrtModule module = new WinrtModule(); - var app = new TestApp(); + var app = new App(); // TODO: load up some MUX! //Assert.Equal(true, true); } diff --git a/WinRT.Runtime/Interop/IContextCallback.cs b/WinRT.Runtime/Interop/IContextCallback.cs index cfec75da6..49c4b9752 100644 --- a/WinRT.Runtime/Interop/IContextCallback.cs +++ b/WinRT.Runtime/Interop/IContextCallback.cs @@ -71,9 +71,15 @@ private unsafe struct ContextCallData public ComCallData* userData; } + private const int RPC_E_DISCONNECTED = unchecked((int)0x80010108); + public unsafe void ContextCallback(global::WinRT.Interop.PFNCONTEXTCALL pfnCallback, ComCallData* pParam, Guid riid, int iMethod) { - Marshal.ThrowExceptionForHR(_obj.Vftbl.ContextCallback_4(ThisPtr, pfnCallback, pParam, ref riid, iMethod, IntPtr.Zero)); + var result = _obj.Vftbl.ContextCallback_4(ThisPtr, pfnCallback, pParam, ref riid, iMethod, IntPtr.Zero); + if (result != RPC_E_DISCONNECTED) + { + Marshal.ThrowExceptionForHR(result); + } } } } \ No newline at end of file diff --git a/WinUI/WinUIProjection/Directory.Build.props b/WinUI/WinUIProjection/Directory.Build.props deleted file mode 100644 index faa4c5964..000000000 --- a/WinUI/WinUIProjection/Directory.Build.props +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - $(DefineConstants);MANUAL_IUNKNOWN - - diff --git a/WinUI/WinUIProjection/readme.txt b/WinUI/WinUIProjection/readme.txt deleted file mode 100644 index e649033d2..000000000 --- a/WinUI/WinUIProjection/readme.txt +++ /dev/null @@ -1,14 +0,0 @@ -This project simply generates and compiles a complete projection of Windows SDK and WinUI metadata. - -With a release cswinrt.exe, it takes < 1s to generate all of the projection sources. -With debug, it takes a minute. So only release builds create the projection by default. -This can be overridden by explicitly setting the BuildTestProjection property. - -This project assumes a private nuget source has been created, pointing to: -https://microsoft.pkgs.visualstudio.com/_packaging/WinUI-Xaml-CI@IXP/nuget/v3/index.json - -For usability (until the cswinrt nuget has msbuild support), this and the UnitTest projects -both make use of Directory.Build.* files to create the projection, stage binaries, etc. - -WinUITest uses a response file to generate the projection, which can be supplied as a -debugging parameter to the cswinrt project. \ No newline at end of file diff --git a/WinUI/WinUITest/Directory.Build.targets b/WinUI/WinUITest/Directory.Build.targets deleted file mode 100644 index 36c0ca02d..000000000 --- a/WinUI/WinUITest/Directory.Build.targets +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/WinUI/WinUITest/Properties/launchSettings.json b/WinUI/WinUITest/Properties/launchSettings.json deleted file mode 100644 index e80f30c0a..000000000 --- a/WinUI/WinUITest/Properties/launchSettings.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "profiles": { - "UnitTest": { - "commandName": "Project", - "nativeDebugging": false - } - } -} \ No newline at end of file diff --git a/WinUI/WinUITest/WinUITest.csproj b/WinUI/WinUITest/WinUITest.csproj deleted file mode 100644 index bc1310a22..000000000 --- a/WinUI/WinUITest/WinUITest.csproj +++ /dev/null @@ -1,39 +0,0 @@ - - - - net5.0 - false - x64;x86 - Always - WinUITest - 8 - - - - 1701;1702;0436;1658 - - - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - - - - diff --git a/WinUI/WinUITest/xunit.runner.json b/WinUI/WinUITest/xunit.runner.json deleted file mode 100644 index 8dac5f6e1..000000000 --- a/WinUI/WinUITest/xunit.runner.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "$schema": "https://xunit.net/schema/current/xunit.runner.schema.json", - "shadowCopy": false -} \ No newline at end of file diff --git a/WinUI/WinUIDesktopSample/App.xaml b/WinUIDesktopSample/App.xaml similarity index 100% rename from WinUI/WinUIDesktopSample/App.xaml rename to WinUIDesktopSample/App.xaml diff --git a/WinUI/WinUIDesktopSample/App.xaml.cs b/WinUIDesktopSample/App.xaml.cs similarity index 100% rename from WinUI/WinUIDesktopSample/App.xaml.cs rename to WinUIDesktopSample/App.xaml.cs diff --git a/WinUI/WinUIDesktopSample/MainPage.xaml b/WinUIDesktopSample/MainPage.xaml similarity index 92% rename from WinUI/WinUIDesktopSample/MainPage.xaml rename to WinUIDesktopSample/MainPage.xaml index 28671b530..aa1fc2287 100644 --- a/WinUI/WinUIDesktopSample/MainPage.xaml +++ b/WinUIDesktopSample/MainPage.xaml @@ -3,7 +3,7 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" - xmlns:local="NetCoreDesktopSample" + xmlns:local="WinUIDesktopSample" mc:Ignorable="d" Height="450" Width="800"> diff --git a/WinUI/WinUIDesktopSample/MainPage.xaml.cs b/WinUIDesktopSample/MainPage.xaml.cs similarity index 100% rename from WinUI/WinUIDesktopSample/MainPage.xaml.cs rename to WinUIDesktopSample/MainPage.xaml.cs diff --git a/WinUI/WinUIDesktopSample/WinUIDesktopSample.csproj b/WinUIDesktopSample/WinUIDesktopSample.csproj similarity index 89% rename from WinUI/WinUIDesktopSample/WinUIDesktopSample.csproj rename to WinUIDesktopSample/WinUIDesktopSample.csproj index f7c27e9b0..0d4f8d9fa 100644 --- a/WinUI/WinUIDesktopSample/WinUIDesktopSample.csproj +++ b/WinUIDesktopSample/WinUIDesktopSample.csproj @@ -22,12 +22,14 @@ + + - compile; + compile; runtime @@ -42,9 +44,4 @@ - - - - - \ No newline at end of file diff --git a/WinUI/WinUIDesktopSample/WinUIDesktopSample.exe.manifest b/WinUIDesktopSample/WinUIDesktopSample.exe.manifest similarity index 100% rename from WinUI/WinUIDesktopSample/WinUIDesktopSample.exe.manifest rename to WinUIDesktopSample/WinUIDesktopSample.exe.manifest diff --git a/build.cmd b/build.cmd index 7e1718afe..b4395cb57 100644 --- a/build.cmd +++ b/build.cmd @@ -104,6 +104,7 @@ if ErrorLevel 1 ( exit /b !ErrorLevel! ) +rem todo remove all this :package set cswinrt_bin_dir=%~dp0_build\%cswinrt_platform%\%cswinrt_configuration%\cswinrt\bin\ set cswinrt_exe=%cswinrt_bin_dir%cswinrt.exe diff --git a/cswinrt.sln b/cswinrt.sln index 763b97452..e9b85aa6f 100644 --- a/cswinrt.sln +++ b/cswinrt.sln @@ -11,8 +11,11 @@ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTest", "UnitTest\UnitTest.csproj", "{9A9F52CA-F624-43A4-B5EF-C50861F584C2}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cswinrt", "cswinrt\cswinrt.vcxproj", "{6ACFD2B2-E8AA-4CD4-AAD8-213CE8BB2637}" + ProjectSection(ProjectDependencies) = postProject + {25244CED-966E-45F2-9711-1F51E951FF89} = {25244CED-966E-45F2-9711-1F51E951FF89} + EndProjectSection EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Files", "Solution Files", "{96495AB4-2D86-47D1-A174-27D0B436DC98}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Files", "Files", "{96495AB4-2D86-47D1-A174-27D0B436DC98}" ProjectSection(SolutionItems) = preProject .gitignore = .gitignore build.cmd = build.cmd @@ -30,13 +33,26 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestComponent", "TestWinRT\ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WinRT.Runtime", "WinRT.Runtime\WinRT.Runtime.csproj", "{25244CED-966E-45F2-9711-1F51E951FF89}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WinUI", "WinUI", "{325B6B80-4029-45FA-9429-004C1214B3EB}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WinUIDesktopSample", "WinUIDesktopSample\WinUIDesktopSample.csproj", "{8E6FBCB2-B0C1-4E92-8AEB-2A11564E6E0D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Test", "Projections\Test\Test.csproj", "{C6D580C5-7037-4733-B933-916FF400AFE2}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WinUIDesktopSample", "WinUI\WinUIDesktopSample\WinUIDesktopSample.csproj", "{B04E3F7C-BE25-4384-8D6F-7E450DBDBC70}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Projections", "Projections", "{6D41796B-9904-40B8-BBCB-40B2D1BAE44B}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WinUIProjection", "WinUI\WinUIProjection\WinUIProjection.csproj", "{DAFC85B3-27AF-43EA-8F83-207E303BE7EF}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Windows", "Projections\Windows\Windows.csproj", "{FFA9A78B-F53F-43EE-AF87-24A80F4C330A}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WinUITest", "WinUI\WinUITest\WinUITest.csproj", "{B2CCF56D-27A9-427A-BA82-6CA11774DA90}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WinUI", "Projections\WinUI\WinUI.csproj", "{0A991D5F-BFEE-4D2F-9AAD-6AD06470A5DF}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Nuget", "Nuget", "{5A94EFDF-A6AC-494D-A731-A0A8A37F1F6C}" + ProjectSection(SolutionItems) = preProject + nuget\LICENSE = nuget\LICENSE + nuget\Microsoft.Windows.CsWinRT.nuspec = nuget\Microsoft.Windows.CsWinRT.nuspec + nuget\Microsoft.Windows.CsWinRT.props = nuget\Microsoft.Windows.CsWinRT.props + nuget\Microsoft.Windows.CsWinRT.targets = nuget\Microsoft.Windows.CsWinRT.targets + nuget\readme.md = nuget\readme.md + nuget\readme.txt = nuget\readme.txt + nuget\SignConfig.xml = nuget\SignConfig.xml + EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -136,56 +152,70 @@ Global {25244CED-966E-45F2-9711-1F51E951FF89}.Release|x64.Build.0 = Release|Any CPU {25244CED-966E-45F2-9711-1F51E951FF89}.Release|x86.ActiveCfg = Release|Any CPU {25244CED-966E-45F2-9711-1F51E951FF89}.Release|x86.Build.0 = Release|Any CPU - {B04E3F7C-BE25-4384-8D6F-7E450DBDBC70}.Debug|Any CPU.ActiveCfg = Debug|x86 - {B04E3F7C-BE25-4384-8D6F-7E450DBDBC70}.Debug|ARM.ActiveCfg = Debug|x86 - {B04E3F7C-BE25-4384-8D6F-7E450DBDBC70}.Debug|ARM64.ActiveCfg = Debug|x86 - {B04E3F7C-BE25-4384-8D6F-7E450DBDBC70}.Debug|x64.ActiveCfg = Debug|x64 - {B04E3F7C-BE25-4384-8D6F-7E450DBDBC70}.Debug|x64.Build.0 = Debug|x64 - {B04E3F7C-BE25-4384-8D6F-7E450DBDBC70}.Debug|x86.ActiveCfg = Debug|x86 - {B04E3F7C-BE25-4384-8D6F-7E450DBDBC70}.Debug|x86.Build.0 = Debug|x86 - {B04E3F7C-BE25-4384-8D6F-7E450DBDBC70}.Release|Any CPU.ActiveCfg = Release|x86 - {B04E3F7C-BE25-4384-8D6F-7E450DBDBC70}.Release|ARM.ActiveCfg = Release|x86 - {B04E3F7C-BE25-4384-8D6F-7E450DBDBC70}.Release|ARM64.ActiveCfg = Release|x86 - {B04E3F7C-BE25-4384-8D6F-7E450DBDBC70}.Release|x64.ActiveCfg = Release|x64 - {B04E3F7C-BE25-4384-8D6F-7E450DBDBC70}.Release|x64.Build.0 = Release|x64 - {B04E3F7C-BE25-4384-8D6F-7E450DBDBC70}.Release|x86.ActiveCfg = Release|x86 - {B04E3F7C-BE25-4384-8D6F-7E450DBDBC70}.Release|x86.Build.0 = Release|x86 - {DAFC85B3-27AF-43EA-8F83-207E303BE7EF}.Debug|Any CPU.ActiveCfg = Debug|x86 - {DAFC85B3-27AF-43EA-8F83-207E303BE7EF}.Debug|ARM.ActiveCfg = Debug|x86 - {DAFC85B3-27AF-43EA-8F83-207E303BE7EF}.Debug|ARM64.ActiveCfg = Debug|x86 - {DAFC85B3-27AF-43EA-8F83-207E303BE7EF}.Debug|x64.ActiveCfg = Debug|x64 - {DAFC85B3-27AF-43EA-8F83-207E303BE7EF}.Debug|x64.Build.0 = Debug|x64 - {DAFC85B3-27AF-43EA-8F83-207E303BE7EF}.Debug|x86.ActiveCfg = Debug|x86 - {DAFC85B3-27AF-43EA-8F83-207E303BE7EF}.Debug|x86.Build.0 = Debug|x86 - {DAFC85B3-27AF-43EA-8F83-207E303BE7EF}.Release|Any CPU.ActiveCfg = Release|x86 - {DAFC85B3-27AF-43EA-8F83-207E303BE7EF}.Release|ARM.ActiveCfg = Release|x86 - {DAFC85B3-27AF-43EA-8F83-207E303BE7EF}.Release|ARM64.ActiveCfg = Release|x86 - {DAFC85B3-27AF-43EA-8F83-207E303BE7EF}.Release|x64.ActiveCfg = Release|x64 - {DAFC85B3-27AF-43EA-8F83-207E303BE7EF}.Release|x64.Build.0 = Release|x64 - {DAFC85B3-27AF-43EA-8F83-207E303BE7EF}.Release|x86.ActiveCfg = Release|x86 - {DAFC85B3-27AF-43EA-8F83-207E303BE7EF}.Release|x86.Build.0 = Release|x86 - {B2CCF56D-27A9-427A-BA82-6CA11774DA90}.Debug|Any CPU.ActiveCfg = Debug|x86 - {B2CCF56D-27A9-427A-BA82-6CA11774DA90}.Debug|ARM.ActiveCfg = Debug|x86 - {B2CCF56D-27A9-427A-BA82-6CA11774DA90}.Debug|ARM64.ActiveCfg = Debug|x86 - {B2CCF56D-27A9-427A-BA82-6CA11774DA90}.Debug|x64.ActiveCfg = Debug|x64 - {B2CCF56D-27A9-427A-BA82-6CA11774DA90}.Debug|x64.Build.0 = Debug|x64 - {B2CCF56D-27A9-427A-BA82-6CA11774DA90}.Debug|x86.ActiveCfg = Debug|x86 - {B2CCF56D-27A9-427A-BA82-6CA11774DA90}.Debug|x86.Build.0 = Debug|x86 - {B2CCF56D-27A9-427A-BA82-6CA11774DA90}.Release|Any CPU.ActiveCfg = Release|x86 - {B2CCF56D-27A9-427A-BA82-6CA11774DA90}.Release|ARM.ActiveCfg = Release|x86 - {B2CCF56D-27A9-427A-BA82-6CA11774DA90}.Release|ARM64.ActiveCfg = Release|x86 - {B2CCF56D-27A9-427A-BA82-6CA11774DA90}.Release|x64.ActiveCfg = Release|x64 - {B2CCF56D-27A9-427A-BA82-6CA11774DA90}.Release|x64.Build.0 = Release|x64 - {B2CCF56D-27A9-427A-BA82-6CA11774DA90}.Release|x86.ActiveCfg = Release|x86 - {B2CCF56D-27A9-427A-BA82-6CA11774DA90}.Release|x86.Build.0 = Release|x86 + {8E6FBCB2-B0C1-4E92-8AEB-2A11564E6E0D}.Debug|Any CPU.ActiveCfg = Debug|x86 + {8E6FBCB2-B0C1-4E92-8AEB-2A11564E6E0D}.Debug|ARM.ActiveCfg = Debug|x86 + {8E6FBCB2-B0C1-4E92-8AEB-2A11564E6E0D}.Debug|ARM64.ActiveCfg = Debug|x86 + {8E6FBCB2-B0C1-4E92-8AEB-2A11564E6E0D}.Debug|x64.ActiveCfg = Debug|x64 + {8E6FBCB2-B0C1-4E92-8AEB-2A11564E6E0D}.Debug|x64.Build.0 = Debug|x64 + {8E6FBCB2-B0C1-4E92-8AEB-2A11564E6E0D}.Debug|x86.ActiveCfg = Debug|x86 + {8E6FBCB2-B0C1-4E92-8AEB-2A11564E6E0D}.Debug|x86.Build.0 = Debug|x86 + {8E6FBCB2-B0C1-4E92-8AEB-2A11564E6E0D}.Release|Any CPU.ActiveCfg = Release|x86 + {8E6FBCB2-B0C1-4E92-8AEB-2A11564E6E0D}.Release|ARM.ActiveCfg = Release|x86 + {8E6FBCB2-B0C1-4E92-8AEB-2A11564E6E0D}.Release|ARM64.ActiveCfg = Release|x86 + {8E6FBCB2-B0C1-4E92-8AEB-2A11564E6E0D}.Release|x64.ActiveCfg = Release|x64 + {8E6FBCB2-B0C1-4E92-8AEB-2A11564E6E0D}.Release|x64.Build.0 = Release|x64 + {8E6FBCB2-B0C1-4E92-8AEB-2A11564E6E0D}.Release|x86.ActiveCfg = Release|x86 + {8E6FBCB2-B0C1-4E92-8AEB-2A11564E6E0D}.Release|x86.Build.0 = Release|x86 + {C6D580C5-7037-4733-B933-916FF400AFE2}.Debug|Any CPU.ActiveCfg = Debug|x86 + {C6D580C5-7037-4733-B933-916FF400AFE2}.Debug|ARM.ActiveCfg = Debug|x86 + {C6D580C5-7037-4733-B933-916FF400AFE2}.Debug|ARM64.ActiveCfg = Debug|x86 + {C6D580C5-7037-4733-B933-916FF400AFE2}.Debug|x64.ActiveCfg = Debug|x64 + {C6D580C5-7037-4733-B933-916FF400AFE2}.Debug|x64.Build.0 = Debug|x64 + {C6D580C5-7037-4733-B933-916FF400AFE2}.Debug|x86.ActiveCfg = Debug|x86 + {C6D580C5-7037-4733-B933-916FF400AFE2}.Debug|x86.Build.0 = Debug|x86 + {C6D580C5-7037-4733-B933-916FF400AFE2}.Release|Any CPU.ActiveCfg = Release|x86 + {C6D580C5-7037-4733-B933-916FF400AFE2}.Release|ARM.ActiveCfg = Release|x86 + {C6D580C5-7037-4733-B933-916FF400AFE2}.Release|ARM64.ActiveCfg = Release|x86 + {C6D580C5-7037-4733-B933-916FF400AFE2}.Release|x64.ActiveCfg = Release|x64 + {C6D580C5-7037-4733-B933-916FF400AFE2}.Release|x64.Build.0 = Release|x64 + {C6D580C5-7037-4733-B933-916FF400AFE2}.Release|x86.ActiveCfg = Release|x86 + {C6D580C5-7037-4733-B933-916FF400AFE2}.Release|x86.Build.0 = Release|x86 + {FFA9A78B-F53F-43EE-AF87-24A80F4C330A}.Debug|Any CPU.ActiveCfg = Debug|x86 + {FFA9A78B-F53F-43EE-AF87-24A80F4C330A}.Debug|ARM.ActiveCfg = Debug|x86 + {FFA9A78B-F53F-43EE-AF87-24A80F4C330A}.Debug|ARM64.ActiveCfg = Debug|x86 + {FFA9A78B-F53F-43EE-AF87-24A80F4C330A}.Debug|x64.ActiveCfg = Debug|x64 + {FFA9A78B-F53F-43EE-AF87-24A80F4C330A}.Debug|x64.Build.0 = Debug|x64 + {FFA9A78B-F53F-43EE-AF87-24A80F4C330A}.Debug|x86.ActiveCfg = Debug|x86 + {FFA9A78B-F53F-43EE-AF87-24A80F4C330A}.Debug|x86.Build.0 = Debug|x86 + {FFA9A78B-F53F-43EE-AF87-24A80F4C330A}.Release|Any CPU.ActiveCfg = Release|x86 + {FFA9A78B-F53F-43EE-AF87-24A80F4C330A}.Release|ARM.ActiveCfg = Release|x86 + {FFA9A78B-F53F-43EE-AF87-24A80F4C330A}.Release|ARM64.ActiveCfg = Release|x86 + {FFA9A78B-F53F-43EE-AF87-24A80F4C330A}.Release|x64.ActiveCfg = Release|x64 + {FFA9A78B-F53F-43EE-AF87-24A80F4C330A}.Release|x64.Build.0 = Release|x64 + {FFA9A78B-F53F-43EE-AF87-24A80F4C330A}.Release|x86.ActiveCfg = Release|x86 + {FFA9A78B-F53F-43EE-AF87-24A80F4C330A}.Release|x86.Build.0 = Release|x86 + {0A991D5F-BFEE-4D2F-9AAD-6AD06470A5DF}.Debug|Any CPU.ActiveCfg = Debug|x86 + {0A991D5F-BFEE-4D2F-9AAD-6AD06470A5DF}.Debug|ARM.ActiveCfg = Debug|x86 + {0A991D5F-BFEE-4D2F-9AAD-6AD06470A5DF}.Debug|ARM64.ActiveCfg = Debug|x86 + {0A991D5F-BFEE-4D2F-9AAD-6AD06470A5DF}.Debug|x64.ActiveCfg = Debug|x64 + {0A991D5F-BFEE-4D2F-9AAD-6AD06470A5DF}.Debug|x64.Build.0 = Debug|x64 + {0A991D5F-BFEE-4D2F-9AAD-6AD06470A5DF}.Debug|x86.ActiveCfg = Debug|x86 + {0A991D5F-BFEE-4D2F-9AAD-6AD06470A5DF}.Debug|x86.Build.0 = Debug|x86 + {0A991D5F-BFEE-4D2F-9AAD-6AD06470A5DF}.Release|Any CPU.ActiveCfg = Release|x86 + {0A991D5F-BFEE-4D2F-9AAD-6AD06470A5DF}.Release|ARM.ActiveCfg = Release|x86 + {0A991D5F-BFEE-4D2F-9AAD-6AD06470A5DF}.Release|ARM64.ActiveCfg = Release|x86 + {0A991D5F-BFEE-4D2F-9AAD-6AD06470A5DF}.Release|x64.ActiveCfg = Release|x64 + {0A991D5F-BFEE-4D2F-9AAD-6AD06470A5DF}.Release|x64.Build.0 = Release|x64 + {0A991D5F-BFEE-4D2F-9AAD-6AD06470A5DF}.Release|x86.ActiveCfg = Release|x86 + {0A991D5F-BFEE-4D2F-9AAD-6AD06470A5DF}.Release|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution - {B04E3F7C-BE25-4384-8D6F-7E450DBDBC70} = {325B6B80-4029-45FA-9429-004C1214B3EB} - {DAFC85B3-27AF-43EA-8F83-207E303BE7EF} = {325B6B80-4029-45FA-9429-004C1214B3EB} - {B2CCF56D-27A9-427A-BA82-6CA11774DA90} = {325B6B80-4029-45FA-9429-004C1214B3EB} + {C6D580C5-7037-4733-B933-916FF400AFE2} = {6D41796B-9904-40B8-BBCB-40B2D1BAE44B} + {FFA9A78B-F53F-43EE-AF87-24A80F4C330A} = {6D41796B-9904-40B8-BBCB-40B2D1BAE44B} + {0A991D5F-BFEE-4D2F-9AAD-6AD06470A5DF} = {6D41796B-9904-40B8-BBCB-40B2D1BAE44B} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {5AE8C9D7-2613-4E1A-A4F2-579BAC28D0A2} diff --git a/cswinrt/Directory.Build.targets b/cswinrt/Directory.Build.targets new file mode 100644 index 000000000..bdfcec900 --- /dev/null +++ b/cswinrt/Directory.Build.targets @@ -0,0 +1,5 @@ + + + + + diff --git a/cswinrt/cswinrt.vcxproj b/cswinrt/cswinrt.vcxproj index 39e0cb77c..261e48aaa 100644 --- a/cswinrt/cswinrt.vcxproj +++ b/cswinrt/cswinrt.vcxproj @@ -1,6 +1,6 @@  - + 15.0 {6acfd2b2-e8aa-4cd4-aad8-213ce8bb2637} @@ -66,6 +66,7 @@ + @@ -110,8 +111,8 @@ - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105.The missing file is {0}. - + \ No newline at end of file diff --git a/cswinrt/cswinrt.vcxproj.filters b/cswinrt/cswinrt.vcxproj.filters index ffc34412a..b1077bc15 100644 --- a/cswinrt/cswinrt.vcxproj.filters +++ b/cswinrt/cswinrt.vcxproj.filters @@ -169,5 +169,6 @@ strings\additions\Microsoft.UI.Xaml + \ No newline at end of file diff --git a/nuget.config b/nuget.config index a1cf6a7d7..9059b791a 100644 --- a/nuget.config +++ b/nuget.config @@ -1,5 +1,8 @@  + + + diff --git a/nuget/Microsoft.Windows.CsWinRT.props b/nuget/Microsoft.Windows.CsWinRT.props index 34b4e8005..e58f26d52 100644 --- a/nuget/Microsoft.Windows.CsWinRT.props +++ b/nuget/Microsoft.Windows.CsWinRT.props @@ -5,8 +5,9 @@ Copyright (C) Microsoft Corporation. All rights reserved. --> - - $([MSBuild]::NormalizeDirectory('$(MSBuildThisFileDirectory)', '..')) - + + $([MSBuild]::NormalizeDirectory('$(MSBuildThisFileDirectory)', '..')) + $(CsWinRTPath)cswinrt.exe + diff --git a/nuget/Microsoft.Windows.CsWinRT.targets b/nuget/Microsoft.Windows.CsWinRT.targets index 3fdf3bff0..9f45a4059 100644 --- a/nuget/Microsoft.Windows.CsWinRT.targets +++ b/nuget/Microsoft.Windows.CsWinRT.targets @@ -1,10 +1,14 @@ - + + + $(ResolveAssemblyReferencesDependsOn);RemoveWindowsReference - - From d392a0d04463f93b0f55082a4d9a4ea7762de413 Mon Sep 17 00:00:00 2001 From: Scott Jones Date: Fri, 12 Jun 2020 14:55:02 -0700 Subject: [PATCH 11/38] Update packages.config fix build break --- cswinrt/packages.config | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cswinrt/packages.config b/cswinrt/packages.config index 4418c5803..7721e4b89 100644 --- a/cswinrt/packages.config +++ b/cswinrt/packages.config @@ -1,4 +1,4 @@  - - \ No newline at end of file + + From 37ae7f1a17e60c8d83a71bf01d4c9db749113432 Mon Sep 17 00:00:00 2001 From: Scott Jones Date: Mon, 15 Jun 2020 09:56:50 -0700 Subject: [PATCH 12/38] Multi-targeting DispatchToInnerBuilds doesn't play nicely with ResolveAssemblyReferences (see also https://github.com/Microsoft/msbuild/issues/2781). Since cswinrt.exe is moving to forked code gen based on TFM, will just adopt that now, and resolve build breaks. (#315) --- Projections/Test/Test.csproj | 10 +++++----- Projections/WinUI/WinUI.csproj | 10 +++++----- Projections/Windows/Windows.csproj | 10 +++++----- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Projections/Test/Test.csproj b/Projections/Test/Test.csproj index 224c1001f..08ab75297 100644 --- a/Projections/Test/Test.csproj +++ b/Projections/Test/Test.csproj @@ -29,7 +29,7 @@ - + $([MSBuild]::NormalizeDirectory('$(NuGetPackageRoot)', 'microsoft.winui', '$(MicrosoftWinUIVersion)')) @@ -52,26 +52,26 @@ -verbose -in 10.0.18362.0 -in @(ReferenceWinMDs->'"%(FullPath)"', ' ') --out "$(ProjectDir)Generated Files" +-out "$(IntermediateOutputPath)Generated Files" -exclude Windows -exclude Microsoft -include TestComponent -include TestComponentCSharp - + - + $([MSBuild]::NormalizeDirectory('$(NuGetPackageRoot)', 'microsoft.winui', '$(MicrosoftWinUIVersion)')) - + diff --git a/Projections/WinUI/WinUI.csproj b/Projections/WinUI/WinUI.csproj index 03340e93e..d8ba37634 100644 --- a/Projections/WinUI/WinUI.csproj +++ b/Projections/WinUI/WinUI.csproj @@ -28,7 +28,7 @@ - + $([MSBuild]::NormalizeDirectory('$(NuGetPackageRoot)', 'microsoft.winui', '$(MicrosoftWinUIVersion)')) @@ -48,7 +48,7 @@ -verbose -in 10.0.18362.0 -in @(ReferenceWinMDs->'"%(FullPath)"', ' ') --out "$(ProjectDir)Generated Files" +-out "$(IntermediateOutputPath)Generated Files" -exclude Windows -include Microsoft # The current WinUI nuget incorrectly references several Windows.* types that should be @@ -68,15 +68,15 @@ -include Windows.UI.Xaml.Media.Animation.ConditionallyIndependentlyAnimatableAttribute - + - + - + diff --git a/Projections/Windows/Windows.csproj b/Projections/Windows/Windows.csproj index f17350fda..c2c5616fa 100644 --- a/Projections/Windows/Windows.csproj +++ b/Projections/Windows/Windows.csproj @@ -30,7 +30,7 @@ - + high $(IntermediateOutputPath)cswinrt_windows.rsp @@ -40,7 +40,7 @@ -verbose -in 10.0.18362.0 --out "$(ProjectDir)Generated Files" +-out "$(IntermediateOutputPath)Generated Files" -include Windows # Exclude causality types colliding with those in System.Private.CoreLib.dll -exclude Windows.Foundation.Diagnostics @@ -61,15 +61,15 @@ -include Windows.UI.Xaml.Media.Animation.ConditionallyIndependentlyAnimatableAttribute - + - + - + From ee6ef1643b47aa541b28a5e9201bc8f3c0827bf2 Mon Sep 17 00:00:00 2001 From: Scott Jones Date: Tue, 16 Jun 2020 07:28:45 -0700 Subject: [PATCH 13/38] Project Reunion blurb (#319) * add pitch for project reunion * typo * tighten --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index b6583df55..da44e9c9d 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,8 @@ WinRT APIs are defined in `*.winmd` format, and C#/WinRT includes tooling that g C#/WinRT is part of the [xlang](https://github.com/microsoft/xlang) family of projects that help developers create APIs that can run on multiple platforms and be used with a variety of languages. The mission of C#/WinRT is not to support cross-platform execution directly, but to support the cross-platform goals of .NET Core. +C#/WinRT is also part of [Project Reunion](https://github.com/microsoft/ProjectReunion) - a set of libraries, frameworks, components, and tools that you can use in your apps to access powerful platform functionality across many versions of Windows. Project Reunion combines Win32 native app capabilities with modern API usage techniques, so your apps light up everywhere your users are. Project Reunion also includes [WinUI](https://docs.microsoft.com/en-us/windows/apps/winui/), [WebView2](https://docs.microsoft.com/en-us/microsoft-edge/webview2/), [MSIX](https://docs.microsoft.com/en-us/windows/msix/overview), [C++/WinRT](https://github.com/microsoft/CppWinRT/), and [Rust/WinRT](https://github.com/microsoft/winrt-rs). + ### Motivation .NET Core is the focus for the .NET platform. It is an open-source, cross-platform runtime that can be used to build device, cloud, and IoT applications. Previous versions of .NET Framework and .NET Core have built-in knowledge of WinRT which is a Windows-specific technology. By lifting this projection support out of the compiler and runtime, we are supporting efforts to make .NET more efficient for its .NET 5 release. More information about .NET can be found at https://docs.microsoft.com/en-us/dotnet/core/ From 9a46c367fc09f92a27a6b75eb9d7d556d7b20648 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Tue, 16 Jun 2020 23:04:38 -0700 Subject: [PATCH 14/38] Update README.md --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index da44e9c9d..b616c2e3c 100644 --- a/README.md +++ b/README.md @@ -128,3 +128,9 @@ provided by the bot. You will only need to do this once across all repos using o This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. + +# Project Reunion + +Project Reunion is a set of libraries, frameworks, components, and tools that you can use to access powerful Windows platform functionality from all kinds of apps on many versions of Windows. Project Reunion combines the power of Win32 native applications alongside modern APIs, so your apps light up everywhere your users are. + +Other Project Reunion components include [WinUI](https://github.com/microsoft/microsoft-ui-xaml), WebView2, MSIX, [C++/WinRT](https://github.com/microsoft/cppwinrt), and [Rust/WinRT](https://github.com/microsoft/winrt-rs). If you'd like to learn more, contribute to Project Reunion, or have app model questions, visit [Project Reunion on GitHub](https://github.com/microsoft/ProjectReunion). From 7d5a654dbe3d5e530855f243a72fe83959e4917a Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Tue, 16 Jun 2020 23:05:21 -0700 Subject: [PATCH 15/38] Update README.md --- README.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/README.md b/README.md index b616c2e3c..da44e9c9d 100644 --- a/README.md +++ b/README.md @@ -128,9 +128,3 @@ provided by the bot. You will only need to do this once across all repos using o This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. - -# Project Reunion - -Project Reunion is a set of libraries, frameworks, components, and tools that you can use to access powerful Windows platform functionality from all kinds of apps on many versions of Windows. Project Reunion combines the power of Win32 native applications alongside modern APIs, so your apps light up everywhere your users are. - -Other Project Reunion components include [WinUI](https://github.com/microsoft/microsoft-ui-xaml), WebView2, MSIX, [C++/WinRT](https://github.com/microsoft/cppwinrt), and [Rust/WinRT](https://github.com/microsoft/winrt-rs). If you'd like to learn more, contribute to Project Reunion, or have app model questions, visit [Project Reunion on GitHub](https://github.com/microsoft/ProjectReunion). From e6126c1c074d891d2bfd4175a6daf2e78bbd303b Mon Sep 17 00:00:00 2001 From: Scott Jones Date: Wed, 17 Jun 2020 14:00:20 -0700 Subject: [PATCH 16/38] Address ComWrappers breaking change and add prerelease policy (#321) * Move to .net 5 sdk preview 6 to address breaking change, add prerelease policy * back off to preview 5 due to unit test failure: Failed to create CoreCLR, HRESULT: 0x80070057 * Revert "back off to preview 5 due to unit test failure: Failed to create CoreCLR, HRESULT: 0x80070057" This reverts commit dae3aed5245a6f44591e0b2f4d5fa108b35a476a. * restored preview 6 reference, with workaround for unit test crash * conditional include of prerelease targets file --- .gitignore | 1 + Projections/Test/Test.csproj | 3 +++ README.md | 26 ++++++++++++++++------- UnitTest/UnitTest.csproj | 5 +++++ WinRT.Runtime/ComWrappersSupport.net5.cs | 14 ++++++------ build.cmd | 27 ++++++++++++++++++------ nuget/Microsoft.Windows.CsWinRT.nuspec | 1 + nuget/Microsoft.Windows.CsWinRT.targets | 2 ++ 8 files changed, 58 insertions(+), 21 deletions(-) diff --git a/.gitignore b/.gitignore index d57e2d16d..74507b4d9 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,4 @@ _build/ global.json .nuget .nupkg +nuget/Microsoft.Windows.CsWinRT.Prerelease.targets diff --git a/Projections/Test/Test.csproj b/Projections/Test/Test.csproj index 08ab75297..1838e15fd 100644 --- a/Projections/Test/Test.csproj +++ b/Projections/Test/Test.csproj @@ -75,6 +75,9 @@ + + + diff --git a/README.md b/README.md index da44e9c9d..dc5224921 100644 --- a/README.md +++ b/README.md @@ -70,9 +70,15 @@ The following msbuild project fragment demonstrates a simple invocation of cswin ``` # Building -C#/WinRT currently depends on a private prerelease WinUI 3 NuGet, which should be made public around //build. C#/WinRT also uses the .NET 5 preview SDK. This is public, but there are some related configuration steps. The build.cmd script takes care of all this, and is the simplest way to get started building C#/WinRT. -The build script is intended to be executed from a Visual Studio Developer command prompt. It installs prerequisites such as nuget and the .NET 5 SDK, configures the environment to use .NET 5 (creating a global.json if necessary), builds the compiler, and builds and executes the unit tests. +C#/WinRT currently requires the following packages to build: +- Visual Studio 16.6 (more specifically, MSBuild 16.6.0 for "net5.0" TFM support) +- .NET 5 SDK 5.0.100-preview.6.20314.3 +- WinUI 3 3.0.0-preview1.200515.3 + +**Note:** As prereleases may make breaking changes before final release, any other combinations above may work but are not supported and will generate a build warning. + +The build.cmd script takes care of all related configuration steps and is the simplest way to get started building C#/WinRT. The build script is intended to be executed from a Visual Studio Developer command prompt. It installs prerequisites such as nuget and the .NET 5 SDK, configures the environment to use .NET 5 (creating a global.json if necessary), builds the compiler, and builds and executes the unit tests. After a successful command-line build, the cswinrt.sln can be launched from the same command prompt, to inherit the necessary environment. By default, the UnitTest and WinUIProjection projections are only generated for Release configurations, where cswinrt.exe can execute in seconds. For Debug configurations, projection generation must be turned on with the project property GenerateTestProjection. @@ -99,10 +105,6 @@ The **/WinRT.Runtime** folder contains the WinRT.Runtime project for building th The **/nuget** folder contains source files for producing a C#/WinRT NuGet package, which is regularly built, signed, and published to nuget.org by Microsoft. The C#/WinRT NuGet package contains the cswinrt.exe compiler, and both versions of the winrt.runtime.dll. -## /UnitTest - -The **/UnitTest** folder contains unit tests for validating the projection generated for the TestComponentCSharp project (below), for the TestWinRT\TestComponent project (below), and for foundational parts of the Windows SDK. All pull requests should ensure that this project executes without errors. - ## /TestWinRT C#/WinRT makes use of the standalone [TestWinRT](https://github.com/microsoft/TestWinRT/) repository for general language projection test coverage. This repo should be cloned into the root of the C#/WinRT repo, via **get_testwinrt.cmd**, so that the cswinrt.sln can resolve its reference to TestComponent.vcxproj. The resulting TestComponent.dll and TestComponent.winmd files are consumed by the UnitTest project above. @@ -111,9 +113,17 @@ C#/WinRT makes use of the standalone [TestWinRT](https://github.com/microsoft/Te The **/TestComponentCSharp** folder contains an implementation of a WinRT test component, defined in class.idl and used by the UnitTest project. To complement the general TestComponent above, the TestComponentCSharp tests scenarios specific to the C#/WinRT language projection. -## /WinUI +## /Projections + +The **/Projections** folder contains several projects for generating and building projections from the Windows SDK, WinUI, and Test metadata (produced by the TestWinRT and TestComponentCSharp projects). + +## /UnitTest + +The **/UnitTest** folder contains unit tests for validating the Windows SDK, WinUI, and Test projections generated above. All pull requests should ensure that this project executes without errors. + +## /WinUIDesktopSample -The **/WinUI** folder contains several related projects for generating and building a complete Windows SDK and WinUI projection, along with an end-to-end sample app that uses the generated projection. The projection is built out of **/winuiprojection**, which is consumed by both the sample app under **/winuidesktopsample**, and a simple test project under **/winuitest**. +The **/WinUIDesktopSample** contains an end-to-end sample app that uses the Windows SDK and WinUI projections generated above. # Contributing diff --git a/UnitTest/UnitTest.csproj b/UnitTest/UnitTest.csproj index 7fb23a253..524c30285 100644 --- a/UnitTest/UnitTest.csproj +++ b/UnitTest/UnitTest.csproj @@ -58,6 +58,11 @@ + + + + + diff --git a/WinRT.Runtime/ComWrappersSupport.net5.cs b/WinRT.Runtime/ComWrappersSupport.net5.cs index 3f37c64e5..cf78f72b3 100644 --- a/WinRT.Runtime/ComWrappersSupport.net5.cs +++ b/WinRT.Runtime/ComWrappersSupport.net5.cs @@ -21,15 +21,17 @@ private static ComWrappers ComWrappers { if (_comWrappers is null) { - _comWrappers = new DefaultComWrappers(); - _comWrappers.RegisterAsGlobalInstance(); + _comWrappers = new DefaultComWrappers(); + ComWrappers.RegisterForTrackerSupport(_comWrappers); + ComWrappers.RegisterForMarshalling(_comWrappers); } return _comWrappers; } set { - _comWrappers = value; - _comWrappers.RegisterAsGlobalInstance(); + _comWrappers = value; + ComWrappers.RegisterForTrackerSupport(_comWrappers); + ComWrappers.RegisterForMarshalling(_comWrappers); } } @@ -117,8 +119,8 @@ static DefaultComWrappers() AddRef = Marshal.GetDelegateForFunctionPointer(addRef), Release = Marshal.GetDelegateForFunctionPointer(release), }; - } - + } + protected override unsafe ComInterfaceEntry* ComputeVtables(object obj, CreateComInterfaceFlags flags, out int count) { if (IsRuntimeImplementedRCW(obj)) diff --git a/build.cmd b/build.cmd index b4395cb57..5ea6fd91b 100644 --- a/build.cmd +++ b/build.cmd @@ -1,6 +1,7 @@ @echo off -set Net5SdkVersion=5.0.100-preview.4.20227.10 +set CsWinRTNet5SdkVersion=5.0.100-preview.6.20314.3 +set CsWinRTMSBuildVersion=16.6.0 :dotnet rem Install required .NET 5 SDK version and add to environment @@ -10,21 +11,21 @@ set path=%DOTNET_ROOT%;%path% powershell -NoProfile -ExecutionPolicy unrestricted -Command ^ [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; ^ &([scriptblock]::Create((Invoke-WebRequest -UseBasicParsing 'https://dot.net/v1/dotnet-install.ps1'))) ^ --Version '%Net5SdkVersion%' -InstallDir "%DOTNET_ROOT%" -Architecture 'x64' ^ +-Version '%CsWinRTNet5SdkVersion%' -InstallDir "%DOTNET_ROOT%" -Architecture 'x64' ^ -AzureFeed 'https://dotnetcli.blob.core.windows.net/dotnet' " powershell -NoProfile -ExecutionPolicy unrestricted -Command ^ [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; ^ &([scriptblock]::Create((Invoke-WebRequest -UseBasicParsing 'https://dot.net/v1/dotnet-install.ps1'))) ^ --Version '%Net5SdkVersion%' -InstallDir "%DOTNET_ROOT(86)%" -Architecture 'x86' ^ +-Version '%CsWinRTNet5SdkVersion%' -InstallDir "%DOTNET_ROOT(86)%" -Architecture 'x86' ^ -AzureFeed 'https://dotnetcli.blob.core.windows.net/dotnet' " :globaljson rem User expected to provide global.json with allowPrerelease=true if not exist %~dp0global.json ( - echo global.json not found, creating one to allowPrelease for unit test project builds + echo Creating default global.json to allowPrelease for unit test project builds echo { > global.json echo "sdk": { >> global.json - echo "version": "%Net5SdkVersion%", >> global.json + echo "version": "%CsWinRTNet5SdkVersion%", >> global.json echo "rollForward": "patch", >> global.json echo "allowPrerelease": true >> global.json echo } >> global.json @@ -39,7 +40,7 @@ set cswinrt_platform=%1 set cswinrt_configuration=%2 set cswinrt_version_number=%3 set cswinrt_version_string=%4 -set cswinrt_label=%5 +set "%5"!="" set cswinrt_label=%5 if "%cswinrt_platform%"=="" set cswinrt_platform=x64 @@ -67,6 +68,18 @@ if "%cswinrt_configuration%"=="" ( if "%cswinrt_version_number%"=="" set cswinrt_version_number=0.0.0.0 if "%cswinrt_version_string%"=="" set cswinrt_version_string=0.0.0-private.0 +rem Generate prerelease targets file to exercise build warnings +set prerelease_targets=nuget\Microsoft.Windows.CsWinRT.Prerelease.targets +if not exist %prerelease_targets% ( + echo Creating default %prerelease_targets% + echo ^ > %prerelease_targets% + echo ^> %prerelease_targets% + echo ^Condition="'$(Net5SdkVersion)' ^!= '%CsWinRTNet5SdkVersion%' or '$(MSBuildVersion)' ^!= '%CsWinRTMSBuildVersion%'"^> >> %prerelease_targets% + echo ^ >> %prerelease_targets% + echo ^ >> %prerelease_targets% + echo ^ >> %prerelease_targets% +) + if not "%cswinrt_label%"=="" goto %cswinrt_label% :restore @@ -78,7 +91,7 @@ if not exist .nuget\nuget.exe powershell -Command "Invoke-WebRequest https://dis :build call get_testwinrt.cmd echo Building cswinrt for %cswinrt_platform% %cswinrt_configuration% -msbuild cswinrt.sln /p:platform=%cswinrt_platform%;configuration=%cswinrt_configuration%;VersionNumber=%cswinrt_version_number%;VersionString=%cswinrt_version_string%;GenerateTestProjection=true +msbuild cswinrt.sln %cswinrt_build_params% /p:platform=%cswinrt_platform%;configuration=%cswinrt_configuration%;VersionNumber=%cswinrt_version_number%;VersionString=%cswinrt_version_string%;GenerateTestProjection=true :test rem Build/Run xUnit tests, generating xml output report for Azure Devops reporting, via XunitXml.TestLogger NuGet diff --git a/nuget/Microsoft.Windows.CsWinRT.nuspec b/nuget/Microsoft.Windows.CsWinRT.nuspec index 6e7ba1617..e57ffa015 100644 --- a/nuget/Microsoft.Windows.CsWinRT.nuspec +++ b/nuget/Microsoft.Windows.CsWinRT.nuspec @@ -23,6 +23,7 @@ + diff --git a/nuget/Microsoft.Windows.CsWinRT.targets b/nuget/Microsoft.Windows.CsWinRT.targets index 9f45a4059..c446b8c2d 100644 --- a/nuget/Microsoft.Windows.CsWinRT.targets +++ b/nuget/Microsoft.Windows.CsWinRT.targets @@ -15,4 +15,6 @@ Copyright (C) Microsoft Corporation. All rights reserved. + + From cd016440b5551ef0a3b3cb01e7248b08637e599a Mon Sep 17 00:00:00 2001 From: Scott Jones Date: Thu, 18 Jun 2020 10:47:12 -0700 Subject: [PATCH 17/38] update testwinrt nuget and use latest public winui nuget (#322) --- Directory.Build.props | 2 +- get_testwinrt.cmd | 2 +- nuget.config | 19 ------------------- 3 files changed, 2 insertions(+), 21 deletions(-) delete mode 100644 nuget.config diff --git a/Directory.Build.props b/Directory.Build.props index 7b3b40496..d2ac61ff8 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -6,7 +6,7 @@ 15.0 15.0 high - 3.0.0-preview1.200419.0-CI + 3.0.0-preview1.200515.3 netcoreapp5.0 diff --git a/get_testwinrt.cmd b/get_testwinrt.cmd index f67c4ed1c..35214e130 100644 --- a/get_testwinrt.cmd +++ b/get_testwinrt.cmd @@ -12,7 +12,7 @@ git checkout -f master if ErrorLevel 1 popd & exit /b !ErrorLevel! git fetch -f if ErrorLevel 1 popd & exit /b !ErrorLevel! -git reset -q --hard b9b413dba2c1058b87400ea1b080f3a1f3b7cbea +git reset -q --hard d5fca25d5e2bb9861b7000f011b50000f2fd8a29 if ErrorLevel 1 popd & exit /b !ErrorLevel! echo Restoring Nuget ..\.nuget\nuget.exe restore diff --git a/nuget.config b/nuget.config deleted file mode 100644 index 9059b791a..000000000 --- a/nuget.config +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - From 27e66899d658601df40edfeeabdbf3162e8478a4 Mon Sep 17 00:00:00 2001 From: Scott Jones Date: Thu, 18 Jun 2020 11:34:39 -0700 Subject: [PATCH 18/38] updated to public winui nuget (#323) --- TestComponentCSharp/TestComponentCSharp.vcxproj | 8 ++++---- TestComponentCSharp/packages.config | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/TestComponentCSharp/TestComponentCSharp.vcxproj b/TestComponentCSharp/TestComponentCSharp.vcxproj index 3f7998ec1..b2cb1b4e4 100644 --- a/TestComponentCSharp/TestComponentCSharp.vcxproj +++ b/TestComponentCSharp/TestComponentCSharp.vcxproj @@ -1,6 +1,6 @@ - + high @@ -94,7 +94,7 @@ - + @@ -102,7 +102,7 @@ - - + + \ No newline at end of file diff --git a/TestComponentCSharp/packages.config b/TestComponentCSharp/packages.config index 6dc37423c..72ab06b94 100644 --- a/TestComponentCSharp/packages.config +++ b/TestComponentCSharp/packages.config @@ -1,5 +1,5 @@  - + \ No newline at end of file From 94e6db00a37a7d162ee1973fcef97dae32afa8bb Mon Sep 17 00:00:00 2001 From: Scott Jones Date: Thu, 18 Jun 2020 14:32:45 -0700 Subject: [PATCH 19/38] backing off to preview 5 due to WinUI concerns (#324) --- README.md | 2 +- build.cmd | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index dc5224921..aab758b26 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,7 @@ The following msbuild project fragment demonstrates a simple invocation of cswin C#/WinRT currently requires the following packages to build: - Visual Studio 16.6 (more specifically, MSBuild 16.6.0 for "net5.0" TFM support) -- .NET 5 SDK 5.0.100-preview.6.20314.3 +- .NET 5 SDK 5.0.100-preview.5.20279.10 - WinUI 3 3.0.0-preview1.200515.3 **Note:** As prereleases may make breaking changes before final release, any other combinations above may work but are not supported and will generate a build warning. diff --git a/build.cmd b/build.cmd index 5ea6fd91b..c9d76dcae 100644 --- a/build.cmd +++ b/build.cmd @@ -1,6 +1,6 @@ @echo off -set CsWinRTNet5SdkVersion=5.0.100-preview.6.20314.3 +set CsWinRTNet5SdkVersion=5.0.100-preview.5.20279.10 set CsWinRTMSBuildVersion=16.6.0 :dotnet From 281e536d39952424f1b6cee5660dedbf8a249a90 Mon Sep 17 00:00:00 2001 From: Scott Jones Date: Tue, 23 Jun 2020 06:54:11 -0700 Subject: [PATCH 20/38] add ability to share debug/release generated files (#325) * add ability to share debug/release generated files (restore original dev workflow) * fixed issue with prerelease verify target and clarified debug/release projection builds --- Directory.Build.targets | 4 ++++ Projections/Test/Test.csproj | 8 ++++---- Projections/WinUI/WinUI.csproj | 8 ++++---- Projections/Windows/Windows.csproj | 8 ++++---- README.md | 4 +++- build.cmd | 2 +- nuget/Microsoft.Windows.CsWinRT.targets | 4 +++- 7 files changed, 23 insertions(+), 15 deletions(-) diff --git a/Directory.Build.targets b/Directory.Build.targets index 4d90f8d5b..d10196724 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -1,5 +1,9 @@ + + $([MSBuild]::NormalizeDirectory('$(MSBuildProjectDirectory)', 'Generated Files')) + + diff --git a/Projections/Test/Test.csproj b/Projections/Test/Test.csproj index 1838e15fd..414a8bfda 100644 --- a/Projections/Test/Test.csproj +++ b/Projections/Test/Test.csproj @@ -44,7 +44,7 @@ high - $(IntermediateOutputPath)cswinrt_test.rsp + $(GeneratedFilesDir)cswinrt_test.rsp $(CsWinRTExe) %40"$(CsWinRTResponseFile)" @@ -52,14 +52,14 @@ -verbose -in 10.0.18362.0 -in @(ReferenceWinMDs->'"%(FullPath)"', ' ') --out "$(IntermediateOutputPath)Generated Files" +-out "$(GeneratedFilesDir.TrimEnd('\'))" -exclude Windows -exclude Microsoft -include TestComponent -include TestComponentCSharp - + @@ -71,7 +71,7 @@ $([MSBuild]::NormalizeDirectory('$(NuGetPackageRoot)', 'microsoft.winui', '$(MicrosoftWinUIVersion)')) - + diff --git a/Projections/WinUI/WinUI.csproj b/Projections/WinUI/WinUI.csproj index d8ba37634..7d072ba81 100644 --- a/Projections/WinUI/WinUI.csproj +++ b/Projections/WinUI/WinUI.csproj @@ -40,7 +40,7 @@ high - $(IntermediateOutputPath)cswinrt_winui.rsp + $(GeneratedFilesDir)cswinrt_winui.rsp $(CsWinrtExe) %40"$(CsWinRTResponseFile)" @@ -48,7 +48,7 @@ -verbose -in 10.0.18362.0 -in @(ReferenceWinMDs->'"%(FullPath)"', ' ') --out "$(IntermediateOutputPath)Generated Files" +-out "$(GeneratedFilesDir.TrimEnd('\'))" -exclude Windows -include Microsoft # The current WinUI nuget incorrectly references several Windows.* types that should be @@ -68,7 +68,7 @@ -include Windows.UI.Xaml.Media.Animation.ConditionallyIndependentlyAnimatableAttribute - + @@ -76,7 +76,7 @@ - + diff --git a/Projections/Windows/Windows.csproj b/Projections/Windows/Windows.csproj index c2c5616fa..a99feca2e 100644 --- a/Projections/Windows/Windows.csproj +++ b/Projections/Windows/Windows.csproj @@ -33,14 +33,14 @@ high - $(IntermediateOutputPath)cswinrt_windows.rsp + $(GeneratedFilesDir)cswinrt_windows.rsp $(CsWinrtExe) %40"$(CsWinRTResponseFile)" -verbose -in 10.0.18362.0 --out "$(IntermediateOutputPath)Generated Files" +-out "$(GeneratedFilesDir.TrimEnd('\'))" -include Windows # Exclude causality types colliding with those in System.Private.CoreLib.dll -exclude Windows.Foundation.Diagnostics @@ -61,7 +61,7 @@ -include Windows.UI.Xaml.Media.Animation.ConditionallyIndependentlyAnimatableAttribute - + @@ -69,7 +69,7 @@ - + diff --git a/README.md b/README.md index aab758b26..a7a395870 100644 --- a/README.md +++ b/README.md @@ -80,7 +80,9 @@ C#/WinRT currently requires the following packages to build: The build.cmd script takes care of all related configuration steps and is the simplest way to get started building C#/WinRT. The build script is intended to be executed from a Visual Studio Developer command prompt. It installs prerequisites such as nuget and the .NET 5 SDK, configures the environment to use .NET 5 (creating a global.json if necessary), builds the compiler, and builds and executes the unit tests. -After a successful command-line build, the cswinrt.sln can be launched from the same command prompt, to inherit the necessary environment. By default, the UnitTest and WinUIProjection projections are only generated for Release configurations, where cswinrt.exe can execute in seconds. For Debug configurations, projection generation must be turned on with the project property GenerateTestProjection. +After a successful command-line build, the cswinrt.sln can be launched from the same command prompt, to inherit the necessary environment. + +**Note:** By default, projection projects only generate source files for Release configurations, where cswinrt.exe can execute in seconds. To generate projection sources for Debug configurations, set the project property GenerateTestProjection to 'true'. In either case, existing projection sources under the "Generated Files" folder will still be compiled into the projection assembly. This configuration permits a faster inner loop in Visual Studio. # Structure The C#/WinRT compiler and unit tests are all contained within the Visual Studio 2019 solution file, \cswinrt\cswinrt.sln. diff --git a/build.cmd b/build.cmd index c9d76dcae..3edae3b61 100644 --- a/build.cmd +++ b/build.cmd @@ -72,7 +72,7 @@ rem Generate prerelease targets file to exercise build warnings set prerelease_targets=nuget\Microsoft.Windows.CsWinRT.Prerelease.targets if not exist %prerelease_targets% ( echo Creating default %prerelease_targets% - echo ^ > %prerelease_targets% + echo ^ > %prerelease_targets% echo ^> %prerelease_targets% echo ^Condition="'$(Net5SdkVersion)' ^!= '%CsWinRTNet5SdkVersion%' or '$(MSBuildVersion)' ^!= '%CsWinRTMSBuildVersion%'"^> >> %prerelease_targets% echo ^ >> %prerelease_targets% diff --git a/nuget/Microsoft.Windows.CsWinRT.targets b/nuget/Microsoft.Windows.CsWinRT.targets index c446b8c2d..44a588ab5 100644 --- a/nuget/Microsoft.Windows.CsWinRT.targets +++ b/nuget/Microsoft.Windows.CsWinRT.targets @@ -5,10 +5,12 @@ Copyright (C) Microsoft Corporation. All rights reserved. --> - + $([MSBuild]::NormalizeDirectory('$(MSBuildProjectDirectory)', '$(IntermediateOutputPath)', 'Generated Files')) $(ResolveAssemblyReferencesDependsOn);RemoveWindowsReference + + From 1ab913d26ff01fed64e66006abc7f2cc38fa1ca1 Mon Sep 17 00:00:00 2001 From: Scott Jones Date: Tue, 23 Jun 2020 14:41:41 -0700 Subject: [PATCH 21/38] do not register for ComWrappers marshaling support, but only reference tracking (#327) --- Directory.Build.props | 2 +- Directory.Build.targets | 6 +++--- WinRT.Runtime/ComWrappersSupport.net5.cs | 2 -- build.cmd | 7 ++----- 4 files changed, 6 insertions(+), 11 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index d2ac61ff8..9ab32438e 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -84,6 +84,6 @@ - + diff --git a/Directory.Build.targets b/Directory.Build.targets index d10196724..049c13e33 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -1,9 +1,9 @@ - + $([MSBuild]::NormalizeDirectory('$(MSBuildProjectDirectory)', 'Generated Files')) - - + + diff --git a/WinRT.Runtime/ComWrappersSupport.net5.cs b/WinRT.Runtime/ComWrappersSupport.net5.cs index cf78f72b3..95d64d644 100644 --- a/WinRT.Runtime/ComWrappersSupport.net5.cs +++ b/WinRT.Runtime/ComWrappersSupport.net5.cs @@ -23,7 +23,6 @@ private static ComWrappers ComWrappers { _comWrappers = new DefaultComWrappers(); ComWrappers.RegisterForTrackerSupport(_comWrappers); - ComWrappers.RegisterForMarshalling(_comWrappers); } return _comWrappers; } @@ -31,7 +30,6 @@ private static ComWrappers ComWrappers { _comWrappers = value; ComWrappers.RegisterForTrackerSupport(_comWrappers); - ComWrappers.RegisterForMarshalling(_comWrappers); } } diff --git a/build.cmd b/build.cmd index 3edae3b61..ff147b490 100644 --- a/build.cmd +++ b/build.cmd @@ -1,7 +1,6 @@ @echo off set CsWinRTNet5SdkVersion=5.0.100-preview.5.20279.10 -set CsWinRTMSBuildVersion=16.6.0 :dotnet rem Install required .NET 5 SDK version and add to environment @@ -26,7 +25,6 @@ if not exist %~dp0global.json ( echo { > global.json echo "sdk": { >> global.json echo "version": "%CsWinRTNet5SdkVersion%", >> global.json - echo "rollForward": "patch", >> global.json echo "allowPrerelease": true >> global.json echo } >> global.json echo } >> global.json @@ -74,8 +72,8 @@ if not exist %prerelease_targets% ( echo Creating default %prerelease_targets% echo ^ > %prerelease_targets% echo ^> %prerelease_targets% - echo ^Condition="'$(Net5SdkVersion)' ^!= '%CsWinRTNet5SdkVersion%' or '$(MSBuildVersion)' ^!= '%CsWinRTMSBuildVersion%'"^> >> %prerelease_targets% - echo ^ >> %prerelease_targets% + echo Condition="'$(NetCoreSdkVersion)' ^!= '%CsWinRTNet5SdkVersion%' and '$(Net5SdkVersion)' ^!= '%CsWinRTNet5SdkVersion%'"^> >> %prerelease_targets% + echo ^ >> %prerelease_targets% echo ^ >> %prerelease_targets% echo ^ >> %prerelease_targets% ) @@ -117,7 +115,6 @@ if ErrorLevel 1 ( exit /b !ErrorLevel! ) -rem todo remove all this :package set cswinrt_bin_dir=%~dp0_build\%cswinrt_platform%\%cswinrt_configuration%\cswinrt\bin\ set cswinrt_exe=%cswinrt_bin_dir%cswinrt.exe From e15892a2964669f7c3a629208ab00515636b9bf8 Mon Sep 17 00:00:00 2001 From: Scott Jones Date: Thu, 25 Jun 2020 13:44:04 -0700 Subject: [PATCH 22/38] Replace INotify*-related IIDs with MUX versions, fix NRE crash on uninitialized CWT (#331) * WUX -> MUX INotify* GUIDs changed * fixed INPC issues --- .../Projections/INotifyCollectionChanged.cs | 6 +++--- .../Projections/INotifyPropertyChanged.cs | 9 +++++---- .../NotifyCollectionChangedEventArgs.cs | 14 +++++++------- .../NotifyCollectionChangedEventHandler.cs | 4 ++-- .../Projections/PropertyChangedEventArgs.cs | 10 +++++----- .../Projections/PropertyChangedEventHandler.cs | 2 +- 6 files changed, 23 insertions(+), 22 deletions(-) diff --git a/WinRT.Runtime/Projections/INotifyCollectionChanged.cs b/WinRT.Runtime/Projections/INotifyCollectionChanged.cs index 9e92de782..4b4e799b1 100644 --- a/WinRT.Runtime/Projections/INotifyCollectionChanged.cs +++ b/WinRT.Runtime/Projections/INotifyCollectionChanged.cs @@ -7,12 +7,12 @@ using WinRT.Interop; namespace ABI.System.Collections.Specialized -{ +{ [global::WinRT.ObjectReferenceWrapper(nameof(_obj)), EditorBrowsable(EditorBrowsableState.Never)] - [Guid("28B167D5-1A31-465B-9B25-D5C3AE686C40")] + [Guid("530155E1-28A5-5693-87CE-30724D95A06D")] public class INotifyCollectionChanged : global::System.Collections.Specialized.INotifyCollectionChanged { - [Guid("28B167D5-1A31-465B-9B25-D5C3AE686C40")] + [Guid("530155E1-28A5-5693-87CE-30724D95A06D")] public struct Vftbl { internal IInspectable.Vftbl IInspectableVftbl; diff --git a/WinRT.Runtime/Projections/INotifyPropertyChanged.cs b/WinRT.Runtime/Projections/INotifyPropertyChanged.cs index 70e896fe8..e1672d7b4 100644 --- a/WinRT.Runtime/Projections/INotifyPropertyChanged.cs +++ b/WinRT.Runtime/Projections/INotifyPropertyChanged.cs @@ -6,12 +6,12 @@ using WinRT.Interop; namespace ABI.System.ComponentModel -{ +{ [global::WinRT.ObjectReferenceWrapper(nameof(_obj)), global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] - [Guid("CF75D69C-F2F4-486B-B302-BB4C09BAEBFA")] + [Guid("90B17601-B065-586E-83D9-9ADC3A695284")] public class INotifyPropertyChanged : global::System.ComponentModel.INotifyPropertyChanged { - [Guid("CF75D69C-F2F4-486B-B302-BB4C09BAEBFA")] + [Guid("90B17601-B065-586E-83D9-9ADC3A695284")] [StructLayout(LayoutKind.Sequential)] public struct Vftbl { @@ -34,7 +34,8 @@ static unsafe Vftbl() AbiToProjectionVftablePtr = (IntPtr)nativeVftbl; } - private static global::System.Runtime.CompilerServices.ConditionalWeakTable> _PropertyChanged_TokenTables; + private static global::System.Runtime.CompilerServices.ConditionalWeakTable> _PropertyChanged_TokenTables = new global::System.Runtime.CompilerServices.ConditionalWeakTable>(); + private static unsafe int Do_Abi_add_PropertyChanged_0(IntPtr thisPtr, IntPtr handler, out global::WinRT.EventRegistrationToken token) { token = default; diff --git a/WinRT.Runtime/Projections/NotifyCollectionChangedEventArgs.cs b/WinRT.Runtime/Projections/NotifyCollectionChangedEventArgs.cs index a5cb8f023..d54810c5b 100644 --- a/WinRT.Runtime/Projections/NotifyCollectionChangedEventArgs.cs +++ b/WinRT.Runtime/Projections/NotifyCollectionChangedEventArgs.cs @@ -8,12 +8,12 @@ using WinRT.Interop; namespace ABI.Microsoft.UI.Xaml.Interop -{ +{ [global::WinRT.ObjectReferenceWrapper(nameof(_obj))] - [Guid("4CF68D33-E3F2-4964-B85E-945B4F7E2F21")] + [Guid("DA049FF2-D2E0-5FE8-8C7B-F87F26060B6F")] internal class INotifyCollectionChangedEventArgs { - [Guid("4CF68D33-E3F2-4964-B85E-945B4F7E2F21")] + [Guid("DA049FF2-D2E0-5FE8-8C7B-F87F26060B6F")] [StructLayout(LayoutKind.Sequential)] public struct Vftbl { @@ -107,14 +107,14 @@ internal static class INotifyCollectionChangedEventArgs_Delegates public unsafe delegate int get_Action_0(IntPtr thisPtr, out global::System.Collections.Specialized.NotifyCollectionChangedAction value); public unsafe delegate int get_NewItems_1(IntPtr thisPtr, out IntPtr value); public unsafe delegate int get_OldItems_2(IntPtr thisPtr, out IntPtr value); - } - + } + [global::WinRT.ObjectReferenceWrapper(nameof(_obj))] - [Guid("B30C3E3A-DF8D-44A5-9A38-7AC0D08CE63D")] + [Guid("5108EBA4-4892-5A20-8374-A96815E0FD27")] internal class WinRTNotifyCollectionChangedEventArgsRuntimeClassFactory { - [Guid("B30C3E3A-DF8D-44A5-9A38-7AC0D08CE63D")] + [Guid("5108EBA4-4892-5A20-8374-A96815E0FD27")] [StructLayout(LayoutKind.Sequential)] public struct Vftbl { diff --git a/WinRT.Runtime/Projections/NotifyCollectionChangedEventHandler.cs b/WinRT.Runtime/Projections/NotifyCollectionChangedEventHandler.cs index 69a016d6c..d539114b1 100644 --- a/WinRT.Runtime/Projections/NotifyCollectionChangedEventHandler.cs +++ b/WinRT.Runtime/Projections/NotifyCollectionChangedEventHandler.cs @@ -7,9 +7,9 @@ namespace ABI.System.Collections.Specialized { - + [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] - [Guid("CA10B37C-F382-4591-8557-5E24965279B0")] + [Guid("8B0909DC-2005-5D93-BF8A-725F017BAA8D")] public static class NotifyCollectionChangedEventHandler { private unsafe delegate int Abi_Invoke(IntPtr thisPtr, IntPtr sender, IntPtr e); diff --git a/WinRT.Runtime/Projections/PropertyChangedEventArgs.cs b/WinRT.Runtime/Projections/PropertyChangedEventArgs.cs index 44e9dd143..027151d1e 100644 --- a/WinRT.Runtime/Projections/PropertyChangedEventArgs.cs +++ b/WinRT.Runtime/Projections/PropertyChangedEventArgs.cs @@ -8,20 +8,20 @@ namespace ABI.Microsoft.UI.Xaml.Data { - [Guid("4F33A9A0-5CF4-47A4-B16F-D7FAAF17457E")] + [Guid("63D0C952-396B-54F4-AF8C-BA8724A427BF")] [StructLayout(LayoutKind.Sequential)] internal struct IPropertyChangedEventArgsVftbl { internal IInspectable.Vftbl IInspectableVftbl; public _get_PropertyAsString get_PropertyName_0; - } - + } + [global::WinRT.ObjectReferenceWrapper(nameof(_obj))] - [Guid("6DCC9C03-E0C7-4EEE-8EA9-37E3406EEB1C")] + [Guid("7C0C27A8-0B41-5070-B160-FC9AE960A36C")] internal class WinRTPropertyChangedEventArgsRuntimeClassFactory { - [Guid("6DCC9C03-E0C7-4EEE-8EA9-37E3406EEB1C")] + [Guid("7C0C27A8-0B41-5070-B160-FC9AE960A36C")] [StructLayout(LayoutKind.Sequential)] public struct Vftbl { diff --git a/WinRT.Runtime/Projections/PropertyChangedEventHandler.cs b/WinRT.Runtime/Projections/PropertyChangedEventHandler.cs index 5171381d7..8a69f01c2 100644 --- a/WinRT.Runtime/Projections/PropertyChangedEventHandler.cs +++ b/WinRT.Runtime/Projections/PropertyChangedEventHandler.cs @@ -8,7 +8,7 @@ namespace ABI.System.ComponentModel { [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] - [Guid("50F19C16-0A22-4D8E-A089-1EA9951657D2")] + [Guid("E3DE52F6-1E32-5DA6-BB2D-B5B6096C962D")] public static class PropertyChangedEventHandler { private unsafe delegate int Abi_Invoke(IntPtr thisPtr, IntPtr sender, IntPtr e); From fc3192cd4d09b999a49a8042dbb66008253b9f81 Mon Sep 17 00:00:00 2001 From: Scott Jones Date: Fri, 26 Jun 2020 12:42:58 -0700 Subject: [PATCH 23/38] Update README.md fixed link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a7a395870..0836f9f0d 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ However, C#/WinRT is a general effort and is intended to support other scenarios The [C#/WinRT NuGet Package](https://aka.ms/cswinrt/nuget) provides distinct support for both WinRT component projects and application projects. ## Component Project -A component project adds a NuGet reference to C#/WinRT to invoke cswinrt.exe at build time, generate projection sources, and compile these into an interop assembly. For an example of this, see the [UnitTest targets](https://github.com/microsoft/CsWinRT/blob/master/UnitTest/Directory.Build.targets). Command line options can be displayed by running **cswinrt -?**. The interop assembly is then typically distributed as a NuGet package itself. +A component project adds a NuGet reference to C#/WinRT to invoke cswinrt.exe at build time, generate projection sources, and compile these into an interop assembly. For an example of this, see the [Test Projection](https://github.com/microsoft/CsWinRT/blob/master/Projections/Test/Test.csproj). Command line options can be displayed by running **cswinrt -?**. The interop assembly is then typically distributed as a NuGet package itself. ## Application Project An application project adds NuGet references to both the component interop assembly produced above, and to C#/WinRT to include the winrt.runtime assembly. If a third party WinRT component is distributed without an official interop assembly, an application project may add a reference to C#/WinRT to generate its own private component interop assembly. There are versioning concerns related to this scenario, so the preferred solution is for the third party to publish an interop assembly directly. From 13a08cb5987a46311664e04f7e59fb4499a54e1b Mon Sep 17 00:00:00 2001 From: Scott Jones Date: Mon, 29 Jun 2020 08:31:18 -0700 Subject: [PATCH 24/38] Add ComImport casting support, subject to some constraints (#333) * comimport casting support * release QI'd comimport interface --- Projections/Test/Test.csproj | 2 +- TestComponentCSharp/ComImports.cpp | 61 ++++++++++++++++ TestComponentCSharp/ComImports.h | 19 +++++ TestComponentCSharp/StaticClass.cpp | 22 ------ TestComponentCSharp/StaticClass.h | 19 ----- TestComponentCSharp/TestComponentCSharp.idl | 6 +- .../TestComponentCSharp.vcxproj | 4 +- .../TestComponentCSharp.vcxproj.filters | 6 +- UnitTest/TestComponentCSharp_Tests.cs | 71 ++++++++++++++++--- WinRT.Runtime/CastExtensions.cs | 30 +++++++- WinRT.Runtime/ComWrappersSupport.cs | 4 +- 11 files changed, 181 insertions(+), 63 deletions(-) create mode 100644 TestComponentCSharp/ComImports.cpp create mode 100644 TestComponentCSharp/ComImports.h delete mode 100644 TestComponentCSharp/StaticClass.cpp delete mode 100644 TestComponentCSharp/StaticClass.h diff --git a/Projections/Test/Test.csproj b/Projections/Test/Test.csproj index 414a8bfda..803485d94 100644 --- a/Projections/Test/Test.csproj +++ b/Projections/Test/Test.csproj @@ -8,7 +8,7 @@ - true + true true 8305;0618 diff --git a/TestComponentCSharp/ComImports.cpp b/TestComponentCSharp/ComImports.cpp new file mode 100644 index 000000000..5dafacb87 --- /dev/null +++ b/TestComponentCSharp/ComImports.cpp @@ -0,0 +1,61 @@ +#include "pch.h" +#include "Class.h" +#include "ComImports.h" +#include "ComImports.g.cpp" + +using namespace winrt::Windows::Foundation; + +namespace winrt::TestComponentCSharp::implementation +{ + namespace statics + { + int _count{}; + } + + struct __declspec(uuid("EECDBF0E-BAE9-4CB6-A68E-9598E1CB57BB")) IWindowNative : ::IUnknown + { + virtual HRESULT __stdcall get_WindowHandle(HWND* hWnd) noexcept = 0; + }; + + struct __declspec(uuid("3E68D4BD-7135-4D10-8018-9FB6D9F33FA1")) IInitializeWithWindow : ::IUnknown + { + virtual HRESULT __stdcall Initialize(HWND hWnd) noexcept = 0; + }; + + struct ComImportObject : winrt::implements + { + ComImportObject() + { + ++statics::_count; + } + + ~ComImportObject() + { + --statics::_count; + } + + HWND m_hWnd = (HWND)0; + + HRESULT __stdcall get_WindowHandle(HWND* hWnd) noexcept override + { + *hWnd = m_hWnd; + return 0; + } + + HRESULT __stdcall Initialize(HWND hWnd) noexcept override + { + m_hWnd = hWnd; + return 0; + } + }; + + IInspectable ComImports::MakeObject() + { + return winrt::make(); + } + + int32_t ComImports::NumObjects() + { + return statics::_count; + } +} diff --git a/TestComponentCSharp/ComImports.h b/TestComponentCSharp/ComImports.h new file mode 100644 index 000000000..2876b7ddd --- /dev/null +++ b/TestComponentCSharp/ComImports.h @@ -0,0 +1,19 @@ +#pragma once +#include "ComImports.g.h" + +namespace winrt::TestComponentCSharp::implementation +{ + struct ComImports + { + ComImports() = default; + + static Windows::Foundation::IInspectable MakeObject(); + static int32_t NumObjects(); + }; +} +namespace winrt::TestComponentCSharp::factory_implementation +{ + struct ComImports : ComImportsT + { + }; +} diff --git a/TestComponentCSharp/StaticClass.cpp b/TestComponentCSharp/StaticClass.cpp deleted file mode 100644 index e977f670d..000000000 --- a/TestComponentCSharp/StaticClass.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "pch.h" -#include "Class.h" -#include "StaticClass.h" -#include "StaticClass.g.cpp" - -namespace winrt::TestComponentCSharp::implementation -{ - namespace statics - { - int _count{}; - } - - TestComponentCSharp::Class StaticClass::MakeClass() - { - ++statics::_count; - return winrt::make(); - } - int32_t StaticClass::NumClasses() - { - return statics::_count; - } -} diff --git a/TestComponentCSharp/StaticClass.h b/TestComponentCSharp/StaticClass.h deleted file mode 100644 index 8c8f9d4c7..000000000 --- a/TestComponentCSharp/StaticClass.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once -#include "StaticClass.g.h" - -namespace winrt::TestComponentCSharp::implementation -{ - struct StaticClass - { - StaticClass() = default; - - static TestComponentCSharp::Class MakeClass(); - static int32_t NumClasses(); - }; -} -namespace winrt::TestComponentCSharp::factory_implementation -{ - struct StaticClass : StaticClassT - { - }; -} diff --git a/TestComponentCSharp/TestComponentCSharp.idl b/TestComponentCSharp/TestComponentCSharp.idl index 20a16661d..1e3765f19 100644 --- a/TestComponentCSharp/TestComponentCSharp.idl +++ b/TestComponentCSharp/TestComponentCSharp.idl @@ -87,10 +87,10 @@ namespace TestComponentCSharp //String DistinctProperty{ get; set; }; } - static runtimeclass StaticClass + static runtimeclass ComImports { - static Class MakeClass(); - static Int32 NumClasses{ get; }; + static Object MakeObject(); + static Int32 NumObjects{ get; }; } [default_interface] diff --git a/TestComponentCSharp/TestComponentCSharp.vcxproj b/TestComponentCSharp/TestComponentCSharp.vcxproj index b2cb1b4e4..d9b136671 100644 --- a/TestComponentCSharp/TestComponentCSharp.vcxproj +++ b/TestComponentCSharp/TestComponentCSharp.vcxproj @@ -70,7 +70,7 @@ TestComponentCSharp.idl - + @@ -81,7 +81,7 @@ TestComponentCSharp.idl - + diff --git a/TestComponentCSharp/TestComponentCSharp.vcxproj.filters b/TestComponentCSharp/TestComponentCSharp.vcxproj.filters index 9c0351ae0..6e9156a6f 100644 --- a/TestComponentCSharp/TestComponentCSharp.vcxproj.filters +++ b/TestComponentCSharp/TestComponentCSharp.vcxproj.filters @@ -9,15 +9,15 @@ - - + + - + diff --git a/UnitTest/TestComponentCSharp_Tests.cs b/UnitTest/TestComponentCSharp_Tests.cs index c6ac128f3..671d48260 100644 --- a/UnitTest/TestComponentCSharp_Tests.cs +++ b/UnitTest/TestComponentCSharp_Tests.cs @@ -7,7 +7,6 @@ using WinRT; using Windows.Foundation; -using Windows.Foundation.Collections; using Windows.UI; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls.Primitives; @@ -19,8 +18,8 @@ using TestComponentCSharp; using System.Collections.Generic; using System.Collections; -using TestComponent; using WinRT.Interop; +using System.Runtime.InteropServices; namespace UnitTest { @@ -260,14 +259,6 @@ public void TestStaticMembers() Assert.Equal("foo", Class.StaticStringProperty); } - [Fact] - public void TestStaticClass() - { - Assert.Equal(0, StaticClass.NumClasses); - var obj = StaticClass.MakeClass(); - Assert.Equal(1, StaticClass.NumClasses); - } - [Fact] public void TestInterfaces() { @@ -1594,5 +1585,65 @@ public void TestNonAgileDelegateCall() observable.Add(3); Assert.Equal(6, observable.Observation); } + + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("EECDBF0E-BAE9-4CB6-A68E-9598E1CB57BB")] + internal interface IWindowNative + { + IntPtr WindowHandle { get; } + } + + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("3E68D4BD-7135-4D10-8018-9FB6D9F33FA1")] + internal interface IInitializeWithWindow + { + void Initialize(IntPtr hwnd); + } + + [Fact] + unsafe public void TestComImports() + { + static Object MakeObject() + { + Assert.Equal(0, ComImports.NumObjects); + var obj = ComImports.MakeObject(); + Assert.Equal(1, ComImports.NumObjects); + return obj; + } + + static void TestObject() => MakeObject(); + + static (IInitializeWithWindow, IWindowNative) MakeImports() + { + var obj = MakeObject(); + var initializeWithWindow = obj.As(); + var windowNative = obj.As(); + return (initializeWithWindow, windowNative); + } + + static void TestImports() + { + var (initializeWithWindow, windowNative) = MakeImports(); + + GC.Collect(); + GC.WaitForPendingFinalizers(); + + var hwnd = new IntPtr(0x12345678); + initializeWithWindow.Initialize(hwnd); + Assert.Equal(windowNative.WindowHandle, hwnd); + } + + TestObject(); + GC.Collect(); + GC.WaitForPendingFinalizers(); + Assert.Equal(0, ComImports.NumObjects); + + TestImports(); + GC.Collect(); + GC.WaitForPendingFinalizers(); + Assert.Equal(0, ComImports.NumObjects); + } } } \ No newline at end of file diff --git a/WinRT.Runtime/CastExtensions.cs b/WinRT.Runtime/CastExtensions.cs index 09510ee59..5d5661164 100644 --- a/WinRT.Runtime/CastExtensions.cs +++ b/WinRT.Runtime/CastExtensions.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using System.Text; using WinRT.Interop; @@ -39,7 +41,33 @@ public static TInterface As(this object value) } using (var objRef = GetRefForObject(value)) - { + { + if (typeof(TInterface).GetCustomAttribute(typeof(System.Runtime.InteropServices.ComImportAttribute)) is object) + { + unsafe + { + static WinRT.Interop.IUnknownVftbl MarshalIUnknown(IntPtr thisPtr) + { + var vftblPtr = Unsafe.AsRef(thisPtr.ToPointer()); + var vftblIUnknown = Marshal.PtrToStructure(vftblPtr.Vftbl); + return vftblIUnknown; + } + + Guid iid = typeof(TInterface).GUID; + IntPtr comPtr; + MarshalIUnknown(objRef.ThisPtr).QueryInterface(objRef.ThisPtr, ref iid, out comPtr); + try + { + var obj = Marshal.GetObjectForIUnknown(comPtr); + return (TInterface)obj; + } + finally + { + MarshalIUnknown(comPtr).Release(comPtr); + } + } + } + return (TInterface)typeof(TInterface).GetHelperType().GetConstructor(new[] { typeof(IObjectReference) }).Invoke(new object[] { objRef }); } } diff --git a/WinRT.Runtime/ComWrappersSupport.cs b/WinRT.Runtime/ComWrappersSupport.cs index ebddffbce..1d813ed25 100644 --- a/WinRT.Runtime/ComWrappersSupport.cs +++ b/WinRT.Runtime/ComWrappersSupport.cs @@ -265,8 +265,8 @@ private static Func CreateArrayFactory(Type implementation internal static Func CreateTypedRcwFactory(string runtimeClassName) { - // If we don't have a runtime class name, then we just use IInspectable. - if (string.IsNullOrEmpty(runtimeClassName)) + // If runtime class name is empty or "Object", then just use IInspectable. + if (string.IsNullOrEmpty(runtimeClassName) || runtimeClassName == "Object") { return (IInspectable obj) => obj; } From 824abecd40511bea73eb50339c8043e61877a121 Mon Sep 17 00:00:00 2001 From: Manodasan Wignarajah Date: Mon, 29 Jun 2020 13:14:46 -0700 Subject: [PATCH 25/38] Improving performance of non default query interface calls by caching a lazy reference rather than constructing it each time. --- cswinrt/code_writers.h | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/cswinrt/code_writers.h b/cswinrt/code_writers.h index abc0dce30..0f307117b 100644 --- a/cswinrt/code_writers.h +++ b/cswinrt/code_writers.h @@ -752,6 +752,29 @@ set => %.% = value; bind(iface, as_abi, false)); } + void write_lazy_interface_initialization(writer& w, TypeDef const& type) + { + for (auto&& ii : type.InterfaceImpl()) + { + if (has_attribute(ii, "Windows.Foundation.Metadata", "DefaultAttribute")) + { + continue; + } + + for_typedef(w, get_type_semantics(ii.Interface()), [&](auto interface_type) + { + auto interface_name = write_type_name_temp(w, interface_type); + auto interface_abi_name = write_type_name_temp(w, interface_type, "%", true); + + w.write(R"( +{typeof(%), new Lazy<%>(() => new %(GetReferenceForQI()))},)", + interface_name, + interface_abi_name, + interface_abi_name); + }); + } + } + std::string write_explicit_name(writer& w, TypeDef const& iface, std::string_view name) { return w.write_temp("%.%", write_type_name_temp(w, iface), name); @@ -1439,11 +1462,12 @@ target); if (!is_default_interface) { w.write(R"( -private % AsInternal(InterfaceTag<%> _) => new %(GetReferenceForQI()); +private % AsInternal(InterfaceTag<%> _) => ((Lazy<%>)_lazyInterfaces[typeof(%)]).Value; )", interface_name, interface_name, - interface_abi_name); + interface_abi_name, + interface_name); } if(auto mapping = get_mapped_type(interface_type.TypeNamespace(), interface_type.TypeName()); mapping && mapping->has_custom_members_output) @@ -3909,6 +3933,7 @@ public %IntPtr ThisPtr => _default.ThisPtr; private IObjectReference _inner = null; private readonly Lazy<%> _defaultLazy; +private readonly Dictionary _lazyInterfaces; private % _default => _defaultLazy.Value; % @@ -3922,6 +3947,9 @@ return obj is % ? (%)obj : new %((%)obj); % %(% ifc)% { _defaultLazy = new Lazy<%>(() => ifc); +_lazyInterfaces = new Dictionary() +{% +}; } public static bool operator ==(% x, % y) => (x?.ThisPtr ?? IntPtr.Zero) == (y?.ThisPtr ?? IntPtr.Zero); @@ -3957,6 +3985,7 @@ private % AsInternal(InterfaceTag<%> _) => _default; default_interface_abi_name, bind(base_semantics), default_interface_abi_name, + bind(type), type_name, type_name, type_name, From bd5f80781b8cec81c7f151c8676e9f32706c61b0 Mon Sep 17 00:00:00 2001 From: Scott Jones Date: Tue, 30 Jun 2020 07:05:25 -0700 Subject: [PATCH 26/38] update to .net 5 sdk preview 7, and a few other dependencies (#339) --- Projections/Windows/Windows.csproj | 18 ++++++++---------- .../TestComponentCSharp.vcxproj | 8 ++++---- TestComponentCSharp/packages.config | 2 +- UnitTest/UnitTest.csproj | 6 +++--- WinRT.Runtime/WinRT.Runtime.csproj | 2 +- WinUIDesktopSample/WinUIDesktopSample.csproj | 2 +- build.cmd | 2 +- get_testwinrt.cmd | 2 +- 8 files changed, 20 insertions(+), 22 deletions(-) diff --git a/Projections/Windows/Windows.csproj b/Projections/Windows/Windows.csproj index a99feca2e..fd75e76b9 100644 --- a/Projections/Windows/Windows.csproj +++ b/Projections/Windows/Windows.csproj @@ -13,19 +13,19 @@ 8305;0618 - - full - true + + full + true - - full - true + + full + true - + - + @@ -42,8 +42,6 @@ -in 10.0.18362.0 -out "$(GeneratedFilesDir.TrimEnd('\'))" -include Windows -# Exclude causality types colliding with those in System.Private.CoreLib.dll --exclude Windows.Foundation.Diagnostics # Exclude Windows.UI, Windows.UI.Text, Windows.UI.Xaml per Microsoft.Windows.SDK.WinUI.Contracts NuGet -include Windows.UI.Popups -exclude Windows.UI.Colors diff --git a/TestComponentCSharp/TestComponentCSharp.vcxproj b/TestComponentCSharp/TestComponentCSharp.vcxproj index d9b136671..fae3655f2 100644 --- a/TestComponentCSharp/TestComponentCSharp.vcxproj +++ b/TestComponentCSharp/TestComponentCSharp.vcxproj @@ -1,7 +1,7 @@ - + high true @@ -93,15 +93,15 @@ - + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - + + diff --git a/TestComponentCSharp/packages.config b/TestComponentCSharp/packages.config index 72ab06b94..8a0930c09 100644 --- a/TestComponentCSharp/packages.config +++ b/TestComponentCSharp/packages.config @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/UnitTest/UnitTest.csproj b/UnitTest/UnitTest.csproj index 524c30285..01dd36843 100644 --- a/UnitTest/UnitTest.csproj +++ b/UnitTest/UnitTest.csproj @@ -19,7 +19,7 @@ - + @@ -30,13 +30,13 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/WinRT.Runtime/WinRT.Runtime.csproj b/WinRT.Runtime/WinRT.Runtime.csproj index fd849df76..d28514b9f 100644 --- a/WinRT.Runtime/WinRT.Runtime.csproj +++ b/WinRT.Runtime/WinRT.Runtime.csproj @@ -42,7 +42,7 @@ - + \ No newline at end of file diff --git a/WinUIDesktopSample/WinUIDesktopSample.csproj b/WinUIDesktopSample/WinUIDesktopSample.csproj index 0d4f8d9fa..64cc5e1ab 100644 --- a/WinUIDesktopSample/WinUIDesktopSample.csproj +++ b/WinUIDesktopSample/WinUIDesktopSample.csproj @@ -21,7 +21,7 @@ - + + true + Benchmarks.manifest + + + + + + + + + + + + + + + + BenchmarkComponent.dll + PreserveNewest + True + + + + $(MSBuildThisFileDirectory)..\_build\$(Platform)\$(Configuration)\BenchmarkComponent\bin\BenchmarkComponent\BenchmarkComponent.winmd + true + + + + + Benchmarks.manifest + PreserveNewest + True + + + + + + + + + + + + diff --git a/Benchmarks/Benchmarks.manifest b/Benchmarks/Benchmarks.manifest new file mode 100644 index 000000000..74774097c --- /dev/null +++ b/Benchmarks/Benchmarks.manifest @@ -0,0 +1,12 @@ + + + + + + + + + diff --git a/Benchmarks/Program.cs b/Benchmarks/Program.cs new file mode 100644 index 000000000..03a29cf41 --- /dev/null +++ b/Benchmarks/Program.cs @@ -0,0 +1,96 @@ +using BenchmarkDotNet.Running; +using System; +using BenchmarkDotNet.Configs; +using BenchmarkDotNet.Jobs; +using BenchmarkDotNet.Toolchains.CsProj; +using BenchmarkDotNet.Toolchains.DotNetCli; +using BenchmarkDotNet.Toolchains; +using BenchmarkDotNet.Loggers; +using BenchmarkDotNet.Characteristics; +using System.IO; + +namespace Benchmarks +{ + public class Program + { + static void Main(string[] args) => BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args, new CustomConfig().Config); + + private class CustomConfig : Attribute, IConfigSource + { + public IConfig Config { get; } = DefaultConfig.Instance; + + public CustomConfig() + { + // Test CsWinRT projection + var job = Job.Default + .WithPlatform(BenchmarkDotNet.Environments.Platform.X64) + .WithArguments( + new Argument[] { + new MsBuildArgument("/p:platform=x64"), + new MsBuildArgument("/p:MsAppxPackageTargets=%temp%\\EmptyMsAppxPackage.Targets") + } + ).AsDefault(); + + // Test WinMD support +#if NETCOREAPP3_1 + // BenchmarkDotNet will rebuild the project with a project reference when this exe is ran and + // in the same folder as it we have the application manifest binplaced which we want to embed in the new exe. + string manifestFile = Path.Combine( + Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), + "Benchmarks.manifest"); + + var winmdJob = Job.Default + .WithPlatform(BenchmarkDotNet.Environments.Platform.X64) + .WithToolchain(new NetCore3ToolChainWithNativeExecution()) + .WithArguments( + new Argument[] { + new MsBuildArgument("/p:platform=x64"), + new MsBuildArgument("/p:ApplicationManifest=" + manifestFile), + new MsBuildArgument("/p:BenchmarkWinmdSupport=true") + } + ) + .WithId("WinMD NetCoreApp31"); + + // Optimizer needs to be diabled as it errors on WinMDs + Config = Config.WithOption(ConfigOptions.DisableOptimizationsValidator, true) + .AddJob(winmdJob); +#else + Config = Config.AddJob(job); +#endif + } + } + + // Custom tool chain for building the benchmark with WinMDs as we need to execute the + // exe version of the benchmark rather than the dll version which runs under dotnet cli. + // This is becuase we need to be able to embed a side by side manifest for reg free winrt + // and to enable COM to find the WinMDs. + private class NetCore3ToolChainWithNativeExecution : Toolchain + { + public NetCore3ToolChainWithNativeExecution() + : base("netcoreapp3.1-native", + new CsProjGeneratorWithNativeExe(NetCoreAppSettings.NetCoreApp31), + CsProjCoreToolchain.NetCoreApp31.Builder, + new Executor()) + { + } + + public override bool IsSupported(BenchmarkCase benchmarkCase, ILogger logger, IResolver resolver) + { + return CsProjCoreToolchain.NetCoreApp31.IsSupported(benchmarkCase, logger, resolver); + } + } + + private class CsProjGeneratorWithNativeExe : CsProjGenerator + { + public CsProjGeneratorWithNativeExe(NetCoreAppSettings settings) + :base(settings.TargetFrameworkMoniker, settings.CustomDotNetCliPath, settings.PackagesPath, settings.RuntimeFrameworkVersion) + { + } + + protected override string GetExecutableExtension() + { + return ".exe"; + } + } + } +} diff --git a/Benchmarks/QueryInterface.cs b/Benchmarks/QueryInterface.cs new file mode 100644 index 000000000..9f7441dc3 --- /dev/null +++ b/Benchmarks/QueryInterface.cs @@ -0,0 +1,78 @@ +using BenchmarkComponent; +using BenchmarkDotNet.Attributes; +using Windows.ApplicationModel.Chat; + +namespace Benchmarks +{ + public class QueryInterfacePerf + { + ClassWithMultipleInterfaces instance; + ChatMessage message; + + [GlobalSetup] + public void Setup() + { + instance = new ClassWithMultipleInterfaces(); + message = new ChatMessage(); + } + + [Benchmark] + public int QueryDefaultInterface() + { + return instance.Property1; + } + + [Benchmark] + public int QueryNonDefaultInterface() + { + return instance.IntProperty1; + } + + [Benchmark] + public bool QueryNonDefaultInterface2() + { + return instance.BoolProperty1; + } + + [Benchmark] + public void QueryDefaultInterfaceSetProperty() + { + instance.Property1 = 4; + } + + [Benchmark] + public void QueryNonDefaultInterfaceSetProperty() + { + instance.IntProperty1 = 4; + } + + [Benchmark] + public bool QuerySDKDefaultInterface() + { + return message.IsForwardingDisabled; + } + + [Benchmark] + public bool QuerySDKNonDefaultInterface() + { + return message.IsSeen; + } + + // The following 2 benchmarks try to benchmark the time taken for the first call + // rather than the mean time over several calls. It has the overhead of the object + // construction, but it can be used to track regressions to performance. + [Benchmark] + public int ConstructAndQueryDefaultInterfaceFirstCall() + { + ClassWithMultipleInterfaces instance2 = new ClassWithMultipleInterfaces(); + return instance2.Property1; + } + + [Benchmark] + public int ConstructAndQueryNonDefaultInterfaceFirstCall() + { + ClassWithMultipleInterfaces instance2 = new ClassWithMultipleInterfaces(); + return instance2.IntProperty1; + } + } +} \ No newline at end of file diff --git a/benchmark.cmd b/benchmark.cmd new file mode 100644 index 000000000..7b2f42e7a --- /dev/null +++ b/benchmark.cmd @@ -0,0 +1,2 @@ +msbuild Benchmarks\Benchmarks.csproj -t:restore -t:build /p:platform=x64 /p:configuration=release +dotnet S:\CsWinRT\Benchmarks\bin\x64\Release\netcoreapp2.0\Benchmarks.dll -filter * --runtimes netcoreapp2.0 netcoreapp3.1 netcoreapp5.0 \ No newline at end of file diff --git a/benchmark_winmd.cmd b/benchmark_winmd.cmd new file mode 100644 index 000000000..e2d5c03aa --- /dev/null +++ b/benchmark_winmd.cmd @@ -0,0 +1,4 @@ +msbuild Benchmarks\Benchmarks.csproj -t:restore -t:clean;rebuild /p:BenchmarkWinmdSupport=true /p:platform=x64 /p:configuration=release /p:TargetFramework=netcoreapp3.1 +S:\CsWinRT\Benchmarks\bin\x64\Release\netcoreapp3.1\Benchmarks.exe -filter * +rem Clean project to prevent mismatch scenarios with the typical benchmark.cmd scenario. +msbuild Benchmarks\Benchmarks.csproj -t:restore -t:clean /p:BenchmarkWinmdSupport=true /p:platform=x64 /p:configuration=release /p:TargetFramework=netcoreapp3.1 >nul \ No newline at end of file From 404483965f7a4fd63b591ca74d26cbc1c0e9d063 Mon Sep 17 00:00:00 2001 From: Manodasan Wignarajah Date: Mon, 29 Jun 2020 13:13:07 -0700 Subject: [PATCH 29/38] Adding managed memory tracking. --- Benchmarks/QueryInterface.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Benchmarks/QueryInterface.cs b/Benchmarks/QueryInterface.cs index 9f7441dc3..eb6305f13 100644 --- a/Benchmarks/QueryInterface.cs +++ b/Benchmarks/QueryInterface.cs @@ -4,6 +4,7 @@ namespace Benchmarks { + [MemoryDiagnoser] public class QueryInterfacePerf { ClassWithMultipleInterfaces instance; From 193c04ffd72c477099c78cce319297c26c9565dd Mon Sep 17 00:00:00 2001 From: Manodasan Wignarajah Date: Tue, 30 Jun 2020 11:25:40 -0700 Subject: [PATCH 30/38] Adopting to changes to benchmarkcomponent --- Benchmarks/Benchmarks.csproj | 2 +- Benchmarks/QueryInterface.cs | 14 +++--- Projections/Benchmark/Benchmark.csproj | 68 ++++++++++++++++++++++++++ cswinrt.sln | 49 +++++++++++++++++++ 4 files changed, 125 insertions(+), 8 deletions(-) create mode 100644 Projections/Benchmark/Benchmark.csproj diff --git a/Benchmarks/Benchmarks.csproj b/Benchmarks/Benchmarks.csproj index 4d2245383..bd31585a1 100644 --- a/Benchmarks/Benchmarks.csproj +++ b/Benchmarks/Benchmarks.csproj @@ -20,7 +20,7 @@ - + diff --git a/Benchmarks/QueryInterface.cs b/Benchmarks/QueryInterface.cs index eb6305f13..567ef3aa9 100644 --- a/Benchmarks/QueryInterface.cs +++ b/Benchmarks/QueryInterface.cs @@ -20,31 +20,31 @@ public void Setup() [Benchmark] public int QueryDefaultInterface() { - return instance.Property1; + return instance.DefaultIntProperty; } [Benchmark] public int QueryNonDefaultInterface() { - return instance.IntProperty1; + return instance.IntProperty; } [Benchmark] public bool QueryNonDefaultInterface2() { - return instance.BoolProperty1; + return instance.BoolProperty; } [Benchmark] public void QueryDefaultInterfaceSetProperty() { - instance.Property1 = 4; + instance.DefaultIntProperty = 4; } [Benchmark] public void QueryNonDefaultInterfaceSetProperty() { - instance.IntProperty1 = 4; + instance.IntProperty = 4; } [Benchmark] @@ -66,14 +66,14 @@ public bool QuerySDKNonDefaultInterface() public int ConstructAndQueryDefaultInterfaceFirstCall() { ClassWithMultipleInterfaces instance2 = new ClassWithMultipleInterfaces(); - return instance2.Property1; + return instance2.DefaultIntProperty; } [Benchmark] public int ConstructAndQueryNonDefaultInterfaceFirstCall() { ClassWithMultipleInterfaces instance2 = new ClassWithMultipleInterfaces(); - return instance2.IntProperty1; + return instance2.IntProperty; } } } \ No newline at end of file diff --git a/Projections/Benchmark/Benchmark.csproj b/Projections/Benchmark/Benchmark.csproj new file mode 100644 index 000000000..180a2694b --- /dev/null +++ b/Projections/Benchmark/Benchmark.csproj @@ -0,0 +1,68 @@ + + + + netstandard2.0;net5.0 + x64;x86 + 10.0.18362.0 + 8 + + + + true + true + 8305;0618 + + + + full + true + + + + + + + + + + + + + + + + + + + + high + $(GeneratedFilesDir)cswinrt_benchmark.rsp + $(CsWinRTExe) %40"$(CsWinRTResponseFile)" + + + +-verbose +-in 10.0.18362.0 +-in @(ReferenceWinMDs->'"%(FullPath)"', ' ') +-out "$(GeneratedFilesDir.TrimEnd('\'))" +-exclude Windows +-include BenchmarkComponent + + + + + + + + + + + + + + + + + + + diff --git a/cswinrt.sln b/cswinrt.sln index e9b85aa6f..41b4794e9 100644 --- a/cswinrt.sln +++ b/cswinrt.sln @@ -54,6 +54,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Nuget", "Nuget", "{5A94EFDF nuget\SignConfig.xml = nuget\SignConfig.xml EndProjectSection EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Benchmarks", "Benchmarks\Benchmarks.csproj", "{B34C96F4-3660-4B2D-8ABD-A4B428166DC7}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BenchmarkComponent", "TestWinRT\BenchmarkComponent\BenchmarkComponent.vcxproj", "{78D85F23-7CB1-44A1-9238-6DF2C76754E4}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Benchmark", "Projections\Benchmark\Benchmark.csproj", "{03EEF460-2F10-4FBE-AFFA-53477D3FC8D5}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -208,6 +214,48 @@ Global {0A991D5F-BFEE-4D2F-9AAD-6AD06470A5DF}.Release|x64.Build.0 = Release|x64 {0A991D5F-BFEE-4D2F-9AAD-6AD06470A5DF}.Release|x86.ActiveCfg = Release|x86 {0A991D5F-BFEE-4D2F-9AAD-6AD06470A5DF}.Release|x86.Build.0 = Release|x86 + {B34C96F4-3660-4B2D-8ABD-A4B428166DC7}.Debug|Any CPU.ActiveCfg = Debug|x86 + {B34C96F4-3660-4B2D-8ABD-A4B428166DC7}.Debug|ARM.ActiveCfg = Debug|x86 + {B34C96F4-3660-4B2D-8ABD-A4B428166DC7}.Debug|ARM64.ActiveCfg = Debug|x86 + {B34C96F4-3660-4B2D-8ABD-A4B428166DC7}.Debug|x64.ActiveCfg = Debug|x64 + {B34C96F4-3660-4B2D-8ABD-A4B428166DC7}.Debug|x64.Build.0 = Debug|x64 + {B34C96F4-3660-4B2D-8ABD-A4B428166DC7}.Debug|x86.ActiveCfg = Debug|x86 + {B34C96F4-3660-4B2D-8ABD-A4B428166DC7}.Debug|x86.Build.0 = Debug|x86 + {B34C96F4-3660-4B2D-8ABD-A4B428166DC7}.Release|Any CPU.ActiveCfg = Release|x86 + {B34C96F4-3660-4B2D-8ABD-A4B428166DC7}.Release|ARM.ActiveCfg = Release|x86 + {B34C96F4-3660-4B2D-8ABD-A4B428166DC7}.Release|ARM64.ActiveCfg = Release|x86 + {B34C96F4-3660-4B2D-8ABD-A4B428166DC7}.Release|x64.ActiveCfg = Release|x64 + {B34C96F4-3660-4B2D-8ABD-A4B428166DC7}.Release|x64.Build.0 = Release|x64 + {B34C96F4-3660-4B2D-8ABD-A4B428166DC7}.Release|x86.ActiveCfg = Release|x86 + {B34C96F4-3660-4B2D-8ABD-A4B428166DC7}.Release|x86.Build.0 = Release|x86 + {78D85F23-7CB1-44A1-9238-6DF2C76754E4}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {78D85F23-7CB1-44A1-9238-6DF2C76754E4}.Debug|ARM.ActiveCfg = Debug|Win32 + {78D85F23-7CB1-44A1-9238-6DF2C76754E4}.Debug|ARM64.ActiveCfg = Debug|Win32 + {78D85F23-7CB1-44A1-9238-6DF2C76754E4}.Debug|x64.ActiveCfg = Debug|x64 + {78D85F23-7CB1-44A1-9238-6DF2C76754E4}.Debug|x64.Build.0 = Debug|x64 + {78D85F23-7CB1-44A1-9238-6DF2C76754E4}.Debug|x86.ActiveCfg = Debug|Win32 + {78D85F23-7CB1-44A1-9238-6DF2C76754E4}.Debug|x86.Build.0 = Debug|Win32 + {78D85F23-7CB1-44A1-9238-6DF2C76754E4}.Release|Any CPU.ActiveCfg = Release|Win32 + {78D85F23-7CB1-44A1-9238-6DF2C76754E4}.Release|ARM.ActiveCfg = Release|Win32 + {78D85F23-7CB1-44A1-9238-6DF2C76754E4}.Release|ARM64.ActiveCfg = Release|Win32 + {78D85F23-7CB1-44A1-9238-6DF2C76754E4}.Release|x64.ActiveCfg = Release|x64 + {78D85F23-7CB1-44A1-9238-6DF2C76754E4}.Release|x64.Build.0 = Release|x64 + {78D85F23-7CB1-44A1-9238-6DF2C76754E4}.Release|x86.ActiveCfg = Release|Win32 + {78D85F23-7CB1-44A1-9238-6DF2C76754E4}.Release|x86.Build.0 = Release|Win32 + {03EEF460-2F10-4FBE-AFFA-53477D3FC8D5}.Debug|Any CPU.ActiveCfg = Debug|x86 + {03EEF460-2F10-4FBE-AFFA-53477D3FC8D5}.Debug|ARM.ActiveCfg = Debug|x86 + {03EEF460-2F10-4FBE-AFFA-53477D3FC8D5}.Debug|ARM64.ActiveCfg = Debug|x86 + {03EEF460-2F10-4FBE-AFFA-53477D3FC8D5}.Debug|x64.ActiveCfg = Debug|x64 + {03EEF460-2F10-4FBE-AFFA-53477D3FC8D5}.Debug|x64.Build.0 = Debug|x64 + {03EEF460-2F10-4FBE-AFFA-53477D3FC8D5}.Debug|x86.ActiveCfg = Debug|x86 + {03EEF460-2F10-4FBE-AFFA-53477D3FC8D5}.Debug|x86.Build.0 = Debug|x86 + {03EEF460-2F10-4FBE-AFFA-53477D3FC8D5}.Release|Any CPU.ActiveCfg = Release|x86 + {03EEF460-2F10-4FBE-AFFA-53477D3FC8D5}.Release|ARM.ActiveCfg = Release|x86 + {03EEF460-2F10-4FBE-AFFA-53477D3FC8D5}.Release|ARM64.ActiveCfg = Release|x86 + {03EEF460-2F10-4FBE-AFFA-53477D3FC8D5}.Release|x64.ActiveCfg = Release|x64 + {03EEF460-2F10-4FBE-AFFA-53477D3FC8D5}.Release|x64.Build.0 = Release|x64 + {03EEF460-2F10-4FBE-AFFA-53477D3FC8D5}.Release|x86.ActiveCfg = Release|x86 + {03EEF460-2F10-4FBE-AFFA-53477D3FC8D5}.Release|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -216,6 +264,7 @@ Global {C6D580C5-7037-4733-B933-916FF400AFE2} = {6D41796B-9904-40B8-BBCB-40B2D1BAE44B} {FFA9A78B-F53F-43EE-AF87-24A80F4C330A} = {6D41796B-9904-40B8-BBCB-40B2D1BAE44B} {0A991D5F-BFEE-4D2F-9AAD-6AD06470A5DF} = {6D41796B-9904-40B8-BBCB-40B2D1BAE44B} + {03EEF460-2F10-4FBE-AFFA-53477D3FC8D5} = {6D41796B-9904-40B8-BBCB-40B2D1BAE44B} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {5AE8C9D7-2613-4E1A-A4F2-579BAC28D0A2} From cd3b2f16f2fc2abde751f70b16286418bed3536d Mon Sep 17 00:00:00 2001 From: Manodasan Wignarajah Date: Wed, 1 Jul 2020 11:53:25 -0700 Subject: [PATCH 31/38] Building fixes. --- Benchmarks/Benchmarks.csproj | 4 +++- cswinrt.sln | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Benchmarks/Benchmarks.csproj b/Benchmarks/Benchmarks.csproj index bd31585a1..4552e80ba 100644 --- a/Benchmarks/Benchmarks.csproj +++ b/Benchmarks/Benchmarks.csproj @@ -14,7 +14,7 @@ - + @@ -47,6 +47,8 @@ + + diff --git a/cswinrt.sln b/cswinrt.sln index 41b4794e9..40d1ee8d6 100644 --- a/cswinrt.sln +++ b/cswinrt.sln @@ -57,6 +57,9 @@ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Benchmarks", "Benchmarks\Benchmarks.csproj", "{B34C96F4-3660-4B2D-8ABD-A4B428166DC7}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BenchmarkComponent", "TestWinRT\BenchmarkComponent\BenchmarkComponent.vcxproj", "{78D85F23-7CB1-44A1-9238-6DF2C76754E4}" + ProjectSection(ProjectDependencies) = postProject + {6ACFD2B2-E8AA-4CD4-AAD8-213CE8BB2637} = {6ACFD2B2-E8AA-4CD4-AAD8-213CE8BB2637} + EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Benchmark", "Projections\Benchmark\Benchmark.csproj", "{03EEF460-2F10-4FBE-AFFA-53477D3FC8D5}" EndProject From 669484c4c980a0b2875b6b020c336dd86bd4ebee Mon Sep 17 00:00:00 2001 From: Manodasan Wignarajah Date: Wed, 1 Jul 2020 13:32:23 -0700 Subject: [PATCH 32/38] Remove unnecessary removals. --- Projections/Benchmark/Benchmark.csproj | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Projections/Benchmark/Benchmark.csproj b/Projections/Benchmark/Benchmark.csproj index 180a2694b..26aa10a43 100644 --- a/Projections/Benchmark/Benchmark.csproj +++ b/Projections/Benchmark/Benchmark.csproj @@ -30,8 +30,6 @@ - - @@ -59,9 +57,9 @@ - - + + From e30070602e0508549340819e45ee7eb7a0eb7034 Mon Sep 17 00:00:00 2001 From: Manodasan Wignarajah Date: Wed, 1 Jul 2020 13:55:40 -0700 Subject: [PATCH 33/38] Fix PlatformVersion error when building benchmarks due to Window identifier set. --- Directory.Build.props | 1 + 1 file changed, 1 insertion(+) diff --git a/Directory.Build.props b/Directory.Build.props index 573d6c7eb..f8dd4e42b 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -42,6 +42,7 @@ Windows + 10.0.18362.0 From 661a2da5b5ed222d577579976f544270e75dbe52 Mon Sep 17 00:00:00 2001 From: Manodasan Wignarajah Date: Wed, 1 Jul 2020 14:06:27 -0700 Subject: [PATCH 34/38] Updating to include benchmarkcomponent from testwinrt. --- get_testwinrt.cmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/get_testwinrt.cmd b/get_testwinrt.cmd index 971973dc6..d78f9490d 100644 --- a/get_testwinrt.cmd +++ b/get_testwinrt.cmd @@ -12,7 +12,7 @@ git checkout -f master if ErrorLevel 1 popd & exit /b !ErrorLevel! git fetch -f if ErrorLevel 1 popd & exit /b !ErrorLevel! -git reset -q --hard 427f66c2cd0837e81005a840472b0ef1a1d8639d +git reset -q --hard 6d72afbcb51ab3981c6cd620d24954020f4d2bbc if ErrorLevel 1 popd & exit /b !ErrorLevel! echo Restoring Nuget ..\.nuget\nuget.exe restore From 8d8c3976375e2265f5b7fe6e004dab10fb8558b6 Mon Sep 17 00:00:00 2001 From: Manodasan Wignarajah Date: Wed, 1 Jul 2020 15:26:50 -0700 Subject: [PATCH 35/38] Fix absolute paths --- benchmark.cmd | 2 +- benchmark_winmd.cmd | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/benchmark.cmd b/benchmark.cmd index 7b2f42e7a..4ebba8bd6 100644 --- a/benchmark.cmd +++ b/benchmark.cmd @@ -1,2 +1,2 @@ msbuild Benchmarks\Benchmarks.csproj -t:restore -t:build /p:platform=x64 /p:configuration=release -dotnet S:\CsWinRT\Benchmarks\bin\x64\Release\netcoreapp2.0\Benchmarks.dll -filter * --runtimes netcoreapp2.0 netcoreapp3.1 netcoreapp5.0 \ No newline at end of file +dotnet %~dp0Benchmarks\bin\x64\Release\netcoreapp2.0\Benchmarks.dll -filter * --runtimes netcoreapp2.0 netcoreapp3.1 netcoreapp5.0 \ No newline at end of file diff --git a/benchmark_winmd.cmd b/benchmark_winmd.cmd index e2d5c03aa..feaa12298 100644 --- a/benchmark_winmd.cmd +++ b/benchmark_winmd.cmd @@ -1,4 +1,4 @@ msbuild Benchmarks\Benchmarks.csproj -t:restore -t:clean;rebuild /p:BenchmarkWinmdSupport=true /p:platform=x64 /p:configuration=release /p:TargetFramework=netcoreapp3.1 -S:\CsWinRT\Benchmarks\bin\x64\Release\netcoreapp3.1\Benchmarks.exe -filter * +%~dp0Benchmarks\bin\x64\Release\netcoreapp3.1\Benchmarks.exe -filter * rem Clean project to prevent mismatch scenarios with the typical benchmark.cmd scenario. msbuild Benchmarks\Benchmarks.csproj -t:restore -t:clean /p:BenchmarkWinmdSupport=true /p:platform=x64 /p:configuration=release /p:TargetFramework=netcoreapp3.1 >nul \ No newline at end of file From f677bbb88a47fc68742449622271851bfa1b80a0 Mon Sep 17 00:00:00 2001 From: Manodasan Wignarajah Date: Wed, 1 Jul 2020 19:02:57 -0700 Subject: [PATCH 36/38] Update readme and comments. --- Benchmarks/Program.cs | 8 ++++---- README.md | 6 +++++- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/Benchmarks/Program.cs b/Benchmarks/Program.cs index 03a29cf41..f1c3b4d24 100644 --- a/Benchmarks/Program.cs +++ b/Benchmarks/Program.cs @@ -33,8 +33,8 @@ public CustomConfig() // Test WinMD support #if NETCOREAPP3_1 - // BenchmarkDotNet will rebuild the project with a project reference when this exe is ran and - // in the same folder as it we have the application manifest binplaced which we want to embed in the new exe. + // BenchmarkDotNet will rebuild the project with a project reference to this project when this project's output exe is ran. It + // will be ran from the same folder as where we have the application manifest binplaced which we want to embed in the new exe. string manifestFile = Path.Combine( Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "Benchmarks.manifest"); @@ -62,8 +62,8 @@ public CustomConfig() // Custom tool chain for building the benchmark with WinMDs as we need to execute the // exe version of the benchmark rather than the dll version which runs under dotnet cli. - // This is becuase we need to be able to embed a side by side manifest for reg free winrt - // and to enable COM to find the WinMDs. + // This is because we need to be able to embed a side by side manifest for reg free winrt + // and we need COM to be able to find the WinMDs. private class NetCore3ToolChainWithNativeExecution : Toolchain { public NetCore3ToolChainWithNativeExecution() diff --git a/README.md b/README.md index 0836f9f0d..e1286a1df 100644 --- a/README.md +++ b/README.md @@ -117,12 +117,16 @@ The **/TestComponentCSharp** folder contains an implementation of a WinRT test c ## /Projections -The **/Projections** folder contains several projects for generating and building projections from the Windows SDK, WinUI, and Test metadata (produced by the TestWinRT and TestComponentCSharp projects). +The **/Projections** folder contains several projects for generating and building projections from the Windows SDK, WinUI, Benchmark (produced by the BenchmarkComponent project), and Test metadata (produced by the TestWinRT and TestComponentCSharp projects). ## /UnitTest The **/UnitTest** folder contains unit tests for validating the Windows SDK, WinUI, and Test projections generated above. All pull requests should ensure that this project executes without errors. +## /Benchmarks + +The **/Benchmarks** folder contains benchmarks written using BenchmarkDotNet to track the performance of scenarios in the generated projection. To run the benchmarks using the CsWinRT projection, run **benchmark.cmd**. To run the same benchmarks using the built-in WinMD support in NET Core 3.1 to compare against as a basline, run **benchmark_winmd.cmd**. + ## /WinUIDesktopSample The **/WinUIDesktopSample** contains an end-to-end sample app that uses the Windows SDK and WinUI projections generated above. From e686b736ced1f6277fd1a1b1d79e1183dfa394a7 Mon Sep 17 00:00:00 2001 From: Manodasan Wignarajah Date: Wed, 1 Jul 2020 19:26:17 -0700 Subject: [PATCH 37/38] Fix typo. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e1286a1df..f9e6ff868 100644 --- a/README.md +++ b/README.md @@ -125,7 +125,7 @@ The **/UnitTest** folder contains unit tests for validating the Windows SDK, Win ## /Benchmarks -The **/Benchmarks** folder contains benchmarks written using BenchmarkDotNet to track the performance of scenarios in the generated projection. To run the benchmarks using the CsWinRT projection, run **benchmark.cmd**. To run the same benchmarks using the built-in WinMD support in NET Core 3.1 to compare against as a basline, run **benchmark_winmd.cmd**. +The **/Benchmarks** folder contains benchmarks written using BenchmarkDotNet to track the performance of scenarios in the generated projection. To run the benchmarks using the CsWinRT projection, run **benchmark.cmd**. To run the same benchmarks using the built-in WinMD support in NET Core 3.1 to compare against as a baseline, run **benchmark_winmd.cmd**. ## /WinUIDesktopSample From 521b9579168ce7e7d8b53e87b75fd6508edf9caf Mon Sep 17 00:00:00 2001 From: Manodasan Wignarajah Date: Wed, 8 Jul 2020 15:15:26 -0700 Subject: [PATCH 38/38] PR feedback. --- Benchmarks/Program.cs | 3 +-- Projections/Benchmark/Benchmark.csproj | 1 - Projections/Test/Test.csproj | 1 - Projections/WinUI/WinUI.csproj | 1 - Projections/Windows/Windows.csproj | 1 - 5 files changed, 1 insertion(+), 6 deletions(-) diff --git a/Benchmarks/Program.cs b/Benchmarks/Program.cs index f1c3b4d24..89255f080 100644 --- a/Benchmarks/Program.cs +++ b/Benchmarks/Program.cs @@ -26,8 +26,7 @@ public CustomConfig() .WithPlatform(BenchmarkDotNet.Environments.Platform.X64) .WithArguments( new Argument[] { - new MsBuildArgument("/p:platform=x64"), - new MsBuildArgument("/p:MsAppxPackageTargets=%temp%\\EmptyMsAppxPackage.Targets") + new MsBuildArgument("/p:platform=x64") } ).AsDefault(); diff --git a/Projections/Benchmark/Benchmark.csproj b/Projections/Benchmark/Benchmark.csproj index 26aa10a43..02265c124 100644 --- a/Projections/Benchmark/Benchmark.csproj +++ b/Projections/Benchmark/Benchmark.csproj @@ -3,7 +3,6 @@ netstandard2.0;net5.0 x64;x86 - 10.0.18362.0 8 diff --git a/Projections/Test/Test.csproj b/Projections/Test/Test.csproj index 803485d94..399e05808 100644 --- a/Projections/Test/Test.csproj +++ b/Projections/Test/Test.csproj @@ -3,7 +3,6 @@ netstandard2.0;net5.0 x64;x86 - 10.0.18362.0 8 diff --git a/Projections/WinUI/WinUI.csproj b/Projections/WinUI/WinUI.csproj index 7d072ba81..7d5287727 100644 --- a/Projections/WinUI/WinUI.csproj +++ b/Projections/WinUI/WinUI.csproj @@ -3,7 +3,6 @@ netstandard2.0;net5.0 x64;x86 - 10.0.18362.0 8 diff --git a/Projections/Windows/Windows.csproj b/Projections/Windows/Windows.csproj index fd75e76b9..8d96377ee 100644 --- a/Projections/Windows/Windows.csproj +++ b/Projections/Windows/Windows.csproj @@ -3,7 +3,6 @@ netstandard2.0;net5.0 x64;x86 - 10.0.18362.0 8