diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 3aef60249..83c970a6a 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,11 @@
+2004-03-18  Corinna Vinschen  <corinna@vinschen.de>
+
+	* fhandler_proc.cc (format_proc_meminfo): On NT, try to figure out
+	real swap file usage by requesting SystemPagefileInformation.  Use
+	GlobalMemoryStatus as fallback.
+	* ntdll.h (_SYSTEM_INFORMATION_CLASS): Add SystemPagefileInformation.
+	(struct _SYSTEM_PAGEFILE_INFORMATION): Define.
+
 2004-03-17  Christopher Faylor  <cgf@redhat.com>
 
 	* pipe.cc (fhandler_pipe::dup): Fix debugging message.
diff --git a/winsup/cygwin/fhandler_proc.cc b/winsup/cygwin/fhandler_proc.cc
index 2c77afcd7..278d41b7a 100644
--- a/winsup/cygwin/fhandler_proc.cc
+++ b/winsup/cygwin/fhandler_proc.cc
@@ -390,8 +390,42 @@ format_proc_meminfo (char *destbuf, size_t maxsize)
   GlobalMemoryStatus (&memory_status);
   mem_total = memory_status.dwTotalPhys;
   mem_free = memory_status.dwAvailPhys;
-  swap_total = memory_status.dwTotalPageFile - mem_total;
-  swap_free = memory_status.dwAvailPageFile - mem_total;
+  PSYSTEM_PAGEFILE_INFORMATION spi = NULL;
+  ULONG size = 512;
+  NTSTATUS ret;
+  spi = (PSYSTEM_PAGEFILE_INFORMATION) malloc (size);
+  if (spi)
+    {
+      ret = NtQuerySystemInformation (SystemPagefileInformation, (PVOID) spi,
+				      size, &size);
+      if (ret == STATUS_INFO_LENGTH_MISMATCH)
+        {
+	  free (spi);
+	  spi = (PSYSTEM_PAGEFILE_INFORMATION) malloc (size);
+	  if (spi)
+	    ret = NtQuerySystemInformation (SystemPagefileInformation,
+					    (PVOID) spi, size, &size);
+	}
+    }
+  if (!spi || ret || (!ret && GetLastError () == ERROR_PROC_NOT_FOUND))
+    {
+      swap_total = memory_status.dwTotalPageFile - mem_total;
+      swap_free = memory_status.dwAvailPageFile - mem_total;
+    }
+  else
+    {
+      PSYSTEM_PAGEFILE_INFORMATION spp = spi;
+      do
+        {
+	  swap_total += spp->CurrentSize * getpagesize ();
+	  swap_free += (spp->CurrentSize - spp->TotalUsed) * getpagesize ();
+	}
+      while (spp->NextEntryOffset
+	     && (spp = (PSYSTEM_PAGEFILE_INFORMATION)
+			   ((char *) spp + spp->NextEntryOffset)));
+    }
+  if (spi)
+    free (spi);
   return __small_sprintf (destbuf, "         total:      used:      free:\n"
 				   "Mem:  %10lu %10lu %10lu\n"
 				   "Swap: %10lu %10lu %10lu\n"
diff --git a/winsup/cygwin/ntdll.h b/winsup/cygwin/ntdll.h
index 45739bf38..21e63932e 100644
--- a/winsup/cygwin/ntdll.h
+++ b/winsup/cygwin/ntdll.h
@@ -31,6 +31,7 @@ typedef enum _SYSTEM_INFORMATION_CLASS
   SystemTimeOfDayInformation = 3,
   SystemProcessesAndThreadsInformation = 5,
   SystemProcessorTimes = 8,
+  SystemPagefileInformation = 18,
   /* There are a lot more of these... */
 } SYSTEM_INFORMATION_CLASS;
 
@@ -49,6 +50,15 @@ typedef struct _SYSTEM_BASIC_INFORMATION
   UCHAR NumberProcessors;
 } SYSTEM_BASIC_INFORMATION, *PSYSTEM_BASIC_INFORMATION;
 
+typedef struct _SYSTEM_PAGEFILE_INFORMATION
+{
+  ULONG NextEntryOffset;
+  ULONG CurrentSize;
+  ULONG TotalUsed;
+  ULONG PeakUsed;
+  UNICODE_STRING FileName;
+} SYSTEM_PAGEFILE_INFORMATION, *PSYSTEM_PAGEFILE_INFORMATION;
+
 typedef struct __attribute__ ((aligned (8))) _SYSTEM_PROCESSOR_TIMES
 {
   LARGE_INTEGER IdleTime;