-
Notifications
You must be signed in to change notification settings - Fork 123
Description
Describe the bug
Opening this as part of an investigation into a NativeAOT crash I noticed in ComputeSharp, which we've been trying to narrow down (as a collaborative effort over in the C# Discord). While trying to put together a minimal repro, I couldn't quite reproduce the same crash (which seems to be something going wrong in ComWrappers on NAOT), but I still noticed what seems to be incorrect behavior on NAOT, so here's a separate issue to track that. Not entirely sure whether this is more an issue with ComWrappers or CsWinRT, so opening it here for now. Will try to create a ComWrappers-only repro too later on to see if it also repros with just that.
To Reproduce
- Create a new project with
new7-windows10.0.22621as TFM - Paste the following code:
Code (click to expand):
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using WinRT.Interop;
using WinRT;
unsafe
{
DummyUnknown unknown = new();
for (int i = 0; i < 10; i++)
{
var value2 = MarshalInspectable<object>.CreateMarshaler2(unknown);
try
{
var abi = (IUnknownVftbl*)value2.GetAbi();
var guid = new Guid("33D8B971-2ABF-4A2B-8071-1FFCBCBC8124");
DummyUnknownAbi* ppv = null;
ExceptionHelpers.ThrowExceptionForHR(Marshal.QueryInterface((IntPtr)abi, ref guid, out *(IntPtr*)&ppv));
Console.WriteLine($"{i}: {ppv->GetNumber()}");
ppv->Release();
}
finally
{
MarshalInspectable<object>.DisposeMarshaler(value2);
}
}
}
Console.WriteLine("Done!");
public unsafe class DummyUnknown : IDummyUnknown
{
private int number = 42;
public int GetNumber()
{
return number++;
}
}
public unsafe struct DummyUnknownAbi
{
public void** lpVtbl;
public int QueryInterface(Guid* riid, void** ppvObject)
{
return ((delegate* unmanaged[Stdcall]<DummyUnknownAbi*, Guid*, void**, int>)lpVtbl[0])((DummyUnknownAbi*)Unsafe.AsPointer(ref this), riid, ppvObject);
}
public uint AddRef()
{
return ((delegate* unmanaged[Stdcall]<DummyUnknownAbi*, uint>)lpVtbl[1])((DummyUnknownAbi*)Unsafe.AsPointer(ref this));
}
public uint Release()
{
return ((delegate* unmanaged[Stdcall]<DummyUnknownAbi*, uint>)lpVtbl[2])((DummyUnknownAbi*)Unsafe.AsPointer(ref this));
}
public int GetNumber()
{
return ((delegate* unmanaged[Stdcall]<DummyUnknownAbi*, int>)lpVtbl[3])((DummyUnknownAbi*)Unsafe.AsPointer(ref this));
}
}
[Guid("33D8B971-2ABF-4A2B-8071-1FFCBCBC8124")]
[WindowsRuntimeType]
[WindowsRuntimeHelperType(typeof(IDummyUnknown))]
public interface IDummyUnknown
{
int GetNumber();
[Guid("33D8B971-2ABF-4A2B-8071-1FFCBCBC8124")]
public unsafe struct Vftbl
{
public static readonly IntPtr AbiToProjectionVftablePtr = InitVtbl();
private static IntPtr InitVtbl()
{
Vftbl* lpVtbl = (Vftbl*)ComWrappersSupport.AllocateVtableMemory(typeof(Vftbl), sizeof(Vftbl));
lpVtbl->IUnknownVftbl = IUnknownVftbl.AbiToProjectionVftbl;
lpVtbl->GetNumber = &GetNumberFromAbi;
return (IntPtr)lpVtbl;
}
internal IUnknownVftbl IUnknownVftbl;
internal delegate* unmanaged[Stdcall]<IntPtr, int> GetNumber;
[UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvStdcall) })]
private static int GetNumberFromAbi(IntPtr thisPtr)
{
try
{
return ComWrappersSupport.FindObject<IDummyUnknown>(thisPtr).GetNumber();
}
catch (Exception e)
{
ExceptionHelpers.SetErrorInfo(e);
return Marshal.GetHRForException(e);
}
}
}
}- Add
<PublishAot>true</PublishAot>to the .csproj file - Publish with NAOT:
msbuild ComWrappersRepro.csproj -t:restore,publish /p:Configuration=Release /p:Platform=x64 /p:RuntimeIdentifier=win10-x64 /p:TreatWarningsAsErrors=FalseExpected behavior
0: 42
1: 43
2: 44
3: 45
4: 46
5: 47
6: 48
7: 49
8: 50
9: 51
Done!
This is what you also get with a normal F5 deploy.
Actual behavior
0: 42
1: -2147467261
2: -2147467261
3: -2147467261
4: -2147467261
5: -2147467261
6: -2147467261
7: -2147467261
8: -2147467261
9: -2147467261
Done!
...?!?!?? wha-