Dynamic menus and miscounted references

I know I promised weekly reports but it’s summer time and, although I haven’t really been out on vacation, I have been taking my schedule a lot more loosely than usual.

After fixing the stobject compilation, I set my sights on the file browser menus. I began by trying to figure out how the Windows shell manages the menus, and I realized that most of the actual work was done in the WM_INITMENUPOPUP message handler.

This message is initially received by the shell browser object, which does its own processing first, and then forwards it to the shell view. The message would normally contain the index of the menu item that opened the submenu that is being initialized. Because the shell uses custom menus based on toolbars, the submenus don’t know the index of the item that opened them, so the shell browser has to check which menu is opening, and then set the appropriate index in the right parameter, before forwarding. After doing this change and implementing the message handler in the shell view, I reused part of the existing code that built the menus, and moved it to the init handler.

I later discovered, while trying to implement the edit menu, that both the edit menu and the view menu are initialized only once, when the view activates for the first time. I moved the view menu initialization, and added code to also initialize the edit menu, and only left the code that marks the currently active view mode in the message handler. In order to implement the edit menu, I had to add some new resources to shell32, which for now only include en-US translation.

The next step was to implement the File menu. Unlike the edit and view menus, which are only initialized once, the file menu is cleaned up and the items of the current selection are added to it, every time the menu is shown. For this, Windows has a special function that gathers the available actions for the current selection, and builds a special menu for those items. Since we don’t have this function yet, I just obtained the items of the context menu, and added them to the File menu as-is. This will need future improvements, but serves its purpose for now.

While the dynamic menus were working the way they are supposed to -- even if the contents still aren’t fully correct – the Favorites menu wasn’t working anymore. This was because the favorites menu now uses the CMergedFolder, but it was using the old interface that didn’t exist anymore. To fix it, I had to expose the new interface to browseui, and fix the menu callback handler so that the favorites menu uses the new interface.

While I was fixing the menus bugs, Giannis asked me about the icons losing the selection overlay when the menus are shown. Since Windows keep the selection shown on windows (but not the desktop), I added the appropriate flag only when not in desktop mode, and now the icons look as expected.

At this point, began a long arduous debugging session, spanning nearly two weeks. The problem was that refreshing the desktop twice would cause the desktop thread to crash, and the desktop icons to disappear. I already knew there must be some sort of corruption or usage of a freed pointer, but I couldn’t find where things were going wrong. By the end, I mostly had given up on finding a solution, until Giannis popped into IRC and explaining the issue gave me an idea: I could trace when the object was created, and when it was destroyed, and see which function was the misbehaving one. If the object was being released prematurely, this would find it. If not, I’d have to find a different way to debug.

Luckily, I quickly found which function was the last to see the object alive, and tracing back, I found which function was double-releasing the reference counter. Because that bug had happened from misusing/mismatching interface pointers, CComPtr and AddRef/Release, I decided to take that chance and get rid of as many direct interface pointers as possible, keeping only those that really had to remain as pointers (such as function parameters or struct fields). This most probably has caused some regressions, but those should be relatively easy to fix, and everything is for the best.

While I was working on the crash, I also did some trunk syncs, after some developers fixed some issues related to the shell, or which would benefit the shell development. I also fixed the way accelerators (hotkeys) are handled in the file browser, so that the shell view can cancel the key handing if the listview is in editing mode. This allows the user to press backspace, ctrl-c and such, and get the expected result.

After fixing this, I turned my eyes to the DDE issue. Giannis made me notice the existing stubs in shell32, and suggested I should test the DDE functions from Windows, because our implementation is not that good. I did so, and managed to find some details about the shell DDE, that I didn’t know, which should help implement the feature in ReactOS. A lot more investigation is needed, though, so it will be a while until DDE is working.