diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2008-03-07 11:24:51 +0000 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2008-03-07 11:24:51 +0000 |
commit | 752b16ce359bb46948b8aa2bc88f7c32bf2cc95b (patch) | |
tree | 1ed3d9abb89e7e21ee47faf099632cf05b3a05be /winsup/cygwin/spawn.cc | |
parent | d8e218442b004997287aaf202af88d9f1f86074e (diff) | |
download | cygnal-752b16ce359bb46948b8aa2bc88f7c32bf2cc95b.tar.gz cygnal-752b16ce359bb46948b8aa2bc88f7c32bf2cc95b.tar.bz2 cygnal-752b16ce359bb46948b8aa2bc88f7c32bf2cc95b.zip |
* Makefile.in (DLL_OFILES): Add tls_pbuf.o.
* autoload.cc (CreateDesktopW): Replace CreateDesktopA.
(CreateWindowStationW): Replace CreateWindowStationA.
(GetUserObjectInformationW): Replace GetUserObjectInformationA.
* cygheap.h (cwdstuff::get): Assume default buffer size NT_MAX_PATH.
* cygtls.cc (_cygtls::remove): Free temporary TLS path buffers.
* cygtls.h (TP_NUM_C_BUFS): Define.
(TP_NUM_W_BUFS): Define.
(class tls_pathbuf): New class to store pointers to thread local
temporary path buffers.
(_local_storage::pathbufs): New member.
* environ.cc (win_env::add_cache): Use temporary TLS path buffer instead
of stack based buffer.
(posify): Get temporary outenv buffer from calling function.
(environ_init): Create temporary TLS path buffer for posify.
(build_env): Create Windows environment block as WCHAR buffer.
* environ.h (build_env): Change declaration accordingly.
* external.cc (sync_winenv): Accommodate build_env change.
* fhandler_console.cc (fhandler_console::need_invisible): Use
GetUserObjectInformationW and CreateWindowStationW.
* fhandler_process.cc (format_process_maps): Use temporary TLS path
buffer instead of stack based buffer.
* fork.cc (frok::parent): Convert to use CreateProcessW.
* path.cc: Throughout use temporary TLS path buffers instead of stack
based buffer. Replace checks for CYG_MAX_PATH by checks for
NT_MAX_PATH.
(getfileattr): New function to replace GetFileAttributesA.
(normalize_win32_path): Remove Win32 and NT long path prefixes.
(getwd): Assume PATH_MAX + 1 buffer per SUSv3.
* path.h (class path_conv): Set path buffer to size NT_MAX_PATH.
(iswdrive): Define.
* pinfo.cc (commune_process): Use temporary TLS path buffer instead of
stack based buffer.
* registry.cc (get_registry_hive_path): Ditto.
(load_registry_hive): Ditto.
* spawn.cc (spawn_guts): Convert to use CreateProcessW and
CreateProcessAsUserW.
(av::fixup): Open/close file using NtOpenFile/NtClose.
* syscalls.cc (mknod_worker): Allow PATH_MAX file name.
(mknod32): Ditto.
(getusershell): Ditto.
* tls_pbuf.cc: New file implementing tls_pathbuf and tmp_pathbuf
methods.
* tls_pbuf.h: New header for files using tmp_pathbuf.
* tlsoffsets.h: Regenerate.
* winsup.h (NT_MAX_PATH): Define as 32767 to avoid USHORT overflow.
Diffstat (limited to 'winsup/cygwin/spawn.cc')
-rw-r--r-- | winsup/cygwin/spawn.cc | 119 |
1 files changed, 68 insertions, 51 deletions
diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc index e016f1797..4ea04d934 100644 --- a/winsup/cygwin/spawn.cc +++ b/winsup/cygwin/spawn.cc @@ -18,6 +18,7 @@ details. */ #include <limits.h> #include <wingdi.h> #include <winuser.h> +#include <wchar.h> #include <ctype.h> #include "cygerrno.h" #include <sys/cygwin.h> @@ -33,6 +34,7 @@ details. */ #include "registry.h" #include "environ.h" #include "cygtls.h" +#include "tls_pbuf.h" #include "winf.h" #include "ntdll.h" @@ -301,18 +303,19 @@ spawn_guts (const char * prog_arg, const char *const *argv, av newargv; linebuf one_line; child_info_spawn ch; - char *envblock = NULL; + PWCHAR envblock = NULL; path_conv real_path; bool reset_sendsig = false; - const char *runpath; + tmp_pathbuf tp; + PWCHAR runpath = tp.w_get (); int c_flags; bool wascygexec; cygheap_exec_info *moreinfo; bool null_app_name = false; - STARTUPINFO si = {0, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, - NULL, NULL, NULL}; + STARTUPINFOW si = {0, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, + NULL, NULL, NULL}; int looped = 0; HANDLE orig_wr_proc_pipe = NULL; @@ -333,7 +336,8 @@ spawn_guts (const char * prog_arg, const char *const *argv, else chtype = PROC_EXEC; - moreinfo = (cygheap_exec_info *) ccalloc_abort (HEAP_1_EXEC, 1, sizeof (cygheap_exec_info)); + moreinfo = (cygheap_exec_info *) ccalloc_abort (HEAP_1_EXEC, 1, + sizeof (cygheap_exec_info)); moreinfo->old_title = NULL; /* CreateProcess takes one long string that is the command line (sigh). @@ -382,7 +386,8 @@ spawn_guts (const char * prog_arg, const char *const *argv, { if (wascygexec) newargv.dup_all (); - else if (!one_line.fromargv (newargv, real_path.get_win32 (), real_path.iscygexec ())) + else if (!one_line.fromargv (newargv, real_path.get_win32 (), + real_path.iscygexec ())) { res = -1; goto out; @@ -395,12 +400,14 @@ spawn_guts (const char * prog_arg, const char *const *argv, if (mode != _P_OVERLAY || !DuplicateHandle (hMainProc, myself.shared_handle (), hMainProc, - &moreinfo->myself_pinfo, 0, - TRUE, DUPLICATE_SAME_ACCESS)) + &moreinfo->myself_pinfo, 0, TRUE, + DUPLICATE_SAME_ACCESS)) moreinfo->myself_pinfo = NULL; else VerifyHandle (moreinfo->myself_pinfo); } + WCHAR wone_line[one_line.ix + 1]; + sys_mbstowcs (wone_line, one_line.ix + 1, one_line.buf); PROCESS_INFORMATION pi; pi.hProcess = pi.hThread = NULL; @@ -418,7 +425,7 @@ spawn_guts (const char * prog_arg, const char *const *argv, c_flags = GetPriorityClass (hMainProc); sigproc_printf ("priority class %d", c_flags); - c_flags |= CREATE_SEPARATE_WOW_VDM; + c_flags |= CREATE_SEPARATE_WOW_VDM | CREATE_UNICODE_ENVIRONMENT; if (mode == _P_DETACH) c_flags |= DETACHED_PROCESS; @@ -444,8 +451,9 @@ spawn_guts (const char * prog_arg, const char *const *argv, generating its own pids again? */ if (cygheap->pid_handle) /* already done previously */; - else if (DuplicateHandle (hMainProc, hMainProc, hMainProc, &cygheap->pid_handle, - PROCESS_QUERY_INFORMATION, TRUE, 0)) + else if (DuplicateHandle (hMainProc, hMainProc, hMainProc, + &cygheap->pid_handle, PROCESS_QUERY_INFORMATION, + TRUE, 0)) ProtectHandleINH (cygheap->pid_handle); else system_printf ("duplicate to pid_handle failed, %E"); @@ -456,19 +464,22 @@ spawn_guts (const char * prog_arg, const char *const *argv, So we have to start the child in suspend state, unfortunately, to avoid a race condition. */ if (!newargv.win16_exe - && (!ch.iscygwin () || mode != _P_OVERLAY || cygheap->fdtab.need_fixup_before ())) + && (!ch.iscygwin () || mode != _P_OVERLAY + || cygheap->fdtab.need_fixup_before ())) c_flags |= CREATE_SUSPENDED; - runpath = null_app_name ? NULL : real_path.get_win32 (); + runpath = null_app_name ? NULL : real_path.get_wide_win32_path (runpath); - syscall_printf ("null_app_name %d (%s, %.9500s)", null_app_name, runpath, one_line.buf); + syscall_printf ("null_app_name %d (%W, %.9500W)", null_app_name, + runpath, wone_line); cygbench ("spawn-guts"); if (!real_path.iscygexec()) cygheap->fdtab.set_file_pointers_for_exec (); - moreinfo->envp = build_env (envp, envblock, moreinfo->envc, real_path.iscygexec ()); + moreinfo->envp = build_env (envp, envblock, moreinfo->envc, + real_path.iscygexec ()); if (!moreinfo->envp || !envblock) { set_errno (E2BIG); @@ -496,16 +507,16 @@ loop: && cygheap->user.saved_gid == cygheap->user.real_gid && !cygheap->user.groups.issetgroups ())) { - rc = CreateProcess (runpath, /* image name - with full path */ - one_line.buf, /* what was passed to exec */ - &sec_none_nih,/* process security attrs */ - &sec_none_nih,/* thread security attrs */ - TRUE, /* inherit handles from parent */ - c_flags, - envblock, /* environment */ - NULL, - &si, - &pi); + rc = CreateProcessW (runpath, /* image name - with full path */ + wone_line, /* what was passed to exec */ + &sec_none_nih, /* process security attrs */ + &sec_none_nih, /* thread security attrs */ + TRUE, /* inherit handles from parent */ + c_flags, + envblock, /* environment */ + NULL, + &si, + &pi); } else { @@ -513,7 +524,7 @@ loop: if (mode == _P_OVERLAY) myself.set_acl(); - char wstname[1024] = { '\0' }; + WCHAR wstname[1024] = { L'\0' }; HWINSTA hwst_orig = NULL, hwst = NULL; HDESK hdsk_orig = NULL, hdsk = NULL; PSECURITY_ATTRIBUTES sa; @@ -521,16 +532,16 @@ loop: hwst_orig = GetProcessWindowStation (); hdsk_orig = GetThreadDesktop (GetCurrentThreadId ()); - GetUserObjectInformation (hwst_orig, UOI_NAME, wstname, 1024, &n); + GetUserObjectInformationW (hwst_orig, UOI_NAME, wstname, 1024, &n); /* Prior to Vista it was possible to start a service with the "Interact with desktop" flag. This started the service in the interactive window station of the console. A big security risk, but we don't want to disable this behaviour for older OSes because it's still heavily used by some users. They have been warned. */ - if (!ascii_strcasematch (wstname, "WinSta0")) + if (wcscasecmp (wstname, L"WinSta0") != 0) { - char sid[128]; + WCHAR sid[128]; sa = sec_user ((PSECURITY_ATTRIBUTES) alloca (1024), cygheap->user.sid ()); @@ -540,34 +551,34 @@ loop: make sense in terms of security to create a new window station for every logon of the same user. It just fills up the system with window stations for no good reason. */ - hwst = CreateWindowStationA (cygheap->user.get_windows_id (sid), 0, + hwst = CreateWindowStationW (cygheap->user.get_windows_id (sid), 0, GENERIC_READ | GENERIC_WRITE, sa); if (!hwst) system_printf ("CreateWindowStation failed, %E"); else if (!SetProcessWindowStation (hwst)) system_printf ("SetProcessWindowStation failed, %E"); - else if (!(hdsk = CreateDesktopA ("Default", NULL, NULL, 0, + else if (!(hdsk = CreateDesktopW (L"Default", NULL, NULL, 0, GENERIC_ALL, sa))) system_printf ("CreateDesktop failed, %E"); else { - stpcpy (stpcpy (wstname, sid), "\\Default"); + wcpcpy (wcpcpy (wstname, sid), L"\\Default"); si.lpDesktop = wstname; - debug_printf ("Desktop: %s", si.lpDesktop); + debug_printf ("Desktop: %W", si.lpDesktop); } } - rc = CreateProcessAsUser (cygheap->user.primary_token (), - runpath, /* image name - with full path */ - one_line.buf, /* what was passed to exec */ - &sec_none_nih, /* process security attrs */ - &sec_none_nih, /* thread security attrs */ - TRUE, /* inherit handles from parent */ - c_flags, - envblock, /* environment */ - NULL, - &si, - &pi); + rc = CreateProcessAsUserW (cygheap->user.primary_token (), + runpath, /* image name - with full path */ + wone_line, /* what was passed to exec */ + &sec_none_nih, /* process security attrs */ + &sec_none_nih, /* thread security attrs */ + TRUE, /* inherit handles from parent */ + c_flags, + envblock, /* environment */ + NULL, + &si, + &pi); if (hwst) { SetProcessWindowStation (hwst_orig); @@ -952,16 +963,22 @@ av::fixup (const char *prog_arg, path_conv& real_path, const char *ext) char *pgm = NULL; char *arg1 = NULL; char *ptr, *buf; - - HANDLE h = CreateFile (real_path.get_win32 (), GENERIC_READ, - FILE_SHARE_READ | FILE_SHARE_WRITE, - &sec_none_nih, OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, 0); - if (h == INVALID_HANDLE_VALUE) + OBJECT_ATTRIBUTES attr; + IO_STATUS_BLOCK io; + HANDLE h; + NTSTATUS status; + + status = NtOpenFile (&h, SYNCHRONIZE | GENERIC_READ, + real_path.get_object_attr (attr, sec_none_nih), + &io, FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_SYNCHRONOUS_IO_NONALERT + | FILE_OPEN_FOR_BACKUP_INTENT + | FILE_NON_DIRECTORY_FILE); + if (!NT_SUCCESS (status)) goto err; HANDLE hm = CreateFileMapping (h, &sec_none_nih, PAGE_READONLY, 0, 0, NULL); - CloseHandle (h); + NtClose (h); if (!hm) { /* ERROR_FILE_INVALID indicates very likely an empty file. */ |