You may remember from last week I said I would need more information in order to implement the mechanism browseui uses to open new windows in an existing process.
Well, spoiler alert if you haven’t read the SVN log: I got the information, and I wrote an implementation.
First of all, it turns out message 1037 is related to the rooted idlists. Since rooting is completely unimplemented at all the levels down to the implementation of the idlists, I stopped trying to figure out that message, and instead focused on the important one, 1035.
I discovered that the message is sent to one of two windows: either the actual desktop window (that is the “ProgMan” window that lies at the root of the explorer hierarchy), or to the first “Proxy Desktop” window it can find.
The proxy is used in one of two conditions: either if the /SEPARATE flag is specified in the command line, or if the “Open folders in a separate process” option is enabled in the settings. Because we don’t have such an option implemented yet, I implemented that check using a global variable that will initially be changed only while debugging.
After confirming that the shared memory is allocated in the context of the target window, and that it was using the “SH*Shared” set of functions (an abstraction of the low-level shared memory) as a means to use shared memory, I wrote the code necessary to assemble the shared memory packet, and recreate the parameter structure from the other side, using those functions.
Then for the case of the separate process, which needs a proxy window, I implemented the code that creates this hidden proxy window and tells it to open a new folder. In the proxy implementation, I wrote a handler for the two messages, even though only 1035 will be implemented for now. The other is a stub in case one day we want to add rooted folders, which may need message 1037 to be windows-like.
Then what was left was to investigate what happens when message 1035 is received by the desktop window, and Giannis happened to have the information from his previous work in the shell. This message calls SHOnCWMCommandLine, which is takes the shared memory handle, decodes the parameters from the packet, and calls SHOpenFolderWindow with the information.
In windows, SHOpenFolderWindow does a whole lot of work, including deciding if it should activate an existing window or open a new window. Since we don’t really care about that just yet, I decided to implement this function based on the existing implementation of SHOpenNewFrame. I took some of the code from there and moved it to SHOpenFolderWindow, making SHOpenNewFrame call this function instead.
Now with all this done, it was time to test just how far the code I had written went before breaking. And here is where everything stopped being all nice and smooth.
Remember I mentioned those shell functions used for shared memory? Well it turns out WINE never tested if the functions work when the shared memory is allocated in the context of another process. And they don’t. And I have no idea why. To be fair, I did find one bug, but even after fixing that bug, the code still fails to lock the memory and return a raw pointer to the shared buffer. Which makes the shared memory useless… ;P
So I derived this issue to Thomas Fabber, and decided to cleanup the implementation, commit it, and then work on something else until we have a functional shell shared memory API.
I have started to plan how the Shell DDE parser is going to look like, and my intention is to work on this starting Monday.
Thanks for reading, and until next weekend.