OSDN Git Service

* autoload.cc (RtlAnsiStringToUnicodeString): Define.
authorcorinna <corinna>
Tue, 16 Jan 2007 18:01:06 +0000 (18:01 +0000)
committercorinna <corinna>
Tue, 16 Jan 2007 18:01:06 +0000 (18:01 +0000)
(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
winsup/cygwin/autoload.cc
winsup/cygwin/ntdll.h
winsup/cygwin/path.cc

index 6163e91..786ba4c 100644 (file)
@@ -1,5 +1,27 @@
 2007-01-16  Corinna Vinschen  <corinna@vinschen.de>
 
+       * 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  <corinna@vinschen.de>
+
        * fhandler_socket.cc (fhandler_socket::ioctl): Handle SIOCGIFINDEX.
        * net.cc (get_2k_ifconf): Ditto.
        (get_nt_ifconf): Fake SIOCGIFINDEX.
index 62e2a3b..4a8d1d1 100644 (file)
@@ -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)
index 53c2132..fc56ce0 100644 (file)
@@ -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);
 }
index bbc0239..287c6f6 100644 (file)
@@ -77,6 +77,7 @@ details. */
 #include "cygtls.h"
 #include "environ.h"
 #include <assert.h>
+#include <ntdll.h>
 
 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);
                }
            }