Skip to content
This repository was archived by the owner on Mar 19, 2021. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Switched from deprecated DllImports to ICLRStrongName, tests pass
  • Loading branch information
jnm2 committed Feb 15, 2017
commit f48773c0e8ba228bb7f871b1292a259f690bd79a
33 changes: 33 additions & 0 deletions System.Compiler/ClrStrongName.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using System.Runtime.InteropServices;

namespace System.Compiler
{
public static class ClrStrongName
{
private static IClrStrongName clrStrongName;
private static IClrStrongName GetClrStrongName()
{
return clrStrongName ?? (clrStrongName =
(IClrStrongName)RuntimeEnvironment.GetRuntimeInterfaceAsObject(
new Guid("B79B0ACD-F5CD-409b-B5A5-A16244610B92"),
typeof(IClrStrongName).GUID));
}

public static void SignatureGeneration(string filePath, string keyContainer, byte[] keyBlob)
{
GetClrStrongName().StrongNameSignatureGeneration(filePath, keyContainer, keyBlob, keyBlob.Length, IntPtr.Zero, IntPtr.Zero);
}

[ComImport, ComConversionLoss, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("9FD93CCF-3280-4391-B3A9-96E1CDE77C8D")]
private interface IClrStrongName
Copy link
Contributor Author

@jnm2 jnm2 Sep 15, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For future readers: this is a bad interface declaration because COM interface calls are made in .NET not by method name but rather method declaration order inside the interface. There are 16 missing method declarations that should have come lexically above StrongNameSignatureGeneration. Therefore the first slot number is used instead of the seventeenth, and so, in spite of its name, the COM call ends up being to GetHashFromAssemblyFile instead of to StrongNameSignatureGeneration .

See the fix: #49

{
void StrongNameSignatureGeneration(
[MarshalAs(UnmanagedType.LPWStr)] string pwzFilePath,
[MarshalAs(UnmanagedType.LPWStr)] string pwzKeyContainer,
[In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] byte[] pbKeyBlob,
int cbKeyBlob,
IntPtr ppbSignatureBlob,
IntPtr pcbSignatureBlob);
}
}
}
1 change: 1 addition & 0 deletions System.Compiler/System.Compiler.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@
<Compile Include="AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="ClrStrongName.cs" />
<Compile Include="Comparer.cs">
<SubType>Code</SubType>
</Compile>
Expand Down
103 changes: 23 additions & 80 deletions System.Compiler/Writer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5296,7 +5296,20 @@ public MethodInfo() {
}
}
public class KeyFileNotFoundException : System.ArgumentException{}
public class AssemblyCouldNotBeSignedException : System.ApplicationException{}

public class AssemblyCouldNotBeSignedException : System.ApplicationException
{
private const string AssemblyCouldNotBeSignedMessage = "Assembly could not be signed.";

public AssemblyCouldNotBeSignedException() : base(AssemblyCouldNotBeSignedMessage)
{
}

public AssemblyCouldNotBeSignedException(Exception innerException) : base(AssemblyCouldNotBeSignedMessage, innerException)
{
}
}

public class DebugSymbolsCouldNotBeWrittenException : System.ApplicationException { }
internal class Writer {
private Writer(){}
Expand Down Expand Up @@ -5349,90 +5362,20 @@ private static void WritePE(string/*!*/ location, bool writeDebugSymbols, Module
if (keyFileNameDoesNotExist) throw new KeyFileNotFoundException();
if (delaySign || assem == null) return;
if (assem.KeyBlob != null || (assem.KeyContainerName != null && assem.KeyContainerName.Length > 0)){
try{
if (!Writer.StrongNameSignatureGeneration(location, keyName, assem.KeyBlob, assem.KeyBlob == null ? 0 : assem.KeyBlob.Length, IntPtr.Zero, IntPtr.Zero))
throw new AssemblyCouldNotBeSignedException();
}catch{
if (!Writer.MscorsnStrongNameSignatureGeneration(location, keyName, assem.KeyBlob, assem.KeyBlob == null ? 0 : assem.KeyBlob.Length, IntPtr.Zero, IntPtr.Zero))
throw new AssemblyCouldNotBeSignedException();
try
{
ClrStrongName.SignatureGeneration(location, keyName, assem.KeyBlob);
}catch (Exception ex) {
throw new AssemblyCouldNotBeSignedException(ex);
}
}
}
[DllImport("mscoree.dll", EntryPoint="StrongNameSignatureGeneration",
SetLastError=true, CharSet=CharSet.Unicode, ExactSpelling=true,
CallingConvention=CallingConvention.StdCall)]
private static extern bool StrongNameSignatureGeneration(
string wszFilePath, // [in] valid path to the PE file for the assembly
string wszKeyContainer, // [in] desired key container name
[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)]
byte[] pbKeyBlob, // [in] public/private key blob (optional)
int cbKeyBlob,
IntPtr ppbSignatureBlob, // [out] signature blob
IntPtr pcbSignatureBlob);
[DllImport("mscorsn.dll", EntryPoint="StrongNameSignatureGeneration",
SetLastError=true, CharSet=CharSet.Unicode, ExactSpelling=true,
CallingConvention=CallingConvention.StdCall)]
private static extern bool MscorsnStrongNameSignatureGeneration(
string wszFilePath, // [in] valid path to the PE file for the assembly
string wszKeyContainer, // [in] desired key container name
[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)]
byte[] pbKeyBlob, // [in] public/private key blob (optional)
int cbKeyBlob,
IntPtr ppbSignatureBlob, // [out] signature blob
IntPtr pcbSignatureBlob);
private unsafe static byte[] GetPublicKey(AssemblyNode/*!*/ assem) {
private static byte[] GetPublicKey(AssemblyNode/*!*/ assem) {
Debug.Assert(assem != null);
IntPtr publicKey = IntPtr.Zero;
int size;
try{

if (assem.KeyBlob != null){
Writer.StrongNameGetPublicKey(null, assem.KeyBlob, assem.KeyBlob.Length, out publicKey, out size);
if (publicKey == IntPtr.Zero) return assem.KeyBlob;
}else if (assem.KeyContainerName != null){
Writer.StrongNameGetPublicKey(assem.KeyContainerName, null, 0, out publicKey, out size);
if (publicKey == IntPtr.Zero) return null;
}else
return assem.PublicKeyOrToken;
byte[] result = new byte[size];
byte* ptr = (byte*)publicKey;
for (int i = 0; i < size; i++) result[i] = *ptr++;
return result;
}catch{} {
if (assem.KeyBlob != null){
Writer.MscorsnStrongNameGetPublicKeyUsing(null, assem.KeyBlob, assem.KeyBlob.Length, out publicKey, out size);
if (publicKey == IntPtr.Zero) return assem.KeyBlob;
}else if (assem.KeyContainerName != null){
Writer.MscorsnStrongNameGetPublicKeyUsing(assem.KeyContainerName, null, 0, out publicKey, out size);
if (publicKey == IntPtr.Zero) return null;
}else
return assem.PublicKeyOrToken;
byte[] result = new byte[size];
byte* ptr = (byte*)publicKey;
for (int i = 0; i < size; i++) result[i] = *ptr++;
return result;
}
if (assem.KeyContainerName != null) return new Reflection.StrongNameKeyPair(assem.KeyContainerName).PublicKey;
if (assem.KeyBlob != null) return new Reflection.StrongNameKeyPair(assem.KeyBlob).PublicKey;
return assem.PublicKeyOrToken;
}
[DllImport("mscoree.dll", EntryPoint="StrongNameGetPublicKey",
SetLastError=true, CharSet=CharSet.Unicode, ExactSpelling=true,
CallingConvention=CallingConvention.StdCall)]
private static extern bool StrongNameGetPublicKey(
string wszKeyContainer, // [in] desired key container name
[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)]
byte[] pbKeyBlob, // [in] public/private key blob (optional)
int cbKeyBlob,
[Out] out IntPtr ppbPublicKeyBlob, // [out] public key blob
[Out] out int pcbPublicKeyBlob);
[DllImport("mscorsn.dll", EntryPoint="StrongNameGetPublicKey",
SetLastError=true, CharSet=CharSet.Unicode, ExactSpelling=true,
CallingConvention=CallingConvention.StdCall)]
private static extern bool MscorsnStrongNameGetPublicKeyUsing(
string wszKeyContainer, // [in] desired key container name
[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)]
byte[] pbKeyBlob, // [in] public/private key blob (optional)
int cbKeyBlob,
[Out] out IntPtr ppbPublicKeyBlob, // [out] public key blob
[Out] out int pcbPublicKeyBlob);

internal static void WritePE(Stream/*!*/ executable, Stream debugSymbols, Module/*!*/ module) {
MemoryStream mstream = new MemoryStream();
Expand Down