Damjan Jovanovic : winemenubuilder: Track, update and clean up file open associations.
Alexandre Julliard
julliard at winehq.org
Fri Jun 5 08:56:56 CDT 2009
Module: wine
Branch: master
Commit: 4af750a57824f2c4b93c509883120e61d7adb5e7
URL: http://source.winehq.org/git/wine.git/?a=commit;h=4af750a57824f2c4b93c509883120e61d7adb5e7
Author: Damjan Jovanovic <damjan.jov at gmail.com>
Date: Thu Jun 4 21:57:45 2009 +0200
winemenubuilder: Track, update and clean up file open associations.
---
programs/winemenubuilder/winemenubuilder.c | 170 ++++++++++++++++++++++++++++
1 files changed, 170 insertions(+), 0 deletions(-)
diff --git a/programs/winemenubuilder/winemenubuilder.c b/programs/winemenubuilder/winemenubuilder.c
index bd9c30d..eeded0e 100644
--- a/programs/winemenubuilder/winemenubuilder.c
+++ b/programs/winemenubuilder/winemenubuilder.c
@@ -1514,6 +1514,21 @@ static BOOL freedesktop_mime_type_for_extension(struct list *native_mime_types,
return ret;
}
+static CHAR* reg_get_valA(HKEY key, LPCSTR subkey, LPCSTR name)
+{
+ DWORD size;
+ if (RegGetValueA(key, subkey, name, RRF_RT_REG_SZ, NULL, NULL, &size) == ERROR_SUCCESS)
+ {
+ CHAR *ret = HeapAlloc(GetProcessHeap(), 0, size);
+ if (ret)
+ {
+ if (RegGetValueA(key, subkey, name, RRF_RT_REG_SZ, NULL, ret, &size) == ERROR_SUCCESS)
+ return ret;
+ }
+ }
+ return NULL;
+}
+
static WCHAR* reg_get_valW(HKEY key, LPCWSTR subkey, LPCWSTR name)
{
DWORD size;
@@ -1529,6 +1544,158 @@ static WCHAR* reg_get_valW(HKEY key, LPCWSTR subkey, LPCWSTR name)
return NULL;
}
+static HKEY open_associations_reg_key(void)
+{
+ static const WCHAR Software_Wine_FileOpenAssociationsW[] = {
+ 'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\','F','i','l','e','O','p','e','n','A','s','s','o','c','i','a','t','i','o','n','s',0};
+ HKEY assocKey;
+ if (RegCreateKeyW(HKEY_CURRENT_USER, Software_Wine_FileOpenAssociationsW, &assocKey) == ERROR_SUCCESS)
+ return assocKey;
+ return NULL;
+}
+
+static BOOL has_association_changed(LPCSTR extensionA, LPCWSTR extensionW, LPCSTR mimeType, LPCWSTR progId, LPCSTR appName, LPCWSTR docName)
+{
+ static const WCHAR ProgIDW[] = {'P','r','o','g','I','D',0};
+ static const WCHAR DocNameW[] = {'D','o','c','N','a','m','e',0};
+ HKEY assocKey;
+ BOOL ret;
+
+ if ((assocKey = open_associations_reg_key()))
+ {
+ CHAR *valueA;
+ WCHAR *value;
+
+ ret = FALSE;
+
+ valueA = reg_get_valA(assocKey, extensionA, "MimeType");
+ if (!valueA || lstrcmpA(valueA, mimeType))
+ ret = TRUE;
+ HeapFree(GetProcessHeap(), 0, valueA);
+
+ value = reg_get_valW(assocKey, extensionW, ProgIDW);
+ if (!value || strcmpW(value, progId))
+ ret = TRUE;
+ HeapFree(GetProcessHeap(), 0, value);
+
+ valueA = reg_get_valA(assocKey, extensionA, "AppName");
+ if (!valueA || lstrcmpA(valueA, appName))
+ ret = TRUE;
+ HeapFree(GetProcessHeap(), 0, valueA);
+
+ value = reg_get_valW(assocKey, extensionW, DocNameW);
+ if (docName && (!value || strcmpW(value, docName)))
+ ret = TRUE;
+ HeapFree(GetProcessHeap(), 0, value);
+
+ RegCloseKey(assocKey);
+ }
+ else
+ {
+ WINE_ERR("error opening associations registry key\n");
+ ret = FALSE;
+ }
+ return ret;
+}
+
+static void update_association(LPCWSTR extension, LPCSTR mimeType, LPCWSTR progId, LPCSTR appName, LPCWSTR docName, LPCSTR desktopFile)
+{
+ static const WCHAR ProgIDW[] = {'P','r','o','g','I','D',0};
+ static const WCHAR DocNameW[] = {'D','o','c','N','a','m','e',0};
+ HKEY assocKey;
+
+ if ((assocKey = open_associations_reg_key()))
+ {
+ HKEY subkey;
+ if (RegCreateKeyW(assocKey, extension, &subkey) == ERROR_SUCCESS)
+ {
+ RegSetValueExA(subkey, "MimeType", 0, REG_SZ, (BYTE*) mimeType, lstrlenA(mimeType) + 1);
+ RegSetValueExW(subkey, ProgIDW, 0, REG_SZ, (BYTE*) progId, (lstrlenW(progId) + 1) * sizeof(WCHAR));
+ RegSetValueExA(subkey, "AppName", 0, REG_SZ, (BYTE*) appName, lstrlenA(appName) + 1);
+ if (docName)
+ RegSetValueExW(subkey, DocNameW, 0, REG_SZ, (BYTE*) docName, (lstrlenW(docName) + 1) * sizeof(WCHAR));
+ RegSetValueExA(subkey, "DesktopFile", 0, REG_SZ, (BYTE*) desktopFile, (lstrlenA(desktopFile) + 1));
+ RegCloseKey(subkey);
+ }
+ else
+ WINE_ERR("could not create extension subkey\n");
+ RegCloseKey(assocKey);
+ }
+ else
+ WINE_ERR("could not open file associations key\n");
+}
+
+static BOOL cleanup_associations(void)
+{
+ HKEY assocKey;
+ BOOL hasChanged = FALSE;
+ if ((assocKey = open_associations_reg_key()))
+ {
+ int i;
+ BOOL done = FALSE;
+ for (i = 0; !done; i++)
+ {
+ WCHAR *extensionW = NULL;
+ char *extensionA = NULL;
+ DWORD size = 1024;
+ LSTATUS ret;
+
+ do
+ {
+ HeapFree(GetProcessHeap(), 0, extensionW);
+ extensionW = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
+ if (extensionW == NULL)
+ {
+ WINE_ERR("out of memory\n");
+ ret = ERROR_OUTOFMEMORY;
+ break;
+ }
+ ret = RegEnumKeyExW(assocKey, i, extensionW, &size, NULL, NULL, NULL, NULL);
+ size *= 2;
+ } while (ret == ERROR_MORE_DATA);
+
+ if (ret == ERROR_SUCCESS)
+ {
+ WCHAR *command;
+ extensionA = wchars_to_utf8_chars(extensionW);
+ if (extensionA == NULL)
+ {
+ WINE_ERR("out of memory\n");
+ done = TRUE;
+ goto end;
+ }
+ command = assoc_query(ASSOCSTR_COMMAND, extensionW, NULL);
+ if (command == NULL)
+ {
+ char *desktopFile = reg_get_valA(assocKey, extensionA, "DesktopFile");
+ if (desktopFile)
+ {
+ WINE_TRACE("removing file type association for %s\n", wine_dbgstr_a(extensionA));
+ remove(desktopFile);
+ }
+ RegDeleteKeyW(assocKey, extensionW);
+ hasChanged = TRUE;
+ HeapFree(GetProcessHeap(), 0, desktopFile);
+ }
+ HeapFree(GetProcessHeap(), 0, command);
+ }
+ else
+ {
+ if (ret != ERROR_NO_MORE_ITEMS)
+ WINE_ERR("error %d while reading registry\n", ret);
+ done = TRUE;
+ }
+ end:
+ HeapFree(GetProcessHeap(), 0, extensionA);
+ HeapFree(GetProcessHeap(), 0, extensionW);
+ }
+ RegCloseKey(assocKey);
+ }
+ else
+ WINE_ERR("could not open file associations key\n");
+ return hasChanged;
+}
+
static BOOL write_freedesktop_mime_type_entry(const char *packages_dir, const char *dot_extension,
const char *mime_type, const char *comment)
{
@@ -1732,6 +1899,7 @@ static BOOL generate_associations(const char *xdg_data_home, const char *package
else
goto end; /* no progID => not a file type association */
+ if (has_association_changed(extensionA, extensionW, mimeTypeA, progIdW, friendlyAppNameA, friendlyDocNameW))
{
char *desktopPath = heap_printf("%s/wine-extension-%s.desktop", applications_dir, &extensionA[1]);
if (desktopPath)
@@ -1739,6 +1907,7 @@ static BOOL generate_associations(const char *xdg_data_home, const char *package
if (write_freedesktop_association_entry(desktopPath, extensionA, friendlyAppNameA, mimeTypeA, progIdA))
{
hasChanged = TRUE;
+ update_association(extensionW, mimeTypeA, progIdW, friendlyAppNameA, friendlyDocNameW, desktopPath);
}
HeapFree(GetProcessHeap(), 0, desktopPath);
}
@@ -2232,6 +2401,7 @@ static void RefreshFileTypeAssociations(void)
create_directories(applications_dir);
hasChanged = generate_associations(xdg_data_dir, packages_dir, applications_dir);
+ hasChanged |= cleanup_associations();
if (hasChanged)
{
char *command = heap_printf("update-mime-database %s", mime_dir);
More information about the wine-cvs
mailing list