Skip to content
This repository has been archived by the owner on Nov 1, 2020. It is now read-only.

Add simple marshaller which marshal only null COM interfaces #8128

Merged
merged 7 commits into from
May 6, 2020
Merged

Add simple marshaller which marshal only null COM interfaces #8128

merged 7 commits into from
May 6, 2020

Conversation

kant2002
Copy link
Contributor

@kant2002 kant2002 commented May 2, 2020

This idea was proposed by @MichalStrehovsky in #7994

Implemented only marshalling of in parameters, since this is case which I found in the stack trace of the issue. I think other directions can be implemented in same way, I just lack of examples for testing.

Tested code

// [DllImport(Libraries.UiaCore, CharSet = CharSet.Unicode)]
// public static extern IntPtr UiaReturnRawElementProvider(IntPtr hwnd, IntPtr wParam, IntPtr lParam, IRawElementProviderSimple el);
IntPtr result = UiaCore.UiaReturnRawElementProvider(IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, null);

Closes #7994

This idea was proposed by @MichalStrehovsky in #7994

Implemented only marshalling of `in` parameters, since this is case which I found in the stack trace of the issue. I think other directions can be implemented in same way, I just lack of examples for testing.

Tested code
```
// [DllImport(Libraries.UiaCore, CharSet = CharSet.Unicode)]
// public static extern IntPtr UiaReturnRawElementProvider(IntPtr hwnd, IntPtr wParam, IntPtr lParam, IRawElementProviderSimple el);
IntPtr result = UiaCore.UiaReturnRawElementProvider(IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, null);
```

Closes #7994
ILEmitter emitter = _ilCodeStreams.Emitter;

// Check if we marshall null pointer
ILCodeLabel lNullInterface = emitter.NewCodeLabel();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be better to call a helper method to do this instead of inlining the logic here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what should I do. If you asking about labels creation, then this is how BlittableArrayMarshaller implemented. In a sense for sure, but they are directly created there. I understand that maybe I can create helper method for reporting that scenario not supported (throwing exception code) but you point to different location. I'm lost. Can you clarify?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant add a method to InteropHelpers and just call it from here to do all the work. Many marshalers are implemented like that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do I properly understand you, that I add code in the System.Private.CoreLib and then marshaller will just assume that classlib has that method, and just call that method. Am I correctly understand you?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it is exactly what I meant.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jkotas It's magic. Much easier then I initially thought how it should be done!

@@ -407,6 +407,26 @@ public static IntPtr GetCurrentCalleeOpenStaticDelegateFunctionPointer()
return PInvokeMarshal.GetCurrentCalleeDelegate<T>();
}

public static object ConvertManagedComInterfaceToNative(object pUnk)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public static object ConvertManagedComInterfaceToNative(object pUnk)
public static IntPtr ConvertManagedComInterfaceToNative(object pUnk)

The type to use for the unmanaged side should be IntPtr.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(multiple places)

return null;
}

throw new PlatformNotSupportedException("Marhalling of non null COM interfaces does not supported");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
throw new PlatformNotSupportedException("Marhalling of non null COM interfaces does not supported");
throw new PlatformNotSupportedException("Marhalling of non-null COM interfaces is not supported");

@jkotas jkotas mentioned this pull request May 3, 2020
Copy link
Member

@MichalStrehovsky MichalStrehovsky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good modulo the type thing, thanks!

Would you mind adding a test for this under tests\src\Simple\PInvoke? There's a CPP file to put unmanaged code into, and a CS file with managed code.

@@ -68,6 +68,7 @@ public static partial class MarshalHelpers
case MarshallerKind.BlittableStruct:
case MarshallerKind.Decimal:
case MarshallerKind.VoidReturn:
case MarshallerKind.ComInterface:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be some kind of a pointer, not type. E.g. return context.GetWellKnownType(WellKnownType.IntPtr);

(This is the native type we marshal into. Leaving this at type would hit RyuJIT asserts added in dotnet/runtime#35026 because type is a GC pointer. Once marshalling is done, this is an unmanaged pointer.)

return IntPtr.Zero;
}

throw new PlatformNotSupportedException("Marhalling of non null COM interfaces is not supported");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
throw new PlatformNotSupportedException("Marhalling of non null COM interfaces is not supported");
throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop);

@kant2002
Copy link
Contributor Author

kant2002 commented May 4, 2020

@MichalStrehovsky I was little bit lazy and do not create specific functions in native code. I take existing sample which I have. Should I implement function for marshalling in native code?

@MichalStrehovsky
Copy link
Member

Should I implement function for marshalling in native code?

Yes please - it will be even less code that way (the interface doesn't need to have any members, etc.).

I don't know what UI automation would do with this call - I don't want the test to accidentally break screen readers, so it's better to call into "known" code.

@MichalStrehovsky MichalStrehovsky merged commit 3216e1a into dotnet:master May 6, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Windows Forms] Form.Close crash application
3 participants