I've been working the past few days on cleaning up low-hanging-fruit bugs relating to MSOffice. I've run into one bug for which I have a solution, but I have no explanation as to why the solution is correct. It's what Windows does, but I don't know why! This email's a bit long, but it describes the problem and various things I've tried to understand the solution. Hopefully someone reading this list has some ideas :)
The bug is in PowerPoint. On native, when a slideshow is exited (i.e. go out of 'presentation mode'), the currently-displayed slide should become activated in the main 'editor' PowerPoint window. In Wine, however, the main window shows the slide that was active when the slideshow began. This makes resuming the slideshow from where you left off a big pain.
The problem is in the hlink module, specifically with IHlink::Navigate (implemented in Wine as IHlink_fnNavigate around dlls/hlink/link.c:436). IHlink objects can contain an IHlinkSite reference, which the Navigate function makes calls to as it proceeds through navigation, as a sort of callback.
The last call in IHlink::Navigate is to IHlinkSite::OnNavigationComplete. This function takes an HRESULT argument which, according to MSDN, should contain the final result of the navigation. Again, according to MSDN, IHlink::Navigate should return S_OK on success, error otherwise.
Of course, reality is different from what MSDN claims. On native, IHlinkSite::OnNavigationComplete is consistently called by IHlink::Navigate with its HRESULT argument set to 0x40100. I have no idea what this value is supposed to represent. Every Windows version with an hlink DLL, on both x86 and x86_64, passes 0x40100 to the IHlinkSite when IHlink::Navigate is called. It doesn't seem to matter what the target of the navigation is (website, file on filesystem). See the tests linked below.
Currently in Wine our IHlink::Navigate passes S_OK, as you'd expect from both the documentation and common sense. For whatever bizarre reason, however, PowerPoint requires that this HRESULT value be greater than zero. If zero (S_OK) is passed, then PowerPoint fails to restore the proper slide and just does nothing. If an error code is passed, PowerPoint pops up an error message, as you'd expect. But if a value greater than zero is passed (it's not picky about 0x40100), PowerPoint correctly opens the proper slide. So unfortunately, we need to do this "right" for PowerPoint to behave.
Interpreted as an HRESULT, 0x40100 is DRAGDROP_S_DROP, a successful DND operation, as returned by DoDragDrop. Is it possible that Windows navigates to items by drag-dropping into the appropriate application? IHlink _does_ also implement IOleObject, which is the "object" passed by DoDragDrop. This interpretation seems unlikely, though, since all programs that are associated with a filetype (i.e. open with ShellExecute) must then implement IDropTarget. I'm not ruling this interpretation out, but I can't make sense of it.
You'll note that the value looks something like a set of two bitflags. File access permissions were the first thing to come to mind, but Julliard said it looks nothing like permission flags that he's seen. I've looked at every constant in include with the value 0x40000 and seen nothing that looks relevant.
I sent a hack implementation off to wine-patches, but it was rejected. Alexandre said he'd like a better investigation of where 0x40100 comes from. I've exhausted my knowledge and can think of no place to derive this value from. I'm here asking if the value stands out to anyone, or if there are any suggestions of things to probe or functions to poke to get some meaning attached to this number.
Any ideas?
My hackish fix, with tests: http://www.winehq.org/pipermail/wine-patches/2010-January/083470.html
MSDN IHlink documentation: http://msdn.microsoft.com/en-us/library/aa767974%28VS.85%29.aspx
MSDN IHlinkSite documentation: http://msdn.microsoft.com/en-us/library/aa767933%28VS.85%29.aspx
Andrew
Andrew Eikum schrieb:
I've been working the past few days on cleaning up low-hanging-fruit bugs relating to MSOffice. I've run into one bug for which I have a solution, but I have no explanation as to why the solution is correct. It's what Windows does, but I don't know why! This email's a bit long, but it describes the problem and various things I've tried to understand the solution. Hopefully someone reading this list has some ideas :)
The bug is in PowerPoint. On native, when a slideshow is exited (i.e. go out of 'presentation mode'), the currently-displayed slide should become activated in the main 'editor' PowerPoint window. In Wine, however, the main window shows the slide that was active when the slideshow began. This makes resuming the slideshow from where you left off a big pain.
The problem is in the hlink module, specifically with IHlink::Navigate (implemented in Wine as IHlink_fnNavigate around dlls/hlink/link.c:436). IHlink objects can contain an IHlinkSite reference, which the Navigate function makes calls to as it proceeds through navigation, as a sort of callback.
The last call in IHlink::Navigate is to IHlinkSite::OnNavigationComplete. This function takes an HRESULT argument which, according to MSDN, should contain the final result of the navigation. Again, according to MSDN, IHlink::Navigate should return S_OK on success, error otherwise.
Of course, reality is different from what MSDN claims. On native, IHlinkSite::OnNavigationComplete is consistently called by IHlink::Navigate with its HRESULT argument set to 0x40100. I have no idea what this value is supposed to represent. Every Windows version with an hlink DLL, on both x86 and x86_64, passes 0x40100 to the IHlinkSite when IHlink::Navigate is called. It doesn't seem to matter what the target of the navigation is (website, file on filesystem). See the tests linked below.
Currently in Wine our IHlink::Navigate passes S_OK, as you'd expect from both the documentation and common sense. For whatever bizarre reason, however, PowerPoint requires that this HRESULT value be greater than zero. If zero (S_OK) is passed, then PowerPoint fails to restore the proper slide and just does nothing. If an error code is passed, PowerPoint pops up an error message, as you'd expect. But if a value greater than zero is passed (it's not picky about 0x40100), PowerPoint correctly opens the proper slide. So unfortunately, we need to do this "right" for PowerPoint to behave.
Interpreted as an HRESULT, 0x40100 is DRAGDROP_S_DROP, a successful DND operation, as returned by DoDragDrop. Is it possible that Windows navigates to items by drag-dropping into the appropriate application? IHlink _does_ also implement IOleObject, which is the "object" passed by DoDragDrop. This interpretation seems unlikely, though, since all programs that are associated with a filetype (i.e. open with ShellExecute) must then implement IDropTarget. I'm not ruling this interpretation out, but I can't make sense of it.
You'll note that the value looks something like a set of two bitflags. File access permissions were the first thing to come to mind, but Julliard said it looks nothing like permission flags that he's seen. I've looked at every constant in include with the value 0x40000 and seen nothing that looks relevant.
I sent a hack implementation off to wine-patches, but it was rejected. Alexandre said he'd like a better investigation of where 0x40100 comes from. I've exhausted my knowledge and can think of no place to derive this value from. I'm here asking if the value stands out to anyone, or if there are any suggestions of things to probe or functions to poke to get some meaning attached to this number.
Any ideas?
My hackish fix, with tests: http://www.winehq.org/pipermail/wine-patches/2010-January/083470.html
MSDN IHlink documentation: http://msdn.microsoft.com/en-us/library/aa767974%28VS.85%29.aspx
MSDN IHlinkSite documentation: http://msdn.microsoft.com/en-us/library/aa767933%28VS.85%29.aspx
Andrew
As you see msdn is often wrong. I first would start to get the tests committed with todowine's so that everyone can see that this is the behavior, also i would try to get some other returns if possible. Looking through constants ending up with 40000 is also tricky as there might be some macros which shifts some things to get a number like 0x40100. (ioctls does so) Then if you really had no chance to figure out what it is, maybe AJ would commit something like #define UNDOCUMENTED 0x40100 (already seen in code)
2010/1/7 Andrew Eikum aeikum@codeweavers.com:
The last call in IHlink::Navigate is to IHlinkSite::OnNavigationComplete. This function takes an HRESULT argument which, according to MSDN, should contain the final result of the navigation. Again, according to MSDN, IHlink::Navigate should return S_OK on success, error otherwise.
MSDN says that the HRESULT is for the
Is http://msdn.microsoft.com/en-us/library/aa767919%28VS.85%29.aspx (hyperlinking) useful? http://msdn.microsoft.com/en-us/library/aa740928%28VS.85%29.aspx (hyperlinking tutorial) is linked from there and contains sections of code for various IHlinkTarget and IHlink related methods.
Of interest is the bit under "Jumping to the hyperlink target" -- according to MSDN: "The following code is a theoretical implementation of a hyperlink object. The system-provided hyperlink object uses similar code." It proceeds to show some code of what an IHlink::Navigate call is doing.
Of course, reality is different from what MSDN claims. On native, IHlinkSite::OnNavigationComplete is consistently called by IHlink::Navigate with its HRESULT argument set to 0x40100. I have no idea what this value is supposed to represent. Every Windows version with an hlink DLL, on both x86 and x86_64, passes 0x40100 to the IHlinkSite when IHlink::Navigate is called. It doesn't seem to matter what the target of the navigation is (website, file on filesystem). See the tests linked below.
The code above is using different methods to locate an IHlinkTarget object, and then calling the Navigate method on that (and presumably returning the HRESULT of that call, although the code listed does not return anything).
NOTE: The test is incomplete (there are a lot of methods on the interfaces that are returning E_NOTIMPL), especially the QueryInterface and QueryService methods.
- Reece
Thanks for the suggestions, André, Erich, and Reece. Got a few more ideas at least, though I still haven't found the answer.
Reece Dunn wrote:
The code above is using different methods to locate an IHlinkTarget object, and then calling the Navigate method on that (and presumably returning the HRESULT of that call, although the code listed does not return anything).
I found this interesting, so investigated a bit more. I pulled out the code path from MSDN with no IHlinkSite and no IHlinkBrowseContext (as my HlinkNavigate call does). The test makes a moniker, binds its object to an IHlinkTarget, and executes IHlinkTarget::Navigate.
On native, the test succeeds navigating to winehq.org. But IHlinkTarget::Navigate returns S_OK, not 0x40100. So that probably eliminates IHlinkTarget::Navigate as the source of the mystery value. It was a good guess, anyway.
As near as I can tell, the "unwrapped" version in the test should have all of the same information as the call to HlinkNavigate, but at no point does 0x40100 appear.
Per Erich's suggestion, I tried a number of different flags to both HlinkNavigate and IHlinkTarget::Navigate, but was never able to get either to change their return values at all. On success, HlinkNavigate always seems to return 0x40100.
NOTE: The test is incomplete (there are a lot of methods on the interfaces that are returning E_NOTIMPL), especially the QueryInterface and QueryService methods.
Yeah, I'm aware of that. Native doesn't seem to care, and just removing the IHlinkSite reference entirely returns 0x40100 from HlinkNavigate anyway.
Finally, I've got a test for this which doesn't require any interaction from the user, but will leave a browser window open after the test finishes. Is this acceptable, or should I still leave it in a "winetest_interactive" if statement?
Andrew