diff --git a/programs/winemenubuilder/appbundler.c b/programs/winemenubuilder/appbundler.c
index b001f88..3bd07d2 100644
--- a/programs/winemenubuilder/appbundler.c
+++ b/programs/winemenubuilder/appbundler.c
@@ -30,7 +30,7 @@
  * There can be more to a bundle depending on the target, what resources
  * it contains and what the target platform but this simplifed format
  * is all we really need for now for Wine.
- * 
+ *
  * TODO:
  * - Add support for writing bundles to the Desktop
  * - Convert to using CoreFoundation API rather than standard unix file ops
@@ -39,7 +39,7 @@
  *   and or Wine Version information come to mind.
  * - Association Support
  * - sha1hash of target application in bundle plist
- */ 
+ */
 
 #include "config.h"
 #include "wine/port.h"
@@ -59,76 +59,77 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(menubuilder);
 
-char *bundle_name = NULL;
+char *path_to_bundle = NULL;
 char *mac_desktop_dir = NULL;
 char *wine_applications_dir = NULL;
 char* heap_printf(const char *format, ...);
 BOOL create_directories(char *directory);
+DWORD register_menus_entry(const char *unix_file, const char *windows_file);
 
 #ifdef __APPLE__
- 
+
 //CFPropertyListRef CreateMyPropertyListFromFile(CFURLRef fileURL);
 void WriteMyPropertyListToFile(CFPropertyListRef propertyList, CFURLRef fileURL );
- 
- 
+
+
 CFDictionaryRef CreateMyDictionary(const char *linkname)
 {
    CFMutableDictionaryRef dict;
    CFStringRef linkstr;
 
    linkstr = CFStringCreateWithCString(NULL, linkname, CFStringGetSystemEncoding());
- 
- 
+
+
    /* Create a dictionary that will hold the data. */
    dict = CFDictionaryCreateMutable( kCFAllocatorDefault,
             0,
             &kCFTypeDictionaryKeyCallBacks,
             &kCFTypeDictionaryValueCallBacks );
- 
-   /* Put the various items into the dictionary. */ 
+
+   /* Put the various items into the dictionary. */
    /* FIXME - Some values assumed the ought not to be */
-   CFDictionarySetValue( dict, CFSTR("CFBundleDevelopmentRegion"), CFSTR("English") ); 
+   CFDictionarySetValue( dict, CFSTR("CFBundleDevelopmentRegion"), CFSTR("English") );
    CFDictionarySetValue( dict, CFSTR("CFBundleExecutable"), linkstr );
-   CFDictionarySetValue( dict, CFSTR("CFBundleIdentifier"), CFSTR("org.winehq.wine") ); 
-   CFDictionarySetValue( dict, CFSTR("CFBundleInfoDictionaryVersion"), CFSTR("6.0") ); 
+   /* FIXME - Avoid identifier if not unique. */
+   //CFDictionarySetValue( dict, CFSTR("CFBundleIdentifier"), CFSTR("org.winehq.wine") );
+   CFDictionarySetValue( dict, CFSTR("CFBundleInfoDictionaryVersion"), CFSTR("6.0") );
    CFDictionarySetValue( dict, CFSTR("CFBundleName"), linkstr );
-   CFDictionarySetValue( dict, CFSTR("CFBundlePackageType"), CFSTR("APPL") ); 
-   CFDictionarySetValue( dict, CFSTR("CFBundleVersion"), CFSTR("1.0") ); 
-   CFDictionarySetValue( dict, CFSTR("CFBundleSignature"), CFSTR("???") ); 
-   CFDictionarySetValue( dict, CFSTR("CFBundleVersion"), CFSTR("1.0") ); 
+   CFDictionarySetValue( dict, CFSTR("CFBundlePackageType"), CFSTR("APPL") );
+   CFDictionarySetValue( dict, CFSTR("CFBundleVersion"), CFSTR("1.0") );
+   // Not needed CFDictionarySetValue( dict, CFSTR("CFBundleSignature"), CFSTR("????") );
    /* Fixme - install a default icon */
-   //CFDictionarySetValue( dict, CFSTR("CFBundleIconFile"), CFSTR("wine.icns") ); 
-   
+   //CFDictionarySetValue( dict, CFSTR("CFBundleIconFile"), CFSTR("wine.icns") );
+
    return dict;
 }
- 
-void WriteMyPropertyListToFile( CFPropertyListRef propertyList, CFURLRef fileURL ) 
+
+void WriteMyPropertyListToFile( CFPropertyListRef propertyList, CFURLRef fileURL )
 {
    CFDataRef xmlData;
    Boolean status;
    SInt32 errorCode;
- 
+
    /* Convert the property list into XML data */
    xmlData = CFPropertyListCreateXMLData( kCFAllocatorDefault, propertyList );
- 
+
    /* Write the XML data to the file */
    status = CFURLWriteDataAndPropertiesToResource (
                fileURL,
                xmlData,
                NULL,
                &errorCode);
- 
+
    // CFRelease(xmlData);
 }
 
-static CFPropertyListRef CreateMyPropertyListFromFile( CFURLRef fileURL ) 
+static CFPropertyListRef CreateMyPropertyListFromFile( CFURLRef fileURL )
 {
     CFPropertyListRef propertyList;
     CFStringRef       errorString;
     CFDataRef         resourceData;
     Boolean           status;
     SInt32            errorCode;
- 
+
     /* Read the XML file */
     status = CFURLCreateDataAndPropertiesFromResource(
                kCFAllocatorDefault,
@@ -137,13 +138,13 @@ static CFPropertyListRef CreateMyPropertyListFromFile( CFURLRef fileURL )
                NULL,
                NULL,
                &errorCode);
- 
+
     /* Reconstitute the dictionary using the XML data. */
     propertyList = CFPropertyListCreateFromXMLData( kCFAllocatorDefault,
                resourceData,
                kCFPropertyListImmutable,
                &errorString);
- 
+
     //CFRelease( resourceData );
     return propertyList;
 }
@@ -156,8 +157,8 @@ BOOL modify_plist_value(char *plist_path, const char *key, char *value)
     CFStringRef keystr;
     CFStringRef valuestr;
     CFURLRef fileURL;
- 
-    WINE_TRACE("Modifying Bundle Info.plist at %s\n", plist_path); 
+
+    WINE_TRACE("Modifying Bundle Info.plist at %s\n", plist_path);
 
     /* Convert strings to something these Mac APIs can handle */
     pathstr = CFStringCreateWithCString(NULL, plist_path, CFStringGetSystemEncoding());
@@ -201,9 +202,9 @@ static BOOL generate_plist(const char *path_to_bundle_contents, const char *link
     CFURLRef fileURL;
 
     /* Append all of the filename and path stuff and shove it in to CFStringRef */
-    plist_path = heap_printf("%s/%s", path_to_bundle_contents, info_dot_plist_file); 
+    plist_path = heap_printf("%s/%s", path_to_bundle_contents, info_dot_plist_file);
     pathstr = CFStringCreateWithCString(NULL, plist_path, CFStringGetSystemEncoding());
- 
+
     /* Construct a complex dictionary object */
     propertyList = CreateMyDictionary(linkname);
 
@@ -216,11 +217,11 @@ static BOOL generate_plist(const char *path_to_bundle_contents, const char *link
     /* Write the property list to the file */
     WriteMyPropertyListToFile( propertyList, fileURL );
     CFRelease(propertyList);
- 
+
 #if 0
     /* Recreate the property list from the file */
     propertyList = CreateMyPropertyListFromFile( fileURL );
- 
+
     /* Release any objects to which we have references */
     CFRelease(propertyList);
 #endif
@@ -233,6 +234,7 @@ static BOOL generate_plist(const char *path_to_bundle_contents, const char *link
 #endif /* __APPLE__ */
 
 
+#if 0
 /* TODO: If I understand this file correctly, it is used for associations */
 static BOOL generate_pkginfo_file(const char* path_to_bundle_contents)
 {
@@ -253,14 +255,16 @@ static BOOL generate_pkginfo_file(const char* path_to_bundle_contents)
     fclose(file);
     return TRUE;
 }
+#endif
 
 
 /* inspired by write_desktop_entry() in xdg support code */
-static BOOL generate_bundle_script(const char *path_to_bundle_macos, const char *path, 
+static BOOL generate_bundle_script(const char *path_to_bundle_macos, const char *path,
                                    const char *args, const char *linkname)
 {
     FILE *file;
     char *bundle_and_script;
+    const char *libpath;
 
     bundle_and_script = heap_printf("%s/%s", path_to_bundle_macos, linkname);
 
@@ -273,37 +277,42 @@ static BOOL generate_bundle_script(const char *path_to_bundle_macos, const char
     fprintf(file, "#!/bin/sh\n");
     fprintf(file, "#Helper script for %s\n\n", linkname);
 
-    /* Just like xdg-menus we DO NOT support running a wine binary other
-     * than one that is already present in the path
-     */
-    fprintf(file, "WINEPREFIX=\"%s\" wine \"%s\" %s\n\n",
-            wine_get_config_dir(), path, args);
-
-    fprintf(file, "#EOF");
-    
-    fclose(file);    
-    chmod(bundle_and_script,0755);
-    
+    fprintf(file, "PATH=\"%s\"\nexport PATH\n", getenv("PATH"));
+    libpath = getenv("DYLD_FALLBACK_LIBRARY_PATH");
+    if (libpath)
+        fprintf(file, "DYLD_FALLBACK_LIBRARY_PATH=\"%s\"\nexport DYLD_FALLBACK_LIBRARY_PATH\n", libpath);
+    fprintf(file, "WINEPREFIX=\"%s\"\nexport WINEPREFIX\n\n", wine_get_config_dir());
+
+    fprintf(file, "exec sh -c \"exec wine %s %s\"\n\n", path, args);
+
+    fprintf(file, "#EOF\n");
+
+    fclose(file);
+    chmod(bundle_and_script, 0755);
+
     return TRUE;
 }
 
 /* build out the directory structure for the bundle and then populate */
-BOOL build_app_bundle(const char *path, const char *args, const char *linkname)
+BOOL build_app_bundle(const char *unix_link, const char *path, const char *args, const char *dir, const char *link, const char *linkname)
 {
 #ifdef __APPLE__
     BOOL ret = FALSE;
-    char *path_to_bundle, *path_to_bundle_contents, *path_to_bundle_macos;
+    char *bundle_name, *path_to_bundle_contents, *path_to_bundle_macos;
     char *path_to_bundle_resources, *path_to_bundle_resources_lang;
     static const char extentsion[] = "app";
     static const char contents[] = "Contents";
     static const char macos[] = "MacOS";
     static const char resources[] = "Resources";
     static const char resources_lang[] = "English.lproj"; /* FIXME */
-    
+
     WINE_TRACE("bundle file name %s\n", wine_dbgstr_a(linkname));
 
-    bundle_name = heap_printf("%s.%s", linkname, extentsion);
-    path_to_bundle = heap_printf("%s/%s", wine_applications_dir, bundle_name);
+    if (!dir)
+	dir = wine_applications_dir;
+
+    bundle_name = heap_printf("%s.%s", link, extentsion);
+    path_to_bundle = heap_printf("%s/%s", dir, bundle_name);
     path_to_bundle_contents = heap_printf("%s/%s", path_to_bundle, contents);
     path_to_bundle_macos =  heap_printf("%s/%s", path_to_bundle_contents, macos);
     path_to_bundle_resources = heap_printf("%s/%s", path_to_bundle_contents, resources);
@@ -321,14 +330,23 @@ BOOL build_app_bundle(const char *path, const char *args, const char *linkname)
     if(ret==FALSE)
        return ret;
 
-    ret = generate_pkginfo_file(path_to_bundle_contents); 
+#if 0
+    ret = generate_pkginfo_file(path_to_bundle_contents);
     if(ret==FALSE)
        return ret;
+#endif
 
     ret = generate_plist(path_to_bundle_contents, linkname);
     if(ret==FALSE)
        return ret;
 
+    if (unix_link)
+    {
+        DWORD ret = register_menus_entry(path_to_bundle, unix_link);
+        if (ret != ERROR_SUCCESS)
+            return FALSE;
+    }
+
 #endif /* __APPLE__ */
     return TRUE;
 }
@@ -338,7 +356,7 @@ BOOL init_apple_de(void)
 {
 #ifdef __APPLE__
     WCHAR shellDesktopPath[MAX_PATH];
-    
+
     HRESULT hr = SHGetFolderPathW(NULL, CSIDL_DESKTOP, NULL, SHGFP_TYPE_CURRENT, shellDesktopPath);
     if (SUCCEEDED(hr))
         mac_desktop_dir = wine_get_unix_file_name(shellDesktopPath);
@@ -351,12 +369,12 @@ BOOL init_apple_de(void)
 
     if (getenv("HOME"))
     {
-        wine_applications_dir = heap_printf("%s/Applications/wine", getenv("HOME"));
+        wine_applications_dir = heap_printf("%s/Applications/Wine", getenv("HOME"));
         create_directories(wine_applications_dir);
         WINE_TRACE("%s\n", wine_applications_dir);
 
         return TRUE;
-    }    
+    }
     else
     {
         WINE_ERR("out of memory\n");
diff --git a/programs/winemenubuilder/winemenubuilder.c b/programs/winemenubuilder/winemenubuilder.c
index d6e9bd2..16587e1 100644
--- a/programs/winemenubuilder/winemenubuilder.c
+++ b/programs/winemenubuilder/winemenubuilder.c
@@ -41,14 +41,14 @@
  * executable containing its icon.
  *
  * TODO
- *  Handle data lnk files. There is no icon in the file; the icon is in 
- * the handler for the file type (or pointed to by the lnk file).  Also it 
+ *  Handle data lnk files. There is no icon in the file; the icon is in
+ * the handler for the file type (or pointed to by the lnk file).  Also it
  * might be better to use a native handler (e.g. a native acroread for pdf
- * files).  
+ * files).
  *  Differentiate between the user's entries and the "All Users" entries.
  * If it is possible to add the desktop files to the native system's
  * shared location for an "All Users" entry then do so.  As a suggestion the
- * shared menu Wine base could be writable to the wine group, or a wineadm 
+ * shared menu Wine base could be writable to the wine group, or a wineadm
  * group.
  *  Clean up fd.o menu icons and .directory files when the menu is deleted
  * in Windows.
@@ -76,6 +76,8 @@
 #ifdef HAVE_FNMATCH_H
 #include <fnmatch.h>
 #endif
+#include <dirent.h>
+#include <limits.h>
 
 #define COBJMACROS
 #define NONAMELESSUNION
@@ -103,7 +105,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(menubuilder);
                                (csidl)==CSIDL_COMMON_DESKTOPDIRECTORY)
 #define in_startmenu(csidl)   ((csidl)==CSIDL_STARTMENU || \
                                (csidl)==CSIDL_COMMON_STARTMENU)
-        
+
 /* link file formats */
 
 #include "pshpack1.h"
@@ -195,17 +197,17 @@ static char *xdg_data_dir;
 static char *xdg_desktop_dir;
 
 /* Mac OS X .app bundle support */
-extern char *wine_applications_dir;
 extern char *mac_desktop_dir;
-extern char *bundle_name;
+extern char *path_to_bundle;
 
 BOOL init_apple_de(void);
-BOOL build_app_bundle(const char *path, const char *args, const char *linkname);
+BOOL build_app_bundle(const char *unix_link, const char *path, const char *args, const char *dir, const char *link, const char *linkname);
 
 static WCHAR* assoc_query(ASSOCSTR assocStr, LPCWSTR name, LPCWSTR extra);
 static HRESULT open_icon(LPCWSTR filename, int index, BOOL bWait, IStream **ppStream);
 
 /* Utility routines */
+#ifndef __APPLE__
 static unsigned short crc16(const char* string)
 {
     unsigned short crc = 0;
@@ -224,6 +226,7 @@ static unsigned short crc16(const char* string)
     }
     return crc;
 }
+#endif
 
 static char *strdupA( const char *str )
 {
@@ -1066,7 +1069,8 @@ static inline int size_to_slot(int size)
 BOOL modify_plist_value(char *plist_path, const char *key, char *value);
 
 static HRESULT platform_write_icon(IStream *icoStream, int exeIndex, LPCWSTR icoPathW,
-                                   const char *destFilename, char **nativeIdentifier)
+                                   const char *destFilename, char **nativeIdentifier,
+                                   BOOL test_only)
 {
     ICONDIRENTRY *iconDirEntries = NULL;
     int numEntries;
@@ -1144,9 +1148,9 @@ static HRESULT platform_write_icon(IStream *icoStream, int exeIndex, LPCWSTR ico
         goto end;
     }
 
-    WINE_FIXME("--------icns files should go in %s/Contents/Resources---------\n", wine_dbgstr_a(bundle_name));
+    WINE_FIXME("--------icns files should go in %s/Contents/Resources---------\n", wine_dbgstr_a(path_to_bundle));
 
-    bundle_path = heap_printf("%s/%s/Contents/Resources", wine_applications_dir, bundle_name);
+    bundle_path = heap_printf("%s/Contents/Resources", path_to_bundle);
     WINE_FIXME("--------icns files should go in %s- (full path)------\n", wine_dbgstr_a(bundle_path));
 
  //   icnsName = heap_printf("%s.icns", guidStrA);
@@ -1158,6 +1162,10 @@ static HRESULT platform_write_icon(IStream *icoStream, int exeIndex, LPCWSTR ico
         WINE_WARN("out of memory creating ICNS path\n");
         goto end;
     }
+
+    if (test_only)
+        goto end;
+
     zero.QuadPart = 0;
     hr = IStream_Seek(icoStream, zero, STREAM_SEEK_SET, NULL);
     if (FAILED(hr))
@@ -1174,7 +1182,7 @@ static HRESULT platform_write_icon(IStream *icoStream, int exeIndex, LPCWSTR ico
         goto end;
     }
 
-    plist_path = heap_printf("%s/%s/Contents/Info.plist", wine_applications_dir, bundle_name);
+    plist_path = heap_printf("%s/Contents/Info.plist", path_to_bundle);
     WINE_FIXME("--------attempting to modify %s- (full path)------\n", wine_dbgstr_a(plist_path));
     icnsName = heap_printf("%s.icns", guidStrA);
     ret = modify_plist_value(plist_path, iconKey, icnsName);
@@ -1187,7 +1195,6 @@ end:
         *nativeIdentifier = icnsPath;
     else
         HeapFree(GetProcessHeap(), 0, icnsPath);
-
     return hr;
 }
 #else
@@ -1212,7 +1219,8 @@ static void refresh_icon_cache(const char *iconsDir)
 }
 
 static HRESULT platform_write_icon(IStream *icoStream, int exeIndex, LPCWSTR icoPathW,
-                                   const char *destFilename, char **nativeIdentifier)
+                                   const char *destFilename, char **nativeIdentifier,
+                                   BOOL test_only)
 {
     ICONDIRENTRY *iconDirEntries = NULL;
     int numEntries;
@@ -1262,6 +1270,9 @@ static HRESULT platform_write_icon(IStream *icoStream, int exeIndex, LPCWSTR ico
         goto end;
     }
 
+    if (test_only)
+        goto end;
+
     for (i = 0; i < numEntries; i++)
     {
         int bestIndex = i;
@@ -1333,7 +1344,7 @@ end:
 #endif /* defined(__APPLE__) */
 
 /* extract an icon from an exe or icon file; helper for IPersistFile_fnSave */
-static char *extract_icon(LPCWSTR icoPathW, int index, const char *destFilename, BOOL bWait)
+static char *extract_icon(LPCWSTR icoPathW, int index, const char *destFilename, BOOL bWait, BOOL test_only)
 {
     IStream *stream = NULL;
     HRESULT hr;
@@ -1347,7 +1358,7 @@ static char *extract_icon(LPCWSTR icoPathW, int index, const char *destFilename,
         WINE_WARN("opening icon %s index %d failed, hr=0x%08X\n", wine_dbgstr_w(icoPathW), index, hr);
         goto end;
     }
-    hr = platform_write_icon(stream, index, icoPathW, destFilename, &nativeIdentifier);
+    hr = platform_write_icon(stream, index, icoPathW, destFilename, &nativeIdentifier, test_only);
     if (FAILED(hr))
         WINE_WARN("writing icon failed, error 0x%08X\n", hr);
 
@@ -1375,7 +1386,7 @@ static HKEY open_menus_reg_key(void)
     return NULL;
 }
 
-static DWORD register_menus_entry(const char *unix_file, const char *windows_file)
+DWORD register_menus_entry(const char *unix_file, const char *windows_file)
 {
     WCHAR *unix_fileW;
     WCHAR *windows_fileW;
@@ -1413,6 +1424,54 @@ static DWORD register_menus_entry(const char *unix_file, const char *windows_fil
     return ret;
 }
 
+static BOOL remove_unix_link(const char *unix_link)
+{
+    struct stat st;
+
+    if (lstat(unix_link, &st))
+        return FALSE;
+
+    if (S_ISDIR(st.st_mode))
+    {
+        char path[PATH_MAX], *epath;
+        DIR *dir = opendir(unix_link);
+        struct dirent *ent;
+
+        if (!dir)
+            return FALSE;
+
+        epath = stpncpy(path, unix_link, PATH_MAX);
+        if (epath - path >= PATH_MAX - 1)
+            return FALSE;
+        *epath++ = '/';
+
+        while ((ent = readdir(dir)))
+        {
+            if ((epath - path) + ent->d_namlen >= PATH_MAX)
+            {
+                closedir(dir);
+                return FALSE;
+            }
+            strcpy(epath, ent->d_name);
+            if (!remove_unix_link(path))
+            {
+                closedir(dir);
+                return FALSE;
+            }
+        }
+        closedir(dir);
+
+        if (rmdir(unix_link))
+            return FALSE;
+    }
+    else
+    {
+        if (unlink(unix_link))
+            return FALSE;
+    }
+    return TRUE;
+}
+
 static BOOL write_desktop_entry(const char *unix_link, const char *location, const char *linkname,
                                 const char *path, const char *args, const char *descr,
                                 const char *workdir, const char *icon)
@@ -1605,9 +1664,11 @@ static BOOL write_menu_entry(const char *unix_link, const char *link, const char
     /* Check for OS X first before attempting xdg support */
     if (mac_desktop_dir)
     {
-        ret = build_app_bundle(path,args,linkname);
+        ret = build_app_bundle(unix_link, path, args, NULL, link, linkname);
+        if (!ret)
+            goto end;
     }
-    
+
     desktopPath = heap_printf("%s/applications/wine/%s.desktop", xdg_data_dir, link);
     if (!desktopPath)
     {
@@ -2392,7 +2453,7 @@ static BOOL cleanup_associations(void)
                     if (desktopFile)
                     {
                         WINE_TRACE("removing file type association for %s\n", wine_dbgstr_w(extensionW));
-                        remove(desktopFile);
+                        remove_unix_link(desktopFile);
                     }
                     RegDeleteKeyW(assocKey, extensionW);
                     hasChanged = TRUE;
@@ -2623,7 +2684,7 @@ static BOOL generate_associations(const char *xdg_data_home, const char *package
                                 *comma = 0;
                                 index = atoiW(comma + 1);
                             }
-                            iconA = extract_icon(iconW, index, flattened_mime, FALSE);
+                            iconA = extract_icon(iconW, index, flattened_mime, FALSE, FALSE);
                             HeapFree(GetProcessHeap(), 0, flattened_mime);
                         }
                     }
@@ -2645,7 +2706,7 @@ static BOOL generate_associations(const char *xdg_data_home, const char *package
 
             executableW = assoc_query(ASSOCSTR_EXECUTABLE, extensionW, openW);
             if (executableW)
-                openWithIconA = extract_icon(executableW, 0, NULL, FALSE);
+                openWithIconA = extract_icon(executableW, 0, NULL, FALSE, FALSE);
 
             friendlyAppNameW = assoc_query(ASSOCSTR_FRIENDLYAPPNAME, extensionW, NULL);
             if (friendlyAppNameW)
@@ -2771,29 +2832,6 @@ static char* escape_unix_link_arg(LPCSTR unix_link)
     return ret;
 }
 
-static BOOL extract_wait ( int iIconId, LPCWSTR szPath, LPCWSTR szIconPath, char *icon_name, BOOL bWait )
-{
-    BOOL ret = TRUE;
-        /* extract the icon */
-        if( szIconPath[0] )
-            icon_name = extract_icon( szIconPath , iIconId, NULL, bWait );
-        else
-            icon_name = extract_icon( szPath, iIconId, NULL, bWait );
-
-        /* fail - try once again after parent process exit */
-        if( !icon_name )
-        {
-            if (bWait)
-            {
-                WINE_WARN("Unable to extract icon, deferring.\n");
-                return FALSE; 
-            }
-            WINE_ERR("failed to extract icon from %s\n",
-                     wine_dbgstr_w( szIconPath[0] ? szIconPath : szPath ));
-        }
-    return ret;
-}
-
 static BOOL InvokeShellLinker( IShellLinkW *sl, LPCWSTR link, BOOL bWait )
 {
     static const WCHAR startW[] = {'\\','c','o','m','m','a','n','d',
@@ -2855,11 +2893,22 @@ static BOOL InvokeShellLinker( IShellLinkW *sl, LPCWSTR link, BOOL bWait )
             WINE_TRACE("pidl path  : %s\n", wine_dbgstr_w(szPath));
     }
 
-    /* insure the icon's are generated after bundle creation */
-    if(!mac_desktop_dir) 
+    /* extract the icon */
+    if( szIconPath[0] )
+        icon_name = extract_icon( szIconPath , iIconId, NULL, bWait, !!mac_desktop_dir );
+    else
+        icon_name = extract_icon( szPath, iIconId, NULL, bWait, !!mac_desktop_dir );
+
+    /* fail - try once again after parent process exit */
+    if( !icon_name )
     {
-        if (!extract_wait ( iIconId, szPath, szIconPath, icon_name, bWait ))
+        if (bWait)
+        {
+            WINE_WARN("Unable to extract icon, deferring.\n");
             goto cleanup;
+        }
+        WINE_ERR("failed to extract icon from %s\n",
+                 wine_dbgstr_w( szIconPath[0] ? szIconPath : szPath ));
     }
 
     unix_link = wine_get_unix_file_name(link);
@@ -2945,31 +2994,41 @@ static BOOL InvokeShellLinker( IShellLinkW *sl, LPCWSTR link, BOOL bWait )
             lastEntry = link_name;
         else
             ++lastEntry;
- 
-        if(mac_desktop_dir)
+
+        if (csidl == CSIDL_COMMON_DESKTOPDIRECTORY)
         {
-            WINE_FIXME("Unable to write bundles to the Desktop\n");
-            goto cleanup;
+            char *link_arg = escape_unix_link_arg(unix_link);
+            if (link_arg)
+            {
+                if (mac_desktop_dir)
+                    r = !build_app_bundle(unix_link, start_path, link_arg, mac_desktop_dir, lastEntry, lastEntry);
+                else
+                {
+                    location = heap_printf("%s/%s.desktop", xdg_desktop_dir, lastEntry);
+                    if (location)
+                    {
+                        r = !write_desktop_entry(unix_link, location, lastEntry,
+                            start_path, link_arg, description, work_dir, icon_name);
+                        HeapFree(GetProcessHeap(), 0, link_arg);
+                        if (r == 0)
+                            chmod(location, 0755);
+                    }
+                }
+            }
         }
- 
-        location = heap_printf("%s/%s.desktop", xdg_desktop_dir, lastEntry);
-        if (location)
+        else
         {
-            if (csidl == CSIDL_COMMON_DESKTOPDIRECTORY)
+            if (mac_desktop_dir)
+                r = !build_app_bundle(unix_link, escaped_path, escaped_args, mac_desktop_dir, lastEntry, lastEntry);
+            else
             {
-                char *link_arg = escape_unix_link_arg(unix_link);
-                if (link_arg)
+                location = heap_printf("%s/%s.desktop", xdg_desktop_dir, lastEntry);
+                if (location)
                 {
-                    r = !write_desktop_entry(unix_link, location, lastEntry,
-                        start_path, link_arg, description, work_dir, icon_name);
-                    HeapFree(GetProcessHeap(), 0, link_arg);
+                    r = !write_desktop_entry(NULL, location, lastEntry, escaped_path, escaped_args, description, work_dir, icon_name);
+                    HeapFree(GetProcessHeap(), 0, location);
                 }
             }
-            else
-                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);
         }
     }
     else
@@ -2979,15 +3038,16 @@ static BOOL InvokeShellLinker( IShellLinkW *sl, LPCWSTR link, BOOL bWait )
         {
             r = !write_menu_entry(unix_link, link_name, start_path, link_arg, description, work_dir, icon_name);
             HeapFree(GetProcessHeap(), 0, link_arg);
-
-            /* Try the icons again if we are on OS X */
-            if(mac_desktop_dir)
-            {
-                if (!extract_wait ( iIconId, szPath, szIconPath, icon_name, bWait ))
-                    goto cleanup;
-            }
         }
     }
+    /* Try the icons again if we are on OS X */
+    if (mac_desktop_dir)
+    {
+        if( szIconPath[0] )
+            icon_name = extract_icon( szIconPath , iIconId, NULL, bWait, FALSE );
+        else
+            icon_name = extract_icon( szPath, iIconId, NULL, bWait, FALSE );
+    }
 
     ReleaseSemaphore( hsem, 1, NULL );
 
@@ -3089,7 +3149,7 @@ static BOOL InvokeShellLinkerForURL( IUniformResourceLocatorW *url, LPCWSTR link
             {
                 if (pv[0].vt == VT_LPWSTR && pv[0].u.pwszVal)
                 {
-                    icon_name = extract_icon( pv[0].u.pwszVal, pv[1].u.iVal, NULL, bWait );
+                    icon_name = extract_icon( pv[0].u.pwszVal, pv[1].u.iVal, NULL, bWait, !!mac_desktop_dir );
 
                     WINE_TRACE("URL icon path: %s icon index: %d icon name: %s\n", wine_dbgstr_w(pv[0].u.pwszVal), pv[1].u.iVal, icon_name);
                 }
@@ -3129,17 +3189,48 @@ static BOOL InvokeShellLinkerForURL( IUniformResourceLocatorW *url, LPCWSTR link
             lastEntry = link_name;
         else
             ++lastEntry;
-        location = heap_printf("%s/%s.desktop", xdg_desktop_dir, lastEntry);
-        if (location)
+        if (mac_desktop_dir)
+            r = !build_app_bundle(NULL, start_path, escaped_urlPath, mac_desktop_dir, lastEntry, lastEntry);
+        else
         {
-            r = !write_desktop_entry(NULL, location, lastEntry, start_path, escaped_urlPath, NULL, NULL, icon_name);
-            if (r == 0)
-                chmod(location, 0755);
-            HeapFree(GetProcessHeap(), 0, location);
+            location = heap_printf("%s/%s.desktop", xdg_desktop_dir, lastEntry);
+            if (location)
+            {
+                r = !write_desktop_entry(NULL, location, lastEntry, start_path, escaped_urlPath, NULL, NULL, icon_name);
+                if (r == 0)
+                    chmod(location, 0755);
+                HeapFree(GetProcessHeap(), 0, location);
+            }
         }
     }
     else
         r = !write_menu_entry(unix_link, link_name, start_path, escaped_urlPath, NULL, NULL, icon_name);
+    /* Try the icons again if we are on OS X */
+    if (mac_desktop_dir)
+    {
+        hr = url->lpVtbl->QueryInterface(url, &IID_IPropertySetStorage, (void **) &pPropSetStg);
+        if (SUCCEEDED(hr))
+        {
+            hr = IPropertySetStorage_Open(pPropSetStg, &FMTID_Intshcut, STGM_READ | STGM_SHARE_EXCLUSIVE, &pPropStg);
+            if (SUCCEEDED(hr))
+            {
+                hr = IPropertyStorage_ReadMultiple(pPropStg, 2, ps, pv);
+                if (SUCCEEDED(hr))
+                {
+                    if (pv[0].vt == VT_LPWSTR && pv[0].u.pwszVal)
+                    {
+                        icon_name = extract_icon( pv[0].u.pwszVal, pv[1].u.iVal, NULL, bWait, FALSE );
+
+                        WINE_TRACE("URL icon path: %s icon index: %d icon name: %s\n", wine_dbgstr_w(pv[0].u.pwszVal), pv[1].u.iVal, icon_name);
+                    }
+                    PropVariantClear(&pv[0]);
+                    PropVariantClear(&pv[1]);
+                }
+                IPropertyStorage_Release(pPropStg);
+            }
+            IPropertySetStorage_Release(pPropSetStg);
+        }
+    }
     ret = (r != 0);
     ReleaseSemaphore(hSem, 1, NULL);
 
@@ -3272,12 +3363,6 @@ static BOOL Process_URL( LPCWSTR urlname, BOOL bWait )
 
     WINE_TRACE("%s, wait %d\n", wine_dbgstr_w(urlname), bWait);
 
-    if(mac_desktop_dir)
-    {
-        WINE_FIXME("Url processing is currently unsupported on this platform\n");
-        return 1;
-    }
-    
     if( !urlname[0] )
     {
         WINE_ERR("URL name missing\n");
@@ -3443,7 +3528,7 @@ static void cleanup_menus(void)
                     if (stat(windows_file, &filestats) < 0 && errno == ENOENT)
                     {
                         WINE_TRACE("removing menu related file %s\n", unix_file);
-                        remove(unix_file);
+                        remove_unix_link(unix_file);
                         RegDeleteValueW(hkey, value);
                     }
                     else
@@ -3662,9 +3747,9 @@ int PASCAL wWinMain (HINSTANCE hInstance, HINSTANCE prev, LPWSTR cmdline, int sh
 
 #ifdef __APPLE__
     if (!init_apple_de())
-#else
-    if (!init_xdg())
+        return 1;
 #endif
+    if (!init_xdg())
         return 1;
 
     hr = CoInitialize(NULL);
