Fake Visual Studio being installed for EazFuscator for .NET5 and up obfuscation (in progress)
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
2025-02-04 00:55:10 +01:00
parent 343a8662b3
commit f83b3558a6
17 changed files with 964 additions and 0 deletions

View File

@@ -0,0 +1,101 @@
using System;
using System.Runtime.InteropServices;
namespace VisualStudioMock
{
delegate int GetInterfaceDelegate(IntPtr @this, [MarshalAs(UnmanagedType.LPStruct)] Guid iid, out IntPtr ppv);
delegate int AddRefDelegate(IntPtr @this);
delegate int ReleaseDelegate(IntPtr @this);
sealed class ComProxy
{
private const int S_OK = 0;
private const int E_NOINTERFACE = -2147467262;
private static readonly Guid IID_IUnknown = new Guid("00000000-0000-0000-c000-000000000046");
private static readonly Guid IID_IManagedObject = new Guid("C3FCC19E-A970-11D2-8B5A-00A0C9B7C9C4");
private readonly object _realInstance;
private readonly IntPtr _realInstanceN;
private readonly IntPtr _proxyInstanceN;
private readonly GetInterfaceDelegate _getInterface;
private readonly IntPtr _getInterfaceN;
private readonly AddRefDelegate _addRef;
private readonly ReleaseDelegate _release;
internal ComProxy(object instance)
{
this._realInstance = instance;
this._realInstanceN = Marshal.GetIUnknownForObject(instance);
this._proxyInstanceN = Marshal.AllocHGlobal(IntPtr.Size * 4);
IntPtr vtbl = _proxyInstanceN + IntPtr.Size;
Marshal.WriteIntPtr(_proxyInstanceN, vtbl);
Marshal.WriteIntPtr(vtbl, this._getInterfaceN = Marshal.GetFunctionPointerForDelegate((Delegate)(this._getInterface = new GetInterfaceDelegate(GetInterface))));
Marshal.WriteIntPtr(vtbl, IntPtr.Size * 1, Marshal.GetFunctionPointerForDelegate((Delegate)(this._addRef = new AddRefDelegate(AddRef))));
Marshal.WriteIntPtr(vtbl, IntPtr.Size * 2, Marshal.GetFunctionPointerForDelegate((Delegate)(this._release = new ReleaseDelegate(Release))));
}
internal object GetIUnknown()
{
return Marshal.GetObjectForIUnknown(_proxyInstanceN);
}
private int GetInterface(IntPtr @this, [MarshalAs(UnmanagedType.LPStruct)] Guid iid, out IntPtr ppv)
{
if (iid == IID_IUnknown)
{
ppv = _proxyInstanceN;
Ext.LogCall(_realInstance.GetType().Name, nameof(GetInterface), "IUnknown OK");
return S_OK;
}
if (iid == IID_IManagedObject)
{
ppv = IntPtr.Zero;
Ext.LogCall(_realInstance.GetType().Name, nameof(GetInterface), "IManagedObject Fail");
return E_NOINTERFACE;
}
int result = Marshal.QueryInterface(_realInstanceN, ref iid, out ppv);
if (result == S_OK)
{
// Patch the vtable with our own thunks
IntPtr origVtbl = Marshal.ReadIntPtr(ppv);
Type iType = null;
foreach (Type i in _realInstance.GetType().GetInterfaces())
if (i.GUID == iid)
{
iType = i;
break;
}
if (iType != null)
{
// TODO generate proper thunks in machine code
int slotCount = Marshal.GetEndComSlot(iType) + 1;
int slotsSizeBytes = IntPtr.Size * slotCount;
IntPtr newVtbl = Marshal.AllocHGlobal(slotsSizeBytes);
...
}
Ext.LogCall(_realInstance.GetType().Name, nameof(GetInterface), (iType == null ? iid.ToString() : iType.Name) + " OK");
}
else
{
Ext.LogCall(_realInstance.GetType().Name, nameof(GetInterface), iid.ToString() + " Fail");
}
return result;
}
private int AddRef(IntPtr @this)
{
return 1;
}
private int Release(IntPtr @this)
{
return 1;
}
}
}

31
VisualStudioMock/Ext.cs Normal file
View File

@@ -0,0 +1,31 @@
using System;
namespace VisualStudioMock
{
static class Ext
{
public static void Log(string message)
{
Console.WriteLine("Mock: " + message);
}
public static void LogCall(string @class, string method, string message = null)
{
Console.WriteLine("Mock call: " + @class + "!" + method + " " + message);
}
public static void LogEnter(string @class, string method)
{
Console.WriteLine("Mock enter: " + @class + "!" + method);
}
public static void LogExit(string @class, string method)
{
Console.WriteLine("Mock exit: " + @class + "!" + method);
}
public static U ComBarrier<T, U>(this T instance) where T : U {
return (U)(new ComProxy(instance).GetIUnknown());
}
}
}

View File

@@ -0,0 +1,41 @@
using System;
using System.Runtime.InteropServices;
namespace VisualStudioMock
{
/// <summary>
/// An enumerator of installed <see cref="ISetupInstance" /> objects.
/// </summary>
[ComImport]
[ComVisible(true)]
[Guid("6380BCFF-41D3-4B2E-8B2E-BF8A6810C848")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IEnumSetupInstances
{
/// <summary>
/// Retrieves the next set of product instances in the enumeration sequence.
/// </summary>
/// <param name="celt">The number of product instances to retrieve.</param>
/// <param name="rgelt">A pointer to an array of <see cref="ISetupInstance" />.</param>
/// <param name="pceltFetched">A pointer to the number of product instances retrieved. If <paramref name="celt" /> is 1 this parameter may be NULL.</param>
void Next([In] [MarshalAs(UnmanagedType.U4)] int celt, [Out] [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.Interface)] ISetupInstance[] rgelt, [MarshalAs(UnmanagedType.U4)] out int pceltFetched);
/// <summary>
/// Skips the next set of product instances in the enumeration sequence.
/// </summary>
/// <param name="celt">The number of product instances to skip.</param>
void Skip([In] [MarshalAs(UnmanagedType.U4)] int celt);
/// <summary>
/// Resets the enumeration sequence to the beginning.
/// </summary>
void Reset();
/// <summary>
/// Creates a new enumeration object in the same state as the current enumeration object: the new object points to the same place in the enumeration sequence.
/// </summary>
/// <returns>A pointer to a pointer to a new <see cref="T:Microsoft.VisualStudio.Setup.Configuration.IEnumSetupInstances" /> interface. If the method fails, this parameter is undefined.</returns>
[return: MarshalAs(UnmanagedType.Interface)]
IEnumSetupInstances Clone();
}
}

View File

@@ -0,0 +1,42 @@
using System;
using System.Runtime.InteropServices;
namespace VisualStudioMock
{
/// <summary>
/// Gets information about product instances installed on the machine.
/// </summary>
[ComImport]
[Guid("42843719-DB4C-46C2-8E7C-64F1816EFD5B")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ISetupConfiguration
{
/// <summary>
/// Enumerates all launchable product instances installed.
/// </summary>
/// <returns>An enumeration of installed product instances.</returns>
[return: MarshalAs(UnmanagedType.Interface)]
IEnumSetupInstances EnumInstances();
/// <summary>
/// Gets the instance for the current process path.
/// </summary>
/// <returns>The instance for the current process path.</returns>
/// <remarks>
/// The returned instance may not be launchable.
/// </remarks>
[return: MarshalAs(UnmanagedType.Interface)]
ISetupInstance GetInstanceForCurrentProcess();
/// <summary>
/// Gets the instance for the given path.
/// </summary>
/// <param name="path">Path used to determine instance</param>
/// <returns>The instance for the given path.</returns>
/// <remarks>
/// The returned instance may not be launchable.
/// </remarks>
[return: MarshalAs(UnmanagedType.Interface)]
ISetupInstance GetInstanceForPath([In] [MarshalAs(UnmanagedType.LPWStr)] string path);
}
}

View File

@@ -0,0 +1,49 @@
using System;
using System.Runtime.InteropServices;
namespace VisualStudioMock
{
/// <summary>
/// Gets information about product instances set up on the machine.
/// </summary>
[ComImport]
[Guid("26AAB78C-4A60-49D6-AF3B-3C35BC93365D")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ISetupConfiguration2 : ISetupConfiguration
{
/// <summary>
/// Enumerates all launchable product instances installed.
/// </summary>
/// <returns>An enumeration of installed product instances.</returns>
[return: MarshalAs(UnmanagedType.Interface)]
new IEnumSetupInstances EnumInstances();
/// <summary>
/// Gets the instance for the current process path.
/// </summary>
/// <returns>The instance for the current process path.</returns>
/// <remarks>
/// The returned instance may not be launchable.
/// </remarks>
[return: MarshalAs(UnmanagedType.Interface)]
new ISetupInstance GetInstanceForCurrentProcess();
/// <summary>
/// Gets the instance for the given path.
/// </summary>
/// <param name="path">Path used to determine instance</param>
/// <returns>The instance for the given path.</returns>
/// <remarks>
/// The returned instance may not be launchable.
/// </remarks>
[return: MarshalAs(UnmanagedType.Interface)]
new ISetupInstance GetInstanceForPath([In] [MarshalAs(UnmanagedType.LPWStr)] string path);
/// <summary>
/// Enumerates all product instances.
/// </summary>
/// <returns>An enumeration of all product instances.</returns>
[return: MarshalAs(UnmanagedType.Interface)]
IEnumSetupInstances EnumAllInstances();
}
}

View File

@@ -0,0 +1,30 @@
using System;
using System.Runtime.InteropServices;
namespace VisualStudioMock
{
/// <summary>
/// Information about the error state of an instance.
/// </summary>
[ComImport]
[Guid("46DCCD94-A287-476A-851E-DFBC2FFDBC20")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ISetupErrorState
{
/*
/// <summary>
/// Gets an array of failed package references.
/// </summary>
/// <returns>An array of failed package references.</returns>
[return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_UNKNOWN)]
ISetupFailedPackageReference[] GetFailedPackages();
/// <summary>
/// Gets an array of skipped package references.
/// </summary>
/// <returns>An array of skipped package references.</returns>
[return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_UNKNOWN)]
ISetupPackageReference[] GetSkippedPackages();
*/
}
}

View File

@@ -0,0 +1,77 @@
using System;
using System.Runtime.InteropServices;
using FILETIME = System.Runtime.InteropServices.ComTypes.FILETIME;
namespace VisualStudioMock
{
/// <summary>
/// Information about an instance of a product.
/// </summary>
/// <remarks>
/// You can enumerate all properties of basic types by casting to an <see cref="ISetupPropertyStore" />.
/// </remarks>
[ComImport]
[Guid("B41463C3-8866-43B5-BC33-2B0676F7F42E")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ISetupInstance
{
/// <summary>
/// Gets the instance identifier (should match the name of the parent instance directory).
/// </summary>
/// <returns>The instance identifier.</returns>
[return: MarshalAs(UnmanagedType.BStr)]
string GetInstanceId();
/// <summary>
/// Gets the local date and time when the installation was originally installed.
/// </summary>
/// <returns>The local date and time when the installation was originally installed.</returns>
[return: MarshalAs(UnmanagedType.Struct)]
FILETIME GetInstallDate();
/// <summary>
/// Gets the unique name of the installation, often indicating the branch and other information used for telemetry.
/// </summary>
/// <returns>The unique name of the installation, often indicating the branch and other information used for telemetry.</returns>
[return: MarshalAs(UnmanagedType.BStr)]
string GetInstallationName();
/// <summary>
/// Gets the path to the installation root of the product.
/// </summary>
/// <returns>The path to the installation root of the product.</returns>
[return: MarshalAs(UnmanagedType.BStr)]
string GetInstallationPath();
/// <summary>
/// Gets the version of the product installed in this instance.
/// </summary>
/// <returns>The version of the product installed in this instance.</returns>
[return: MarshalAs(UnmanagedType.BStr)]
string GetInstallationVersion();
/// <summary>
/// Gets the display name (title) of the product installed in this instance.
/// </summary>
/// <param name="lcid">The LCID for the display name.</param>
/// <returns>The display name (title) of the product installed in this instance.</returns>
[return: MarshalAs(UnmanagedType.BStr)]
string GetDisplayName([In] [MarshalAs(UnmanagedType.U4)] int lcid = 0);
/// <summary>
/// Gets the description of the product installed in this instance.
/// </summary>
/// <param name="lcid">The LCID for the description.</param>
/// <returns>The description of the product installed in this instance.</returns>
[return: MarshalAs(UnmanagedType.BStr)]
string GetDescription([In] [MarshalAs(UnmanagedType.U4)] int lcid = 0);
/// <summary>
/// Resolves the optional relative path to the root path of the instance.
/// </summary>
/// <param name="pwszRelativePath">A relative path within the instance to resolve, or NULL to get the root path.</param>
/// <returns>The full path to the optional relative path within the instance. If the relative path is NULL, the root path will always terminate in a backslash.</returns>
[return: MarshalAs(UnmanagedType.BStr)]
string ResolvePath([In] [MarshalAs(UnmanagedType.LPWStr)] string pwszRelativePath = null);
}
}

View File

@@ -0,0 +1,83 @@
using System;
using System.Runtime.InteropServices;
namespace VisualStudioMock
{
/// <summary>
/// Information about an instance of a product.
/// </summary>
/// <remarks>
/// You can enumerate all properties of basic types by casting to an <see cref="ISetupPropertyStore" />.
/// </remarks>
[ComImport]
[Guid("89143C9A-05AF-49B0-B717-72E218A2185C")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ISetupInstance2 : ISetupInstance
{
/// <summary>
/// Gets the state of the instance.
/// </summary>
/// <returns>The state of the instance.</returns>
[return: MarshalAs(UnmanagedType.U4)]
InstanceState GetState();
/// <summary>
/// Gets an array of package references registered to the instance.
/// </summary>
/// <returns>An array of package references registered to the instance.</returns>
[return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_UNKNOWN)]
ISetupPackageReference[] GetPackages();
/// <summary>
/// Gets a package reference to the product registered to the instance
/// </summary>
/// <returns>A package reference to the product registered to the instance. This may be null if <see cref="M:Microsoft.VisualStudio.Setup.Configuration.ISetupInstance2.GetState" /> does not return <see cref="F:Microsoft.VisualStudio.Setup.Configuration.InstanceState.Complete" />.</returns>
ISetupPackageReference GetProduct();
/// <summary>
/// Gets the relative path to the product application, if available.
/// </summary>
/// <returns>The relative path to the product application, if available.</returns>
[return: MarshalAs(UnmanagedType.BStr)]
string GetProductPath();
/// <summary>
/// Gets the error state of the instance, if available.
/// </summary>
/// <returns>The error state of the instance, if available.</returns>
ISetupErrorState GetErrors();
/// <summary>
/// Gets a value indicating whether the instance can be launched.
/// </summary>
/// <returns>Whether the instance can be launched.</returns>
/// <remarks>
/// An instance could have had errors during install but still be launched. Some features may not work correctly, but others will.
/// </remarks>
[return: MarshalAs(UnmanagedType.VariantBool)]
bool IsLaunchable();
/// <summary>
/// Gets a value indicating whether the instance is complete.
/// </summary>
/// <returns>Whether the instance is complete.</returns>
/// <remarks>
/// An instance is complete if it had no errors during install, resume, or repair.
/// </remarks>
[return: MarshalAs(UnmanagedType.VariantBool)]
bool IsComplete();
/// <summary>
/// Gets product-specific properties.
/// </summary>
/// <returns>An <see cref="T:Microsoft.VisualStudio.Setup.Configuration.ISetupPropertyStore" /> of product-specific properties, or null if no properties are defined.</returns>
ISetupPropertyStore GetProperties();
/// <summary>
/// Gets the directory path to the setup engine that installed the instance.
/// </summary>
/// <returns>The directory path to the setup engine that installed the instance.</returns>
[return: MarshalAs(UnmanagedType.BStr)]
string GetEnginePath();
}
}

View File

@@ -0,0 +1,73 @@
using System;
using System.Runtime.InteropServices;
namespace VisualStudioMock
{
/// <summary>
/// A reference to a package.
/// </summary>
/// <remarks>
/// You can enumerate all properties of basic types by casting to an <see cref="ISetupPropertyStore" />.
/// </remarks>
[ComImport]
[Guid("DA8D8A16-B2B6-4487-A2F1-594CCCCD6BF5")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ISetupPackageReference
{
/// <summary>
/// Gets the general package identifier.
/// </summary>
/// <returns>The general package identifier.</returns>
[return: MarshalAs(UnmanagedType.BStr)]
string GetId();
/// <summary>
/// Gets the version of the package.
/// </summary>
/// <returns>The version of the package.</returns>
[return: MarshalAs(UnmanagedType.BStr)]
string GetVersion();
/// <summary>
/// Gets the target process architecture of the package.
/// </summary>
/// <returns>The target process architecture of the package.</returns>
[return: MarshalAs(UnmanagedType.BStr)]
string GetChip();
/// <summary>
/// Gets the language and optional region identifier.
/// </summary>
/// <returns>The language and optional region identifier.</returns>
[return: MarshalAs(UnmanagedType.BStr)]
string GetLanguage();
/// <summary>
/// Gets the build branch of the package.
/// </summary>
/// <returns>The build branch of the package.</returns>
[return: MarshalAs(UnmanagedType.BStr)]
string GetBranch();
/// <summary>
/// Gets the type of the package.
/// </summary>
/// <returns>The type of the package.</returns>
[return: MarshalAs(UnmanagedType.BStr)]
new string GetType();
/// <summary>
/// Gets the unique identifier consisting of all defined tokens.
/// </summary>
/// <returns>The unique identifier consisting of all defined tokens.</returns>
[return: MarshalAs(UnmanagedType.BStr)]
string GetUniqueId();
/// <summary>
/// Gets a value indicating whether the package refers to an external extension.
/// </summary>
/// <returns>A value indicating whether the package refers to an external extension.</returns>
[return: MarshalAs(UnmanagedType.VariantBool)]
bool GetIsExtension();
}
}

View File

@@ -0,0 +1,31 @@
using System;
using System.Runtime.InteropServices;
namespace VisualStudioMock
{
/// <summary>
/// Provides named properties.
/// </summary>
/// <remarks>
/// You can get this from an <see cref="ISetupInstance" />, <see cref="ISetupPackageReference" />, or derivative.
/// </remarks>
[ComImport]
[Guid("c601c175-a3be-44bc-91f6-4568d230fc83")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ISetupPropertyStore
{
/// <summary>
/// Gets an array of property names in this property store.
/// </summary>
/// <returns>An array of property names in this property store.</returns>
[return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)]
string[] GetNames();
/// <summary>
/// Gets the value of a named property in this property store.
/// </summary>
/// <param name="pwszName">The name of the property to get.</param>
/// <returns>The value of the property.</returns>
object GetValue([In] [MarshalAs(UnmanagedType.LPWStr)] string pwszName);
}
}

View File

@@ -0,0 +1,36 @@
using System;
namespace VisualStudioMock
{
/// <summary>
/// The state of an <see cref="ISetupInstance2" />.
/// </summary>
[Flags]
public enum InstanceState : uint
{
/// <summary>
/// The instance state has not been determined.
/// </summary>
None = 0x0,
/// <summary>
/// The instance installation path exists.
/// </summary>
Local = 0x1,
/// <summary>
/// A product is registered to the instance.
/// </summary>
Registered = 0x2,
/// <summary>
/// No reboot is required for the instance.
/// </summary>
NoRebootRequired = 0x4,
/// <summary>
/// No errors were reported for the instance.
/// </summary>
NoErrors = 0x8,
/// <summary>
/// The instance represents a complete install.
/// </summary>
Complete = uint.MaxValue
}
}

View File

@@ -0,0 +1,50 @@
using System;
using System.Reflection;
using Microsoft.Win32;
[assembly: AssemblyCompany("Ivasoft s.r.o.")]
[assembly: AssemblyProduct("VisualStudioMock")]
[assembly: AssemblyTitle("Visual Studio Mock for EAZfuscator")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace VisualStudioMock
{
public class Program
{
[STAThread]
public static void Main(string[] args)
{
AppDomain.CurrentDomain.UnhandledException += (object sender, UnhandledExceptionEventArgs e) => Console.WriteLine("Exception: " + e.ExceptionObject);
if (args.Length == 1)
switch (args[0]) {
case "/reg":
using (RegistryKey regBase = RegistryKey.OpenBaseKey(RegistryHive.ClassesRoot, RegistryView.Registry64))
using (RegistryKey regCoClass = regBase.CreateSubKey("CLSID\\{177F0C4A-1CD3-4DE7-A32C-71DBBB9FA36D}\\InprocServer32"))
{
regCoClass.SetValue("", "mscoree.dll");
regCoClass.SetValue("Class", "VisualStudioMock.SetupConfiguration");
regCoClass.SetValue("Assembly", "VisualStudioMock, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");
regCoClass.SetValue("RuntimeVersion", "v4.0.30319");
regCoClass.SetValue("ThreadingModel", "Apartment");
regCoClass.SetValue("CodeBase", Assembly.GetExecutingAssembly().Location);
}
Console.WriteLine("Visual Studio Mock registered.");
return;
case "/unreg":
using (RegistryKey regBase = RegistryKey.OpenBaseKey(RegistryHive.ClassesRoot, RegistryView.Registry64))
{
regBase.DeleteSubKey("CLSID\\{177F0C4A-1CD3-4DE7-A32C-71DBBB9FA36D}\\InprocServer32", throwOnMissingSubKey: false);
regBase.DeleteSubKey("CLSID\\{177F0C4A-1CD3-4DE7-A32C-71DBBB9FA36D}\\LocalServer32", throwOnMissingSubKey: false);
regBase.DeleteSubKey("CLSID\\{177F0C4A-1CD3-4DE7-A32C-71DBBB9FA36D}", throwOnMissingSubKey: false);
}
Console.WriteLine("Visual Studio Mock unregistered.");
return;
}
Console.WriteLine("Usage: VisualStudioMock.exe [ /reg | /unreg ]");
return;
}
}
}

View File

@@ -0,0 +1,140 @@
using System;
using System.Runtime.InteropServices;
namespace VisualStudioMock
{
[ComVisible(true)]
[Guid("177F0C4A-1CD3-4DE7-A32C-71DBBB9FA36D")]
[ClassInterface(ClassInterfaceType.None)]
public sealed class SetupConfiguration : ISetupConfiguration, ISetupConfiguration2
{
private readonly SetupInstance _singleInstance;
public SetupConfiguration()
{
Ext.LogCall(nameof(SetupConfiguration), ".ctor");
ComProxy proxy = new ComProxy(new SetupConfiguration(false));
object proxyCcw = proxy.GetIUnknown();
// Copy managed object
GCHandle hThis = GCHandle.Alloc(this, GCHandleType.WeakTrackResurrection);
IntPtr pThis = Marshal.ReadIntPtr(GCHandle.ToIntPtr(hThis));
GCHandle hProxy = GCHandle.Alloc(proxyCcw, GCHandleType.WeakTrackResurrection);
IntPtr pProxy = Marshal.ReadIntPtr(GCHandle.ToIntPtr(hProxy));
byte[] buffer = new byte[IntPtr.Size * 3];
Marshal.Copy(pProxy - IntPtr.Size, buffer, 0, buffer.Length);
Marshal.Copy(buffer, 0, pThis - IntPtr.Size, buffer.Length);
/*
Ext.Log("Casting to ISetupConfiguration");
proxyCcw = this;
ISetupConfigurationTest wrapper = (ISetupConfigurationTest)proxyCcw;
GC.KeepAlive(wrapper.GetInstanceForCurrentProcess());
*/
Ext.LogExit(nameof(SetupConfiguration), ".ctor");
}
private SetupConfiguration(bool any)
{
this._singleInstance = new SetupInstance();
}
#region ISetupConfiguration Members
public IEnumSetupInstances EnumInstances()
{
Ext.LogCall(nameof(SetupConfiguration), nameof(EnumInstances));
return new Enum(this).ComBarrier<Enum, IEnumSetupInstances>();
}
public ISetupInstance GetInstanceForCurrentProcess()
{
Ext.LogCall(nameof(SetupConfiguration), nameof(GetInstanceForCurrentProcess));
return _singleInstance.ComBarrier<SetupInstance, ISetupInstance>();
}
public ISetupInstance GetInstanceForPath([In, MarshalAs(UnmanagedType.LPWStr)] string path)
{
Ext.LogCall(nameof(SetupConfiguration), nameof(GetInstanceForPath));
throw new NotImplementedException();
}
#endregion
#region ISetupConfiguration2 Members
public IEnumSetupInstances EnumAllInstances()
{
Ext.LogEnter(nameof(SetupConfiguration), nameof(EnumAllInstances));
IEnumSetupInstances result = new Enum(this).ComBarrier<Enum, IEnumSetupInstances>();
Ext.LogExit(nameof(SetupConfiguration), nameof(EnumAllInstances));
return result;
}
#endregion
sealed class Enum : IEnumSetupInstances
{
private readonly SetupConfiguration _owner;
private int _idx;
internal Enum(SetupConfiguration owner)
{
this._owner = owner;
}
public IEnumSetupInstances Clone()
{
Ext.LogCall(nameof(Enum), nameof(Clone));
return ((Enum)MemberwiseClone()).ComBarrier<Enum, IEnumSetupInstances>();
}
public void Next([In, MarshalAs(UnmanagedType.U4)] int celt, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.Interface), Out] ISetupInstance[] rgelt, [MarshalAs(UnmanagedType.U4)] out int pceltFetched)
{
Ext.LogEnter(nameof(Enum), nameof(Next));
if (_idx == 0 && celt > 0)
{
rgelt[0] = _owner._singleInstance.ComBarrier<SetupInstance, ISetupInstance>();
pceltFetched = 1;
}
else
{
pceltFetched = 0;
}
Ext.LogExit(nameof(Enum), nameof(Next));
}
public void Reset()
{
Ext.LogCall(nameof(Enum), nameof(Reset));
_idx = 0;
}
public void Skip([In, MarshalAs(UnmanagedType.U4)] int celt)
{
Ext.LogEnter(nameof(Enum), nameof(Skip));
if (celt < 0)
throw new ArgumentOutOfRangeException();
_idx += celt;
Ext.LogExit(nameof(Enum), nameof(Skip));
}
}
/*
[ComImport]
[Guid("42843719-DB4C-46C2-8E7C-64F1816EFD5B")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ISetupConfigurationTest
{
[return: MarshalAs(UnmanagedType.Interface)]
IEnumSetupInstances EnumInstances();
[return: MarshalAs(UnmanagedType.Interface)]
ISetupInstance GetInstanceForCurrentProcess();
[return: MarshalAs(UnmanagedType.Interface)]
ISetupInstance GetInstanceForPath([In] [MarshalAs(UnmanagedType.LPWStr)] string path);
}
*/
}
}

View File

@@ -0,0 +1,135 @@
using System;
using System.Runtime.InteropServices;
using FILETIME = System.Runtime.InteropServices.ComTypes.FILETIME;
namespace VisualStudioMock
{
public class SetupInstance : ISetupInstance, ISetupInstance2, ISetupPropertyStore
{
#region ISetupInstance Members
public string GetDescription([In, MarshalAs(UnmanagedType.U4)] int lcid = 0)
{
Ext.LogCall(nameof(SetupInstance), nameof(GetDescription));
return "description";
}
public string GetDisplayName([In, MarshalAs(UnmanagedType.U4)] int lcid = 0)
{
Ext.LogCall(nameof(SetupInstance), nameof(GetDisplayName));
return "display name";
}
public string GetInstallationName()
{
Ext.LogCall(nameof(SetupInstance), nameof(GetInstallationName));
return "installation name";
}
public string GetInstallationPath()
{
Ext.LogCall(nameof(SetupInstance), nameof(GetInstallationPath));
throw new NotImplementedException();
}
public string GetInstallationVersion()
{
Ext.LogCall(nameof(SetupInstance), nameof(GetInstallationVersion));
throw new NotImplementedException();
}
public FILETIME GetInstallDate()
{
Ext.LogCall(nameof(SetupInstance), nameof(GetInstallDate));
throw new NotImplementedException();
}
public string GetInstanceId()
{
Ext.LogCall(nameof(SetupInstance), nameof(GetInstanceId));
return "id1";
}
public string ResolvePath([In, MarshalAs(UnmanagedType.LPWStr)] string pwszRelativePath = null)
{
Ext.LogCall(nameof(SetupInstance), nameof(ResolvePath));
throw new NotImplementedException();
}
#endregion
#region ISetupInstance2 Members
public string GetEnginePath()
{
Ext.LogCall(nameof(SetupInstance), nameof(GetEnginePath));
throw new NotImplementedException();
}
public ISetupErrorState GetErrors()
{
Ext.LogCall(nameof(SetupInstance), nameof(GetEnginePath));
throw new NotImplementedException();
}
public ISetupPackageReference[] GetPackages()
{
Ext.LogCall(nameof(SetupInstance), nameof(GetEnginePath));
throw new NotImplementedException();
}
public ISetupPackageReference GetProduct()
{
Ext.LogCall(nameof(SetupInstance), nameof(GetEnginePath));
throw new NotImplementedException();
}
public string GetProductPath()
{
Ext.LogCall(nameof(SetupInstance), nameof(GetEnginePath));
throw new NotImplementedException();
}
public ISetupPropertyStore GetProperties()
{
Ext.LogCall(nameof(SetupInstance), nameof(GetProperties));
return this;
}
public InstanceState GetState()
{
Ext.LogCall(nameof(SetupInstance), nameof(GetState));
return InstanceState.Complete;
}
public bool IsComplete()
{
Ext.LogCall(nameof(SetupInstance), nameof(IsComplete));
return true;
}
public bool IsLaunchable()
{
Ext.LogCall(nameof(SetupInstance), nameof(IsLaunchable));
return true;
}
#endregion
#region ISetupPropertyStore Members
public string[] GetNames()
{
Ext.LogCall(nameof(SetupInstance), nameof(GetNames));
throw new NotImplementedException();
}
public object GetValue(string pwszName)
{
Ext.LogCall(nameof(SetupInstance), nameof(GetValue));
throw new NotImplementedException();
}
#endregion
}
}

View File

@@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net472</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<!--Nullable>enable</Nullable-->
</PropertyGroup>
<ItemGroup>
<Reference Include="System.Windows.Forms" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,23 @@
using System;
using System.Runtime.InteropServices;
using Microsoft.VisualStudio.Setup.Configuration;
class A {
public static void Main(string[] args) {
Console.WriteLine("Creating instance of SetupConfiguration");
SetupConfiguration setup = new SetupConfiguration();
Console.WriteLine("Created instance of SetupConfiguration");
var a = setup.EnumAllInstances();
ISetupInstance[] b = new ISetupInstance[1];
while (true) {
a.Next(1, b, out _);
if (b[0] == null)
break;
ISetupInstance c = b[0];
Console.WriteLine("Instance - " + c.GetDisplayName());
}
}
}

View File

@@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net472</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.VisualStudio.Setup.Configuration.Interop" Version="3.12.2149" />
</ItemGroup>
</Project>