From: Jeremy Koritzinsky Date: Mon, 12 Jun 2023 18:08:06 +0000 (-0700) Subject: Move System.Transactions.Local over to using source-generated COM instead of built... X-Git-Tag: accepted/tizen/unified/riscv/20231226.055536~1705 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=5c7be099662973f9520159e2434745891db15b7c;p=platform%2Fupstream%2Fdotnet%2Fruntime.git Move System.Transactions.Local over to using source-generated COM instead of built-in COM whenever possible. (#87351) Co-authored-by: Shay Rojansky --- diff --git a/src/libraries/System.Transactions.Local/System.Transactions.Local.sln b/src/libraries/System.Transactions.Local/System.Transactions.Local.sln index 6f3c8b9..38eaab6 100644 --- a/src/libraries/System.Transactions.Local/System.Transactions.Local.sln +++ b/src/libraries/System.Transactions.Local/System.Transactions.Local.sln @@ -1,4 +1,8 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.7.33711.456 +MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestUtilities", "..\Common\tests\TestUtilities\TestUtilities.csproj", "{B67D04B7-C5ED-44ED-8DB3-8AD788232A5C}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Collections", "..\System.Collections\ref\System.Collections.csproj", "{6D254833-6EC5-4E3E-96CE-1D97CD66B35F}" @@ -25,6 +29,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "gen", "gen", "{2ECC9D1A-2EF EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{9D6D84CE-3891-482B-B7C0-0089CF93CF45}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ComInterfaceGenerator", "..\System.Runtime.InteropServices\gen\ComInterfaceGenerator\ComInterfaceGenerator.csproj", "{75D2D615-58E5-41BB-9C57-FFC2F01B4931}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -67,20 +73,25 @@ Global {C5519C4C-69AF-4437-8594-D2A019119988}.Debug|Any CPU.Build.0 = Debug|Any CPU {C5519C4C-69AF-4437-8594-D2A019119988}.Release|Any CPU.ActiveCfg = Release|Any CPU {C5519C4C-69AF-4437-8594-D2A019119988}.Release|Any CPU.Build.0 = Release|Any CPU + {75D2D615-58E5-41BB-9C57-FFC2F01B4931}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {75D2D615-58E5-41BB-9C57-FFC2F01B4931}.Debug|Any CPU.Build.0 = Debug|Any CPU + {75D2D615-58E5-41BB-9C57-FFC2F01B4931}.Release|Any CPU.ActiveCfg = Release|Any CPU + {75D2D615-58E5-41BB-9C57-FFC2F01B4931}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution {B67D04B7-C5ED-44ED-8DB3-8AD788232A5C} = {E66BBFB5-F07D-4986-89C0-F0E395DD5BA1} - {C5519C4C-69AF-4437-8594-D2A019119988} = {E66BBFB5-F07D-4986-89C0-F0E395DD5BA1} {6D254833-6EC5-4E3E-96CE-1D97CD66B35F} = {B4E1F144-E017-4E02-8320-DB7467E42BF8} + {2A01A433-50B7-4CFA-AA76-CB51971535BB} = {2ECC9D1A-2EF1-4411-98D1-AFFCDAAF9D05} + {193FBAA0-BAE2-484A-BB0E-1ADDDC810FC9} = {2ECC9D1A-2EF1-4411-98D1-AFFCDAAF9D05} {8D9731A5-CB30-4AAA-9A3B-9C937352623F} = {B4E1F144-E017-4E02-8320-DB7467E42BF8} {7CC8FC26-F825-4B5D-9E38-6CE8382BEEAC} = {B4E1F144-E017-4E02-8320-DB7467E42BF8} {0C886713-72D7-43C7-A1BB-72CD0F8430D2} = {B4E1F144-E017-4E02-8320-DB7467E42BF8} - {2A01A433-50B7-4CFA-AA76-CB51971535BB} = {2ECC9D1A-2EF1-4411-98D1-AFFCDAAF9D05} - {193FBAA0-BAE2-484A-BB0E-1ADDDC810FC9} = {2ECC9D1A-2EF1-4411-98D1-AFFCDAAF9D05} {6BFF19CB-C412-4D12-AA55-68D61F69C4F7} = {9D6D84CE-3891-482B-B7C0-0089CF93CF45} + {C5519C4C-69AF-4437-8594-D2A019119988} = {E66BBFB5-F07D-4986-89C0-F0E395DD5BA1} + {75D2D615-58E5-41BB-9C57-FFC2F01B4931} = {2ECC9D1A-2EF1-4411-98D1-AFFCDAAF9D05} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {197B13C9-4EA6-408B-8EF6-B551B2A58A89} diff --git a/src/libraries/System.Transactions.Local/src/System.Transactions.Local.csproj b/src/libraries/System.Transactions.Local/src/System.Transactions.Local.csproj index 78e7ed3..5a7cc44 100644 --- a/src/libraries/System.Transactions.Local/src/System.Transactions.Local.csproj +++ b/src/libraries/System.Transactions.Local/src/System.Transactions.Local.csproj @@ -3,7 +3,7 @@ true true $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent) - CA1805;IDE0059;CS1591 + CA1805;IDE0059;CS1591;CS3016 $([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) @@ -44,6 +44,7 @@ + @@ -118,4 +119,7 @@ + + + diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/IPrepareInfo.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/IPrepareInfo.cs index 576f55f..70a23d2 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/IPrepareInfo.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/IPrepareInfo.cs @@ -2,14 +2,15 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; namespace System.Transactions.DtcProxyShim.DtcInterfaces; // https://docs.microsoft.com/previous-versions/windows/desktop/ms686533(v=vs.85) -[ComImport, Guid("80c7bfd0-87ee-11ce-8081-0080c758527e"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] -internal interface IPrepareInfo +[GeneratedComInterface, Guid("80c7bfd0-87ee-11ce-8081-0080c758527e"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] +internal partial interface IPrepareInfo { void GetPrepareInfoSize(out uint pcbPrepInfo); - void GetPrepareInfo([MarshalAs(UnmanagedType.LPArray), Out] byte[] pPrepInfo); + void GetPrepareInfo([MarshalAs(UnmanagedType.LPArray)] byte[] pPrepInfo); } diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/IResourceManager.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/IResourceManager.cs index 4cec70b..b10be08 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/IResourceManager.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/IResourceManager.cs @@ -2,12 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; namespace System.Transactions.DtcProxyShim.DtcInterfaces; // https://docs.microsoft.com/previous-versions/windows/desktop/ms681790(v=vs.85) -[ComImport, Guid(Guids.IID_IResourceManager), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] -internal interface IResourceManager +[GeneratedComInterface, Guid(Guids.IID_IResourceManager), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] +internal partial interface IResourceManager { internal void Enlist( [MarshalAs(UnmanagedType.Interface)] ITransaction pTransaction, @@ -20,7 +21,7 @@ internal interface IResourceManager [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] pPrepInfo, uint cbPrepInfom, uint lTimeout, - [MarshalAs(UnmanagedType.I4)] out OletxXactStat pXactStat); + out OletxXactStat pXactStat); void ReenlistmentComplete(); diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/IResourceManagerFactory2.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/IResourceManagerFactory2.cs index dd4777c..e29ed9a7 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/IResourceManagerFactory2.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/IResourceManagerFactory2.cs @@ -2,12 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; namespace System.Transactions.DtcProxyShim.DtcInterfaces; // https://docs.microsoft.com/previous-versions/windows/desktop/ms686489(v=vs.85) -[ComImport, Guid("6B369C21-FBD2-11d1-8F47-00C04F8EE57D"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] -internal interface IResourceManagerFactory2 +[GeneratedComInterface, Guid("6B369C21-FBD2-11d1-8F47-00C04F8EE57D"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] +internal partial interface IResourceManagerFactory2 { internal void Create( in Guid pguidRM, diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/IResourceManagerSink.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/IResourceManagerSink.cs index 0e87218..b39510b 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/IResourceManagerSink.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/IResourceManagerSink.cs @@ -2,12 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; namespace System.Transactions.DtcProxyShim.DtcInterfaces; // https://docs.microsoft.com/previous-versions/windows/desktop/ms686073(v=vs.85) -[ComImport, Guid("0D563181-DEFB-11CE-AED1-00AA0051E2C4"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] -internal interface IResourceManagerSink +[GeneratedComInterface, Guid("0D563181-DEFB-11CE-AED1-00AA0051E2C4"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] +internal partial interface IResourceManagerSink { void TMDown(); } diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITmNodeName.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITmNodeName.cs index 4816352..4b6b4df 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITmNodeName.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITmNodeName.cs @@ -2,12 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; namespace System.Transactions.DtcProxyShim.DtcInterfaces; // https://docs.microsoft.com/previous-versions/windows/desktop/ms687122(v=vs.85) -[ComImport, Guid("30274F88-6EE4-474e-9B95-7807BC9EF8CF"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] -internal interface ITmNodeName +[GeneratedComInterface, Guid("30274F88-6EE4-474e-9B95-7807BC9EF8CF"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] +internal partial interface ITmNodeName { internal void GetNodeNameSize(out uint pcbNodeNameSize); diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransaction.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransaction.cs index de54474..6a16212 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransaction.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransaction.cs @@ -2,16 +2,17 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; namespace System.Transactions.DtcProxyShim.DtcInterfaces; // https://docs.microsoft.com/previous-versions/windows/desktop/ms686531(v=vs.85) -[ComImport, Guid(Guids.IID_ITransaction), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] -internal interface ITransaction +[GeneratedComInterface, Guid(Guids.IID_ITransaction), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] +internal partial interface ITransaction { void Commit( [MarshalAs(UnmanagedType.Bool)] bool fRetaining, - [MarshalAs(UnmanagedType.U4)] OletxXacttc grfTC, + OletxXacttc grfTC, uint grfRM); void Abort( diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionCloner.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionCloner.cs index 3090333..3a513b6 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionCloner.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionCloner.cs @@ -2,16 +2,17 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; namespace System.Transactions.DtcProxyShim.DtcInterfaces; // https://docs.microsoft.com/previous-versions/windows/desktop/ms684377(v=vs.85) -[ComImport, Guid("02656950-2152-11d0-944C-00A0C905416E"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] -internal interface ITransactionCloner +[GeneratedComInterface, Guid("02656950-2152-11d0-944C-00A0C905416E"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] +internal partial interface ITransactionCloner { void Commit( [MarshalAs(UnmanagedType.Bool)] bool fRetainingt, - [MarshalAs(UnmanagedType.U4)] OletxXacttc grfTC, + OletxXacttc grfTC, uint grfRM); void Abort( diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionDispenser.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionDispenser.cs index d5ca436..8d0a1d7 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionDispenser.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionDispenser.cs @@ -2,21 +2,22 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; using System.Transactions.DtcProxyShim; using System.Transactions.Oletx; namespace System.Transactions.DtcProxyShim.DtcInterfaces; // https://docs.microsoft.com/previous-versions/windows/desktop/ms687604(v=vs.85) -[ComImport, Guid(Guids.IID_ITransactionDispenser), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] -internal interface ITransactionDispenser +[GeneratedComInterface, Guid(Guids.IID_ITransactionDispenser), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] +internal partial interface ITransactionDispenser { void GetOptionsObject([MarshalAs(UnmanagedType.Interface)] out ITransactionOptions ppOptions); void BeginTransaction( IntPtr punkOuter, - [MarshalAs(UnmanagedType.I4)] OletxTransactionIsolationLevel isoLevel, - [MarshalAs(UnmanagedType.I4)] OletxTransactionIsoFlags isoFlags, + OletxTransactionIsolationLevel isoLevel, + OletxTransactionIsoFlags isoFlags, [MarshalAs(UnmanagedType.Interface)] ITransactionOptions pOptions, [MarshalAs(UnmanagedType.Interface)] out ITransaction ppTransaction); } diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionEnlistmentAsync.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionEnlistmentAsync.cs index 8fb42b4..e5a2d36 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionEnlistmentAsync.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionEnlistmentAsync.cs @@ -2,12 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; namespace System.Transactions.DtcProxyShim.DtcInterfaces; // https://docs.microsoft.com/previous-versions/windows/desktop/ms686429(v=vs.85) -[ComImport, Guid("0fb15081-af41-11ce-bd2b-204c4f4f5020"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] -internal interface ITransactionEnlistmentAsync +[GeneratedComInterface, Guid("0fb15081-af41-11ce-bd2b-204c4f4f5020"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] +internal partial interface ITransactionEnlistmentAsync { void PrepareRequestDone(int hr, IntPtr pmk, IntPtr pboidReason); diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionExport.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionExport.cs index 75b6e7e..7fd2822 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionExport.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionExport.cs @@ -2,18 +2,19 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; namespace System.Transactions.DtcProxyShim.DtcInterfaces; // https://docs.microsoft.com/previous-versions/windows/desktop/ms678954(v=vs.85) -[ComImport, Guid("0141fda5-8fc0-11ce-bd18-204c4f4f5020"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] -internal interface ITransactionExport +[GeneratedComInterface, Guid("0141fda5-8fc0-11ce-bd18-204c4f4f5020"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] +internal partial interface ITransactionExport { void Export([MarshalAs(UnmanagedType.Interface)] ITransaction punkTransaction, out uint pcbTransactionCookie); void GetTransactionCookie( [MarshalAs(UnmanagedType.Interface)] ITransaction pITransaction, uint cbTransactionCookie, - [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1), Out] byte[] rgbTransactionCookie, + [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] rgbTransactionCookie, out uint pcbUsed); } diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionExportFactory.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionExportFactory.cs index 0369283..672f457 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionExportFactory.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionExportFactory.cs @@ -2,12 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; namespace System.Transactions.DtcProxyShim.DtcInterfaces; // https://docs.microsoft.com/previous-versions/windows/desktop/ms686771(v=vs.85) -[ComImport, Guid("E1CF9B53-8745-11ce-A9BA-00AA006C3706"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] -internal interface ITransactionExportFactory +[GeneratedComInterface, Guid("E1CF9B53-8745-11ce-A9BA-00AA006C3706"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] +internal partial interface ITransactionExportFactory { void GetRemoteClassId(out Guid pclsid); diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionImport.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionImport.cs index a7095a6..57d4656 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionImport.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionImport.cs @@ -2,12 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; namespace System.Transactions.DtcProxyShim.DtcInterfaces; // https://docs.microsoft.com/previous-versions/windows/desktop/ms681296(v=vs.85) -[ComImport, Guid("E1CF9B5A-8745-11ce-A9BA-00AA006C3706"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] -internal interface ITransactionImport +[GeneratedComInterface, Guid("E1CF9B5A-8745-11ce-A9BA-00AA006C3706"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] +internal partial interface ITransactionImport { void Import( uint cbTransactionCookie, diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionImportWhereabouts.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionImportWhereabouts.cs index 28f932e..58b3d2f 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionImportWhereabouts.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionImportWhereabouts.cs @@ -2,17 +2,18 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; namespace System.Transactions.DtcProxyShim.DtcInterfaces; // https://docs.microsoft.com/previous-versions/windows/desktop/ms682783(v=vs.85) -[ComImport, Guid("0141fda4-8fc0-11ce-bd18-204c4f4f5020"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] -internal interface ITransactionImportWhereabouts +[GeneratedComInterface, Guid("0141fda4-8fc0-11ce-bd18-204c4f4f5020"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] +internal partial interface ITransactionImportWhereabouts { internal void GetWhereaboutsSize(out uint pcbSize); internal void GetWhereabouts( uint cbWhereabouts, - [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0), Out] byte[] rgbWhereabouts, + [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] byte[] rgbWhereabouts, out uint pcbUsed); } diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionOptions.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionOptions.cs index 6635861..3a894ec 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionOptions.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionOptions.cs @@ -2,12 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; namespace System.Transactions.DtcProxyShim.DtcInterfaces; // https://docs.microsoft.com/previous-versions/windows/desktop/ms686489(v=vs.85) -[ComImport, Guid("3A6AD9E0-23B9-11cf-AD60-00AA00A74CCD"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] -internal interface ITransactionOptions +[GeneratedComInterface, Guid("3A6AD9E0-23B9-11cf-AD60-00AA00A74CCD"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] +internal partial interface ITransactionOptions { void SetOptions(Xactopt pOptions); diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionOutcomeEvents.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionOutcomeEvents.cs index 3627730..6d26bbb 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionOutcomeEvents.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionOutcomeEvents.cs @@ -2,10 +2,10 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Runtime.InteropServices; -using System.Transactions.Oletx; namespace System.Transactions.DtcProxyShim.DtcInterfaces; +// Keep this type as a ComImport type as it is used with IConnectionPointContainer (and as a result needs to use built-in COM). // https://docs.microsoft.com/previous-versions/windows/desktop/ms686465(v=vs.85) [ComImport, Guid("3A6AD9E2-23B9-11cf-AD60-00AA00A74CCD"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface ITransactionOutcomeEvents @@ -22,7 +22,7 @@ internal interface ITransactionOutcomeEvents int hresult); void HeuristicDecision( - [MarshalAs(UnmanagedType.U4)] OletxTransactionHeuristic dwDecision, + OletxTransactionHeuristic dwDecision, IntPtr pboidReason, int hresult); diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionPhase0EnlistmentAsync.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionPhase0EnlistmentAsync.cs index ca6872f..c77761e 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionPhase0EnlistmentAsync.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/DtcInterfaces/ITransactionPhase0EnlistmentAsync.cs @@ -2,12 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; namespace System.Transactions.DtcProxyShim.DtcInterfaces; // https://docs.microsoft.com/previous-versions/windows/desktop/ms685087(v=vs.85). _eventHandle = notificationEventHandle; // https://docs.microsoft.com/previous-versions/windows/desktop/ms678898(v=vs.85) - [DllImport(Interop.Libraries.Xolehlp, CharSet = CharSet.Unicode, ExactSpelling = true, PreserveSig = false)] + [LibraryImport(Interop.Libraries.Xolehlp, StringMarshalling = StringMarshalling.Utf16)] [RequiresUnreferencedCode(TransactionManager.DistributedTransactionTrimmingWarning)] - private static extern void DtcGetTransactionManagerExW( + private static unsafe partial int DtcGetTransactionManagerExW( [MarshalAs(UnmanagedType.LPWStr)] string? pszHost, [MarshalAs(UnmanagedType.LPWStr)] string? pszTmName, in Guid riid, int grfOptions, - object? pvConfigPararms, + void* pvConfigPararms, [MarshalAs(UnmanagedType.Interface)] out ITransactionDispenser ppvObject); [RequiresUnreferencedCode(TransactionManager.DistributedTransactionTrimmingWarning)] - private static void DtcGetTransactionManager(string? nodeName, out ITransactionDispenser localDispenser) => - DtcGetTransactionManagerExW(nodeName, null, Guids.IID_ITransactionDispenser_Guid, 0, null, out localDispenser); + private static unsafe void DtcGetTransactionManager(string? nodeName, out ITransactionDispenser localDispenser) => Marshal.ThrowExceptionForHR(DtcGetTransactionManagerExW(nodeName, null, Guids.IID_ITransactionDispenser_Guid, 0, null, out localDispenser)); public void ConnectToProxy( string? nodeName, @@ -329,7 +328,7 @@ internal sealed class DtcProxyShimFactory transaction.GetTransactionInfo(out OletxXactTransInfo xactInfo); // Register for outcome events. - var pContainer = (IConnectionPointContainer)transaction; + var pContainer = (IConnectionPointContainer)TransactionInterop.GetDtcTransaction(transaction); var guid = Guids.IID_ITransactionOutcomeEvents_Guid; pContainer.FindConnectionPoint(ref guid, out IConnectionPoint? pConnPoint); pConnPoint!.Advise(transactionNotifyShim, out int connPointCookie); diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/EnlistmentNotifyShim.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/EnlistmentNotifyShim.cs index b8f46ce..ad3beff 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/EnlistmentNotifyShim.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/EnlistmentNotifyShim.cs @@ -2,13 +2,15 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Runtime.InteropServices.Marshalling; using System.Threading; using System.Transactions.DtcProxyShim.DtcInterfaces; using System.Transactions.Oletx; namespace System.Transactions.DtcProxyShim; -internal sealed class EnlistmentNotifyShim : NotificationShimBase, ITransactionResourceAsync +[GeneratedComClass] +internal sealed partial class EnlistmentNotifyShim : NotificationShimBase, ITransactionResourceAsync { internal ITransactionEnlistmentAsync? EnlistmentAsync; diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/NativeEnums.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/NativeEnums.cs index f852af7..a8e7de4 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/NativeEnums.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/NativeEnums.cs @@ -115,7 +115,7 @@ internal enum OletxTransactionHeuristic : uint XACTHEURISTIC_DANGER = 4 } -internal enum OletxXactStat +internal enum OletxXactStat : int { XACTSTAT_NONE = 0, XACTSTAT_OPENNORMAL = 0x1, diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/Phase0NotifyShim.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/Phase0NotifyShim.cs index dc2d192..4676b7a 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/Phase0NotifyShim.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/Phase0NotifyShim.cs @@ -1,12 +1,14 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Runtime.InteropServices.Marshalling; using System.Transactions.DtcProxyShim.DtcInterfaces; using System.Transactions.Oletx; namespace System.Transactions.DtcProxyShim; -internal sealed class Phase0NotifyShim : NotificationShimBase, ITransactionPhase0NotifyAsync +[GeneratedComClass] +internal sealed partial class Phase0NotifyShim : NotificationShimBase, ITransactionPhase0NotifyAsync { internal Phase0NotifyShim(DtcProxyShimFactory shimFactory, object enlistmentIdentifier) : base(shimFactory, enlistmentIdentifier) diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/ResourceManagerNotifyShim.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/ResourceManagerNotifyShim.cs index 53ac780..edeeac1 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/ResourceManagerNotifyShim.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/ResourceManagerNotifyShim.cs @@ -3,10 +3,12 @@ using System.Transactions.Oletx; using System.Transactions.DtcProxyShim.DtcInterfaces; +using System.Runtime.InteropServices.Marshalling; namespace System.Transactions.DtcProxyShim; -internal sealed class ResourceManagerNotifyShim : NotificationShimBase, IResourceManagerSink +[GeneratedComClass] +internal sealed partial class ResourceManagerNotifyShim : NotificationShimBase, IResourceManagerSink { internal ResourceManagerNotifyShim( DtcProxyShimFactory shimFactory, diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/TransactionShim.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/TransactionShim.cs index 0c428d6..741b997 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/TransactionShim.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/TransactionShim.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; using System.Transactions.DtcProxyShim.DtcInterfaces; using System.Transactions.Oletx; @@ -52,12 +54,12 @@ internal sealed class TransactionShim cookieBuffer = buffer; } - public void GetITransactionNative(out IDtcTransaction transactionNative) + public void GetITransactionNative(out ITransaction transactionNative) { var cloner = (ITransactionCloner)Transaction; cloner.CloneWithCommitDisabled(out ITransaction returnTransaction); - transactionNative = (IDtcTransaction)returnTransaction; + transactionNative = returnTransaction; } public unsafe byte[] GetPropagationToken() diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/VoterNotifyShim.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/VoterNotifyShim.cs index fad9958..206795f 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/VoterNotifyShim.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/VoterNotifyShim.cs @@ -2,12 +2,14 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; using System.Transactions.DtcProxyShim.DtcInterfaces; using System.Transactions.Oletx; namespace System.Transactions.DtcProxyShim; -internal sealed class VoterNotifyShim : NotificationShimBase, ITransactionVoterNotifyAsync2 +[GeneratedComClass] +internal sealed partial class VoterNotifyShim : NotificationShimBase, ITransactionVoterNotifyAsync2 { internal VoterNotifyShim(DtcProxyShimFactory shimFactory, object enlistmentIdentifier) : base(shimFactory, enlistmentIdentifier) diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/Xactopt.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/Xactopt.cs index 2f6bac5..338df45 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/Xactopt.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/DtcProxyShim/Xactopt.cs @@ -1,12 +1,14 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; +using System.Text; namespace System.Transactions.DtcProxyShim; // https://docs.microsoft.com/previous-versions/windows/desktop/ms679195(v=vs.85) +[NativeMarshalling(typeof(Marshaller))] [StructLayout(LayoutKind.Sequential)] internal struct Xactopt { @@ -17,4 +19,32 @@ internal struct Xactopt [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 40)] public string SzDescription; + + [CustomMarshaller(typeof(Xactopt), MarshalMode.ManagedToUnmanagedIn, typeof(Marshaller))] + [CustomMarshaller(typeof(Xactopt), MarshalMode.UnmanagedToManagedIn, typeof(Marshaller))] + internal static class Marshaller + { + internal unsafe struct XactoptNative + { + public uint UlTimeout; + + public fixed byte SzDescription[40]; + } + + public static unsafe XactoptNative ConvertToUnmanaged(Xactopt managed) + { + XactoptNative native = new() + { + UlTimeout = managed.UlTimeout, + }; + + // Usage of Xactopt never passes non-ASCII chars, so we can ignore them. + Encoding.ASCII.TryGetBytes(managed.SzDescription, new Span(native.SzDescription, 40), out _); + + return native; + } + + public static unsafe Xactopt ConvertToManaged(XactoptNative unmanaged) + => new(unmanaged.UlTimeout, Encoding.ASCII.GetString(unmanaged.SzDescription, 40)); + } } diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/TransactionInterop.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/TransactionInterop.cs index e2da43f..3c5ecb5 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/TransactionInterop.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/TransactionInterop.cs @@ -3,6 +3,7 @@ using System.Diagnostics; using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; using System.Transactions.DtcProxyShim; using System.Transactions.DtcProxyShim.DtcInterfaces; using System.Transactions.Oletx; @@ -278,14 +279,21 @@ namespace System.Transactions etwLog.MethodEnter(TraceSourceType.TraceSourceOleTx, $"{nameof(TransactionInterop)}.{nameof(GetDtcTransaction)}"); } - IDtcTransaction? transactionNative; + IDtcTransaction? transactionComObject; // First, make sure we are working with an OletxTransaction. OletxTransaction oletxTx = ConvertToOletxTransaction(transaction); try { - oletxTx.RealOletxTransaction.TransactionShim.GetITransactionNative(out transactionNative); + oletxTx.RealOletxTransaction.TransactionShim.GetITransactionNative(out ITransaction transactionNative); + + ComWrappers.TryGetComInstance(transactionNative, out IntPtr transactionNativePtr); + + transactionComObject = (IDtcTransaction)Marshal.GetObjectForIUnknown(transactionNativePtr); + Marshal.SetComObjectData(transactionComObject, typeof(ITransaction), transactionNative); + + Marshal.Release(transactionNativePtr); } catch (COMException comException) { @@ -298,6 +306,17 @@ namespace System.Transactions etwLog.MethodExit(TraceSourceType.TraceSourceOleTx, $"{nameof(TransactionInterop)}.{nameof(GetDtcTransaction)}"); } + return transactionComObject; + } + + internal static IDtcTransaction GetDtcTransaction(ITransaction transaction) + { + ComWrappers.TryGetComInstance(transaction, out IntPtr transactionNativePtr); + + var transactionNative = (IDtcTransaction)Marshal.GetObjectForIUnknown(transactionNativePtr); + Marshal.SetComObjectData(transactionNative, typeof(ITransaction), transaction); + + Marshal.Release(transactionNativePtr); return transactionNative; } @@ -320,12 +339,9 @@ namespace System.Transactions RealOletxTransaction? realTx = null; OletxTransaction? oleTx = null; - // Let's get the guid of the transaction from the proxy to see if we already have an object. - if (transactionNative is not ITransaction myTransactionNative) - { - throw new ArgumentException(SR.InvalidArgument, nameof(transactionNative)); - } + ITransaction myTransactionNative = GetITransactionFromIDtcTransaction(transactionNative); + // Let's get the guid of the transaction from the proxy to see if we already have an object. OletxXactTransInfo xactInfo; try { @@ -419,6 +435,32 @@ namespace System.Transactions return transaction; } + internal static ITransaction GetITransactionFromIDtcTransaction(IDtcTransaction transactionNative) + { + if (Marshal.GetComObjectData(transactionNative, typeof(ITransaction)) is not ITransaction myTransactionNative) + { + unsafe + { + nint unknown = Marshal.GetIUnknownForObject(transactionNative); + Guid iid = Guids.IID_ITransaction_Guid; + if (Marshal.QueryInterface(unknown, ref iid, out IntPtr transactionNativePtr) == 0) + { + Marshal.Release(unknown); + myTransactionNative = ComInterfaceMarshaller.ConvertToManaged((void*)transactionNativePtr)!; + Marshal.SetComObjectData(transactionNative, typeof(ITransaction), myTransactionNative); + Marshal.Release(transactionNativePtr); + } + else + { + Marshal.Release(unknown); + throw new ArgumentException(SR.InvalidArgument, nameof(transactionNative)); + } + } + } + + return myTransactionNative; + } + public static byte[] GetWhereabouts() { TransactionsEtwProvider etwLog = TransactionsEtwProvider.Log;