-
Notifications
You must be signed in to change notification settings - Fork 4.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement TLB support in the RegFreeComManifest generation code. (#51413
- Loading branch information
1 parent
fe8a6c3
commit cecc76a
Showing
10 changed files
with
387 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
26 changes: 26 additions & 0 deletions
26
src/installer/managed/Microsoft.NET.HostModel/ComHost/InvalidTypeLibraryException.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using System; | ||
|
||
namespace Microsoft.NET.HostModel.ComHost | ||
{ | ||
/// <summary> | ||
/// The provided type library file is an invalid format. | ||
/// </summary> | ||
public class InvalidTypeLibraryException : Exception | ||
{ | ||
public InvalidTypeLibraryException(string path) | ||
{ | ||
Path = path; | ||
} | ||
|
||
public InvalidTypeLibraryException(string path, Exception innerException) | ||
:base($"Invalid type library at '{path}'.", innerException) | ||
{ | ||
Path = path; | ||
} | ||
|
||
public string Path { get; } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
75 changes: 75 additions & 0 deletions
75
src/installer/managed/Microsoft.NET.HostModel/ComHost/TypeLibReader.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
// 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.Buffers.Binary; | ||
|
||
namespace Microsoft.NET.HostModel.ComHost | ||
{ | ||
/// <summary> | ||
/// Reads data from a COM Type Library file based on the official implementation in the Win32 function LoadTypeLib. | ||
/// We do the reading ourselves instead of calling into the OS so we don't have to worry about the type library's | ||
/// dependencies being discoverable on disk. | ||
/// </summary> | ||
internal class TypeLibReader | ||
{ | ||
private byte[] tlbBytes; | ||
|
||
public TypeLibReader(byte[] tlbBytes) | ||
{ | ||
this.tlbBytes = tlbBytes; | ||
} | ||
|
||
private const int OffsetOfGuidOffset = sizeof(int) * 2; | ||
private const int SizeOfGuidOffset = sizeof(int); | ||
|
||
private const int OffsetOfMajorVersion = OffsetOfGuidOffset + SizeOfGuidOffset + sizeof(int) * 2 + sizeof(ushort) * 2; | ||
private const int SizeOfMajorVersion = sizeof(ushort); | ||
private const int OffsetOfMinorVersion = OffsetOfMajorVersion + SizeOfMajorVersion; | ||
private const int SizeOfMinorVersion = sizeof(ushort); | ||
|
||
private const int OffsetOfTypeInfosCount = OffsetOfMinorVersion + SizeOfMinorVersion + sizeof(int); | ||
private const int SizeOfTypeInfosCount = sizeof(int); | ||
|
||
private const int OffsetOfTablesStart = OffsetOfTypeInfosCount + SizeOfTypeInfosCount + sizeof(int) * 12; | ||
private const int NumTablesToSkip = 5; | ||
private const int SizeOfTableHeader = sizeof(int) * 4; | ||
|
||
private Guid FindGuid(ReadOnlySpan<byte> fileContents) | ||
{ | ||
checked | ||
{ | ||
int typelibGuidEntryOffset = (int)BinaryPrimitives.ReadUInt32LittleEndian(fileContents.Slice(OffsetOfGuidOffset)); | ||
int infoRefsOffsetCount = (int)BinaryPrimitives.ReadUInt32LittleEndian(fileContents.Slice(OffsetOfTypeInfosCount)); | ||
int infoBytes = infoRefsOffsetCount * SizeOfTypeInfosCount; | ||
int guidTableOffset = OffsetOfTablesStart + infoBytes + SizeOfTableHeader * NumTablesToSkip; | ||
int fileOffset = (int)BinaryPrimitives.ReadUInt32LittleEndian(fileContents.Slice(guidTableOffset)); | ||
return new Guid(fileContents.Slice(fileOffset + typelibGuidEntryOffset, 16).ToArray()); | ||
} | ||
} | ||
|
||
public bool TryReadTypeLibGuidAndVersion(out Guid typelibId, out Version version) | ||
{ | ||
typelibId = default; | ||
version = default; | ||
try | ||
{ | ||
var span = new ReadOnlySpan<byte>(tlbBytes); | ||
typelibId = FindGuid(span); | ||
ushort majorVer = BinaryPrimitives.ReadUInt16LittleEndian(span.Slice(OffsetOfMajorVersion)); | ||
ushort minorVer = BinaryPrimitives.ReadUInt16LittleEndian(span.Slice(OffsetOfMinorVersion)); | ||
version = new Version(majorVer, minorVer); | ||
return true; | ||
} | ||
catch (System.OverflowException) | ||
{ | ||
return false; | ||
} | ||
catch (System.IndexOutOfRangeException) | ||
{ | ||
return false; | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
126 changes: 126 additions & 0 deletions
126
src/installer/tests/HostActivation.Tests/NativeHosting/ComhostSideBySide.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Reflection.Metadata; | ||
using System.Runtime.InteropServices; | ||
|
||
using Microsoft.DotNet.Cli.Build.Framework; | ||
using Microsoft.NET.HostModel.ComHost; | ||
using Xunit; | ||
|
||
namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.NativeHosting | ||
{ | ||
public class ComhostSideBySide : IClassFixture<ComhostSideBySide.SharedTestState> | ||
{ | ||
private readonly SharedTestState sharedState; | ||
|
||
public ComhostSideBySide(SharedTestState sharedTestState) | ||
{ | ||
sharedState = sharedTestState; | ||
} | ||
|
||
[Fact] | ||
public void ActivateClass() | ||
{ | ||
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) | ||
{ | ||
// COM activation is only supported on Windows | ||
return; | ||
} | ||
|
||
string [] args = { | ||
"activation", | ||
sharedState.ClsidString | ||
}; | ||
|
||
CommandResult result = Command.Create(sharedState.ComSxsPath, args) | ||
.EnableTracingAndCaptureOutputs() | ||
.DotNetRoot(sharedState.ComLibraryFixture.BuiltDotnet.BinPath) | ||
.MultilevelLookup(false) | ||
.Execute(); | ||
|
||
result.Should().Pass() | ||
.And.HaveStdOutContaining("New instance of Server created"); | ||
} | ||
|
||
[Fact] | ||
public void LocateEmbeddedTlb() | ||
{ | ||
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) | ||
{ | ||
// COM activation is only supported on Windows | ||
return; | ||
} | ||
|
||
string [] args = { | ||
"typelib_lookup", | ||
sharedState.TypeLibId | ||
}; | ||
|
||
CommandResult result = Command.Create(sharedState.ComSxsPath, args) | ||
.EnableTracingAndCaptureOutputs() | ||
.DotNetRoot(sharedState.ComLibraryFixture.BuiltDotnet.BinPath) | ||
.MultilevelLookup(false) | ||
.Execute(); | ||
|
||
result.Should().Pass() | ||
.And.HaveStdOutContaining("Located type library by typeid."); | ||
} | ||
|
||
public class SharedTestState : Comhost.SharedTestState | ||
{ | ||
public string TypeLibId { get; } = "{20151109-a0e8-46ae-b28e-8ff2c0e72166}"; | ||
|
||
public string ComSxsPath { get; } | ||
|
||
public SharedTestState() | ||
{ | ||
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) | ||
{ | ||
// COM activation is only supported on Windows | ||
return; | ||
} | ||
|
||
using (var assemblyStream = new FileStream(ComLibraryFixture.TestProject.AppDll, FileMode.Open, FileAccess.Read, FileShare.Delete | FileShare.Read)) | ||
using (var peReader = new System.Reflection.PortableExecutable.PEReader(assemblyStream)) | ||
{ | ||
if (peReader.HasMetadata) | ||
{ | ||
string regFreeManifestPath = Path.Combine(BaseDirectory, $"{ ComLibraryFixture.TestProject.AssemblyName }.X.manifest"); | ||
|
||
MetadataReader reader = peReader.GetMetadataReader(); | ||
RegFreeComManifest.CreateManifestFromClsidmap( | ||
ComLibraryFixture.TestProject.AssemblyName, | ||
Path.GetFileName(ComHostPath), | ||
reader.GetAssemblyDefinition().Version.ToString(), | ||
ClsidMapPath, | ||
regFreeManifestPath, | ||
TypeLibraries | ||
); | ||
} | ||
} | ||
|
||
string testDirectoryPath = Path.GetDirectoryName(NativeHostPath); | ||
string comsxsName = RuntimeInformationExtensions.GetExeFileNameForCurrentPlatform("comsxs"); | ||
ComSxsPath = Path.Combine(testDirectoryPath, comsxsName); | ||
File.Copy( | ||
Path.Combine(RepoDirectories.Artifacts, "corehost_test", comsxsName), | ||
ComSxsPath); | ||
File.Copy( | ||
ComHostPath, | ||
Path.Combine(testDirectoryPath, Path.GetFileName(ComHostPath))); | ||
File.Copy( | ||
ComLibraryFixture.TestProject.AppDll, | ||
Path.Combine(testDirectoryPath, Path.GetFileName(ComLibraryFixture.TestProject.AppDll))); | ||
File.Copy( | ||
ComLibraryFixture.TestProject.DepsJson, | ||
Path.Combine(testDirectoryPath, Path.GetFileName(ComLibraryFixture.TestProject.DepsJson))); | ||
File.Copy( | ||
ComLibraryFixture.TestProject.RuntimeConfigJson, | ||
Path.Combine(testDirectoryPath, Path.GetFileName(ComLibraryFixture.TestProject.RuntimeConfigJson))); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.