diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index cb80c589c..7ed188da2 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,18 @@
+2007-08-21  Corinna Vinschen  <corinna@vinschen.de>
+
+	* ntdll.h (NtNotifyChangeDirectoryFile): Declare.
+	(NtQueryAttributesFile): Move to maintain alphabetical order of
+	declarations.  Add comment to note that timestamp information returned
+	by NtQueryAttributesFile is unreliable.
+	* path.h (etc::changed_h): Move here.
+	(etc::fn): Change type to OBJECT_ATTRIBUTES.
+	(etc::last_modified): Change type to LARGE_INTEGER.
+	(etc::init): Take PUNICODE_STRING as second argument.
+	* path.cc: Accomodate above changes.
+	(etc::test_file_change): Use NT native functions.
+	(etc::dir_changed): Ditto.
+	* uinfo.cc (pwdgrp::load): Call etc::init with NT native path.
+
 2007-08-21  Corinna Vinschen  <corinna@vinschen.de>
 
 	* fhandler_disk_file.cc: Change debugging output througout to print
diff --git a/winsup/cygwin/ntdll.h b/winsup/cygwin/ntdll.h
index ff9f95506..f5c079767 100644
--- a/winsup/cygwin/ntdll.h
+++ b/winsup/cygwin/ntdll.h
@@ -779,11 +779,19 @@ extern "C"
   NTSTATUS NTAPI NtMapViewOfSection (HANDLE, HANDLE, PVOID *, ULONG, ULONG,
 				     PLARGE_INTEGER, PULONG, SECTION_INHERIT,
 				     ULONG, ULONG);
+  NTSTATUS NTAPI NtNotifyChangeDirectoryFile (HANDLE, HANDLE, PIO_APC_ROUTINE,
+                                              PVOID, PIO_STATUS_BLOCK,
+					      PFILE_NOTIFY_INFORMATION, ULONG,
+					      ULONG, BOOLEAN);
   NTSTATUS NTAPI NtOpenDirectoryObject (PHANDLE, ACCESS_MASK,
   					POBJECT_ATTRIBUTES);
   NTSTATUS NTAPI NtOpenFile (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES,
 			     PIO_STATUS_BLOCK, ULONG, ULONG);
   NTSTATUS NTAPI NtOpenSection (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES);
+  /* WARNING!  Don't rely on the timestamp information returned by
+     NtQueryAttributesFile.  Only the DOS file attribute info is reliable. */
+  NTSTATUS NTAPI NtQueryAttributesFile (POBJECT_ATTRIBUTES,
+					PFILE_BASIC_INFORMATION);
   NTSTATUS NTAPI NtQueryDirectoryFile(HANDLE, HANDLE, PVOID, PVOID,
 				      PIO_STATUS_BLOCK, PVOID, ULONG,
 				      FILE_INFORMATION_CLASS, BOOLEAN,
@@ -792,8 +800,6 @@ extern "C"
   					 BOOLEAN, PULONG, PULONG);
   NTSTATUS NTAPI NtQueryEaFile (HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG,
 				BOOLEAN, PVOID, ULONG, PULONG, BOOLEAN);
-  NTSTATUS NTAPI NtQueryAttributesFile (POBJECT_ATTRIBUTES,
-					PFILE_BASIC_INFORMATION);
   NTSTATUS NTAPI NtQueryFullAttributesFile (POBJECT_ATTRIBUTES,
 					    PFILE_NETWORK_OPEN_INFORMATION);
   NTSTATUS NTAPI NtQueryInformationFile (HANDLE, PIO_STATUS_BLOCK, PVOID,
diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc
index e3377a069..8dcccc847 100644
--- a/winsup/cygwin/path.cc
+++ b/winsup/cygwin/path.cc
@@ -4456,11 +4456,11 @@ out:
 int etc::curr_ix = 0;
 /* Note that the first elements of the below arrays are unused */
 bool etc::change_possible[MAX_ETC_FILES + 1];
-const char *etc::fn[MAX_ETC_FILES + 1];
-FILETIME etc::last_modified[MAX_ETC_FILES + 1];
+OBJECT_ATTRIBUTES etc::fn[MAX_ETC_FILES + 1];
+LARGE_INTEGER etc::last_modified[MAX_ETC_FILES + 1];
 
 int
-etc::init (int n, const char *etc_fn)
+etc::init (int n, PUNICODE_STRING etc_fn)
 {
   if (n > 0)
     /* ok */;
@@ -4469,35 +4469,36 @@ etc::init (int n, const char *etc_fn)
   else
     api_fatal ("internal error");
 
-  fn[n] = etc_fn;
+  InitializeObjectAttributes (&fn[n], etc_fn, OBJ_CASE_INSENSITIVE, NULL, NULL);
   change_possible[n] = false;
   test_file_change (n);
-  paranoid_printf ("fn[%d] %s, curr_ix %d", n, fn[n], curr_ix);
+  paranoid_printf ("fn[%d] %S, curr_ix %d", n, fn[n].ObjectName, curr_ix);
   return n;
 }
 
 bool
 etc::test_file_change (int n)
 {
-  HANDLE h;
-  WIN32_FIND_DATA data;
+  NTSTATUS status;
+  FILE_NETWORK_OPEN_INFORMATION fnoi;
   bool res;
 
-  if ((h = FindFirstFile (fn[n], &data)) == INVALID_HANDLE_VALUE)
+  status = NtQueryFullAttributesFile (&fn[n], &fnoi);
+  if (!NT_SUCCESS (status))
     {
       res = true;
       memset (last_modified + n, 0, sizeof (last_modified[n]));
-      debug_printf ("FindFirstFile failed, %E");
+      debug_printf ("NtQueryFullAttributesFile (%S) failed, %p",
+		    fn[n].ObjectName, status);
     }
   else
     {
-      FindClose (h);
-      res = CompareFileTime (&data.ftLastWriteTime, last_modified + n) > 0;
-      last_modified[n] = data.ftLastWriteTime;
-      debug_printf ("FindFirstFile succeeded");
+      res = CompareFileTime ((FILETIME *) &fnoi.LastWriteTime,
+			     (FILETIME *) last_modified + n) > 0;
+      last_modified[n].QuadPart = fnoi.LastWriteTime.QuadPart;
     }
 
-  paranoid_printf ("fn[%d] %s res %d", n, fn[n], res);
+  paranoid_printf ("fn[%d] %S res %d", n, fn[n].ObjectName, res);
   return res;
 }
 
@@ -4507,17 +4508,42 @@ etc::dir_changed (int n)
   if (!change_possible[n])
     {
       static HANDLE changed_h NO_COPY;
+      NTSTATUS status;
+      IO_STATUS_BLOCK io;
 
       if (!changed_h)
 	{
-	  path_conv pwd ("/etc");
-	  changed_h = FindFirstChangeNotification (pwd.get_win32 (), FALSE,
-						  FILE_NOTIFY_CHANGE_LAST_WRITE
-						  | FILE_NOTIFY_CHANGE_FILE_NAME);
+	  OBJECT_ATTRIBUTES attr;
+
+	  path_conv dir ("/etc");
+	  status = NtOpenFile (&changed_h, SYNCHRONIZE | FILE_LIST_DIRECTORY,
+			       dir.get_object_attr (attr, sec_none_nih), &io,
+			       FILE_SHARE_VALID_FLAGS, FILE_DIRECTORY_FILE);
+	  if (!NT_SUCCESS (status))
+	    {
 #ifdef DEBUGGING
-	  if (changed_h == INVALID_HANDLE_VALUE)
-	    system_printf ("Can't open %s for checking, %E", (char *) pwd);
+	      system_printf ("NtOpenFile (%S) failed, %p",
+			     dir.get_nt_native_path (), status);
 #endif
+	      changed_h = INVALID_HANDLE_VALUE;
+	    }
+	  else
+	    {
+	      status = NtNotifyChangeDirectoryFile (changed_h, NULL, NULL,
+						NULL, &io, NULL, 0,
+						FILE_NOTIFY_CHANGE_LAST_WRITE
+						| FILE_NOTIFY_CHANGE_FILE_NAME,
+						FALSE);
+	      if (!NT_SUCCESS (status))
+		{
+#ifdef DEBUGGING
+		  system_printf ("NtNotifyChangeDirectoryFile (1) failed, %p",
+				 status);
+#endif
+		  NtClose (changed_h);
+		  changed_h = INVALID_HANDLE_VALUE;
+		}
+	    }
 	  memset (change_possible, true, sizeof (change_possible));
 	}
 
@@ -4525,12 +4551,26 @@ etc::dir_changed (int n)
 	change_possible[n] = true;
       else if (WaitForSingleObject (changed_h, 0) == WAIT_OBJECT_0)
 	{
-	  FindNextChangeNotification (changed_h);
+	  status = NtNotifyChangeDirectoryFile (changed_h, NULL, NULL,
+						NULL, &io, NULL, 0,
+						FILE_NOTIFY_CHANGE_LAST_WRITE
+						| FILE_NOTIFY_CHANGE_FILE_NAME,
+						FALSE);
+	  if (!NT_SUCCESS (status))
+	    {
+#ifdef DEBUGGING
+	      system_printf ("NtNotifyChangeDirectoryFile (2) failed, %p",
+			     status);
+#endif
+	      NtClose (changed_h);
+	      changed_h = INVALID_HANDLE_VALUE;
+	    }
 	  memset (change_possible, true, sizeof change_possible);
 	}
     }
 
-  paranoid_printf ("fn[%d] %s change_possible %d", n, fn[n], change_possible[n]);
+  paranoid_printf ("fn[%d] %S change_possible %d",
+		   n, fn[n].ObjectName, change_possible[n]);
   return change_possible[n];
 }
 
@@ -4541,7 +4581,7 @@ etc::file_changed (int n)
   if (dir_changed (n) && test_file_change (n))
     res = true;
   change_possible[n] = false;	/* Change is no longer possible */
-  paranoid_printf ("fn[%d] %s res %d", n, fn[n], res);
+  paranoid_printf ("fn[%d] %S res %d", n, fn[n].ObjectName, res);
   return res;
 }
 
diff --git a/winsup/cygwin/path.h b/winsup/cygwin/path.h
index b258ac9b6..5bf9717e3 100644
--- a/winsup/cygwin/path.h
+++ b/winsup/cygwin/path.h
@@ -336,11 +336,12 @@ class etc
 {
   friend class dtable;
   static int curr_ix;
+  static HANDLE changed_h;
   static bool change_possible[MAX_ETC_FILES + 1];
-  static const char *fn[MAX_ETC_FILES + 1];
-  static FILETIME last_modified[MAX_ETC_FILES + 1];
+  static OBJECT_ATTRIBUTES fn[MAX_ETC_FILES + 1];
+  static LARGE_INTEGER last_modified[MAX_ETC_FILES + 1];
   static bool dir_changed (int);
-  static int init (int, const char *);
+  static int init (int, PUNICODE_STRING);
   static bool file_changed (int);
   static bool test_file_change (int);
   friend class pwdgrp;
diff --git a/winsup/cygwin/uinfo.cc b/winsup/cygwin/uinfo.cc
index 4ebe7245c..210b1d1f7 100644
--- a/winsup/cygwin/uinfo.cc
+++ b/winsup/cygwin/uinfo.cc
@@ -518,7 +518,7 @@ pwdgrp::load (const char *posix_fname)
   curr_lines = 0;
 
   pc.check (posix_fname);
-  etc_ix = etc::init (etc_ix, pc.get_win32 ());
+  etc_ix = etc::init (etc_ix, pc.get_nt_native_path ());
 
   paranoid_printf ("%s", posix_fname);