core,w32: Improve handling of Unicode paths
* src/dirinfo.c (get_gpgconf_item): Use _gpgme_access. * src/posix-util.c (_gpgme_access): Add forward to normal access. * src/sys-util.h (_gpgme_access): New for posix and w32. * src/w32-io.c (_gpgme_io_spawn): Use _gpgme_crate_process_utf8. * src/w32-util.c (utf8_to_wchar, utf8_to_wchar0): The usual w32 conv. (find_program_in_dir): Use _gpgme_access. (find_program_at_standard_place): Use wchar API and convert to UTF-8. (_gpgme_access): Convert UTF-8 to wchar and use wchar API. (_gpgme_create_process_utf8): Convert UTF-8 to wchar and use wchar API. -- While we should not say that we have full support for unicode path installations of GnuPG, this ensures that GPGME works if GPGME itself is installed in a unicode path. e.g.: Libreoffice supports this. GnuPG-Bug-Id: T4453 Based on a patch provided by Egor Pugin. Thanks.
This commit is contained in:
parent
937adfdcbb
commit
a82e3a0ae5
@ -260,7 +260,7 @@ get_gpgconf_item (int what)
|
||||
char *pgmname;
|
||||
|
||||
pgmname = dirinfo.disable_gpgconf? NULL : _gpgme_get_gpgconf_path ();
|
||||
if (pgmname && access (pgmname, F_OK))
|
||||
if (pgmname && _gpgme_access (pgmname, F_OK))
|
||||
{
|
||||
_gpgme_debug (DEBUG_INIT, -1, NULL, NULL, NULL,
|
||||
"gpgme-dinfo: gpgconf='%s' [not installed]\n", pgmname);
|
||||
|
@ -157,3 +157,10 @@ _gpgme_allow_set_foreground_window (pid_t pid)
|
||||
(void)pid;
|
||||
/* Not needed. */
|
||||
}
|
||||
|
||||
/* See w32-util.c */
|
||||
int
|
||||
_gpgme_access (const char *path, int mode)
|
||||
{
|
||||
return access (path, mode);
|
||||
}
|
||||
|
@ -28,9 +28,22 @@ int _gpgme_set_override_inst_dir (const char *dir);
|
||||
char *_gpgme_get_gpg_path (void);
|
||||
char *_gpgme_get_gpgconf_path (void);
|
||||
|
||||
int _gpgme_access (const char *path_utf8, int mode);
|
||||
|
||||
#ifdef HAVE_W32_SYSTEM
|
||||
const char *_gpgme_get_inst_dir (void);
|
||||
void _gpgme_w32_cancel_synchronous_io (HANDLE thread);
|
||||
/* See CreateProcessA returns true on success */
|
||||
int _gpgme_create_process_utf8 (const char *application_name_utf8,
|
||||
char *command_line_utf8,
|
||||
LPSECURITY_ATTRIBUTES lpProcessAttributes,
|
||||
LPSECURITY_ATTRIBUTES lpThreadAttributes,
|
||||
BOOL bInheritHandles,
|
||||
DWORD dwCreationFlags,
|
||||
void *lpEnvironment,
|
||||
char *working_directory_utf8,
|
||||
LPSTARTUPINFOA lpStartupInfo,
|
||||
LPPROCESS_INFORMATION lpProcessInformation);
|
||||
#endif
|
||||
|
||||
#endif /* SYS_UTIL_H */
|
||||
|
@ -1481,7 +1481,7 @@ _gpgme_io_spawn (const char *path, char *const argv[], unsigned int flags,
|
||||
free (tmp_name);
|
||||
return TRACE_SYSRES (-1);
|
||||
}
|
||||
if (!CreateProcessA (spawnhelper,
|
||||
if (!_gpgme_create_process_utf8 (spawnhelper,
|
||||
arg_string,
|
||||
&sec_attr, /* process security attributes */
|
||||
&sec_attr, /* thread security attributes */
|
||||
|
105
src/w32-util.c
105
src/w32-util.c
@ -168,6 +168,48 @@ wchar_to_utf8 (const wchar_t *string)
|
||||
}
|
||||
|
||||
|
||||
/* Return a malloced wide char string from an UTF-8 encoded input
|
||||
string STRING. Caller must free this value. On failure returns
|
||||
NULL; caller may use GetLastError to get the actual error number.
|
||||
Calling this function with STRING set to NULL is not defined. */
|
||||
static wchar_t *
|
||||
utf8_to_wchar (const char *string)
|
||||
{
|
||||
int n;
|
||||
wchar_t *result;
|
||||
|
||||
|
||||
n = MultiByteToWideChar (CP_UTF8, 0, string, -1, NULL, 0);
|
||||
if (n < 0)
|
||||
return NULL;
|
||||
|
||||
result = (wchar_t *) malloc ((n+1) * sizeof *result);
|
||||
if (!result)
|
||||
return NULL;
|
||||
|
||||
n = MultiByteToWideChar (CP_UTF8, 0, string, -1, result, n);
|
||||
if (n < 0)
|
||||
{
|
||||
free (result);
|
||||
return NULL;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/* Same as utf8_to_wchar but calling it with NULL returns
|
||||
NULL. So a return value of NULL only indicates failure
|
||||
if STRING is not set to NULL. */
|
||||
static wchar_t *
|
||||
utf8_to_wchar0 (const char *string)
|
||||
{
|
||||
if (!string)
|
||||
return NULL;
|
||||
|
||||
return utf8_to_wchar (string);
|
||||
}
|
||||
|
||||
|
||||
/* Replace all forward slashes by backslashes. */
|
||||
static void
|
||||
replace_slashes (char *string)
|
||||
@ -395,7 +437,7 @@ find_program_in_dir (const char *dir, const char *name)
|
||||
if (!result)
|
||||
return NULL;
|
||||
|
||||
if (access (result, F_OK))
|
||||
if (_gpgme_access (result, F_OK))
|
||||
{
|
||||
free (result);
|
||||
return NULL;
|
||||
@ -408,7 +450,7 @@ find_program_in_dir (const char *dir, const char *name)
|
||||
static char *
|
||||
find_program_at_standard_place (const char *name)
|
||||
{
|
||||
char path[MAX_PATH];
|
||||
wchar_t path[MAX_PATH];
|
||||
char *result = NULL;
|
||||
|
||||
/* See https://wiki.tcl-lang.org/page/Getting+Windows+%22special+folders%22+with+Ffidl for details on compatibility.
|
||||
@ -416,20 +458,24 @@ find_program_at_standard_place (const char *name)
|
||||
We First try the generic place and then fallback to the x86
|
||||
(i.e. 32 bit) place. This will prefer a 64 bit of the program
|
||||
over a 32 bit version on 64 bit Windows if installed. */
|
||||
if (SHGetSpecialFolderPathA (NULL, path, CSIDL_PROGRAM_FILES, 0))
|
||||
if (SHGetSpecialFolderPathW (NULL, path, CSIDL_PROGRAM_FILES, 0))
|
||||
{
|
||||
result = _gpgme_strconcat (path, "\\", name, NULL);
|
||||
if (result && access (result, F_OK))
|
||||
char *utf8_path = wchar_to_utf8 (path);
|
||||
result = _gpgme_strconcat (utf8_path, "\\", name, NULL);
|
||||
free (utf8_path);
|
||||
if (result && _gpgme_access (result, F_OK))
|
||||
{
|
||||
free (result);
|
||||
result = NULL;
|
||||
}
|
||||
}
|
||||
if (!result
|
||||
&& SHGetSpecialFolderPathA (NULL, path, CSIDL_PROGRAM_FILESX86, 0))
|
||||
&& SHGetSpecialFolderPathW (NULL, path, CSIDL_PROGRAM_FILESX86, 0))
|
||||
{
|
||||
result = _gpgme_strconcat (path, "\\", name, NULL);
|
||||
if (result && access (result, F_OK))
|
||||
char *utf8_path = wchar_to_utf8 (path);
|
||||
result = _gpgme_strconcat (utf8_path, "\\", name, NULL);
|
||||
free (utf8_path);
|
||||
if (result && _gpgme_access (result, F_OK))
|
||||
{
|
||||
free (result);
|
||||
result = NULL;
|
||||
@ -781,6 +827,49 @@ _gpgme_mkstemp (int *fd, char **name)
|
||||
}
|
||||
|
||||
|
||||
/* Like access but using windows _waccess */
|
||||
int
|
||||
_gpgme_access (const char *path, int mode)
|
||||
{
|
||||
wchar_t *u16 = utf8_to_wchar0 (path);
|
||||
int r = _waccess (u16, F_OK);
|
||||
|
||||
free(u16);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Like CreateProcessA but mapping the arguments to wchar API */
|
||||
int _gpgme_create_process_utf8 (const char *application_name_utf8,
|
||||
char *command_line_utf8,
|
||||
LPSECURITY_ATTRIBUTES lpProcessAttributes,
|
||||
LPSECURITY_ATTRIBUTES lpThreadAttributes,
|
||||
BOOL bInheritHandles,
|
||||
DWORD dwCreationFlags,
|
||||
void *lpEnvironment,
|
||||
char *working_directory_utf8,
|
||||
LPSTARTUPINFOA lpStartupInfo,
|
||||
LPPROCESS_INFORMATION lpProcessInformation)
|
||||
{
|
||||
BOOL ret;
|
||||
wchar_t *application_name = utf8_to_wchar0 (application_name_utf8);
|
||||
wchar_t *command_line = utf8_to_wchar0 (command_line_utf8);
|
||||
wchar_t *working_directory = utf8_to_wchar0 (working_directory_utf8);
|
||||
|
||||
ret = CreateProcessW (application_name,
|
||||
command_line,
|
||||
lpProcessAttributes,
|
||||
lpThreadAttributes,
|
||||
bInheritHandles,
|
||||
dwCreationFlags,
|
||||
lpEnvironment,
|
||||
working_directory,
|
||||
lpStartupInfo,
|
||||
lpProcessInformation);
|
||||
free (application_name);
|
||||
free (command_line);
|
||||
free (working_directory);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Entry point called by the DLL loader. */
|
||||
#ifdef DLL_EXPORT
|
||||
|
Loading…
Reference in New Issue
Block a user