winemenubuilder: Use Unicode strings to process association entries.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
542d67342d
commit
41881ff625
|
@ -176,14 +176,14 @@ typedef struct
|
|||
|
||||
struct xdg_mime_type
|
||||
{
|
||||
char *mimeType;
|
||||
char *glob;
|
||||
WCHAR *mimeType;
|
||||
WCHAR *glob;
|
||||
struct list entry;
|
||||
};
|
||||
|
||||
struct rb_string_entry
|
||||
{
|
||||
char *string;
|
||||
WCHAR *string;
|
||||
struct wine_rb_entry entry;
|
||||
};
|
||||
|
||||
|
@ -195,15 +195,15 @@ static char *xdg_desktop_dir;
|
|||
|
||||
|
||||
/* Utility routines */
|
||||
static unsigned short crc16(const char* string)
|
||||
static unsigned short crc16(const WCHAR *string)
|
||||
{
|
||||
unsigned short crc = 0;
|
||||
int i, j, xor_poly;
|
||||
|
||||
for (i = 0; string[i] != 0; i++)
|
||||
{
|
||||
char c = string[i];
|
||||
for (j = 0; j < 8; c >>= 1, j++)
|
||||
WCHAR c = string[i];
|
||||
for (j = 0; j < 16; c >>= 1, j++)
|
||||
{
|
||||
xor_poly = (c ^ crc) & 1;
|
||||
crc >>= 1;
|
||||
|
@ -247,6 +247,16 @@ static char *xstrdup( const char *str )
|
|||
return ret;
|
||||
}
|
||||
|
||||
static WCHAR *xwcsdup( const WCHAR *str )
|
||||
{
|
||||
WCHAR *ret;
|
||||
|
||||
if (!str) return NULL;
|
||||
ret = xmalloc( (strlenW(str) + 1) * sizeof(WCHAR) );
|
||||
strcpyW( ret, str );
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void heap_free( void *ptr )
|
||||
{
|
||||
HeapFree( GetProcessHeap(), 0, ptr );
|
||||
|
@ -275,11 +285,34 @@ static char* heap_printf(const char *format, ...)
|
|||
}
|
||||
}
|
||||
|
||||
static WCHAR * WINAPIV heap_wprintf(const WCHAR *format, ...)
|
||||
{
|
||||
__ms_va_list args;
|
||||
int size = 4096;
|
||||
WCHAR *buffer;
|
||||
int n;
|
||||
|
||||
while (1)
|
||||
{
|
||||
buffer = xmalloc(size * sizeof(WCHAR));
|
||||
__ms_va_start(args, format);
|
||||
n = _vsnwprintf(buffer, size, format, args);
|
||||
__ms_va_end(args);
|
||||
if (n == -1)
|
||||
size *= 2;
|
||||
else if (n >= size)
|
||||
size = n + 1;
|
||||
else
|
||||
return buffer;
|
||||
heap_free(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
static int winemenubuilder_rb_string_compare(const void *key, const struct wine_rb_entry *entry)
|
||||
{
|
||||
const struct rb_string_entry *t = WINE_RB_ENTRY_VALUE(entry, const struct rb_string_entry, entry);
|
||||
|
||||
return strcmp((char*)key, t->string);
|
||||
return strcmpW((WCHAR *)key, t->string);
|
||||
}
|
||||
|
||||
static void winemenubuilder_rb_destroy(struct wine_rb_entry *entry, void *context)
|
||||
|
@ -363,7 +396,7 @@ static WCHAR* utf8_chars_to_wchars(LPCSTR string)
|
|||
*/
|
||||
|
||||
static HRESULT convert_to_native_icon(IStream *icoFile, int *indices, int numIndices,
|
||||
const CLSID *outputFormat, const char *outputFileName, LPCWSTR commentW)
|
||||
const CLSID *outputFormat, const char *outputFileName)
|
||||
{
|
||||
WCHAR *dosOutputFileName = NULL;
|
||||
IWICImagingFactory *factory = NULL;
|
||||
|
@ -960,7 +993,7 @@ static HRESULT validate_ico(IStream **ppStream, ICONDIRENTRY **ppIconDirEntries,
|
|||
}
|
||||
|
||||
static HRESULT write_native_icon(IStream *iconStream, ICONDIRENTRY *pIconDirEntry,
|
||||
int numEntries, const char *icon_name, LPCWSTR szFileName)
|
||||
int numEntries, const char *icon_name)
|
||||
{
|
||||
int nMax = 0, nMaxBits = 0;
|
||||
int nIndex = 0;
|
||||
|
@ -984,7 +1017,7 @@ static HRESULT write_native_icon(IStream *iconStream, ICONDIRENTRY *pIconDirEntr
|
|||
position.QuadPart = 0;
|
||||
hr = IStream_Seek(iconStream, position, STREAM_SEEK_SET, NULL);
|
||||
if (FAILED(hr)) return hr;
|
||||
return convert_to_native_icon(iconStream, &nIndex, 1, &CLSID_WICPngEncoder, icon_name, szFileName);
|
||||
return convert_to_native_icon(iconStream, &nIndex, 1, &CLSID_WICPngEncoder, icon_name);
|
||||
}
|
||||
|
||||
static WCHAR* assoc_query(ASSOCSTR assocStr, LPCWSTR name, LPCWSTR extra)
|
||||
|
@ -1088,30 +1121,22 @@ static HRESULT open_icon(LPCWSTR filename, int index, BOOL bWait, IStream **ppSt
|
|||
return hr;
|
||||
}
|
||||
|
||||
static char* compute_native_identifier(int exeIndex, LPCWSTR icoPathW)
|
||||
static WCHAR *compute_native_identifier(int exeIndex, LPCWSTR icoPathW, LPCWSTR filename)
|
||||
{
|
||||
char* nativeIdentifier;
|
||||
char *icoPathA;
|
||||
static const WCHAR fmtW[] = {'%','0','4','X','_','%','.','*','s','.','%','d',0};
|
||||
unsigned short crc;
|
||||
char *basename, *ext;
|
||||
const WCHAR *basename, *ext;
|
||||
|
||||
icoPathA = wchars_to_utf8_chars(icoPathW);
|
||||
crc = crc16(icoPathA);
|
||||
basename = strrchr(icoPathA, '\\');
|
||||
if (basename == NULL)
|
||||
basename = icoPathA;
|
||||
else
|
||||
{
|
||||
*basename = 0;
|
||||
basename++;
|
||||
}
|
||||
ext = strrchr(basename, '.');
|
||||
if (ext)
|
||||
*ext = 0;
|
||||
if (filename) return xwcsdup( filename );
|
||||
|
||||
nativeIdentifier = heap_printf("%04X_%s.%d", crc, basename, exeIndex);
|
||||
heap_free(icoPathA);
|
||||
return nativeIdentifier;
|
||||
crc = crc16(icoPathW);
|
||||
basename = strrchrW(icoPathW, '\\');
|
||||
if (basename == NULL) basename = icoPathW;
|
||||
else basename++;
|
||||
ext = strrchrW(basename, '.');
|
||||
if (!ext) ext = basename + strlenW(basename);
|
||||
|
||||
return heap_wprintf(fmtW, crc, (int)(ext - basename), basename, exeIndex);
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
@ -1137,7 +1162,7 @@ static inline int size_to_slot(int size)
|
|||
|
||||
static HRESULT platform_write_icon(IStream *icoStream, ICONDIRENTRY *iconDirEntries,
|
||||
int numEntries, int exeIndex, LPCWSTR icoPathW,
|
||||
const char *destFilename, char **nativeIdentifier)
|
||||
const WCHAR *destFilename, WCHAR **nativeIdentifier)
|
||||
{
|
||||
struct {
|
||||
int index;
|
||||
|
@ -1204,12 +1229,9 @@ static HRESULT platform_write_icon(IStream *icoStream, ICONDIRENTRY *iconDirEntr
|
|||
}
|
||||
}
|
||||
|
||||
if (destFilename)
|
||||
*nativeIdentifier = heap_printf("%s", destFilename);
|
||||
else
|
||||
*nativeIdentifier = compute_native_identifier(exeIndex, icoPathW);
|
||||
*nativeIdentifier = compute_native_identifier(exeIndex, icoPathW, destFilename);
|
||||
if (!(tmpdir = getenv("TMPDIR"))) tmpdir = "/tmp";
|
||||
icnsPath = heap_printf("%s/%s.icns", tmpdir, *nativeIdentifier);
|
||||
icnsPath = heap_printf("%s/%s.icns", tmpdir, wchars_to_utf8_chars(*nativeIdentifier));
|
||||
zero.QuadPart = 0;
|
||||
hr = IStream_Seek(icoStream, zero, STREAM_SEEK_SET, NULL);
|
||||
if (FAILED(hr))
|
||||
|
@ -1217,8 +1239,7 @@ static HRESULT platform_write_icon(IStream *icoStream, ICONDIRENTRY *iconDirEntr
|
|||
WINE_WARN("seeking icon stream failed, error 0x%08X\n", hr);
|
||||
goto end;
|
||||
}
|
||||
hr = convert_to_native_icon(icoStream, indexes, numEntries, &CLSID_WICIcnsEncoder,
|
||||
icnsPath, icoPathW);
|
||||
hr = convert_to_native_icon(icoStream, indexes, numEntries, &CLSID_WICIcnsEncoder, icnsPath);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WINE_WARN("converting %s to %s failed, error 0x%08X\n",
|
||||
|
@ -1250,17 +1271,14 @@ static void refresh_icon_cache(const char *iconsDir)
|
|||
|
||||
static HRESULT platform_write_icon(IStream *icoStream, ICONDIRENTRY *iconDirEntries,
|
||||
int numEntries, int exeIndex, LPCWSTR icoPathW,
|
||||
const char *destFilename, char **nativeIdentifier)
|
||||
const WCHAR *destFilename, WCHAR **nativeIdentifier)
|
||||
{
|
||||
int i;
|
||||
char *iconsDir = NULL;
|
||||
HRESULT hr = S_OK;
|
||||
LARGE_INTEGER zero;
|
||||
|
||||
if (destFilename)
|
||||
*nativeIdentifier = heap_printf("%s", destFilename);
|
||||
else
|
||||
*nativeIdentifier = compute_native_identifier(exeIndex, icoPathW);
|
||||
*nativeIdentifier = compute_native_identifier(exeIndex, icoPathW, destFilename);
|
||||
iconsDir = heap_printf("%s/icons/hicolor", xdg_data_dir);
|
||||
|
||||
for (i = 0; i < numEntries; i++)
|
||||
|
@ -1301,12 +1319,11 @@ static HRESULT platform_write_icon(IStream *icoStream, ICONDIRENTRY *iconDirEntr
|
|||
h = iconDirEntries[bestIndex].bHeight ? iconDirEntries[bestIndex].bHeight : 256;
|
||||
iconDir = heap_printf("%s/%dx%d/apps", iconsDir, w, h);
|
||||
create_directories(iconDir);
|
||||
pngPath = heap_printf("%s/%s.png", iconDir, *nativeIdentifier);
|
||||
pngPath = heap_printf("%s/%s.png", iconDir, wchars_to_utf8_chars(*nativeIdentifier));
|
||||
zero.QuadPart = 0;
|
||||
hr = IStream_Seek(icoStream, zero, STREAM_SEEK_SET, NULL);
|
||||
if (SUCCEEDED(hr))
|
||||
hr = convert_to_native_icon(icoStream, &bestIndex, 1, &CLSID_WICPngEncoder,
|
||||
pngPath, icoPathW);
|
||||
hr = convert_to_native_icon(icoStream, &bestIndex, 1, &CLSID_WICPngEncoder, pngPath);
|
||||
|
||||
heap_free(iconDir);
|
||||
heap_free(pngPath);
|
||||
|
@ -1318,15 +1335,15 @@ static HRESULT platform_write_icon(IStream *icoStream, ICONDIRENTRY *iconDirEntr
|
|||
#endif /* defined(__APPLE__) */
|
||||
|
||||
/* extract an icon from an exe or icon file; helper for IPersistFile_fnSave */
|
||||
static char *extract_icon(LPCWSTR icoPathW, int index, const char *destFilename, BOOL bWait)
|
||||
static WCHAR *extract_icon(LPCWSTR icoPathW, int index, const WCHAR *destFilename, BOOL bWait)
|
||||
{
|
||||
IStream *stream = NULL;
|
||||
ICONDIRENTRY *pIconDirEntries = NULL;
|
||||
int numEntries;
|
||||
HRESULT hr;
|
||||
char *nativeIdentifier = NULL;
|
||||
WCHAR *nativeIdentifier = NULL;
|
||||
|
||||
WINE_TRACE("path=[%s] index=%d destFilename=[%s]\n", wine_dbgstr_w(icoPathW), index, wine_dbgstr_a(destFilename));
|
||||
WINE_TRACE("path=[%s] index=%d destFilename=[%s]\n", wine_dbgstr_w(icoPathW), index, wine_dbgstr_w(destFilename));
|
||||
|
||||
hr = open_icon(icoPathW, index, bWait, &stream, &pIconDirEntries, &numEntries);
|
||||
if (FAILED(hr))
|
||||
|
@ -1388,7 +1405,7 @@ static DWORD register_menus_entry(const char *unix_file, const WCHAR *windows_fi
|
|||
|
||||
static BOOL write_desktop_entry(const WCHAR *link, const char *location, const char *linkname,
|
||||
const char *path, const char *args, const char *descr,
|
||||
const char *workdir, const char *icon, const char *wmclass)
|
||||
const char *workdir, const WCHAR *icon, const char *wmclass)
|
||||
{
|
||||
FILE *file;
|
||||
const char *prefix = getenv("WINEPREFIX");
|
||||
|
@ -1396,7 +1413,7 @@ static BOOL write_desktop_entry(const WCHAR *link, const char *location, const c
|
|||
|
||||
WINE_TRACE("(%s,%s,%s,%s,%s,%s,%s,%s,%s)\n", wine_dbgstr_w(link), wine_dbgstr_a(location),
|
||||
wine_dbgstr_a(linkname), wine_dbgstr_a(path), wine_dbgstr_a(args),
|
||||
wine_dbgstr_a(descr), wine_dbgstr_a(workdir), wine_dbgstr_a(icon),
|
||||
wine_dbgstr_a(descr), wine_dbgstr_a(workdir), wine_dbgstr_w(icon),
|
||||
wine_dbgstr_a(wmclass));
|
||||
|
||||
file = fopen(location, "w");
|
||||
|
@ -1418,7 +1435,7 @@ static BOOL write_desktop_entry(const WCHAR *link, const char *location, const c
|
|||
if (workdir && *workdir)
|
||||
fprintf(file, "Path=%s\n", workdir);
|
||||
if (icon && *icon)
|
||||
fprintf(file, "Icon=%s\n", icon);
|
||||
fprintf(file, "Icon=%s\n", wchars_to_utf8_chars(icon));
|
||||
if (wmclass && *wmclass)
|
||||
fprintf(file, "StartupWMClass=%s\n", wmclass);
|
||||
|
||||
|
@ -1558,7 +1575,7 @@ end:
|
|||
}
|
||||
|
||||
static BOOL write_menu_entry(const WCHAR *windows_link, const char *link, const char *path, const char *args,
|
||||
const char *descr, const char *workdir, const char *icon, const char *wmclass)
|
||||
const char *descr, const char *workdir, const WCHAR *icon, const char *wmclass)
|
||||
{
|
||||
const char *linkname;
|
||||
char *desktopPath = NULL;
|
||||
|
@ -1568,7 +1585,7 @@ static BOOL write_menu_entry(const WCHAR *windows_link, const char *link, const
|
|||
|
||||
WINE_TRACE("(%s, %s, %s, %s, %s, %s, %s, %s)\n", wine_dbgstr_w(windows_link), wine_dbgstr_a(link),
|
||||
wine_dbgstr_a(path), wine_dbgstr_a(args), wine_dbgstr_a(descr),
|
||||
wine_dbgstr_a(workdir), wine_dbgstr_a(icon), wine_dbgstr_a(wmclass));
|
||||
wine_dbgstr_a(workdir), wine_dbgstr_w(icon), wine_dbgstr_a(wmclass));
|
||||
|
||||
linkname = strrchr(link, '/');
|
||||
if (linkname == NULL)
|
||||
|
@ -1869,10 +1886,10 @@ static HRESULT get_cmdline( IShellLinkW *sl, LPWSTR szPath, DWORD pathSize,
|
|||
return hr;
|
||||
}
|
||||
|
||||
static char *slashes_to_minuses(const char *string)
|
||||
static WCHAR *slashes_to_minuses(const WCHAR *string)
|
||||
{
|
||||
int i;
|
||||
char *ret = xstrdup(string);
|
||||
WCHAR *ret = xwcsdup(string);
|
||||
|
||||
for (i = 0; ret[i]; i++) if (ret[i] == '/') ret[i] = '-';
|
||||
return ret;
|
||||
|
@ -1933,8 +1950,8 @@ static BOOL add_mimes(const char *xdg_data_dir, struct list *mime_types)
|
|||
{
|
||||
mime_type_entry = xmalloc(sizeof(struct xdg_mime_type));
|
||||
*pos = 0;
|
||||
mime_type_entry->mimeType = xstrdup(line);
|
||||
mime_type_entry->glob = xstrdup(pos + 1);
|
||||
mime_type_entry->mimeType = utf8_chars_to_wchars(line);
|
||||
mime_type_entry->glob = utf8_chars_to_wchars(pos + 1);
|
||||
list_add_tail(mime_types, &mime_type_entry->entry);
|
||||
}
|
||||
}
|
||||
|
@ -1993,9 +2010,8 @@ static BOOL build_native_mime_types(const char *xdg_data_home, struct list *mime
|
|||
}
|
||||
|
||||
static BOOL freedesktop_mime_type_for_extension(struct list *native_mime_types,
|
||||
const char *extensionA,
|
||||
LPCWSTR extensionW,
|
||||
char **match)
|
||||
WCHAR **match)
|
||||
{
|
||||
struct xdg_mime_type *mime_type_entry;
|
||||
int matchLength = 0;
|
||||
|
@ -2004,17 +2020,17 @@ static BOOL freedesktop_mime_type_for_extension(struct list *native_mime_types,
|
|||
|
||||
LIST_FOR_EACH_ENTRY(mime_type_entry, native_mime_types, struct xdg_mime_type, entry)
|
||||
{
|
||||
if (PathMatchSpecA( extensionA, mime_type_entry->glob ))
|
||||
if (PathMatchSpecW( extensionW, mime_type_entry->glob ))
|
||||
{
|
||||
if (*match == NULL || matchLength < strlen(mime_type_entry->glob))
|
||||
if (*match == NULL || matchLength < strlenW(mime_type_entry->glob))
|
||||
{
|
||||
*match = mime_type_entry->mimeType;
|
||||
matchLength = strlen(mime_type_entry->glob);
|
||||
matchLength = strlenW(mime_type_entry->glob);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (*match != NULL) *match = xstrdup(*match);
|
||||
if (*match != NULL) *match = xwcsdup(*match);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -2053,8 +2069,8 @@ static HKEY open_associations_reg_key(void)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static BOOL has_association_changed(LPCWSTR extensionW, LPCSTR mimeType, LPCWSTR progId,
|
||||
LPCSTR appName, LPCSTR openWithIcon)
|
||||
static BOOL has_association_changed(LPCWSTR extensionW, const WCHAR *mimeType, const WCHAR *progId,
|
||||
const WCHAR *appName, const WCHAR *openWithIcon)
|
||||
{
|
||||
static const WCHAR ProgIDW[] = {'P','r','o','g','I','D',0};
|
||||
static const WCHAR MimeTypeW[] = {'M','i','m','e','T','y','p','e',0};
|
||||
|
@ -2065,32 +2081,31 @@ static BOOL has_association_changed(LPCWSTR extensionW, LPCSTR mimeType, LPCWSTR
|
|||
|
||||
if ((assocKey = open_associations_reg_key()))
|
||||
{
|
||||
CHAR *valueA;
|
||||
WCHAR *value;
|
||||
|
||||
ret = FALSE;
|
||||
|
||||
valueA = reg_get_val_utf8(assocKey, extensionW, MimeTypeW);
|
||||
if (!valueA || lstrcmpA(valueA, mimeType))
|
||||
value = reg_get_valW(assocKey, extensionW, MimeTypeW);
|
||||
if (!value || strcmpW(value, mimeType))
|
||||
ret = TRUE;
|
||||
heap_free(valueA);
|
||||
heap_free(value);
|
||||
|
||||
value = reg_get_valW(assocKey, extensionW, ProgIDW);
|
||||
if (!value || strcmpW(value, progId))
|
||||
ret = TRUE;
|
||||
heap_free(value);
|
||||
|
||||
valueA = reg_get_val_utf8(assocKey, extensionW, AppNameW);
|
||||
if (!valueA || lstrcmpA(valueA, appName))
|
||||
value = reg_get_valW(assocKey, extensionW, AppNameW);
|
||||
if (!value || strcmpW(value, appName))
|
||||
ret = TRUE;
|
||||
heap_free(valueA);
|
||||
heap_free(value);
|
||||
|
||||
valueA = reg_get_val_utf8(assocKey, extensionW, OpenWithIconW);
|
||||
if ((openWithIcon && !valueA) ||
|
||||
(!openWithIcon && valueA) ||
|
||||
(openWithIcon && valueA && lstrcmpA(valueA, openWithIcon)))
|
||||
value = reg_get_valW(assocKey, extensionW, OpenWithIconW);
|
||||
if ((openWithIcon && !value) ||
|
||||
(!openWithIcon && value) ||
|
||||
(openWithIcon && value && strcmpW(value, openWithIcon)))
|
||||
ret = TRUE;
|
||||
heap_free(valueA);
|
||||
heap_free(value);
|
||||
|
||||
RegCloseKey(assocKey);
|
||||
}
|
||||
|
@ -2102,8 +2117,8 @@ static BOOL has_association_changed(LPCWSTR extensionW, LPCSTR mimeType, LPCWSTR
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void update_association(LPCWSTR extension, LPCSTR mimeType, LPCWSTR progId,
|
||||
LPCSTR appName, LPCSTR desktopFile, LPCSTR openWithIcon)
|
||||
static void update_association(LPCWSTR extension, const WCHAR *mimeType, const WCHAR *progId,
|
||||
const WCHAR *appName, LPCSTR desktopFile, const WCHAR *openWithIcon)
|
||||
{
|
||||
static const WCHAR ProgIDW[] = {'P','r','o','g','I','D',0};
|
||||
static const WCHAR MimeTypeW[] = {'M','i','m','e','T','y','p','e',0};
|
||||
|
@ -2112,10 +2127,7 @@ static void update_association(LPCWSTR extension, LPCSTR mimeType, LPCWSTR progI
|
|||
static const WCHAR OpenWithIconW[] = {'O','p','e','n','W','i','t','h','I','c','o','n',0};
|
||||
HKEY assocKey = NULL;
|
||||
HKEY subkey = NULL;
|
||||
WCHAR *mimeTypeW = NULL;
|
||||
WCHAR *appNameW = NULL;
|
||||
WCHAR *desktopFileW = NULL;
|
||||
WCHAR *openWithIconW = NULL;
|
||||
|
||||
assocKey = open_associations_reg_key();
|
||||
if (assocKey == NULL)
|
||||
|
@ -2130,27 +2142,21 @@ static void update_association(LPCWSTR extension, LPCSTR mimeType, LPCWSTR progI
|
|||
goto done;
|
||||
}
|
||||
|
||||
mimeTypeW = utf8_chars_to_wchars(mimeType);
|
||||
appNameW = utf8_chars_to_wchars(appName);
|
||||
desktopFileW = utf8_chars_to_wchars(desktopFile);
|
||||
if (openWithIcon) openWithIconW = utf8_chars_to_wchars(openWithIcon);
|
||||
|
||||
RegSetValueExW(subkey, MimeTypeW, 0, REG_SZ, (const BYTE*) mimeTypeW, (lstrlenW(mimeTypeW) + 1) * sizeof(WCHAR));
|
||||
RegSetValueExW(subkey, MimeTypeW, 0, REG_SZ, (const BYTE*) mimeType, (lstrlenW(mimeType) + 1) * sizeof(WCHAR));
|
||||
RegSetValueExW(subkey, ProgIDW, 0, REG_SZ, (const BYTE*) progId, (lstrlenW(progId) + 1) * sizeof(WCHAR));
|
||||
RegSetValueExW(subkey, AppNameW, 0, REG_SZ, (const BYTE*) appNameW, (lstrlenW(appNameW) + 1) * sizeof(WCHAR));
|
||||
RegSetValueExW(subkey, AppNameW, 0, REG_SZ, (const BYTE*) appName, (lstrlenW(appName) + 1) * sizeof(WCHAR));
|
||||
RegSetValueExW(subkey, DesktopFileW, 0, REG_SZ, (const BYTE*) desktopFileW, (lstrlenW(desktopFileW) + 1) * sizeof(WCHAR));
|
||||
if (openWithIcon)
|
||||
RegSetValueExW(subkey, OpenWithIconW, 0, REG_SZ, (const BYTE*) openWithIconW, (lstrlenW(openWithIconW) + 1) * sizeof(WCHAR));
|
||||
RegSetValueExW(subkey, OpenWithIconW, 0, REG_SZ, (const BYTE*) openWithIcon, (lstrlenW(openWithIcon) + 1) * sizeof(WCHAR));
|
||||
else
|
||||
RegDeleteValueW(subkey, OpenWithIconW);
|
||||
|
||||
done:
|
||||
RegCloseKey(assocKey);
|
||||
RegCloseKey(subkey);
|
||||
heap_free(mimeTypeW);
|
||||
heap_free(appNameW);
|
||||
heap_free(desktopFileW);
|
||||
heap_free(openWithIconW);
|
||||
}
|
||||
|
||||
static BOOL cleanup_associations(void)
|
||||
|
@ -2212,32 +2218,32 @@ static BOOL cleanup_associations(void)
|
|||
return hasChanged;
|
||||
}
|
||||
|
||||
static BOOL write_freedesktop_mime_type_entry(const char *packages_dir, const char *dot_extension,
|
||||
const char *mime_type, const char *comment)
|
||||
static BOOL write_freedesktop_mime_type_entry(const char *packages_dir, const WCHAR *dot_extension,
|
||||
const WCHAR *mime_type, const WCHAR *comment)
|
||||
{
|
||||
BOOL ret = FALSE;
|
||||
char *filename;
|
||||
FILE *packageFile;
|
||||
|
||||
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));
|
||||
WINE_TRACE("writing MIME type %s, extension=%s, comment=%s\n", wine_dbgstr_w(mime_type),
|
||||
wine_dbgstr_w(dot_extension), wine_dbgstr_w(comment));
|
||||
|
||||
filename = heap_printf("%s/x-wine-extension-%s.xml", packages_dir, &dot_extension[1]);
|
||||
filename = heap_printf("%s/x-wine-extension-%s.xml", packages_dir, wchars_to_utf8_chars(dot_extension + 1));
|
||||
packageFile = fopen(filename, "w");
|
||||
if (packageFile)
|
||||
{
|
||||
fprintf(packageFile, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
|
||||
fprintf(packageFile, "<mime-info xmlns=\"http://www.freedesktop.org/standards/shared-mime-info\">\n");
|
||||
fprintf(packageFile, " <mime-type type=\"");
|
||||
write_xml_text(packageFile, mime_type);
|
||||
write_xml_text(packageFile, wchars_to_utf8_chars(mime_type));
|
||||
fprintf(packageFile, "\">\n");
|
||||
fprintf(packageFile, " <glob pattern=\"*");
|
||||
write_xml_text(packageFile, dot_extension);
|
||||
write_xml_text(packageFile, wchars_to_utf8_chars(dot_extension));
|
||||
fprintf(packageFile, "\"/>\n");
|
||||
if (comment)
|
||||
{
|
||||
fprintf(packageFile, " <comment>");
|
||||
write_xml_text(packageFile, comment);
|
||||
write_xml_text(packageFile, wchars_to_utf8_chars(comment));
|
||||
fprintf(packageFile, "</comment>\n");
|
||||
}
|
||||
fprintf(packageFile, " </mime-type>\n");
|
||||
|
@ -2265,44 +2271,45 @@ static BOOL is_extension_banned(LPCWSTR extension)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static const char* get_special_mime_type(LPCWSTR extension)
|
||||
static WCHAR *get_special_mime_type(LPCWSTR extension)
|
||||
{
|
||||
static const WCHAR lnkW[] = {'.','l','n','k',0};
|
||||
static const WCHAR shortcutW[] = {'a','p','p','l','i','c','a','t','i','o','n','/','x','-','m','s','-','s','h','o','r','t','c','u','t',0};
|
||||
if (!strcmpiW(extension, lnkW))
|
||||
return "application/x-ms-shortcut";
|
||||
return xwcsdup(shortcutW);
|
||||
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(const char *desktopPath, const WCHAR *friendlyAppName,
|
||||
const WCHAR *mimeType, const WCHAR *progId,
|
||||
const WCHAR *openWithIcon)
|
||||
{
|
||||
BOOL ret = FALSE;
|
||||
FILE *desktop;
|
||||
const char *prefix = getenv("WINEPREFIX");
|
||||
const char *home = getenv("HOME");
|
||||
|
||||
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),
|
||||
wine_dbgstr_a(progId), wine_dbgstr_a(openWithIcon), wine_dbgstr_a(desktopPath));
|
||||
WINE_TRACE("friendlyAppName=%s, MIME type %s, progID=%s, icon=%s to file %s\n",
|
||||
wine_dbgstr_w(friendlyAppName), wine_dbgstr_w(mimeType),
|
||||
wine_dbgstr_w(progId), wine_dbgstr_w(openWithIcon), wine_dbgstr_a(desktopPath));
|
||||
|
||||
desktop = fopen(desktopPath, "w");
|
||||
if (desktop)
|
||||
{
|
||||
fprintf(desktop, "[Desktop Entry]\n");
|
||||
fprintf(desktop, "Type=Application\n");
|
||||
fprintf(desktop, "Name=%s\n", friendlyAppName);
|
||||
fprintf(desktop, "MimeType=%s;\n", mimeType);
|
||||
fprintf(desktop, "Name=%s\n", wchars_to_utf8_chars(friendlyAppName));
|
||||
fprintf(desktop, "MimeType=%s;\n", wchars_to_utf8_chars(mimeType));
|
||||
if (prefix)
|
||||
fprintf(desktop, "Exec=env WINEPREFIX=\"%s\" wine start /ProgIDOpen %s %%f\n", prefix, progId);
|
||||
fprintf(desktop, "Exec=env WINEPREFIX=\"%s\" wine start /ProgIDOpen %s %%f\n", prefix, escape(progId));
|
||||
else if (home)
|
||||
fprintf(desktop, "Exec=env WINEPREFIX=\"%s/.wine\" wine start /ProgIDOpen %s %%f\n", home, progId);
|
||||
fprintf(desktop, "Exec=env WINEPREFIX=\"%s/.wine\" wine start /ProgIDOpen %s %%f\n", home, escape(progId));
|
||||
else
|
||||
fprintf(desktop, "Exec=wine start /ProgIDOpen %s %%f\n", progId);
|
||||
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", openWithIcon);
|
||||
fprintf(desktop, "Icon=%s\n", wchars_to_utf8_chars(openWithIcon));
|
||||
ret = TRUE;
|
||||
fclose(desktop);
|
||||
}
|
||||
|
@ -2313,6 +2320,8 @@ static BOOL write_freedesktop_association_entry(const char *desktopPath, const c
|
|||
|
||||
static BOOL generate_associations(const char *xdg_data_home, const char *packages_dir, const char *applications_dir)
|
||||
{
|
||||
static const WCHAR wine_appW[] = {'A',' ','W','i','n','e',' ','a','p','p','l','i','c','a','t','i','o','n',0};
|
||||
static const WCHAR progidfmtW[] = {'%','s','=','>','%','s',0};
|
||||
static const WCHAR openW[] = {'o','p','e','n',0};
|
||||
struct wine_rb_tree mimeProgidTree = { winemenubuilder_rb_string_compare };
|
||||
struct list nativeMimeTypes = LIST_INIT(nativeMimeTypes);
|
||||
|
@ -2341,26 +2350,20 @@ static BOOL generate_associations(const char *xdg_data_home, const char *package
|
|||
|
||||
if (ret == ERROR_SUCCESS && extensionW[0] == '.' && !is_extension_banned(extensionW))
|
||||
{
|
||||
char *extensionA = NULL;
|
||||
WCHAR *commandW = NULL;
|
||||
WCHAR *executableW = NULL;
|
||||
char *openWithIconA = NULL;
|
||||
WCHAR *openWithIcon = NULL;
|
||||
WCHAR *friendlyDocNameW = NULL;
|
||||
char *friendlyDocNameA = NULL;
|
||||
WCHAR *iconW = NULL;
|
||||
char *iconA = NULL;
|
||||
WCHAR *contentTypeW = NULL;
|
||||
char *mimeTypeA = NULL;
|
||||
WCHAR *friendlyAppNameW = NULL;
|
||||
char *friendlyAppNameA = NULL;
|
||||
WCHAR *mimeType = NULL;
|
||||
const WCHAR *friendlyAppName;
|
||||
WCHAR *progIdW = NULL;
|
||||
char *progIdA = NULL;
|
||||
char *mimeProgId = NULL;
|
||||
WCHAR *mimeProgId = NULL;
|
||||
struct rb_string_entry *entry;
|
||||
|
||||
extensionA = wchars_to_utf8_chars(strlwrW(extensionW));
|
||||
strlwrW(extensionW);
|
||||
friendlyDocNameW = assoc_query(ASSOCSTR_FRIENDLYDOCNAME, extensionW, NULL);
|
||||
if (friendlyDocNameW) friendlyDocNameA = wchars_to_utf8_chars(friendlyDocNameW);
|
||||
|
||||
iconW = assoc_query(ASSOCSTR_DEFAULTICON, extensionW, NULL);
|
||||
|
||||
|
@ -2368,24 +2371,23 @@ 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 (!freedesktop_mime_type_for_extension(&nativeMimeTypes, extensionW, &mimeType))
|
||||
goto end;
|
||||
|
||||
if (mimeTypeA == NULL)
|
||||
if (mimeType == NULL)
|
||||
{
|
||||
static const WCHAR extW[] = {'a','p','p','l','i','c','a','t','i','o','n','/','x','-','w','i','n','e','-','e','x','t','e','n','s','i','o','n','-','%','s',0};
|
||||
if (contentTypeW != NULL && strchrW(contentTypeW, '/'))
|
||||
mimeTypeA = wchars_to_utf8_chars(contentTypeW);
|
||||
else if ((get_special_mime_type(extensionW)))
|
||||
mimeTypeA = xstrdup(get_special_mime_type(extensionW));
|
||||
else
|
||||
mimeTypeA = heap_printf("application/x-wine-extension-%s", &extensionA[1]);
|
||||
mimeType = xwcsdup(contentTypeW);
|
||||
else if (!(mimeType = get_special_mime_type(extensionW)))
|
||||
mimeType = heap_wprintf(extW, &extensionW[1]);
|
||||
|
||||
/* GNOME seems to ignore the <icon> tag in MIME packages,
|
||||
* and the default name is more intuitive anyway.
|
||||
*/
|
||||
if (iconW)
|
||||
{
|
||||
char *flattened_mime = slashes_to_minuses(mimeTypeA);
|
||||
WCHAR *flattened_mime = slashes_to_minuses(mimeType);
|
||||
int index = 0;
|
||||
WCHAR *comma = strrchrW(iconW, ',');
|
||||
if (comma)
|
||||
|
@ -2393,11 +2395,11 @@ static BOOL generate_associations(const char *xdg_data_home, const char *package
|
|||
*comma = 0;
|
||||
index = atoiW(comma + 1);
|
||||
}
|
||||
iconA = extract_icon(iconW, index, flattened_mime, FALSE);
|
||||
extract_icon(iconW, index, flattened_mime, FALSE);
|
||||
heap_free(flattened_mime);
|
||||
}
|
||||
|
||||
write_freedesktop_mime_type_entry(packages_dir, extensionA, mimeTypeA, friendlyDocNameA);
|
||||
write_freedesktop_mime_type_entry(packages_dir, extensionW, mimeType, friendlyDocNameW);
|
||||
hasChanged = TRUE;
|
||||
}
|
||||
|
||||
|
@ -2408,22 +2410,16 @@ static BOOL generate_associations(const char *xdg_data_home, const char *package
|
|||
|
||||
executableW = assoc_query(ASSOCSTR_EXECUTABLE, extensionW, openW);
|
||||
if (executableW)
|
||||
openWithIconA = compute_native_identifier(0, executableW);
|
||||
openWithIcon = compute_native_identifier(0, executableW, NULL);
|
||||
|
||||
friendlyAppNameW = assoc_query(ASSOCSTR_FRIENDLYAPPNAME, extensionW, openW);
|
||||
if (friendlyAppNameW)
|
||||
friendlyAppNameA = wchars_to_utf8_chars(friendlyAppNameW);
|
||||
else
|
||||
friendlyAppNameA = heap_printf("A Wine application");
|
||||
friendlyAppName = assoc_query(ASSOCSTR_FRIENDLYAPPNAME, extensionW, openW);
|
||||
if (!friendlyAppName) friendlyAppName = wine_appW;
|
||||
|
||||
progIdW = reg_get_valW(HKEY_CLASSES_ROOT, extensionW, NULL);
|
||||
if (progIdW)
|
||||
progIdA = escape(progIdW);
|
||||
else
|
||||
goto end; /* no progID => not a file type association */
|
||||
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_printf("%s=>%s", mimeTypeA, progIdA);
|
||||
mimeProgId = heap_wprintf(progidfmtW, mimeType, progIdW);
|
||||
if (wine_rb_get(&mimeProgidTree, mimeProgId))
|
||||
{
|
||||
heap_free(mimeProgId);
|
||||
|
@ -2437,38 +2433,28 @@ static BOOL generate_associations(const char *xdg_data_home, const char *package
|
|||
goto end;
|
||||
}
|
||||
|
||||
if (has_association_changed(extensionW, mimeTypeA, progIdW, friendlyAppNameA, openWithIconA))
|
||||
if (has_association_changed(extensionW, mimeType, progIdW, friendlyAppName, openWithIcon))
|
||||
{
|
||||
char *desktopPath = heap_printf("%s/wine-extension-%s.desktop", applications_dir, &extensionA[1]);
|
||||
if (write_freedesktop_association_entry(desktopPath, extensionA, friendlyAppNameA, mimeTypeA, progIdA, openWithIconA))
|
||||
char *desktopPath = heap_printf("%s/wine-extension-%s.desktop", applications_dir, wchars_to_utf8_chars(&extensionW[1]));
|
||||
if (write_freedesktop_association_entry(desktopPath, friendlyAppName, mimeType, progIdW, openWithIcon))
|
||||
{
|
||||
hasChanged = TRUE;
|
||||
update_association(extensionW, mimeTypeA, progIdW, friendlyAppNameA, desktopPath, openWithIconA);
|
||||
update_association(extensionW, mimeType, progIdW, friendlyAppName, desktopPath, openWithIcon);
|
||||
}
|
||||
heap_free(desktopPath);
|
||||
}
|
||||
|
||||
if (hasChanged && openWithIconA)
|
||||
{
|
||||
char *outputIconA = extract_icon(executableW, 0, openWithIconA, FALSE);
|
||||
heap_free(outputIconA);
|
||||
}
|
||||
if (hasChanged && openWithIcon) extract_icon(executableW, 0, openWithIcon, FALSE);
|
||||
|
||||
end:
|
||||
heap_free(extensionA);
|
||||
heap_free(commandW);
|
||||
heap_free(executableW);
|
||||
heap_free(openWithIconA);
|
||||
heap_free(openWithIcon);
|
||||
heap_free(friendlyDocNameW);
|
||||
heap_free(friendlyDocNameA);
|
||||
heap_free(iconW);
|
||||
heap_free(iconA);
|
||||
heap_free(contentTypeW);
|
||||
heap_free(mimeTypeA);
|
||||
heap_free(friendlyAppNameW);
|
||||
heap_free(friendlyAppNameA);
|
||||
heap_free(mimeType);
|
||||
heap_free(progIdW);
|
||||
heap_free(progIdA);
|
||||
}
|
||||
heap_free(extensionW);
|
||||
if (ret != ERROR_SUCCESS)
|
||||
|
@ -2492,7 +2478,8 @@ static char *get_start_exe_path(void)
|
|||
|
||||
static BOOL InvokeShellLinker( IShellLinkW *sl, LPCWSTR link, BOOL bWait )
|
||||
{
|
||||
char *link_name = NULL, *icon_name = NULL, *work_dir = NULL;
|
||||
WCHAR *icon_name;
|
||||
char *link_name = NULL, *work_dir = NULL;
|
||||
char *description = NULL;
|
||||
char *wmclass = NULL;
|
||||
WCHAR szTmp[INFOTIPSIZE];
|
||||
|
@ -2637,7 +2624,8 @@ cleanup:
|
|||
|
||||
static BOOL InvokeShellLinkerForURL( IUniformResourceLocatorW *url, LPCWSTR link, BOOL bWait )
|
||||
{
|
||||
char *link_name = NULL, *icon_name = NULL;
|
||||
char *link_name = NULL;
|
||||
WCHAR *icon_name = NULL;
|
||||
DWORD csidl = -1;
|
||||
LPWSTR urlPath = NULL;
|
||||
char *escaped_urlPath = NULL;
|
||||
|
@ -2701,7 +2689,7 @@ static BOOL InvokeShellLinkerForURL( IUniformResourceLocatorW *url, LPCWSTR link
|
|||
has_icon = TRUE;
|
||||
icon_name = extract_icon( pv[0].pwszVal, pv[1].iVal, NULL, bWait );
|
||||
|
||||
WINE_TRACE("URL icon path: %s icon index: %d icon name: %s\n", wine_dbgstr_w(pv[0].pwszVal), pv[1].iVal, icon_name);
|
||||
WINE_TRACE("URL icon path: %s icon index: %d icon name: %s\n", wine_dbgstr_w(pv[0].pwszVal), pv[1].iVal, debugstr_w(icon_name));
|
||||
}
|
||||
PropVariantClear(&pv[0]);
|
||||
PropVariantClear(&pv[1]);
|
||||
|
@ -3096,13 +3084,13 @@ static void thumbnail_lnk(LPCWSTR lnkPath, LPCWSTR outputPath)
|
|||
{
|
||||
hr = open_icon(szIconPath, iconId, FALSE, &stream, &pIconDirEntries, &numEntries);
|
||||
if (SUCCEEDED(hr))
|
||||
hr = write_native_icon(stream, pIconDirEntries, numEntries, utf8OutputPath, NULL);
|
||||
hr = write_native_icon(stream, pIconDirEntries, numEntries, utf8OutputPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = open_icon(szPath, iconId, FALSE, &stream, &pIconDirEntries, &numEntries);
|
||||
if (SUCCEEDED(hr))
|
||||
hr = write_native_icon(stream, pIconDirEntries, numEntries, utf8OutputPath, NULL);
|
||||
hr = write_native_icon(stream, pIconDirEntries, numEntries, utf8OutputPath);
|
||||
}
|
||||
|
||||
end:
|
||||
|
|
Loading…
Reference in New Issue