Actual behavior
Generated APIs that take [In] NativeOverlapped object don't work, causing null refs in the callbacks when trying to retrieve the original state.
Expected behavior
We've (@AaronRobinsonMSFT ) found that NativeOverlapped parameters need to be passed by ref (NativeOverlapped*) in both generated signatures so that the native call can correctly update the value.
Repro steps
NativeMethods.txt content:
Generated API:
internal static unsafe uint HttpReceiveHttpRequest(SafeHandle RequestQueueHandle, ulong RequestId, winmdroot.Networking.HttpServer.HTTP_RECEIVE_HTTP_REQUEST_FLAGS Flags, out winmdroot.Networking.HttpServer.HTTP_REQUEST_V2 RequestBuffer, uint RequestBufferLength, uint* BytesReturned, global::System.Threading.NativeOverlapped? Overlapped)
{
bool RequestQueueHandleAddRef = false;
try
{
fixed (winmdroot.Networking.HttpServer.HTTP_REQUEST_V2* RequestBufferLocal = &RequestBuffer)
{
winmdroot.Foundation.HANDLE RequestQueueHandleLocal;
if (RequestQueueHandle is object)
{
RequestQueueHandle.DangerousAddRef(ref RequestQueueHandleAddRef);
RequestQueueHandleLocal = (winmdroot.Foundation.HANDLE)RequestQueueHandle.DangerousGetHandle();
}
else
throw new ArgumentNullException(nameof(RequestQueueHandle));
global::System.Threading.NativeOverlapped OverlappedLocal = Overlapped ?? default(global::System.Threading.NativeOverlapped);
uint __result = PInvoke.HttpReceiveHttpRequest(RequestQueueHandleLocal, RequestId, Flags, RequestBufferLocal, RequestBufferLength, BytesReturned, Overlapped.HasValue ? &OverlappedLocal : null);
return __result;
}
}
finally
{
if (RequestQueueHandleAddRef)
RequestQueueHandle.DangerousRelease();
}
}
internal static extern unsafe uint HttpReceiveHttpRequest(winmdroot.Foundation.HANDLE RequestQueueHandle, ulong RequestId, winmdroot.Networking.HttpServer.HTTP_RECEIVE_HTTP_REQUEST_FLAGS Flags, winmdroot.Networking.HttpServer.HTTP_REQUEST_V2* RequestBuffer, uint RequestBufferLength, [Optional] uint* BytesReturned, [Optional] global::System.Threading.NativeOverlapped* Overlapped);
// From
HTTPAPI_LINKAGE ULONG HttpReceiveHttpRequest(
[in] HANDLE RequestQueueHandle,
[in] HTTP_REQUEST_ID RequestId,
[in] ULONG Flags,
[out] PHTTP_REQUEST RequestBuffer,
[in] ULONG RequestBufferLength,
[out, optional] PULONG BytesReturned,
[in, optional] LPOVERLAPPED Overlapped
);
When I copy and modify the generated code as follows it works:
[SupportedOSPlatform("windows6.0.6000")]
internal static unsafe uint HttpReceiveHttpRequest(SafeHandle RequestQueueHandle, ulong RequestId, winmdroot.Networking.HttpServer.HTTP_RECEIVE_HTTP_REQUEST_FLAGS Flags, out winmdroot.Networking.HttpServer.HTTP_REQUEST_V2 RequestBuffer, uint RequestBufferLength, uint* BytesReturned, global::System.Threading.NativeOverlapped* Overlapped)
{
bool RequestQueueHandleAddRef = false;
try
{
fixed (winmdroot.Networking.HttpServer.HTTP_REQUEST_V2* RequestBufferLocal = &RequestBuffer)
{
winmdroot.Foundation.HANDLE RequestQueueHandleLocal;
if (RequestQueueHandle is object)
{
RequestQueueHandle.DangerousAddRef(ref RequestQueueHandleAddRef);
RequestQueueHandleLocal = (winmdroot.Foundation.HANDLE)RequestQueueHandle.DangerousGetHandle();
}
else
throw new ArgumentNullException(nameof(RequestQueueHandle));
uint __result = PInvoke.HttpReceiveHttpRequest(RequestQueueHandleLocal, RequestId, Flags, RequestBufferLocal, RequestBufferLength, BytesReturned, Overlapped);
return __result;
}
}
finally
{
if (RequestQueueHandleAddRef)
RequestQueueHandle.DangerousRelease();
}
}
I found #545 which first introduced NativeOverlapped support for ReadFile and I see that NativeOverlapped* is generated correctly there.
internal static unsafe winmdroot.Foundation.BOOL ReadFile(SafeHandle hFile, Span<byte> lpBuffer, uint* lpNumberOfBytesRead, global::System.Threading.NativeOverlapped* lpOverlapped) { ... }
// From
BOOL ReadFile(
[in] HANDLE hFile,
[out] LPVOID lpBuffer,
[in] DWORD nNumberOfBytesToRead,
[out, optional] LPDWORD lpNumberOfBytesRead,
[in, out, optional] LPOVERLAPPED lpOverlapped
);
Any of your own code that should be shared?
Use generated PInvokes and exchange types dotnet/aspnetcore#50685
Context
CsWin32 version: 0.3.18-beta
Target Framework: net9.0
LangVersion preview
Actual behavior
Generated APIs that take [In] NativeOverlapped object don't work, causing null refs in the callbacks when trying to retrieve the original state.
Expected behavior
We've (@AaronRobinsonMSFT) found that NativeOverlapped parameters need to be passed by ref (NativeOverlapped*) in both generated signatures so that the native call can correctly update the value.
Repro steps
NativeMethods.txtcontent:Generated API:
When I copy and modify the generated code as follows it works:
I found #545 which first introduced NativeOverlapped support for ReadFile and I see that NativeOverlapped* is generated correctly there.
Use generated PInvokes and exchange types dotnet/aspnetcore#50685
Context
LangVersionpreview