Signed-off-by: Alex Henrie alexhenrie24@gmail.com --- programs/winemenubuilder/winemenubuilder.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-)
diff --git a/programs/winemenubuilder/winemenubuilder.c b/programs/winemenubuilder/winemenubuilder.c index e02d7bd787f..51d83aed971 100644 --- a/programs/winemenubuilder/winemenubuilder.c +++ b/programs/winemenubuilder/winemenubuilder.c @@ -1874,29 +1874,26 @@ static BOOL build_native_mime_types(struct list *mime_types) return ret; }
-static BOOL freedesktop_mime_type_for_extension(struct list *native_mime_types, - LPCWSTR extensionW, - WCHAR **match) +static WCHAR *freedesktop_mime_type_for_extension(struct list *native_mime_types, + const WCHAR *extensionW) { struct xdg_mime_type *mime_type_entry; int matchLength = 0; - - *match = NULL; + const WCHAR* match = NULL;
LIST_FOR_EACH_ENTRY(mime_type_entry, native_mime_types, struct xdg_mime_type, entry) { if (PathMatchSpecW( extensionW, mime_type_entry->glob )) { - if (*match == NULL || matchLength < lstrlenW(mime_type_entry->glob)) + if (match == NULL || matchLength < lstrlenW(mime_type_entry->glob)) { - *match = mime_type_entry->mimeType; + match = mime_type_entry->mimeType; matchLength = lstrlenW(mime_type_entry->glob); } } }
- if (*match != NULL) *match = xwcsdup(*match); - return TRUE; + return match ? xwcsdup(match) : NULL; }
static WCHAR* reg_get_valW(HKEY key, LPCWSTR subkey, LPCWSTR name) @@ -2190,8 +2187,7 @@ static BOOL generate_associations(const WCHAR *packages_dir, const WCHAR *applic if (contentTypeW) wcslwr(contentTypeW);
- if (!freedesktop_mime_type_for_extension(&nativeMimeTypes, extensionW, &mimeType)) - goto end; + mimeType = freedesktop_mime_type_for_extension(&nativeMimeTypes, extensionW);
if (mimeType == NULL) {
When Freedesktop recognizes the content type, the value from the registry is ignored.
Signed-off-by: Alex Henrie alexhenrie24@gmail.com --- programs/winemenubuilder/winemenubuilder.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/programs/winemenubuilder/winemenubuilder.c b/programs/winemenubuilder/winemenubuilder.c index 51d83aed971..278480d3a9c 100644 --- a/programs/winemenubuilder/winemenubuilder.c +++ b/programs/winemenubuilder/winemenubuilder.c @@ -2183,16 +2183,13 @@ static BOOL generate_associations(const WCHAR *packages_dir, const WCHAR *applic
iconW = assoc_query(ASSOCSTR_DEFAULTICON, extensionW, NULL);
- contentTypeW = assoc_query(ASSOCSTR_CONTENTTYPE, extensionW, NULL); - if (contentTypeW) - wcslwr(contentTypeW); - mimeType = freedesktop_mime_type_for_extension(&nativeMimeTypes, extensionW);
if (mimeType == NULL) { + contentTypeW = assoc_query(ASSOCSTR_CONTENTTYPE, extensionW, NULL); if (contentTypeW != NULL && wcschr(contentTypeW, '/')) - mimeType = xwcsdup(contentTypeW); + mimeType = xwcsdup(wcslwr(contentTypeW)); else if (!(mimeType = get_special_mime_type(extensionW))) mimeType = heap_wprintf(L"application/x-wine-extension-%s", &extensionW[1]);
Alex Henrie alexhenrie24@gmail.com writes:
When Freedesktop recognizes the content type, the value from the registry is ignored.
That's true for the other values also.
Signed-off-by: Alex Henrie alexhenrie24@gmail.com --- I recommend using `git show -w` to visualize this patch. --- programs/winemenubuilder/winemenubuilder.c | 538 +++++++++++---------- 1 file changed, 270 insertions(+), 268 deletions(-)
diff --git a/programs/winemenubuilder/winemenubuilder.c b/programs/winemenubuilder/winemenubuilder.c index 278480d3a9c..f10026a418e 100644 --- a/programs/winemenubuilder/winemenubuilder.c +++ b/programs/winemenubuilder/winemenubuilder.c @@ -577,30 +577,32 @@ static int populate_module_icons(HMODULE hModule, GRPICONDIR *grpIconDir, ICONDI { HRSRC hResInfo; LPCWSTR lpName = MAKEINTRESOURCEW(grpIconDir->idEntries[i].nID); - if ((hResInfo = FindResourceW(hModule, lpName, (LPCWSTR)RT_ICON))) + HGLOBAL hResData; + BITMAPINFO *pIcon; + DWORD size; + + if (!(hResInfo = FindResourceW(hModule, lpName, (const WCHAR *)RT_ICON))) + continue; + + if (!(hResData = LoadResource(hModule, hResInfo))) + continue; + + size = min(grpIconDir->idEntries[i].dwBytesInRes, ((IMAGE_RESOURCE_DATA_ENTRY *)hResInfo)->Size); + if ((pIcon = LockResource(hResData))) { - HGLOBAL hResData; - if ((hResData = LoadResource(hModule, hResInfo))) - { - BITMAPINFO *pIcon; - DWORD size = min( grpIconDir->idEntries[i].dwBytesInRes, ((IMAGE_RESOURCE_DATA_ENTRY *)hResInfo)->Size ); - if ((pIcon = LockResource(hResData))) - { - iconDirEntries[validEntries].bWidth = grpIconDir->idEntries[i].bWidth; - iconDirEntries[validEntries].bHeight = grpIconDir->idEntries[i].bHeight; - iconDirEntries[validEntries].bColorCount = grpIconDir->idEntries[i].bColorCount; - iconDirEntries[validEntries].bReserved = grpIconDir->idEntries[i].bReserved; - iconDirEntries[validEntries].wPlanes = grpIconDir->idEntries[i].wPlanes; - iconDirEntries[validEntries].wBitCount = grpIconDir->idEntries[i].wBitCount; - iconDirEntries[validEntries].dwBytesInRes = size; - iconDirEntries[validEntries].dwImageOffset = *iconOffset; - validEntries++; - memcpy(&icons[*iconOffset], pIcon, size); - *iconOffset += size; - } - FreeResource(hResData); - } + iconDirEntries[validEntries].bWidth = grpIconDir->idEntries[i].bWidth; + iconDirEntries[validEntries].bHeight = grpIconDir->idEntries[i].bHeight; + iconDirEntries[validEntries].bColorCount = grpIconDir->idEntries[i].bColorCount; + iconDirEntries[validEntries].bReserved = grpIconDir->idEntries[i].bReserved; + iconDirEntries[validEntries].wPlanes = grpIconDir->idEntries[i].wPlanes; + iconDirEntries[validEntries].wBitCount = grpIconDir->idEntries[i].wBitCount; + iconDirEntries[validEntries].dwBytesInRes = size; + iconDirEntries[validEntries].dwImageOffset = *iconOffset; + validEntries++; + memcpy(&icons[*iconOffset], pIcon, size); + *iconOffset += size; } + FreeResource(hResData); } return validEntries; } @@ -864,27 +866,25 @@ static HRESULT open_module_icon(LPCWSTR szFileName, int nIndex, IStream **ppStre } }
- if (hResInfo) - { - if ((hResData = LoadResource(hModule, hResInfo))) - { - if ((pIconDir = LockResource(hResData))) - { - *ppStream = add_module_icons_to_stream(0, hModule, pIconDir); - if (*ppStream) - hr = S_OK; - } - - FreeResource(hResData); - } - } - else + if (!hResInfo) { WINE_WARN("found no icon\n"); FreeLibrary(hModule); return HRESULT_FROM_WIN32(ERROR_NOT_FOUND); }
+ if ((hResData = LoadResource(hModule, hResInfo))) + { + if ((pIconDir = LockResource(hResData))) + { + *ppStream = add_module_icons_to_stream(0, hModule, pIconDir); + if (*ppStream) + hr = S_OK; + } + + FreeResource(hResData); + } + FreeLibrary(hModule); return hr; } @@ -1648,6 +1648,11 @@ static HRESULT get_cmdline( IShellLinkW *sl, LPWSTR szPath, DWORD pathSize, IShellLinkDataList *dl = NULL; EXP_DARWIN_LINK *dar = NULL; HRESULT hr; + WCHAR* szCmdline = NULL; + DWORD cmdSize; + WCHAR *s, *d; + int bcount = 0; + BOOL in_quotes = FALSE;
szPath[0] = 0; szArgs[0] = 0; @@ -1664,92 +1669,86 @@ static HRESULT get_cmdline( IShellLinkW *sl, LPWSTR szPath, DWORD pathSize, return hr;
hr = IShellLinkDataList_CopyDataBlock( dl, EXP_DARWIN_ID_SIG, (LPVOID*) &dar ); - if (SUCCEEDED(hr)) - { - WCHAR* szCmdline; - DWORD cmdSize; + if (FAILED(hr)) + goto end;
- cmdSize=0; - hr = CommandLineFromMsiDescriptor( dar->szwDarwinID, NULL, &cmdSize ); - if (hr == ERROR_SUCCESS) + cmdSize=0; + hr = CommandLineFromMsiDescriptor( dar->szwDarwinID, NULL, &cmdSize ); + if (FAILED(hr)) + goto end; + + cmdSize++; + szCmdline = xmalloc( cmdSize*sizeof(WCHAR) ); + hr = CommandLineFromMsiDescriptor( dar->szwDarwinID, szCmdline, &cmdSize ); + WINE_TRACE(" command : %s\n", wine_dbgstr_w(szCmdline)); + if (FAILED(hr)) + goto end; + + /* Extract the application path */ + s=szCmdline; + d=szPath; + while (*s) + { + if ((*s==0x0009 || *s==0x0020) && !in_quotes) { - cmdSize++; - szCmdline = xmalloc(cmdSize*sizeof(WCHAR) ); - hr = CommandLineFromMsiDescriptor( dar->szwDarwinID, szCmdline, &cmdSize ); - WINE_TRACE(" command : %s\n", wine_dbgstr_w(szCmdline)); - if (hr == ERROR_SUCCESS) + /* skip the remaining spaces */ + do { + s++; + } while (*s==0x0009 || *s==0x0020); + break; + } + else if (*s==0x005c) + { + /* '\' */ + *d++=*s++; + bcount++; + } + else if (*s==0x0022) + { + /* '"' */ + if ((bcount & 1)==0) { - WCHAR *s, *d; - int bcount = 0; - BOOL in_quotes = FALSE; - - /* Extract the application path */ - s=szCmdline; - d=szPath; - while (*s) - { - if ((*s==0x0009 || *s==0x0020) && !in_quotes) - { - /* skip the remaining spaces */ - do { - s++; - } while (*s==0x0009 || *s==0x0020); - break; - } - else if (*s==0x005c) - { - /* '\' */ - *d++=*s++; - bcount++; - } - else if (*s==0x0022) - { - /* '"' */ - if ((bcount & 1)==0) - { - /* Preceded by an even number of '', this is - * half that number of '', plus a quote which - * we erase. - */ - d-=bcount/2; - in_quotes=!in_quotes; - s++; - } - else - { - /* Preceded by an odd number of '', this is - * half that number of '' followed by a '"' - */ - d=d-bcount/2-1; - *d++='"'; - s++; - } - bcount=0; - } - else - { - /* a regular character */ - *d++=*s++; - bcount=0; - } - if ((d-szPath) == pathSize) - { - /* Keep processing the path till we get to the - * arguments, but 'stand still' - */ - d--; - } - } - /* Close the application path */ - *d=0; - - lstrcpynW(szArgs, s, argsSize); + /* Preceded by an even number of '', this is + * half that number of '', plus a quote which + * we erase. + */ + d-=bcount/2; + in_quotes=!in_quotes; + s++; + } + else + { + /* Preceded by an odd number of '', this is + * half that number of '' followed by a '"' + */ + d=d-bcount/2-1; + *d++='"'; + s++; } - heap_free(szCmdline ); + bcount=0; + } + else + { + /* a regular character */ + *d++=*s++; + bcount=0; + } + if ((d-szPath) == pathSize) + { + /* Keep processing the path till we get to the + * arguments, but 'stand still' + */ + d--; } - LocalFree( dar ); } + /* Close the application path */ + *d=0;
+ lstrcpynW(szArgs, s, argsSize); + +end: + heap_free( szCmdline ); + LocalFree( dar ); IShellLinkDataList_Release( dl ); return hr; } @@ -1998,56 +1997,57 @@ static BOOL cleanup_associations(void) { HKEY assocKey; BOOL hasChanged = FALSE; - if ((assocKey = open_associations_reg_key())) + int i = 0; + + if (!(assocKey = open_associations_reg_key())) { - int i; - BOOL done = FALSE; - for (i = 0; !done;) + WINE_ERR("could not open file associations key\n"); + return FALSE; + } + + for (;;) + { + WCHAR *extensionW = NULL; + DWORD size = 1024; + LSTATUS ret; + WCHAR *command; + + do { - WCHAR *extensionW = NULL; - DWORD size = 1024; - LSTATUS ret; + heap_free(extensionW); + extensionW = xmalloc(size * sizeof(WCHAR)); + ret = RegEnumKeyExW(assocKey, i, extensionW, &size, NULL, NULL, NULL, NULL); + size *= 2; + } while (ret == ERROR_MORE_DATA);
- do - { - heap_free(extensionW); - extensionW = xmalloc(size * sizeof(WCHAR)); - ret = RegEnumKeyExW(assocKey, i, extensionW, &size, NULL, NULL, NULL, NULL); - size *= 2; - } while (ret == ERROR_MORE_DATA); + if (ret != ERROR_SUCCESS) + { + if (ret != ERROR_NO_MORE_ITEMS) + WINE_ERR("error %d while reading registry\n", ret); + heap_free(extensionW); + break; + }
- if (ret == ERROR_SUCCESS) - { - WCHAR *command; - command = assoc_query(ASSOCSTR_COMMAND, extensionW, L"open"); - if (command == NULL) - { - WCHAR *desktopFile = reg_get_valW(assocKey, extensionW, L"DesktopFile"); - if (desktopFile) - { - WINE_TRACE("removing file type association for %s\n", wine_dbgstr_w(extensionW)); - DeleteFileW(desktopFile); - } - RegDeleteKeyW(assocKey, extensionW); - hasChanged = TRUE; - heap_free(desktopFile); - } - else - i++; - heap_free(command); - } - else + command = assoc_query(ASSOCSTR_COMMAND, extensionW, L"open"); + if (command == NULL) + { + WCHAR *desktopFile = reg_get_valW(assocKey, extensionW, L"DesktopFile"); + if (desktopFile) { - if (ret != ERROR_NO_MORE_ITEMS) - WINE_ERR("error %d while reading registry\n", ret); - done = TRUE; + WINE_TRACE("removing file type association for %s\n", wine_dbgstr_w(extensionW)); + DeleteFileW(desktopFile); } - heap_free(extensionW); + RegDeleteKeyW(assocKey, extensionW); + hasChanged = TRUE; + heap_free(desktopFile); } - RegCloseKey(assocKey); + else + i++; + heap_free(command); + heap_free(extensionW); } - else - WINE_ERR("could not open file associations key\n"); + RegCloseKey(assocKey); + return hasChanged; }
@@ -2102,7 +2102,6 @@ static BOOL write_freedesktop_association_entry(const WCHAR *desktopPath, const const WCHAR *mimeType, const WCHAR *progId, const WCHAR *openWithIcon) { - BOOL ret = FALSE; FILE *desktop; const WCHAR *prefix = _wgetenv( L"WINECONFIGDIR" );
@@ -2111,30 +2110,30 @@ static BOOL write_freedesktop_association_entry(const WCHAR *desktopPath, const wine_dbgstr_w(progId), wine_dbgstr_w(openWithIcon), wine_dbgstr_w(desktopPath));
desktop = _wfopen( desktopPath, L"wb" ); - if (desktop) + if (!desktop) { - fprintf(desktop, "[Desktop Entry]\n"); - fprintf(desktop, "Type=Application\n"); - fprintf(desktop, "Name=%s\n", wchars_to_utf8_chars(friendlyAppName)); - fprintf(desktop, "MimeType=%s;\n", wchars_to_utf8_chars(mimeType)); - if (prefix) - { - char *path = wine_get_unix_file_name( prefix ); - fprintf(desktop, "Exec=env WINEPREFIX="%s" wine start /ProgIDOpen %s %%f\n", path, escape(progId)); - heap_free( path ); - } - else - fprintf(desktop, "Exec=wine start /ProgIDOpen %s %%f\n", escape(progId)); - fprintf(desktop, "NoDisplay=true\n"); - fprintf(desktop, "StartupNotify=true\n"); - if (openWithIcon) - fprintf(desktop, "Icon=%s\n", wchars_to_utf8_chars(openWithIcon)); - ret = TRUE; - fclose(desktop); + WINE_ERR("error writing association file %s\n", wine_dbgstr_w(desktopPath)); + return FALSE; + } + + fprintf(desktop, "[Desktop Entry]\n"); + fprintf(desktop, "Type=Application\n"); + fprintf(desktop, "Name=%s\n", wchars_to_utf8_chars(friendlyAppName)); + fprintf(desktop, "MimeType=%s;\n", wchars_to_utf8_chars(mimeType)); + if (prefix) + { + char *path = wine_get_unix_file_name( prefix ); + fprintf(desktop, "Exec=env WINEPREFIX="%s" wine start /ProgIDOpen %s %%f\n", path, escape(progId)); + heap_free( path ); } else - WINE_ERR("error writing association file %s\n", wine_dbgstr_w(desktopPath)); - return ret; + fprintf(desktop, "Exec=wine start /ProgIDOpen %s %%f\n", escape(progId)); + fprintf(desktop, "NoDisplay=true\n"); + fprintf(desktop, "StartupNotify=true\n"); + if (openWithIcon) + fprintf(desktop, "Icon=%s\n", wchars_to_utf8_chars(openWithIcon)); + fclose(desktop); + return TRUE; }
static BOOL generate_associations(const WCHAR *packages_dir, const WCHAR *applications_dir) @@ -2155,6 +2154,17 @@ static BOOL generate_associations(const WCHAR *packages_dir, const WCHAR *applic { WCHAR *extensionW = NULL; DWORD size = 1024; + WCHAR *commandW = NULL; + WCHAR *executableW = NULL; + WCHAR *openWithIcon = NULL; + WCHAR *friendlyDocNameW = NULL; + WCHAR *iconW = NULL; + WCHAR *contentTypeW = NULL; + WCHAR *mimeType = NULL; + const WCHAR *friendlyAppName; + WCHAR *progIdW = NULL; + WCHAR *mimeProgId = NULL; + struct rb_string_entry *entry;
do { @@ -2164,113 +2174,105 @@ static BOOL generate_associations(const WCHAR *packages_dir, const WCHAR *applic size *= 2; } while (ret == ERROR_MORE_DATA);
- if (ret == ERROR_SUCCESS && extensionW[0] == '.' && !is_extension_banned(extensionW)) + if (ret != ERROR_SUCCESS) { - WCHAR *commandW = NULL; - WCHAR *executableW = NULL; - WCHAR *openWithIcon = NULL; - WCHAR *friendlyDocNameW = NULL; - WCHAR *iconW = NULL; - WCHAR *contentTypeW = NULL; - WCHAR *mimeType = NULL; - const WCHAR *friendlyAppName; - WCHAR *progIdW = NULL; - WCHAR *mimeProgId = NULL; - struct rb_string_entry *entry; + heap_free(extensionW); + break; + } + + if (extensionW[0] != '.' || is_extension_banned(extensionW)) + goto end;
- wcslwr(extensionW); - friendlyDocNameW = assoc_query(ASSOCSTR_FRIENDLYDOCNAME, extensionW, NULL); + wcslwr(extensionW); + friendlyDocNameW = assoc_query(ASSOCSTR_FRIENDLYDOCNAME, extensionW, NULL);
- iconW = assoc_query(ASSOCSTR_DEFAULTICON, extensionW, NULL); + iconW = assoc_query(ASSOCSTR_DEFAULTICON, extensionW, NULL);
- mimeType = freedesktop_mime_type_for_extension(&nativeMimeTypes, extensionW); + mimeType = freedesktop_mime_type_for_extension(&nativeMimeTypes, extensionW);
- if (mimeType == NULL) + if (mimeType == NULL) + { + contentTypeW = assoc_query(ASSOCSTR_CONTENTTYPE, extensionW, NULL); + if (contentTypeW != NULL && wcschr(contentTypeW, '/')) + mimeType = xwcsdup(wcslwr(contentTypeW)); + else if (!(mimeType = get_special_mime_type(extensionW))) + mimeType = heap_wprintf(L"application/x-wine-extension-%s", &extensionW[1]); + + /* GNOME seems to ignore the <icon> tag in MIME packages, + * and the default name is more intuitive anyway. + */ + if (iconW) { - contentTypeW = assoc_query(ASSOCSTR_CONTENTTYPE, extensionW, NULL); - if (contentTypeW != NULL && wcschr(contentTypeW, '/')) - mimeType = xwcsdup(wcslwr(contentTypeW)); - else if (!(mimeType = get_special_mime_type(extensionW))) - mimeType = heap_wprintf(L"application/x-wine-extension-%s", &extensionW[1]); - - /* GNOME seems to ignore the <icon> tag in MIME packages, - * and the default name is more intuitive anyway. - */ - if (iconW) + WCHAR *flattened_mime = slashes_to_minuses(mimeType); + int index = 0; + WCHAR *comma = wcsrchr(iconW, ','); + if (comma) { - WCHAR *flattened_mime = slashes_to_minuses(mimeType); - int index = 0; - WCHAR *comma = wcsrchr(iconW, ','); - if (comma) - { - *comma = 0; - index = wcstol(comma + 1, NULL, 10); - } - extract_icon(iconW, index, flattened_mime, FALSE); - heap_free(flattened_mime); + *comma = 0; + index = wcstol(comma + 1, NULL, 10); } - - write_freedesktop_mime_type_entry(packages_dir, extensionW, mimeType, friendlyDocNameW); - hasChanged = TRUE; + extract_icon(iconW, index, flattened_mime, FALSE); + heap_free(flattened_mime); }
- commandW = assoc_query(ASSOCSTR_COMMAND, extensionW, L"open"); - if (commandW == NULL) - /* no command => no application is associated */ - goto end; + write_freedesktop_mime_type_entry(packages_dir, extensionW, mimeType, friendlyDocNameW); + hasChanged = TRUE; + }
- executableW = assoc_query(ASSOCSTR_EXECUTABLE, extensionW, L"open"); - if (executableW) - openWithIcon = compute_native_identifier(0, executableW, NULL); + commandW = assoc_query(ASSOCSTR_COMMAND, extensionW, L"open"); + if (commandW == NULL) + /* no command => no application is associated */ + goto end;
- friendlyAppName = assoc_query(ASSOCSTR_FRIENDLYAPPNAME, extensionW, L"open"); - if (!friendlyAppName) friendlyAppName = L"A Wine application"; + executableW = assoc_query(ASSOCSTR_EXECUTABLE, extensionW, L"open"); + if (executableW) + openWithIcon = compute_native_identifier(0, executableW, NULL);
- progIdW = reg_get_valW(HKEY_CLASSES_ROOT, extensionW, NULL); - if (!progIdW) goto end; /* no progID => not a file type association */ + friendlyAppName = assoc_query(ASSOCSTR_FRIENDLYAPPNAME, extensionW, L"open"); + if (!friendlyAppName) friendlyAppName = L"A Wine application";
- /* Do not allow duplicate ProgIDs for a MIME type, it causes unnecessary duplication in Open dialogs */ - mimeProgId = heap_wprintf(L"%s=>%s", mimeType, progIdW); - if (wine_rb_get(&mimeProgidTree, mimeProgId)) - { - heap_free(mimeProgId); - goto end; - } - entry = xmalloc(sizeof(struct rb_string_entry)); - entry->string = mimeProgId; - if (wine_rb_put(&mimeProgidTree, mimeProgId, &entry->entry)) - { - WINE_ERR("error updating rb tree\n"); - goto end; - } + progIdW = reg_get_valW(HKEY_CLASSES_ROOT, extensionW, NULL); + if (!progIdW) goto end; /* no progID => not a file type association */ + + /* Do not allow duplicate ProgIDs for a MIME type, it causes unnecessary duplication in Open dialogs */ + mimeProgId = heap_wprintf(L"%s=>%s", mimeType, progIdW); + if (wine_rb_get(&mimeProgidTree, mimeProgId)) + { + heap_free(mimeProgId); + goto end; + } + entry = xmalloc(sizeof(struct rb_string_entry)); + entry->string = mimeProgId; + if (wine_rb_put(&mimeProgidTree, mimeProgId, &entry->entry)) + { + WINE_ERR("error updating rb tree\n"); + goto end; + }
- if (has_association_changed(extensionW, mimeType, progIdW, friendlyAppName, openWithIcon)) + if (has_association_changed(extensionW, mimeType, progIdW, friendlyAppName, openWithIcon)) + { + WCHAR *desktopPath = heap_wprintf(L"%s\wine-extension-%s.desktop", + applications_dir, extensionW + 1 ); + if (write_freedesktop_association_entry(desktopPath, friendlyAppName, mimeType, progIdW, openWithIcon)) { - WCHAR *desktopPath = heap_wprintf(L"%s\wine-extension-%s.desktop", - applications_dir, extensionW + 1 ); - if (write_freedesktop_association_entry(desktopPath, friendlyAppName, mimeType, progIdW, openWithIcon)) - { - hasChanged = TRUE; - update_association(extensionW, mimeType, progIdW, friendlyAppName, desktopPath, openWithIcon); - } - heap_free(desktopPath); + hasChanged = TRUE; + update_association(extensionW, mimeType, progIdW, friendlyAppName, desktopPath, openWithIcon); } - - if (hasChanged && openWithIcon) extract_icon(executableW, 0, openWithIcon, FALSE); - - end: - heap_free(commandW); - heap_free(executableW); - heap_free(openWithIcon); - heap_free(friendlyDocNameW); - heap_free(iconW); - heap_free(contentTypeW); - heap_free(mimeType); - heap_free(progIdW); + heap_free(desktopPath); } + + if (hasChanged && openWithIcon) extract_icon(executableW, 0, openWithIcon, FALSE); + + end: + heap_free(commandW); + heap_free(executableW); + heap_free(openWithIcon); + heap_free(friendlyDocNameW); + heap_free(iconW); + heap_free(contentTypeW); + heap_free(mimeType); + heap_free(progIdW); heap_free(extensionW); - if (ret != ERROR_SUCCESS) - break; }
wine_rb_destroy(&mimeProgidTree, winemenubuilder_rb_destroy, NULL);
Alex Henrie alexhenrie24@gmail.com writes:
Signed-off-by: Alex Henrie alexhenrie24@gmail.com
I recommend using `git show -w` to visualize this patch.
programs/winemenubuilder/winemenubuilder.c | 538 +++++++++++---------- 1 file changed, 270 insertions(+), 268 deletions(-)
Even if the existing code is not great, it's not a good idea to do such large scale reformatting.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=41275 Signed-off-by: Alex Henrie alexhenrie24@gmail.com --- An old version of this patch has been in Wine Staging for over a year. --- dlls/mshtml/mshtml.inf | 6 +++ loader/wine.inf.in | 10 +++++ programs/winemenubuilder/winemenubuilder.c | 50 +++++++++++++++++++--- 3 files changed, 61 insertions(+), 5 deletions(-)
diff --git a/dlls/mshtml/mshtml.inf b/dlls/mshtml/mshtml.inf index 4a650b444fc..183d401b494 100644 --- a/dlls/mshtml/mshtml.inf +++ b/dlls/mshtml/mshtml.inf @@ -111,6 +111,7 @@ HKCR,"giffile\shell\open\ddeexec",,,"""file:%%1"",,-1,,,,," HKCR,"giffile\shell\open\ddeexec\Application",,,"IExplore" HKCR,"giffile\shell\open\ddeexec\Topic",,,"WWW_OpenURL" ;; HKCR,"giffile\DefaultIcon",,,"%16422%\Internet Explorer\iexplore.exe,9" +HKCU,Software\Wine\FileOpenNoIntegration.gif,"iexplore",,"""%16422%\Internet Explorer\iexplore.exe"" -nohome"
;; GZIP HKCR,"MIME\Database\Content Type\application/x-gzip","Extension",,".gz" @@ -158,6 +159,7 @@ HKCR,"jpegfile\shell\open\ddeexec",,,"""file:%%1"",,-1,,,,," HKCR,"jpegfile\shell\open\ddeexec\Application",,,"IExplore" HKCR,"jpegfile\shell\open\ddeexec\Topic",,,"WWW_OpenURL" ;; HKCR,"jpegfile\DefaultIcon",,,"%16422%\Internet Explorer\iexplore.exe,8" +HKCU,Software\Wine\FileOpenNoIntegration.jpe,"iexplore",,"""%16422%\Internet Explorer\iexplore.exe"" -nohome"
;; JPEG HKCR,"MIME\Database\Content Type\image/jpeg","CLSID",,"%CLSID_HTMLDocument%" @@ -173,6 +175,7 @@ HKCR,"jpegfile\shell\open\ddeexec",,,"""file:%%1"",,-1,,,,," HKCR,"jpegfile\shell\open\ddeexec\Application",,,"IExplore" HKCR,"jpegfile\shell\open\ddeexec\Topic",,,"WWW_OpenURL" ;; HKCR,"jpegfile\DefaultIcon",,,"%16422%\Internet Explorer\iexplore.exe,8" +HKCU,Software\Wine\FileOpenNoIntegration.jpeg,"iexplore",,"""%16422%\Internet Explorer\iexplore.exe"" -nohome"
;; JPG HKCR,".jpg",,2,"jpegfile" @@ -184,6 +187,7 @@ HKCR,"jpegfile\shell\open\ddeexec",,,"""file:%%1"",,-1,,,,," HKCR,"jpegfile\shell\open\ddeexec\Application",,,"IExplore" HKCR,"jpegfile\shell\open\ddeexec\Topic",,,"WWW_OpenURL" ;; HKCR,"jpegfile\DefaultIcon",,,"%16422%\Internet Explorer\iexplore.exe,8" +HKCU,Software\Wine\FileOpenNoIntegration.jpg,"iexplore",,"""%16422%\Internet Explorer\iexplore.exe"" -nohome"
;; MHTML HKCR,"MIME\Database\Content Type\message/rfc822","CLSID",,"%CLSID_MHTMLDocument%" @@ -221,6 +225,7 @@ HKCR,"pjpegfile\shell\open\ddeexec",,,"""file:%%1"",,-1,,,,," HKCR,"pjpegfile\shell\open\ddeexec\Application",,,"IExplore" HKCR,"pjpegfile\shell\open\ddeexec\Topic",,,"WWW_OpenURL" ;; HKCR,"pjpegfile\DefaultIcon",,,"%16422%\Internet Explorer\iexplore.exe,8" +HKCU,Software\Wine\FileOpenNoIntegration.jfif,"iexplore",,"""%16422%\Internet Explorer\iexplore.exe"" -nohome"
;; PNG HKCR,"MIME\Database\Content Type\image/png","Extension",,".png" @@ -234,6 +239,7 @@ HKCR,"pngfile\shell\open\ddeexec",,,"""file:%%1"",,-1,,,,," HKCR,"pngfile\shell\open\ddeexec\Application",,,"IExplore" HKCR,"pngfile\shell\open\ddeexec\Topic",,,"WWW_OpenURL" ;; HKCR,"pngfile\DefaultIcon",,,"%16422%\Internet Explorer\iexplore.exe,9" +HKCU,Software\Wine\FileOpenNoIntegration.png,"iexplore",,"""%16422%\Internet Explorer\iexplore.exe"" -nohome"
;; PS HKCR,"MIME\Database\Content Type\application/postscript","Extension",,".ps" diff --git a/loader/wine.inf.in b/loader/wine.inf.in index d023701c04b..b2747ad9a34 100644 --- a/loader/wine.inf.in +++ b/loader/wine.inf.in @@ -507,6 +507,16 @@ HKCR,MIME\Database\Charset\us-ascii,"AliasForCharset",,iso-8859-1 HKCR,MIME\Database\Charset\visual,"AliasForCharset",,iso-8859-8 HKCR,MIME\Database\Charset\Windows-1254,"AliasForCharset",,iso-8859-9
+HKCU,Software\Wine\FileOpenNoIntegration.htm,"winebrowser",,"""%11%\winebrowser.exe"" ""%1""" +HKCU,Software\Wine\FileOpenNoIntegration.html,"winebrowser",,"""%11%\winebrowser.exe"" ""%1""" +HKCU,Software\Wine\FileOpenNoIntegration.ini,"notepad",,"""%11%\notepad.exe"" ""%1""" +HKCU,Software\Wine\FileOpenNoIntegration.pdf,"winebrowser",,"""%11%\winebrowser.exe"" ""%1""" +HKCU,Software\Wine\FileOpenNoIntegration.rtf,"wordpad",,"""%16422%\Windows NT\Accessories\wordpad.exe"" ""%1""" +HKCU,Software\Wine\FileOpenNoIntegration.txt,"notepad",,"""%11%\notepad.exe"" ""%1""" +HKCU,Software\Wine\FileOpenNoIntegration.url,"ieframe",,"rundll32.exe ieframe.dll,OpenURL %l" +HKCU,Software\Wine\FileOpenNoIntegration.wri,"wordpad",,"""%16422%\Windows NT\Accessories\wordpad.exe"" ""%1""" +HKCU,Software\Wine\FileOpenNoIntegration.xml,"winebrowser",,"""%11%\winebrowser.exe"" ""%1""" + [ContentIndex] HKLM,System\CurrentControlSet\Control\ContentIndex\Language\Neutral,"WBreakerClass",,"{369647e0-17b0-11ce-9950-00aa004bbb1f}" HKLM,System\CurrentControlSet\Control\ContentIndex\Language\Neutral,"StemmerClass",,"" diff --git a/programs/winemenubuilder/winemenubuilder.c b/programs/winemenubuilder/winemenubuilder.c index f10026a418e..a2790cf203d 100644 --- a/programs/winemenubuilder/winemenubuilder.c +++ b/programs/winemenubuilder/winemenubuilder.c @@ -2091,6 +2091,42 @@ static BOOL is_extension_banned(LPCWSTR extension) return FALSE; }
+static BOOL on_exclude_list(const WCHAR *extension, const WCHAR *command) +{ + static const WCHAR FileOpenNoIntegrationW[] = L"Software\Wine\FileOpenNoIntegration\"; + WCHAR key_path[MAX_PATH]; + HKEY key; + WCHAR program_name[MAX_PATH], *command_to_exclude; + DWORD len = ARRAY_SIZE(program_name); + DWORD i = 0; + + if (ARRAY_SIZE(FileOpenNoIntegrationW) + lstrlenW(extension) > ARRAY_SIZE(key_path)) + return FALSE; + + lstrcpyW(key_path, FileOpenNoIntegrationW); + lstrcatW(key_path, extension); + + if (RegOpenKeyExW(HKEY_CURRENT_USER, key_path, 0, KEY_QUERY_VALUE, &key) != ERROR_SUCCESS) + return FALSE; + + while (RegEnumValueW(key, i, program_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) + { + command_to_exclude = reg_get_valW(HKEY_CURRENT_USER, key_path, program_name); + if (wcscmp(command, command_to_exclude) == 0) + { + heap_free(command_to_exclude); + RegCloseKey(key); + return TRUE; + } + heap_free(command_to_exclude); + len = ARRAY_SIZE(program_name); + i++; + } + + RegCloseKey(key); + return FALSE; +} + static WCHAR *get_special_mime_type(LPCWSTR extension) { if (!wcsicmp(extension, L".lnk")) @@ -2183,6 +2219,15 @@ static BOOL generate_associations(const WCHAR *packages_dir, const WCHAR *applic if (extensionW[0] != '.' || is_extension_banned(extensionW)) goto end;
+ commandW = assoc_query(ASSOCSTR_COMMAND, extensionW, L"open"); + if (commandW == NULL) + /* no command => no application is associated */ + goto end; + + if (on_exclude_list(extensionW, commandW)) + /* command is on the exclude list => desktop integration is not desirable */ + goto end; + wcslwr(extensionW); friendlyDocNameW = assoc_query(ASSOCSTR_FRIENDLYDOCNAME, extensionW, NULL);
@@ -2219,11 +2264,6 @@ static BOOL generate_associations(const WCHAR *packages_dir, const WCHAR *applic hasChanged = TRUE; }
- commandW = assoc_query(ASSOCSTR_COMMAND, extensionW, L"open"); - if (commandW == NULL) - /* no command => no application is associated */ - goto end; - executableW = assoc_query(ASSOCSTR_EXECUTABLE, extensionW, L"open"); if (executableW) openWithIcon = compute_native_identifier(0, executableW, NULL);
Alex Henrie alexhenrie24@gmail.com writes:
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=41275 Signed-off-by: Alex Henrie alexhenrie24@gmail.com
An old version of this patch has been in Wine Staging for over a year.
dlls/mshtml/mshtml.inf | 6 +++ loader/wine.inf.in | 10 +++++ programs/winemenubuilder/winemenubuilder.c | 50 +++++++++++++++++++--- 3 files changed, 61 insertions(+), 5 deletions(-)
That's fairly ugly, especially requiring all modules to create explicit settings under HKCU, and the fact that the commands have to match exactly. I'd suggest to try to find a better approach.
On Mon, Oct 11, 2021 at 12:19 PM Alexandre Julliard julliard@winehq.org wrote:
Alex Henrie alexhenrie24@gmail.com writes:
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=41275 Signed-off-by: Alex Henrie alexhenrie24@gmail.com
An old version of this patch has been in Wine Staging for over a year.
dlls/mshtml/mshtml.inf | 6 +++ loader/wine.inf.in | 10 +++++ programs/winemenubuilder/winemenubuilder.c | 50 +++++++++++++++++++--- 3 files changed, 61 insertions(+), 5 deletions(-)
That's fairly ugly, especially requiring all modules to create explicit settings under HKCU, and the fact that the commands have to match exactly. I'd suggest to try to find a better approach.
Open question for all Wine developers: What do you think is the right approach to preventing unwanted associations?
-Alex
On Tue, Oct 12, 2021 at 10:58 AM Alex Henrie alexhenrie24@gmail.com wrote:
On Mon, Oct 11, 2021 at 12:19 PM Alexandre Julliard julliard@winehq.org wrote:
Alex Henrie alexhenrie24@gmail.com writes:
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=41275 Signed-off-by: Alex Henrie alexhenrie24@gmail.com
An old version of this patch has been in Wine Staging for over a year.
dlls/mshtml/mshtml.inf | 6 +++ loader/wine.inf.in | 10 +++++ programs/winemenubuilder/winemenubuilder.c | 50 +++++++++++++++++++--- 3 files changed, 61 insertions(+), 5 deletions(-)
That's fairly ugly, especially requiring all modules to create explicit settings under HKCU, and the fact that the commands have to match exactly. I'd suggest to try to find a better approach.
Open question for all Wine developers: What do you think is the right approach to preventing unwanted associations?
Another solution that occurs to me is to set the InitialPreference property in all .desktop files generated by Wine so that all Wine applications have lower default priority than native applications. InitialPreference is supported by KDE and LXQt and there is an open bug report about supporting it in GNOME.[1] Would that be considered acceptable?
-Alex
On Tue, Oct 12, 2021 at 6:58 PM Alex Henrie alexhenrie24@gmail.com wrote:
On Mon, Oct 11, 2021 at 12:19 PM Alexandre Julliard julliard@winehq.org wrote:
Open question for all Wine developers: What do you think is the right approach to preventing unwanted associations?
Add support for further desktop standards, for example the default application to open a file type ( https://specifications.freedesktop.org/mime-apps-spec/latest/ar01s04.html).
Generate a file open association per application instead of per extension, so each application appears in Freedesktop's right-click list and "Open with" list only once. I already sent patches for this long ago, but I don't think people understood them: https://www.winehq.org/pipermail/wine-patches/2011-February/099364.html https://www.winehq.org/pipermail/wine-patches/2011-February/099365.html
Damjan
On Tue, Oct 12, 2021 at 12:01 PM Damjan Jovanovic damjan.jov@gmail.com wrote:
On Tue, Oct 12, 2021 at 6:58 PM Alex Henrie alexhenrie24@gmail.com wrote:
Open question for all Wine developers: What do you think is the right approach to preventing unwanted associations?
Add support for further desktop standards, for example the default application to open a file type (https://specifications.freedesktop.org/mime-apps-spec/latest/ar01s04.html).
When multiple native programs can open a file type, I don't think that Wine should be in charge of setting the default. That should be left to the desktop environment or to the user.
Generate a file open association per application instead of per extension, so each application appears in Freedesktop's right-click list and "Open with" list only once. I already sent patches for this long ago, but I don't think people understood them: https://www.winehq.org/pipermail/wine-patches/2011-February/099364.html https://www.winehq.org/pipermail/wine-patches/2011-February/099365.html
That's not a bad idea, but it doesn't solve the problem of unwanted file associations.
-Alex
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=22904 Signed-off-by: Alex Henrie alexhenrie24@gmail.com --- loader/wine.inf.in | 4 + programs/winemenubuilder/winemenubuilder.c | 172 ++++++++++++--------- 2 files changed, 102 insertions(+), 74 deletions(-)
diff --git a/loader/wine.inf.in b/loader/wine.inf.in index b2747ad9a34..ef1a0e759d7 100644 --- a/loader/wine.inf.in +++ b/loader/wine.inf.in @@ -516,6 +516,10 @@ HKCU,Software\Wine\FileOpenNoIntegration.txt,"notepad",,"""%11%\notepad.exe"" " HKCU,Software\Wine\FileOpenNoIntegration.url,"ieframe",,"rundll32.exe ieframe.dll,OpenURL %l" HKCU,Software\Wine\FileOpenNoIntegration.wri,"wordpad",,"""%16422%\Windows NT\Accessories\wordpad.exe"" ""%1""" HKCU,Software\Wine\FileOpenNoIntegration.xml,"winebrowser",,"""%11%\winebrowser.exe"" ""%1""" +HKCU,Software\Wine\FileOpenNoIntegration\ftp,"winebrowser",,"""%11%\winebrowser.exe"" ""%1""" +HKCU,Software\Wine\FileOpenNoIntegration\http,"winebrowser",,"""%11%\winebrowser.exe"" ""%1""" +HKCU,Software\Wine\FileOpenNoIntegration\https,"winebrowser",,"""%11%\winebrowser.exe"" ""%1""" +HKCU,Software\Wine\FileOpenNoIntegration\mailto,"winebrowser",,"""%11%\winebrowser.exe"" ""%1"""
[ContentIndex] HKLM,System\CurrentControlSet\Control\ContentIndex\Language\Neutral,"WBreakerClass",,"{369647e0-17b0-11ce-9950-00aa004bbb1f}" diff --git a/programs/winemenubuilder/winemenubuilder.c b/programs/winemenubuilder/winemenubuilder.c index a2790cf203d..88d41cd9e7b 100644 --- a/programs/winemenubuilder/winemenubuilder.c +++ b/programs/winemenubuilder/winemenubuilder.c @@ -1933,10 +1933,13 @@ static BOOL has_association_changed(LPCWSTR extensionW, const WCHAR *mimeType, c ret = TRUE; heap_free(value);
- value = reg_get_valW(assocKey, extensionW, L"ProgID"); - if (!value || wcscmp(value, progId)) - ret = TRUE; - heap_free(value); + if (progId) + { + value = reg_get_valW(assocKey, extensionW, L"ProgID"); + if (!value || wcscmp(value, progId)) + ret = TRUE; + heap_free(value); + }
value = reg_get_valW(assocKey, extensionW, L"AppName"); if (!value || wcscmp(value, appName)) @@ -1980,7 +1983,7 @@ static void update_association(LPCWSTR extension, const WCHAR *mimeType, const W }
RegSetValueExW(subkey, L"MimeType", 0, REG_SZ, (const BYTE*) mimeType, (lstrlenW(mimeType) + 1) * sizeof(WCHAR)); - RegSetValueExW(subkey, L"ProgID", 0, REG_SZ, (const BYTE*) progId, (lstrlenW(progId) + 1) * sizeof(WCHAR)); + if (progId) RegSetValueExW(subkey, L"ProgID", 0, REG_SZ, (const BYTE*) progId, (lstrlenW(progId) + 1) * sizeof(WCHAR)); RegSetValueExW(subkey, L"AppName", 0, REG_SZ, (const BYTE*) appName, (lstrlenW(appName) + 1) * sizeof(WCHAR)); RegSetValueExW(subkey, L"DesktopFile", 0, REG_SZ, (const BYTE*) desktopFile, (lstrlenW(desktopFile) + 1) * sizeof(WCHAR)); if (openWithIcon) @@ -2091,7 +2094,7 @@ static BOOL is_extension_banned(LPCWSTR extension) return FALSE; }
-static BOOL on_exclude_list(const WCHAR *extension, const WCHAR *command) +static BOOL on_exclude_list(const WCHAR *win_type, const WCHAR *command) { static const WCHAR FileOpenNoIntegrationW[] = L"Software\Wine\FileOpenNoIntegration\"; WCHAR key_path[MAX_PATH]; @@ -2100,11 +2103,11 @@ static BOOL on_exclude_list(const WCHAR *extension, const WCHAR *command) DWORD len = ARRAY_SIZE(program_name); DWORD i = 0;
- if (ARRAY_SIZE(FileOpenNoIntegrationW) + lstrlenW(extension) > ARRAY_SIZE(key_path)) + if (ARRAY_SIZE(FileOpenNoIntegrationW) + lstrlenW(win_type) > ARRAY_SIZE(key_path)) return FALSE;
lstrcpyW(key_path, FileOpenNoIntegrationW); - lstrcatW(key_path, extension); + lstrcatW(key_path, win_type);
if (RegOpenKeyExW(HKEY_CURRENT_USER, key_path, 0, KEY_QUERY_VALUE, &key) != ERROR_SUCCESS) return FALSE; @@ -2134,15 +2137,15 @@ static WCHAR *get_special_mime_type(LPCWSTR extension) return NULL; }
-static BOOL write_freedesktop_association_entry(const WCHAR *desktopPath, const WCHAR *friendlyAppName, - const WCHAR *mimeType, const WCHAR *progId, - const WCHAR *openWithIcon) +static BOOL write_freedesktop_association_entry(const WCHAR *desktopPath, const WCHAR *winType, + const WCHAR *friendlyAppName, const WCHAR *mimeType, + const WCHAR *progId, const WCHAR *openWithIcon) { FILE *desktop; const WCHAR *prefix = _wgetenv( L"WINECONFIGDIR" );
- WINE_TRACE("friendlyAppName=%s, MIME type %s, progID=%s, icon=%s to file %s\n", - wine_dbgstr_w(friendlyAppName), wine_dbgstr_w(mimeType), + WINE_TRACE("winType=%s, friendlyAppName=%s, MIME type %s, progID=%s, icon=%s to file %s\n", + wine_dbgstr_w(winType), wine_dbgstr_w(friendlyAppName), wine_dbgstr_w(mimeType), wine_dbgstr_w(progId), wine_dbgstr_w(openWithIcon), wine_dbgstr_w(desktopPath));
desktop = _wfopen( desktopPath, L"wb" ); @@ -2159,11 +2162,15 @@ static BOOL write_freedesktop_association_entry(const WCHAR *desktopPath, const if (prefix) { char *path = wine_get_unix_file_name( prefix ); - fprintf(desktop, "Exec=env WINEPREFIX="%s" wine start /ProgIDOpen %s %%f\n", path, escape(progId)); + fprintf(desktop, "Exec=env WINEPREFIX="%s" wine start ", path); heap_free( path ); } else - fprintf(desktop, "Exec=wine start /ProgIDOpen %s %%f\n", escape(progId)); + fprintf(desktop, "Exec=wine start "); + if (progId) /* file association */ + fprintf(desktop, "/ProgIDOpen %s %%f\n", escape(progId)); + else /* protocol association */ + fprintf(desktop, "%%u\n"); fprintf(desktop, "NoDisplay=true\n"); fprintf(desktop, "StartupNotify=true\n"); if (openWithIcon) @@ -2188,7 +2195,7 @@ static BOOL generate_associations(const WCHAR *packages_dir, const WCHAR *applic
for (i = 0; ; i++) { - WCHAR *extensionW = NULL; + WCHAR *winTypeW = NULL; DWORD size = 1024; WCHAR *commandW = NULL; WCHAR *executableW = NULL; @@ -2201,102 +2208,119 @@ static BOOL generate_associations(const WCHAR *packages_dir, const WCHAR *applic WCHAR *progIdW = NULL; WCHAR *mimeProgId = NULL; struct rb_string_entry *entry; + BOOL is_protocol_type = FALSE;
do { - heap_free(extensionW); - extensionW = xmalloc(size * sizeof(WCHAR)); - ret = RegEnumKeyExW(HKEY_CLASSES_ROOT, i, extensionW, &size, NULL, NULL, NULL, NULL); + heap_free(winTypeW); + winTypeW = xmalloc(size * sizeof(WCHAR)); + ret = RegEnumKeyExW(HKEY_CLASSES_ROOT, i, winTypeW, &size, NULL, NULL, NULL, NULL); size *= 2; } while (ret == ERROR_MORE_DATA);
if (ret != ERROR_SUCCESS) { - heap_free(extensionW); + heap_free(winTypeW); break; }
- if (extensionW[0] != '.' || is_extension_banned(extensionW)) + if (winTypeW[0] != '.') + { + if (RegGetValueW(HKEY_CLASSES_ROOT, winTypeW, L"URL Protocol", RRF_RT_ANY, NULL, NULL, NULL) == ERROR_SUCCESS) + is_protocol_type = TRUE; + } + + if (!is_protocol_type && (winTypeW[0] != '.' || is_extension_banned(winTypeW))) goto end;
- commandW = assoc_query(ASSOCSTR_COMMAND, extensionW, L"open"); + commandW = assoc_query(ASSOCSTR_COMMAND, winTypeW, L"open"); if (commandW == NULL) /* no command => no application is associated */ goto end;
- if (on_exclude_list(extensionW, commandW)) + if (on_exclude_list(winTypeW, commandW)) /* command is on the exclude list => desktop integration is not desirable */ goto end;
- wcslwr(extensionW); - friendlyDocNameW = assoc_query(ASSOCSTR_FRIENDLYDOCNAME, extensionW, NULL); + wcslwr(winTypeW); + friendlyDocNameW = assoc_query(ASSOCSTR_FRIENDLYDOCNAME, winTypeW, NULL);
- iconW = assoc_query(ASSOCSTR_DEFAULTICON, extensionW, NULL); + iconW = assoc_query(ASSOCSTR_DEFAULTICON, winTypeW, NULL);
- mimeType = freedesktop_mime_type_for_extension(&nativeMimeTypes, extensionW); - - if (mimeType == NULL) + if (is_protocol_type) { - contentTypeW = assoc_query(ASSOCSTR_CONTENTTYPE, extensionW, NULL); - if (contentTypeW != NULL && wcschr(contentTypeW, '/')) - mimeType = xwcsdup(wcslwr(contentTypeW)); - else if (!(mimeType = get_special_mime_type(extensionW))) - mimeType = heap_wprintf(L"application/x-wine-extension-%s", &extensionW[1]); + mimeType = heap_wprintf(L"x-scheme-handler/%s", winTypeW); + } + else + { + mimeType = freedesktop_mime_type_for_extension(&nativeMimeTypes, winTypeW);
- /* GNOME seems to ignore the <icon> tag in MIME packages, - * and the default name is more intuitive anyway. - */ - if (iconW) + if (mimeType == NULL) { - WCHAR *flattened_mime = slashes_to_minuses(mimeType); - int index = 0; - WCHAR *comma = wcsrchr(iconW, ','); - if (comma) + contentTypeW = assoc_query(ASSOCSTR_CONTENTTYPE, winTypeW, NULL); + if (contentTypeW != NULL && wcschr(contentTypeW, '/')) + mimeType = xwcsdup(wcslwr(contentTypeW)); + else if (!(mimeType = get_special_mime_type(winTypeW))) + mimeType = heap_wprintf(L"application/x-wine-extension-%s", &winTypeW[1]); + + /* GNOME seems to ignore the <icon> tag in MIME packages, + * and the default name is more intuitive anyway. + */ + if (iconW) { - *comma = 0; - index = wcstol(comma + 1, NULL, 10); + WCHAR *flattened_mime = slashes_to_minuses(mimeType); + int index = 0; + WCHAR *comma = wcsrchr(iconW, ','); + if (comma) + { + *comma = 0; + index = wcstol(comma + 1, NULL, 10); + } + extract_icon(iconW, index, flattened_mime, FALSE); + heap_free(flattened_mime); } - extract_icon(iconW, index, flattened_mime, FALSE); - heap_free(flattened_mime); + + write_freedesktop_mime_type_entry(packages_dir, winTypeW, mimeType, friendlyDocNameW); + hasChanged = TRUE; }
- write_freedesktop_mime_type_entry(packages_dir, extensionW, mimeType, friendlyDocNameW); - hasChanged = TRUE; + progIdW = reg_get_valW(HKEY_CLASSES_ROOT, winTypeW, NULL); + if (!progIdW) goto end; /* no progID => not a file type association */ + + /* Do not allow duplicate ProgIDs for a MIME type, it causes unnecessary duplication in Open dialogs */ + mimeProgId = heap_wprintf(L"%s=>%s", mimeType, progIdW); + if (wine_rb_get(&mimeProgidTree, mimeProgId)) + { + heap_free(mimeProgId); + goto end; + } + entry = xmalloc(sizeof(struct rb_string_entry)); + entry->string = mimeProgId; + if (wine_rb_put(&mimeProgidTree, mimeProgId, &entry->entry)) + { + WINE_ERR("error updating rb tree\n"); + goto end; + } }
- executableW = assoc_query(ASSOCSTR_EXECUTABLE, extensionW, L"open"); + executableW = assoc_query(ASSOCSTR_EXECUTABLE, winTypeW, L"open"); if (executableW) openWithIcon = compute_native_identifier(0, executableW, NULL);
- friendlyAppName = assoc_query(ASSOCSTR_FRIENDLYAPPNAME, extensionW, L"open"); + friendlyAppName = assoc_query(ASSOCSTR_FRIENDLYAPPNAME, winTypeW, L"open"); if (!friendlyAppName) friendlyAppName = L"A Wine application";
- progIdW = reg_get_valW(HKEY_CLASSES_ROOT, extensionW, NULL); - if (!progIdW) goto end; /* no progID => not a file type association */ - - /* Do not allow duplicate ProgIDs for a MIME type, it causes unnecessary duplication in Open dialogs */ - mimeProgId = heap_wprintf(L"%s=>%s", mimeType, progIdW); - if (wine_rb_get(&mimeProgidTree, mimeProgId)) + if (has_association_changed(winTypeW, mimeType, progIdW, friendlyAppName, openWithIcon)) { - heap_free(mimeProgId); - goto end; - } - entry = xmalloc(sizeof(struct rb_string_entry)); - entry->string = mimeProgId; - if (wine_rb_put(&mimeProgidTree, mimeProgId, &entry->entry)) - { - WINE_ERR("error updating rb tree\n"); - goto end; - } - - if (has_association_changed(extensionW, mimeType, progIdW, friendlyAppName, openWithIcon)) - { - WCHAR *desktopPath = heap_wprintf(L"%s\wine-extension-%s.desktop", - applications_dir, extensionW + 1 ); - if (write_freedesktop_association_entry(desktopPath, friendlyAppName, mimeType, progIdW, openWithIcon)) + WCHAR *desktopPath; + if (is_protocol_type) + desktopPath = heap_wprintf(L"%s\wine-protocol-%s.desktop", applications_dir, winTypeW); + else + desktopPath = heap_wprintf(L"%s\wine-extension-%s.desktop", applications_dir, winTypeW+1); + if (write_freedesktop_association_entry(desktopPath, winTypeW, friendlyAppName, mimeType, progIdW, openWithIcon)) { hasChanged = TRUE; - update_association(extensionW, mimeType, progIdW, friendlyAppName, desktopPath, openWithIcon); + update_association(winTypeW, mimeType, progIdW, friendlyAppName, desktopPath, openWithIcon); } heap_free(desktopPath); } @@ -2312,7 +2336,7 @@ static BOOL generate_associations(const WCHAR *packages_dir, const WCHAR *applic heap_free(contentTypeW); heap_free(mimeType); heap_free(progIdW); - heap_free(extensionW); + heap_free(winTypeW); }
wine_rb_destroy(&mimeProgidTree, winemenubuilder_rb_destroy, NULL);