Open vsfeedback opened 1 month ago
Can you please provide a minimal sample repro?
The ID for the registered format is 0xC079 (RegisterClipboardFormat reserves 0xC000 to 0xFFFF for custom formats).
FORMATETC defines the format IDs as 2 bytes (WORD
), RegisterClipboardFormat is using UINT
, which well, the typedef used to be 16bit, not 32 as it is now.
Now, since history class is over, WPF defines clipboard format as Int32
because UInt16
wouldn't be CLS compliant is my guess (which wouldn't matter now in case of WPF but earlier they were really scared of unsigned types).
InternalGetDataFormat
will mask out the top 2 bytes and match only on the two low ones, however the value underlying value is still saved as Int32
.
I guess simple solution would be to add a debug display attribute for DataFormat to stop confusing people.
I guess simple solution would be to add a debug display attribute for DataFormat to stop confusing people.
I don't think that's the issue right, the issue is that ContainsData
wrongly returns false
.
I might want to read the whole issue instead of checking the image I guess.
Hah, yeah, well, that will happen.
I also believe the CLS compliance is only concerned about publicly exposed types. I don't see why we couldn't change the pinvoke signatures to uint
and have only the public DataFormat.ID
cast to int
.
Well that's not really the problem, is it. You have 2 high bytes that shouldn't be there.
Formats are just undocumented atoms (ATOM's typedef is WORD - UInt16 mapping), RegisterClipboardFormat
is just RegisterWindowMessage
, which is just a wrapper for win32u.NtUserRegisterWindowMessage
; so it already comes from kernel, because it uses extended (4byte) registers to pass down the value (as you would expect for UInt32
).
Now the fun part is that we use RegisterWindowMessage
in a lot of places, and never downcasted to UInt16 either, which might create some fun bugs if something like this actually happens. I can't force it.
Eitherway, in my mind, the solution is to just define the PInvokes as UInt16
that deal with atoms, since you cannot get more usable bit width out of them.
Regarding CLS compliance you're correct afaik, I also mentioned that because of DataFormat
being a public type hence Id
being an int
.
I am not very keen on declaring PInvokes using different parameter types than they are documented/declared in native code and relying on undocumented assumptions. We could also just fix the number when calling ContainsData
(although since the ctor accepts int and is public, we should probably not do that). Either way, can we have a repro? I cannot reproduce it easily.
Well, I wouldn't say undocumented. If you go onto Atom Tables overview (https://learn.microsoft.com/en-us/windows/win32/dataxchg/about-atom-tables); you're gonna get a whole portion of how it is an atom (and its true, in kernel they're stored alongside).
Yeah I wouldn't apply the fix onto ContainsData
tbh. But the repro is something I wanna see because it doesn't make sense. My guess is there's some detour in the call-chain and that's how those two bytes got returned to us in the first place.
This issue has been moved from a ticket on Developer Community.
[severity:It's more difficult to complete my work] I am running into some edge cases in my application where registering a clipboard format returns a negative format ID, so the DataFormat that is created has a negative ID.
When this happens, if I call
Clipboard.ContainsData()
with my formats, it returns false, even though the formats are in the _formatList and they are on the clipboard.What causes the format ID to be negative?
Original Comments
Feedback Bot on 9/19/2024, 06:55 AM:
We have directed your feedback to the appropriate engineering team for further evaluation. The team will review the feedback and notify you about the next steps.