]> code.delx.au - gnu-emacs/blobdiff - src/w32.c
Fix MSDOS build broken by 2010-09-10T16:44:35Z!larsi@gnus.org, support MSDOS build...
[gnu-emacs] / src / w32.c
index c7af7f0634076ec8f53f34bae6b73abd6e4690a3..c2bc94fae0133c7a064ee5eaf7cbdbdf73a3e092 100644 (file)
--- a/src/w32.c
+++ b/src/w32.c
@@ -1,6 +1,6 @@
 /* Utility and Unix shadow routines for GNU Emacs on the Microsoft W32 API.
    Copyright (C) 1994, 1995, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
-                 2007, 2008  Free Software Foundation, Inc.
+                 2007, 2008, 2009, 2010  Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -23,6 +23,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <stddef.h> /* for offsetof */
 #include <stdlib.h>
 #include <stdio.h>
+#include <float.h>     /* for DBL_EPSILON */
 #include <io.h>
 #include <errno.h>
 #include <fcntl.h>
@@ -33,6 +34,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <sys/utime.h>
 #include <mbstring.h>  /* for _mbspbrk */
 #include <math.h>
+#include <setjmp.h>
 
 /* must include CRT headers *before* config.h */
 
@@ -92,8 +94,11 @@ typedef struct _MEMORY_STATUS_EX {
 
 #include <tlhelp32.h>
 #include <psapi.h>
+#include <w32api.h>
+#if !defined(__MINGW32__) || __W32API_MAJOR_VERSION < 3 || (__W32API_MAJOR_VERSION == 3 && __W32API_MINOR_VERSION < 15)
 /* This either is not in psapi.h or guarded by higher value of
-   _WIN32_WINNT than what we use.  */
+   _WIN32_WINNT than what we use.  w32api suplied with MinGW 3.15
+   defines it in psapi.h  */
 typedef struct _PROCESS_MEMORY_COUNTERS_EX {
        DWORD cb;
        DWORD PageFaultCount;
@@ -107,6 +112,7 @@ typedef struct _PROCESS_MEMORY_COUNTERS_EX {
        DWORD PeakPagefileUsage;
        DWORD PrivateUsage;
 } PROCESS_MEMORY_COUNTERS_EX,*PPROCESS_MEMORY_COUNTERS_EX;
+#endif
 
 #ifdef HAVE_SOCKETS    /* TCP connection support, if kernel can do it */
 #include <sys/socket.h>
@@ -138,15 +144,11 @@ typedef struct _PROCESS_MEMORY_COUNTERS_EX {
 
 /* For serial_configure and serial_open.  */
 #include "process.h"
-/* From process.c  */
-extern Lisp_Object QCport, QCspeed, QCprocess;
-extern Lisp_Object QCbytesize, QCstopbits, QCparity, Qodd, Qeven;
-extern Lisp_Object QCflowcontrol, Qhw, Qsw, QCsummary;
 
 typedef HRESULT (WINAPI * ShGetFolderPath_fn)
   (IN HWND, IN int, IN HANDLE, IN DWORD, OUT char *);
 
-void globals_of_w32 ();
+void globals_of_w32 (void);
 static DWORD get_rid (PSID);
 
 extern Lisp_Object Vw32_downcase_file_names;
@@ -191,6 +193,8 @@ static BOOL g_b_init_global_memory_status_ex;
 static BOOL g_b_init_get_length_sid;
 static BOOL g_b_init_equal_sid;
 static BOOL g_b_init_copy_sid;
+static BOOL g_b_init_get_native_system_info;
+static BOOL g_b_init_get_system_times;
 
 /*
   BEGIN: Wrapper functions around OpenProcessToken
@@ -293,20 +297,26 @@ typedef BOOL (WINAPI * EqualSid_Proc) (
     PSID pSid2);
 typedef DWORD (WINAPI * GetLengthSid_Proc) (
     PSID pSid);
+typedef void (WINAPI * GetNativeSystemInfo_Proc) (
+    LPSYSTEM_INFO lpSystemInfo);
+typedef BOOL (WINAPI * GetSystemTimes_Proc) (
+    LPFILETIME lpIdleTime,
+    LPFILETIME lpKernelTime,
+    LPFILETIME lpUserTime);
 
 
 
   /* ** A utility function ** */
 static BOOL
-is_windows_9x ()
+is_windows_9x (void)
 {
   static BOOL s_b_ret=0;
   OSVERSIONINFO os_ver;
   if (g_b_init_is_windows_9x == 0)
     {
       g_b_init_is_windows_9x = 1;
-      ZeroMemory(&os_ver, sizeof(OSVERSIONINFO));
-      os_ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+      ZeroMemory (&os_ver, sizeof (OSVERSIONINFO));
+      os_ver.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
       if (GetVersionEx (&os_ver))
         {
           s_b_ret = (os_ver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS);
@@ -319,12 +329,12 @@ is_windows_9x ()
    Returns a list of three integers if the times are provided by the OS
    (NT derivatives), otherwise it returns the result of current-time. */
 Lisp_Object
-w32_get_internal_run_time ()
+w32_get_internal_run_time (void)
 {
   if (get_process_times_fn)
     {
       FILETIME create, exit, kernel, user;
-      HANDLE proc = GetCurrentProcess();
+      HANDLE proc = GetCurrentProcess ();
       if ((*get_process_times_fn) (proc, &create, &exit, &kernel, &user))
         {
           LARGE_INTEGER user_int, kernel_int, total;
@@ -723,6 +733,47 @@ BOOL WINAPI copy_sid (
   supported in Windows NT / 2k / XP
 */
 
+void WINAPI get_native_system_info (
+    LPSYSTEM_INFO lpSystemInfo)
+{
+  static GetNativeSystemInfo_Proc s_pfn_Get_Native_System_Info = NULL;
+  if (is_windows_9x () != TRUE)
+    {
+      if (g_b_init_get_native_system_info == 0)
+       {
+         g_b_init_get_native_system_info = 1;
+         s_pfn_Get_Native_System_Info =
+           (GetNativeSystemInfo_Proc)GetProcAddress (GetModuleHandle ("kernel32.dll"),
+                                                     "GetNativeSystemInfo");
+       }
+      if (s_pfn_Get_Native_System_Info != NULL)
+       s_pfn_Get_Native_System_Info (lpSystemInfo);
+    }
+  else
+    lpSystemInfo->dwNumberOfProcessors = -1;
+}
+
+BOOL WINAPI get_system_times (
+    LPFILETIME lpIdleTime,
+    LPFILETIME lpKernelTime,
+    LPFILETIME lpUserTime)
+{
+  static GetSystemTimes_Proc s_pfn_Get_System_times = NULL;
+  if (is_windows_9x () == TRUE)
+    {
+      return FALSE;
+    }
+  if (g_b_init_get_system_times == 0)
+    {
+      g_b_init_get_system_times = 1;
+      s_pfn_Get_System_times =
+       (GetSystemTimes_Proc)GetProcAddress (GetModuleHandle ("kernel32.dll"),
+                                            "GetSystemTimes");
+    }
+  if (s_pfn_Get_System_times == NULL)
+    return FALSE;
+  return (s_pfn_Get_System_times (lpIdleTime, lpKernelTime, lpUserTime));
+}
 \f
 /* Equivalent of strerror for W32 error codes.  */
 char *
@@ -795,17 +846,160 @@ gethostname (char *buffer, int size)
 #endif /* HAVE_SOCKETS */
 
 /* Emulate getloadavg.  */
+
+struct load_sample {
+  time_t sample_time;
+  ULONGLONG idle;
+  ULONGLONG kernel;
+  ULONGLONG user;
+};
+
+/* Number of processors on this machine.  */
+static unsigned num_of_processors;
+
+/* We maintain 1-sec samples for the last 16 minutes in a circular buffer.  */
+static struct load_sample samples[16*60];
+static int first_idx = -1, last_idx = -1;
+static int max_idx = sizeof (samples) / sizeof (samples[0]);
+
+static int
+buf_next (int from)
+{
+  int next_idx = from + 1;
+
+  if (next_idx >= max_idx)
+    next_idx = 0;
+
+  return next_idx;
+}
+
+static int
+buf_prev (int from)
+{
+  int prev_idx = from - 1;
+
+  if (prev_idx < 0)
+    prev_idx = max_idx - 1;
+
+  return prev_idx;
+}
+
+static void
+sample_system_load (ULONGLONG *idle, ULONGLONG *kernel, ULONGLONG *user)
+{
+  SYSTEM_INFO sysinfo;
+  FILETIME ft_idle, ft_user, ft_kernel;
+
+  /* Initialize the number of processors on this machine.  */
+  if (num_of_processors <= 0)
+    {
+      get_native_system_info (&sysinfo);
+      num_of_processors = sysinfo.dwNumberOfProcessors;
+      if (num_of_processors <= 0)
+       {
+         GetSystemInfo (&sysinfo);
+         num_of_processors = sysinfo.dwNumberOfProcessors;
+       }
+      if (num_of_processors <= 0)
+       num_of_processors = 1;
+    }
+
+  /* TODO: Take into account threads that are ready to run, by
+     sampling the "\System\Processor Queue Length" performance
+     counter.  The code below accounts only for threads that are
+     actually running.  */
+
+  if (get_system_times (&ft_idle, &ft_kernel, &ft_user))
+    {
+      ULARGE_INTEGER uidle, ukernel, uuser;
+
+      memcpy (&uidle, &ft_idle, sizeof (ft_idle));
+      memcpy (&ukernel, &ft_kernel, sizeof (ft_kernel));
+      memcpy (&uuser, &ft_user, sizeof (ft_user));
+      *idle = uidle.QuadPart;
+      *kernel = ukernel.QuadPart;
+      *user = uuser.QuadPart;
+    }
+  else
+    {
+      *idle = 0;
+      *kernel = 0;
+      *user = 0;
+    }
+}
+
+/* Produce the load average for a given time interval, using the
+   samples in the samples[] array.  WHICH can be 0, 1, or 2, meaning
+   1-minute, 5-minute, or 15-minute average, respectively. */
+static double
+getavg (int which)
+{
+  double retval = -1.0;
+  double tdiff;
+  int idx;
+  double span = (which == 0 ? 1.0 : (which == 1 ? 5.0 : 15.0)) * 60;
+  time_t now = samples[last_idx].sample_time;
+
+  if (first_idx != last_idx)
+    {
+      for (idx = buf_prev (last_idx); ; idx = buf_prev (idx))
+       {
+         tdiff = difftime (now, samples[idx].sample_time);
+         if (tdiff >= span - 2*DBL_EPSILON*now)
+           {
+             long double sys =
+               samples[last_idx].kernel + samples[last_idx].user
+               - (samples[idx].kernel + samples[idx].user);
+             long double idl = samples[last_idx].idle - samples[idx].idle;
+
+             retval = (1.0 - idl / sys) * num_of_processors;
+             break;
+           }
+         if (idx == first_idx)
+           break;
+       }
+    }
+
+  return retval;
+}
+
 int
 getloadavg (double loadavg[], int nelem)
 {
-  int i;
+  int elem;
+  ULONGLONG idle, kernel, user;
+  time_t now = time (NULL);
+
+  /* Store another sample.  We ignore samples that are less than 1 sec
+     apart.  */
+  if (difftime (now, samples[last_idx].sample_time) >= 1.0 - 2*DBL_EPSILON*now)
+    {
+      sample_system_load (&idle, &kernel, &user);
+      last_idx = buf_next (last_idx);
+      samples[last_idx].sample_time = now;
+      samples[last_idx].idle = idle;
+      samples[last_idx].kernel = kernel;
+      samples[last_idx].user = user;
+      /* If the buffer has more that 15 min worth of samples, discard
+        the old ones.  */
+      if (first_idx == -1)
+       first_idx = last_idx;
+      while (first_idx != last_idx
+            && (difftime (now, samples[first_idx].sample_time)
+                >= 15.0*60 + 2*DBL_EPSILON*now))
+       first_idx = buf_next (first_idx);
+    }
 
-  /* A faithful emulation is going to have to be saved for a rainy day.  */
-  for (i = 0; i < nelem; i++)
+  for (elem = 0; elem < nelem; elem++)
     {
-      loadavg[i] = 0.0;
+      double avg = getavg (elem);
+
+      if (avg < 0)
+       break;
+      loadavg[elem] = avg;
     }
-  return i;
+
+  return elem;
 }
 
 /* Emulate getpwuid, getpwnam and others.  */
@@ -840,14 +1034,14 @@ static struct group dflt_group =
   0,
 };
 
-int
-getuid ()
+unsigned
+getuid (void)
 {
   return dflt_passwd.pw_uid;
 }
 
-int
-geteuid ()
+unsigned
+geteuid (void)
 {
   /* I could imagine arguing for checking to see whether the user is
      in the Administrators group and returning a UID of 0 for that
@@ -855,20 +1049,20 @@ geteuid ()
   return getuid ();
 }
 
-int
-getgid ()
+unsigned
+getgid (void)
 {
   return dflt_passwd.pw_gid;
 }
 
-int
-getegid ()
+unsigned
+getegid (void)
 {
   return getgid ();
 }
 
 struct passwd *
-getpwuid (int uid)
+getpwuid (unsigned uid)
 {
   if (uid == dflt_passwd.pw_uid)
     return &dflt_passwd;
@@ -897,7 +1091,7 @@ getpwnam (char *name)
 }
 
 void
-init_user_info ()
+init_user_info (void)
 {
   /* Find the user's real name by opening the process token and
      looking up the name associated with the user-sid in that token.
@@ -907,20 +1101,37 @@ init_user_info ()
      primary group sid from the process token). */
 
   char         uname[UNLEN+1], gname[GNLEN+1], domain[1025];
-  DWORD        ulength = sizeof (uname), dlength = sizeof (domain), trash;
+  DWORD        ulength = sizeof (uname), dlength = sizeof (domain), needed;
   DWORD               glength = sizeof (gname);
   HANDLE       token = NULL;
   SID_NAME_USE user_type;
-  unsigned char buf[1024];
+  unsigned char *buf = NULL;
+  DWORD        blen = 0;
   TOKEN_USER   user_token;
   TOKEN_PRIMARY_GROUP group_token;
+  BOOL         result;
 
-  if (open_process_token (GetCurrentProcess (), TOKEN_QUERY, &token)
-      && get_token_information (token, TokenUser,
-                               (PVOID)buf, sizeof (buf), &trash)
-      && (memcpy (&user_token, buf, sizeof (user_token)),
-         lookup_account_sid (NULL, user_token.User.Sid, uname, &ulength,
-                             domain, &dlength, &user_type)))
+  result = open_process_token (GetCurrentProcess (), TOKEN_QUERY, &token);
+  if (result)
+    {
+      result = get_token_information (token, TokenUser, NULL, 0, &blen);
+      if (!result && GetLastError () == ERROR_INSUFFICIENT_BUFFER)
+       {
+         buf = xmalloc (blen);
+         result = get_token_information (token, TokenUser,
+                                         (LPVOID)buf, blen, &needed);
+         if (result)
+           {
+             memcpy (&user_token, buf, sizeof (user_token));
+             result = lookup_account_sid (NULL, user_token.User.Sid,
+                                          uname, &ulength,
+                                          domain, &dlength, &user_type);
+           }
+       }
+      else
+       result = FALSE;
+    }
+  if (result)
     {
       strcpy (dflt_passwd.pw_name, uname);
       /* Determine a reasonable uid value.  */
@@ -936,12 +1147,22 @@ init_user_info ()
          dflt_passwd.pw_uid = get_rid (user_token.User.Sid);
 
          /* Get group id and name.  */
-         if (get_token_information (token, TokenPrimaryGroup,
-                                    (PVOID)buf, sizeof (buf), &trash))
+         result = get_token_information (token, TokenPrimaryGroup,
+                                         (LPVOID)buf, blen, &needed);
+         if (!result && GetLastError () == ERROR_INSUFFICIENT_BUFFER)
+           {
+             buf = xrealloc (buf, blen = needed);
+             result = get_token_information (token, TokenPrimaryGroup,
+                                             (LPVOID)buf, blen, &needed);
+           }
+         if (result)
            {
              memcpy (&group_token, buf, sizeof (group_token));
              dflt_passwd.pw_gid = get_rid (group_token.PrimaryGroup);
              dlength = sizeof (domain);
+             /* If we can get at the real Primary Group name, use that.
+                Otherwise, the default group name was already set to
+                "None" in globals_of_w32.  */
              if (lookup_account_sid (NULL, group_token.PrimaryGroup,
                                      gname, &glength, NULL, &dlength,
                                      &user_type))
@@ -952,7 +1173,7 @@ init_user_info ()
        }
     }
   /* If security calls are not supported (presumably because we
-     are running under Windows 95), fallback to this. */
+     are running under Windows 9X), fallback to this: */
   else if (GetUserName (uname, &ulength))
     {
       strcpy (dflt_passwd.pw_name, uname);
@@ -980,12 +1201,13 @@ init_user_info ()
   strcpy (dflt_passwd.pw_dir, getenv ("HOME"));
   strcpy (dflt_passwd.pw_shell, getenv ("SHELL"));
 
+  xfree (buf);
   if (token)
     CloseHandle (token);
 }
 
 int
-random ()
+random (void)
 {
   /* rand () on NT gives us 15 random bits...hack together 30 bits.  */
   return ((rand () << 15) | rand ());
@@ -1003,9 +1225,7 @@ srandom (int seed)
    case path name components to lower case.  */
 
 static void
-normalize_filename (fp, path_sep)
-     register char *fp;
-     char path_sep;
+normalize_filename (register char *fp, char path_sep)
 {
   char sep;
   char *elem;
@@ -1061,16 +1281,14 @@ normalize_filename (fp, path_sep)
 
 /* Destructively turn backslashes into slashes.  */
 void
-dostounix_filename (p)
-     register char *p;
+dostounix_filename (register char *p)
 {
   normalize_filename (p, '/');
 }
 
 /* Destructively turn slashes into backslashes.  */
 void
-unixtodos_filename (p)
-     register char *p;
+unixtodos_filename (register char *p)
 {
   normalize_filename (p, '\\');
 }
@@ -1079,9 +1297,7 @@ unixtodos_filename (p)
    (From msdos.c...probably should figure out a way to share it,
    although this code isn't going to ever change.)  */
 int
-crlf_to_lf (n, buf)
-     register int n;
-     register unsigned char *buf;
+crlf_to_lf (register int n, register unsigned char *buf)
 {
   unsigned char *np = buf;
   unsigned char *startp = buf;
@@ -1259,6 +1475,30 @@ sigunblock (int sig)
   return 0;
 }
 
+int
+sigemptyset (sigset_t *set)
+{
+  return 0;
+}
+
+int
+sigaddset (sigset_t *set, int signo)
+{
+  return 0;
+}
+
+int
+sigfillset (sigset_t *set)
+{
+  return 0;
+}
+
+int
+sigprocmask (int how, const sigset_t *set, sigset_t *oset)
+{
+  return 0;
+}
+
 int
 setpgrp (int pid, int gid)
 {
@@ -1274,9 +1514,7 @@ alarm (int seconds)
 #define REG_ROOT "SOFTWARE\\GNU\\Emacs"
 
 LPBYTE
-w32_get_resource (key, lpdwtype)
-    char *key;
-    LPDWORD lpdwtype;
+w32_get_resource (char *key, LPDWORD lpdwtype)
 {
   LPBYTE lpvalue;
   HKEY hrootkey = NULL;
@@ -1396,7 +1634,7 @@ init_environment (char ** argv)
       {"LANG", NULL},
     };
 
-#define N_ENV_VARS sizeof(dflt_envvars)/sizeof(dflt_envvars[0])
+#define N_ENV_VARS sizeof (dflt_envvars)/sizeof (dflt_envvars[0])
 
     /* We need to copy dflt_envvars[] and work on the copy because we
        don't want the dumped Emacs to inherit the values of
@@ -1415,12 +1653,10 @@ init_environment (char ** argv)
       HRESULT profile_result;
       /* Dynamically load ShGetFolderPath, as it won't exist on versions
         of Windows 95 and NT4 that have not been updated to include
-        MSIE 5.  Also we don't link with shell32.dll by default.  */
-      HMODULE shell32_dll;
+        MSIE 5.  */
       ShGetFolderPath_fn get_folder_path;
-      shell32_dll = GetModuleHandle ("shell32.dll");
       get_folder_path = (ShGetFolderPath_fn)
-       GetProcAddress (shell32_dll, "SHGetFolderPathA");
+       GetProcAddress (GetModuleHandle ("shell32.dll"), "SHGetFolderPathA");
 
       if (get_folder_path != NULL)
        {
@@ -1431,9 +1667,6 @@ init_environment (char ** argv)
          if (profile_result == S_OK)
            env_vars[0].def_value = default_home;
        }
-
-      /* Unload shell32.dll, it is not needed anymore.  */
-      FreeLibrary (shell32_dll);
     }
 
   /* Get default locale info and use it for LANG.  */
@@ -1474,7 +1707,7 @@ init_environment (char ** argv)
          for (p = modname; *p; p++)
            if (*p == '\\') *p = '/';
 
-         _snprintf (buf, sizeof(buf)-1, "emacs_dir=%s", modname);
+         _snprintf (buf, sizeof (buf)-1, "emacs_dir=%s", modname);
          _putenv (strdup (buf));
        }
       /* Handle running emacs from the build directory: src/oo-spd/i386/  */
@@ -1498,7 +1731,7 @@ init_environment (char ** argv)
                  for (p = modname; *p; p++)
                    if (*p == '\\') *p = '/';
 
-                 _snprintf (buf, sizeof(buf)-1, "emacs_dir=%s", modname);
+                 _snprintf (buf, sizeof (buf)-1, "emacs_dir=%s", modname);
                  _putenv (strdup (buf));
                }
            }
@@ -1526,12 +1759,12 @@ init_environment (char ** argv)
                char buf1[SET_ENV_BUF_SIZE], buf2[SET_ENV_BUF_SIZE];
 
                if (dwType == REG_EXPAND_SZ)
-                 ExpandEnvironmentStrings ((LPSTR) lpval, buf1, sizeof(buf1));
+                 ExpandEnvironmentStrings ((LPSTR) lpval, buf1, sizeof (buf1));
                else if (dwType == REG_SZ)
                  strcpy (buf1, lpval);
                if (dwType == REG_EXPAND_SZ || dwType == REG_SZ)
                  {
-                   _snprintf (buf2, sizeof(buf2)-1, "%s=%s", env_vars[i].name,
+                   _snprintf (buf2, sizeof (buf2)-1, "%s=%s", env_vars[i].name,
                               buf1);
                    _putenv (strdup (buf2));
                  }
@@ -1874,7 +2107,7 @@ GetCachedVolumeInformation (char * root_dir)
      involve network access, and so is extremely quick).  */
 
   /* Map drive letter to UNC if remote. */
-  if ( isalpha( root_dir[0] ) && !fixed[ DRIVE_INDEX( root_dir[0] ) ] )
+  if (isalpha (root_dir[0]) && !fixed[DRIVE_INDEX (root_dir[0])])
     {
       char remote_name[ 256 ];
       char drive[3] = { root_dir[0], ':' };
@@ -2273,8 +2506,8 @@ open_unc_volume (const char *path)
   nr.lpComment = NULL;
   nr.lpProvider = NULL;
 
-  result = WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_DISK,
-                       RESOURCEUSAGE_CONNECTABLE, &nr, &henum);
+  result = WNetOpenEnum (RESOURCE_GLOBALNET, RESOURCETYPE_DISK,
+                        RESOURCEUSAGE_CONNECTABLE, &nr, &henum);
 
   if (result == NO_ERROR)
     return henum;
@@ -2339,12 +2572,23 @@ logon_network_drive (const char *path)
   char share[MAX_PATH];
   int i, n_slashes;
   char drive[4];
+  UINT drvtype;
 
-  sprintf (drive, "%c:\\", path[0]);
+  if (IS_DIRECTORY_SEP (path[0]) && IS_DIRECTORY_SEP (path[1]))
+    drvtype = DRIVE_REMOTE;
+  else if (path[0] == '\0' || path[1] != ':')
+    drvtype = GetDriveType (NULL);
+  else
+    {
+      drive[0] = path[0];
+      drive[1] = ':';
+      drive[2] = '\\';
+      drive[3] = '\0';
+      drvtype = GetDriveType (drive);
+    }
 
   /* Only logon to networked drives.  */
-  if ((!IS_DIRECTORY_SEP (path[0]) || !IS_DIRECTORY_SEP (path[1]))
-      && GetDriveType (drive) != DRIVE_REMOTE)
+  if (drvtype != DRIVE_REMOTE)
     return;
 
   n_slashes = 2;
@@ -2439,7 +2683,7 @@ sys_creat (const char * path, int mode)
 }
 
 FILE *
-sys_fopen(const char * path, const char * mode)
+sys_fopen (const char * path, const char * mode)
 {
   int fd;
   int oflag;
@@ -2526,7 +2770,7 @@ sys_link (const char * old, const char * new)
 
          data.wid.dwStreamId = BACKUP_LINK;
          data.wid.dwStreamAttributes = 0;
-         data.wid.Size.LowPart = wlen * sizeof(WCHAR);
+         data.wid.Size.LowPart = wlen * sizeof (WCHAR);
          data.wid.Size.HighPart = 0;
          data.wid.dwStreamNameSize = 0;
 
@@ -2716,76 +2960,69 @@ sys_unlink (const char * path)
 }
 
 static FILETIME utc_base_ft;
-static long double utc_base;
+static ULONGLONG utc_base;  /* In 100ns units */
 static int init = 0;
 
-static long double
-convert_time_raw (FILETIME ft)
+#define FILETIME_TO_U64(result, ft)        \
+  do {                                     \
+    ULARGE_INTEGER uiTemp;                 \
+    uiTemp.LowPart = (ft).dwLowDateTime;   \
+    uiTemp.HighPart = (ft).dwHighDateTime; \
+    result = uiTemp.QuadPart;              \
+  } while (0)
+
+static void
+initialize_utc_base (void)
 {
-  return
-    (long double) ft.dwHighDateTime
-    * 4096.0L * 1024.0L * 1024.0L + ft.dwLowDateTime;
+  /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
+  SYSTEMTIME st;
+
+  st.wYear = 1970;
+  st.wMonth = 1;
+  st.wDay = 1;
+  st.wHour = 0;
+  st.wMinute = 0;
+  st.wSecond = 0;
+  st.wMilliseconds = 0;
+
+  SystemTimeToFileTime (&st, &utc_base_ft);
+  FILETIME_TO_U64 (utc_base, utc_base_ft);
 }
 
 static time_t
 convert_time (FILETIME ft)
 {
-  long double ret;
+  ULONGLONG tmp;
 
   if (!init)
     {
-      /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
-      SYSTEMTIME st;
-
-      st.wYear = 1970;
-      st.wMonth = 1;
-      st.wDay = 1;
-      st.wHour = 0;
-      st.wMinute = 0;
-      st.wSecond = 0;
-      st.wMilliseconds = 0;
-
-      SystemTimeToFileTime (&st, &utc_base_ft);
-      utc_base = (long double) utc_base_ft.dwHighDateTime
-       * 4096.0L * 1024.0L * 1024.0L + utc_base_ft.dwLowDateTime;
+      initialize_utc_base();
       init = 1;
     }
 
   if (CompareFileTime (&ft, &utc_base_ft) < 0)
     return 0;
 
-  return (time_t) ((convert_time_raw (ft) - utc_base) * 1e-7L);
+  FILETIME_TO_U64 (tmp, ft);
+  return (time_t) ((tmp - utc_base) / 10000000L);
 }
 
 
 void
 convert_from_time_t (time_t time, FILETIME * pft)
 {
-  long double tmp;
+  ULARGE_INTEGER tmp;
 
   if (!init)
     {
-      /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
-      SYSTEMTIME st;
-
-      st.wYear = 1970;
-      st.wMonth = 1;
-      st.wDay = 1;
-      st.wHour = 0;
-      st.wMinute = 0;
-      st.wSecond = 0;
-      st.wMilliseconds = 0;
-
-      SystemTimeToFileTime (&st, &utc_base_ft);
-      utc_base = (long double) utc_base_ft.dwHighDateTime
-       * 4096 * 1024 * 1024 + utc_base_ft.dwLowDateTime;
+      initialize_utc_base ();
       init = 1;
     }
 
   /* time in 100ns units since 1-Jan-1601 */
-  tmp = (long double) time * 1e7 + utc_base;
-  pft->dwHighDateTime = (DWORD) (tmp / (4096.0 * 1024 * 1024));
-  pft->dwLowDateTime = (DWORD) (tmp - (4096.0 * 1024 * 1024) * pft->dwHighDateTime);
+  tmp.QuadPart = (ULONGLONG) time * 10000000L + utc_base;
+  pft->dwHighDateTime = tmp.HighPart;
+  pft->dwLowDateTime = tmp.LowPart;
 }
 
 #if 0
@@ -2878,7 +3115,7 @@ get_rid (PSID sid)
 #endif
 
 struct w32_id {
-  int rid;
+  unsigned rid;
   struct w32_id *next;
   char name[GNLEN+1];
   unsigned char sid[FLEXIBLE_ARRAY_MEMBER];
@@ -2887,7 +3124,7 @@ struct w32_id {
 static struct w32_id *w32_idlist;
 
 static int
-w32_cached_id (PSID sid, int *id, char *name)
+w32_cached_id (PSID sid, unsigned *id, char *name)
 {
   struct w32_id *tail, *found;
 
@@ -2910,7 +3147,7 @@ w32_cached_id (PSID sid, int *id, char *name)
 }
 
 static void
-w32_add_to_cache (PSID sid, int id, char *name)
+w32_add_to_cache (PSID sid, unsigned id, char *name)
 {
   DWORD sid_len;
   struct w32_id *new_entry;
@@ -2937,7 +3174,7 @@ w32_add_to_cache (PSID sid, int id, char *name)
 
 static int
 get_name_and_id (PSECURITY_DESCRIPTOR psd, const char *fname,
-                int *id, char *nm, int what)
+                unsigned *id, char *nm, int what)
 {
   PSID sid = NULL;
   char machine[MAX_COMPUTERNAME_LENGTH+1];
@@ -2946,7 +3183,7 @@ get_name_and_id (PSECURITY_DESCRIPTOR psd, const char *fname,
   char name[UNLEN+1];
   DWORD name_len = sizeof (name);
   char domain[1024];
-  DWORD domain_len = sizeof(domain);
+  DWORD domain_len = sizeof (domain);
   char *mp = NULL;
   int use_dflt = 0;
   int result;
@@ -3025,6 +3262,28 @@ get_file_owner_and_group (
     }
 }
 
+/* Return non-zero if NAME is a potentially slow filesystem.  */
+int
+is_slow_fs (const char *name)
+{
+  char drive_root[4];
+  UINT devtype;
+
+  if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1]))
+    devtype = DRIVE_REMOTE;       /* assume UNC name is remote */
+  else if (!(strlen (name) >= 2 && IS_DEVICE_SEP (name[1])))
+    devtype = GetDriveType (NULL); /* use root of current drive */
+  else
+    {
+      /* GetDriveType needs the root directory of the drive.  */
+      strncpy (drive_root, name, 2);
+      drive_root[2] = '\\';
+      drive_root[3] = '\0';
+      devtype = GetDriveType (drive_root);
+    }
+  return !(devtype == DRIVE_FIXED || devtype == DRIVE_RAMDISK);
+}
+
 /* MSVC stat function can't cope with UNC names and has other bugs, so
    replace it with our own.  This also allows us to calculate consistent
    inode values without hacks in the main Emacs code. */
@@ -3138,19 +3397,8 @@ stat (const char * path, struct stat * buf)
        }
     }
 
-  /* GetDriveType needs the root directory of NAME's drive.  */
-  if (!(strlen (name) >= 2 && IS_DEVICE_SEP (name[1])))
-    devtype = GetDriveType (NULL); /* use root of current diectory */
-  else
-    {
-      strncpy (drive_root, name, 3);
-      drive_root[3] = '\0';
-      devtype = GetDriveType (drive_root);
-    }
-
   if (!(NILP (Vw32_get_true_file_attributes)
-       || (EQ (Vw32_get_true_file_attributes, Qlocal)
-           && devtype != DRIVE_FIXED && devtype != DRIVE_RAMDISK))
+       || (EQ (Vw32_get_true_file_attributes, Qlocal) && is_slow_fs (name)))
       /* No access rights required to get info.  */
       && (fh = CreateFile (name, 0, 0, NULL, OPEN_EXISTING,
                           FILE_FLAG_BACKUP_SEMANTICS, NULL))
@@ -3410,7 +3658,7 @@ utime (const char *name, struct utimbuf *times)
 
 /* Helper wrapper functions.  */
 
-HANDLE WINAPI create_toolhelp32_snapshot(
+HANDLE WINAPI create_toolhelp32_snapshot (
     DWORD Flags,
     DWORD Ignored)
 {
@@ -3430,7 +3678,7 @@ HANDLE WINAPI create_toolhelp32_snapshot(
   return (s_pfn_Create_Toolhelp32_Snapshot (Flags, Ignored));
 }
 
-BOOL WINAPI process32_first(
+BOOL WINAPI process32_first (
     HANDLE hSnapshot,
     LPPROCESSENTRY32 lppe)
 {
@@ -3450,7 +3698,7 @@ BOOL WINAPI process32_first(
   return (s_pfn_Process32_First (hSnapshot, lppe));
 }
 
-BOOL WINAPI process32_next(
+BOOL WINAPI process32_next (
     HANDLE hSnapshot,
     LPPROCESSENTRY32 lppe)
 {
@@ -3648,7 +3896,7 @@ BOOL WINAPI global_memory_status_ex (
 }
 
 Lisp_Object
-w32_list_system_processes ()
+list_system_processes (void)
 {
   struct gcpro gcpro1;
   Lisp_Object proclist = Qnil;
@@ -3739,53 +3987,54 @@ restore_privilege (TOKEN_PRIVILEGES *priv)
 }
 
 static Lisp_Object
-ltime (time_sec, time_usec)
-     long time_sec, time_usec;
+ltime (long time_sec, long time_usec)
 {
   return list3 (make_number ((time_sec >> 16) & 0xffff),
                make_number (time_sec & 0xffff),
                make_number (time_usec));
 }
 
+#define U64_TO_LISP_TIME(time) ltime ((time) / 1000000L, (time) % 1000000L)
+
 static int
-process_times (h_proc, ctime, etime, stime, utime, pcpu)
-     HANDLE h_proc;
-     Lisp_Object *ctime, *etime, *stime, *utime;
-     double *pcpu;
+process_times (HANDLE h_proc, Lisp_Object *ctime, Lisp_Object *etime,
+              Lisp_Object *stime, Lisp_Object *utime, Lisp_Object *ttime,
+              double *pcpu)
 {
   FILETIME ft_creation, ft_exit, ft_kernel, ft_user, ft_current;
-  long ctime_sec, ctime_usec, stime_sec, stime_usec, utime_sec, utime_usec;
-  long etime_sec, etime_usec;
-  long double tem1, tem2, tem;
+  ULONGLONG tem1, tem2, tem3, tem;
 
   if (!h_proc
       || !get_process_times_fn
-      || !(*get_process_times_fn)(h_proc, &ft_creation, &ft_exit,
-                                 &ft_kernel, &ft_user))
+      || !(*get_process_times_fn) (h_proc, &ft_creation, &ft_exit,
+                                  &ft_kernel, &ft_user))
     return 0;
 
   GetSystemTimeAsFileTime (&ft_current);
 
-  tem1 = convert_time_raw (ft_kernel) * 0.1L;
-  stime_usec = fmodl (tem1, 1000000.0L);
-  stime_sec = tem1 * 0.000001L;
-  *stime = ltime (stime_sec, stime_usec);
-  tem2 = convert_time_raw (ft_user) * 0.1L;
-  utime_usec = fmodl (tem2, 1000000.0L);
-  utime_sec = tem2 * 0.000001L;
-  *utime = ltime (utime_sec, utime_usec);
-  tem = convert_time_raw (ft_creation);
+  FILETIME_TO_U64 (tem1, ft_kernel);
+  tem1 /= 10L;
+  *stime = U64_TO_LISP_TIME (tem1);
+
+  FILETIME_TO_U64 (tem2, ft_user);
+  tem2 /= 10L;
+  *utime = U64_TO_LISP_TIME (tem2);
+
+  tem3 = tem1 + tem2;
+  *ttime = U64_TO_LISP_TIME (tem3);
+
+  FILETIME_TO_U64 (tem, ft_creation);
   /* Process no 4 (System) returns zero creation time.  */
   if (tem)
-    tem = (tem - utc_base) * 0.1;
-  ctime_usec = fmodl (tem, 1000000.0L);
-  ctime_sec = tem * 0.000001L;
-  *ctime = ltime (ctime_sec, ctime_usec);
+    tem = (tem - utc_base) / 10L;
+  *ctime = U64_TO_LISP_TIME (tem);
+
   if (tem)
-    tem = (convert_time_raw (ft_current) - utc_base) * 0.1L - tem;
-  etime_usec = fmodl (tem, 1000000.0L);
-  etime_sec = tem * 0.000001L;
-  *etime = ltime (etime_sec, etime_usec);
+    {
+      FILETIME_TO_U64 (tem3, ft_current);
+      tem = (tem3 - utc_base) / 10L - tem;
+    }
+  *etime = U64_TO_LISP_TIME (tem);
 
   if (tem)
     {
@@ -3800,8 +4049,7 @@ process_times (h_proc, ctime, etime, stime, utime, pcpu)
 }
 
 Lisp_Object
-w32_system_process_attributes (pid)
-     Lisp_Object pid;
+system_process_attributes (Lisp_Object pid)
 {
   struct gcpro gcpro1, gcpro2, gcpro3;
   Lisp_Object attrs = Qnil;
@@ -3810,15 +4058,16 @@ w32_system_process_attributes (pid)
   DWORD proc_id;
   int found_proc = 0;
   char uname[UNLEN+1], gname[GNLEN+1], domain[1025];
-  DWORD ulength = sizeof (uname), dlength = sizeof (domain), trash;
+  DWORD ulength = sizeof (uname), dlength = sizeof (domain), needed;
   DWORD glength = sizeof (gname);
   HANDLE token = NULL;
   SID_NAME_USE user_type;
-  unsigned char buf[1024];
+  unsigned char *buf = NULL;
+  DWORD blen = 0;
   TOKEN_USER user_token;
   TOKEN_PRIMARY_GROUP group_token;
-  int euid;
-  int egid;
+  unsigned euid;
+  unsigned egid;
   DWORD sess;
   PROCESS_MEMORY_COUNTERS mem;
   PROCESS_MEMORY_COUNTERS_EX mem_ex;
@@ -3826,8 +4075,9 @@ w32_system_process_attributes (pid)
   MEMORYSTATUS memst;
   MEMORY_STATUS_EX memstex;
   double totphys = 0.0;
-  Lisp_Object ctime, stime, utime, etime;
+  Lisp_Object ctime, stime, utime, etime, ttime;
   double pcpu;
+  BOOL result = FALSE;
 
   CHECK_NUMBER_OR_FLOAT (pid);
   proc_id = FLOATP (pid) ? XFLOAT_DATA (pid) : XINT (pid);
@@ -3898,87 +4148,124 @@ w32_system_process_attributes (pid)
          revert_to_self ();
        }
     }
-  if (h_proc
-      && open_process_token (h_proc, TOKEN_QUERY, &token)
-      && get_token_information (token, TokenUser,
-                               (PVOID)buf, sizeof (buf), &trash))
+  if (h_proc)
     {
-      memcpy (&user_token, buf, sizeof (user_token));
-      if (w32_cached_id (user_token.User.Sid, &euid, uname))
-       ulength = strlen (uname);
-      else
-       {
-         lookup_account_sid (NULL, user_token.User.Sid, uname, &ulength,
-                             domain, &dlength, &user_type);
-         euid = get_rid (user_token.User.Sid);
-         w32_add_to_cache (user_token.User.Sid, euid, uname);
-       }
-      /* Determine a reasonable euid and gid values.  */
-      if (xstrcasecmp ("administrator", uname) == 0)
+      result = open_process_token (h_proc, TOKEN_QUERY, &token);
+      if (result)
        {
-         euid = 500;   /* well-known Administrator uid */
-         egid = 513;   /* well-known None gid */
+         result = get_token_information (token, TokenUser, NULL, 0, &blen);
+         if (!result && GetLastError () == ERROR_INSUFFICIENT_BUFFER)
+           {
+             buf = xmalloc (blen);
+             result = get_token_information (token, TokenUser,
+                                             (LPVOID)buf, blen, &needed);
+             if (result)
+               {
+                 memcpy (&user_token, buf, sizeof (user_token));
+                 if (!w32_cached_id (user_token.User.Sid, &euid, uname))
+                   {
+                     euid = get_rid (user_token.User.Sid);
+                     result = lookup_account_sid (NULL, user_token.User.Sid,
+                                                  uname, &ulength,
+                                                  domain, &dlength,
+                                                  &user_type);
+                     if (result)
+                       w32_add_to_cache (user_token.User.Sid, euid, uname);
+                     else
+                       {
+                         strcpy (uname, "unknown");
+                         result = TRUE;
+                       }
+                   }
+                 ulength = strlen (uname);
+               }
+           }
        }
-      else
+      if (result)
        {
-         /* Get group id and name.  */
-         if (get_token_information (token, TokenPrimaryGroup,
-                                    (PVOID)buf, sizeof (buf), &trash))
+         /* Determine a reasonable euid and gid values.  */
+         if (xstrcasecmp ("administrator", uname) == 0)
            {
-             memcpy (&group_token, buf, sizeof (group_token));
-             if (w32_cached_id (group_token.PrimaryGroup, &egid, gname))
-               glength = strlen (gname);
-             else
+             euid = 500;       /* well-known Administrator uid */
+             egid = 513;       /* well-known None gid */
+           }
+         else
+           {
+             /* Get group id and name.  */
+             result = get_token_information (token, TokenPrimaryGroup,
+                                             (LPVOID)buf, blen, &needed);
+             if (!result && GetLastError () == ERROR_INSUFFICIENT_BUFFER)
                {
-                 dlength = sizeof (domain);
-                 lookup_account_sid (NULL, group_token.PrimaryGroup,
-                                     gname, &glength, NULL, &dlength,
-                                     &user_type);
-                 egid = get_rid (group_token.PrimaryGroup);
-                 w32_add_to_cache (group_token.PrimaryGroup, egid, gname);
+                 buf = xrealloc (buf, blen = needed);
+                 result = get_token_information (token, TokenPrimaryGroup,
+                                                 (LPVOID)buf, blen, &needed);
+               }
+             if (result)
+               {
+                 memcpy (&group_token, buf, sizeof (group_token));
+                 if (!w32_cached_id (group_token.PrimaryGroup, &egid, gname))
+                   {
+                     egid = get_rid (group_token.PrimaryGroup);
+                     dlength = sizeof (domain);
+                     result =
+                       lookup_account_sid (NULL, group_token.PrimaryGroup,
+                                           gname, &glength, NULL, &dlength,
+                                           &user_type);
+                     if (result)
+                       w32_add_to_cache (group_token.PrimaryGroup,
+                                         egid, gname);
+                     else
+                       {
+                         strcpy (gname, "None");
+                         result = TRUE;
+                       }
+                   }
+                 glength = strlen (gname);
                }
            }
-         else
-           egid = euid;
        }
+      xfree (buf);
     }
-  else if (!is_windows_9x ())
-    {
-      /* We couldn't open the process token, presumably because of
-        insufficient access rights.  Assume this process is run by
-        the system.  */
-      strcpy (uname, "SYSTEM");
-      strcpy (gname, "None");
-      euid = 18;       /* SYSTEM */
-      egid = 513;      /* None */
-      glength = strlen (gname);
-      ulength = strlen (uname);
-    }
-  /* If we are running under Windows 9X, where security calls are not
-     supported, we assume all processes are run by the current
-     user.  */
-  else if (GetUserName (uname, &ulength))
+  if (!result)
     {
-      if (xstrcasecmp ("administrator", uname) == 0)
-       euid = 0;
+      if (!is_windows_9x ())
+       {
+         /* We couldn't open the process token, presumably because of
+            insufficient access rights.  Assume this process is run
+            by the system.  */
+         strcpy (uname, "SYSTEM");
+         strcpy (gname, "None");
+         euid = 18;    /* SYSTEM */
+         egid = 513;   /* None */
+         glength = strlen (gname);
+         ulength = strlen (uname);
+       }
+      /* If we are running under Windows 9X, where security calls are
+        not supported, we assume all processes are run by the current
+        user.  */
+      else if (GetUserName (uname, &ulength))
+       {
+         if (xstrcasecmp ("administrator", uname) == 0)
+           euid = 0;
+         else
+           euid = 123;
+         egid = euid;
+         strcpy (gname, "None");
+         glength = strlen (gname);
+         ulength = strlen (uname);
+       }
       else
-       euid = 123;
-      egid = euid;
-      strcpy (gname, "None");
-      glength = strlen (gname);
-      ulength = strlen (uname);
-    }
-  else
-    {
-      euid = 123;
-      egid = 123;
-      strcpy (uname, "administrator");
-      ulength = strlen (uname);
-      strcpy (gname, "None");
-      glength = strlen (gname);
+       {
+         euid = 123;
+         egid = 123;
+         strcpy (uname, "administrator");
+         ulength = strlen (uname);
+         strcpy (gname, "None");
+         glength = strlen (gname);
+       }
+      if (token)
+       CloseHandle (token);
     }
-  if (token)
-    CloseHandle (token);
 
   attrs = Fcons (Fcons (Qeuid, make_fixnum_or_float (euid)), attrs);
   tem = make_unibyte_string (uname, ulength);
@@ -4046,10 +4333,11 @@ w32_system_process_attributes (pid)
        attrs = Fcons (Fcons (Qpmem, make_float (100. * rss / totphys)), attrs);
     }
 
-  if (process_times (h_proc, &ctime, &etime, &stime, &utime, &pcpu))
+  if (process_times (h_proc, &ctime, &etime, &stime, &utime, &ttime, &pcpu))
     {
       attrs = Fcons (Fcons (Qutime, utime), attrs);
       attrs = Fcons (Fcons (Qstime, stime), attrs);
+      attrs = Fcons (Fcons (Qtime,  ttime), attrs);
       attrs = Fcons (Fcons (Qstart, ctime), attrs);
       attrs = Fcons (Fcons (Qetime, etime), attrs);
       attrs = Fcons (Fcons (Qpcpu, make_float (pcpu)), attrs);
@@ -4160,34 +4448,34 @@ init_winsock (int load_now)
       if ((pfn_##fn = (void *) GetProcAddress (winsock_lib, #fn)) == NULL) \
         goto fail;
 
-      LOAD_PROC( WSAStartup );
-      LOAD_PROC( WSASetLastError );
-      LOAD_PROC( WSAGetLastError );
-      LOAD_PROC( WSAEventSelect );
-      LOAD_PROC( WSACreateEvent );
-      LOAD_PROC( WSACloseEvent );
-      LOAD_PROC( socket );
-      LOAD_PROC( bind );
-      LOAD_PROC( connect );
-      LOAD_PROC( ioctlsocket );
-      LOAD_PROC( recv );
-      LOAD_PROC( send );
-      LOAD_PROC( closesocket );
-      LOAD_PROC( shutdown );
-      LOAD_PROC( htons );
-      LOAD_PROC( ntohs );
-      LOAD_PROC( inet_addr );
-      LOAD_PROC( gethostname );
-      LOAD_PROC( gethostbyname );
-      LOAD_PROC( getservbyname );
-      LOAD_PROC( getpeername );
-      LOAD_PROC( WSACleanup );
-      LOAD_PROC( setsockopt );
-      LOAD_PROC( listen );
-      LOAD_PROC( getsockname );
-      LOAD_PROC( accept );
-      LOAD_PROC( recvfrom );
-      LOAD_PROC( sendto );
+      LOAD_PROC (WSAStartup);
+      LOAD_PROC (WSASetLastError);
+      LOAD_PROC (WSAGetLastError);
+      LOAD_PROC (WSAEventSelect);
+      LOAD_PROC (WSACreateEvent);
+      LOAD_PROC (WSACloseEvent);
+      LOAD_PROC (socket);
+      LOAD_PROC (bind);
+      LOAD_PROC (connect);
+      LOAD_PROC (ioctlsocket);
+      LOAD_PROC (recv);
+      LOAD_PROC (send);
+      LOAD_PROC (closesocket);
+      LOAD_PROC (shutdown);
+      LOAD_PROC (htons);
+      LOAD_PROC (ntohs);
+      LOAD_PROC (inet_addr);
+      LOAD_PROC (gethostname);
+      LOAD_PROC (gethostbyname);
+      LOAD_PROC (getservbyname);
+      LOAD_PROC (getpeername);
+      LOAD_PROC (WSACleanup);
+      LOAD_PROC (setsockopt);
+      LOAD_PROC (listen);
+      LOAD_PROC (getsockname);
+      LOAD_PROC (accept);
+      LOAD_PROC (recvfrom);
+      LOAD_PROC (sendto);
 #undef LOAD_PROC
 
       /* specify version 1.1 of winsock */
@@ -4227,7 +4515,7 @@ int h_errno = 0;
    normal system codes where they overlap (non-overlapping definitions
    are already in <sys/socket.h> */
 static void
-set_errno ()
+set_errno (void)
 {
   if (winsock_lib == NULL)
     h_errno = EINVAL;
@@ -4249,7 +4537,7 @@ set_errno ()
 }
 
 static void
-check_errno ()
+check_errno (void)
 {
   if (h_errno == 0 && winsock_lib != NULL)
     pfn_WSASetLastError (0);
@@ -4332,7 +4620,7 @@ struct {
 };
 
 char *
-sys_strerror(int error_no)
+sys_strerror (int error_no)
 {
   int i;
   static char unknown_msg[40];
@@ -4344,7 +4632,7 @@ sys_strerror(int error_no)
     if (_wsa_errlist[i].errnum == error_no)
       return _wsa_errlist[i].msg;
 
-  sprintf(unknown_msg, "Unidentified error: %d", error_no);
+  sprintf (unknown_msg, "Unidentified error: %d", error_no);
   return unknown_msg;
 }
 
@@ -4363,7 +4651,7 @@ sys_strerror(int error_no)
 int socket_to_fd (SOCKET s);
 
 int
-sys_socket(int af, int type, int protocol)
+sys_socket (int af, int type, int protocol)
 {
   SOCKET s;
 
@@ -4566,7 +4854,7 @@ sys_gethostname (char * name, int namelen)
 }
 
 struct hostent *
-sys_gethostbyname(const char * name)
+sys_gethostbyname (const char * name)
 {
   struct hostent * host;
 
@@ -4584,7 +4872,7 @@ sys_gethostbyname(const char * name)
 }
 
 struct servent *
-sys_getservbyname(const char * name, const char * proto)
+sys_getservbyname (const char * name, const char * proto)
 {
   struct servent * serv;
 
@@ -4739,7 +5027,7 @@ sys_accept (int s, struct sockaddr * addr, int * addrlen)
 
 int
 sys_recvfrom (int s, char * buf, int len, int flags,
-         struct sockaddr * from, int * fromlen)
+             struct sockaddr * from, int * fromlen)
 {
   if (winsock_lib == NULL)
     {
@@ -5237,8 +5525,8 @@ sys_read (int fd, char * buffer, unsigned int count)
                  int res = pfn_recv (SOCK_HANDLE (fd), buffer, count, 0);
                  if (res == SOCKET_ERROR)
                    {
-                     DebPrint(("sys_read.recv failed with error %d on socket %ld\n",
-                               pfn_WSAGetLastError (), SOCK_HANDLE (fd)));
+                     DebPrint (("sys_read.recv failed with error %d on socket %ld\n",
+                                pfn_WSAGetLastError (), SOCK_HANDLE (fd)));
                      set_errno ();
                      return -1;
                    }
@@ -5394,20 +5682,47 @@ sys_write (int fd, const void * buffer, unsigned int count)
 
       if (nchars == SOCKET_ERROR)
         {
-         DebPrint(("sys_write.send failed with error %d on socket %ld\n",
-                   pfn_WSAGetLastError (), SOCK_HANDLE (fd)));
+         DebPrint (("sys_write.send failed with error %d on socket %ld\n",
+                    pfn_WSAGetLastError (), SOCK_HANDLE (fd)));
          set_errno ();
        }
     }
   else
 #endif
-    nchars = _write (fd, buffer, count);
+    {
+      /* Some networked filesystems don't like too large writes, so
+        break them into smaller chunks.  See the Comments section of
+        the MSDN documentation of WriteFile for details behind the
+        choice of the value of CHUNK below.  See also the thread
+        http://thread.gmane.org/gmane.comp.version-control.git/145294
+        in the git mailing list.  */
+      const unsigned char *p = buffer;
+      const unsigned chunk = 30 * 1024 * 1024;
+
+      nchars = 0;
+      while (count > 0)
+       {
+         unsigned this_chunk = count < chunk ? count : chunk;
+         int n = _write (fd, p, this_chunk);
+
+         nchars += n;
+         if (n < 0)
+           {
+             nchars = n;
+             break;
+           }
+         else if (n < this_chunk)
+           break;
+         count -= n;
+         p += n;
+       }
+    }
 
   return nchars;
 }
 
 static void
-check_windows_init_file ()
+check_windows_init_file (void)
 {
   extern int noninteractive, inhibit_window_system;
 
@@ -5463,7 +5778,7 @@ check_windows_init_file ()
 }
 
 void
-term_ntproc ()
+term_ntproc (void)
 {
 #ifdef HAVE_SOCKETS
   /* shutdown the socket interface if necessary */
@@ -5474,7 +5789,7 @@ term_ntproc ()
 }
 
 void
-init_ntproc ()
+init_ntproc (void)
 {
 #ifdef HAVE_SOCKETS
   /* Initialise the socket interface now if available and requested by
@@ -5582,7 +5897,8 @@ init_ntproc ()
         shutdown_handler ensures that buffers' autosave files are
        up to date when the user logs off, or the system shuts down.
 */
-BOOL WINAPI shutdown_handler(DWORD type)
+BOOL WINAPI
+shutdown_handler (DWORD type)
 {
   /* Ctrl-C and Ctrl-Break are already suppressed, so don't handle them.  */
   if (type == CTRL_CLOSE_EVENT        /* User closes console window.  */
@@ -5603,7 +5919,7 @@ BOOL WINAPI shutdown_handler(DWORD type)
        initialized is non zero (see the function main in emacs.c).
 */
 void
-globals_of_w32 ()
+globals_of_w32 (void)
 {
   HMODULE kernel32 = GetModuleHandle ("kernel32.dll");
 
@@ -5634,18 +5950,22 @@ globals_of_w32 ()
   g_b_init_equal_sid = 0;
   g_b_init_copy_sid = 0;
   g_b_init_get_length_sid = 0;
+  g_b_init_get_native_system_info = 0;
+  g_b_init_get_system_times = 0;
+  num_of_processors = 0;
   /* The following sets a handler for shutdown notifications for
      console apps. This actually applies to Emacs in both console and
      GUI modes, since we had to fool windows into thinking emacs is a
      console application to get console mode to work.  */
-  SetConsoleCtrlHandler(shutdown_handler, TRUE);
+  SetConsoleCtrlHandler (shutdown_handler, TRUE);
 
   /* "None" is the default group name on standalone workstations.  */
   strcpy (dflt_group_name, "None");
 }
 
 /* For make-serial-process  */
-int serial_open (char *port)
+int
+serial_open (char *port)
 {
   HANDLE hnd;
   child_process *cp;
@@ -5685,7 +6005,7 @@ int serial_open (char *port)
 /* For serial-process-configure  */
 void
 serial_configure (struct Lisp_Process *p,
-                     Lisp_Object contact)
+                 Lisp_Object contact)
 {
   Lisp_Object childp2 = Qnil;
   Lisp_Object tem = Qnil;