From cbe2437b281270f1647ba63fb16aa4d6ed07298d Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Tue, 16 Jan 2007 18:01:06 +0000 Subject: * autoload.cc (RtlAnsiStringToUnicodeString): Define. (RtlOemStringToUnicodeString): Define. * ntdll.h (struct _RTL_USER_PROCESS_PARAMETERS): Define. (struct _PEB): Redefine with a bit of content. (RtlAnsiStringToUnicodeString): Declare. (RtlOemStringToUnicodeString): Declare. * path.cc: Include ntdll.h. (_upp): New global variable pointing to user process parameter block. (get_user_proc_parms): New static function to retrieve user process parameter block. (close_user_proc_parms_cwd_handle): New function to close handle to current working directory in user process parameter block. (cwdstuff::init): Drop redundant declaration of dynamically_loaded. Set current dir only on 9x. Call close_user_proc_parms_cwd_handle on NT instead. (cwdstuff::keep_in_sync): Only on 9x. (cwdstuff::set): Keep behaviour on 9x. On NT write cwd path into user process parameter block and set cwd handle to NULL. Fix comments to reflect new behaviour. --- winsup/cygwin/ChangeLog | 22 ++++++++++++ winsup/cygwin/autoload.cc | 2 ++ winsup/cygwin/ntdll.h | 47 ++++++++++++++++++++++++- winsup/cygwin/path.cc | 89 +++++++++++++++++++++++++++++++++++++++-------- 4 files changed, 144 insertions(+), 16 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 6163e9120..786ba4cb0 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,25 @@ +2007-01-16 Corinna Vinschen + + * autoload.cc (RtlAnsiStringToUnicodeString): Define. + (RtlOemStringToUnicodeString): Define. + * ntdll.h (struct _RTL_USER_PROCESS_PARAMETERS): Define. + (struct _PEB): Redefine with a bit of content. + (RtlAnsiStringToUnicodeString): Declare. + (RtlOemStringToUnicodeString): Declare. + * path.cc: Include ntdll.h. + (_upp): New global variable pointing to user process parameter block. + (get_user_proc_parms): New static function to retrieve user process + parameter block. + (close_user_proc_parms_cwd_handle): New function to close handle to + current working directory in user process parameter block. + (cwdstuff::init): Drop redundant declaration of dynamically_loaded. + Set current dir only on 9x. Call close_user_proc_parms_cwd_handle + on NT instead. + (cwdstuff::keep_in_sync): Only on 9x. + (cwdstuff::set): Keep behaviour on 9x. On NT write cwd path into user + process parameter block and set cwd handle to NULL. Fix comments to + reflect new behaviour. + 2007-01-16 Corinna Vinschen * fhandler_socket.cc (fhandler_socket::ioctl): Handle SIOCGIFINDEX. diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc index 62e2a3b63..4a8d1d1d9 100644 --- a/winsup/cygwin/autoload.cc +++ b/winsup/cygwin/autoload.cc @@ -409,9 +409,11 @@ LoadDLLfuncNt (NtSetInformationFile, 20, ntdll) LoadDLLfuncNt (NtSetSecurityObject, 12, ntdll) LoadDLLfuncNt (NtUnlockVirtualMemory, 16, ntdll) LoadDLLfuncNt (NtUnmapViewOfSection, 8, ntdll) +LoadDLLfuncNt (RtlAnsiStringToUnicodeString, 12, ntdll) LoadDLLfuncNt (RtlInitUnicodeString, 8, ntdll) LoadDLLfuncNt (RtlIsDosDeviceName_U, 4, ntdll) LoadDLLfuncNt (RtlNtStatusToDosError, 4, ntdll) +LoadDLLfuncNt (RtlOemStringToUnicodeString, 12, ntdll) LoadDLLfuncEx (EnumProcessModules, 16, psapi, 1) LoadDLLfuncEx (GetModuleFileNameExA, 16, psapi, 1) diff --git a/winsup/cygwin/ntdll.h b/winsup/cygwin/ntdll.h index 53c21320b..fc56ce00c 100644 --- a/winsup/cygwin/ntdll.h +++ b/winsup/cygwin/ntdll.h @@ -428,7 +428,48 @@ typedef struct _KERNEL_USER_TIMES LARGE_INTEGER UserTime; } KERNEL_USER_TIMES, *PKERNEL_USER_TIMES; -typedef void *PPEB; +typedef struct _RTL_USER_PROCESS_PARAMETERS +{ + ULONG AllocationSize; + ULONG Size; + ULONG Flags; + ULONG DebugFlags; + HANDLE hConsole; + ULONG ProcessGroup; + HANDLE hStdInput; + HANDLE hStdOutput; + HANDLE hStdError; + UNICODE_STRING CurrentDirectoryName; + HANDLE CurrentDirectoryHandle; + UNICODE_STRING DllPath; + UNICODE_STRING ImagePathName; + UNICODE_STRING CommandLine; + PWSTR Environment; + ULONG dwX; + ULONG dwY; + ULONG dwXSize; + ULONG dwYSize; + ULONG dwXCountChars; + ULONG dwYCountChars; + ULONG dwFillAttribute; + ULONG dwFlags; + ULONG wShowWindow; + UNICODE_STRING WindowTitle; + UNICODE_STRING DesktopInfo; + UNICODE_STRING ShellInfo; + UNICODE_STRING RuntimeInfo; +} RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS; + +typedef struct _PEB +{ + BYTE Reserved1[2]; + BYTE BeingDebugged; + BYTE Reserved2[9]; + PVOID LoaderData; + PRTL_USER_PROCESS_PARAMETERS ProcessParameters; + BYTE Reserved3[448]; + ULONG SessionId; +} PEB, *PPEB; typedef struct _PROCESS_BASIC_INFORMATION { @@ -669,7 +710,11 @@ extern "C" PSECURITY_DESCRIPTOR); NTSTATUS NTAPI NtUnlockVirtualMemory (HANDLE, PVOID *, ULONG *, ULONG); NTSTATUS NTAPI NtUnmapViewOfSection (HANDLE, PVOID); + NTSTATUS NTAPI RtlAnsiStringToUnicodeString (PUNICODE_STRING, PANSI_STRING, + BOOLEAN); VOID NTAPI RtlInitUnicodeString (PUNICODE_STRING, PCWSTR); ULONG NTAPI RtlIsDosDeviceName_U (PCWSTR); ULONG NTAPI RtlNtStatusToDosError (NTSTATUS); + NTSTATUS NTAPI RtlOemStringToUnicodeString (PUNICODE_STRING, POEM_STRING, + BOOLEAN); } diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index bbc023968..287c6f69b 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -77,6 +77,7 @@ details. */ #include "cygtls.h" #include "environ.h" #include +#include bool dos_file_warning = true; static int normalize_win32_path (const char *, char *, char *&); @@ -4153,18 +4154,50 @@ cwdstuff::get_hash () extern char windows_system_directory[]; +static PRTL_USER_PROCESS_PARAMETERS _upp NO_COPY; + +static PRTL_USER_PROCESS_PARAMETERS +get_user_proc_parms () +{ + if (!_upp) + { + NTSTATUS stat; + PROCESS_BASIC_INFORMATION pbi; + stat = NtQueryInformationProcess (GetCurrentProcess (), + ProcessBasicInformation, + &pbi, sizeof pbi, NULL); + if (!NT_SUCCESS (stat)) + api_fatal ("Can't retrieve process parameters, status %p", stat); + _upp = pbi.PebBaseAddress->ProcessParameters; + } + return _upp; +} + +static void +close_user_proc_parms_cwd_handle () +{ + PHANDLE phdl = &get_user_proc_parms ()->CurrentDirectoryHandle; + if (*phdl) + { + NtClose (*phdl); + *phdl = NULL; + } +} + /* Initialize cygcwd 'muto' for serializing access to cwd info. */ void cwdstuff::init () { - extern int dynamically_loaded; cwd_lock.init ("cwd_lock"); get_initial (); if (!dynamically_loaded && !keep_in_sync ()) { - /* Actually chdir into the system dir to avoid cwd problems. See comment - in cwdstuff::set below. */ - SetCurrentDirectory (windows_system_directory); + /* Actually chdir into the system dir to avoid cwd problems on 9x. + See comment in cwdstuff::set below. */ + if (!wincap.can_open_directories ()) + SetCurrentDirectory (windows_system_directory); + else + close_user_proc_parms_cwd_handle (); } cwd_lock.release (); } @@ -4172,12 +4205,14 @@ cwdstuff::init () void cwdstuff::keep_in_sync (bool val) { - sync = val; - SetCurrentDirectory (val ? win32 : windows_system_directory); + if (!wincap.can_open_directories ()) + { + sync = val; + SetCurrentDirectory (val ? win32 : windows_system_directory); + } } -/* Get initial cwd. Should only be called once in a - process tree. */ +/* Get initial cwd. Should only be called once in a process tree. */ bool cwdstuff::get_initial () { @@ -4209,7 +4244,7 @@ cwdstuff::set (const char *win32_cwd, const char *posix_cwd, bool doit) /* If a Cygwin application called cygwin_internal(CW_SYNC_WINENV), then it's about to call native Windows functions. This also sets the keep_in_sync flag so that we actually chdir into the - native directory to avoid confusion. */ + native directory on 9x to avoid confusion. */ if (!SetCurrentDirectory (win32_cwd)) { __seterrno (); @@ -4218,13 +4253,20 @@ cwdstuff::set (const char *win32_cwd, const char *posix_cwd, bool doit) } else { - /* Check if we *could* chdir, if we actually would. - - Why don't we actually chdir? For two reasons: + /* We don't actually chdir on 9x but stay in the system dir. + + On NT we utilize the user parameter block. The directory is + stored manually, but the handle to the directory is always + closed and set to NULL. This way the directory isn't blocked + even if it's the cwd of a Cygwin process. + + Why the hassle? + - A process has always an open handle to the current working directory which disallows manipulating this directory. - POSIX allows to remove a directory if the permissions are - ok. The fact that its the cwd of some process doesn't matter. + POSIX allows to remove a directory if the permissions are ok. + The fact that its the cwd of some process doesn't matter. + - SetCurrentDirectory fails for directories with strict permissions even for processes with the SE_BACKUP_NAME privilege enabled. The reason is apparently that @@ -4243,7 +4285,7 @@ cwdstuff::set (const char *win32_cwd, const char *posix_cwd, bool doit) } if (wincap.can_open_directories ()) { - HANDLE h = CreateFile (win32_cwd, GENERIC_READ, + HANDLE h = CreateFile (win32_cwd, FILE_TRAVERSE, wincap.shared (), NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); if (h == INVALID_HANDLE_VALUE) @@ -4251,6 +4293,23 @@ cwdstuff::set (const char *win32_cwd, const char *posix_cwd, bool doit) __seterrno (); goto out; } + ULONG len = strlen (win32_cwd); + ANSI_STRING as = {len, len + 2, (PCHAR) alloca (len + 2)}; + strcpy (as.Buffer, win32_cwd); + if (as.Buffer[len - 1] != '\\') + { + strcpy (as.Buffer + len, "\\"); + ++as.Length; + } + if (current_codepage == ansi_cp) + RtlAnsiStringToUnicodeString ( + &get_user_proc_parms ()->CurrentDirectoryName, + &as, FALSE); + else + RtlOemStringToUnicodeString ( + &get_user_proc_parms ()->CurrentDirectoryName, + &as, FALSE); + close_user_proc_parms_cwd_handle (); CloseHandle (h); } } -- cgit v1.2.3