Dmitry Timoshkov wrote:
Since you didn't provide your test app I wrote my own (attached). My comments are based on its results.
Well, since I was lazy I wrote it in Delphi and you'd have to enter window handles yourself, I didn't attach it but since I keep being accused of tainted sources I tried to clarify this.
The results of the research I just did:
- GetComboBoxInfo works with all handles, even with handles not
belonging to the calling process
Most likely it's true.
That's right, the reason I mentioned is that Christoph's implementation won't work because of different address spaces. Even if it points to the desktop heap (which ReactOS doesn't have yet) it's not guaranteed to work because it might have gotten mapped to another base address. So the implementation basically can't work this way.
- It does NOT send a message, not even in the case it doesn't belong
to the calling process
True, but that might be an internal message catched by the message handling code.
I of course only checked if a message would get dispatched to the window procedure of the owning thread. I don't know how windows handles it internally but I assume it reads the information from the desktop heap without reading the ptr using GetWindowLongPtr. If of course might send an internal message that only gets dispatched internally, but that'd be much overhead that could easily be a avoided. I forgot to mention that the function even works if the thread that owns the combo box hangs, it immediately returns the requested information. So sending a (internal) special message is not likely in my opinion.
- It sets the last error code to ERROR_WINDOW_NOT_COMBOBOX and
returns FALSE if the window handle isn't a combo box
True. That might be accomplished by retrieving a window data pointer with GetWindowLongPtrW and testing some internal fields.
That however only works for controls owned by a thread of the same process.
- If the cbSize field of the COMBOBOXINFO structure doesn't match,
it sets the last error code to ERROR_INVALID_PARAMETER and returns FALSE
Poor Microsoft programmers even decided to fail if cbi.cbSize = sizeof(cbi) + 1, i.e. if it's enough space to store the result.
That actually is common in the native api. Unless the buffer needed may vary depending on the content it returns, in most cases the size fields have to match. There are however a few exceptions I found by tests. One reason however might be to support different structure versions (.e.g. GetVersionEx()). So I don't think it's a "bad thing(tm)". Plus you might find bugs caused by using incorrect structure layouts.
In Wine we can always send our custom WINE_GETCOMBOBOXINFO message if a window belongs to other process.
Unless the window owner thread hangs, that then causes the caller to hang as well, which is not the case in windows. Sending a message with a timout would not work correctly if the system is too busy to process the request in time, even if the target thread doesn't hang.
My test app shows that Windows correctly handles a superclassed window, so the thesis that it checks the class name is wrong.
As I haven't tested that case, I guess you're right.
Best Regards, Thomas