Actual behavior
When generating a SafeHandle for a handle type whose release method returns NTSTATUS, CsWin32 fails during source generation:
PInvoke000: An internal error occurred: Failed while generating extern method: MySubscribeFunction.
Failed while generating SafeHandle for MyReleaseFunction.
Unable to find expected constant: STATUS_SUCCESS.
This occurs when the release method is defined in a custom ProjectionMetadataWinmd, while STATUS_SUCCESS is defined in the standard Win32Metadata winmd. Both winmds are loaded as ProjectionMetadataWinmd items.
In Generator.Handle.cs, the case "NTSTATUS" block calls this.TryGenerateConstantOrThrow("STATUS_SUCCESS") on the individual Generator instance, which only searches its own MetadataIndex. SuperGenerator provides cross-metadata search for types, methods, and enums,
but not for constants — so STATUS_SUCCESS from Win32Metadata is invisible during SafeHandle generation.
Expected behavior
CsWin32 should find STATUS_SUCCESS in Win32Metadata when generating a SafeHandle, since it's loaded as a ProjectionMetadataWinmd input alongside the custom winmd.
Repro steps
-
NativeMethods.txt content:
MyReleaseFunction
-
NativeMethods.json content (if present):
{
"$schema": "https://aka.ms/CsWin32.schema.json",
"emitSingleFile": true
}
-
Any of your own code that should be shared?
Create a custom winmd (via WinmdGenerator) containing:
- A handle typedef mapped via autoTypes.json with a release method that returns NTSTATUS
- Do NOT define STATUS_SUCCESS in the custom winmd
Reference both the custom winmd and Win32Metadata as ProjectionMetadataWinmd items in the consuming project:
Workaround: Define STATUS_SUCCESS in the custom winmd's source header so it gets scraped into the custom winmd:
#ifndef STATUS_SUCCESS
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
#endif
Context
- CsWin32 version: 0.3.213 and 0.3.269 (both reproduce)
- Win32Metadata version: default (via CsWin32 dependency)
- Target Framework: netstandard2.0
- LangVersion: not explicitly set
This issue was drafted with the assistance of GitHub Copilot.
Actual behavior
When generating a SafeHandle for a handle type whose release method returns NTSTATUS, CsWin32 fails during source generation:
PInvoke000: An internal error occurred: Failed while generating extern method: MySubscribeFunction.
Failed while generating SafeHandle for MyReleaseFunction.
Unable to find expected constant: STATUS_SUCCESS.
This occurs when the release method is defined in a custom ProjectionMetadataWinmd, while STATUS_SUCCESS is defined in the standard Win32Metadata winmd. Both winmds are loaded as ProjectionMetadataWinmd items.
In Generator.Handle.cs, the case "NTSTATUS" block calls this.TryGenerateConstantOrThrow("STATUS_SUCCESS") on the individual Generator instance, which only searches its own MetadataIndex. SuperGenerator provides cross-metadata search for types, methods, and enums,
but not for constants — so STATUS_SUCCESS from Win32Metadata is invisible during SafeHandle generation.
Expected behavior
CsWin32 should find STATUS_SUCCESS in Win32Metadata when generating a SafeHandle, since it's loaded as a ProjectionMetadataWinmd input alongside the custom winmd.
Repro steps
NativeMethods.txt content:
MyReleaseFunctionNativeMethods.json content (if present):
{ "$schema": "https://aka.ms/CsWin32.schema.json", "emitSingleFile": true }Any of your own code that should be shared?
Create a custom winmd (via WinmdGenerator) containing:
Reference both the custom winmd and Win32Metadata as ProjectionMetadataWinmd items in the consuming project:
Workaround: Define STATUS_SUCCESS in the custom winmd's source header so it gets scraped into the custom winmd:
#ifndef STATUS_SUCCESS
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
#endif
Context
This issue was drafted with the assistance of GitHub Copilot.