w32: Change spawn functions to use Unicode version of CreateProcess.

* common/exechelp-w32.c (gnupg_spawn_process): Change to use
CreateProcessW.
(gnupg_spawn_process_fd): Ditto.
(gnupg_spawn_process_detached): Ditto.
* g10/exec.c (w32_system): Ditto.
--

GnuPG-bug-id: 4398

We do not use this weirdo CREATE_UNICODE_ENVIRONMENT flag because it
does not make any sense to have non-ASCII names in the environment.  I
can't imagine why this should be used at all and rationale for this
API features is, well, sparse.
This commit is contained in:
Werner Koch 2021-03-08 21:26:16 +01:00
parent fc99f77b14
commit cf2f6d8a3f
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
2 changed files with 111 additions and 53 deletions

View File

@ -424,9 +424,11 @@ gnupg_spawn_process (const char *pgmname, const char *argv[],
0, /* Returns pid. */ 0, /* Returns pid. */
0 /* Returns tid. */ 0 /* Returns tid. */
}; };
STARTUPINFO si; STARTUPINFOW si;
int cr_flags; int cr_flags;
char *cmdline; char *cmdline;
wchar_t *wcmdline = NULL;
wchar_t *wpgmname = NULL;
HANDLE inpipe[2] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE}; HANDLE inpipe[2] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE};
HANDLE outpipe[2] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE}; HANDLE outpipe[2] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE};
HANDLE errpipe[2] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE}; HANDLE errpipe[2] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE};
@ -436,7 +438,7 @@ gnupg_spawn_process (const char *pgmname, const char *argv[],
HANDLE nullhd[3] = {INVALID_HANDLE_VALUE, HANDLE nullhd[3] = {INVALID_HANDLE_VALUE,
INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE,
INVALID_HANDLE_VALUE}; INVALID_HANDLE_VALUE};
int i; int i, rc;
es_syshd_t syshd; es_syshd_t syshd;
gpg_err_source_t errsource = default_errsource; gpg_err_source_t errsource = default_errsource;
int nonblock = !!(flags & GNUPG_SPAWN_NONBLOCK); int nonblock = !!(flags & GNUPG_SPAWN_NONBLOCK);
@ -574,20 +576,34 @@ gnupg_spawn_process (const char *pgmname, const char *argv[],
| ((flags & GNUPG_SPAWN_DETACHED)? DETACHED_PROCESS : 0) | ((flags & GNUPG_SPAWN_DETACHED)? DETACHED_PROCESS : 0)
| GetPriorityClass (GetCurrentProcess ()) | GetPriorityClass (GetCurrentProcess ())
| CREATE_SUSPENDED); | CREATE_SUSPENDED);
/* log_debug ("CreateProcess, path='%s' cmdline='%s'\n", pgmname, cmdline); */ /* log_debug ("CreateProcess, path='%s' cmdline='%s'\n", */
if (!CreateProcess (pgmname, /* Program to start. */ /* pgmname, cmdline); */
cmdline, /* Command line arguments. */ /* Take care: CreateProcessW may modify wpgmname */
&sec_attr, /* Process security attributes. */ if (!(wpgmname = utf8_to_wchar (pgmname)))
&sec_attr, /* Thread security attributes. */ rc = 0;
TRUE, /* Inherit handles. */ else if (!(wcmdline = utf8_to_wchar (cmdline)))
cr_flags, /* Creation flags. */ rc = 0;
NULL, /* Environment. */ else
NULL, /* Use current drive/directory. */ rc = CreateProcessW (wpgmname, /* Program to start. */
&si, /* Startup information. */ wcmdline, /* Command line arguments. */
&pi /* Returns process information. */ &sec_attr, /* Process security attributes. */
)) &sec_attr, /* Thread security attributes. */
TRUE, /* Inherit handles. */
cr_flags, /* Creation flags. */
NULL, /* Environment. */
NULL, /* Use current drive/directory. */
&si, /* Startup information. */
&pi /* Returns process information. */
);
if (!rc)
{ {
log_error ("CreateProcess failed: %s\n", w32_strerror (-1)); if (!wpgmname || !wcmdline)
log_error ("CreateProcess failed (utf8_to_wchar): %s\n",
strerror (errno));
else
log_error ("CreateProcess failed: %s\n", w32_strerror (-1));
xfree (wpgmname);
xfree (wcmdline);
xfree (cmdline); xfree (cmdline);
if (infp) if (infp)
es_fclose (infp); es_fclose (infp);
@ -609,6 +625,8 @@ gnupg_spawn_process (const char *pgmname, const char *argv[],
CloseHandle (errpipe[1]); CloseHandle (errpipe[1]);
return gpg_err_make (errsource, GPG_ERR_GENERAL); return gpg_err_make (errsource, GPG_ERR_GENERAL);
} }
xfree (wpgmname);
xfree (wcmdline);
xfree (cmdline); xfree (cmdline);
cmdline = NULL; cmdline = NULL;
@ -670,9 +688,11 @@ gnupg_spawn_process_fd (const char *pgmname, const char *argv[],
gpg_error_t err; gpg_error_t err;
SECURITY_ATTRIBUTES sec_attr; SECURITY_ATTRIBUTES sec_attr;
PROCESS_INFORMATION pi = { NULL, 0, 0, 0 }; PROCESS_INFORMATION pi = { NULL, 0, 0, 0 };
STARTUPINFO si; STARTUPINFOW si;
char *cmdline; char *cmdline;
int i; wchar_t *wcmdline = NULL;
wchar_t *wpgmname = NULL;
int i, rc;
HANDLE stdhd[3]; HANDLE stdhd[3];
/* Setup return values. */ /* Setup return values. */
@ -700,25 +720,38 @@ gnupg_spawn_process_fd (const char *pgmname, const char *argv[],
si.hStdError = errfd == -1? stdhd[2] : (void*)_get_osfhandle (errfd); si.hStdError = errfd == -1? stdhd[2] : (void*)_get_osfhandle (errfd);
/* log_debug ("CreateProcess, path='%s' cmdline='%s'\n", pgmname, cmdline); */ /* log_debug ("CreateProcess, path='%s' cmdline='%s'\n", pgmname, cmdline); */
if (!CreateProcess (pgmname, /* Program to start. */ /* Take care: CreateProcessW may modify wpgmname */
cmdline, /* Command line arguments. */ if (!(wpgmname = utf8_to_wchar (pgmname)))
&sec_attr, /* Process security attributes. */ rc = 0;
&sec_attr, /* Thread security attributes. */ else if (!(wcmdline = utf8_to_wchar (cmdline)))
TRUE, /* Inherit handles. */ rc = 0;
(CREATE_DEFAULT_ERROR_MODE else
| GetPriorityClass (GetCurrentProcess ()) rc = CreateProcessW (wpgmname, /* Program to start. */
| CREATE_SUSPENDED | DETACHED_PROCESS), wcmdline, /* Command line arguments. */
NULL, /* Environment. */ &sec_attr, /* Process security attributes. */
NULL, /* Use current drive/directory. */ &sec_attr, /* Thread security attributes. */
&si, /* Startup information. */ TRUE, /* Inherit handles. */
&pi /* Returns process information. */ (CREATE_DEFAULT_ERROR_MODE
)) | GetPriorityClass (GetCurrentProcess ())
| CREATE_SUSPENDED | DETACHED_PROCESS),
NULL, /* Environment. */
NULL, /* Use current drive/directory. */
&si, /* Startup information. */
&pi /* Returns process information. */
);
if (!rc)
{ {
log_error ("CreateProcess failed: %s\n", w32_strerror (-1)); if (!wpgmname || !wcmdline)
log_error ("CreateProcess failed (utf8_to_wchar): %s\n",
strerror (errno));
else
log_error ("CreateProcess failed: %s\n", w32_strerror (-1));
err = my_error (GPG_ERR_GENERAL); err = my_error (GPG_ERR_GENERAL);
} }
else else
err = 0; err = 0;
xfree (wpgmname);
xfree (wcmdline);
xfree (cmdline); xfree (cmdline);
for (i=0; i < 3; i++) for (i=0; i < 3; i++)
if (stdhd[i] != INVALID_HANDLE_VALUE) if (stdhd[i] != INVALID_HANDLE_VALUE)
@ -862,12 +895,14 @@ gnupg_spawn_process_detached (const char *pgmname, const char *argv[],
0, /* Returns pid. */ 0, /* Returns pid. */
0 /* Returns tid. */ 0 /* Returns tid. */
}; };
STARTUPINFO si; STARTUPINFOW si;
int cr_flags; int cr_flags;
char *cmdline; char *cmdline;
wchar_t *wcmdline = NULL;
wchar_t *wpgmname = NULL;
BOOL in_job = FALSE; BOOL in_job = FALSE;
gpg_err_code_t ec; gpg_err_code_t ec;
int rc;
/* We don't use ENVP. */ /* We don't use ENVP. */
(void)envp; (void)envp;
@ -939,24 +974,39 @@ gnupg_spawn_process_detached (const char *pgmname, const char *argv[],
} }
} }
/* log_debug ("CreateProcess(detached), path='%s' cmdline='%s'\n", */ /* log_debug ("CreateProcess(detached), path='%s' cmdline='%s'\n", */
/* pgmname, cmdline); */ /* pgmname, cmdline); */
if (!CreateProcess (pgmname, /* Program to start. */ /* Take care: CreateProcessW may modify wpgmname */
cmdline, /* Command line arguments. */ if (!(wpgmname = utf8_to_wchar (pgmname)))
&sec_attr, /* Process security attributes. */ rc = 0;
&sec_attr, /* Thread security attributes. */ else if (!(wcmdline = utf8_to_wchar (cmdline)))
FALSE, /* Inherit handles. */ rc = 0;
cr_flags, /* Creation flags. */ else
NULL, /* Environment. */ rc = CreateProcessW (wpgmname, /* Program to start. */
NULL, /* Use current drive/directory. */ wcmdline, /* Command line arguments. */
&si, /* Startup information. */ &sec_attr, /* Process security attributes. */
&pi /* Returns process information. */ &sec_attr, /* Thread security attributes. */
)) FALSE, /* Inherit handles. */
cr_flags, /* Creation flags. */
NULL, /* Environment. */
NULL, /* Use current drive/directory. */
&si, /* Startup information. */
&pi /* Returns process information. */
);
if (!rc)
{ {
log_error ("CreateProcess(detached) failed: %s\n", w32_strerror (-1)); if (!wpgmname || !wcmdline)
log_error ("CreateProcess failed (utf8_to_wchar): %s\n",
strerror (errno));
else
log_error ("CreateProcess(detached) failed: %s\n", w32_strerror (-1));
xfree (wpgmname);
xfree (wcmdline);
xfree (cmdline); xfree (cmdline);
return my_error (GPG_ERR_GENERAL); return my_error (GPG_ERR_GENERAL);
} }
xfree (wpgmname);
xfree (wcmdline);
xfree (cmdline); xfree (cmdline);
cmdline = NULL; cmdline = NULL;

View File

@ -107,28 +107,36 @@ w32_system(const char *command)
else else
{ {
char *string; char *string;
wchar_t *wstring;
PROCESS_INFORMATION pi; PROCESS_INFORMATION pi;
STARTUPINFO si; STARTUPINFOW si;
/* We must use a copy of the command as CreateProcess modifies /* We must use a copy of the command as CreateProcess modifies
* this argument. */ * this argument. */
string = xstrdup (command); string = xstrdup (command);
wstring = utf8_to_wchar (string);
xfree (string);
if (!wstring)
return -1;
memset (&pi, 0, sizeof(pi)); memset (&pi, 0, sizeof(pi));
memset (&si, 0, sizeof(si)); memset (&si, 0, sizeof(si));
si.cb = sizeof (si); si.cb = sizeof (si);
if (!CreateProcess (NULL, string, NULL, NULL, FALSE, if (!CreateProcessW (NULL, wstring, NULL, NULL, FALSE,
DETACHED_PROCESS, DETACHED_PROCESS,
NULL, NULL, &si, &pi)) NULL, NULL, &si, &pi))
return -1; {
xfree (wstring);
return -1;
}
/* Wait for the child to exit */ /* Wait for the child to exit */
WaitForSingleObject (pi.hProcess, INFINITE); WaitForSingleObject (pi.hProcess, INFINITE);
CloseHandle (pi.hProcess); CloseHandle (pi.hProcess);
CloseHandle (pi.hThread); CloseHandle (pi.hThread);
xfree (string); xfree (wstring);
} }
return 0; return 0;