Skip to content

Commit

Permalink
Support for 32Bit assemblies (#65)
Browse files Browse the repository at this point in the history
* Support for 32Bit assemblies
Fixes #60

* Check Is64BitProcess property for win32 output

* Add binaries to releases
  • Loading branch information
marklechtermann authored Jul 18, 2022
1 parent bdc2b98 commit 7057d04
Show file tree
Hide file tree
Showing 16 changed files with 134 additions and 34 deletions.
20 changes: 19 additions & 1 deletion .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,22 @@ jobs:

- name: Nuget push tool
run: dotnet nuget push *.nupkg --api-key ${{ secrets.NUGET }} --source https://api.nuget.org/v3/index.json
working-directory: src/dscom.client/bin/Release
working-directory: src/dscom.client/bin/Release

- name: Publish 32Bit binary
run: dotnet publish .\src\dscom.client\dscom.client.csproj --no-self-contained -c Release -r win-x86 -f net6.0 /p:PublishSingleFile=true; copy src\dscom.client\bin\Release\net6.0\win-x86\publish\dscom.exe src\dscom.client\bin\Release\net6.0\win-x86\publish\dscom32.exe

- name: Release 32Bit binary
uses: softprops/action-gh-release@v1
if: startsWith(github.ref, 'refs/tags/')
with:
files: src\dscom.client\bin\Release\net6.0\win-x86\publish\dscom32.exe

- name: Publish 64Bit binary
run: dotnet publish .\src\dscom.client\dscom.client.csproj --no-self-contained -c Release -r win-x64 -f net6.0 /p:PublishSingleFile=true

- name: Release 64Bit binary
uses: softprops/action-gh-release@v1
if: startsWith(github.ref, 'refs/tags/')
with:
files: src\dscom.client\bin\Release\net6.0\win-x64\publish\dscom.exe
70 changes: 70 additions & 0 deletions scripts/demo32Bit.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
@echo off

SET workspace=%~dp0..\
@REM set filterregex=--filterregex \.file\= --filterregex \.attributes\.guid\= --filterregex numberOfImplementedInterfaces --filterregex implementedInterfaces
set filterregex=

SET net60dll=%workspace%src\dscom.demo\assembly1\bin\Release\net6.0\dSPACE.Runtime.InteropServices.DemoAssembly1.dll
SET net48dll=%workspace%src\dscom.demo\assembly1\bin\Release\net48\dSPACE.Runtime.InteropServices.DemoAssembly1.dll

del %workspace%src\dscom.demo\assembly1\bin\Release\net48\*.tlb
del %workspace%src\dscom.demo\assembly1\bin\Release\net6.0\*.tlb
del %workspace%src\dscom.demo\assembly1\bin\Release\net6.0\*.yaml
del %workspace%src\dscom.demo\assembly1\bin\Release\net48\*.yaml

dotnet build -c Release "%workspace%dscom.sln"
IF ERRORLEVEL 1 goto error

@REM dscom
echo ############## dscom.exe tlbexport
dotnet run --project %workspace%src\dscom.client\dscom.client.csproj -r win-x86 -f net6.0 --no-self-contained tlbexport /win32 /silent "%net60dll%" "/out:%net60dll%.tlb"

IF ERRORLEVEL 1 goto error

echo ############## dscom.exe tlbdump
dotnet run --project %workspace%src\dscom.client\dscom.client.csproj -r win-x86 -f net6.0 --no-self-contained tlbdump %filterregex% "/tlbrefpath:%net60dll%.tlb/.." "%net60dll%.tlb" "/out:%net60dll%.yaml"
IF ERRORLEVEL 1 goto error

WHERE tlbexp
IF %ERRORLEVEL% NEQ 0 (
ECHO.
ECHO ######################################################
ECHO.
ECHO tlbexp.exe not found
ECHO Please add the path to tlbexp.exe to your PATH variable.
ECHO.
ECHO ######################################################
ECHO.
goto error
)

@REM tlbexp
echo ############## tlbexp.exe
tlbexp /win32 /silent "%net48dll%" "/out:%net48dll%.tlb"
IF ERRORLEVEL 1 goto error

echo ############## dscom.exe tlbdump
dotnet run --project %workspace%src\dscom.client\dscom.client.csproj -r win-x86 -f net6.0 --no-self-contained tlbdump %filterregex% "/tlbrefpath:%net48dll%.tlb/.." "%net48dll%.tlb" "/out:%net48dll%.yaml"
IF ERRORLEVEL 1 goto error

WHERE code
IF %ERRORLEVEL% NEQ 0 (
ECHO.
ECHO ######################################################
ECHO.
ECHO You don't have Visual Studio Code installed, too bad.
ECHO https://code.visualstudio.com/download
ECHO.
ECHO Please compare the following files:
ECHO %net48dll%.yaml
ECHO %net60dll%.yaml
ECHO.
ECHO ######################################################
ECHO.
goto error
)

code -d "%net48dll%.yaml" "%net60dll%.yaml"

:error
pause
7 changes: 4 additions & 3 deletions src/dscom.client/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public static int Main(string[] args)
new Option<string[]>(new string [] {"--names", "/names"}, description: "A file in which each line specifies the capitalization of a name in the type library.", getDefaultValue: () => Array.Empty<string>()) { Arity = ArgumentArity.ZeroOrMore},
new Option<Guid>(new string [] {"--overridetlbid", "/overridetlbid"}, description: "Overwrites the library id"),
new Option<bool?>(new string [] {"--createmissingdependenttlbs", "/createmissingdependenttlbs"}, description: "Generate missing type libraries for referenced assemblies. (default true)"),
new Option<bool?>(new string [] {"--win32", "/win32"}, description: "Create a 32-bit type library"),
};

var tlbdumpCommand = new Command("tlbdump", "Dump a type library")
Expand Down Expand Up @@ -69,7 +70,7 @@ public static int Main(string[] args)
tlbunregisterCommand
};

rootCommand.Description = "dSPACE COM tools";
rootCommand.Description = $"dSPACE COM tools ({(Environment.Is64BitProcess ? "64Bit" : "32Bit")})";

ConfigureTLBExportHandler(tlbexportCommand);
ConfigureTLBDumpHandler(tlbdumpCommand);
Expand Down Expand Up @@ -199,13 +200,13 @@ private static void ConfigureTLBExportHandler(Command tlbexportCommand)
{
throw;
}
#else
#else
catch (Exception e)
{
Console.Error.WriteLine($"Failed to export type library. {e.Message} {e.InnerException?.Message}");
return 1;
}
#endif
#endif
});
}

Expand Down
3 changes: 2 additions & 1 deletion src/dscom.client/dscom.client.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
<AssemblyName>dscom</AssemblyName>
<OutputType>Exe</OutputType>
<TargetFrameworks>net6.0</TargetFrameworks>
<PlatformTarget>x64</PlatformTarget>
<PlatformTarget>AnyCPU</PlatformTarget>
<Platforms>AnyCPU;x86</Platforms>
<LangVersion>10.0</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
Expand Down
10 changes: 5 additions & 5 deletions src/dscom.common/ICreateTypeInfo2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,19 +93,19 @@ internal interface ICreateTypeInfo2 : ICreateTypeInfo
HRESULT DeleteImplType(uint index);

[PreserveSig]
HRESULT SetCustData(in Guid guid, [In, MarshalAs(UnmanagedType.Struct)] object pVarVal);
HRESULT SetCustData(in Guid guid, [In, MarshalAs(UnmanagedType.Struct)] ref object pVarVal);

[PreserveSig]
HRESULT SetFuncCustData(uint index, in Guid guid, [In, MarshalAs(UnmanagedType.Struct)] object pVarVal);
HRESULT SetFuncCustData(uint index, in Guid guid, [In, MarshalAs(UnmanagedType.Struct)] ref object pVarVal);

[PreserveSig]
HRESULT SetParamCustData(uint indexFunc, uint indexParam, in Guid guid, [In, MarshalAs(UnmanagedType.Struct)] object pVarVal);
HRESULT SetParamCustData(uint indexFunc, uint indexParam, in Guid guid, [In, MarshalAs(UnmanagedType.Struct)] ref object pVarVal);

[PreserveSig]
HRESULT SetVarCustData(uint index, in Guid guid, [In, MarshalAs(UnmanagedType.Struct)] object pVarVal);
HRESULT SetVarCustData(uint index, in Guid guid, [In, MarshalAs(UnmanagedType.Struct)] ref object pVarVal);

[PreserveSig]
HRESULT SetImplTypeCustData(uint index, in Guid guid, [In, MarshalAs(UnmanagedType.Struct)] object pVarVal);
HRESULT SetImplTypeCustData(uint index, in Guid guid, [In, MarshalAs(UnmanagedType.Struct)] ref object pVarVal);

[PreserveSig]
HRESULT SetHelpStringContext(uint dwHelpStringContext);
Expand Down
2 changes: 1 addition & 1 deletion src/dscom.common/ICreateTypeLib2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ internal interface ICreateTypeLib2 : ICreateTypeLib
HRESULT DeleteTypeInfo([MarshalAs(UnmanagedType.LPWStr)] string? szName);

[PreserveSig]
HRESULT SetCustData(in Guid guid, [In, MarshalAs(UnmanagedType.Struct)] object? pVarVal);
HRESULT SetCustData(in Guid guid, [In, MarshalAs(UnmanagedType.Struct)] ref object? pVarVal);

[PreserveSig]
HRESULT SetHelpStringContext(uint dwHelpStringContext);
Expand Down
3 changes: 2 additions & 1 deletion src/dscom.demo/assembly1/assembly1.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<TargetFrameworks>net6.0;net48</TargetFrameworks>
<PlatformTarget>x64</PlatformTarget>
<PlatformTarget>AnyCPU</PlatformTarget>
<LangVersion>10.0</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
Expand All @@ -12,6 +12,7 @@
<AnalysisMode>Recommended</AnalysisMode>
<EnableNETAnalyzers>true</EnableNETAnalyzers>
<NoWarn>CA1416;CA1401;CA1707;CA1720;CA1711;CA2201;CA1200;CA5351;CS0618;CA1305;</NoWarn>
<Platforms>AnyCPU;x86</Platforms>
<!-- <EnableComHosting>true</EnableComHosting> -->
</PropertyGroup>

Expand Down
3 changes: 2 additions & 1 deletion src/dscom.demo/assembly2/assembly2.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<TargetFrameworks>net6.0;net48</TargetFrameworks>
<PlatformTarget>x64</PlatformTarget>
<PlatformTarget>AnyCPU</PlatformTarget>
<LangVersion>10.0</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
Expand All @@ -11,6 +11,7 @@
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<AnalysisMode>Recommended</AnalysisMode>
<EnableNETAnalyzers>true</EnableNETAnalyzers>
<Platforms>AnyCPU;x86</Platforms>
</PropertyGroup>

</Project>
3 changes: 2 additions & 1 deletion src/dscom.demo/assembly3/assembly3.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<TargetFrameworks>net6.0;net48</TargetFrameworks>
<PlatformTarget>x64</PlatformTarget>
<PlatformTarget>AnyCPU</PlatformTarget>
<LangVersion>10.0</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
Expand All @@ -11,6 +11,7 @@
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<AnalysisMode>Recommended</AnalysisMode>
<EnableNETAnalyzers>true</EnableNETAnalyzers>
<Platforms>AnyCPU;x86</Platforms>
</PropertyGroup>

</Project>
1 change: 1 addition & 0 deletions src/dscom.test/dscom.test.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<AnalysisMode>Recommended</AnalysisMode>
<EnableNETAnalyzers>true</EnableNETAnalyzers>
<NoWarn>CA1416;CA1401;CA1707;CA1720;CA1711;CA2201;CA1200;CA5351;CS0618;CA1305;</NoWarn>
<Platforms>AnyCPU;x86</Platforms>
</PropertyGroup>

<ItemGroup>
Expand Down
9 changes: 7 additions & 2 deletions src/dscom/TypeLibConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,12 @@ public class TypeLibConverter
/// <returns>An object that implements the <see langword="ITypeLib" /> interface.</returns>
public object? ConvertAssemblyToTypeLib(Assembly assembly, string tlbFilePath, ITypeLibExporterNotifySink? notifySink)
{
var options = new TypeLibConverterSettings() { Out = tlbFilePath };
var options = new TypeLibConverterSettings
{
Out = tlbFilePath,
Win32 = !Environment.Is64BitProcess
};

return ConvertAssemblyToTypeLib(assembly, options, notifySink);
}

Expand All @@ -51,7 +56,7 @@ public class TypeLibConverter
{
CheckPlatform();

OleAut32.CreateTypeLib2(SYSKIND.SYS_WIN64, settings.Out!, out var typelib).ThrowIfFailed("Failed to create type library.");
OleAut32.CreateTypeLib2(settings.Win32 ? SYSKIND.SYS_WIN32 : SYSKIND.SYS_WIN64, settings.Out!, out var typelib).ThrowIfFailed("Failed to create type library.");

using var writer = new LibraryWriter(assembly, new WriterContext(settings, typelib, notifySink));
writer.Create();
Expand Down
5 changes: 5 additions & 0 deletions src/dscom/TypeLibConverterSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,9 @@ public class TypeLibConverterSettings
/// Gets or sets the type library GUID.
/// </summary>
public Guid OverrideTlbId { get; set; } = Guid.Empty;

/// <summary>
/// Gets or sets a value indicating whether the TLB is 32Bit.
/// </summary>
public bool Win32 { get; set; } = !Environment.Is64BitProcess;
}
5 changes: 5 additions & 0 deletions src/dscom/WriterContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ public WriterContext(TypeLibConverterSettings options, ICreateTypeLib2 targetTyp

public NameResolver NameResolver { get; private set; }

/// <summary>
/// Gets size of a pointer or handle in this process, measured in bytes. The value of this property is 4 in a 32-bit process, and 8 in a 64-bit process.
/// </summary>
internal int IntPtrSize => Options.Win32 ? 4 : 8;

public void LogTypeExported(string message)
{
if (NotifySink != null)
Expand Down
3 changes: 2 additions & 1 deletion src/dscom/dscom.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
<PropertyGroup>
<AssemblyName>dSPACE.Runtime.InteropServices</AssemblyName>
<TargetFrameworks>net6.0;net48</TargetFrameworks>
<Platforms>x64</Platforms>
<PlatformTarget>AnyCPU</PlatformTarget>
<Platforms>AnyCPU;x86</Platforms>
<LangVersion>10.0</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
Expand Down
3 changes: 2 additions & 1 deletion src/dscom/writer/IUnknownInterfaceWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ public IUnknownInterfaceWriter(Type sourceType, LibraryWriter libraryWriter, Wri
TypeFlags = TYPEFLAGS.TYPEFLAG_FOLEAUTOMATION;
TypeKind = TYPEKIND.TKIND_INTERFACE;
FuncKind = FUNCKIND.FUNC_PUREVIRTUAL;
VTableOffsetUserMethodStart = 24;

VTableOffsetUserMethodStart = 3 * Context.IntPtrSize;
ComInterfaceType = ComInterfaceType.InterfaceIsIUnknown;
UseHResultAsReturnValue = true;
}
Expand Down
21 changes: 5 additions & 16 deletions src/dscom/writer/InterfaceWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,12 @@ internal abstract class InterfaceWriter : TypeWriter
{
public InterfaceWriter(Type sourceType, LibraryWriter libraryWriter, WriterContext context) : base(sourceType, libraryWriter, context)
{
VTableOffsetUserMethodStart = 7 * context.IntPtrSize;
}

public DispatchIdCreator? DispatchIdCreator { get; protected set; }

public int VTableOffsetUserMethodStart { get; set; } = 56;
public int VTableOffsetUserMethodStart { get; set; }

public ComInterfaceType ComInterfaceType { get; set; }

Expand Down Expand Up @@ -70,20 +71,8 @@ public override void Create()
// Handle special IDs like 0 or -4, and try to fix duplicate DispIds if possible.
DispatchIdCreator.NormalizeIds();

// This index is necessary to generate the correct offset of the VTable.
// Every method must be considered, even those that cannot be generated.
// var index = 0;

// // The index of the function inside the type library
// var functionIndex = 0;
foreach (var item in MethodWriter)
{
// item.FunctionIndex = functionIndex;
// item.VTableOffset = VTableOffsetUserMethodStart + (index * 8);
item.Create();
// functionIndex += item.IsValid ? 1 : 0;
// index++;
}
// Create all writer.
MethodWriter.ForEach(writer => writer.Create());

TypeInfo.LayOut().ThrowIfFailed($"Failed to layout type {SourceType}.");
}
Expand Down Expand Up @@ -129,7 +118,7 @@ private void CreateMethodWriters()
foreach (var methodWriter in MethodWriter)
{
methodWriter.FunctionIndex = functionIndex;
methodWriter.VTableOffset = VTableOffsetUserMethodStart + (index * 8);
methodWriter.VTableOffset = VTableOffsetUserMethodStart + (index * Context.IntPtrSize);
DispatchIdCreator!.RegisterMember(methodWriter);
functionIndex += methodWriter.IsValid ? 1 : 0;
index++;
Expand Down

0 comments on commit 7057d04

Please sign in to comment.