diff --git a/programs/winemenubuilder/appbundler.c b/programs/winemenubuilder/appbundler.c
new file mode 100644
index 0000000..b69f096
--- /dev/null
+++ b/programs/winemenubuilder/appbundler.c
@@ -0,0 +1,305 @@
+/*
+ * Helper program to build OS X Application Bundles
+ *
+ * Copyright 2009 Steven Edwards
+ *
+ * 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
+ *
+ * Thanks to Sveinbjorn Thordarson for his Platypus App Bundler for
+ * helping me understand how to do this.
+ *
+ * NOTES:
+ * This code will create a .app bundle rather than a xdg .desktop menu
+ * while reusing most of the same infrastructure. From there we will
+ * embed a helper binary that will invoke our bash script to load Wine
+ * and the target application.
+ * 
+ * Roadmap:
+ * - Add the Carbon helper app to the Bundle
+ * - Add the script infrastructure
+ * - .plist stuff / version information? / Wine Version information?
+ * - Maybe sha1/md5sum of target application in bundle plist, then we can
+ *   have the helper check it at startup time and or force regeneration
+ *   of shortcuts/associations
+ * - Associations?
+ */ 
+
+
+#include "config.h"
+#include "wine/port.h"
+
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <errno.h>
+#include <stdarg.h>
+#ifdef HAVE_FNMATCH_H
+#include <fnmatch.h>
+#endif
+
+#define COBJMACROS
+
+#include <windows.h>
+#include <shlobj.h>
+#include <objidl.h>
+#include <shlguid.h>
+#include <appmgmt.h>
+#include <tlhelp32.h>
+#include <intshcut.h>
+#include <shlwapi.h>
+
+#include "wine/unicode.h"
+#include "wine/debug.h"
+#include "wine/library.h"
+#include "wine/list.h"
+#include "wine.xpm"
+
+// get/setxattr
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/xattr.h>
+
+
+WINE_DEFAULT_DEBUG_CHANNEL(menubuilder);
+
+/*
+ * foo.app/Contents
+ * foo.app/Contents/Info.plist
+ * foo.app/Contents/MacOS
+ * foo.app/Contents/MacOS/foo (helper binary)
+ * foo.app/Contents/Resources/appIcon.icns (See about using png or something else)
+ * foo.app/Contents/Resources/AppSettings.plist
+ * foo.app/Contents/Resources/English.lproj
+ * foo.app/Contents/Resources/English.lproj/infoPlist.strings
+ * foo.app/Contents/Resources/English.lproj/MainMenu.nib (copy this from wine prefix or tree)
+ * foo.app/Contents/Resources/script
+ */
+
+// Build -/Wine/Programs?
+//       -/Wine/Builtin Wine Applications?
+//
+// Icon as an argumnet to function?
+
+
+char* heap_printf(const char *format, ...);
+BOOL create_directories(char *directory);
+
+char *mac_desktop_dir;
+char *wine_applications_dir;
+char *windows_applications_dir;
+char *xdg_data_dir;
+char *xdg_config_dir;
+
+
+BOOL generate_plist_for_bundle(const char *path_to_bundle_contents, const char *linkname)
+{
+    int err;
+    FILE *file;
+    char *bundle_and_info_dot_plist;
+    static const char info_dot_plist_file[] = "Info.plist";
+    static char eaname[] = "com.apple.xcode.PlistType";
+    static char eavalue[] = "com.apple.xcode.plist.structure-definition.info-plist";
+    ssize_t xattr_size;
+    
+    bundle_and_info_dot_plist = heap_printf("%s/%s", path_to_bundle_contents, info_dot_plist_file);
+
+    WINE_TRACE("Creating Bundle Info.plist at %s\n", wine_dbgstr_a(bundle_and_info_dot_plist));
+
+    file = fopen(bundle_and_info_dot_plist, "w");
+    if (file == NULL)
+        return FALSE;
+
+    /* BE SURE YOU ESCAPE YOUR QUOTES! 
+     * Use use \t here for consitancey with Property Editor generated plists
+     * spaces might work just as well
+     */
+
+    fprintf(file, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+    fprintf(file, "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n");
+    fprintf(file, "<plist version=\"1.0\">\n");
+    fprintf(file, "<dict>\n");
+    fprintf(file, "\t<key>CFBundleDevelopmentRegion</key>\n");
+    fprintf(file, "\t<string>English</string>\n");
+    fprintf(file, "\t<key>CFBundleExecutable</key>\n");
+    fprintf(file, "\t<string>wineappbundler</string>\n");
+    fprintf(file, "\t<key>CFBundleIdentifier</key>\n");
+    fprintf(file, "\t<string>org.winehq.wine</string>\n");
+    fprintf(file, "\t<key>CFBundleInfoDictionaryVersion</key>\n");
+    fprintf(file, "\t<string>6.0</string>\n");
+    fprintf(file, "\t<key>CFBundleName</key>\n");
+    fprintf(file, "\t<string>wineappbundler</string>\n");
+    fprintf(file, "\t<key>CFBundlePackageType</key>\n");
+    fprintf(file, "\t<string>APPL</string>\n");
+    fprintf(file, "\t<key>CFBundleSignature</key>\n");
+    fprintf(file, "\t<string>????</string>\n");
+    fprintf(file, "\t<key>CFBundleVersion</key>\n");
+    fprintf(file, "\t<string>1.0</string>\n");
+    fprintf(file, "\t<key>CFBundleIconFile</key>\n");
+    fprintf(file, "\t<string>Wine.icns</string>\n");
+    fprintf(file, "</dict>\n");
+    fprintf(file, "</plist>\n");
+
+    fclose(file);
+
+    xattr_size = strlen(eavalue);
+
+    err = setxattr(bundle_and_info_dot_plist, eaname, eavalue, xattr_size, 0, 0);
+    
+    if (err < 0 )
+    {
+        WINE_TRACE("Error Setting Extened Attributes %s ,%s on file %s\n", 
+                   wine_dbgstr_a(eaname), wine_dbgstr_a(eavalue),wine_dbgstr_a(bundle_and_info_dot_plist));
+    }
+
+    return TRUE;
+}
+
+BOOL copy_helper_to_bundle(char *filename)
+{
+    /* TODO */
+    return FALSE;
+}
+
+//Change APPL???? to something else if you want another type of assocations
+//More research required
+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;
+}
+
+
+// see write_desktop_entry() in xdg support code
+BOOL generate_helper_script(const char *path_to_bundle_resources, const char *path, const char *args, const char *linkname)
+{
+    FILE *file;
+    char *bundle_and_script;
+    static const char script[] = "script.sh";
+
+    bundle_and_script = heap_printf("%s/%s", path_to_bundle_resources, script);
+
+    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/bash\n");
+    fprintf(file, "#Helper script for %s\n\n", linkname);
+
+    /* FIXME: What to do about Wine not in path or run out of source tree? */
+    fprintf(file, "WINEPREFIX=\"%s\" wine \"%s\" %s\n\n",
+            wine_get_config_dir(), path, args);
+
+    fprintf(file, "#EOF");
+
+    fclose(file);
+    return TRUE;
+}
+
+BOOL build_app_bundle(const char *path, const char *args, const char *linkname)
+{
+    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", windows_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_helper_script(path_to_bundle_resources, path, args, linkname);
+    if(ret==FALSE)
+       return ret;
+
+    ret = generate_pkginfo_file(path_to_bundle_contents); 
+    if(ret==FALSE)
+       return ret;
+
+    ret = generate_plist_for_bundle(path_to_bundle_contents, linkname);
+    if(ret==FALSE)
+       return ret;
+
+    return TRUE;
+}
+
+int init_apple_de(void)
+{
+    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 0;
+    }
+
+    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);
+
+        windows_applications_dir = heap_printf("%s/Applications/wine", getenv("HOME"));
+        create_directories(windows_applications_dir);
+        WINE_TRACE("%s\n", windows_applications_dir);
+
+        return 1;
+    }    
+    else
+    {
+        WINE_ERR("out of memory\n");
+        return 0;
+    }
+}
+
diff --git a/programs/winemenubuilder/winemenubuilder.c b/programs/winemenubuilder/winemenubuilder.c
index 1eaa530..9aa1429 100644
--- a/programs/winemenubuilder/winemenubuilder.c
+++ b/programs/winemenubuilder/winemenubuilder.c
@@ -168,9 +168,12 @@ struct xdg_mime_type
     struct list entry;
 };
 
-static char *xdg_config_dir;
-static char *xdg_data_dir;
-static char *xdg_desktop_dir;
+char *xdg_config_dir;
+char *xdg_data_dir;
+char *xdg_desktop_dir;
+
+BOOL init_apple_de(void);
+int is_mac = 0;
 
 /* Icon extraction routines
  *
@@ -692,7 +695,7 @@ static unsigned short crc16(const char* string)
     return crc;
 }
 
-static char* heap_printf(const char *format, ...)
+char* heap_printf(const char *format, ...)
 {
     va_list args;
     int size = 4096;
@@ -718,7 +721,7 @@ static char* heap_printf(const char *format, ...)
     return buffer;
 }
 
-static BOOL create_directories(char *directory)
+BOOL create_directories(char *directory)
 {
     BOOL ret = TRUE;
     int i;
@@ -834,6 +837,8 @@ static HKEY open_menus_reg_key(void)
     return NULL;
 }
 
+BOOL build_app_bundle(const char *path, const char *args, const char *linkname);
+
 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)
@@ -844,6 +849,12 @@ static BOOL write_desktop_entry(const char *unix_link, const char *location, con
                wine_dbgstr_a(linkname), wine_dbgstr_a(path), wine_dbgstr_a(args),
                wine_dbgstr_a(descr), wine_dbgstr_a(workdir), wine_dbgstr_a(icon));
 
+    /* This check should happen before any xdg stuff like in InvokeShellLinkerfoo */
+    if (is_mac)
+    {
+        return build_app_bundle(path,args,linkname);
+    }
+
     file = fopen(location, "w");
     if (file == NULL)
         return FALSE;
@@ -918,6 +929,12 @@ static BOOL write_menu_file(const char *unix_link, const char *filename)
 
     WINE_TRACE("(%s)\n", wine_dbgstr_a(filename));
 
+    if(is_mac)
+    {
+        /* Bail out as we don't need menus */
+        return ret;
+    }
+
     while (1)
     {
         tempfilename = heap_printf("%s/wine-menu-XXXXXX", xdg_config_dir);
@@ -1051,7 +1068,6 @@ static BOOL write_menu_entry(const char *unix_link, const char *link, const char
         ret = FALSE;
         goto end;
     }
-
     filename = heap_printf("wine/%s.desktop", link);
     if (!filename || !write_menu_file(unix_link, filename))
     {
@@ -2492,6 +2508,13 @@ static void RefreshFileTypeAssociations(void)
     char *applications_dir = NULL;
     BOOL hasChanged;
 
+    if(is_mac)
+    {
+        WINE_FIXME("Add Association Support to OS X Build\n");
+        goto end;
+    }
+
+
     hSem = CreateSemaphoreA( NULL, 1, 1, "winemenubuilder_semaphore");
     if( WAIT_OBJECT_0 != MsgWaitForMultipleObjects( 1, &hSem, FALSE, INFINITE, QS_ALLINPUT ) )
     {
@@ -2696,8 +2719,10 @@ int PASCAL WinMain (HINSTANCE hInstance, HINSTANCE prev, LPSTR cmdline, int show
     BOOL bURL = FALSE;
     int ret = 0;
 
-    if (!init_xdg())
-        return 1;
+    is_mac = init_apple_de();
+    
+    if (!is_mac || !init_xdg())
+        return 0;
 
     for( p = cmdline; p && *p; )
     {
diff --git a/tools/wineappbundler.c b/tools/wineappbundler.c
new file mode 100644
index 0000000..a174805
--- /dev/null
+++ b/tools/wineappbundler.c
@@ -0,0 +1,109 @@
+
+#include <stdio.h>
+#include <Carbon/Carbon.h>
+#include <unistd.h>
+
+#include <sys/param.h> /* needed for MAXPATHLEN */
+
+static pascal OSErr OpenDocumentsAE(const AppleEvent *theAppleEvent, AppleEvent *reply, long handlerRefcon);
+
+static OSErr OpenDocument(FSRef *theFSRef)
+{
+	OSErr err;
+	UInt8 path[MAXPATHLEN];
+
+	err = FSRefMakePath( theFSRef, path, MAXPATHLEN);
+	printf("Open File: %s\n", path);
+	
+	return err;
+}
+
+/* http://developer.apple.com/documentation/applescript/conceptual/AppleEvents/responding_aepg/responding_aepg.html */
+
+static pascal OSErr OpenDocumentsAE(const AppleEvent *theAppleEvent, AppleEvent *reply, long handlerRefcon)
+{
+	AEDescList docList;
+	FSRef theFSRef;
+	long index;
+	long count = 0;
+	OSErr err;
+
+	QuitApplicationEventLoop();	/* Quit the EventLoop as we have what we want */
+	
+	err = AEGetParamDesc(theAppleEvent, keyDirectObject, typeAEList, &docList);
+	require_noerr(err, CantGetDocList);
+	err = AECountItems(&docList, &count);
+	require_noerr(err, CantGetCount);
+    for(index = 1; index <= count; index++) {
+		err = AEGetNthPtr(&docList, index, typeFSRef, NULL, NULL, &theFSRef, sizeof(FSRef), NULL);
+		require_noerr(err, CantGetDocDescPtr);
+		err = OpenDocument(&theFSRef);
+	}
+	AEDisposeDesc(&docList);
+
+    CantGetDocList:
+    CantGetCount:
+    CantGetDocDescPtr:
+
+	return(err);
+}
+
+
+static OSErr InstallMacOSEventHandlers(void)
+{
+    OSErr err;
+	
+    err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, NewAEEventHandlerUPP(OpenDocumentsAE), 0, false);
+    require_noerr(err, CantInstallAppleEventHandler);
+	
+    CantInstallAppleEventHandler:
+
+    return err;
+}
+
+
+int main (int argc, const char * argv[])
+{
+	/* Example code from Philip Lamb
+	 * http://lists.apple.com/archives/Mac-games-dev/2005/Nov/msg00049.html
+	 */
+	CFURLRef pathCFURLRef;
+	CFStringRef pathCFString;
+	char *path;
+	int pathLen;
+	
+	/* Change working directory to "Resources" directory inside main bundle. */
+	/* Could find out where we begin with getcwd(path, MAXPATHLEN); */
+	path = (char *)malloc(MAXPATHLEN * sizeof(char));
+	pathCFURLRef = CFBundleCopyBundleURL(CFBundleGetMainBundle()); // Get path to application bundle.
+	pathCFString = CFURLCopyFileSystemPath(pathCFURLRef, kCFURLPOSIXPathStyle);
+	CFStringGetCString(pathCFString, path, MAXPATHLEN, CFStringGetSystemEncoding());
+	CFRelease(pathCFString);
+	CFRelease(pathCFURLRef);
+	
+	fprintf(stderr,"Application bundle directory is %s\n", path);
+	pathLen = strlen(path);
+	path[pathLen++] = '/';
+	pathCFURLRef = CFBundleCopyResourcesDirectoryURL (CFBundleGetMainBundle()); /* Get relative path to resources directory. */
+	pathCFString = CFURLCopyFileSystemPath(pathCFURLRef, kCFURLPOSIXPathStyle);
+	CFStringGetCString(pathCFString, path + pathLen, MAXPATHLEN, CFStringGetSystemEncoding());
+	if (chdir(path) != 0) {
+		fprintf(stderr, "Unable to change working directory to %s.\n", path);
+		perror(NULL);
+		exit(-1);
+	}
+	
+	fprintf(stderr,"Current working directory is %s\n", path); 
+	CFRelease(pathCFString);
+	CFRelease(pathCFURLRef);
+	free(path);
+	
+	if(fork()==0) {
+		execl( "/bin/bash", "bash", "script.sh", NULL);
+		exit(0);
+	}
+
+	InstallMacOSEventHandlers(); /* register for kAEOpenDocuments events */
+    RunApplicationEventLoop(); /* we need a running EventLoop to catch the kAEOpenDocuments event */		
+}
+
