winemenubuilder: manage desktop shortcuts better

Damjan Jovanovic damjan.jov at gmail.com
Wed May 19 14:49:01 CDT 2010


Changelog:
* winemenubuilder: manage desktop shortcuts better

Details:
* When we write a .lnk to ~/Desktop, do not generate a .desktop file.
Patches committed in the last round ensured .lnk will still start
through a double-click, and future patches could thumbnail an icon for
the .lnk. Deletion of the .lnk on uninstall fully cleans up
everything.
* When we write a .lnk to the "public desktop", which isn't ~/Desktop,
then generate a .desktop file in ~/Desktop and link the 2 together in
the registry, so when the .lnk is deleted on uninstall the .desktop is
also deleted later.
* The .desktop file, when we generate it, now also runs start.exe with
the path to the .lnk instead of the escaped/quoted command in the
.lnk.
* Simplify the InvokeShellLinker function.

Except for the cosmetic details like the icon, this essentially closes #3548.

Damjan Jovanovic
-------------- next part --------------
diff --git a/programs/winemenubuilder/winemenubuilder.c b/programs/winemenubuilder/winemenubuilder.c
index 9f10fdb..b0dc7c5 100644
--- a/programs/winemenubuilder/winemenubuilder.c
+++ b/programs/winemenubuilder/winemenubuilder.c
@@ -2222,12 +2222,37 @@ static BOOL generate_associations(const char *xdg_data_home, const char *package
     return hasChanged;
 }
 
-static BOOL InvokeShellLinker( IShellLinkW *sl, LPCWSTR link, BOOL bWait )
+static char* escape_unix_link_arg(LPCSTR unix_link)
+{
+    char *ret = NULL;
+    WCHAR *unix_linkW = utf8_chars_to_wchars(unix_link);
+    if (unix_linkW)
+    {
+        char *escaped_lnk = escape(unix_linkW);
+        if (escaped_lnk)
+        {
+            ret = heap_printf("/Unix %s", escaped_lnk);
+            HeapFree(GetProcessHeap(), 0, escaped_lnk);
+        }
+        HeapFree(GetProcessHeap(), 0, unix_linkW);
+    }
+    return ret;
+}
+
+static char *get_start_exe_path(void)
 {
     static const WCHAR startW[] = {'\\','c','o','m','m','a','n','d',
                                    '\\','s','t','a','r','t','.','e','x','e',0};
+    WCHAR start_path[MAX_PATH];
+    GetWindowsDirectoryW(start_path, MAX_PATH);
+    lstrcatW(start_path, startW);
+    return escape(start_path);
+}
+
+static BOOL InvokeShellLinker( IShellLinkW *sl, LPCWSTR link, BOOL bWait )
+{
     char *link_name = NULL, *icon_name = NULL, *work_dir = NULL;
-    char *escaped_path = NULL, *escaped_args = NULL, *description = NULL;
+    char *description = NULL;
     WCHAR szTmp[INFOTIPSIZE];
     WCHAR szDescription[INFOTIPSIZE], szPath[MAX_PATH], szWorkDir[MAX_PATH];
     WCHAR szArgs[INFOTIPSIZE], szIconPath[MAX_PATH];
@@ -2235,6 +2260,7 @@ static BOOL InvokeShellLinker( IShellLinkW *sl, LPCWSTR link, BOOL bWait )
     DWORD csidl = -1;
     HANDLE hsem = NULL;
     char *unix_link = NULL;
+    char *start_path = NULL;
 
     if ( !link )
     {
@@ -2310,52 +2336,22 @@ static BOOL InvokeShellLinker( IShellLinkW *sl, LPCWSTR link, BOOL bWait )
     /* check the path */
     if( szPath[0] )
     {
-        static const WCHAR exeW[] = {'.','e','x','e',0};
-        WCHAR *p;
-
-        /* check for .exe extension */
-        if (!(p = strrchrW( szPath, '.' )) ||
-            strchrW( p, '\\' ) || strchrW( p, '/' ) ||
-            lstrcmpiW( p, exeW ))
-        {
-            /* Not .exe - use 'start.exe' to launch this file */
-            p = szArgs + lstrlenW(szPath) + 2;
-            if (szArgs[0])
-            {
-                p[0] = ' ';
-                memmove( p+1, szArgs, min( (lstrlenW(szArgs) + 1) * sizeof(szArgs[0]),
-                                           sizeof(szArgs) - (p + 1 - szArgs) * sizeof(szArgs[0]) ) );
-            }
-            else
-                p[0] = 0;
-
-            szArgs[0] = '"';
-            lstrcpyW(szArgs + 1, szPath);
-            p[-1] = '"';
-
-            GetWindowsDirectoryW(szPath, MAX_PATH);
-            lstrcatW(szPath, startW);
-        }
-
         /* convert app working dir */
         if (szWorkDir[0])
             work_dir = wine_get_unix_file_name( szWorkDir );
     }
-    else
+
+    description = wchars_to_utf8_chars(szDescription);
+    if (description == NULL)
     {
-        /* if there's no path... try run the link itself */
-        lstrcpynW(szArgs, link, MAX_PATH);
-        GetWindowsDirectoryW(szPath, MAX_PATH);
-        lstrcatW(szPath, startW);
+        WINE_ERR("out of memory allocating description\n");
+        goto cleanup;
     }
 
-    /* escape the path and parameters */
-    escaped_path = escape(szPath);
-    escaped_args = escape(szArgs);
-    description = wchars_to_utf8_chars(szDescription);
-    if (escaped_path == NULL || escaped_args == NULL || description == NULL)
+    start_path = get_start_exe_path();
+    if (start_path == NULL)
     {
-        WINE_ERR("out of memory allocating/escaping parameters\n");
+        WINE_ERR("out of memory\n");
         goto cleanup;
     }
 
@@ -2369,39 +2365,40 @@ static BOOL InvokeShellLinker( IShellLinkW *sl, LPCWSTR link, BOOL bWait )
 
     if (in_desktop_dir(csidl))
     {
-        char *location;
-        const char *lastEntry;
-        lastEntry = strrchr(link_name, '/');
-        if (lastEntry == NULL)
-            lastEntry = link_name;
-        else
-            ++lastEntry;
-        location = heap_printf("%s/%s.desktop", xdg_desktop_dir, lastEntry);
-        if (location)
+        if (csidl == CSIDL_COMMON_DESKTOPDIRECTORY)
         {
-            r = !write_desktop_entry(NULL, location, lastEntry, escaped_path, escaped_args, description, work_dir, icon_name);
-            if (r == 0)
-                chmod(location, 0755);
-            HeapFree(GetProcessHeap(), 0, location);
+            char *location;
+            const char *lastEntry;
+            lastEntry = strrchr(link_name, '/');
+            if (lastEntry == NULL)
+                lastEntry = link_name;
+            else
+                ++lastEntry;
+            location = heap_printf("%s/%s.desktop", xdg_desktop_dir, lastEntry);
+            if (location)
+            {
+                char *link_arg = escape_unix_link_arg(unix_link);
+                if (link_arg)
+                {
+                    r = !write_desktop_entry(unix_link, location, lastEntry,
+                        start_path, link_arg, description, work_dir, icon_name);
+                    if (r == 0)
+                        chmod(location, 0755);
+                    HeapFree(GetProcessHeap(), 0, link_arg);
+                }
+                HeapFree(GetProcessHeap(), 0, location);
+            }
         }
+        else
+            WINE_TRACE("not generating .desktop file for %s, it is already on the desktop\n", unix_link);
     }
     else
     {
-        WCHAR *unix_linkW = utf8_chars_to_wchars(unix_link);
-        if (unix_linkW)
+        char *link_arg = escape_unix_link_arg(unix_link);
+        if (link_arg)
         {
-            char *escaped_lnk = escape(unix_linkW);
-            if (escaped_lnk)
-            {
-                char *menuarg = heap_printf("/Unix %s", escaped_lnk);
-                if (menuarg)
-                {
-                    r = !write_menu_entry(unix_link, link_name, "start", menuarg, description, work_dir, icon_name);
-                    HeapFree(GetProcessHeap(), 0, menuarg);
-                }
-                HeapFree(GetProcessHeap(), 0, escaped_lnk);
-            }
-            HeapFree(GetProcessHeap(), 0, unix_linkW);
+            r = !write_menu_entry(unix_link, link_name, start_path, link_arg, description, work_dir, icon_name);
+            HeapFree(GetProcessHeap(), 0, link_arg);
         }
     }
 
@@ -2412,10 +2409,9 @@ cleanup:
     HeapFree( GetProcessHeap(), 0, icon_name );
     HeapFree( GetProcessHeap(), 0, work_dir );
     HeapFree( GetProcessHeap(), 0, link_name );
-    HeapFree( GetProcessHeap(), 0, escaped_args );
-    HeapFree( GetProcessHeap(), 0, escaped_path );
     HeapFree( GetProcessHeap(), 0, description );
-    HeapFree( GetProcessHeap(), 0, unix_link);
+    HeapFree( GetProcessHeap(), 0, unix_link );
+    HeapFree( GetProcessHeap(), 0, start_path );
 
     if (r && !bWait)
         WINE_ERR("failed to build the menu\n" );


More information about the wine-patches mailing list