Hello all,
Recently there has been a revived interest in putting up a 'Windows' like 'Start Menu' onto the Window managers. That's good.Thanks.
But as I see it, this task is REALLY easy. Once we resolve the Windows shorcut files,figuring out how to implement the resolved menu entries for respective Desktop environments is dependent on the Desktop environment themselves, and people wanting to implement the 'Start Menu' on that environment. Windows maintains it's 'Start Menu' under '%ROOTDIR%\Documents and Settings%USER%\Start Menu' (yeah I am talking >=NT,Win2k. For 9x, it will be probably 'C:\WINDOWS\Start Menu'), and this folder contains LOADS of shortcut (.lnk) files. So if we can just recurse through this folder and read out the .lnk files into compatible menu/desktop entries of the corresponding Desktop environment (KDE,GNOME...), we have a working, synchronized 'Start Menu'.
And that's JUST what McCormack's 'winemenubuilder' does, and reading out the code I can see it's THE thing we need.
Unfortunately, 'winemenubuilder' shipped from Wine-20030618 - the VERY version from which IPersistFile::Load() (the VERY function used to resolve windows shortcuts) got broken, so I could not see 'winemenubuilder' in practise! (Mike, if you are reading this, could you tell me on what Wine ver you originally developed it, and does 'winemenubuilder' work now ? Thanks)
You yourself may try out 'winemenubuilder', and if it works let me know. I will know that I was at fault all along,and that would be good news for me !
Now, there arises the problem. Microsoft really does not tell us what's the data structure of .lnk files, though if Alexandre (or somebody of his status..) requested Matt Pietrek for that information, we can probably get it.
Till then we are having to do with reverse engg., and let me tell you,that worked fine till Wine-20030618, i.e the Wine tarball release on the 18th June 2003.
From Wine-20030618 , the way Wine handled COM went a
MAJOR overhaul, and it worked great in most cases and older code had to rewritten... .. and resolution of shortcuts just stopped working since then. So I have downgraded to using Wine 20030508 since it's the last version till which resolution of shortcuts works (though the code in 'shelllink.c' for this version is not nice to look at ;) ).
DETAILS: --------
You see, the resolving of shortcuts is handled through IPersistFile::Load() using COM.
The code for this instance of the interface can be found in 'dlls/shell32/shelllink.c'. IPersistFile::Load() calls IPersistFile_fnLoad from 'dlls/shell32/shelllink.c', which passes control to IPersistStream_Load() after a CreateStreamOnFile() call. Now the problem starts in IPersistStream_Load() at/after the following piece of code:
'if( hdr.dwFlags & SCF_DESCRIPTION ) r = Stream_LoadString( pLoadStream, unicode, &This->sDescription );'...
Everything before this seems to work just fine!
[That's a pity because most of the time we just require the program location from the shortcut file, and that's ALWAYS dumped correctly into 'This->pPidl' You can verify this by adding the following code after 'r = Stream_LoadLocation( pLoadStream );' in 'shelllink.c'
LPCITEMIDLIST pidltemp = This->pPidl; do { char szSubho[MAX_PATH]; _dbg_ILSimpleGetText(pidltemp, szSubho, MAX_PATH); TRACE ("name="%s"\n",szSubho); pidltemp = _dbg_ILGetNext(pidltemp); }while (pidltemp->mkid.cb); You need to turn on the trace messages and you shall see the program path resolved allright! I had even tried to put a 'return S_OK;' after the Stream_LoadLocation() call,because ALL i required was the program path, but unfortunately that did NOT work :( ]
The call 'Stream_LoadString( pLoadStream, unicode, &This->sDescription );' works in some cases and fails in some. But you can be sure that all the following Stream_LoadString() calls starting from 'Stream_LoadString( pLoadStream, unicode, &This->sPathRel);' WILL fail! It did everytime on my SuSE 8.2,Wine-20030911. Thus, IPersistStream_fnLoad() will NEVER return S_OK !
The last time I debugged, I found that 'IStream_Read(pStm, &len, sizeof(len), &count);' under 'Stream_LoadString( IStream* pStm, BOOL unicode, LPWSTR *pstr )' was failing at/after the 'Description' string was read from the Windows shortcut file, apparently because the 'number of bytes read!=number of bytes to be read'( i.e, for those of you going through the 'shelllink.c' code, the 'count != len' condition was getting satisfied..) You may again verify this by turning on tracing and observing the messages for the above APIs from Wine while running my shortcut resolving code (found in the archives) OR McCormack's 'winemenubuilder'.
I hope to get a suitable response to this post. PLEASE correct me if I have gone wrong anywhere! Thanks :=)
Also, I will be VERY happy to recieve pseudocode/algorithm for the mentioned APIs specially Stream_LoadString() and IPersistStream_fnLoad() as I am having a hard time understanding a few lines in the code. And could someone send me the layout of .lnk files ?
Please keep up the good work. Regards
Subhobroto Sinha
__________________________________ Do you Yahoo!? The New Yahoo! Shopping - with improved product search http://shopping.yahoo.com
Hi Subhobroto,
Unfortunately, it's not just as simple as enumerating "C:\Windows\Start Menu", though that would be a good start.
To do things exactly the same way as Windows does them, we have to make a shell namespace that contains all the stuff on the start menu, then enumerate that. Furthermore, since the namespace is dynamic, the menu really should be constructed on the fly, not just written to an .desktop file.
I had a bit of discussion with Robert van Herk about this (see the thread about ""Start menu" (continued)" on this list). I mentioned to him that I thought the best way to solve the problem would be to write a gnome-vfs library and KDE plugin that query a wine process for the structure of the startmenu at runtime.
For starters we could just use the 'Start Menu' directory, but you miss out on things like Outlook Express and Internet Explorer's Icons, because there's no .lnk file for those... they are created by a shell namespace extension (I think :).
Anyway, it would be great if we figured out the remaining structure of .lnk files, and finished the IShellLink implementation properly, and no matter how things are done, we need that code to be complete. The best way to do that, IMO, is to examine alot of .lnk files from windows systems :)
Mike
Subhobroto Sinha wrote:
Hello all,
Recently there has been a revived interest in putting up a 'Windows' like 'Start Menu' onto the Window managers. That's good.Thanks.
But as I see it, this task is REALLY easy. Once we resolve the Windows shorcut files,figuring out how to implement the resolved menu entries for respective Desktop environments is dependent on the Desktop environment themselves, and people wanting to implement the 'Start Menu' on that environment. Windows maintains it's 'Start Menu' under '%ROOTDIR%\Documents and Settings%USER%\Start Menu' (yeah I am talking >=NT,Win2k. For 9x, it will be probably 'C:\WINDOWS\Start Menu'), and this folder contains LOADS of shortcut (.lnk) files. So if we can just recurse through this folder and read out the .lnk files into compatible menu/desktop entries of the corresponding Desktop environment (KDE,GNOME...), we have a working, synchronized 'Start Menu'.
And that's JUST what McCormack's 'winemenubuilder' does, and reading out the code I can see it's THE thing we need.
Unfortunately, 'winemenubuilder' shipped from Wine-20030618 - the VERY version from which IPersistFile::Load() (the VERY function used to resolve windows shortcuts) got broken, so I could not see 'winemenubuilder' in practise! (Mike, if you are reading this, could you tell me on what Wine ver you originally developed it, and does 'winemenubuilder' work now ? Thanks)
You yourself may try out 'winemenubuilder', and if it works let me know. I will know that I was at fault all along,and that would be good news for me !
Now, there arises the problem. Microsoft really does not tell us what's the data structure of .lnk files, though if Alexandre (or somebody of his status..) requested Matt Pietrek for that information, we can probably get it.
Till then we are having to do with reverse engg., and let me tell you,that worked fine till Wine-20030618, i.e the Wine tarball release on the 18th June 2003.
From Wine-20030618 , the way Wine handled COM went a
MAJOR overhaul, and it worked great in most cases and older code had to rewritten... .. and resolution of shortcuts just stopped working since then. So I have downgraded to using Wine 20030508 since it's the last version till which resolution of shortcuts works (though the code in 'shelllink.c' for this version is not nice to look at ;) ).
DETAILS:
You see, the resolving of shortcuts is handled through IPersistFile::Load() using COM.
The code for this instance of the interface can be found in 'dlls/shell32/shelllink.c'. IPersistFile::Load() calls IPersistFile_fnLoad from 'dlls/shell32/shelllink.c', which passes control to IPersistStream_Load() after a CreateStreamOnFile() call. Now the problem starts in IPersistStream_Load() at/after the following piece of code:
'if( hdr.dwFlags & SCF_DESCRIPTION ) r = Stream_LoadString( pLoadStream, unicode, &This->sDescription );'...
Everything before this seems to work just fine!
[That's a pity because most of the time we just require the program location from the shortcut file, and that's ALWAYS dumped correctly into 'This->pPidl' You can verify this by adding the following code after 'r = Stream_LoadLocation( pLoadStream );' in 'shelllink.c'
LPCITEMIDLIST pidltemp = This->pPidl; do { char szSubho[MAX_PATH]; _dbg_ILSimpleGetText(pidltemp, szSubho,
MAX_PATH); TRACE ("name="%s"\n",szSubho); pidltemp = _dbg_ILGetNext(pidltemp); }while (pidltemp->mkid.cb); You need to turn on the trace messages and you shall see the program path resolved allright! I had even tried to put a 'return S_OK;' after the Stream_LoadLocation() call,because ALL i required was the program path, but unfortunately that did NOT work :( ]
The call 'Stream_LoadString( pLoadStream, unicode, &This->sDescription );' works in some cases and fails in some. But you can be sure that all the following Stream_LoadString() calls starting from 'Stream_LoadString( pLoadStream, unicode, &This->sPathRel);' WILL fail! It did everytime on my SuSE 8.2,Wine-20030911. Thus, IPersistStream_fnLoad() will NEVER return S_OK !
The last time I debugged, I found that 'IStream_Read(pStm, &len, sizeof(len), &count);' under 'Stream_LoadString( IStream* pStm, BOOL unicode, LPWSTR *pstr )' was failing at/after the 'Description' string was read from the Windows shortcut file, apparently because the 'number of bytes read!=number of bytes to be read'( i.e, for those of you going through the 'shelllink.c' code, the 'count != len' condition was getting satisfied..) You may again verify this by turning on tracing and observing the messages for the above APIs from Wine while running my shortcut resolving code (found in the archives) OR McCormack's 'winemenubuilder'.
I hope to get a suitable response to this post. PLEASE correct me if I have gone wrong anywhere! Thanks :=)
Also, I will be VERY happy to recieve pseudocode/algorithm for the mentioned APIs specially Stream_LoadString() and IPersistStream_fnLoad() as I am having a hard time understanding a few lines in the code. And could someone send me the layout of .lnk files ?
Please keep up the good work. Regards
Subhobroto Sinha
Do you Yahoo!? The New Yahoo! Shopping - with improved product search http://shopping.yahoo.com
Subhobroto Sinha wrote:
But as I see it, this task is REALLY easy. Once we resolve the Windows shorcut files,figuring out how to implement the resolved menu entries for respective Desktop environments is dependent on the Desktop environment themselves, and people wanting to implement the 'Start Menu' on that environment. Windows maintains it's 'Start Menu' under '%ROOTDIR%\Documents and Settings%USER%\Start Menu' (yeah I am talking >=NT,Win2k. For 9x, it will be probably 'C:\WINDOWS\Start Menu'), and this folder contains LOADS of shortcut (.lnk) files. So if we can just recurse through this folder and read out the .lnk files into compatible menu/desktop entries of the corresponding Desktop environment (KDE,GNOME...), we have a working, synchronized 'Start Menu'.
There are a few things though:
From discussions with others from this list, I understand that you should not just want to list the entries in the start menu folder, but also other things (control panel, etc).
There should be a dll file (shell32.dll?) that can be queried to provide this information.
What I am currently working on is a client on Linux and a server in Windows (Wine). The server should notify the client when new entries appear, and the client uses the server to get all the needed information for the start menu.
I am about half way for the first client, that will run on KDE.
Didn't touch the server yet, seems harder to build. Also didn't think really hard on the communication between the server and the client. Pipes won't probably be a good idea, because you want bidirectional communication.
Anyhow, the first client is set up using QT. I am not shure whether this is general enough, so please tell me if this is not wise to do, for example if it won't be compatible with Gnome. If everything is QT compatible, only the very frontend of the client will have to be reprogrammed for the different desktop environments. That means that most classes could be recycled from the KDE version.
Grtz, Robert