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);