From 24379873f589cff33965f1104041f61c0c4503e0 Mon Sep 17 00:00:00 2001 From: Sean Hall Date: Sun, 22 Dec 2019 10:31:33 +1100 Subject: Move the responsibility of wrapping the binary interfaces from mbahost to the new mbanative dll of WixToolset.Mba.Core. --- src/WixToolset.Mba.Core/BalUtil.cs | 22 ++++ .../BaseBootstrapperApplicationFactory.cs | 28 ++++- .../BootstrapperApplicationFactory.cs | 14 ++- .../IBootstrapperApplicationFactory.cs | 28 ++++- src/WixToolset.Mba.Core/WixToolset.Mba.Core.csproj | 1 + src/WixToolset.Mba.Core/WixToolset.Mba.Core.nuspec | 4 +- .../build/net20/WixToolset.Mba.Core.props | 11 ++ src/balutil/balutil.vcxproj | 6 +- src/balutil/inc/IBootstrapperApplicationFactory.h | 5 +- src/balutil/packages.config | 2 +- src/mbanative/mbanative.cpp | 29 ++++++ src/mbanative/mbanative.def | 6 ++ src/mbanative/mbanative.vcxproj | 76 ++++++++++++++ src/mbanative/packages.config | 6 ++ src/mbanative/precomp.cpp | 3 + src/mbanative/precomp.h | 15 +++ .../BaseBootstrapperApplicationFactoryFixture.cs | 113 +++++++++++++++++++++ .../WixToolsetTest.Mba.Core.csproj | 29 ++++++ .../WixToolsetTest.Mba.Core.v3.ncrunchproject | 5 + 19 files changed, 381 insertions(+), 22 deletions(-) create mode 100644 src/WixToolset.Mba.Core/BalUtil.cs create mode 100644 src/WixToolset.Mba.Core/build/net20/WixToolset.Mba.Core.props create mode 100644 src/mbanative/mbanative.cpp create mode 100644 src/mbanative/mbanative.def create mode 100644 src/mbanative/mbanative.vcxproj create mode 100644 src/mbanative/packages.config create mode 100644 src/mbanative/precomp.cpp create mode 100644 src/mbanative/precomp.h create mode 100644 src/test/WixToolsetTest.Mba.Core/BaseBootstrapperApplicationFactoryFixture.cs create mode 100644 src/test/WixToolsetTest.Mba.Core/WixToolsetTest.Mba.Core.csproj create mode 100644 src/test/WixToolsetTest.Mba.Core/WixToolsetTest.Mba.Core.v3.ncrunchproject (limited to 'src') diff --git a/src/WixToolset.Mba.Core/BalUtil.cs b/src/WixToolset.Mba.Core/BalUtil.cs new file mode 100644 index 00000000..f478eca4 --- /dev/null +++ b/src/WixToolset.Mba.Core/BalUtil.cs @@ -0,0 +1,22 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + +namespace WixToolset.Mba.Core +{ + using System; + using System.Runtime.InteropServices; + + internal static class BalUtil + { + [DllImport("mbanative.dll", ExactSpelling = true, PreserveSig = false)] + internal static extern IBootstrapperEngine InitializeFromCreateArgs( + IntPtr pArgs, + ref Command pCommand + ); + + [DllImport("mbanative.dll", ExactSpelling = true)] + internal static extern void StoreBAInCreateResults( + IntPtr pResults, + [MarshalAs(UnmanagedType.Interface)] IBootstrapperApplication pBA + ); + } +} diff --git a/src/WixToolset.Mba.Core/BaseBootstrapperApplicationFactory.cs b/src/WixToolset.Mba.Core/BaseBootstrapperApplicationFactory.cs index 20151b71..264733ac 100644 --- a/src/WixToolset.Mba.Core/BaseBootstrapperApplicationFactory.cs +++ b/src/WixToolset.Mba.Core/BaseBootstrapperApplicationFactory.cs @@ -2,15 +2,35 @@ namespace WixToolset.Mba.Core { + using System; + using System.Runtime.InteropServices; + public abstract class BaseBootstrapperApplicationFactory : IBootstrapperApplicationFactory { - public IBootstrapperApplication Create(IBootstrapperEngine pEngine, ref Command command) + public void Create(IntPtr pArgs, IntPtr pResults) { - IEngine engine = new Engine(pEngine); - IBootstrapperCommand bootstrapperCommand = command.GetBootstrapperCommand(); - return this.Create(engine, bootstrapperCommand); + InitializeFromCreateArgs(pArgs, out var engine, out var bootstrapperCommand); + + var ba = this.Create(engine, bootstrapperCommand); + StoreBAInCreateResults(pResults, ba); } protected abstract IBootstrapperApplication Create(IEngine engine, IBootstrapperCommand bootstrapperCommand); + + public static void InitializeFromCreateArgs(IntPtr pArgs, out IEngine engine, out IBootstrapperCommand bootstrapperCommand) + { + Command pCommand = new Command + { + cbSize = Marshal.SizeOf(typeof(Command)) + }; + var pEngine = BalUtil.InitializeFromCreateArgs(pArgs, ref pCommand); + engine = new Engine(pEngine); + bootstrapperCommand = pCommand.GetBootstrapperCommand(); + } + + public static void StoreBAInCreateResults(IntPtr pResults, IBootstrapperApplication ba) + { + BalUtil.StoreBAInCreateResults(pResults, ba); + } } } diff --git a/src/WixToolset.Mba.Core/BootstrapperApplicationFactory.cs b/src/WixToolset.Mba.Core/BootstrapperApplicationFactory.cs index 968c6336..55f0e83b 100644 --- a/src/WixToolset.Mba.Core/BootstrapperApplicationFactory.cs +++ b/src/WixToolset.Mba.Core/BootstrapperApplicationFactory.cs @@ -8,7 +8,7 @@ namespace WixToolset.Mba.Core using System.Runtime.InteropServices; /// - /// Entry point for the MBA host to create and return the IBootstrapperApplication implementation to the engine. + /// Entry point for the MBA host to create and return the BA to the engine. /// [ClassInterface(ClassInterfaceType.None)] public sealed class BootstrapperApplicationFactory : MarshalByRefObject, IBootstrapperApplicationFactory @@ -21,14 +21,13 @@ namespace WixToolset.Mba.Core } /// - /// Loads the bootstrapper application assembly and creates an instance of the IBootstrapperApplication. + /// Loads the bootstrapper application assembly and calls its IBootstrapperApplicationFactory.Create method. /// - /// IBootstrapperEngine provided for the bootstrapper application. - /// Command line for the bootstrapper application. - /// Bootstrapper application via interface. + /// Pointer to BOOTSTRAPPER_CREATE_ARGS struct. + /// Pointer to BOOTSTRAPPER_CREATE_RESULTS struct. /// The bootstrapper application assembly /// does not define the . - public IBootstrapperApplication Create(IBootstrapperEngine pEngine, ref Command command) + public void Create(IntPtr pArgs, IntPtr pResults) { // Get the wix.boostrapper section group to get the name of the bootstrapper application assembly to host. var section = ConfigurationManager.GetSection("wix.bootstrapper/host") as HostSection; @@ -45,8 +44,7 @@ namespace WixToolset.Mba.Core throw new InvalidBootstrapperApplicationFactoryException(); } - var ba = baFactory.Create(pEngine, ref command); - return ba; + baFactory.Create(pArgs, pResults); } /// diff --git a/src/WixToolset.Mba.Core/IBootstrapperApplicationFactory.cs b/src/WixToolset.Mba.Core/IBootstrapperApplicationFactory.cs index f5d4c705..700f0888 100644 --- a/src/WixToolset.Mba.Core/IBootstrapperApplicationFactory.cs +++ b/src/WixToolset.Mba.Core/IBootstrapperApplicationFactory.cs @@ -12,9 +12,9 @@ namespace WixToolset.Mba.Core [GeneratedCodeAttribute("WixToolset.Bootstrapper.InteropCodeGenerator", "1.0.0.0")] public interface IBootstrapperApplicationFactory { - IBootstrapperApplication Create( - [MarshalAs(UnmanagedType.Interface)] IBootstrapperEngine pEngine, - ref Command command + void Create( + IntPtr pArgs, + IntPtr pResults ); } @@ -23,6 +23,7 @@ namespace WixToolset.Mba.Core [GeneratedCodeAttribute("WixToolset.Bootstrapper.InteropCodeGenerator", "1.0.0.0")] public struct Command { + [MarshalAs(UnmanagedType.I4)] internal int cbSize; [MarshalAs(UnmanagedType.U4)] private readonly LaunchAction action; [MarshalAs(UnmanagedType.U4)] private readonly Display display; [MarshalAs(UnmanagedType.U4)] private readonly Restart restart; @@ -49,4 +50,25 @@ namespace WixToolset.Mba.Core this.wzLayoutDirectory); } } + + [Serializable] + [StructLayout(LayoutKind.Sequential)] + [GeneratedCodeAttribute("WixToolset.Bootstrapper.InteropCodeGenerator", "1.0.0.0")] + public struct BootstrapperCreateArgs + { + [MarshalAs(UnmanagedType.I4)] public readonly int cbSize; + [MarshalAs(UnmanagedType.I8)] public readonly long qwEngineAPIVersion; + public readonly IntPtr pfnBootstrapperEngineProc; + public readonly IntPtr pvBootstrapperEngineProcContext; + public readonly IntPtr pCommand; + + public BootstrapperCreateArgs(long version, IntPtr pEngineProc, IntPtr pEngineContext, IntPtr pCommand) + { + this.cbSize = Marshal.SizeOf(typeof(BootstrapperCreateArgs)); + this.qwEngineAPIVersion = version; + this.pfnBootstrapperEngineProc = pEngineProc; + this.pvBootstrapperEngineProcContext = pEngineContext; + this.pCommand = pCommand; + } + } } diff --git a/src/WixToolset.Mba.Core/WixToolset.Mba.Core.csproj b/src/WixToolset.Mba.Core/WixToolset.Mba.Core.csproj index 05d042c3..4b14a545 100644 --- a/src/WixToolset.Mba.Core/WixToolset.Mba.Core.csproj +++ b/src/WixToolset.Mba.Core/WixToolset.Mba.Core.csproj @@ -23,6 +23,7 @@ $(DefineConstants);TRACE + diff --git a/src/WixToolset.Mba.Core/WixToolset.Mba.Core.nuspec b/src/WixToolset.Mba.Core/WixToolset.Mba.Core.nuspec index 04eee9ec..bbac204f 100644 --- a/src/WixToolset.Mba.Core/WixToolset.Mba.Core.nuspec +++ b/src/WixToolset.Mba.Core/WixToolset.Mba.Core.nuspec @@ -7,7 +7,7 @@ WiX Toolset Team https://licenses.nuget.org/MS-RL - https://github.com/wixtoolset/BootstrapperCore + https://github.com/wixtoolset/balutil false $description$ $copyright$ @@ -15,6 +15,8 @@ + + diff --git a/src/WixToolset.Mba.Core/build/net20/WixToolset.Mba.Core.props b/src/WixToolset.Mba.Core/build/net20/WixToolset.Mba.Core.props new file mode 100644 index 00000000..c0018e0d --- /dev/null +++ b/src/WixToolset.Mba.Core/build/net20/WixToolset.Mba.Core.props @@ -0,0 +1,11 @@ + + + + + + $(MSBuildThisFileDirectory)x86\mbanative.dll + + + + + diff --git a/src/balutil/balutil.vcxproj b/src/balutil/balutil.vcxproj index 42aa909e..9d7dc0a5 100644 --- a/src/balutil/balutil.vcxproj +++ b/src/balutil/balutil.vcxproj @@ -2,7 +2,7 @@ - + @@ -70,7 +70,9 @@ + + @@ -88,7 +90,7 @@ 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/src/balutil/inc/IBootstrapperApplicationFactory.h b/src/balutil/inc/IBootstrapperApplicationFactory.h index e29c23bc..fd603e50 100644 --- a/src/balutil/inc/IBootstrapperApplicationFactory.h +++ b/src/balutil/inc/IBootstrapperApplicationFactory.h @@ -7,8 +7,7 @@ DECLARE_INTERFACE_IID_(IBootstrapperApplicationFactory, IUnknown, "2965A12F-AC7B-43A0-85DF-E4B2168478A4") { STDMETHOD(Create)( - __in IBootstrapperEngine* pEngine, - __in const BOOTSTRAPPER_COMMAND *pCommand, - __out IBootstrapperApplication **ppApplication + __in const BOOTSTRAPPER_CREATE_ARGS* pArgs, + __inout BOOTSTRAPPER_CREATE_RESULTS *pResults ); }; diff --git a/src/balutil/packages.config b/src/balutil/packages.config index 769c5a6e..d747d6a9 100644 --- a/src/balutil/packages.config +++ b/src/balutil/packages.config @@ -1,6 +1,6 @@  - + \ No newline at end of file diff --git a/src/mbanative/mbanative.cpp b/src/mbanative/mbanative.cpp new file mode 100644 index 00000000..745b50e7 --- /dev/null +++ b/src/mbanative/mbanative.cpp @@ -0,0 +1,29 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + +#include "precomp.h" +#include "BalBaseBootstrapperApplicationProc.h" + +extern "C" HRESULT WINAPI InitializeFromCreateArgs( + __in const BOOTSTRAPPER_CREATE_ARGS* pArgs, + __inout BOOTSTRAPPER_COMMAND* pCommand, + __out IBootstrapperEngine** ppEngine + ) +{ + HRESULT hr = S_OK; + + hr = BalInitializeFromCreateArgs(pArgs, ppEngine); + ExitOnFailure(hr, "Failed to initialize Bal."); + + memcpy_s(pCommand, pCommand->cbSize, pArgs->pCommand, pArgs->pCommand->cbSize); +LExit: + return hr; +} + +extern "C" void WINAPI StoreBAInCreateResults( + __inout BOOTSTRAPPER_CREATE_RESULTS* pResults, + __in IBootstrapperApplication* pBA + ) +{ + pResults->pfnBootstrapperApplicationProc = BalBaseBootstrapperApplicationProc; + pResults->pvBootstrapperApplicationProcContext = pBA; +} diff --git a/src/mbanative/mbanative.def b/src/mbanative/mbanative.def new file mode 100644 index 00000000..bd366ac7 --- /dev/null +++ b/src/mbanative/mbanative.def @@ -0,0 +1,6 @@ +; Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + + +EXPORTS + InitializeFromCreateArgs + StoreBAInCreateResults diff --git a/src/mbanative/mbanative.vcxproj b/src/mbanative/mbanative.vcxproj new file mode 100644 index 00000000..5ec21f74 --- /dev/null +++ b/src/mbanative/mbanative.vcxproj @@ -0,0 +1,76 @@ + + + + + + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + {665E0441-17F9-4105-B202-EDF274657F6E} + DynamicLibrary + v141 + Unicode + mbanative + mbanative.def + + + + + + + + ..\balutil\inc + balutil.lib + + + + + + Create + + + + + + + + + + + + + + + + + + + + + + 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/src/mbanative/packages.config b/src/mbanative/packages.config new file mode 100644 index 00000000..d37b6def --- /dev/null +++ b/src/mbanative/packages.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/mbanative/precomp.cpp b/src/mbanative/precomp.cpp new file mode 100644 index 00000000..37664a1c --- /dev/null +++ b/src/mbanative/precomp.cpp @@ -0,0 +1,3 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + +#include "precomp.h" diff --git a/src/mbanative/precomp.h b/src/mbanative/precomp.h new file mode 100644 index 00000000..54d8cb08 --- /dev/null +++ b/src/mbanative/precomp.h @@ -0,0 +1,15 @@ +#pragma once +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + + +#include +#include + +#include + +#include "BootstrapperEngine.h" +#include "BootstrapperApplication.h" +#include "IBootstrapperEngine.h" +#include "IBootstrapperApplication.h" + +#include "balutil.h" diff --git a/src/test/WixToolsetTest.Mba.Core/BaseBootstrapperApplicationFactoryFixture.cs b/src/test/WixToolsetTest.Mba.Core/BaseBootstrapperApplicationFactoryFixture.cs new file mode 100644 index 00000000..12483ddf --- /dev/null +++ b/src/test/WixToolsetTest.Mba.Core/BaseBootstrapperApplicationFactoryFixture.cs @@ -0,0 +1,113 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + +namespace WixToolsetTest.Util +{ + using System; + using System.Runtime.InteropServices; + using WixToolset.Mba.Core; + using Xunit; + + public class BaseBootstrapperApplicationFactoryFixture + { + [Fact] + public void CanCreateBA() + { + var command = new TestCommand + { + action = LaunchAction.Install, + cbSize = Marshal.SizeOf(typeof(TestCommand)), + display = Display.Full, + wzCommandLine = "this \"is a\" test", + }; + var pCommand = Marshal.AllocHGlobal(command.cbSize); + try + { + Marshal.StructureToPtr(command, pCommand, false); + var createArgs = new BootstrapperCreateArgs(0, IntPtr.Zero, IntPtr.Zero, pCommand); + var pArgs = Marshal.AllocHGlobal(createArgs.cbSize); + try + { + Marshal.StructureToPtr(createArgs, pArgs, false); + var createResults = new TestCreateResults + { + cbSize = Marshal.SizeOf(), + }; + var pResults = Marshal.AllocHGlobal(createResults.cbSize); + try + { + var baFactory = new TestBAFactory(); + baFactory.Create(pArgs, pResults); + + createResults = Marshal.PtrToStructure(pResults); + Assert.Equal(baFactory.BA, createResults.pBA); + Assert.Equal(baFactory.BA.Command.Action, command.action); + Assert.Equal(baFactory.BA.Command.Display, command.display); + Assert.Equal(baFactory.BA.Command.CommandLineArgs, new string[] { "this", "is a", "test" }); + } + finally + { + Marshal.FreeHGlobal(pResults); + } + } + finally + { + Marshal.FreeHGlobal(pArgs); + } + } + finally + { + Marshal.FreeHGlobal(pCommand); + } + } + + internal class TestBAFactory : BaseBootstrapperApplicationFactory + { + public TestBA BA { get; private set; } + + protected override IBootstrapperApplication Create(IEngine engine, IBootstrapperCommand bootstrapperCommand) + { + this.BA = new TestBA(engine, bootstrapperCommand); + return this.BA; + } + } + + internal class TestBA : BootstrapperApplication + { + public IBootstrapperCommand Command { get; } + + public TestBA(IEngine engine, IBootstrapperCommand command) + : base(engine) + { + this.Command = command; + } + + protected override void Run() + { + } + } + + [StructLayout(LayoutKind.Sequential)] + public struct TestCommand + { + public int cbSize; + public LaunchAction action; + public Display display; + public Restart restart; + [MarshalAs(UnmanagedType.LPWStr)] public string wzCommandLine; + public int nCmdShow; + public ResumeType resume; + public IntPtr hwndSplashScreen; + public RelationType relation; + [MarshalAs(UnmanagedType.Bool)] public bool passthrough; + [MarshalAs(UnmanagedType.LPWStr)] public string wzLayoutDirectory; + } + + [StructLayout(LayoutKind.Sequential)] + public struct TestCreateResults + { + public int cbSize; + public IntPtr pBAProc; + [MarshalAs(UnmanagedType.Interface)] public IBootstrapperApplication pBA; + } + } +} diff --git a/src/test/WixToolsetTest.Mba.Core/WixToolsetTest.Mba.Core.csproj b/src/test/WixToolsetTest.Mba.Core/WixToolsetTest.Mba.Core.csproj new file mode 100644 index 00000000..d401d877 --- /dev/null +++ b/src/test/WixToolsetTest.Mba.Core/WixToolsetTest.Mba.Core.csproj @@ -0,0 +1,29 @@ + + + + + + netcoreapp2.1 + false + AnyCPU;x86;x64 + + + + NU1701 + + + + + {665E0441-17F9-4105-B202-EDF274657F6E} + Content + Always + + + + + + + + + + diff --git a/src/test/WixToolsetTest.Mba.Core/WixToolsetTest.Mba.Core.v3.ncrunchproject b/src/test/WixToolsetTest.Mba.Core/WixToolsetTest.Mba.Core.v3.ncrunchproject new file mode 100644 index 00000000..7b5b2139 --- /dev/null +++ b/src/test/WixToolsetTest.Mba.Core/WixToolsetTest.Mba.Core.v3.ncrunchproject @@ -0,0 +1,5 @@ + + + True + + \ No newline at end of file -- cgit v1.2.3-55-g6feb