wixtoolset / issues

WiX Toolset Issues Tracker
http://wixtoolset.org/
129 stars 36 forks source link

Heat.exe crash when harvesting native COM dll #5127

Open ghost opened 8 years ago

ghost commented 8 years ago

I have a COM DLL that causes heat.exe to crash. The COM dll is msjava.dll and can be downloaded from http://www.dll-found.com/msjava.dll_download.html. The version I used for testing is 5.0.3234.0 version but the error occurs with both.

The crash does not happen for all COM DLLs.

[System Environment] Heat commandline: heat.exe file msjava.dll -nologo -cg "temp.component.group" -dr INSTALLDIR -srd -suid -svb6 -out out.wxs OS: Windows 8.1, Windows Server 2008R2 WiX: 3.9.1208.0 Visual Studio 2012

When running the above command line on my dev machine, heat.exe does not crash; however, on our build it machine it does. Our build machine is largely identical to my dev machine.

I have built my own version of WiX 3.9 and stepped through in the debugger to find that harvesting is performed as expected (i.e. the output file generated) but when the heat.exe process is closing (after return statement), something causes the whole process to fail (manifest as a "WiX Toolset Harvester has stopped working" dialog.

Sometimes, but not always, I get a PInvokeStackImbalance exception, which is the best hint to date. This exception is thrown in DllHarvester.cs, line 75, when DllRegisterServer is invoked.

The exception details are:

Message: A call to PInvoke function 'wixTempAssembly!::DllRegisterServer' has unbalanced the stack. This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature.

CallStack: [Managed to Native Transition]
[Native to Managed Transition]

WixUtilExtension.dll!Microsoft.Tools.WindowsInstallerXml.Extensions.DllHarvester.DynamicPInvoke(string dll, string entryPoint, System.Type returnType, System.Type[] parameterTypes, object[] parameterValues) Line 75 + 0xf bytes C# WixUtilExtension.dll!Microsoft.Tools.WindowsInstallerXml.Extensions.DllHarvester.HarvestRegistryValues(string file) Line 42 + 0x3b bytes C# WixUtilExtension.dll!Microsoft.Tools.WindowsInstallerXml.Extensions.UtilHarvesterMutator.HarvestSelfReg(Microsoft.Tools.WindowsInstallerXml.Serialize.IParentElement parentElement, string fileSource) Line 203 + 0xd bytes C# WixUtilExtension.dll!Microsoft.Tools.WindowsInstallerXml.Extensions.UtilHarvesterMutator.MutateFile(Microsoft.Tools.WindowsInstallerXml.Serialize.IParentElement parentElement, Microsoft.Tools.WindowsInstallerXml.Serialize.File file) Line 149 + 0xe bytes C# WixUtilExtension.dll!Microsoft.Tools.WindowsInstallerXml.Extensions.UtilHarvesterMutator.MutateElement(Microsoft.Tools.WindowsInstallerXml.Serialize.IParentElement parentElement, Microsoft.Tools.WindowsInstallerXml.Serialize.ISchemaElement element) Line 93 + 0x34 bytes C# WixUtilExtension.dll!Microsoft.Tools.WindowsInstallerXml.Extensions.UtilHarvesterMutator.MutateElement(Microsoft.Tools.WindowsInstallerXml.Serialize.IParentElement parentElement, Microsoft.Tools.WindowsInstallerXml.Serialize.ISchemaElement element) Line 109 + 0x1e bytes C# WixUtilExtension.dll!Microsoft.Tools.WindowsInstallerXml.Extensions.UtilHarvesterMutator.MutateElement(Microsoft.Tools.WindowsInstallerXml.Serialize.IParentElement parentElement, Microsoft.Tools.WindowsInstallerXml.Serialize.ISchemaElement element) Line 109 + 0x1e bytes C# WixUtilExtension.dll!Microsoft.Tools.WindowsInstallerXml.Extensions.UtilHarvesterMutator.MutateElement(Microsoft.Tools.WindowsInstallerXml.Serialize.IParentElement parentElement, Microsoft.Tools.WindowsInstallerXml.Serialize.ISchemaElement element) Line 109 + 0x1e bytes C# WixUtilExtension.dll!Microsoft.Tools.WindowsInstallerXml.Extensions.UtilHarvesterMutator.MutateElement(Microsoft.Tools.WindowsInstallerXml.Serialize.IParentElement parentElement, Microsoft.Tools.WindowsInstallerXml.Serialize.ISchemaElement element) Line 109 + 0x1e bytes C# WixUtilExtension.dll!Microsoft.Tools.WindowsInstallerXml.Extensions.UtilHarvesterMutator.MutateElement(Microsoft.Tools.WindowsInstallerXml.Serialize.IParentElement parentElement, Microsoft.Tools.WindowsInstallerXml.Serialize.ISchemaElement element) Line 109 + 0x1e bytes C# WixUtilExtension.dll!Microsoft.Tools.WindowsInstallerXml.Extensions.UtilHarvesterMutator.Mutate(Microsoft.Tools.WindowsInstallerXml.Serialize.Wix wix) Line 81 + 0xd bytes C# wix.dll!Microsoft.Tools.WindowsInstallerXml.Mutator.Mutate(Microsoft.Tools.WindowsInstallerXml.Serialize.Wix wix) Line 85 + 0xe bytes C# heat.exe!Microsoft.Tools.WindowsInstallerXml.Tools.Heat.Run(string[] args) Line 146 + 0x23 bytes C# heat.exe!Microsoft.Tools.WindowsInstallerXml.Tools.Heat.Main(string[] args) Line 68 + 0xd bytes C# [Native to Managed Transition]
[Managed to Native Transition]
mscorlib.dll!System.AppDomain.ExecuteAssembly(string assemblyFile, System.Security.Policy.Evidence assemblySecurity, string[] args) + 0x6b bytes
Microsoft.VisualStudio.HostingProcess.Utilities.dll!Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() + 0x27 bytes
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart_Context(object state) + 0x6f bytes
mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) + 0xa7 bytes
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) + 0x16 bytes
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) + 0x41 bytes
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart() + 0x44 bytes
[Native to Managed Transition]

heaths commented 8 years ago

The DllRegisterServer entry point should always have the same signature and, of course, is unlikely to change between your dev and build machines. It does lead me to wonder if your dev and build machines are using the exact same version of the .NET Framework, though (considering the major.minor.build version of .NET, as well as any updates available for said version).

ghost commented 8 years ago

I have tried rebuilding an independent machine that exactly mimicked my dev machine (i.e. same OS, Visual Studio, and WiX versions) and it still continues to fail.

I don't think the issue is around the function signature for DllRegisterServer but may have something to do with the calling conventions, as stated in the PInvokeException.

Looking at the WiX harvesting code, I don't believe it accounts for the various calling conventions on Windows, nor do I know how it'll be able to.

Are you able to reproduce the issue? Perhaps you can get a better understanding of the issue in your dev environment.

heaths commented 8 years ago

DllRegisterServer should always use a __stdcall calling convention. That is part of the signature. We could probably handle different calling conventions, but that the function isn't (perhaps) declared properly may lead to other problems.

Is your function declared as __stdcall?

jchoover commented 8 years ago

If the signature is invalid, I would expect regsvr32 to also have the same issue on the machine that heat is failing on.

It would be interesting to compare a dependency walker scan of regsvr32 on the dll between a good and based machine.

On Thursday, December 24, 2015, Heath Stewart notifications@github.com wrote:

DllRegisterServer should always use a __stdcall calling convention. That is part of the signature. We could probably handle different calling conventions, but that the function isn't (perhaps) declared properly may lead to other problems.

Is your function declared as __stdcall?

— Reply to this email directly or view it on GitHub https://github.com/wixtoolset/issues/issues/5127#issuecomment-167141359.

ghost commented 8 years ago

I don't know the calling convention for DllRegisterServer for msjava.dll; it's from a third party. We're using it in one of our products and no one here seems to know too much about it. I don't know if msjava.dll is open sourced or who the publisher is.

On Fri, Dec 25, 2015 at 6:50 AM, Heath Stewart notifications@github.com wrote:

DllRegisterServer should always use a __stdcall calling convention. That is part of the signature. We could probably handle different calling conventions, but that the function isn't (perhaps) declared properly may lead to other problems.

Is your function declared as __stdcall?

— Reply to this email directly or view it on GitHub https://github.com/wixtoolset/issues/issues/5127#issuecomment-167141359.