[2/10] winemenubuilder: Use a dispatch table to access XDG specific parts. (try 2)

Per Johansson per at morth.org
Wed Mar 20 02:43:26 CDT 2013


Also adds a "none" option for dispatch to disable winemenubuilder.

build_desktop_link and build_menu_link was made to have identical
arguments, which is why lastEntry was moved.
---
 programs/winemenubuilder/winemenubuilder.c | 384 ++++++++++++++++++-----------
 programs/winemenubuilder/winemenubuilder.h |  59 +++++
 2 files changed, 305 insertions(+), 138 deletions(-)
 create mode 100644 programs/winemenubuilder/winemenubuilder.h

diff --git a/programs/winemenubuilder/winemenubuilder.c b/programs/winemenubuilder/winemenubuilder.c
index 1aabda0..5425854 100644
--- a/programs/winemenubuilder/winemenubuilder.c
+++ b/programs/winemenubuilder/winemenubuilder.c
@@ -7,6 +7,7 @@
  * Copyright 2004 Dmitry Timoshkov
  * Copyright 2005 Bill Medland
  * Copyright 2008 Damjan Jovanovic
+ * Copyright 2011 - 2013 Per Johansson
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -97,6 +98,8 @@
 #include "wine/list.h"
 #include "wine/rbtree.h"
 
+#include "winemenubuilder.h"
+
 WINE_DEFAULT_DEBUG_CHANNEL(menubuilder);
 
 #define in_desktop_dir(csidl) ((csidl)==CSIDL_DESKTOPDIRECTORY || \
@@ -130,25 +133,6 @@ typedef struct
 
 typedef struct
 {
-    BYTE bWidth;
-    BYTE bHeight;
-    BYTE bColorCount;
-    BYTE bReserved;
-    WORD wPlanes;
-    WORD wBitCount;
-    DWORD dwBytesInRes;
-    DWORD dwImageOffset;
-} ICONDIRENTRY;
-
-typedef struct
-{
-    WORD idReserved;
-    WORD idType;
-    WORD idCount;
-} ICONDIR;
-
-typedef struct
-{
     WORD offset;
     WORD length;
     WORD flags;
@@ -175,6 +159,15 @@ typedef struct
         int   nIndex;
 } ENUMRESSTRUCT;
 
+struct xdg_file_type_user_data
+{
+    char *mime_dir;
+    char *packages_dir;
+    char *applications_dir;
+
+    struct list *native_mime_types;
+};
+
 struct xdg_mime_type
 {
     char *mimeType;
@@ -191,6 +184,8 @@ struct rb_string_entry
 
 DEFINE_GUID(CLSID_WICIcnsEncoder, 0x312fb6f1,0xb767,0x409d,0x8a,0x6d,0x0f,0xc1,0x54,0xd4,0xf0,0x5c);
 
+const struct winemenubuilder_dispatch *wmb_dispatch;
+
 static char *xdg_config_dir;
 static char *xdg_data_dir;
 static char *xdg_desktop_dir;
@@ -1126,7 +1121,7 @@ static inline int size_to_slot(int size)
 
 #define CLASSIC_SLOT 3
 
-static HRESULT platform_write_icon(IStream *icoStream, int exeIndex, LPCWSTR icoPathW,
+static HRESULT osx_write_icon(IStream *icoStream, int exeIndex, LPCWSTR icoPathW,
                                    const char *destFilename, char **nativeIdentifier)
 {
     ICONDIRENTRY *iconDirEntries = NULL;
@@ -1256,7 +1251,7 @@ static void refresh_icon_cache(const char *iconsDir)
     }
 }
 
-static HRESULT platform_write_icon(IStream *icoStream, int exeIndex, LPCWSTR icoPathW,
+static HRESULT xdg_write_icon(IStream *icoStream, int exeIndex, LPCWSTR icoPathW,
                                    const char *destFilename, char **nativeIdentifier)
 {
     ICONDIRENTRY *iconDirEntries = NULL;
@@ -1370,7 +1365,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 = wmb_dispatch->write_icon(stream, index, icoPathW, destFilename, &nativeIdentifier);
     if (FAILED(hr))
         WINE_WARN("writing icon failed, error 0x%08X\n", hr);
 
@@ -2177,14 +2172,15 @@ static BOOL match_glob(struct list *native_mime_types, const char *extension,
     return TRUE;
 }
 
-static BOOL freedesktop_mime_type_for_extension(struct list *native_mime_types,
+static BOOL freedesktop_mime_type_for_extension(void *user,
                                                 const char *extensionA,
                                                 LPCWSTR extensionW,
                                                 char **mime_type)
 {
+    struct xdg_file_type_user_data *ud = user;
     WCHAR *lower_extensionW;
     INT len;
-    BOOL ret = match_glob(native_mime_types, extensionA, 0, mime_type);
+    BOOL ret = match_glob(ud->native_mime_types, extensionA, 0, mime_type);
     if (ret == FALSE || *mime_type != NULL)
         return ret;
     len = strlenW(extensionW);
@@ -2197,7 +2193,7 @@ static BOOL freedesktop_mime_type_for_extension(struct list *native_mime_types,
         lower_extensionA = wchars_to_utf8_chars(lower_extensionW);
         if (lower_extensionA)
         {
-            ret = match_glob(native_mime_types, lower_extensionA, 1, mime_type);
+            ret = match_glob(ud->native_mime_types, lower_extensionA, 1, mime_type);
             HeapFree(GetProcessHeap(), 0, lower_extensionA);
         }
         else
@@ -2368,7 +2364,7 @@ done:
     HeapFree(GetProcessHeap(), 0, openWithIconW);
 }
 
-static BOOL cleanup_associations(char *applications_dir)
+static BOOL cleanup_associations(void *user)
 {
     static const WCHAR openW[] = {'o','p','e','n',0};
     HKEY assocKey;
@@ -2406,14 +2402,8 @@ static BOOL cleanup_associations(char *applications_dir)
                     char *extensionA = wchars_to_utf8_chars(strlwrW(extensionW));
                     if (extensionA)
                     {
-                        char *desktopFile = heap_printf("%s/wine-extension-%s.desktop", applications_dir, &extensionA[1]);
+                        wmb_dispatch->remove_file_type_association(user, extensionA, extensionW);
 
-                        if (desktopFile)
-                        {
-                            WINE_TRACE("removing file type association for %s\n", wine_dbgstr_w(extensionW));
-                            remove(desktopFile);
-                            HeapFree(GetProcessHeap(), 0, desktopFile);
-                        }
                         HeapFree(GetProcessHeap(), 0, extensionA);
                     }
                     RegDeleteKeyW(assocKey, extensionW);
@@ -2438,16 +2428,17 @@ static BOOL cleanup_associations(char *applications_dir)
     return hasChanged;
 }
 
-static BOOL write_freedesktop_mime_type_entry(const char *packages_dir, const char *dot_extension,
+static BOOL write_freedesktop_mime_type_entry(void *user, const char *dot_extension,
                                               const char *mime_type, const char *comment)
 {
+    struct xdg_file_type_user_data *ud = user;
     BOOL ret = FALSE;
     char *filename;
 
     WINE_TRACE("writing MIME type %s, extension=%s, comment=%s\n", wine_dbgstr_a(mime_type),
                wine_dbgstr_a(dot_extension), wine_dbgstr_a(comment));
 
-    filename = heap_printf("%s/x-wine-extension-%s.xml", packages_dir, &dot_extension[1]);
+    filename = heap_printf("%s/x-wine-extension-%s.xml", ud->packages_dir, &dot_extension[1]);
     if (filename)
     {
         FILE *packageFile = fopen(filename, "w");
@@ -2503,12 +2494,21 @@ static const char* get_special_mime_type(LPCWSTR extension)
     return NULL;
 }
 
-static BOOL write_freedesktop_association_entry(const char *desktopPath, const char *dot_extension,
-                                                const char *friendlyAppName, const char *mimeType,
-                                                const char *progId, const char *openWithIcon)
+static BOOL write_freedesktop_association_entry(void *user, const char *dot_extension,
+                                                const char *friendlyAppName,
+                                                const char *friendlyDocNameA,
+                                                const char *mimeType, const char *progId,
+                                                const char *openWithIcon)
 {
+    struct xdg_file_type_user_data *ud = user;
     BOOL ret = FALSE;
     FILE *desktop;
+    char *desktopPath = heap_printf("%s/wine-extension-%s.desktop", ud->applications_dir, &dot_extension[1]);
+
+    if (!desktopPath) {
+        WINE_ERR("out of memory\n");
+        return FALSE;
+    }
 
     WINE_TRACE("writing association for file type %s, friendlyAppName=%s, MIME type %s, progID=%s, icon=%s to file %s\n",
                wine_dbgstr_a(dot_extension), wine_dbgstr_a(friendlyAppName), wine_dbgstr_a(mimeType),
@@ -2534,11 +2534,10 @@ static BOOL write_freedesktop_association_entry(const char *desktopPath, const c
     return ret;
 }
 
-static BOOL generate_associations(const char *xdg_data_home, const char *packages_dir, const char *applications_dir)
+static BOOL generate_associations(void *user)
 {
     static const WCHAR openW[] = {'o','p','e','n',0};
     struct wine_rb_tree mimeProgidTree;
-    struct list *nativeMimeTypes = NULL;
     LSTATUS ret = 0;
     int i;
     BOOL hasChanged = FALSE;
@@ -2548,11 +2547,6 @@ static BOOL generate_associations(const char *xdg_data_home, const char *package
         WINE_ERR("wine_rb_init failed\n");
         return FALSE;
     }
-    if (!build_native_mime_types(xdg_data_home, &nativeMimeTypes))
-    {
-        WINE_ERR("could not build native MIME types\n");
-        return FALSE;
-    }
 
     for (i = 0; ; i++)
     {
@@ -2615,7 +2609,7 @@ static BOOL generate_associations(const char *xdg_data_home, const char *package
             if (contentTypeW)
                 strlwrW(contentTypeW);
 
-            if (!freedesktop_mime_type_for_extension(nativeMimeTypes, extensionA, extensionW, &mimeTypeA))
+            if (!wmb_dispatch->mime_type_for_extension(user, extensionA, extensionW, &mimeTypeA))
                 goto end;
 
             if (mimeTypeA == NULL)
@@ -2649,7 +2643,7 @@ static BOOL generate_associations(const char *xdg_data_home, const char *package
                         }
                     }
 
-                    write_freedesktop_mime_type_entry(packages_dir, extensionA, mimeTypeA, friendlyDocNameA);
+                    wmb_dispatch->write_mime_type_entry(user, extensionA, mimeTypeA, friendlyDocNameA);
                     hasChanged = TRUE;
                 }
                 else
@@ -2727,15 +2721,10 @@ static BOOL generate_associations(const char *xdg_data_home, const char *package
 
             if (has_association_changed(extensionW, mimeTypeA, progIdW, friendlyAppNameA, openWithIconA))
             {
-                char *desktopPath = heap_printf("%s/wine-extension-%s.desktop", applications_dir, &extensionA[1]);
-                if (desktopPath)
+                if (wmb_dispatch->write_association_entry(user, extensionA, friendlyAppNameA, friendlyDocNameA, mimeTypeA, progIdA, openWithIconA))
                 {
-                    if (write_freedesktop_association_entry(desktopPath, extensionA, friendlyAppNameA, mimeTypeA, progIdA, openWithIconA))
-                    {
-                        hasChanged = TRUE;
-                        update_association(extensionW, mimeTypeA, progIdW, friendlyAppNameA, openWithIconA);
-                    }
-                    HeapFree(GetProcessHeap(), 0, desktopPath);
+                    hasChanged = TRUE;
+                    update_association(extensionW, mimeTypeA, progIdW, friendlyAppNameA, openWithIconA);
                 }
             }
 
@@ -2761,7 +2750,6 @@ static BOOL generate_associations(const char *xdg_data_home, const char *package
     }
 
     wine_rb_destroy(&mimeProgidTree, winemenubuilder_rb_destroy, NULL);
-    free_native_mime_types(nativeMimeTypes);
     return hasChanged;
 }
 
@@ -2806,6 +2794,7 @@ static BOOL InvokeShellLinker( IShellLinkW *sl, LPCWSTR link, BOOL bWait )
     HANDLE hsem = NULL;
     char *unix_link = NULL;
     char *start_path = NULL;
+    const char *lastEntry;
 
     if ( !link )
     {
@@ -2945,33 +2934,27 @@ static BOOL InvokeShellLinker( IShellLinkW *sl, LPCWSTR link, BOOL bWait )
         goto cleanup;
     }
 
+    lastEntry = strrchr(link_name, '/');
+    if (lastEntry == NULL)
+        lastEntry = link_name;
+    else
+        ++lastEntry;
+
     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)
         {
-            if (csidl == CSIDL_COMMON_DESKTOPDIRECTORY)
+            char *link_arg = escape_unix_link_arg(unix_link);
+            if (link_arg)
             {
-                char *link_arg = escape_unix_link_arg(unix_link);
-                if (link_arg)
-                {
-                    r = !write_desktop_entry(unix_link, location, lastEntry,
+                r = wmb_dispatch->build_desktop_link(unix_link, link_name, lastEntry,
                         start_path, link_arg, description, work_dir, icon_name);
-                    HeapFree(GetProcessHeap(), 0, link_arg);
-                }
+                HeapFree(GetProcessHeap(), 0, link_arg);
             }
-            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
+        {
+            r = wmb_dispatch->build_desktop_link(NULL, link_name, lastEntry, escaped_path, escaped_args, description, work_dir, icon_name);
         }
     }
     else
@@ -2979,7 +2962,7 @@ static BOOL InvokeShellLinker( IShellLinkW *sl, LPCWSTR link, BOOL bWait )
         char *link_arg = escape_unix_link_arg(unix_link);
         if (link_arg)
         {
-            r = !write_menu_entry(unix_link, link_name, start_path, link_arg, description, work_dir, icon_name);
+            r = wmb_dispatch->build_menu_link(unix_link, link_name, lastEntry, start_path, link_arg, description, work_dir, icon_name);
             HeapFree(GetProcessHeap(), 0, link_arg);
         }
     }
@@ -3020,6 +3003,7 @@ static BOOL InvokeShellLinkerForURL( IUniformResourceLocatorW *url, LPCWSTR link
     PROPVARIANT pv[2];
     char *start_path = NULL;
     BOOL has_icon = FALSE;
+    char *lastEntry;
 
     if ( !link )
     {
@@ -3117,26 +3101,15 @@ static BOOL InvokeShellLinkerForURL( IUniformResourceLocatorW *url, LPCWSTR link
         WINE_ERR("failed wait for semaphore\n");
         goto cleanup;
     }
+    lastEntry = strrchr(link_name, '/');
+    if (lastEntry == NULL)
+        lastEntry = link_name;
+    else
+        ++lastEntry;
     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)
-        {
-            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);
-        }
-    }
+        r = wmb_dispatch->build_desktop_link(NULL, link_name, lastEntry, start_path, escaped_urlPath, NULL, NULL, icon_name);
     else
-        r = !write_menu_entry(unix_link, link_name, start_path, escaped_urlPath, NULL, NULL, icon_name);
+        r = wmb_dispatch->build_menu_link(unix_link, link_name, lastEntry, start_path, escaped_urlPath, NULL, NULL, icon_name);
     ret = (r == 0);
     ReleaseSemaphore(hSem, 1, NULL);
 
@@ -3318,10 +3291,8 @@ static BOOL Process_URL( LPCWSTR urlname, BOOL bWait )
 static void RefreshFileTypeAssociations(void)
 {
     HANDLE hSem = NULL;
-    char *mime_dir = NULL;
-    char *packages_dir = NULL;
-    char *applications_dir = NULL;
     BOOL hasChanged;
+    void *user;
 
     hSem = CreateSemaphoreA( NULL, 1, 1, "winemenubuilder_semaphore");
     if( WAIT_OBJECT_0 != MsgWaitForMultipleObjects( 1, &hSem, FALSE, INFINITE, QS_ALLINPUT ) )
@@ -3332,45 +3303,15 @@ static void RefreshFileTypeAssociations(void)
         goto end;
     }
 
-    mime_dir = heap_printf("%s/mime", xdg_data_dir);
-    if (mime_dir == NULL)
-    {
-        WINE_ERR("out of memory\n");
-        goto end;
-    }
-    create_directories(mime_dir);
-
-    packages_dir = heap_printf("%s/packages", mime_dir);
-    if (packages_dir == NULL)
-    {
-        WINE_ERR("out of memory\n");
-        goto end;
-    }
-    create_directories(packages_dir);
+    user = wmb_dispatch->refresh_file_type_associations_init();
 
-    applications_dir = heap_printf("%s/applications", xdg_data_dir);
-    if (applications_dir == NULL)
-    {
-        WINE_ERR("out of memory\n");
+    if (!user)
         goto end;
-    }
-    create_directories(applications_dir);
-
-    hasChanged = generate_associations(xdg_data_dir, packages_dir, applications_dir);
-    hasChanged |= cleanup_associations(applications_dir);
-    if (hasChanged)
-    {
-        const char *argv[3];
 
-        argv[0] = "update-mime-database";
-        argv[1] = mime_dir;
-        argv[2] = NULL;
-        spawnvp( _P_DETACH, argv[0], argv );
+    hasChanged = generate_associations(user);
+    hasChanged |= cleanup_associations(user);
 
-        argv[0] = "update-desktop-database";
-        argv[1] = applications_dir;
-        spawnvp( _P_DETACH, argv[0], argv );
-    }
+    wmb_dispatch->refresh_file_type_associations_cleanup(user, hasChanged);
 
 end:
     if (hSem)
@@ -3378,9 +3319,6 @@ end:
         ReleaseSemaphore(hSem, 1, NULL);
         CloseHandle(hSem);
     }
-    HeapFree(GetProcessHeap(), 0, mime_dir);
-    HeapFree(GetProcessHeap(), 0, packages_dir);
-    HeapFree(GetProcessHeap(), 0, applications_dir);
 }
 
 static void cleanup_menus(void)
@@ -3627,6 +3565,173 @@ static BOOL init_xdg(void)
     return FALSE;
 }
 
+static int xdg_build_desktop_link(const char *unix_link, const char *link, const char *link_name, const char *path,
+                                const char *args, const char *descr, const char *workdir, char *icon)
+{
+    char *location;
+    int r = -1;
+
+    location = heap_printf("%s/%s.desktop", xdg_desktop_dir, link_name);
+    if (location)
+    {
+        r = !write_desktop_entry(unix_link, location, link_name,
+                path, args, descr, workdir, icon);
+        if (r == 0)
+            chmod(location, 0755);
+    }
+    return r;
+}
+
+static int xdg_build_menu_link(const char *unix_link, const char *link, const char *link_name, const char *path,
+                             const char *args, const char *descr, const char *workdir, char *icon)
+{
+    return !write_menu_entry(unix_link, link, path, args, descr, workdir, icon);
+}
+
+static void *xdg_refresh_file_type_associations_init(void)
+{
+    struct xdg_file_type_user_data *ud = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ud));
+
+    if (ud == NULL)
+    {
+        WINE_ERR("out of memory\n");
+        return NULL;
+    }
+
+    ud->mime_dir = heap_printf("%s/mime", xdg_data_dir);
+    if (ud->mime_dir == NULL)
+    {
+        WINE_ERR("out of memory\n");
+        return NULL;
+    }
+    create_directories(ud->mime_dir);
+
+    ud->packages_dir = heap_printf("%s/packages", ud->mime_dir);
+    if (ud->packages_dir == NULL)
+    {
+        WINE_ERR("out of memory\n");
+        return NULL;
+    }
+    create_directories(ud->packages_dir);
+
+    ud->applications_dir = heap_printf("%s/applications", xdg_data_dir);
+    if (ud->applications_dir == NULL)
+    {
+        WINE_ERR("out of memory\n");
+        return NULL;
+    }
+    create_directories(ud->applications_dir);
+
+    if (!build_native_mime_types(xdg_data_dir, &ud->native_mime_types))
+        return NULL;
+
+    return ud;
+}
+
+static BOOL xdg_remove_file_type_association(void *user, const char *dot_extension, LPCWSTR extensionW)
+{
+    struct xdg_file_type_user_data *ud = user;
+    char *desktopPath = heap_printf("%s/wine-extension-%s.desktop", ud->applications_dir, &dot_extension[1]);
+
+    if (desktopPath)
+    {
+        WINE_TRACE("removing file type association for %s\n", wine_dbgstr_w(extensionW));
+        remove(desktopPath);
+        HeapFree(GetProcessHeap(), 0, desktopPath);
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
+static void xdg_refresh_file_type_associations_cleanup(void *user, BOOL hasChanged)
+{
+    struct xdg_file_type_user_data *ud = user;
+
+    if (hasChanged)
+    {
+        const char *argv[3];
+
+        argv[0] = "update-mime-database";
+        argv[1] = ud->mime_dir;
+        argv[2] = NULL;
+        spawnvp( _P_DETACH, argv[0], argv );
+
+        argv[0] = "update-desktop-database";
+        argv[1] = ud->applications_dir;
+        spawnvp( _P_DETACH, argv[0], argv );
+    }
+
+    HeapFree(GetProcessHeap(), 0, ud->mime_dir);
+    HeapFree(GetProcessHeap(), 0, ud->packages_dir);
+    HeapFree(GetProcessHeap(), 0, ud->applications_dir);
+    HeapFree(GetProcessHeap(), 0, ud);
+}
+
+const struct winemenubuilder_dispatch xdg_dispatch =
+{
+    init_xdg,
+
+    xdg_build_desktop_link,
+    xdg_build_menu_link,
+
+#ifdef __APPLE__
+    osx_write_icon,
+#else
+    xdg_write_icon,
+#endif
+
+    xdg_refresh_file_type_associations_init,
+    freedesktop_mime_type_for_extension,
+    write_freedesktop_mime_type_entry,
+    write_freedesktop_association_entry,
+    xdg_remove_file_type_association,
+    xdg_refresh_file_type_associations_cleanup
+};
+
+static BOOL dispatch_init(void)
+{
+    const char *dispatch = NULL;
+    unsigned char buffer[256];
+    HKEY hkey;
+
+    if (RegOpenKeyExA(HKEY_CURRENT_USER, "Software\\Wine\\MenuBuilder", 0, KEY_READ, &hkey) == ERROR_SUCCESS)
+    {
+        DWORD type, count = sizeof(buffer);
+
+        buffer[0] = 0;
+
+        RegQueryValueExA(hkey, "Dispatch", 0, &type, buffer, &count);
+        if (buffer[0] && type == REG_SZ)
+        {
+            dispatch = (char*)buffer;
+            WINE_TRACE("Dispatch set to %s from registry\n", dispatch);
+        }
+        else
+            WINE_TRACE("No Dispatch key in registry or type != string\n");
+    }
+    else
+        WINE_TRACE("No MenuBuilder key in registry\n");
+
+    if (dispatch)
+    {
+        if (strcmp(dispatch, "none") == 0)
+            return FALSE;
+
+        if (strcmp(dispatch, "xdg") == 0)
+        {
+            wmb_dispatch = &xdg_dispatch;
+            return TRUE;
+        }
+
+        WINE_WARN("Unknown Wine MenuBuilder Dispatch \"%s\"\n", dispatch);
+    }
+
+    wmb_dispatch = &xdg_dispatch;
+    WINE_TRACE("Dispatch set to xdg by default\n");
+    return TRUE;
+}
+
 /***********************************************************************
  *
  *           wWinMain
@@ -3645,7 +3750,10 @@ int PASCAL wWinMain (HINSTANCE hInstance, HINSTANCE prev, LPWSTR cmdline, int sh
     HRESULT hr;
     int ret = 0;
 
-    if (!init_xdg())
+    if (!dispatch_init())
+        return 0;
+
+    if (!wmb_dispatch->init())
         return 1;
 
     hr = CoInitialize(NULL);
diff --git a/programs/winemenubuilder/winemenubuilder.h b/programs/winemenubuilder/winemenubuilder.h
new file mode 100644
index 0000000..0bd3425
--- /dev/null
+++ b/programs/winemenubuilder/winemenubuilder.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2011 - 2013 Per Johansson
+ *
+ * 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
+ */
+
+typedef struct
+{
+    BYTE bWidth;
+    BYTE bHeight;
+    BYTE bColorCount;
+    BYTE bReserved;
+    WORD wPlanes;
+    WORD wBitCount;
+    DWORD dwBytesInRes;
+    DWORD dwImageOffset;
+} ICONDIRENTRY;
+
+typedef struct
+{
+    WORD idReserved;
+    WORD idType;
+    WORD idCount;
+} ICONDIR;
+
+struct winemenubuilder_dispatch
+{
+    BOOL (*init)(void);
+
+    int (*build_desktop_link)(const char *unix_link, const char *link, const char *link_name, const char *path,
+            const char *args, const char *descr, const char *workdir, char *icon);
+    int (*build_menu_link)(const char *unix_link, const char *link, const char *link_name, const char *path,
+            const char *args, const char *descr, const char *workdir, char *icon);
+
+    HRESULT (*write_icon)(IStream *icoStream, int exeIndex, LPCWSTR icoPathW,
+            const char *destFilename, char **nativeIdentifier);
+
+
+    void *(*refresh_file_type_associations_init)(void);
+    BOOL (*mime_type_for_extension)(void *user, const char *extensionA, LPCWSTR extensionW, char **mime_type);
+    BOOL (*write_mime_type_entry)(void *user, const char *extensionA, const char *mimeTypeA, const char *friendlyDocNameA);
+    BOOL (*write_association_entry)(void *user, const char *extensionA, const char *friendlyAppNameA,
+            const char *friendlyDocNameA, const char *mimeTypeA, const char *progIdA,
+            const char *appIconA);
+    BOOL (*remove_file_type_association)(void *user, const char *extensionA, LPCWSTR extensionW);
+    void (*refresh_file_type_associations_cleanup)(void *user, BOOL hasChanged);
+};
-- 
1.8.0.2




More information about the wine-patches mailing list