-
Notifications
You must be signed in to change notification settings - Fork 1k
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
Conversation
The build is failing |
@AaronRobinsonMSFT @JeremyKuhne I'd appreciate it if you could review this. |
[UnmanagedCallersOnly] | ||
private static HRESULT GetData(IntPtr thisPtr, FORMATETC* format, STGMEDIUM_Raw* pMedium) | ||
{ | ||
var inst = ComInterfaceDispatch.GetInstance<IDataObject>((ComInterfaceDispatch*)thisPtr); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nit]
var inst = ComInterfaceDispatch.GetInstance<IDataObject>((ComInterfaceDispatch*)thisPtr); | |
var instance = ComInterfaceDispatch.GetInstance<IDataObject>((ComInterfaceDispatch*)thisPtr); |
ditto other places
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; |
There was a problem hiding this comment.
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
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
src/System.Windows.Forms.Primitives/src/Interop/WinFormsComWrappers.IDataObjectVtbl.cs
Show resolved
Hide resolved
src/System.Windows.Forms.Primitives/src/Interop/WinFormsComWrappers.IDataObjectVtbl.cs
Outdated
Show resolved
Hide resolved
@kant2002 can you please summarize what was broken and why? |
@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. |
src/System.Windows.Forms.Primitives/src/Interop/Ole32/Interop.DoDragDrop.cs
Outdated
Show resolved
Hide resolved
src/System.Windows.Forms.Primitives/src/Interop/WinFormsComWrappers.IDataObjectVtbl.cs
Outdated
Show resolved
Hide resolved
src/System.Windows.Forms.Primitives/src/Interop/WinFormsComWrappers.IDataObjectVtbl.cs
Show resolved
Hide resolved
return result; | ||
} | ||
|
||
result = RegisterDragDrop(hwnd.Handle, dropTargetPtr); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
QueryInterface
-> +1 refRegisterDragDrop
-> +1 refRevokeDragDrop
-> -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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
Progress towards dotnet#5163
2ff1c87
to
0ef6b07
Compare
- Trace exceptions - Use helper functions to simplify interop - Use object initializer
src/System.Windows.Forms.Primitives/src/Interop/Ole32/Interop.DoDragDrop.cs
Show resolved
Hide resolved
src/System.Windows.Forms.Primitives/src/Interop/WinFormsComWrappers.IDataObjectVtbl.cs
Show resolved
Hide resolved
src/System.Windows.Forms.Primitives/src/Interop/WinFormsComWrappers.IDataObjectVtbl.cs
Show resolved
Hide resolved
There was a problem hiding this 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.
{ | ||
STGMEDIUM medium = new() | ||
{ | ||
pUnkForRelease = pMedium->pUnkForRelease == IntPtr.Zero ? null : Marshal.GetObjectForIUnknown(pMedium->pUnkForRelease), |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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 ?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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().
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I update #7162
Progress towards #5163
Microsoft Reviewers: Open in CodeFlow