diff --git a/programs/winemenubuilder/Makefile.in b/programs/winemenubuilder/Makefile.in
index 092405e..c2b45ba 100644
--- a/programs/winemenubuilder/Makefile.in
+++ b/programs/winemenubuilder/Makefile.in
@@ -6,9 +6,11 @@ VPATH     = @srcdir@
 MODULE    = winemenubuilder.exe
 APPMODE   = -mwindows
 IMPORTS   = uuid shell32 shlwapi ole32 user32 advapi32 kernel32
+EXTRALIBS = @COREFOUNDATIONLIB@
 EXTRAINCL = @PNGINCL@
 
 C_SRCS = \
+	appbundler.c \
 	winemenubuilder.c
 
 @MAKE_PROG_RULES@
diff --git a/programs/winemenubuilder/winemenubuilder.c b/programs/winemenubuilder/winemenubuilder.c
index e14fe81..be40b73 100644
--- a/programs/winemenubuilder/winemenubuilder.c
+++ b/programs/winemenubuilder/winemenubuilder.c
@@ -172,6 +172,11 @@ static char *xdg_config_dir;
 static char *xdg_data_dir;
 static char *xdg_desktop_dir;
 
+/* Mac OS X .app bundle support */
+char *mac_desktop_dir = NULL;
+BOOL init_apple_de(void);
+BOOL build_app_bundle(const char *path, const char *args, const char *linkname);
+
 /* Icon extraction routines
  *
  * FIXME: should use PrivateExtractIcons and friends
@@ -701,7 +706,7 @@ static char *strdupA( const char *str )
     return ret;
 }
 
-static char* heap_printf(const char *format, ...)
+char* heap_printf(const char *format, ...)
 {
     va_list args;
     int size = 4096;
@@ -750,7 +755,7 @@ static void write_xml_text(FILE *file, const char *text)
     }
 }
 
-static BOOL create_directories(char *directory)
+BOOL create_directories(char *directory)
 {
     BOOL ret = TRUE;
     int i;
@@ -1067,6 +1072,13 @@ static BOOL write_menu_entry(const char *unix_link, const char *link, const char
     else
         ++linkname;
 
+    /* Check for OS X first before attempting xdg support since its the odd man out */
+    if (mac_desktop_dir)
+    {
+        ret = build_app_bundle(path,args,linkname);
+        goto end;
+    }
+
     desktopPath = heap_printf("%s/applications/wine/%s.desktop", xdg_data_dir, link);
     if (!desktopPath)
     {
@@ -2235,6 +2247,13 @@ static BOOL InvokeShellLinker( IShellLinkW *sl, LPCWSTR link, BOOL bWait )
             lastEntry = link_name;
         else
             ++lastEntry;
+            
+        if(mac_desktop_dir)
+        {
+            WINE_FIXME("Unable to write bundles to the Desktop\n");
+            goto cleanup;
+        }
+            
         location = heap_printf("%s/%s.desktop", xdg_desktop_dir, lastEntry);
         if (location)
         {
@@ -2475,6 +2494,12 @@ 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");
@@ -2538,6 +2563,12 @@ static void RefreshFileTypeAssociations(void)
     char *applications_dir = NULL;
     BOOL hasChanged;
 
+    if(mac_desktop_dir)
+    {
+        WINE_FIXME("FileType Associations are currently unsupported on this platform\n");
+        goto end;
+    }
+
     hSem = CreateSemaphoreA( NULL, 1, 1, "winemenubuilder_semaphore");
     if( WAIT_OBJECT_0 != MsgWaitForMultipleObjects( 1, &hSem, FALSE, INFINITE, QS_ALLINPUT ) )
     {
@@ -2741,9 +2772,9 @@ int PASCAL WinMain (HINSTANCE hInstance, HINSTANCE prev, LPSTR cmdline, int show
     BOOL bWait = FALSE;
     BOOL bURL = FALSE;
     int ret = 0;
-
-    if (!init_xdg())
-        return 1;
+    
+    if (!init_apple_de() && !init_xdg())
+        return 0;
 
     for( p = cmdline; p && *p; )
     {
--- /dev/null	2009-11-22 18:55:33.775106274 -0500
+++ programs/winemenubuilder/appbundler.c	2009-12-04 01:28:26.000000000 -0500
@@ -0,0 +1,338 @@
+/*
+ * Winemenubuilder support for Mac OS X Application Bundles
+ *
+ * Copyright 2009 Steven Edwards for the Bordeaux Group
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ *
+ * NOTES: An Application Bundle generally has the following layout
+ *
+ * foo.app/Contents
+ * foo.app/Contents/Info.plist
+ * foo.app/Contents/MacOS/foo (can be script or real binary)
+ * foo.app/Contents/Resources/appIcon.icns (Apple Icon format)
+ * foo.app/Contents/Resources/English.lproj/infoPlist.strings
+ * foo.app/Contents/Resources/English.lproj/MainMenu.nib (Menu Layout)
+ *
+ * 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
+ * - Fix up the extract_icon routine from main source file and see if we
+ *   can convert to *.icns or use png directly
+ * - See if there is anything else in the rsrc section of the target that
+ *   we might want to dump in a *.plist. Version information for the target
+ *   and or Wine Version information come to mind.
+ * - Association Support
+ * - sha1hash of target application in bundle plist
+ */ 
+
+#include "config.h"
+#include "wine/port.h"
+
+#include <stdio.h>
+#include <errno.h>
+
+#include <shlobj.h>
+
+#ifdef __APPLE__
+# include <CoreFoundation/CoreFoundation.h>
+#endif
+
+#include "wine/debug.h"
+#include "wine/library.h"
+
+
+WINE_DEFAULT_DEBUG_CHANNEL(menubuilder);
+
+extern char *mac_desktop_dir;
+char *wine_applications_dir;
+char* heap_printf(const char *format, ...);
+BOOL create_directories(char *directory);
+
+#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. */ 
+   /* FIXME - Some values assumed the ought not to be */
+   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") ); 
+   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("CFBundleIconFile"), CFSTR("icon.icns") ); 
+   
+   return dict;
+}
+ 
+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);
+}
+
+/* This might come in handy for debuggging */
+#if 0
+CFPropertyListRef CreateMyPropertyListFromFile( CFURLRef fileURL ) 
+{
+    CFPropertyListRef propertyList;
+    CFStringRef       errorString;
+    CFDataRef         resourceData;
+    Boolean           status;
+    SInt32            errorCode;
+ 
+    /* Read the XML file */
+    status = CFURLCreateDataAndPropertiesFromResource(
+               kCFAllocatorDefault,
+               fileURL,
+               &resourceData,
+               NULL,
+               NULL,
+               &errorCode);
+ 
+   /* Reconstitute the dictionary using the XML data. */
+   propertyList = CFPropertyListCreateFromXMLData( kCFAllocatorDefault,
+               resourceData,
+               kCFPropertyListImmutable,
+               &errorString);
+ 
+   CFRelease( resourceData );
+   return propertyList;
+}
+#endif
+
+static BOOL generate_plist(const char *path_to_bundle_contents, const char *linkname)
+{
+    char *plist_path;
+    static const char info_dot_plist_file[] = "Info.plist";
+    CFPropertyListRef propertyList;
+    CFStringRef pathstr;
+    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); 
+    pathstr = CFStringCreateWithCString(NULL, plist_path, CFStringGetSystemEncoding());
+ 
+    /* Construct a complex dictionary object */
+    propertyList = CreateMyDictionary(linkname);
+ 
+    /* Create a URL that specifies the file we will create to hold the XML data. */
+    fileURL = CFURLCreateWithFileSystemPath( kCFAllocatorDefault,
+                                             pathstr,
+                                             kCFURLPOSIXPathStyle,
+                                             false );
+
+    /* 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
+    CFRelease(fileURL);
+
+    WINE_TRACE("Creating Bundle Info.plist at %s\n", wine_dbgstr_a(plist_path));
+
+    return TRUE;
+}
+#endif /* __APPLE__ */
+
+
+/* TODO: If I understand this file correctly, it is used for associations */
+static BOOL generate_pkginfo_file(const char* path_to_bundle_contents)
+{
+    FILE *file;
+    char *bundle_and_pkginfo;
+    static const char pkginfo_file[] = "PkgInfo";
+
+    bundle_and_pkginfo = heap_printf("%s/%s", path_to_bundle_contents, pkginfo_file);
+
+    WINE_TRACE("Creating Bundle PkgInfo at %s\n", wine_dbgstr_a(bundle_and_pkginfo));
+
+    file = fopen(bundle_and_pkginfo, "w");
+    if (file == NULL)
+        return FALSE;
+
+    fprintf(file, "APPL????");
+
+    fclose(file);
+    return TRUE;
+}
+
+
+/* inspired by write_desktop_entry() in xdg support code */
+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;
+
+    bundle_and_script = heap_printf("%s/%s", path_to_bundle_macos, linkname);
+
+    WINE_TRACE("Creating Bundle helper script at %s\n", wine_dbgstr_a(bundle_and_script));
+
+    file = fopen(bundle_and_script, "w");
+    if (file == NULL)
+        return FALSE;
+
+    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);
+    
+    return TRUE;
+}
+
+BOOL generate_icns_for_bundle(const char *path, const char *path_to_bundle_resources)
+{
+    /* Stub for now */
+    WINE_FIXME("Unable to extract png file from target executable for App Bundle\n");
+    return FALSE;
+}
+
+/* build out the directory structure for the bundle and then populate */
+BOOL build_app_bundle(const char *path, const char *args, const char *linkname)
+{
+#ifdef __APPLE__
+    BOOL ret = FALSE;
+    char *bundle, *path_to_bundle, *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 = heap_printf("%s.%s", linkname, extentsion);
+    path_to_bundle = heap_printf("%s/%s", wine_applications_dir, bundle);
+    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);
+    path_to_bundle_resources_lang = heap_printf("%s/%s", path_to_bundle_resources, resources_lang);
+
+    create_directories(path_to_bundle);
+    create_directories(path_to_bundle_contents);
+    create_directories(path_to_bundle_macos);
+    create_directories(path_to_bundle_resources);
+    create_directories(path_to_bundle_resources_lang);
+
+    WINE_TRACE("created bundle %s\n", wine_dbgstr_a(path_to_bundle));
+    
+    ret = generate_icns_for_bundle(path, path_to_bundle_resources);
+    if(ret==FALSE)
+       WINE_WARN("Failed to generate icon for Application Bundle\n");
+
+    ret = generate_bundle_script(path_to_bundle_macos, path, args, linkname);
+    if(ret==FALSE)
+       return ret;
+
+    ret = generate_pkginfo_file(path_to_bundle_contents); 
+    if(ret==FALSE)
+       return ret;
+
+    ret = generate_plist(path_to_bundle_contents, linkname);
+    if(ret==FALSE)
+       return ret;
+
+#endif /* __APPLE__ */
+    return TRUE;
+}
+
+
+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);
+
+    if (mac_desktop_dir == NULL)
+    {
+        WINE_ERR("error looking up the desktop directory\n");
+        return FALSE;
+    }
+
+    if (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");
+        return FALSE;
+    }
+#else
+    return FALSE;
+#endif
+}
