winemenubuilder: Use Unicode strings to write desktop entries.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
41881ff625
commit
d4a773a1d7
|
@ -1403,44 +1403,105 @@ static DWORD register_menus_entry(const char *unix_file, const WCHAR *windows_fi
|
|||
return ret;
|
||||
}
|
||||
|
||||
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 WCHAR *icon, const char *wmclass)
|
||||
/* This escapes reserved characters in .desktop files' Exec keys. */
|
||||
static LPSTR escape(LPCWSTR arg)
|
||||
{
|
||||
int i, j;
|
||||
WCHAR *escaped_string;
|
||||
char *utf8_string;
|
||||
|
||||
escaped_string = xmalloc((4 * strlenW(arg) + 1) * sizeof(WCHAR));
|
||||
for (i = j = 0; arg[i]; i++)
|
||||
{
|
||||
switch (arg[i])
|
||||
{
|
||||
case '\\':
|
||||
escaped_string[j++] = '\\';
|
||||
escaped_string[j++] = '\\';
|
||||
escaped_string[j++] = '\\';
|
||||
escaped_string[j++] = '\\';
|
||||
break;
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\n':
|
||||
case '"':
|
||||
case '\'':
|
||||
case '>':
|
||||
case '<':
|
||||
case '~':
|
||||
case '|':
|
||||
case '&':
|
||||
case ';':
|
||||
case '$':
|
||||
case '*':
|
||||
case '?':
|
||||
case '#':
|
||||
case '(':
|
||||
case ')':
|
||||
case '`':
|
||||
escaped_string[j++] = '\\';
|
||||
escaped_string[j++] = '\\';
|
||||
/* fall through */
|
||||
default:
|
||||
escaped_string[j++] = arg[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
escaped_string[j] = 0;
|
||||
utf8_string = wchars_to_utf8_chars(escaped_string);
|
||||
heap_free(escaped_string);
|
||||
return utf8_string;
|
||||
}
|
||||
|
||||
static BOOL write_desktop_entry(const WCHAR *link, const char *location, const WCHAR *linkname,
|
||||
const WCHAR *path, const WCHAR *args, const WCHAR *descr,
|
||||
const WCHAR *workdir, const WCHAR *icon, const WCHAR *wmclass)
|
||||
{
|
||||
FILE *file;
|
||||
char *workdir_unix;
|
||||
char *dest_name = NULL;
|
||||
const char *name;
|
||||
const char *prefix = getenv("WINEPREFIX");
|
||||
const char *home = getenv("HOME");
|
||||
|
||||
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_w(icon),
|
||||
wine_dbgstr_a(wmclass));
|
||||
wine_dbgstr_w(linkname), wine_dbgstr_w(path), wine_dbgstr_w(args),
|
||||
wine_dbgstr_w(descr), wine_dbgstr_w(workdir), wine_dbgstr_w(icon),
|
||||
wine_dbgstr_w(wmclass));
|
||||
|
||||
name = wchars_to_utf8_chars( PathFindFileNameW( linkname ));
|
||||
|
||||
if (!location) location = dest_name = heap_printf("%s/%s.desktop", xdg_desktop_dir, name);
|
||||
|
||||
file = fopen(location, "w");
|
||||
if (file == NULL)
|
||||
return FALSE;
|
||||
|
||||
fprintf(file, "[Desktop Entry]\n");
|
||||
fprintf(file, "Name=%s\n", linkname);
|
||||
fprintf(file, "Name=%s\n", name);
|
||||
fprintf(file, "Exec=" );
|
||||
if (prefix)
|
||||
fprintf(file, "Exec=env WINEPREFIX=\"%s\" wine %s %s\n", prefix, path, args);
|
||||
fprintf(file, "env WINEPREFIX=\"%s\" ", prefix);
|
||||
else if (home)
|
||||
fprintf(file, "Exec=env WINEPREFIX=\"%s/.wine\" wine %s %s\n", home, path, args);
|
||||
else
|
||||
fprintf(file, "Exec=wine %s %s\n", path, args);
|
||||
fprintf(file, "env WINEPREFIX=\"%s/.wine\" ", home);
|
||||
fprintf(file, "wine %s", escape(path));
|
||||
if (args) fprintf(file, " %s", escape(args) );
|
||||
fputc( '\n', file );
|
||||
fprintf(file, "Type=Application\n");
|
||||
fprintf(file, "StartupNotify=true\n");
|
||||
if (descr && *descr)
|
||||
fprintf(file, "Comment=%s\n", descr);
|
||||
if (workdir && *workdir)
|
||||
fprintf(file, "Path=%s\n", workdir);
|
||||
fprintf(file, "Comment=%s\n", wchars_to_utf8_chars(descr));
|
||||
if (workdir && *workdir && (workdir_unix = wine_get_unix_file_name(workdir)))
|
||||
fprintf(file, "Path=%s\n", workdir_unix);
|
||||
if (icon && *icon)
|
||||
fprintf(file, "Icon=%s\n", wchars_to_utf8_chars(icon));
|
||||
if (wmclass && *wmclass)
|
||||
fprintf(file, "StartupWMClass=%s\n", wmclass);
|
||||
fprintf(file, "StartupWMClass=%s\n", wchars_to_utf8_chars(wmclass));
|
||||
|
||||
fclose(file);
|
||||
|
||||
if (dest_name) chmod( dest_name, 0755 );
|
||||
|
||||
if (link)
|
||||
{
|
||||
DWORD ret = register_menus_entry(location, link);
|
||||
|
@ -1574,26 +1635,23 @@ end:
|
|||
return ret;
|
||||
}
|
||||
|
||||
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 WCHAR *icon, const char *wmclass)
|
||||
static BOOL write_menu_entry(const WCHAR *windows_link, const WCHAR *link, const WCHAR *path, const WCHAR *args,
|
||||
const WCHAR *descr, const WCHAR *workdir, const WCHAR *icon, const WCHAR *wmclass)
|
||||
{
|
||||
const char *linkname;
|
||||
char *linkname, *p;
|
||||
char *desktopPath = NULL;
|
||||
char *desktopDir;
|
||||
char *filename = NULL;
|
||||
BOOL ret = TRUE;
|
||||
|
||||
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_w(icon), wine_dbgstr_a(wmclass));
|
||||
WINE_TRACE("(%s, %s, %s, %s, %s, %s, %s, %s)\n", wine_dbgstr_w(windows_link), wine_dbgstr_w(link),
|
||||
wine_dbgstr_w(path), wine_dbgstr_w(args), wine_dbgstr_w(descr),
|
||||
wine_dbgstr_w(workdir), wine_dbgstr_w(icon), wine_dbgstr_w(wmclass));
|
||||
|
||||
linkname = strrchr(link, '/');
|
||||
if (linkname == NULL)
|
||||
linkname = link;
|
||||
else
|
||||
++linkname;
|
||||
linkname = wchars_to_unix_chars( link );
|
||||
for (p = linkname; *p; p++) if (*p == '\\') *p = '/';
|
||||
|
||||
desktopPath = heap_printf("%s/applications/wine/%s.desktop", xdg_data_dir, link);
|
||||
desktopPath = heap_printf("%s/applications/wine/%s.desktop", xdg_data_dir, linkname);
|
||||
desktopDir = strrchr(desktopPath, '/');
|
||||
*desktopDir = 0;
|
||||
if (!create_directories(desktopPath))
|
||||
|
@ -1603,14 +1661,14 @@ static BOOL write_menu_entry(const WCHAR *windows_link, const char *link, const
|
|||
goto end;
|
||||
}
|
||||
*desktopDir = '/';
|
||||
if (!write_desktop_entry(windows_link, desktopPath, linkname, path, args, descr, workdir, icon, wmclass))
|
||||
if (!write_desktop_entry(windows_link, desktopPath, link, path, args, descr, workdir, icon, wmclass))
|
||||
{
|
||||
WINE_WARN("couldn't make desktop entry %s\n", wine_dbgstr_a(desktopPath));
|
||||
ret = FALSE;
|
||||
goto end;
|
||||
}
|
||||
|
||||
filename = heap_printf("wine/%s.desktop", link);
|
||||
filename = heap_printf("wine/%s.desktop", linkname);
|
||||
if (!write_menu_file(windows_link, filename))
|
||||
{
|
||||
WINE_WARN("couldn't make menu file %s\n", wine_dbgstr_a(filename));
|
||||
|
@ -1623,108 +1681,18 @@ end:
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* This escapes reserved characters in .desktop files' Exec keys. */
|
||||
static LPSTR escape(LPCWSTR arg)
|
||||
{
|
||||
int i, j;
|
||||
WCHAR *escaped_string;
|
||||
char *utf8_string;
|
||||
|
||||
escaped_string = xmalloc((4 * strlenW(arg) + 1) * sizeof(WCHAR));
|
||||
for (i = j = 0; arg[i]; i++)
|
||||
{
|
||||
switch (arg[i])
|
||||
{
|
||||
case '\\':
|
||||
escaped_string[j++] = '\\';
|
||||
escaped_string[j++] = '\\';
|
||||
escaped_string[j++] = '\\';
|
||||
escaped_string[j++] = '\\';
|
||||
break;
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\n':
|
||||
case '"':
|
||||
case '\'':
|
||||
case '>':
|
||||
case '<':
|
||||
case '~':
|
||||
case '|':
|
||||
case '&':
|
||||
case ';':
|
||||
case '$':
|
||||
case '*':
|
||||
case '?':
|
||||
case '#':
|
||||
case '(':
|
||||
case ')':
|
||||
case '`':
|
||||
escaped_string[j++] = '\\';
|
||||
escaped_string[j++] = '\\';
|
||||
/* fall through */
|
||||
default:
|
||||
escaped_string[j++] = arg[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
escaped_string[j] = 0;
|
||||
utf8_string = wchars_to_utf8_chars(escaped_string);
|
||||
heap_free(escaped_string);
|
||||
return utf8_string;
|
||||
}
|
||||
|
||||
/* Return a heap-allocated copy of the unix format difference between the two
|
||||
* Windows-format paths.
|
||||
* locn is the owning location
|
||||
* link is within locn
|
||||
*/
|
||||
static char *relative_path( LPCWSTR link, LPCWSTR locn )
|
||||
{
|
||||
char *unix_locn, *unix_link;
|
||||
char *relative = NULL;
|
||||
|
||||
unix_locn = wine_get_unix_file_name(locn);
|
||||
unix_link = wine_get_unix_file_name(link);
|
||||
if (unix_locn && unix_link)
|
||||
{
|
||||
size_t len_unix_locn, len_unix_link;
|
||||
len_unix_locn = strlen (unix_locn);
|
||||
len_unix_link = strlen (unix_link);
|
||||
if (len_unix_locn < len_unix_link && memcmp (unix_locn, unix_link, len_unix_locn) == 0 && unix_link[len_unix_locn] == '/')
|
||||
{
|
||||
size_t len_rel;
|
||||
char *p = strrchr (unix_link + len_unix_locn, '/');
|
||||
p = strrchr (p, '.');
|
||||
if (p)
|
||||
{
|
||||
*p = '\0';
|
||||
len_unix_link = p - unix_link;
|
||||
}
|
||||
len_rel = len_unix_link - len_unix_locn;
|
||||
relative = xmalloc(len_rel);
|
||||
memcpy (relative, unix_link + len_unix_locn + 1, len_rel);
|
||||
}
|
||||
}
|
||||
if (!relative)
|
||||
WINE_WARN("Could not separate the relative link path of %s in %s\n", wine_dbgstr_w(link), wine_dbgstr_w(locn));
|
||||
heap_free(unix_locn);
|
||||
heap_free(unix_link);
|
||||
return relative;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* GetLinkLocation
|
||||
* get_link_location
|
||||
*
|
||||
* returns TRUE if successful
|
||||
* *loc will contain CS_DESKTOPDIRECTORY, CS_STARTMENU, CS_STARTUP etc.
|
||||
* *relative will contain the address of a heap-allocated copy of the portion
|
||||
* of the filename that is within the specified location, in unix form
|
||||
*/
|
||||
static BOOL GetLinkLocation( LPCWSTR linkfile, DWORD *loc, char **relative )
|
||||
static BOOL get_link_location( LPCWSTR linkfile, DWORD *loc, WCHAR **relative )
|
||||
{
|
||||
WCHAR filename[MAX_PATH], shortfilename[MAX_PATH], buffer[MAX_PATH];
|
||||
DWORD len, i, r, filelen;
|
||||
DWORD len, i, filelen;
|
||||
const DWORD locations[] = {
|
||||
CSIDL_STARTUP, CSIDL_DESKTOPDIRECTORY, CSIDL_STARTMENU,
|
||||
CSIDL_COMMON_STARTUP, CSIDL_COMMON_DESKTOPDIRECTORY,
|
||||
|
@ -1757,17 +1725,13 @@ static BOOL GetLinkLocation( LPCWSTR linkfile, DWORD *loc, char **relative )
|
|||
|
||||
if (len > filelen || filename[len]!='\\')
|
||||
continue;
|
||||
/* do a lstrcmpinW */
|
||||
filename[len] = 0;
|
||||
r = lstrcmpiW( filename, buffer );
|
||||
filename[len] = '\\';
|
||||
if ( r )
|
||||
continue;
|
||||
if (strncmpiW( filename, buffer, len )) continue;
|
||||
|
||||
/* return the remainder of the string and link type */
|
||||
*loc = locations[i];
|
||||
*relative = relative_path (filename, buffer);
|
||||
return (*relative != NULL);
|
||||
*relative = xwcsdup( filename + len + 1 );
|
||||
PathRemoveExtensionW( *relative );
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
|
@ -2466,22 +2430,9 @@ static BOOL generate_associations(const char *xdg_data_home, const char *package
|
|||
return hasChanged;
|
||||
}
|
||||
|
||||
static char *get_start_exe_path(void)
|
||||
{
|
||||
static const WCHAR startW[] = {'\\','c','o','m','m','a','n','d',
|
||||
'\\','s','t','a','r','t','.','e','x','e',0};
|
||||
WCHAR start_path[MAX_PATH];
|
||||
GetWindowsDirectoryW(start_path, MAX_PATH);
|
||||
lstrcatW(start_path, startW);
|
||||
return escape(start_path);
|
||||
}
|
||||
|
||||
static BOOL InvokeShellLinker( IShellLinkW *sl, LPCWSTR link, BOOL bWait )
|
||||
{
|
||||
WCHAR *icon_name;
|
||||
char *link_name = NULL, *work_dir = NULL;
|
||||
char *description = NULL;
|
||||
char *wmclass = NULL;
|
||||
WCHAR *icon_name, *link_name;
|
||||
WCHAR szTmp[INFOTIPSIZE];
|
||||
WCHAR szDescription[INFOTIPSIZE], szPath[MAX_PATH], szWorkDir[MAX_PATH];
|
||||
WCHAR szArgs[INFOTIPSIZE], szIconPath[MAX_PATH], szWMClass[MAX_PATH];
|
||||
|
@ -2495,7 +2446,7 @@ static BOOL InvokeShellLinker( IShellLinkW *sl, LPCWSTR link, BOOL bWait )
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
if( !GetLinkLocation( link, &csidl, &link_name ) )
|
||||
if( !get_link_location( link, &csidl, &link_name ) )
|
||||
{
|
||||
WINE_WARN("Unknown link location %s. Ignoring.\n",wine_dbgstr_w(link));
|
||||
return TRUE;
|
||||
|
@ -2505,7 +2456,7 @@ static BOOL InvokeShellLinker( IShellLinkW *sl, LPCWSTR link, BOOL bWait )
|
|||
WINE_WARN("Not under desktop or start menu. Ignoring.\n");
|
||||
return TRUE;
|
||||
}
|
||||
WINE_TRACE("Link : %s\n", wine_dbgstr_a(link_name));
|
||||
WINE_TRACE("Link : %s\n", wine_dbgstr_w(link_name));
|
||||
|
||||
szTmp[0] = 0;
|
||||
IShellLinkW_GetWorkingDirectory( sl, szTmp, MAX_PATH );
|
||||
|
@ -2566,15 +2517,8 @@ static BOOL InvokeShellLinker( IShellLinkW *sl, LPCWSTR link, BOOL bWait )
|
|||
lstrcpyW(szWMClass, p);
|
||||
CharLowerW(szWMClass);
|
||||
}
|
||||
|
||||
/* convert app working dir */
|
||||
if (szWorkDir[0])
|
||||
work_dir = wine_get_unix_file_name( szWorkDir );
|
||||
}
|
||||
|
||||
description = wchars_to_utf8_chars(szDescription);
|
||||
wmclass = wchars_to_utf8_chars(szWMClass);
|
||||
|
||||
/* building multiple menus concurrently has race conditions */
|
||||
hsem = CreateSemaphoreA( NULL, 1, 1, "winemenubuilder_semaphore");
|
||||
if( WAIT_OBJECT_0 != MsgWaitForMultipleObjects( 1, &hsem, FALSE, INFINITE, QS_ALLINPUT ) )
|
||||
|
@ -2585,36 +2529,22 @@ static BOOL InvokeShellLinker( IShellLinkW *sl, LPCWSTR link, BOOL bWait )
|
|||
|
||||
if (in_desktop_dir(csidl))
|
||||
{
|
||||
char *location;
|
||||
const char *lastEntry;
|
||||
lastEntry = strrchr(link_name, '/');
|
||||
if (lastEntry == NULL)
|
||||
lastEntry = link_name;
|
||||
else
|
||||
++lastEntry;
|
||||
location = heap_printf("%s/%s.desktop", xdg_desktop_dir, lastEntry);
|
||||
if (csidl == CSIDL_COMMON_DESKTOPDIRECTORY || !szPath[0])
|
||||
r = !write_desktop_entry(link, location, lastEntry, escape(link), "",
|
||||
description, work_dir, icon_name, wmclass);
|
||||
r = !write_desktop_entry(link, NULL, link_name, link, NULL,
|
||||
szDescription, szWorkDir, icon_name, szWMClass);
|
||||
else
|
||||
r = !write_desktop_entry(NULL, location, lastEntry, escape(szPath), escape(szArgs), description, work_dir, icon_name, wmclass);
|
||||
if (r == 0)
|
||||
chmod(location, 0755);
|
||||
heap_free(location);
|
||||
r = !write_desktop_entry(NULL, NULL, link_name, szPath, szArgs,
|
||||
szDescription, szWorkDir, icon_name, szWMClass);
|
||||
}
|
||||
else
|
||||
r = !write_menu_entry(link, link_name, escape(link), "",
|
||||
description, work_dir, icon_name, wmclass);
|
||||
r = !write_menu_entry(link, link_name, link, NULL, szDescription, szWorkDir, icon_name, szWMClass);
|
||||
|
||||
ReleaseSemaphore( hsem, 1, NULL );
|
||||
|
||||
cleanup:
|
||||
if (hsem) CloseHandle( hsem );
|
||||
heap_free(icon_name );
|
||||
heap_free(work_dir );
|
||||
heap_free(link_name );
|
||||
heap_free(description );
|
||||
heap_free(wmclass );
|
||||
|
||||
if (r && !bWait)
|
||||
WINE_ERR("failed to build the menu\n" );
|
||||
|
@ -2624,11 +2554,10 @@ cleanup:
|
|||
|
||||
static BOOL InvokeShellLinkerForURL( IUniformResourceLocatorW *url, LPCWSTR link, BOOL bWait )
|
||||
{
|
||||
char *link_name = NULL;
|
||||
WCHAR *icon_name = NULL;
|
||||
static const WCHAR startW[] = {'s','t','a','r','t','.','e','x','e',0};
|
||||
WCHAR *link_name, *icon_name = NULL;
|
||||
DWORD csidl = -1;
|
||||
LPWSTR urlPath = NULL;
|
||||
char *escaped_urlPath = NULL;
|
||||
HRESULT hr;
|
||||
HANDLE hSem = NULL;
|
||||
BOOL ret = TRUE;
|
||||
|
@ -2637,7 +2566,6 @@ static BOOL InvokeShellLinkerForURL( IUniformResourceLocatorW *url, LPCWSTR link
|
|||
IPropertyStorage *pPropStg;
|
||||
PROPSPEC ps[2];
|
||||
PROPVARIANT pv[2];
|
||||
char *start_path = NULL;
|
||||
BOOL has_icon = FALSE;
|
||||
|
||||
if ( !link )
|
||||
|
@ -2646,7 +2574,7 @@ static BOOL InvokeShellLinkerForURL( IUniformResourceLocatorW *url, LPCWSTR link
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
if( !GetLinkLocation( link, &csidl, &link_name ) )
|
||||
if( !get_link_location( link, &csidl, &link_name ) )
|
||||
{
|
||||
WINE_WARN("Unknown link location %s. Ignoring.\n",wine_dbgstr_w(link));
|
||||
return TRUE;
|
||||
|
@ -2657,7 +2585,7 @@ static BOOL InvokeShellLinkerForURL( IUniformResourceLocatorW *url, LPCWSTR link
|
|||
ret = TRUE;
|
||||
goto cleanup;
|
||||
}
|
||||
WINE_TRACE("Link : %s\n", wine_dbgstr_a(link_name));
|
||||
WINE_TRACE("Link : %s\n", wine_dbgstr_w(link_name));
|
||||
|
||||
hr = url->lpVtbl->GetURL(url, &urlPath);
|
||||
if (FAILED(hr))
|
||||
|
@ -2667,9 +2595,6 @@ static BOOL InvokeShellLinkerForURL( IUniformResourceLocatorW *url, LPCWSTR link
|
|||
}
|
||||
WINE_TRACE("path : %s\n", wine_dbgstr_w(urlPath));
|
||||
|
||||
escaped_urlPath = escape(urlPath);
|
||||
start_path = get_start_exe_path();
|
||||
|
||||
ps[0].ulKind = PRSPEC_PROPID;
|
||||
ps[0].u.propid = PID_IS_ICONFILE;
|
||||
ps[1].ulKind = PRSPEC_PROPID;
|
||||
|
@ -2719,22 +2644,9 @@ static BOOL InvokeShellLinkerForURL( IUniformResourceLocatorW *url, LPCWSTR link
|
|||
goto cleanup;
|
||||
}
|
||||
if (in_desktop_dir(csidl))
|
||||
{
|
||||
char *location;
|
||||
const char *lastEntry;
|
||||
lastEntry = strrchr(link_name, '/');
|
||||
if (lastEntry == NULL)
|
||||
lastEntry = link_name;
|
||||
else
|
||||
++lastEntry;
|
||||
location = heap_printf("%s/%s.desktop", xdg_desktop_dir, lastEntry);
|
||||
r = !write_desktop_entry(NULL, location, lastEntry, start_path, escaped_urlPath, NULL, NULL, icon_name, NULL);
|
||||
if (r == 0)
|
||||
chmod(location, 0755);
|
||||
heap_free(location);
|
||||
}
|
||||
r = !write_desktop_entry(NULL, NULL, link_name, startW, urlPath, NULL, NULL, icon_name, NULL);
|
||||
else
|
||||
r = !write_menu_entry(link, link_name, start_path, escaped_urlPath, NULL, NULL, icon_name, NULL);
|
||||
r = !write_menu_entry(link, link_name, startW, urlPath, NULL, NULL, icon_name, NULL);
|
||||
ret = (r == 0);
|
||||
ReleaseSemaphore(hSem, 1, NULL);
|
||||
|
||||
|
@ -2744,7 +2656,6 @@ cleanup:
|
|||
heap_free(icon_name );
|
||||
heap_free(link_name);
|
||||
CoTaskMemFree( urlPath );
|
||||
heap_free(escaped_urlPath);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue