From 752b16ce359bb46948b8aa2bc88f7c32bf2cc95b Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Fri, 7 Mar 2008 11:24:51 +0000 Subject: [PATCH] * 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. --- winsup/cygwin/ChangeLog | 49 ++++++++++ winsup/cygwin/Makefile.in | 4 +- winsup/cygwin/autoload.cc | 6 +- winsup/cygwin/cygheap.h | 2 +- winsup/cygwin/cygtls.cc | 3 + winsup/cygwin/cygtls.h | 19 ++++ winsup/cygwin/environ.cc | 41 ++++---- winsup/cygwin/environ.h | 2 +- winsup/cygwin/external.cc | 13 +-- winsup/cygwin/fhandler_console.cc | 4 +- winsup/cygwin/fhandler_process.cc | 9 +- winsup/cygwin/fork.cc | 36 ++++--- winsup/cygwin/path.cc | 151 +++++++++++++++++++++++------- winsup/cygwin/path.h | 3 +- winsup/cygwin/pinfo.cc | 4 +- winsup/cygwin/registry.cc | 9 +- winsup/cygwin/spawn.cc | 117 +++++++++++++---------- winsup/cygwin/syscalls.cc | 10 +- winsup/cygwin/tls_pbuf.cc | 60 ++++++++++++ winsup/cygwin/tls_pbuf.h | 20 ++++ winsup/cygwin/tlsoffsets.h | 98 +++++++++---------- winsup/cygwin/winsup.h | 10 +- 22 files changed, 467 insertions(+), 203 deletions(-) create mode 100644 winsup/cygwin/tls_pbuf.cc create mode 100644 winsup/cygwin/tls_pbuf.h diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index a7ae9e73f..dd795bd04 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,52 @@ +2008-03-07 Corinna Vinschen + + * 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. + 2008-03-06 Corinna Vinschen * child_info.h (CURR_CHILD_INFO_MAGIC): Reset. diff --git a/winsup/cygwin/Makefile.in b/winsup/cygwin/Makefile.in index 9586bfdd2..35dc66c28 100644 --- a/winsup/cygwin/Makefile.in +++ b/winsup/cygwin/Makefile.in @@ -143,8 +143,8 @@ DLL_OFILES:=assert.o autoload.o bsdlib.o ctype.o cxx.o cygheap.o cygthread.o \ select.o sem.o shared.o shm.o sigfe.o signal.o sigproc.o smallprint.o \ spawn.o strace.o strfuncs.o strptime.o strsep.o strsig.o sync.o \ syscalls.o sysconf.o syslog.o termios.o thread.o timelocal.o timer.o \ - times.o tty.o uinfo.o uname.o v8_regexp.o v8_regerror.o v8_regsub.o \ - wait.o wincap.o window.o winf.o xsique.o \ + times.o tls_pbuf.o tty.o uinfo.o uname.o v8_regexp.o v8_regerror.o \ + v8_regsub.o wait.o wincap.o window.o winf.o xsique.o \ $(EXTRA_DLL_OFILES) $(EXTRA_OFILES) $(MALLOC_OFILES) $(MT_SAFE_OBJECTS) GMON_OFILES:=gmon.o mcount.o profil.o diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc index 24dea1f78..22b7b6f3e 100644 --- a/winsup/cygwin/autoload.cc +++ b/winsup/cygwin/autoload.cc @@ -324,9 +324,9 @@ LoadDLLfunc (CharNextExA, 12, user32) LoadDLLfunc (CloseClipboard, 0, user32) LoadDLLfunc (CloseDesktop, 4, user32) LoadDLLfunc (CloseWindowStation, 4, user32) -LoadDLLfunc (CreateDesktopA, 24, user32) +LoadDLLfunc (CreateDesktopW, 24, user32) LoadDLLfunc (CreateWindowExA, 48, user32) -LoadDLLfunc (CreateWindowStationA, 16, user32) +LoadDLLfunc (CreateWindowStationW, 16, user32) LoadDLLfunc (DefWindowProcA, 16, user32) LoadDLLfunc (DispatchMessageA, 4, user32) LoadDLLfunc (EmptyClipboard, 0, user32) @@ -339,7 +339,7 @@ LoadDLLfunc (GetPriorityClipboardFormat, 8, user32) LoadDLLfunc (GetProcessWindowStation, 0, user32) LoadDLLfunc (GetThreadDesktop, 4, user32) LoadDLLfunc (GetWindowThreadProcessId, 8, user32) -LoadDLLfunc (GetUserObjectInformationA, 20, user32) +LoadDLLfunc (GetUserObjectInformationW, 20, user32) LoadDLLfunc (MessageBeep, 4, user32) LoadDLLfunc (MessageBoxA, 16, user32) LoadDLLfunc (MsgWaitForMultipleObjects, 20, user32) diff --git a/winsup/cygwin/cygheap.h b/winsup/cygwin/cygheap.h index 567aecf69..d1bc5cc8a 100644 --- a/winsup/cygwin/cygheap.h +++ b/winsup/cygwin/cygheap.h @@ -230,7 +230,7 @@ struct cwdstuff HANDLE dir; DWORD drive_length; static muto cwd_lock; - char *get (char *, int = 1, int = 0, unsigned = CYG_MAX_PATH); + char *get (char *, int = 1, int = 0, unsigned = NT_MAX_PATH); HANDLE get_handle () { return dir; } DWORD get_drive (char * dst) { diff --git a/winsup/cygwin/cygtls.cc b/winsup/cygwin/cygtls.cc index 0370d06e8..749af0158 100644 --- a/winsup/cygwin/cygtls.cc +++ b/winsup/cygwin/cygtls.cc @@ -171,6 +171,9 @@ _cygtls::remove (DWORD wait) free_local (hostent_buf); } + /* Free temporary TLS path buffers. */ + locals.pathbufs.destroy (); + do { sentry here (wait); diff --git a/winsup/cygwin/cygtls.h b/winsup/cygwin/cygtls.h index 14ccffd41..43bdfee6a 100644 --- a/winsup/cygwin/cygtls.h +++ b/winsup/cygwin/cygtls.h @@ -33,7 +33,23 @@ details. */ #include "cygthread.h" +#define TP_NUM_C_BUFS 10 +#define TP_NUM_W_BUFS 10 + #pragma pack(push,4) +/* Defined here to support auto rebuild of tlsoffsets.h. */ +class tls_pathbuf +{ + int c_cnt; + int w_cnt; + char *c_buf[TP_NUM_C_BUFS]; + WCHAR *w_buf[TP_NUM_W_BUFS]; + +public: + void destroy (); + friend class tmp_pathbuf; +}; + struct _local_storage { /* @@ -96,6 +112,9 @@ struct _local_storage /* syscalls.cc */ int setmode_file; int setmode_mode; + + /* All functions requiring temporary path buffers. */ + tls_pathbuf pathbufs; }; typedef struct struct_waitq diff --git a/winsup/cygwin/environ.cc b/winsup/cygwin/environ.cc index 7e1fafd4a..3a427bb06 100644 --- a/winsup/cygwin/environ.cc +++ b/winsup/cygwin/environ.cc @@ -13,6 +13,7 @@ details. */ #include #include #include +#include #include #include #include @@ -27,6 +28,7 @@ details. */ #include "dtable.h" #include "cygheap.h" #include "cygtls.h" +#include "tls_pbuf.h" #include "registry.h" #include "environ.h" #include "child_info.h" @@ -117,7 +119,8 @@ win_env::add_cache (const char *in_posix, const char *in_native) } else { - char buf[NT_MAX_PATH]; + tmp_pathbuf tp; + char *buf = tp.c_get (); strcpy (buf, name + namelen); towin32 (in_posix, buf); native = (char *) realloc (native, namelen + 1 + strlen (buf)); @@ -173,7 +176,7 @@ getwinenv (const char *env, const char *in_posix, win_env *temp) /* Convert windows path specs to POSIX, if appropriate. */ static void __stdcall -posify (char **here, const char *value) +posify (char **here, const char *value, char *outenv) { char *src = *here; win_env *conv; @@ -186,7 +189,6 @@ posify (char **here, const char *value) /* Turn all the items from c:; into their mounted equivalents - if there is one. */ - char outenv[1 + len + NT_MAX_PATH]; memcpy (outenv, src, len); char *newvalue = outenv + len; if (!conv->toposix (value, newvalue) || _impure_ptr->_errno != EIDRM) @@ -740,6 +742,7 @@ environ_init (char **envp, int envc) bool got_something_from_registry; static char NO_COPY cygterm[] = "TERM=cygwin"; myfault efault; + tmp_pathbuf tp; if (efault.faulted ()) api_fatal ("internal error reading the windows environment - too many environment variables?"); @@ -804,6 +807,7 @@ environ_init (char **envp, int envc) form "=X:=X:\foo\bar; these must be changed into something legal (we could just ignore them but maybe an application will eventually want to use them). */ + char *tmpbuf = tp.t_get (); for (i = 0, w = rawenv; *w != L'\0'; w = wcschr (w, L'\0') + 1, i++) { sys_wcstombs_alloc (&newp, HEAP_NOTHEAP, w); @@ -820,7 +824,7 @@ environ_init (char **envp, int envc) if (*newp == 'C' && strncmp (newp, "CYGWIN=", sizeof ("CYGWIN=") - 1) == 0) parse_options (newp + sizeof ("CYGWIN=") - 1); if (*eq && conv_start_chars[(unsigned char)envp[i][0]]) - posify (envp + i, *++eq ? eq : --eq); + posify (envp + i, *++eq ? eq : --eq, tmpbuf); debug_printf ("%p: %s", envp[i], envp[i]); } @@ -957,7 +961,7 @@ spenv::retrieve (bool no_envblock, const char *const env) Converts environment variables noted in conv_envvars into win32 form prior to placing them in the string. */ char ** __stdcall -build_env (const char * const *envp, char *&envblock, int &envc, +build_env (const char * const *envp, PWCHAR &envblock, int &envc, bool no_envblock) { int len, n; @@ -1041,8 +1045,8 @@ build_env (const char * const *envp, char *&envblock, int &envc, qsort (pass_env, pass_envc, sizeof (char *), env_sort); /* Create an environment block suitable for passing to CreateProcess. */ - char *s; - envblock = (char *) malloc (2 + tl); + PWCHAR s; + envblock = (PWCHAR) malloc ((2 + tl) * sizeof (WCHAR)); int new_tl = 0; for (srcp = pass_env, s = envblock; *srcp; srcp++) { @@ -1067,20 +1071,14 @@ build_env (const char * const *envp, char *&envblock, int &envc, p = *srcp; /* Don't worry about it */ len = strlen (p) + 1; - if (len >= 32 * 1024) - { - free (envblock); - envblock = NULL; - goto out; - } new_tl += len; /* Keep running total of block length so far */ /* See if we need to increase the size of the block. */ if (new_tl > tl) { tl = new_tl + 100; - char *new_envblock = - (char *) realloc (envblock, 2 + tl); + PWCHAR new_envblock = + (PWCHAR) realloc (envblock, (2 + tl) * sizeof (WCHAR)); /* If realloc moves the block, move `s' with it. */ if (new_envblock != envblock) { @@ -1089,23 +1087,22 @@ build_env (const char * const *envp, char *&envblock, int &envc, } } - memcpy (s, p, len); + int slen = sys_mbstowcs (s, len, p, len); /* See if environment variable is "special" in a Windows sense. Under NT, the current directories for visited drives are stored as =C:=\bar. Cygwin converts the '=' to '!' for hopefully obvious reasons. We need to convert it back when building the envblock */ - if (s[0] == '!' && (isdrive (s + 1) || (s[1] == ':' && s[2] == ':')) - && s[3] == '=') - *s = '='; - s += len; + if (s[0] == L'!' && (iswdrive (s + 1) || (s[1] == L':' && s[2] == L':')) + && s[3] == L'=') + *s = L'='; + s += slen + 1; } - *s = '\0'; /* Two null bytes at the end */ + *s = L'\0'; /* Two null bytes at the end */ assert ((s - envblock) <= tl); /* Detect if we somehow ran over end of buffer */ } -out: debug_printf ("envp %p, envc %d", newenv, envc); return newenv; } diff --git a/winsup/cygwin/environ.h b/winsup/cygwin/environ.h index 84c88a3c9..c2c29cf9a 100644 --- a/winsup/cygwin/environ.h +++ b/winsup/cygwin/environ.h @@ -45,7 +45,7 @@ char * __stdcall getwinenveq (const char *name, size_t len, int) void __stdcall update_envptrs (); extern char **__cygwin_environ, ***main_environ; extern "C" char __stdcall **cur_environ (); -char ** __stdcall build_env (const char * const *envp, char *&envblock, +char ** __stdcall build_env (const char * const *envp, PWCHAR &envblock, int &envc, bool need_envblock) __attribute__ ((regparm (3))); diff --git a/winsup/cygwin/external.cc b/winsup/cygwin/external.cc index 111bd31c5..32492ba4d 100644 --- a/winsup/cygwin/external.cc +++ b/winsup/cygwin/external.cc @@ -32,6 +32,7 @@ details. */ #include "environ.h" #include #include +#include child_info *get_cygwin_startup_info (); @@ -137,9 +138,9 @@ static void sync_winenv () { int unused_envc; - char *envblock = NULL; + PWCHAR envblock = NULL; char **envp = build_env (cur_environ (), envblock, unused_envc, false); - char *p = envblock; + PWCHAR p = envblock; if (envp) { @@ -151,14 +152,14 @@ sync_winenv () return; while (*p) { - char *eq = strchr (p, '='); + PWCHAR eq = wcschr (p, L'='); if (eq) { - *eq = '\0'; - SetEnvironmentVariable (p, ++eq); + *eq = L'\0'; + SetEnvironmentVariableW (p, ++eq); p = eq; } - p = strchr (p, '\0') + 1; + p = wcschr (p, L'\0') + 1; } free (envblock); } diff --git a/winsup/cygwin/fhandler_console.cc b/winsup/cygwin/fhandler_console.cc index ca1c0879b..0a445aa2e 100644 --- a/winsup/cygwin/fhandler_console.cc +++ b/winsup/cygwin/fhandler_console.cc @@ -1919,7 +1919,7 @@ fhandler_console::need_invisible () USEROBJECTFLAGS oi; DWORD len; if (!horig - || !GetUserObjectInformation (horig, UOI_FLAGS, &oi, sizeof (oi), &len) + || !GetUserObjectInformationW (horig, UOI_FLAGS, &oi, sizeof (oi), &len) || !(oi.dwFlags & WSF_VISIBLE)) { b = true; @@ -1930,7 +1930,7 @@ fhandler_console::need_invisible () { if (myself->ctty != TTY_CONSOLE) { - h = CreateWindowStation (NULL, 0, WINSTA_ACCESS, NULL); + h = CreateWindowStationW (NULL, 0, WINSTA_ACCESS, NULL); termios_printf ("%p = CreateWindowStation(NULL), %E", h); if (h) { diff --git a/winsup/cygwin/fhandler_process.cc b/winsup/cygwin/fhandler_process.cc index b32f83960..b5aa6dfb9 100644 --- a/winsup/cygwin/fhandler_process.cc +++ b/winsup/cygwin/fhandler_process.cc @@ -23,6 +23,7 @@ details. */ #include "cygheap.h" #include "ntdll.h" #include "cygtls.h" +#include "tls_pbuf.h" #include #include #include @@ -525,8 +526,10 @@ format_process_maps (_pinfo *p, char *&destbuf, size_t maxsize) DWORD_PTR wset_size; DWORD_PTR *workingset = NULL; MODULEINFO info; - WCHAR modname[NT_MAX_PATH]; - char posix_modname[NT_MAX_PATH]; + + tmp_pathbuf tp; + PWCHAR modname = tp.w_get (); + char *posix_modname = tp.c_get (); if (!EnumProcessModules (proc, NULL, 0, &needed)) { @@ -552,7 +555,7 @@ format_process_maps (_pinfo *p, char *&destbuf, size_t maxsize) } for (i = 0; i < needed / sizeof (HMODULE); i++) if (GetModuleInformation (proc, modules[i], &info, sizeof info) - && GetModuleFileNameExW (proc, modules[i], modname, sizeof modname)) + && GetModuleFileNameExW (proc, modules[i], modname, NT_MAX_PATH)) { char access[5]; strcpy (access, "r--p"); diff --git a/winsup/cygwin/fork.cc b/winsup/cygwin/fork.cc index 730bc386c..923c1dccc 100644 --- a/winsup/cygwin/fork.cc +++ b/winsup/cygwin/fork.cc @@ -24,6 +24,7 @@ details. */ #include "cygheap.h" #include "child_info.h" #include "cygtls.h" +#include "tls_pbuf.h" #include "perprocess.h" #include "dll_init.h" #include "sync.h" @@ -348,16 +349,21 @@ frok::parent (volatile char * volatile stack_here) ch.stackbottom, ch.stacktop, ch.stacksize); PROCESS_INFORMATION pi; - STARTUPINFO si; + STARTUPINFOW si; memset (&si, 0, sizeof (si)); - si.cb = sizeof (STARTUPINFO); + si.cb = sizeof si; si.lpReserved2 = (LPBYTE) &ch; si.cbReserved2 = sizeof (ch); - syscall_printf ("CreateProcess (%s, %s, 0, 0, 1, %p, 0, 0, %p, %p)", - myself->progname, myself->progname, c_flags, &si, &pi); + /* FIXME: myself->progname should be converted to WCHAR. */ + tmp_pathbuf tp; + PWCHAR progname = tp.w_get (); + sys_mbstowcs (progname, NT_MAX_PATH, myself->progname); + + syscall_printf ("CreateProcess (%W, %W, 0, 0, 1, %p, 0, 0, %p, %p)", + progname, progname, c_flags, &si, &pi); bool locked = __malloc_lock (); time_t start_time = time (NULL); @@ -367,21 +373,21 @@ frok::parent (volatile char * volatile stack_here) while (1) { - rc = CreateProcess (myself->progname, /* image to run */ - myself->progname, /* what we send in arg0 */ - &sec_none_nih, - &sec_none_nih, - TRUE, /* inherit handles from parent */ - c_flags, - NULL, /* environment filled in later */ - 0, /* use current drive/directory */ - &si, - &pi); + rc = CreateProcessW (progname, /* image to run */ + progname, /* what we send in arg0 */ + &sec_none_nih, + &sec_none_nih, + TRUE, /* inherit handles from parent */ + c_flags, + NULL, /* environment filled in later */ + 0, /* use current drive/directory */ + &si, + &pi); if (!rc) { this_errno = geterrno_from_win_error (); - error = "CreateProcessA failed"; + error = "CreateProcessW failed"; memset (&pi, 0, sizeof (pi)); goto cleanup; } diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index 4c4ce2966..11d01bc47 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -76,6 +76,7 @@ details. */ #include "shared_info.h" #include "registry.h" #include "cygtls.h" +#include "tls_pbuf.h" #include "environ.h" #include #include @@ -319,7 +320,7 @@ normalize_posix_path (const char *src, char *dst, char *&tail) *tail++ = '/'; } - if ((tail - dst) >= CYG_MAX_PATH) + if ((tail - dst) >= NT_MAX_PATH) { debug_printf ("ENAMETOOLONG = normalize_posix_path (%s)", src); return ENAMETOOLONG; @@ -355,7 +356,8 @@ static void __stdcall mkrelpath (char *dst) __attribute__ ((regparm (2))); static void __stdcall mkrelpath (char *path) { - char cwd_win32[CYG_MAX_PATH]; + tmp_pathbuf tp; + char *cwd_win32 = tp.c_get (); if (!cygheap->cwd.get (cwd_win32, 0)) return; @@ -647,7 +649,8 @@ warn_msdos (const char *src) { if (user_shared->warned_msdos || !dos_file_warning) return; - char posix_path[CYG_MAX_PATH]; + tmp_pathbuf tp; + char *posix_path = tp.c_get (); small_printf ("cygwin warning:\n"); if (cygwin_conv_to_full_posix_path (src, posix_path)) small_printf (" MS-DOS style path detected: %s\n POSIX equivalent preferred.\n", @@ -662,6 +665,56 @@ warn_msdos (const char *src) user_shared->warned_msdos = true; } +static DWORD +getfileattr (const char *path) /* path has to be always absolute. */ +{ + tmp_pathbuf tp; + UNICODE_STRING upath; + OBJECT_ATTRIBUTES attr; + FILE_BASIC_INFORMATION fbi; + NTSTATUS status; + IO_STATUS_BLOCK io; + + RtlInitEmptyUnicodeString (&upath, tp.w_get (), NT_MAX_PATH * sizeof (WCHAR)); + InitializeObjectAttributes (&attr, &upath, OBJ_CASE_INSENSITIVE, NULL, NULL); + get_nt_native_path (path, upath); + + status = NtQueryAttributesFile (&attr, &fbi); + if (NT_SUCCESS (status)) + return fbi.FileAttributes; + + if (status != STATUS_OBJECT_NAME_NOT_FOUND + && status != STATUS_NO_SUCH_FILE) /* File not found on 9x share */ + { + /* File exists but access denied. Try to get attribute through + directory query. */ + UNICODE_STRING dirname, basename; + HANDLE dir; + FILE_DIRECTORY_INFORMATION fdi; + + RtlSplitUnicodePath (&upath, &dirname, &basename); + InitializeObjectAttributes (&attr, &dirname, + OBJ_CASE_INSENSITIVE, NULL, NULL); + status = NtOpenFile (&dir, SYNCHRONIZE | FILE_LIST_DIRECTORY, + &attr, &io, FILE_SHARE_VALID_FLAGS, + FILE_SYNCHRONOUS_IO_NONALERT + | FILE_OPEN_FOR_BACKUP_INTENT + | FILE_DIRECTORY_FILE); + if (NT_SUCCESS (status)) + { + status = NtQueryDirectoryFile (dir, NULL, NULL, 0, &io, + &fdi, sizeof fdi, + FileDirectoryInformation, + TRUE, &basename, TRUE); + NtClose (dir); + if (NT_SUCCESS (status) || status == STATUS_BUFFER_OVERFLOW) + return fdi.FileAttributes; + } + } + SetLastError (RtlNtStatusToDosError (status)); + return INVALID_FILE_ATTRIBUTES; +} + /* Convert an arbitrary path SRC to a pure Win32 path, suitable for passing to Win32 API routines. @@ -685,10 +738,11 @@ void path_conv::check (PUNICODE_STRING src, unsigned opt, const suffix_info *suffixes) { - char path[CYG_MAX_PATH]; + tmp_pathbuf tp; + char *path = tp.c_get (); user_shared->warned_msdos = true; - sys_wcstombs (path, CYG_MAX_PATH, src->Buffer, src->Length / 2); + sys_wcstombs (path, NT_MAX_PATH, src->Buffer, src->Length / 2); path_conv::check (path, opt, suffixes); } @@ -696,11 +750,12 @@ void path_conv::check (const char *src, unsigned opt, const suffix_info *suffixes) { - /* This array is used when expanding symlinks. It is CYG_MAX_PATH * 2 - in length so that we can hold the expanded symlink plus a - trailer. */ - char path_copy[CYG_MAX_PATH + 3]; - char tmp_buf[2 * CYG_MAX_PATH + 3]; + /* The tmp_buf array is used when expanding symlinks. It is NT_MAX_PATH * 2 + in length so that we can hold the expanded symlink plus a trailer. */ + tmp_pathbuf tp; + char *path_copy = tp.c_get (); + char *pathbuf = tp.c_get (); + char *tmp_buf = tp.t_get (); symlink_info sym; bool need_directory = 0; bool saw_symlinks = 0; @@ -785,7 +840,6 @@ path_conv::check (const char *src, unsigned opt, for (unsigned pflags_or = opt & PC_NO_ACCESS_CHECK; ; pflags_or = 0) { const suffix_info *suff; - char pathbuf[CYG_MAX_PATH]; char *full_path; /* Don't allow symlink.check to set anything in the path_conv @@ -818,7 +872,7 @@ path_conv::check (const char *src, unsigned opt, fileattr = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_READONLY; else { - fileattr = GetFileAttributes (this->path); + fileattr = getfileattr (this->path); dev.devn = FH_FS; } goto out; @@ -827,7 +881,7 @@ path_conv::check (const char *src, unsigned opt, { dev.devn = FH_FS; #if 0 - fileattr = GetFileAttributes (this->path); + fileattr = getfileattr (this->path); if (!component && fileattr == INVALID_FILE_ATTRIBUTES) { fileattr = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_READONLY; @@ -1050,7 +1104,7 @@ virtual_component_retry: } /* Make sure there is enough space */ - if (headptr + symlen >= tmp_buf + sizeof (tmp_buf)) + if (headptr + symlen >= tmp_buf + (2 * NT_MAX_PATH)) { too_long: error = ENAMETOOLONG; @@ -1071,7 +1125,7 @@ virtual_component_retry: if (*(headptr - 1) != '/') *headptr++ = '/'; int taillen = path_end - tail + 1; - if (headptr + taillen > tmp_buf + sizeof (tmp_buf)) + if (headptr + taillen > tmp_buf + (2 * NT_MAX_PATH)) goto too_long; memcpy (headptr, tail, taillen); } @@ -1239,11 +1293,12 @@ path_conv::~path_conv () bool path_conv::is_binary () { + tmp_pathbuf tp; + PWCHAR bintest = tp.w_get (); DWORD bin; - PBYTE bintest[get_nt_native_path ()->Length + sizeof (WCHAR)]; return exec_state () == is_executable && RtlEqualUnicodePathSuffix (get_nt_native_path (), L".exe", TRUE) - && GetBinaryTypeW (get_wide_win32_path ((PWCHAR) bintest), &bin); + && GetBinaryTypeW (get_wide_win32_path (bintest), &bin); } /* Return true if src_path is a valid, internally supported device name. @@ -1286,6 +1341,19 @@ normalize_win32_path (const char *src, char *dst, char *&tail) bool beg_src_slash = isdirsep (src[0]); tail = dst; + /* Skip long path name prefixes in Win32 or NT syntax. */ + if (beg_src_slash && (src[1] == '?' || isdirsep (src[1])) + && src[2] == '?' && isdirsep (src[3])) + { + src += 4; + if (ascii_strncasematch (src, "UNC", 3)) + { + src += 2; /* Fortunately the first char is not copied... */ + beg_src_slash = true; + } + else + beg_src_slash = isdirsep (src[0]); + } if (beg_src_slash && isdirsep (src[1])) { if (isdirsep (src[2])) @@ -1360,7 +1428,7 @@ normalize_win32_path (const char *src, char *dst, char *&tail) *tail++ = *src; src++; } - if ((tail - dst) >= CYG_MAX_PATH) + if ((tail - dst) >= NT_MAX_PATH) return ENAMETOOLONG; } if (tail > dst + 1 && tail[-1] == '.' && tail[-2] == '\\') @@ -1463,7 +1531,7 @@ conv_path_list (const char *src, char *dst, int to_posix) { char *s = strccpy (srcbuf, &src, src_delim); int len = s - srcbuf; - if (len >= CYG_MAX_PATH) + if (len >= NT_MAX_PATH) { err = ENAMETOOLONG; break; @@ -1704,14 +1772,14 @@ mount_item::build_win32 (char *dst, const char *src, unsigned *outflags, unsigne dst[n++] = '\\'; if (!*p || !(flags & MOUNT_ENC)) { - if ((n + strlen (p)) >= CYG_MAX_PATH) + if ((n + strlen (p)) >= NT_MAX_PATH) err = ENAMETOOLONG; else backslashify (p, dst + n, 0); } else { - int left = CYG_MAX_PATH - n; + int left = NT_MAX_PATH - n; while (*p) { char slash = 0; @@ -1743,7 +1811,7 @@ mount_item::build_win32 (char *dst, const char *src, unsigned *outflags, unsigne The result is zero for success, or an errno value. - {,full_}win32_path must have sufficient space (i.e. CYG_MAX_PATH bytes). */ + {,full_}win32_path must have sufficient space (i.e. NT_MAX_PATH bytes). */ int mount_info::conv_to_win32_path (const char *src_path, char *dst, device& dev, @@ -1983,7 +2051,7 @@ mount_info::cygdrive_win32_path (const char *src, char *dst, int& unit) /* conv_to_posix_path: Ensure src_path is a POSIX path. The result is zero for success, or an errno value. - posix_path must have sufficient space (i.e. CYG_MAX_PATH bytes). + posix_path must have sufficient space (i.e. NT_MAX_PATH bytes). If keep_rel_p is non-zero, relative paths stay that way. */ /* TODO: Change conv_to_posix_path to work with native paths. */ @@ -2004,7 +2072,8 @@ mount_info::conv_to_posix_path (PWCHAR src_path, char *posix_path, changed = true; } } - char buf[NT_MAX_PATH]; + tmp_pathbuf tp; + char *buf = tp.c_get (); sys_wcstombs (buf, NT_MAX_PATH, src_path); int ret = conv_to_posix_path (buf, posix_path, keep_rel_p); if (changed) @@ -2033,7 +2102,7 @@ mount_info::conv_to_posix_path (const char *src_path, char *posix_path, trailing_slash_p ? "add-slash" : "no-add-slash"); MALLOC_CHECK; - if (src_path_len >= CYG_MAX_PATH) + if (src_path_len >= NT_MAX_PATH) { debug_printf ("ENAMETOOLONG"); return ENAMETOOLONG; @@ -2049,7 +2118,8 @@ mount_info::conv_to_posix_path (const char *src_path, char *posix_path, return 0; } - char pathbuf[CYG_MAX_PATH]; + tmp_pathbuf tp; + char *pathbuf = tp.c_get (); char *tail; int rc = normalize_win32_path (src_path, pathbuf, tail); if (rc != 0) @@ -2059,6 +2129,7 @@ mount_info::conv_to_posix_path (const char *src_path, char *posix_path, } int pathbuflen = tail - pathbuf; + char *tmpbuf = tp.c_get (); for (int i = 0; i < nmounts; ++i) { mount_item &mi = mount[native_sorted[i]]; @@ -2080,7 +2151,7 @@ mount_info::conv_to_posix_path (const char *src_path, char *posix_path, nextchar = 1; int addslash = nextchar > 0 ? 1 : 0; - if ((mi.posix_pathlen + (pathbuflen - mi.native_pathlen) + addslash) >= CYG_MAX_PATH) + if ((mi.posix_pathlen + (pathbuflen - mi.native_pathlen) + addslash) >= NT_MAX_PATH) return ENAMETOOLONG; strcpy (posix_path, mi.posix_path); if (addslash) @@ -2097,7 +2168,6 @@ mount_info::conv_to_posix_path (const char *src_path, char *posix_path, } if (mi.flags & MOUNT_ENC) { - char tmpbuf[CYG_MAX_PATH]; if (fnunmunge (tmpbuf, posix_path)) strcpy (posix_path, tmpbuf); } @@ -2161,6 +2231,10 @@ mount_info::set_flags_from_win32_path (const char *p) void mount_info::read_mounts (reg_key& r) { + tmp_pathbuf tp; + char *native_path = tp.c_get (); + /* FIXME: The POSIX path is stored as value name right now, which is + restricted to 256 bytes. */ char posix_path[CYG_MAX_PATH]; HKEY key = r.get_key (); DWORD i, posix_path_size; @@ -2172,7 +2246,6 @@ mount_info::read_mounts (reg_key& r) arbitrarily large number of mounts. */ for (i = 0; ; i++) { - char native_path[CYG_MAX_PATH]; int mount_flags; posix_path_size = sizeof (posix_path); @@ -2194,7 +2267,7 @@ mount_info::read_mounts (reg_key& r) reg_key subkey = reg_key (key, KEY_READ, posix_path, NULL); /* Fetch info from the subkey. */ - subkey.get_string ("native", native_path, sizeof (native_path), ""); + subkey.get_string ("native", native_path, NT_MAX_PATH, ""); mount_flags = subkey.get_int ("flags", 0); /* Add mount_item corresponding to registry mount point. */ @@ -2533,7 +2606,10 @@ mount_info::sort () int mount_info::add_item (const char *native, const char *posix, unsigned mountflags, int reg_p) { - char nativetmp[CYG_MAX_PATH]; + tmp_pathbuf tp; + char *nativetmp = tp.c_get (); + /* FIXME: The POSIX path is stored as value name right now, which is + restricted to 256 bytes. */ char posixtmp[CYG_MAX_PATH]; char *nativetail, *posixtail, error[] = "error"; int nativeerr, posixerr; @@ -2607,7 +2683,8 @@ mount_info::add_item (const char *native, const char *posix, unsigned mountflags int mount_info::del_item (const char *path, unsigned flags, int reg_p) { - char pathtmp[CYG_MAX_PATH]; + tmp_pathbuf tp; + char *pathtmp = tp.c_get (); int posix_path_p = false; /* Something's wrong if path is NULL or empty. */ @@ -3969,11 +4046,11 @@ getcwd (char *buf, size_t ulen) return res; } -/* getwd: standards? */ +/* getwd: Legacy. */ extern "C" char * getwd (char *buf) { - return getcwd (buf, CYG_MAX_PATH); + return getcwd (buf, PATH_MAX + 1); /*Per SuSv3!*/ } /* chdir: POSIX 5.2.1.1 */ @@ -4558,9 +4635,10 @@ cwdstuff::set (PUNICODE_STRING nat_cwd, const char *posix_cwd, bool doit) else drive_length = 0; + tmp_pathbuf tp; if (!posix_cwd) { - posix_cwd = (const char *) alloca (NT_MAX_PATH); + posix_cwd = (const char *) tp.c_get (); mount_table->conv_to_posix_path (win32.Buffer, (char *) posix_cwd, 0); } posix = (char *) crealloc_abort (posix, strlen (posix_cwd) + 1); @@ -4578,6 +4656,7 @@ cwdstuff::get (char *buf, int need_posix, int with_chroot, unsigned ulen) { MALLOC_CHECK; + tmp_pathbuf tp; if (ulen) /* nothing */; else if (buf == NULL) @@ -4593,7 +4672,7 @@ cwdstuff::get (char *buf, int need_posix, int with_chroot, unsigned ulen) char *tocopy; if (!need_posix) { - tocopy = (char *) alloca (NT_MAX_PATH); + tocopy = tp.c_get (); sys_wcstombs (tocopy, NT_MAX_PATH, win32.Buffer, win32.Length); } else diff --git a/winsup/cygwin/path.h b/winsup/cygwin/path.h index a19f382bc..268a1a5f1 100644 --- a/winsup/cygwin/path.h +++ b/winsup/cygwin/path.h @@ -283,7 +283,7 @@ class path_conv DWORD get_symlink_length () { return symlink_length; }; private: DWORD symlink_length; - char path[CYG_MAX_PATH]; + char path[NT_MAX_PATH]; }; /* Symlink marker */ @@ -310,6 +310,7 @@ const char * __stdcall find_exec (const char *name, path_conv& buf, /* Common macros for checking for invalid path names */ #define isdrive(s) (isalpha (*(s)) && (s)[1] == ':') +#define iswdrive(s) (iswalpha (*(s)) && (s)[1] == L':') static inline bool has_exec_chars (const char *buf, int len) diff --git a/winsup/cygwin/pinfo.cc b/winsup/cygwin/pinfo.cc index 632cc5f71..85fdf9b37 100644 --- a/winsup/cygwin/pinfo.cc +++ b/winsup/cygwin/pinfo.cc @@ -33,6 +33,7 @@ details. */ #include "fhandler.h" #include "cygmalloc.h" #include "cygtls.h" +#include "tls_pbuf.h" #include "child_info.h" static char NO_COPY pinfo_dummy[sizeof (_pinfo)] = {0}; @@ -392,7 +393,8 @@ DWORD WINAPI commune_process (void *arg) { siginfo_t& si = *((siginfo_t *) arg); - char path[NT_MAX_PATH]; + tmp_pathbuf tp; + char *path = tp.c_get (); DWORD nr; HANDLE& tothem = si._si_commune._si_write_handle; HANDLE process_sync = diff --git a/winsup/cygwin/registry.cc b/winsup/cygwin/registry.cc index 8316551a5..ce0987502 100644 --- a/winsup/cygwin/registry.cc +++ b/winsup/cygwin/registry.cc @@ -19,6 +19,7 @@ details. */ #include "fhandler.h" #include "dtable.h" #include "cygheap.h" +#include "tls_pbuf.h" #include static const char cygnus_class[] = "cygnus"; @@ -220,12 +221,13 @@ get_registry_hive_path (const PWCHAR name, PWCHAR path) wcpcpy (kend, name); if (!RegOpenKeyExW (HKEY_LOCAL_MACHINE, key, 0, KEY_READ, &hkey)) { - WCHAR buf[NT_MAX_PATH]; + tmp_pathbuf tp; + PWCHAR buf = tp.w_get (); DWORD type, siz; path[0] = L'\0'; if (!RegQueryValueExW (hkey, L"ProfileImagePath", 0, &type, - (BYTE *)buf, (siz = sizeof (buf), &siz))) + (BYTE *)buf, (siz = NT_MAX_PATH, &siz))) ExpandEnvironmentStringsW (buf, path, NT_MAX_PATH); RegCloseKey (hkey); if (path[0]) @@ -238,7 +240,8 @@ get_registry_hive_path (const PWCHAR name, PWCHAR path) void load_registry_hive (const PWCHAR name) { - WCHAR path[NT_MAX_PATH]; + tmp_pathbuf tp; + PWCHAR path = tp.w_get (); HKEY hkey; LONG ret; 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 #include #include +#include #include #include "cygerrno.h" #include @@ -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; + OBJECT_ATTRIBUTES attr; + IO_STATUS_BLOCK io; + HANDLE h; + NTSTATUS status; - 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) + 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. */ diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc index d18cf98fa..bc472322e 100644 --- a/winsup/cygwin/syscalls.cc +++ b/winsup/cygwin/syscalls.cc @@ -2336,7 +2336,7 @@ static int __stdcall mknod_worker (const char *path, mode_t type, mode_t mode, _major_t major, _minor_t minor) { - char buf[sizeof (":\\00000000:00000000:00000000") + CYG_MAX_PATH]; + char buf[sizeof (":\\00000000:00000000:00000000") + PATH_MAX]; sprintf (buf, ":\\%x:%x:%x", major, minor, type | (mode & (S_IRWXU | S_IRWXG | S_IRWXO))); return symlink_worker (buf, path, true, true); @@ -2354,7 +2354,7 @@ mknod32 (const char *path, mode_t mode, __dev32_t dev) return -1; } - if (strlen (path) >= CYG_MAX_PATH) + if (strlen (path) >= PATH_MAX) return -1; path_conv w32path (path, PC_SYM_NOFOLLOW); @@ -3327,7 +3327,7 @@ getusershell () "/usr/bin/csh", NULL }; - static char buf[CYG_MAX_PATH]; + static char buf[PATH_MAX]; int ch, buf_idx; if (!shell_fp && !(shell_fp = fopen64 (ETC_SHELLS, "rt"))) @@ -3342,11 +3342,11 @@ getusershell () /* Get each non-whitespace character as part of the shell path as long as it fits in buf. */ for (buf_idx = 0; - ch != EOF && !isspace (ch) && buf_idx < CYG_MAX_PATH; + ch != EOF && !isspace (ch) && buf_idx < PATH_MAX; buf_idx++, ch = getc (shell_fp)) buf[buf_idx] = ch; /* Skip any trailing non-whitespace character not fitting in buf. If the - path is longer than CYG_MAX_PATH, it's invalid anyway. */ + path is longer than PATH_MAX, it's invalid anyway. */ while (ch != EOF && !isspace (ch)) ch = getc (shell_fp); if (buf_idx) diff --git a/winsup/cygwin/tls_pbuf.cc b/winsup/cygwin/tls_pbuf.cc new file mode 100644 index 000000000..704f3bfc9 --- /dev/null +++ b/winsup/cygwin/tls_pbuf.cc @@ -0,0 +1,60 @@ +/* tls_pbuf.cc + + Copyright 2008 Red Hat, Inc. + +This software is a copyrighted work licensed under the terms of the +Cygwin license. Please consult the file "CYGWIN_LICENSE" for +details. */ + +#include +#include +#include "thread.h" +#include "cygtls.h" +#include "tls_pbuf.h" + +#define tls_pbuf _my_tls.locals.pathbufs + +void +tls_pathbuf::destroy () +{ + for (int i = 0; i < TP_NUM_C_BUFS; ++i) + if (c_buf[i]) + free (c_buf[i]); + for (int i = 0; i < TP_NUM_W_BUFS; ++i) + if (w_buf[i]) + free (w_buf[i]); +} + +tmp_pathbuf::tmp_pathbuf () +: c_buf_old (tls_pbuf.c_cnt), + w_buf_old (tls_pbuf.w_cnt) +{} + +tmp_pathbuf::~tmp_pathbuf () +{ + tls_pbuf.c_cnt = c_buf_old; + tls_pbuf.w_cnt = w_buf_old; +} + +char * +tmp_pathbuf::c_get () +{ + if (tls_pbuf.c_cnt >= TP_NUM_C_BUFS) + api_fatal ("Internal error: TP_NUM_C_BUFS too small."); + if (!tls_pbuf.c_buf[tls_pbuf.c_cnt] + && !(tls_pbuf.c_buf[tls_pbuf.c_cnt] = (char *) malloc (NT_MAX_PATH))) + api_fatal ("Internal error: Out of memory for new path buf."); + return tls_pbuf.c_buf[tls_pbuf.c_cnt++]; +} + +PWCHAR +tmp_pathbuf::w_get () +{ + if (tls_pbuf.w_cnt >= TP_NUM_W_BUFS) + api_fatal ("Internal error: TP_NUM_W_BUFS too small."); + if (!tls_pbuf.w_buf[tls_pbuf.w_cnt] + && !(tls_pbuf.w_buf[tls_pbuf.w_cnt] + = (PWCHAR) malloc (NT_MAX_PATH * sizeof (WCHAR)))) + api_fatal ("Internal error: Out of memory for new wide path buf."); + return tls_pbuf.w_buf[tls_pbuf.w_cnt++]; +} diff --git a/winsup/cygwin/tls_pbuf.h b/winsup/cygwin/tls_pbuf.h new file mode 100644 index 000000000..b4a2a7a37 --- /dev/null +++ b/winsup/cygwin/tls_pbuf.h @@ -0,0 +1,20 @@ +/* tls_pbuf.h + + Copyright 2008 Red Hat, Inc. + +This software is a copyrighted work licensed under the terms of the +Cygwin license. Please consult the file "CYGWIN_LICENSE" for +details. */ + +class tmp_pathbuf +{ + int c_buf_old; + int w_buf_old; +public: + tmp_pathbuf (); + ~tmp_pathbuf (); + + char *c_get (); /* Create temporary TLS path buf of size NT_MAX_PATH. */ + PWCHAR w_get (); /* Create temporary TLS path buf of size 2 * NT_MAX_PATH. */ + inline char *t_get () { return (char *) w_get (); } +}; diff --git a/winsup/cygwin/tlsoffsets.h b/winsup/cygwin/tlsoffsets.h index 5fa884ecb..c82520112 100644 --- a/winsup/cygwin/tlsoffsets.h +++ b/winsup/cygwin/tlsoffsets.h @@ -1,6 +1,6 @@ //;# autogenerated: Do not edit. -//; $tls::sizeof__cygtls = 4196; +//; $tls::sizeof__cygtls = 4284; //; $tls::func = -12700; //; $tls::pfunc = 0; //; $tls::el = -12696; @@ -39,30 +39,30 @@ //; $tls::p__dontuse = 420; //; $tls::locals = -11216; //; $tls::plocals = 1484; -//; $tls::_ctinfo = -9600; -//; $tls::p_ctinfo = 3100; -//; $tls::andreas = -9596; -//; $tls::pandreas = 3104; -//; $tls::wq = -9588; -//; $tls::pwq = 3112; -//; $tls::prev = -9560; -//; $tls::pprev = 3140; -//; $tls::next = -9556; -//; $tls::pnext = 3144; -//; $tls::sig = -9552; -//; $tls::psig = 3148; -//; $tls::incyg = -9548; -//; $tls::pincyg = 3152; -//; $tls::spinning = -9544; -//; $tls::pspinning = 3156; -//; $tls::stacklock = -9540; -//; $tls::pstacklock = 3160; -//; $tls::stackptr = -9536; -//; $tls::pstackptr = 3164; -//; $tls::stack = -9532; -//; $tls::pstack = 3168; -//; $tls::initialized = -8508; -//; $tls::pinitialized = 4192; +//; $tls::_ctinfo = -9512; +//; $tls::p_ctinfo = 3188; +//; $tls::andreas = -9508; +//; $tls::pandreas = 3192; +//; $tls::wq = -9500; +//; $tls::pwq = 3200; +//; $tls::prev = -9472; +//; $tls::pprev = 3228; +//; $tls::next = -9468; +//; $tls::pnext = 3232; +//; $tls::sig = -9464; +//; $tls::psig = 3236; +//; $tls::incyg = -9460; +//; $tls::pincyg = 3240; +//; $tls::spinning = -9456; +//; $tls::pspinning = 3244; +//; $tls::stacklock = -9452; +//; $tls::pstacklock = 3248; +//; $tls::stackptr = -9448; +//; $tls::pstackptr = 3252; +//; $tls::stack = -9444; +//; $tls::pstack = 3256; +//; $tls::initialized = -8420; +//; $tls::pinitialized = 4280; //; __DATA__ #define tls_func (-12700) @@ -103,27 +103,27 @@ #define tls_p__dontuse (420) #define tls_locals (-11216) #define tls_plocals (1484) -#define tls__ctinfo (-9600) -#define tls_p_ctinfo (3100) -#define tls_andreas (-9596) -#define tls_pandreas (3104) -#define tls_wq (-9588) -#define tls_pwq (3112) -#define tls_prev (-9560) -#define tls_pprev (3140) -#define tls_next (-9556) -#define tls_pnext (3144) -#define tls_sig (-9552) -#define tls_psig (3148) -#define tls_incyg (-9548) -#define tls_pincyg (3152) -#define tls_spinning (-9544) -#define tls_pspinning (3156) -#define tls_stacklock (-9540) -#define tls_pstacklock (3160) -#define tls_stackptr (-9536) -#define tls_pstackptr (3164) -#define tls_stack (-9532) -#define tls_pstack (3168) -#define tls_initialized (-8508) -#define tls_pinitialized (4192) +#define tls__ctinfo (-9512) +#define tls_p_ctinfo (3188) +#define tls_andreas (-9508) +#define tls_pandreas (3192) +#define tls_wq (-9500) +#define tls_pwq (3200) +#define tls_prev (-9472) +#define tls_pprev (3228) +#define tls_next (-9468) +#define tls_pnext (3232) +#define tls_sig (-9464) +#define tls_psig (3236) +#define tls_incyg (-9460) +#define tls_pincyg (3240) +#define tls_spinning (-9456) +#define tls_pspinning (3244) +#define tls_stacklock (-9452) +#define tls_pstacklock (3248) +#define tls_stackptr (-9448) +#define tls_pstackptr (3252) +#define tls_stack (-9444) +#define tls_pstack (3256) +#define tls_initialized (-8420) +#define tls_pinitialized (4280) diff --git a/winsup/cygwin/winsup.h b/winsup/cygwin/winsup.h index 957cc38fd..e10ffe989 100644 --- a/winsup/cygwin/winsup.h +++ b/winsup/cygwin/winsup.h @@ -81,9 +81,13 @@ extern unsigned long cygwin_inet_addr (const char *cp); buffer sizes. As MAX_PATH and PATH_MAX, this is defined including the trailing 0. Internal buffers and internal path routines should use NT_MAX_PATH. PATH_MAX as defined in limits.h is the maximum length of - application provided path strings we handle. */ -/* FIXME: The name is preliminary and TBD. */ -#define NT_MAX_PATH 32768 + application provided path strings we handle. + + Note that it's defined one less than 32K. This is not only big enough, + it also allows to use the value in UNICODE_STRING fields Length and + MaximumLength when multiplied with sizeof (WCHAR). Both fields are + USHORT... */ +#define NT_MAX_PATH 32767 #ifdef __cplusplus