Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Conversation

@jevansaks
Copy link
Member

@jevansaks jevansaks commented Nov 13, 2025

One reason that parameters were still showing up as pointers in the friendly overloads was because of [optional, out] parameters. For example, IWbemServices.GetObject has two out parameters which are optional and are also interfaces. As we've seen with other optional out/ref parameters, we have to leave these as pointers in the ABI so that they can be passed as "null". #1511 improved things for optional out/ref types that are trivially marshallable, but a case that is particularly unpleasant to deal with as pointers is COM interfaces.

This change improves things so that on the friendly overload that includes optional parameters, the out/ref interfaces are upgraded to managed interfaces and the implementation handles the COM marshalling both for source-generated COM and built-in COM. The helpers also handle Unsafe.NullRef<T> being passed in for the optional parameters in case you want to omit some, same as you can do with the upgraded optional value type params.

I added a test case that demonstrates calling IWbemServices.GetObject which is much simpler than the unmanaged alternative.

I also fixed a couple other minor things:

  • Added the GeneratedCode attribute to PCWSTR and friends
  • NativeOverlapped should always be a pointer even when not [Retained]
  • VARIANT_unmanaged in signatures should be ComVariant

Here's what the generated code looks like (for a function that has just one optional out parameter of this kind) if you don't want to build locally to take a look:

internal static unsafe void DeleteClass(this winmdroot.System.Wmi.IWbemServices @this, SafeHandle strClass, winmdroot.System.Wmi.WBEM_GENERIC_FLAG_TYPE lFlags, winmdroot.System.Wmi.IWbemContext pCtx, ref winmdroot.System.Wmi.IWbemCallResult ppCallResult)
{
	bool strClassAddRef = false;
	winmdroot.System.Wmi.IWbemCallResult_unmanaged* __ppCallResult_native = null;
	bool __ppCallResult_present = !Unsafe.IsNullRef<winmdroot.System.Wmi.IWbemCallResult>(ref ppCallResult);
	try
	{
		winmdroot.Foundation.BSTR strClassLocal;
		if (strClass is object)
		{
			strClass.DangerousAddRef(ref strClassAddRef);
			strClassLocal = (winmdroot.Foundation.BSTR)strClass.DangerousGetHandle();
		}
		else
			throw new ArgumentNullException(nameof(strClass));
		if (__ppCallResult_present)
		{
			__ppCallResult_native = (winmdroot.System.Wmi.IWbemCallResult_unmanaged*)global::System.Runtime.InteropServices.Marshalling.ComInterfaceMarshaller<winmdroot.System.Wmi.IWbemCallResult>.ConvertToUnmanaged(ppCallResult);
		}
		@this.DeleteClass(strClassLocal, lFlags, pCtx, __ppCallResult_present ? &__ppCallResult_native : null);
		if (__ppCallResult_present)
		{
			ppCallResult = global::System.Runtime.InteropServices.Marshalling.ComInterfaceMarshaller<winmdroot.System.Wmi.IWbemCallResult>.ConvertToManaged(__ppCallResult_native);
		}
	}
	finally
	{
		if (strClassAddRef)
			strClass.DangerousRelease();
		global::System.Runtime.InteropServices.Marshalling.ComInterfaceMarshaller<winmdroot.System.Wmi.IWbemCallResult>.Free(__ppCallResult_native);
	}
}

Fixes #1066, Fixes #1528, Fixes #1216, Fixes #1185, Fixes #1066, Fixes #137

Add generated code attribute to PCWSTR

Add test case that exercises optional out

Fix failure that happens sometimes from GetAllWindows test running in parallel with tests that create windows

Add built-in com generation for optional out parameters
@jevansaks jevansaks requested a review from manodasanW November 14, 2025 17:13
test/GenerationSandbox.Tests/BasicTests.cs Show resolved Hide resolved
@jevansaks jevansaks enabled auto-merge (squash) November 15, 2025 02:15
@jevansaks jevansaks merged commit fe382a4 into main Nov 15, 2025
7 checks passed
@jevansaks jevansaks deleted the user/jevansaks/optionaloutinterfaces branch November 15, 2025 02:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

3 participants

Morty Proxy This is a proxified and sanitized view of the page, visit original site.