diff options
Diffstat (limited to 'common/exechelp-w32.c')
-rw-r--r-- | common/exechelp-w32.c | 974 |
1 files changed, 0 insertions, 974 deletions
diff --git a/common/exechelp-w32.c b/common/exechelp-w32.c index 46fb9ae92..51d6920bd 100644 --- a/common/exechelp-w32.c +++ b/common/exechelp-w32.c @@ -184,77 +184,6 @@ get_all_open_fds (void) return array; } - -/* Helper function to build_w32_commandline. */ -static char * -build_w32_commandline_copy (char *buffer, const char *string) -{ - char *p = buffer; - const char *s; - - if (!*string) /* Empty string. */ - p = stpcpy (p, "\"\""); - else if (strpbrk (string, " \t\n\v\f\"")) - { - /* Need to do some kind of quoting. */ - p = stpcpy (p, "\""); - for (s=string; *s; s++) - { - *p++ = *s; - if (*s == '\"') - *p++ = *s; - } - *p++ = '\"'; - *p = 0; - } - else - p = stpcpy (p, string); - - return p; -} - -/* Build a command line for use with W32's CreateProcess. On success - CMDLINE gets the address of a newly allocated string. */ -static gpg_error_t -build_w32_commandline (const char *pgmname, const char * const *argv, - char **cmdline) -{ - int i, n; - const char *s; - char *buf, *p; - - *cmdline = NULL; - n = 0; - s = pgmname; - n += strlen (s) + 1 + 2; /* (1 space, 2 quoting */ - for (; *s; s++) - if (*s == '\"') - n++; /* Need to double inner quotes. */ - for (i=0; (s=argv[i]); i++) - { - n += strlen (s) + 1 + 2; /* (1 space, 2 quoting */ - for (; *s; s++) - if (*s == '\"') - n++; /* Need to double inner quotes. */ - } - n++; - - buf = p = xtrymalloc (n); - if (!buf) - return my_error_from_syserror (); - - p = build_w32_commandline_copy (p, pgmname); - for (i=0; argv[i]; i++) - { - *p++ = ' '; - p = build_w32_commandline_copy (p, argv[i]); - } - - *cmdline= buf; - return 0; -} - - #define INHERIT_READ 1 #define INHERIT_WRITE 2 #define INHERIT_BOTH (INHERIT_READ|INHERIT_WRITE) @@ -293,21 +222,6 @@ create_inheritable_pipe (HANDLE filedes[2], int flags) } -static HANDLE -w32_open_null (int for_write) -{ - HANDLE hfile; - - hfile = CreateFileW (L"nul", - for_write? GENERIC_WRITE : GENERIC_READ, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, OPEN_EXISTING, 0, NULL); - if (hfile == INVALID_HANDLE_VALUE) - log_debug ("can't open 'nul': %s\n", w32_strerror (-1)); - return hfile; -} - - static gpg_error_t create_pipe_and_estream (int filedes[2], int flags, estream_t *r_fp, int outbound, int nonblock) @@ -408,891 +322,3 @@ gnupg_close_pipe (int fd) if (fd != -1) close (fd); } - -struct gnupg_spawn_actions { - void *hd[3]; - void **inherit_hds; - char *env; -}; - -struct gnupg_process { - const char *pgmname; - unsigned int terminated :1; /* or detached */ - unsigned int flags; - HANDLE hProcess; - HANDLE hd_in; - HANDLE hd_out; - HANDLE hd_err; - int exitcode; -}; - -static int gnupg_process_syscall_func_initialized; - -/* Functions called before and after blocking syscalls. */ -static void (*pre_syscall_func) (void); -static void (*post_syscall_func) (void); - -static void -check_syscall_func (void) -{ - if (!gnupg_process_syscall_func_initialized) - { - gpgrt_get_syscall_clamp (&pre_syscall_func, &post_syscall_func); - gnupg_process_syscall_func_initialized = 1; - } -} - - -static void -pre_syscall (void) -{ - if (pre_syscall_func) - pre_syscall_func (); -} - - -static void -post_syscall (void) -{ - if (post_syscall_func) - post_syscall_func (); -} - - -/* - * Check if STARTUPINFOEXW supports PROC_THREAD_ATTRIBUTE_HANDLE_LIST. - */ -static int -check_windows_version (void) -{ - static int is_vista_or_later = -1; - - OSVERSIONINFO osvi; - - if (is_vista_or_later == -1) - { - memset (&osvi,0,sizeof(osvi)); - osvi.dwOSVersionInfoSize = sizeof(osvi); - GetVersionEx (&osvi); - - /* The feature is available on Vista or later. */ - is_vista_or_later = (osvi.dwMajorVersion >= 6); - } - - return is_vista_or_later; -} - - -static gpg_err_code_t -spawn_detached (const char *pgmname, char *cmdline, gnupg_spawn_actions_t act) -{ - SECURITY_ATTRIBUTES sec_attr; - PROCESS_INFORMATION pi = { NULL, 0, 0, 0 }; - STARTUPINFOEXW si; - int cr_flags; - wchar_t *wcmdline = NULL; - wchar_t *wpgmname = NULL; - gpg_err_code_t ec; - int ret; - BOOL ask_inherit = FALSE; - int i; - - ec = gnupg_access (pgmname, X_OK); - if (ec) - { - xfree (cmdline); - return ec; - } - - memset (&si, 0, sizeof si); - - i = 0; - if (act->hd[0] != INVALID_HANDLE_VALUE) - i++; - if (act->hd[1] != INVALID_HANDLE_VALUE) - i++; - if (act->hd[2] != INVALID_HANDLE_VALUE) - i++; - - if (i != 0 || act->inherit_hds) - { - SIZE_T attr_list_size = 0; - HANDLE hd[16]; - HANDLE *hd_p = act->inherit_hds; - int j = 0; - - if (act->hd[0] != INVALID_HANDLE_VALUE) - hd[j++] = act->hd[0]; - if (act->hd[1] != INVALID_HANDLE_VALUE) - hd[j++] = act->hd[1]; - if (act->hd[1] != INVALID_HANDLE_VALUE) - hd[j++] = act->hd[2]; - if (hd_p) - { - while (*hd_p != INVALID_HANDLE_VALUE) - if (j < DIM (hd)) - hd[j++] = *hd_p++; - else - { - log_error ("Too much handles\n"); - break; - } - } - - if (j) - { - if (check_windows_version ()) - { - InitializeProcThreadAttributeList (NULL, 1, 0, &attr_list_size); - si.lpAttributeList = xtrymalloc (attr_list_size); - if (si.lpAttributeList == NULL) - { - xfree (cmdline); - return gpg_err_code_from_syserror (); - } - InitializeProcThreadAttributeList (si.lpAttributeList, 1, 0, - &attr_list_size); - UpdateProcThreadAttribute (si.lpAttributeList, 0, - PROC_THREAD_ATTRIBUTE_HANDLE_LIST, - hd, sizeof (HANDLE) * j, NULL, NULL); - } - - ask_inherit = TRUE; - } - } - - /* Prepare security attributes. */ - memset (&sec_attr, 0, sizeof sec_attr ); - sec_attr.nLength = sizeof sec_attr; - sec_attr.bInheritHandle = FALSE; - - /* Start the process. */ - si.StartupInfo.cb = sizeof (si); - si.StartupInfo.dwFlags = ((i > 0 ? STARTF_USESTDHANDLES : 0) - | STARTF_USESHOWWINDOW); - si.StartupInfo.wShowWindow = DEBUG_W32_SPAWN? SW_SHOW : SW_MINIMIZE; - - cr_flags = (CREATE_DEFAULT_ERROR_MODE - | GetPriorityClass (GetCurrentProcess ()) - | CREATE_NEW_PROCESS_GROUP - | DETACHED_PROCESS); - - /* Take care: CreateProcessW may modify wpgmname */ - if (!(wpgmname = utf8_to_wchar (pgmname))) - ret = 0; - else if (!(wcmdline = utf8_to_wchar (cmdline))) - ret = 0; - else - ret = CreateProcessW (wpgmname, /* Program to start. */ - wcmdline, /* Command line arguments. */ - &sec_attr, /* Process security attributes. */ - &sec_attr, /* Thread security attributes. */ - ask_inherit, /* Inherit handles. */ - cr_flags, /* Creation flags. */ - act->env, /* Environment. */ - NULL, /* Use current drive/directory. */ - (STARTUPINFOW *)&si, /* Startup information. */ - &pi /* Returns process information. */ - ); - if (!ret) - { - if (!wpgmname || !wcmdline) - log_error ("CreateProcess failed (utf8_to_wchar): %s\n", - strerror (errno)); - else - log_error ("CreateProcess(detached) failed: %d\n", - (int)GetLastError ()); - xfree (wpgmname); - xfree (wcmdline); - xfree (cmdline); - return GPG_ERR_GENERAL; - } - if (si.lpAttributeList) - DeleteProcThreadAttributeList (si.lpAttributeList); - xfree (wpgmname); - xfree (wcmdline); - xfree (cmdline); - - /* log_debug ("CreateProcess(detached) ready: hProcess=%p hThread=%p" */ - /* " dwProcessID=%d dwThreadId=%d\n", */ - /* pi.hProcess, pi.hThread, */ - /* (int) pi.dwProcessId, (int) pi.dwThreadId); */ - - /* Note: AllowSetForegroundWindow doesn't make sense for background - process. */ - - CloseHandle (pi.hThread); - CloseHandle (pi.hProcess); - return 0; -} - - -gpg_err_code_t -gnupg_spawn_actions_new (gnupg_spawn_actions_t *r_act) -{ - gnupg_spawn_actions_t act; - int i; - - *r_act = NULL; - - act = xtrycalloc (1, sizeof (struct gnupg_spawn_actions)); - if (act == NULL) - return gpg_err_code_from_syserror (); - - for (i = 0; i <= 2; i++) - act->hd[i] = INVALID_HANDLE_VALUE; - - *r_act = act; - return 0; -} - -void -gnupg_spawn_actions_release (gnupg_spawn_actions_t act) -{ - if (!act) - return; - - xfree (act); -} - -void -gnupg_spawn_actions_set_envvars (gnupg_spawn_actions_t act, char *env) -{ - act->env = env; -} - -void -gnupg_spawn_actions_set_redirect (gnupg_spawn_actions_t act, - void *in, void *out, void *err) -{ - act->hd[0] = in; - act->hd[1] = out; - act->hd[2] = err; -} - -void -gnupg_spawn_actions_set_inherit_handles (gnupg_spawn_actions_t act, - void **handles) -{ - act->inherit_hds = handles; -} - - -gpg_err_code_t -gnupg_process_spawn (const char *pgmname, const char *argv[], - unsigned int flags, gnupg_spawn_actions_t act, - gnupg_process_t *r_process) -{ - gpg_err_code_t ec; - gnupg_process_t process; - SECURITY_ATTRIBUTES sec_attr; - PROCESS_INFORMATION pi = { NULL, 0, 0, 0 }; - STARTUPINFOEXW si; - int cr_flags; - char *cmdline; - wchar_t *wcmdline = NULL; - wchar_t *wpgmname = NULL; - int ret; - HANDLE hd_in[2]; - HANDLE hd_out[2]; - HANDLE hd_err[2]; - int i; - BOOL ask_inherit = FALSE; - BOOL allow_foreground_window = FALSE; - struct gnupg_spawn_actions act_default; - - if (!act) - { - memset (&act_default, 0, sizeof (act_default)); - for (i = 0; i <= 2; i++) - act_default.hd[i] = INVALID_HANDLE_VALUE; - act = &act_default; - } - - check_syscall_func (); - - /* Build the command line. */ - ec = build_w32_commandline (pgmname, argv, &cmdline); - if (ec) - return ec; - - if ((flags & GNUPG_PROCESS_DETACHED)) - { - if ((flags & GNUPG_PROCESS_STDFDS_SETTING)) - { - xfree (cmdline); - return GPG_ERR_INV_FLAG; - } - - /* In detached case, it must be no R_PROCESS. */ - if (r_process) - { - xfree (cmdline); - return GPG_ERR_INV_ARG; - } - - return spawn_detached (pgmname, cmdline, act); - } - - if (r_process) - *r_process = NULL; - - process = xtrymalloc (sizeof (struct gnupg_process)); - if (process == NULL) - { - xfree (cmdline); - return gpg_err_code_from_syserror (); - } - - process->pgmname = pgmname; - process->flags = flags; - - if ((flags & GNUPG_PROCESS_STDINOUT_SOCKETPAIR)) - { - xfree (process); - xfree (cmdline); - return GPG_ERR_NOT_SUPPORTED; - } - - if ((flags & GNUPG_PROCESS_STDIN_PIPE)) - { - ec = create_inheritable_pipe (hd_in, INHERIT_READ); - if (ec) - { - xfree (process); - xfree (cmdline); - return ec; - } - } - else if ((flags & GNUPG_PROCESS_STDIN_KEEP)) - { - hd_in[0] = GetStdHandle (STD_INPUT_HANDLE); - hd_in[1] = INVALID_HANDLE_VALUE; - } - else - { - hd_in[0] = w32_open_null (0); - hd_in[1] = INVALID_HANDLE_VALUE; - } - - if ((flags & GNUPG_PROCESS_STDOUT_PIPE)) - { - ec = create_inheritable_pipe (hd_out, INHERIT_WRITE); - if (ec) - { - if (hd_in[0] != INVALID_HANDLE_VALUE) - CloseHandle (hd_in[0]); - if (hd_in[1] != INVALID_HANDLE_VALUE) - CloseHandle (hd_in[1]); - xfree (process); - xfree (cmdline); - return ec; - } - } - else if ((flags & GNUPG_PROCESS_STDOUT_KEEP)) - { - hd_out[0] = INVALID_HANDLE_VALUE; - hd_out[1] = GetStdHandle (STD_OUTPUT_HANDLE); - } - else - { - hd_out[0] = INVALID_HANDLE_VALUE; - hd_out[1] = w32_open_null (1); - } - - if ((flags & GNUPG_PROCESS_STDERR_PIPE)) - { - ec = create_inheritable_pipe (hd_err, INHERIT_WRITE); - if (ec) - { - if (hd_in[0] != INVALID_HANDLE_VALUE) - CloseHandle (hd_in[0]); - if (hd_in[1] != INVALID_HANDLE_VALUE) - CloseHandle (hd_in[1]); - if (hd_out[0] != INVALID_HANDLE_VALUE) - CloseHandle (hd_out[0]); - if (hd_out[1] != INVALID_HANDLE_VALUE) - CloseHandle (hd_out[1]); - xfree (process); - xfree (cmdline); - return ec; - } - } - else if ((flags & GNUPG_PROCESS_STDERR_KEEP)) - { - hd_err[0] = INVALID_HANDLE_VALUE; - hd_err[1] = GetStdHandle (STD_ERROR_HANDLE); - } - else - { - hd_err[0] = INVALID_HANDLE_VALUE; - hd_err[1] = w32_open_null (1); - } - - memset (&si, 0, sizeof si); - - if (act->hd[0] == INVALID_HANDLE_VALUE) - act->hd[0] = hd_in[0]; - if (act->hd[1] == INVALID_HANDLE_VALUE) - act->hd[1] = hd_out[1]; - if (act->hd[2] == INVALID_HANDLE_VALUE) - act->hd[2] = hd_err[1]; - - i = 0; - if (act->hd[0] != INVALID_HANDLE_VALUE) - i++; - if (act->hd[1] != INVALID_HANDLE_VALUE) - i++; - if (act->hd[2] != INVALID_HANDLE_VALUE) - i++; - - if (i != 0 || act->inherit_hds) - { - SIZE_T attr_list_size = 0; - HANDLE hd[16]; - HANDLE *hd_p = act->inherit_hds; - int j = 0; - - if (act->hd[0] != INVALID_HANDLE_VALUE) - hd[j++] = act->hd[0]; - if (act->hd[1] != INVALID_HANDLE_VALUE) - hd[j++] = act->hd[1]; - if (act->hd[1] != INVALID_HANDLE_VALUE) - hd[j++] = act->hd[2]; - if (hd_p) - { - while (*hd_p != INVALID_HANDLE_VALUE) - if (j < DIM (hd)) - hd[j++] = *hd_p++; - else - { - log_error ("Too much handles\n"); - break; - } - } - - if (j) - { - if (check_windows_version ()) - { - InitializeProcThreadAttributeList (NULL, 1, 0, &attr_list_size); - si.lpAttributeList = xtrymalloc (attr_list_size); - if (si.lpAttributeList == NULL) - { - if ((flags & GNUPG_PROCESS_STDIN_PIPE) - || !(flags & GNUPG_PROCESS_STDIN_KEEP)) - CloseHandle (hd_in[0]); - if ((flags & GNUPG_PROCESS_STDIN_PIPE)) - CloseHandle (hd_in[1]); - if ((flags & GNUPG_PROCESS_STDOUT_PIPE)) - CloseHandle (hd_out[0]); - if ((flags & GNUPG_PROCESS_STDOUT_PIPE) - || !(flags & GNUPG_PROCESS_STDOUT_KEEP)) - CloseHandle (hd_out[1]); - if ((flags & GNUPG_PROCESS_STDERR_PIPE)) - CloseHandle (hd_err[0]); - if ((flags & GNUPG_PROCESS_STDERR_PIPE) - || !(flags & GNUPG_PROCESS_STDERR_KEEP)) - CloseHandle (hd_err[1]); - xfree (process); - xfree (cmdline); - return gpg_err_code_from_syserror (); - } - InitializeProcThreadAttributeList (si.lpAttributeList, 1, 0, - &attr_list_size); - UpdateProcThreadAttribute (si.lpAttributeList, 0, - PROC_THREAD_ATTRIBUTE_HANDLE_LIST, - hd, sizeof (HANDLE) * j, NULL, NULL); - } - ask_inherit = TRUE; - } - } - - /* Prepare security attributes. */ - memset (&sec_attr, 0, sizeof sec_attr ); - sec_attr.nLength = sizeof sec_attr; - sec_attr.bInheritHandle = FALSE; - - /* Start the process. */ - si.StartupInfo.cb = sizeof (si); - si.StartupInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; - si.StartupInfo.wShowWindow = DEBUG_W32_SPAWN? SW_SHOW : SW_HIDE; - si.StartupInfo.hStdInput = act->hd[0]; - si.StartupInfo.hStdOutput = act->hd[1]; - si.StartupInfo.hStdError = act->hd[2]; - - /* log_debug ("CreateProcess, path='%s' cmdline='%s'\n", pgmname, cmdline); */ - cr_flags = (CREATE_DEFAULT_ERROR_MODE - | GetPriorityClass (GetCurrentProcess ()) - | CREATE_SUSPENDED); - if (!(wpgmname = utf8_to_wchar (pgmname))) - ret = 0; - else if (!(wcmdline = utf8_to_wchar (cmdline))) - ret = 0; - else - ret = CreateProcessW (wpgmname, /* Program to start. */ - wcmdline, /* Command line arguments. */ - &sec_attr, /* Process security attributes. */ - &sec_attr, /* Thread security attributes. */ - ask_inherit, /* Inherit handles. */ - cr_flags, /* Creation flags. */ - act->env, /* Environment. */ - NULL, /* Use current drive/directory. */ - (STARTUPINFOW *)&si, /* Startup information. */ - &pi /* Returns process information. */ - ); - if (!ret) - { - if (!wpgmname || !wcmdline) - log_error ("CreateProcess failed (utf8_to_wchar): %s\n", - strerror (errno)); - else - log_error ("CreateProcess failed: ec=%d\n", - (int)GetLastError ()); - if ((flags & GNUPG_PROCESS_STDIN_PIPE) - || !(flags & GNUPG_PROCESS_STDIN_KEEP)) - CloseHandle (hd_in[0]); - if ((flags & GNUPG_PROCESS_STDIN_PIPE)) - CloseHandle (hd_in[1]); - if ((flags & GNUPG_PROCESS_STDOUT_PIPE)) - CloseHandle (hd_out[0]); - if ((flags & GNUPG_PROCESS_STDOUT_PIPE) - || !(flags & GNUPG_PROCESS_STDOUT_KEEP)) - CloseHandle (hd_out[1]); - if ((flags & GNUPG_PROCESS_STDERR_PIPE)) - CloseHandle (hd_err[0]); - if ((flags & GNUPG_PROCESS_STDERR_PIPE) - || !(flags & GNUPG_PROCESS_STDERR_KEEP)) - CloseHandle (hd_err[1]); - xfree (wpgmname); - xfree (wcmdline); - xfree (process); - xfree (cmdline); - return GPG_ERR_GENERAL; - } - - if (si.lpAttributeList) - DeleteProcThreadAttributeList (si.lpAttributeList); - xfree (wpgmname); - xfree (wcmdline); - xfree (cmdline); - - if ((flags & GNUPG_PROCESS_STDIN_PIPE) - || !(flags & GNUPG_PROCESS_STDIN_KEEP)) - CloseHandle (hd_in[0]); - if ((flags & GNUPG_PROCESS_STDOUT_PIPE) - || !(flags & GNUPG_PROCESS_STDOUT_KEEP)) - CloseHandle (hd_out[1]); - if ((flags & GNUPG_PROCESS_STDERR_PIPE) - || !(flags & GNUPG_PROCESS_STDERR_KEEP)) - CloseHandle (hd_err[1]); - - /* log_debug ("CreateProcess ready: hProcess=%p hThread=%p" */ - /* " dwProcessID=%d dwThreadId=%d\n", */ - /* pi.hProcess, pi.hThread, */ - /* (int) pi.dwProcessId, (int) pi.dwThreadId); */ - - if (allow_foreground_window) - { - /* Fixme: For unknown reasons AllowSetForegroundWindow returns - * an invalid argument error if we pass it the correct - * processID. As a workaround we use -1 (ASFW_ANY). */ - if (!AllowSetForegroundWindow (ASFW_ANY /*pi.dwProcessId*/)) - log_info ("AllowSetForegroundWindow() failed: ec=%d\n", - (int)GetLastError ()); - } - - /* Process has been created suspended; resume it now. */ - pre_syscall (); - ResumeThread (pi.hThread); - CloseHandle (pi.hThread); - post_syscall (); - - process->hProcess = pi.hProcess; - process->hd_in = hd_in[1]; - process->hd_out = hd_out[0]; - process->hd_err = hd_err[0]; - process->exitcode = -1; - process->terminated = 0; - - if (r_process == NULL) - { - ec = gnupg_process_wait (process, 1); - gnupg_process_release (process); - return ec; - } - - *r_process = process; - return 0; -} - -gpg_err_code_t -gnupg_process_get_fds (gnupg_process_t process, unsigned int flags, - int *r_fd_in, int *r_fd_out, int *r_fd_err) -{ - (void)flags; - if (r_fd_in) - { - *r_fd_in = _open_osfhandle ((intptr_t)process->hd_in, O_APPEND); - process->hd_in = INVALID_HANDLE_VALUE; - } - if (r_fd_out) - { - *r_fd_out = _open_osfhandle ((intptr_t)process->hd_out, O_RDONLY); - process->hd_out = INVALID_HANDLE_VALUE; - } - if (r_fd_err) - { - *r_fd_err = _open_osfhandle ((intptr_t)process->hd_err, O_RDONLY); - process->hd_err = INVALID_HANDLE_VALUE; - } - - return 0; -} - -gpg_err_code_t -gnupg_process_get_streams (gnupg_process_t process, unsigned int flags, - estream_t *r_fp_in, estream_t *r_fp_out, - estream_t *r_fp_err) -{ - int nonblock = (flags & GNUPG_PROCESS_STREAM_NONBLOCK)? 1: 0; - es_syshd_t syshd; - - syshd.type = ES_SYSHD_HANDLE; - if (r_fp_in) - { - syshd.u.handle = process->hd_in; - *r_fp_in = es_sysopen (&syshd, nonblock? "w,nonblock" : "w"); - process->hd_in = INVALID_HANDLE_VALUE; - } - if (r_fp_out) - { - syshd.u.handle = process->hd_out; - *r_fp_out = es_sysopen (&syshd, nonblock? "r,nonblock" : "r"); - process->hd_out = INVALID_HANDLE_VALUE; - } - if (r_fp_err) - { - syshd.u.handle = process->hd_err; - *r_fp_err = es_sysopen (&syshd, nonblock? "r,nonblock" : "r"); - process->hd_err = INVALID_HANDLE_VALUE; - } - return 0; -} - -static gpg_err_code_t -process_kill (gnupg_process_t process, unsigned int exitcode) -{ - gpg_err_code_t ec = 0; - - pre_syscall (); - if (TerminateProcess (process->hProcess, exitcode)) - ec = gpg_err_code_from_syserror (); - post_syscall (); - return ec; -} - -static gpg_err_code_t -process_vctl (gnupg_process_t process, unsigned int request, va_list arg_ptr) -{ - switch (request) - { - case GNUPG_PROCESS_NOP: - return 0; - - case GNUPG_PROCESS_GET_PROC_ID: - { - int *r_id = va_arg (arg_ptr, int *); - - if (r_id == NULL) - return GPG_ERR_INV_VALUE; - - *r_id = (int)GetProcessId (process->hProcess); - return 0; - } - - case GNUPG_PROCESS_GET_EXIT_ID: - { - int *r_exit_status = va_arg (arg_ptr, int *); - unsigned long exit_code; - - *r_exit_status = -1; - - if (!process->terminated) - return GPG_ERR_UNFINISHED; - - if (process->hProcess == INVALID_HANDLE_VALUE) - return 0; - - if (GetExitCodeProcess (process->hProcess, &exit_code) == 0) - return gpg_err_code_from_syserror (); - - *r_exit_status = (int)exit_code; - return 0; - } - - case GNUPG_PROCESS_GET_P_HANDLE: - { - HANDLE *r_hProcess = va_arg (arg_ptr, HANDLE *); - - if (r_hProcess == NULL) - return GPG_ERR_INV_VALUE; - - *r_hProcess = process->hProcess; - process->hProcess = INVALID_HANDLE_VALUE; - return 0; - } - - case GNUPG_PROCESS_GET_HANDLES: - { - HANDLE *r_hd_in = va_arg (arg_ptr, HANDLE *); - HANDLE *r_hd_out = va_arg (arg_ptr, HANDLE *); - HANDLE *r_hd_err = va_arg (arg_ptr, HANDLE *); - - if (r_hd_in) - { - *r_hd_in = process->hd_in; - process->hd_in = INVALID_HANDLE_VALUE; - } - if (r_hd_out) - { - *r_hd_out = process->hd_out; - process->hd_out = INVALID_HANDLE_VALUE; - } - if (r_hd_err) - { - *r_hd_err = process->hd_err; - process->hd_err = INVALID_HANDLE_VALUE; - } - return 0; - } - - case GNUPG_PROCESS_GET_EXIT_CODE: - { - unsigned long *r_exitcode = va_arg (arg_ptr, unsigned long *); - - if (!process->terminated) - return GPG_ERR_UNFINISHED; - - if (process->hProcess == INVALID_HANDLE_VALUE) - { - *r_exitcode = (unsigned long)-1; - return 0; - } - - if (GetExitCodeProcess (process->hProcess, r_exitcode) == 0) - return gpg_err_code_from_syserror (); - return 0; - } - - case GNUPG_PROCESS_KILL_WITH_EC: - { - unsigned int exitcode = va_arg (arg_ptr, unsigned int); - - if (process->terminated) - return 0; - - if (process->hProcess == INVALID_HANDLE_VALUE) - return 0; - - return process_kill (process, exitcode); - } - - default: - break; - } - - return GPG_ERR_UNKNOWN_COMMAND; -} - -gpg_err_code_t -gnupg_process_ctl (gnupg_process_t process, unsigned int request, ...) -{ - va_list arg_ptr; - gpg_err_code_t ec; - - va_start (arg_ptr, request); - ec = process_vctl (process, request, arg_ptr); - va_end (arg_ptr); - return ec; -} - -gpg_err_code_t -gnupg_process_wait (gnupg_process_t process, int hang) -{ - gpg_err_code_t ec; - int code; - - if (process->hProcess == INVALID_HANDLE_VALUE) - return 0; - - pre_syscall (); - code = WaitForSingleObject (process->hProcess, hang? INFINITE : 0); - post_syscall (); - - switch (code) - { - case WAIT_TIMEOUT: - ec = GPG_ERR_TIMEOUT; /* Still running. */ - break; - - case WAIT_FAILED: - log_error (_("waiting for process to terminate failed: ec=%d\n"), - (int)GetLastError ()); - ec = GPG_ERR_GENERAL; - break; - - case WAIT_OBJECT_0: - process->terminated = 1; - ec = 0; - break; - - default: - log_debug ("WaitForSingleObject returned unexpected code %d\n", code); - ec = GPG_ERR_GENERAL; - break; - } - - return ec; -} - -gpg_err_code_t -gnupg_process_terminate (gnupg_process_t process) -{ - return process_kill (process, 1); -} - -void -gnupg_process_release (gnupg_process_t process) -{ - if (!process) - return; - - if (!process->terminated) - { - gnupg_process_terminate (process); - gnupg_process_wait (process, 1); - } - - CloseHandle (process->hProcess); - xfree (process); -} - -gpg_err_code_t -gnupg_process_wait_list (gnupg_process_t *process_list, int count, int hang) -{ - gpg_err_code_t ec = 0; - int i; - - for (i = 0; i < count; i++) - { - if (process_list[i]->terminated) - continue; - - ec = gnupg_process_wait (process_list[i], hang); - if (ec) - break; - } - - return ec; -} |