Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide CCW for IDataObject #6976

Merged
merged 7 commits into from
Apr 21, 2022
Merged

Conversation

kant2002
Copy link
Contributor

@kant2002 kant2002 commented Apr 6, 2022

Progress towards #5163

Microsoft Reviewers: Open in CodeFlow

@kant2002 kant2002 requested a review from a team as a code owner April 6, 2022 09:44
@ghost ghost assigned kant2002 Apr 6, 2022
@RussKie
Copy link
Member

RussKie commented Apr 6, 2022

The build is failing

@RussKie
Copy link
Member

RussKie commented Apr 6, 2022

@AaronRobinsonMSFT @JeremyKuhne I'd appreciate it if you could review this.

@RussKie RussKie requested a review from JeremyKuhne April 6, 2022 23:29
[UnmanagedCallersOnly]
private static HRESULT GetData(IntPtr thisPtr, FORMATETC* format, STGMEDIUM_Raw* pMedium)
{
var inst = ComInterfaceDispatch.GetInstance<IDataObject>((ComInterfaceDispatch*)thisPtr);
Copy link
Member

Choose a reason for hiding this comment

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

[nit]

Suggested change
var inst = ComInterfaceDispatch.GetInstance<IDataObject>((ComInterfaceDispatch*)thisPtr);
var instance = ComInterfaceDispatch.GetInstance<IDataObject>((ComInterfaceDispatch*)thisPtr);

ditto other places

Comment on lines 58 to 66
STGMEDIUM medium = new();
medium.pUnkForRelease = Marshal.GetObjectForIUnknown(pMedium->pUnkForRelease);
medium.tymed = pMedium->tymed;
medium.unionmember = pMedium->unionmember;
inst.GetDataHere(ref *format, ref medium);
pMedium->pUnkForRelease = medium.pUnkForRelease == null ? IntPtr.Zero : Marshal.GetIUnknownForObject(medium.pUnkForRelease);
pMedium->tymed = medium.tymed;
pMedium->unionmember = medium.unionmember;
return HRESULT.S_OK;
Copy link
Member

Choose a reason for hiding this comment

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

The code would benefit from reformatting and having few empty lines to improve readability

Suggested change
STGMEDIUM medium = new();
medium.pUnkForRelease = Marshal.GetObjectForIUnknown(pMedium->pUnkForRelease);
medium.tymed = pMedium->tymed;
medium.unionmember = pMedium->unionmember;
inst.GetDataHere(ref *format, ref medium);
pMedium->pUnkForRelease = medium.pUnkForRelease == null ? IntPtr.Zero : Marshal.GetIUnknownForObject(medium.pUnkForRelease);
pMedium->tymed = medium.tymed;
pMedium->unionmember = medium.unionmember;
return HRESULT.S_OK;
STGMEDIUM medium = new()
{
pUnkForRelease = Marshal.GetObjectForIUnknown(pMedium->pUnkForRelease);
tymed = pMedium->tymed;
unionmember = pMedium->unionmember;
};
instance.GetDataHere(ref *format, ref medium);
pMedium->pUnkForRelease = medium.pUnkForRelease is null ? IntPtr.Zero : Marshal.GetIUnknownForObject(medium.pUnkForRelease);
pMedium->tymed = medium.tymed;
pMedium->unionmember = medium.unionmember;
return HRESULT.S_OK;

ditto other places

@RussKie RussKie added the waiting-author-feedback The team requires more information from the author label Apr 6, 2022
@JeremyKuhne
Copy link
Member

@kant2002 can you please summarize what was broken and why?

@kant2002
Copy link
Contributor Author

kant2002 commented Apr 7, 2022

@JeremyKuhne better look at this #6981. Yesterday I was probably in a rush to fix, and did not realize that much smaller fix needed. I think for validation that would be easier fix to get, since if you ask me to add tests it can be a much bigger change, and I do want Preview 4 to be in working conditions.

We will still need these changes.

@ghost ghost removed the waiting-author-feedback The team requires more information from the author label Apr 7, 2022
@RussKie RussKie added the waiting-review This item is waiting on review by one or more members of team label Apr 7, 2022
return result;
}

result = RegisterDragDrop(hwnd.Handle, dropTargetPtr);
Copy link

Choose a reason for hiding this comment

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

This might be a silly question (still wrapping my head around ComWrappers for my own project): Where/how does dropTargetPtr actually get released? My understanding is that QueryInterface increments its ref count by 1, but I see no (obvious) matching Release anywhere.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

RegisterDeagDrop also call AddRef. So as RevokeDragDrop https://docs.microsoft.com/en-us/windows/win32/api/ole2/nf-ole2-revokedragdrop#remarks

Releasing of this object in this particular case happens on unmanaged part.

Copy link

Choose a reason for hiding this comment

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

Hmm, I think I'm still confused.

  1. QueryInterface -> +1 ref
  2. RegisterDragDrop -> +1 ref
  3. RevokeDragDrop -> -1 ref

Seems like we're missing a decrement in the process? A Release after RegisterDragDrop would make sense to me since RegisterDragDrop will already have incremented the ref count in order to be able to hang onto the object.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think you are right. and after passing pointer to RegisterDragDrop we should release it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I apply these suggestion in the #6981 because that's smallest PR which is fix the bug, and here is too much additional stuff.

Copy link

Choose a reason for hiding this comment

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

FWIW, I think there were other uses of GetComPointer / GetOrCreateComInterfaceForObject with the same problem when I was looking through the COM interop code in WinForms. Might want to double-check all uses of these.

@kant2002 kant2002 changed the title Properly use QI for all ComWrapper created instances Provide CCW for IDataObject Apr 16, 2022
- Trace exceptions
- Use helper functions to simplify interop
- Use object initializer
Copy link
Member

@AaronRobinsonMSFT AaronRobinsonMSFT left a comment

Choose a reason for hiding this comment

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

@RussKie and @JeremyKuhne This LGTM.

@Tanya-Solyanik Tanya-Solyanik removed the waiting-review This item is waiting on review by one or more members of team label Apr 21, 2022
@Tanya-Solyanik Tanya-Solyanik merged commit d24596e into dotnet:main Apr 21, 2022
@ghost ghost added this to the 7.0 Preview5 milestone Apr 21, 2022
@kant2002 kant2002 deleted the kant/issue-6952 branch April 22, 2022 01:44
{
STGMEDIUM medium = new()
{
pUnkForRelease = pMedium->pUnkForRelease == IntPtr.Zero ? null : Marshal.GetObjectForIUnknown(pMedium->pUnkForRelease),
Copy link
Contributor

Choose a reason for hiding this comment

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

I see a System.ExecutionEngineException getting thrown here after merging these changes.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@willibrandon Can you give me test case ?

Copy link
Contributor

Choose a reason for hiding this comment

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

Working on a mini test case now and will get it to you asap.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Separate question. Should I test on your branch?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

And you can give me vague hints, so I can try repro separately. Do not like when my work broke something.

Copy link
Contributor

Choose a reason for hiding this comment

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

Sorry for being vague, it was late for me last night and was stuck in meeting today. I have not yet confirmed if I can reproduce the issue on the main branch but I'm taking a look now. It could be something that I'm doing incorrectly so first let me confirm a verifiable scenario exists before you waste time looking into it.

Copy link
Contributor

@willibrandon willibrandon May 7, 2022

Choose a reason for hiding this comment

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

ExecutionEngineException might take me some time to confirm, and it could be an issue on my end, so please bear with me. Leading up to that I see NotImplementedException thrown in WinFormsComWrappers, ComputeVtables.

System.NotImplementedException: 'ComWrappers for type System.Windows.Forms.DataObject+FormatEnumerator not implemented.'

That I can also observe on the main branch while debugging DragDrop_QueryDefaultCursors_Async().

Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need to add a ComWrappers IEnumFORMATETC implementation?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That should handled by #7087


internal struct STGMEDIUM_Raw
{
public IntPtr pUnkForRelease;
Copy link
Contributor

Choose a reason for hiding this comment

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

It seems the ExecutionEngineException was due to the STGMEDIUM_Raw struct fields being out of order? But I see it is fixed in #7087.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ooh, yeah. You are right. I forget about that problem.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I update #7162

@ghost ghost locked as resolved and limited conversation to collaborators Jun 10, 2022
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.

7 participants