Change gpgme-w32-spawn to unicode
* src/Makefile.am (gpgme_w32spawn_CFLAGS): Add -municode. * src/gpgme-w32-spawn.c (build_commandline, my_spawn) (translate_handles): Convert to wchar_t API. (main): Use wmain instead. -- Some time ago we introduced an inconsistency that w32-util called gpgme-w32-spawn through CreateProcessW but since gpgme-w32-spawn internally worked with 8 bit the chars were mangled and the arguments not passed correctly through the CreateProcessA of the child process. Since the GnuPG processes use GetCommandLineW this is the proper way to pass on Unicode command line arguments. Please note that we did not pass UTF-8 before this patch but rather some broken native encoding where Windows replaces unicode characters with question marks etc. GnuPG-Bug-Id: T6728
This commit is contained in:
parent
8faaf7b72b
commit
a0a4cd411c
@ -120,6 +120,8 @@ if HAVE_W32_SYSTEM
|
|||||||
# wrapper process.
|
# wrapper process.
|
||||||
libexec_PROGRAMS = gpgme-w32spawn
|
libexec_PROGRAMS = gpgme-w32spawn
|
||||||
|
|
||||||
|
gpgme_w32spawn_CFLAGS = -municode
|
||||||
|
|
||||||
RCCOMPILE = $(RC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES)
|
RCCOMPILE = $(RC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES)
|
||||||
LTRCCOMPILE = $(LIBTOOL) --mode=compile --tag=RC $(RCCOMPILE)
|
LTRCCOMPILE = $(LIBTOOL) --mode=compile --tag=RC $(RCCOMPILE)
|
||||||
|
|
||||||
|
@ -54,13 +54,13 @@ static FILE *mystderr;
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static char *
|
static wchar_t *
|
||||||
build_commandline (char **argv)
|
build_commandline (wchar_t **argv)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int n = 0;
|
int n = 0;
|
||||||
char *buf;
|
wchar_t *buf;
|
||||||
char *p;
|
wchar_t *p;
|
||||||
|
|
||||||
/* We have to quote some things because under Windows the program
|
/* We have to quote some things because under Windows the program
|
||||||
parses the commandline and does some unquoting. We enclose the
|
parses the commandline and does some unquoting. We enclose the
|
||||||
@ -75,7 +75,7 @@ build_commandline (char **argv)
|
|||||||
while (*p)
|
while (*p)
|
||||||
{
|
{
|
||||||
/* An extra one for each literal that must be escaped. */
|
/* An extra one for each literal that must be escaped. */
|
||||||
if (*p == '\\' || *p == '"')
|
if (*p == L'\\' || *p == L'"')
|
||||||
n++;
|
n++;
|
||||||
n++;
|
n++;
|
||||||
p++;
|
p++;
|
||||||
@ -86,22 +86,22 @@ build_commandline (char **argv)
|
|||||||
/* And a trailing zero. */
|
/* And a trailing zero. */
|
||||||
n++;
|
n++;
|
||||||
|
|
||||||
buf = p = malloc (n);
|
buf = p = malloc (n * sizeof (wchar_t));
|
||||||
if (!buf)
|
if (!buf)
|
||||||
return NULL;
|
return NULL;
|
||||||
for (i = 0; argv[i]; i++)
|
for (i = 0; argv[i]; i++)
|
||||||
{
|
{
|
||||||
char *argvp = argv[i];
|
wchar_t *argvp = argv[i];
|
||||||
|
|
||||||
*(p++) = '"';
|
*(p++) = L'"';
|
||||||
while (*argvp)
|
while (*argvp)
|
||||||
{
|
{
|
||||||
if (*argvp == '\\' || *argvp == '"')
|
if (*argvp == L'\\' || *argvp == L'"')
|
||||||
*(p++) = '\\';
|
*(p++) = L'\\';
|
||||||
*(p++) = *(argvp++);
|
*(p++) = *(argvp++);
|
||||||
}
|
}
|
||||||
*(p++) = '"';
|
*(p++) = L'"';
|
||||||
*(p++) = ' ';
|
*(p++) = L' ';
|
||||||
}
|
}
|
||||||
*(p++) = 0;
|
*(p++) = 0;
|
||||||
|
|
||||||
@ -110,7 +110,7 @@ build_commandline (char **argv)
|
|||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
my_spawn (char **argv, struct spawn_fd_item_s *fd_list, unsigned int flags)
|
my_spawn (wchar_t **argv, struct spawn_fd_item_s *fd_list, unsigned int flags)
|
||||||
{
|
{
|
||||||
SECURITY_ATTRIBUTES sec_attr;
|
SECURITY_ATTRIBUTES sec_attr;
|
||||||
PROCESS_INFORMATION pi =
|
PROCESS_INFORMATION pi =
|
||||||
@ -120,12 +120,11 @@ my_spawn (char **argv, struct spawn_fd_item_s *fd_list, unsigned int flags)
|
|||||||
0, /* returns pid */
|
0, /* returns pid */
|
||||||
0 /* returns tid */
|
0 /* returns tid */
|
||||||
};
|
};
|
||||||
STARTUPINFO si;
|
STARTUPINFOW si;
|
||||||
char *envblock = NULL;
|
|
||||||
int cr_flags = CREATE_DEFAULT_ERROR_MODE
|
int cr_flags = CREATE_DEFAULT_ERROR_MODE
|
||||||
| GetPriorityClass (GetCurrentProcess ());
|
| GetPriorityClass (GetCurrentProcess ());
|
||||||
int i;
|
int i;
|
||||||
char *arg_string;
|
wchar_t *arg_string;
|
||||||
int duped_stdin = 0;
|
int duped_stdin = 0;
|
||||||
int duped_stdout = 0;
|
int duped_stdout = 0;
|
||||||
int duped_stderr = 0;
|
int duped_stderr = 0;
|
||||||
@ -134,7 +133,7 @@ my_spawn (char **argv, struct spawn_fd_item_s *fd_list, unsigned int flags)
|
|||||||
i = 0;
|
i = 0;
|
||||||
while (argv[i])
|
while (argv[i])
|
||||||
{
|
{
|
||||||
fprintf (mystderr, PGM": argv[%2i] = %s\n", i, argv[i]);
|
fprintf (mystderr, PGM": argv[%2i] = %S\n", i, argv[i]);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,7 +183,7 @@ my_spawn (char **argv, struct spawn_fd_item_s *fd_list, unsigned int flags)
|
|||||||
memset (&sa, 0, sizeof sa);
|
memset (&sa, 0, sizeof sa);
|
||||||
sa.nLength = sizeof sa;
|
sa.nLength = sizeof sa;
|
||||||
sa.bInheritHandle = TRUE;
|
sa.bInheritHandle = TRUE;
|
||||||
hnul = CreateFile ("nul",
|
hnul = CreateFileW (L"nul",
|
||||||
GENERIC_READ|GENERIC_WRITE,
|
GENERIC_READ|GENERIC_WRITE,
|
||||||
FILE_SHARE_READ|FILE_SHARE_WRITE,
|
FILE_SHARE_READ|FILE_SHARE_WRITE,
|
||||||
&sa,
|
&sa,
|
||||||
@ -210,13 +209,13 @@ my_spawn (char **argv, struct spawn_fd_item_s *fd_list, unsigned int flags)
|
|||||||
}
|
}
|
||||||
|
|
||||||
cr_flags |= CREATE_SUSPENDED;
|
cr_flags |= CREATE_SUSPENDED;
|
||||||
if (!CreateProcessA (argv[0],
|
if (!CreateProcessW (argv[0],
|
||||||
arg_string,
|
arg_string,
|
||||||
&sec_attr, /* process security attributes */
|
&sec_attr, /* process security attributes */
|
||||||
&sec_attr, /* thread security attributes */
|
&sec_attr, /* thread security attributes */
|
||||||
TRUE, /* inherit handles */
|
TRUE, /* inherit handles */
|
||||||
cr_flags, /* creation flags */
|
cr_flags, /* creation flags */
|
||||||
envblock, /* environment */
|
NULL, /* environment */
|
||||||
NULL, /* use current drive/directory */
|
NULL, /* use current drive/directory */
|
||||||
&si, /* startup information */
|
&si, /* startup information */
|
||||||
&pi)) /* returns process information */
|
&pi)) /* returns process information */
|
||||||
@ -247,7 +246,7 @@ my_spawn (char **argv, struct spawn_fd_item_s *fd_list, unsigned int flags)
|
|||||||
{
|
{
|
||||||
/* Available since W2000; thus we dynload it. */
|
/* Available since W2000; thus we dynload it. */
|
||||||
initialized = 1;
|
initialized = 1;
|
||||||
handle = LoadLibrary ("user32.dll");
|
handle = LoadLibraryA ("user32.dll");
|
||||||
if (handle)
|
if (handle)
|
||||||
{
|
{
|
||||||
func = GetProcAddress (handle, "AllowSetForegroundWindow");
|
func = GetProcAddress (handle, "AllowSetForegroundWindow");
|
||||||
@ -275,7 +274,7 @@ my_spawn (char **argv, struct spawn_fd_item_s *fd_list, unsigned int flags)
|
|||||||
#define MAX_TRANS 10
|
#define MAX_TRANS 10
|
||||||
|
|
||||||
int
|
int
|
||||||
translate_get_from_file (const char *trans_file,
|
translate_get_from_file (const wchar_t *trans_file,
|
||||||
struct spawn_fd_item_s *fd_list,
|
struct spawn_fd_item_s *fd_list,
|
||||||
unsigned int *r_flags)
|
unsigned int *r_flags)
|
||||||
{
|
{
|
||||||
@ -292,7 +291,7 @@ translate_get_from_file (const char *trans_file,
|
|||||||
|
|
||||||
*r_flags = 0;
|
*r_flags = 0;
|
||||||
|
|
||||||
fd = open (trans_file, O_RDONLY);
|
fd = _wopen (trans_file, O_RDONLY);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@ -389,14 +388,14 @@ translate_get_from_file (const char *trans_file,
|
|||||||
/* Read the translated handles from TRANS_FILE and do a substitution
|
/* Read the translated handles from TRANS_FILE and do a substitution
|
||||||
in ARGV. Returns the new argv and the list of substitutions in
|
in ARGV. Returns the new argv and the list of substitutions in
|
||||||
FD_LIST (which must be MAX_TRANS+1 large). */
|
FD_LIST (which must be MAX_TRANS+1 large). */
|
||||||
char **
|
wchar_t **
|
||||||
translate_handles (const char *trans_file, const char * const *argv,
|
translate_handles (const wchar_t *trans_file, const wchar_t * const *argv,
|
||||||
struct spawn_fd_item_s *fd_list, unsigned int *r_flags)
|
struct spawn_fd_item_s *fd_list, unsigned int *r_flags)
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
int idx;
|
int idx;
|
||||||
int n_args;
|
int n_args;
|
||||||
char **args;
|
wchar_t **args;
|
||||||
|
|
||||||
res = translate_get_from_file (trans_file, fd_list, r_flags);
|
res = translate_get_from_file (trans_file, fd_list, r_flags);
|
||||||
if (res < 0)
|
if (res < 0)
|
||||||
@ -407,7 +406,7 @@ translate_handles (const char *trans_file, const char * const *argv,
|
|||||||
args = malloc (sizeof (*args) * (idx + 1));
|
args = malloc (sizeof (*args) * (idx + 1));
|
||||||
for (idx = 0; argv[idx]; idx++)
|
for (idx = 0; argv[idx]; idx++)
|
||||||
{
|
{
|
||||||
args[idx] = strdup (argv[idx]);
|
args[idx] = wcsdup (argv[idx]);
|
||||||
if (!args[idx])
|
if (!args[idx])
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -416,7 +415,7 @@ translate_handles (const char *trans_file, const char * const *argv,
|
|||||||
|
|
||||||
for (idx = 0; fd_list[idx].fd != -1; idx++)
|
for (idx = 0; fd_list[idx].fd != -1; idx++)
|
||||||
{
|
{
|
||||||
char buf[25];
|
wchar_t buf[25];
|
||||||
int aidx;
|
int aidx;
|
||||||
|
|
||||||
aidx = fd_list[idx].arg_loc;
|
aidx = fd_list[idx].arg_loc;
|
||||||
@ -439,20 +438,27 @@ translate_handles (const char *trans_file, const char * const *argv,
|
|||||||
/* NOTE: Here is the part where application specific knowledge
|
/* NOTE: Here is the part where application specific knowledge
|
||||||
comes in. GPGME/GnuPG uses two forms of descriptor
|
comes in. GPGME/GnuPG uses two forms of descriptor
|
||||||
specification, a plain number and a "-&" form. */
|
specification, a plain number and a "-&" form. */
|
||||||
if (argv[aidx][0] == '-' && argv[aidx][1] == '&')
|
if (argv[aidx][0] == L'-' && argv[aidx][1] == L'&')
|
||||||
snprintf (args[aidx], sizeof (buf), "-&%d", fd_list[idx].peer_name);
|
snwprintf (args[aidx], sizeof (buf), L"-&%d", fd_list[idx].peer_name);
|
||||||
else
|
else
|
||||||
snprintf (args[aidx], sizeof (buf), "%d", fd_list[idx].peer_name);
|
snwprintf (args[aidx], sizeof (buf), L"%d", fd_list[idx].peer_name);
|
||||||
}
|
}
|
||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Since GPGME might be installed in a unicode directory it
|
||||||
|
must be callable with CreateProcessW which provides the
|
||||||
|
arguments in Unicode form.
|
||||||
|
|
||||||
|
So GPGME converts from its internal UTF-8 representation
|
||||||
|
to wchar, spawns gpgme-w32-spawn with CreateProcessW and then
|
||||||
|
we also forward this as wchar. */
|
||||||
int
|
int
|
||||||
main (int argc, const char * const *argv)
|
wmain (int argc, const wchar_t * const *argv)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
char **argv_spawn;
|
wchar_t **argv_spawn;
|
||||||
struct spawn_fd_item_s fd_list[MAX_TRANS + 1];
|
struct spawn_fd_item_s fd_list[MAX_TRANS + 1];
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
|
|
||||||
@ -479,7 +485,7 @@ main (int argc, const char * const *argv)
|
|||||||
rc = my_spawn (argv_spawn, fd_list, flags);
|
rc = my_spawn (argv_spawn, fd_list, flags);
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
{
|
{
|
||||||
fprintf (mystderr, PGM": executing `%s' failed: %s\n",
|
fprintf (mystderr, PGM": executing `%S' failed: %s\n",
|
||||||
argv[0], strerror (errno));
|
argv[0], strerror (errno));
|
||||||
rc = 2;
|
rc = 2;
|
||||||
goto leave;
|
goto leave;
|
||||||
@ -491,8 +497,8 @@ main (int argc, const char * const *argv)
|
|||||||
/* Always try to delete the temporary file. */
|
/* Always try to delete the temporary file. */
|
||||||
if (argc >= 2)
|
if (argc >= 2)
|
||||||
{
|
{
|
||||||
if (DeleteFile (argv[1]) == 0)
|
if (DeleteFileW (argv[1]) == 0)
|
||||||
fprintf (mystderr, PGM": failed to delete %s: ec=%ld\n",
|
fprintf (mystderr, PGM": failed to delete %S: ec=%ld\n",
|
||||||
argv[1], GetLastError ());
|
argv[1], GetLastError ());
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
|
Loading…
Reference in New Issue
Block a user