Implement dynamic loading of GnuTLS on Windows.
[bpt/emacs.git] / src / w32.c
index f1ed6ae..d81fdf3 100644 (file)
--- a/src/w32.c
+++ b/src/w32.c
@@ -1,6 +1,5 @@
 /* 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, 2009, 2010  Free Software Foundation, Inc.
+   Copyright (C) 1994-1995, 2000-2011  Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -35,12 +34,11 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <mbstring.h>  /* for _mbspbrk */
 #include <math.h>
 #include <setjmp.h>
+#include <time.h>
 
 /* must include CRT headers *before* config.h */
 
-#ifdef HAVE_CONFIG_H
 #include <config.h>
-#endif
 
 #undef access
 #undef chdir
@@ -65,6 +63,8 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #undef strerror
 
+#undef localtime
+
 #include "lisp.h"
 
 #include <pwd.h>
@@ -78,15 +78,15 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 /* Some versions of compiler define MEMORYSTATUSEX, some don't, so we
    use a different name to avoid compilation problems.  */
 typedef struct _MEMORY_STATUS_EX {
-        DWORD dwLength;
-        DWORD dwMemoryLoad;
-        DWORDLONG ullTotalPhys;
-        DWORDLONG ullAvailPhys;
-        DWORDLONG ullTotalPageFile;
-        DWORDLONG ullAvailPageFile;
-        DWORDLONG ullTotalVirtual;
-        DWORDLONG ullAvailVirtual;
-        DWORDLONG ullAvailExtendedVirtual;
+  DWORD dwLength;
+  DWORD dwMemoryLoad;
+  DWORDLONG ullTotalPhys;
+  DWORDLONG ullAvailPhys;
+  DWORDLONG ullTotalPageFile;
+  DWORDLONG ullAvailPageFile;
+  DWORDLONG ullTotalVirtual;
+  DWORDLONG ullAvailVirtual;
+  DWORDLONG ullAvailExtendedVirtual;
 } MEMORY_STATUS_EX,*LPMEMORY_STATUS_EX;
 
 #include <lmcons.h>
@@ -94,23 +94,27 @@ 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 supplied with MinGW 3.15
+   defines it in psapi.h  */
 typedef struct _PROCESS_MEMORY_COUNTERS_EX {
-       DWORD cb;
-       DWORD PageFaultCount;
-       DWORD PeakWorkingSetSize;
-       DWORD WorkingSetSize;
-       DWORD QuotaPeakPagedPoolUsage;
-       DWORD QuotaPagedPoolUsage;
-       DWORD QuotaPeakNonPagedPoolUsage;
-       DWORD QuotaNonPagedPoolUsage;
-       DWORD PagefileUsage;
-       DWORD PeakPagefileUsage;
-       DWORD PrivateUsage;
+  DWORD cb;
+  DWORD PageFaultCount;
+  DWORD PeakWorkingSetSize;
+  DWORD WorkingSetSize;
+  DWORD QuotaPeakPagedPoolUsage;
+  DWORD QuotaPagedPoolUsage;
+  DWORD QuotaPeakNonPagedPoolUsage;
+  DWORD QuotaNonPagedPoolUsage;
+  DWORD PagefileUsage;
+  DWORD PeakPagefileUsage;
+  DWORD PrivateUsage;
 } PROCESS_MEMORY_COUNTERS_EX,*PPROCESS_MEMORY_COUNTERS_EX;
+#endif
 
-#ifdef HAVE_SOCKETS    /* TCP connection support, if kernel can do it */
+/* TCP connection support.  */
 #include <sys/socket.h>
 #undef socket
 #undef bind
@@ -129,7 +133,6 @@ typedef struct _PROCESS_MEMORY_COUNTERS_EX {
 #undef accept
 #undef recvfrom
 #undef sendto
-#endif
 
 #include "w32.h"
 #include "ndir.h"
@@ -138,23 +141,20 @@ typedef struct _PROCESS_MEMORY_COUNTERS_EX {
 #include "dispextern.h"                /* for xstrcasecmp */
 #include "coding.h"            /* for Vlocale_coding_system */
 
+#include "careadlinkat.h"
+#include "allocator.h"
+
 /* For serial_configure and serial_open.  */
 #include "process.h"
 
 typedef HRESULT (WINAPI * ShGetFolderPath_fn)
   (IN HWND, IN int, IN HANDLE, IN DWORD, OUT char *);
 
+Lisp_Object QCloaded_from;
+
 void globals_of_w32 (void);
 static DWORD get_rid (PSID);
 
-extern Lisp_Object Vw32_downcase_file_names;
-extern Lisp_Object Vw32_generate_fake_inodes;
-extern Lisp_Object Vw32_get_true_file_attributes;
-/* Defined in process.c for its own purpose.  */
-extern Lisp_Object Qlocal;
-
-extern int w32_num_mouse_buttons;
-
 \f
 /* Initialization states.
 
@@ -169,7 +169,6 @@ static BOOL g_b_init_is_windows_9x;
 static BOOL g_b_init_open_process_token;
 static BOOL g_b_init_get_token_information;
 static BOOL g_b_init_lookup_account_sid;
-static BOOL g_b_init_get_sid_identifier_authority;
 static BOOL g_b_init_get_sid_sub_authority;
 static BOOL g_b_init_get_sid_sub_authority_count;
 static BOOL g_b_init_get_file_security;
@@ -232,8 +231,6 @@ typedef BOOL (WINAPI * LookupAccountSid_Proc) (
     LPTSTR DomainName,
     LPDWORD cbDomainName,
     PSID_NAME_USE peUse);
-typedef PSID_IDENTIFIER_AUTHORITY (WINAPI * GetSidIdentifierAuthority_Proc) (
-    PSID pSid);
 typedef PDWORD (WINAPI * GetSidSubAuthority_Proc) (
     PSID pSid,
     DWORD n);
@@ -300,13 +297,11 @@ typedef BOOL (WINAPI * GetSystemTimes_Proc) (
     LPFILETIME lpKernelTime,
     LPFILETIME lpUserTime);
 
-
-
   /* ** A utility function ** */
 static BOOL
 is_windows_9x (void)
 {
-  static BOOL s_b_ret=0;
+  static BOOL s_b_ret = 0;
   OSVERSIONINFO os_ver;
   if (g_b_init_is_windows_9x == 0)
     {
@@ -363,10 +358,10 @@ w32_get_internal_run_time (void)
 
   /* ** The wrapper functions ** */
 
-BOOL WINAPI open_process_token (
-    HANDLE ProcessHandle,
-    DWORD DesiredAccess,
-    PHANDLE TokenHandle)
+static BOOL WINAPI
+open_process_token (HANDLE ProcessHandle,
+                   DWORD DesiredAccess,
+                   PHANDLE TokenHandle)
 {
   static OpenProcessToken_Proc s_pfn_Open_Process_Token = NULL;
   HMODULE hm_advapi32 = NULL;
@@ -393,12 +388,12 @@ BOOL WINAPI open_process_token (
       );
 }
 
-BOOL WINAPI get_token_information (
-    HANDLE TokenHandle,
-    TOKEN_INFORMATION_CLASS TokenInformationClass,
-    LPVOID TokenInformation,
-    DWORD TokenInformationLength,
-    PDWORD ReturnLength)
+static BOOL WINAPI
+get_token_information (HANDLE TokenHandle,
+                      TOKEN_INFORMATION_CLASS TokenInformationClass,
+                      LPVOID TokenInformation,
+                      DWORD TokenInformationLength,
+                      PDWORD ReturnLength)
 {
   static GetTokenInformation_Proc s_pfn_Get_Token_Information = NULL;
   HMODULE hm_advapi32 = NULL;
@@ -427,14 +422,14 @@ BOOL WINAPI get_token_information (
       );
 }
 
-BOOL WINAPI lookup_account_sid (
-    LPCTSTR lpSystemName,
-    PSID Sid,
-    LPTSTR Name,
-    LPDWORD cbName,
-    LPTSTR DomainName,
-    LPDWORD cbDomainName,
-    PSID_NAME_USE peUse)
+static BOOL WINAPI
+lookup_account_sid (LPCTSTR lpSystemName,
+                   PSID Sid,
+                   LPTSTR Name,
+                   LPDWORD cbName,
+                   LPTSTR DomainName,
+                   LPDWORD cbDomainName,
+                   PSID_NAME_USE peUse)
 {
   static LookupAccountSid_Proc s_pfn_Lookup_Account_Sid = NULL;
   HMODULE hm_advapi32 = NULL;
@@ -465,33 +460,8 @@ BOOL WINAPI lookup_account_sid (
       );
 }
 
-PSID_IDENTIFIER_AUTHORITY WINAPI get_sid_identifier_authority (
-    PSID pSid)
-{
-  static GetSidIdentifierAuthority_Proc s_pfn_Get_Sid_Identifier_Authority = NULL;
-  HMODULE hm_advapi32 = NULL;
-  if (is_windows_9x () == TRUE)
-    {
-      return NULL;
-    }
-  if (g_b_init_get_sid_identifier_authority == 0)
-    {
-      g_b_init_get_sid_identifier_authority = 1;
-      hm_advapi32 = LoadLibrary ("Advapi32.dll");
-      s_pfn_Get_Sid_Identifier_Authority =
-        (GetSidIdentifierAuthority_Proc) GetProcAddress (
-            hm_advapi32, "GetSidIdentifierAuthority");
-    }
-  if (s_pfn_Get_Sid_Identifier_Authority == NULL)
-    {
-      return NULL;
-    }
-  return (s_pfn_Get_Sid_Identifier_Authority (pSid));
-}
-
-PDWORD WINAPI get_sid_sub_authority (
-    PSID pSid,
-    DWORD n)
+static PDWORD WINAPI
+get_sid_sub_authority (PSID pSid, DWORD n)
 {
   static GetSidSubAuthority_Proc s_pfn_Get_Sid_Sub_Authority = NULL;
   static DWORD zero = 0U;
@@ -515,8 +485,8 @@ PDWORD WINAPI get_sid_sub_authority (
   return (s_pfn_Get_Sid_Sub_Authority (pSid, n));
 }
 
-PUCHAR WINAPI get_sid_sub_authority_count (
-    PSID pSid)
+static PUCHAR WINAPI
+get_sid_sub_authority_count (PSID pSid)
 {
   static GetSidSubAuthorityCount_Proc s_pfn_Get_Sid_Sub_Authority_Count = NULL;
   static UCHAR zero = 0U;
@@ -540,12 +510,12 @@ PUCHAR WINAPI get_sid_sub_authority_count (
   return (s_pfn_Get_Sid_Sub_Authority_Count (pSid));
 }
 
-BOOL WINAPI get_file_security (
-    LPCTSTR lpFileName,
-    SECURITY_INFORMATION RequestedInformation,
-    PSECURITY_DESCRIPTOR pSecurityDescriptor,
-    DWORD nLength,
-    LPDWORD lpnLengthNeeded)
+static BOOL WINAPI
+get_file_security (LPCTSTR lpFileName,
+                  SECURITY_INFORMATION RequestedInformation,
+                  PSECURITY_DESCRIPTOR pSecurityDescriptor,
+                  DWORD nLength,
+                  LPDWORD lpnLengthNeeded)
 {
   static GetFileSecurity_Proc s_pfn_Get_File_Security = NULL;
   HMODULE hm_advapi32 = NULL;
@@ -570,10 +540,10 @@ BOOL WINAPI get_file_security (
                                   lpnLengthNeeded));
 }
 
-BOOL WINAPI get_security_descriptor_owner (
-    PSECURITY_DESCRIPTOR pSecurityDescriptor,
-    PSID *pOwner,
-    LPBOOL lpbOwnerDefaulted)
+static BOOL WINAPI
+get_security_descriptor_owner (PSECURITY_DESCRIPTOR pSecurityDescriptor,
+                              PSID *pOwner,
+                              LPBOOL lpbOwnerDefaulted)
 {
   static GetSecurityDescriptorOwner_Proc s_pfn_Get_Security_Descriptor_Owner = NULL;
   HMODULE hm_advapi32 = NULL;
@@ -597,10 +567,10 @@ BOOL WINAPI get_security_descriptor_owner (
                                               lpbOwnerDefaulted));
 }
 
-BOOL WINAPI get_security_descriptor_group (
-    PSECURITY_DESCRIPTOR pSecurityDescriptor,
-    PSID *pGroup,
-    LPBOOL lpbGroupDefaulted)
+static BOOL WINAPI
+get_security_descriptor_group (PSECURITY_DESCRIPTOR pSecurityDescriptor,
+                              PSID *pGroup,
+                              LPBOOL lpbGroupDefaulted)
 {
   static GetSecurityDescriptorGroup_Proc s_pfn_Get_Security_Descriptor_Group = NULL;
   HMODULE hm_advapi32 = NULL;
@@ -624,8 +594,8 @@ BOOL WINAPI get_security_descriptor_group (
                                               lpbGroupDefaulted));
 }
 
-BOOL WINAPI is_valid_sid (
-    PSID sid)
+static BOOL WINAPI
+is_valid_sid (PSID sid)
 {
   static IsValidSid_Proc s_pfn_Is_Valid_Sid = NULL;
   HMODULE hm_advapi32 = NULL;
@@ -648,9 +618,8 @@ BOOL WINAPI is_valid_sid (
   return (s_pfn_Is_Valid_Sid (sid));
 }
 
-BOOL WINAPI equal_sid (
-    PSID sid1,
-    PSID sid2)
+static BOOL WINAPI
+equal_sid (PSID sid1, PSID sid2)
 {
   static EqualSid_Proc s_pfn_Equal_Sid = NULL;
   HMODULE hm_advapi32 = NULL;
@@ -673,8 +642,8 @@ BOOL WINAPI equal_sid (
   return (s_pfn_Equal_Sid (sid1, sid2));
 }
 
-DWORD WINAPI get_length_sid (
-    PSID sid)
+static DWORD WINAPI
+get_length_sid (PSID sid)
 {
   static GetLengthSid_Proc s_pfn_Get_Length_Sid = NULL;
   HMODULE hm_advapi32 = NULL;
@@ -697,10 +666,8 @@ DWORD WINAPI get_length_sid (
   return (s_pfn_Get_Length_Sid (sid));
 }
 
-BOOL WINAPI copy_sid (
-    DWORD destlen,
-    PSID dest,
-    PSID src)
+static BOOL WINAPI
+copy_sid (DWORD destlen, PSID dest, PSID src)
 {
   static CopySid_Proc s_pfn_Copy_Sid = NULL;
   HMODULE hm_advapi32 = NULL;
@@ -729,8 +696,8 @@ BOOL WINAPI copy_sid (
   supported in Windows NT / 2k / XP
 */
 
-void WINAPI get_native_system_info (
-    LPSYSTEM_INFO lpSystemInfo)
+static void WINAPI
+get_native_system_info (LPSYSTEM_INFO lpSystemInfo)
 {
   static GetNativeSystemInfo_Proc s_pfn_Get_Native_System_Info = NULL;
   if (is_windows_9x () != TRUE)
@@ -749,10 +716,10 @@ void WINAPI get_native_system_info (
     lpSystemInfo->dwNumberOfProcessors = -1;
 }
 
-BOOL WINAPI get_system_times (
-    LPFILETIME lpIdleTime,
-    LPFILETIME lpKernelTime,
-    LPFILETIME lpUserTime)
+static 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)
@@ -830,17 +797,6 @@ getwd (char *dir)
 #endif
 }
 
-#ifndef HAVE_SOCKETS
-/* Emulate gethostname.  */
-int
-gethostname (char *buffer, int size)
-{
-  /* NT only allows small host names, so the buffer is
-     certainly large enough.  */
-  return !GetComputerName (buffer, &size);
-}
-#endif /* HAVE_SOCKETS */
-
 /* Emulate getloadavg.  */
 
 struct load_sample {
@@ -1086,7 +1042,7 @@ getpwnam (char *name)
   return pw;
 }
 
-void
+static void
 init_user_info (void)
 {
   /* Find the user's real name by opening the process token and
@@ -1292,7 +1248,7 @@ unixtodos_filename (register char *p)
 /* Remove all CR's that are followed by a LF.
    (From msdos.c...probably should figure out a way to share it,
    although this code isn't going to ever change.)  */
-int
+static int
 crlf_to_lf (register int n, register unsigned char *buf)
 {
   unsigned char *np = buf;
@@ -1431,7 +1387,7 @@ w32_get_long_filename (char * name, char * buf, int size)
   return TRUE;
 }
 
-int
+static int
 is_unc_volume (const char *filename)
 {
   const char *ptr = filename;
@@ -1557,7 +1513,6 @@ w32_get_resource (char *key, LPDWORD lpdwtype)
 }
 
 char *get_emacs_configuration (void);
-extern Lisp_Object Vsystem_configuration;
 
 void
 init_environment (char ** argv)
@@ -1608,6 +1563,7 @@ init_environment (char ** argv)
     char locale_name[32];
     struct stat ignored;
     char default_home[MAX_PATH];
+    int appdata = 0;
 
     static const struct env_entry
     {
@@ -1645,25 +1601,28 @@ init_environment (char ** argv)
        If not, then we can try to default to the appdata directory under the
        user's profile, which is more likely to be writable.   */
     if (stat ("C:/.emacs", &ignored) < 0)
-    {
-      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.  */
-      ShGetFolderPath_fn get_folder_path;
-      get_folder_path = (ShGetFolderPath_fn)
-       GetProcAddress (GetModuleHandle ("shell32.dll"), "SHGetFolderPathA");
-
-      if (get_folder_path != NULL)
-       {
-         profile_result = get_folder_path (NULL, CSIDL_APPDATA, NULL,
-                                           0, default_home);
+      {
+       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.  */
+       ShGetFolderPath_fn get_folder_path;
+       get_folder_path = (ShGetFolderPath_fn)
+         GetProcAddress (GetModuleHandle ("shell32.dll"), "SHGetFolderPathA");
+
+       if (get_folder_path != NULL)
+         {
+           profile_result = get_folder_path (NULL, CSIDL_APPDATA, NULL,
+                                             0, default_home);
 
-         /* If we can't get the appdata dir, revert to old behavior.  */
-         if (profile_result == S_OK)
-           env_vars[0].def_value = default_home;
-       }
-    }
+           /* If we can't get the appdata dir, revert to old behavior.  */
+           if (profile_result == S_OK)
+             {
+               env_vars[0].def_value = default_home;
+               appdata = 1;
+             }
+         }
+      }
 
   /* Get default locale info and use it for LANG.  */
   if (GetLocaleInfo (LOCALE_USER_DEFAULT,
@@ -1748,6 +1707,14 @@ init_environment (char ** argv)
                lpval = env_vars[i].def_value;
                dwType = REG_EXPAND_SZ;
                dont_free = 1;
+               if (!strcmp (env_vars[i].name, "HOME") && !appdata)
+                 {
+                   Lisp_Object warning[2];
+                   warning[0] = intern ("initialization");
+                   warning[1] = build_string ("Setting HOME to C:\\ by default is deprecated");
+                   Vdelayed_warnings_list = Fcons (Flist (2, warning),
+                                                   Vdelayed_warnings_list);
+                 }
              }
 
            if (lpval)
@@ -1933,7 +1900,25 @@ get_emacs_configuration (void)
 char *
 get_emacs_configuration_options (void)
 {
-  static char options_buffer[256];
+  static char *options_buffer;
+  char cv[32];  /* Enough for COMPILER_VERSION.  */
+  char *options[] = {
+    cv,  /* To be filled later.  */
+#ifdef EMACSDEBUG
+    " --no-opt",
+#endif
+    /* configure.bat already sets USER_CFLAGS and USER_LDFLAGS
+       with a starting space to save work here.  */
+#ifdef USER_CFLAGS
+    " --cflags", USER_CFLAGS,
+#endif
+#ifdef USER_LDFLAGS
+    " --ldflags", USER_LDFLAGS,
+#endif
+    NULL
+  };
+  size_t size = 0;
+  int i;
 
 /* Work out the effective configure options for this build.  */
 #ifdef _MSC_VER
@@ -1946,18 +1931,19 @@ get_emacs_configuration_options (void)
 #endif
 #endif
 
-  sprintf (options_buffer, COMPILER_VERSION);
-#ifdef EMACSDEBUG
-  strcat (options_buffer, " --no-opt");
-#endif
-#ifdef USER_CFLAGS
-  strcat (options_buffer, " --cflags");
-  strcat (options_buffer, USER_CFLAGS);
-#endif
-#ifdef USER_LDFLAGS
-  strcat (options_buffer, " --ldflags");
-  strcat (options_buffer, USER_LDFLAGS);
-#endif
+  if (_snprintf (cv, sizeof (cv) - 1, COMPILER_VERSION) < 0)
+    return "Error: not enough space for compiler version";
+  cv[sizeof (cv) - 1] = '\0';
+
+  for (i = 0; options[i]; i++)
+    size += strlen (options[i]);
+
+  options_buffer = xmalloc (size + 1);
+  options_buffer[0] = '\0';
+
+  for (i = 0; options[i]; i++)
+    strcat (options_buffer, options[i]);
+
   return options_buffer;
 }
 
@@ -1973,6 +1959,12 @@ gettimeofday (struct timeval *tv, struct timezone *tz)
 
   tv->tv_sec = tb.time;
   tv->tv_usec = tb.millitm * 1000L;
+  /* Implementation note: _ftime sometimes doesn't update the dstflag
+     according to the new timezone when the system timezone is
+     changed.  We could fix that by using GetSystemTime and
+     GetTimeZoneInformation, but that doesn't seem necessary, since
+     Emacs always calls gettimeofday with the 2nd argument NULL (see
+     EMACS_GET_TIME).  */
   if (tz)
     {
       tz->tz_minuteswest = tb.timezone;        /* minutes west of Greenwich  */
@@ -2068,7 +2060,7 @@ add_volume_info (char * root_dir, volume_info_data * info)
 /* Wrapper for GetVolumeInformation, which uses caching to avoid
    performance penalty (~2ms on 486 for local drives, 7.5ms for local
    cdrom drive, ~5-10ms or more for remote drives on LAN).  */
-volume_info_data *
+static volume_info_data *
 GetCachedVolumeInformation (char * root_dir)
 {
   volume_info_data * info;
@@ -2117,49 +2109,49 @@ GetCachedVolumeInformation (char * root_dir)
   info = lookup_volume_info (root_dir);
 
   if (info == NULL || ! VOLINFO_STILL_VALID (root_dir, info))
-  {
-    char  name[ 256 ];
-    DWORD serialnum;
-    DWORD maxcomp;
-    DWORD flags;
-    char  type[ 256 ];
-
-    /* Info is not cached, or is stale. */
-    if (!GetVolumeInformation (root_dir,
-                              name, sizeof (name),
-                              &serialnum,
-                              &maxcomp,
-                              &flags,
-                              type, sizeof (type)))
-      return NULL;
+    {
+      char  name[ 256 ];
+      DWORD serialnum;
+      DWORD maxcomp;
+      DWORD flags;
+      char  type[ 256 ];
+
+      /* Info is not cached, or is stale. */
+      if (!GetVolumeInformation (root_dir,
+                                name, sizeof (name),
+                                &serialnum,
+                                &maxcomp,
+                                &flags,
+                                type, sizeof (type)))
+       return NULL;
 
-    /* Cache the volume information for future use, overwriting existing
-       entry if present.  */
-    if (info == NULL)
-      {
-       info = (volume_info_data *) xmalloc (sizeof (volume_info_data));
-       add_volume_info (root_dir, info);
-      }
-    else
-      {
-       xfree (info->name);
-       xfree (info->type);
-      }
+      /* Cache the volume information for future use, overwriting existing
+        entry if present.  */
+      if (info == NULL)
+       {
+         info = (volume_info_data *) xmalloc (sizeof (volume_info_data));
+         add_volume_info (root_dir, info);
+       }
+      else
+       {
+         xfree (info->name);
+         xfree (info->type);
+       }
 
-    info->name = xstrdup (name);
-    info->serialnum = serialnum;
-    info->maxcomp = maxcomp;
-    info->flags = flags;
-    info->type = xstrdup (type);
-    info->timestamp = GetTickCount ();
-  }
+      info->name = xstrdup (name);
+      info->serialnum = serialnum;
+      info->maxcomp = maxcomp;
+      info->flags = flags;
+      info->type = xstrdup (type);
+      info->timestamp = GetTickCount ();
+    }
 
   return info;
 }
 
 /* Get information on the volume where name is held; set path pointer to
    start of pathname in name (past UNC header\volume header if present).  */
-int
+static int
 get_volume_info (const char * name, const char ** pPath)
 {
   char temp[MAX_PATH];
@@ -2210,7 +2202,7 @@ get_volume_info (const char * name, const char ** pPath)
 
 /* Determine if volume is FAT format (ie. only supports short 8.3
    names); also set path pointer to start of pathname in name.  */
-int
+static int
 is_fat_volume (const char * name, const char ** pPath)
 {
   if (get_volume_info (name, pPath))
@@ -2348,9 +2340,9 @@ static WIN32_FIND_DATA dir_find_data;
 /* Support shares on a network resource as subdirectories of a read-only
    root directory. */
 static HANDLE wnet_enum_handle = INVALID_HANDLE_VALUE;
-HANDLE open_unc_volume (const char *);
-char  *read_unc_volume (HANDLE, char *, int);
-void   close_unc_volume (HANDLE);
+static HANDLE open_unc_volume (const char *);
+static char  *read_unc_volume (HANDLE, char *, int);
+static void   close_unc_volume (HANDLE);
 
 DIR *
 opendir (char *filename)
@@ -2411,8 +2403,8 @@ readdir (DIR *dirp)
   if (wnet_enum_handle != INVALID_HANDLE_VALUE)
     {
       if (!read_unc_volume (wnet_enum_handle,
-                             dir_find_data.cFileName,
-                             MAX_PATH))
+                            dir_find_data.cFileName,
+                            MAX_PATH))
        return NULL;
     }
   /* If we aren't dir_finding, do a find-first, otherwise do a find-next. */
@@ -2486,7 +2478,7 @@ readdir (DIR *dirp)
   return &dir_static;
 }
 
-HANDLE
+static HANDLE
 open_unc_volume (const char *path)
 {
   NETRESOURCE nr;
@@ -2511,7 +2503,7 @@ open_unc_volume (const char *path)
     return INVALID_HANDLE_VALUE;
 }
 
-char *
+static char *
 read_unc_volume (HANDLE henum, char *readbuf, int size)
 {
   DWORD count;
@@ -2522,7 +2514,7 @@ read_unc_volume (HANDLE henum, char *readbuf, int size)
 
   count = 1;
   buffer = alloca (bufsize);
-  result = WNetEnumResource (wnet_enum_handle, &count, buffer, &bufsize);
+  result = WNetEnumResource (henum, &count, buffer, &bufsize);
   if (result != NO_ERROR)
     return NULL;
 
@@ -2536,14 +2528,14 @@ read_unc_volume (HANDLE henum, char *readbuf, int size)
   return readbuf;
 }
 
-void
+static void
 close_unc_volume (HANDLE henum)
 {
   if (henum != INVALID_HANDLE_VALUE)
     WNetCloseEnum (henum);
 }
 
-DWORD
+static DWORD
 unc_volume_file_attributes (const char *path)
 {
   HANDLE henum;
@@ -2992,7 +2984,7 @@ convert_time (FILETIME ft)
 
   if (!init)
     {
-      initialize_utc_base();
+      initialize_utc_base ();
       init = 1;
     }
 
@@ -3003,8 +2995,7 @@ convert_time (FILETIME ft)
   return (time_t) ((tmp - utc_base) / 10000000L);
 }
 
-
-void
+static void
 convert_from_time_t (time_t time, FILETIME * pft)
 {
   ULARGE_INTEGER tmp;
@@ -3225,10 +3216,9 @@ get_name_and_id (PSECURITY_DESCRIPTOR psd, const char *fname,
 }
 
 static void
-get_file_owner_and_group (
-    PSECURITY_DESCRIPTOR psd,
-    const char *fname,
-    struct stat *st)
+get_file_owner_and_group (PSECURITY_DESCRIPTOR psd,
+                         const char *fname,
+                         struct stat *st)
 {
   int dflt_usr = 0, dflt_grp = 0;
 
@@ -3287,8 +3277,6 @@ int
 stat (const char * path, struct stat * buf)
 {
   char *name, *r;
-  char drive_root[4];
-  UINT devtype;
   WIN32_FIND_DATA wfd;
   HANDLE fh;
   unsigned __int64 fake_inode;
@@ -3481,7 +3469,6 @@ stat (const char * path, struct stat * buf)
   buf->st_dev = volume_info.serialnum;
   buf->st_rdev = volume_info.serialnum;
 
-
   buf->st_size = wfd.nFileSizeHigh;
   buf->st_size <<= 32;
   buf->st_size += wfd.nFileSizeLow;
@@ -3649,14 +3636,50 @@ utime (const char *name, struct utimbuf *times)
 }
 
 \f
+/* Symlink-related functions that always fail.  Used in fileio.c and in
+   sysdep.c to avoid #ifdef's.  */
+int
+symlink (char const *dummy1, char const *dummy2)
+{
+  errno = ENOSYS;
+  return -1;
+}
+
+ssize_t
+readlink (const char *name, char *dummy1, size_t dummy2)
+{
+  /* `access' is much faster than `stat' on MS-Windows.  */
+  if (sys_access (name, 0) == 0)
+    errno = EINVAL;
+  return -1;
+}
+
+char *
+careadlinkat (int fd, char const *filename,
+              char *buffer, size_t buffer_size,
+              struct allocator const *alloc,
+              ssize_t (*preadlinkat) (int, char const *, char *, size_t))
+{
+  errno = ENOSYS;
+  return NULL;
+}
+
+ssize_t
+careadlinkatcwd (int fd, char const *filename, char *buffer,
+                 size_t buffer_size)
+{
+  (void) fd;
+  return readlink (filename, buffer, buffer_size);
+}
+
+\f
 /* Support for browsing other processes and their attributes.  See
    process.c for the Lisp bindings.  */
 
 /* Helper wrapper functions.  */
 
-HANDLE WINAPI create_toolhelp32_snapshot (
-    DWORD Flags,
-    DWORD Ignored)
+static HANDLE WINAPI
+create_toolhelp32_snapshot (DWORD Flags, DWORD Ignored)
 {
   static CreateToolhelp32Snapshot_Proc s_pfn_Create_Toolhelp32_Snapshot = NULL;
 
@@ -3674,9 +3697,8 @@ HANDLE WINAPI create_toolhelp32_snapshot (
   return (s_pfn_Create_Toolhelp32_Snapshot (Flags, Ignored));
 }
 
-BOOL WINAPI process32_first (
-    HANDLE hSnapshot,
-    LPPROCESSENTRY32 lppe)
+static BOOL WINAPI
+process32_first (HANDLE hSnapshot, LPPROCESSENTRY32 lppe)
 {
   static Process32First_Proc s_pfn_Process32_First = NULL;
 
@@ -3694,9 +3716,8 @@ BOOL WINAPI process32_first (
   return (s_pfn_Process32_First (hSnapshot, lppe));
 }
 
-BOOL WINAPI process32_next (
-    HANDLE hSnapshot,
-    LPPROCESSENTRY32 lppe)
+static BOOL WINAPI
+process32_next (HANDLE hSnapshot, LPPROCESSENTRY32 lppe)
 {
   static Process32Next_Proc s_pfn_Process32_Next = NULL;
 
@@ -3714,11 +3735,11 @@ BOOL WINAPI process32_next (
   return (s_pfn_Process32_Next (hSnapshot, lppe));
 }
 
-BOOL WINAPI open_thread_token (
-    HANDLE ThreadHandle,
-    DWORD DesiredAccess,
-    BOOL OpenAsSelf,
-    PHANDLE TokenHandle)
+static BOOL WINAPI
+open_thread_token (HANDLE ThreadHandle,
+                  DWORD DesiredAccess,
+                  BOOL OpenAsSelf,
+                  PHANDLE TokenHandle)
 {
   static OpenThreadToken_Proc s_pfn_Open_Thread_Token = NULL;
   HMODULE hm_advapi32 = NULL;
@@ -3748,8 +3769,8 @@ BOOL WINAPI open_thread_token (
       );
 }
 
-BOOL WINAPI impersonate_self (
-    SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
+static BOOL WINAPI
+impersonate_self (SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
 {
   static ImpersonateSelf_Proc s_pfn_Impersonate_Self = NULL;
   HMODULE hm_advapi32 = NULL;
@@ -3771,7 +3792,8 @@ BOOL WINAPI impersonate_self (
   return s_pfn_Impersonate_Self (ImpersonationLevel);
 }
 
-BOOL WINAPI revert_to_self (void)
+static BOOL WINAPI
+revert_to_self (void)
 {
   static RevertToSelf_Proc s_pfn_Revert_To_Self = NULL;
   HMODULE hm_advapi32 = NULL;
@@ -3793,10 +3815,10 @@ BOOL WINAPI revert_to_self (void)
   return s_pfn_Revert_To_Self ();
 }
 
-BOOL WINAPI get_process_memory_info (
-    HANDLE h_proc,
-    PPROCESS_MEMORY_COUNTERS mem_counters,
-    DWORD bufsize)
+static BOOL WINAPI
+get_process_memory_info (HANDLE h_proc,
+                        PPROCESS_MEMORY_COUNTERS mem_counters,
+                        DWORD bufsize)
 {
   static GetProcessMemoryInfo_Proc s_pfn_Get_Process_Memory_Info = NULL;
   HMODULE hm_psapi = NULL;
@@ -3819,10 +3841,10 @@ BOOL WINAPI get_process_memory_info (
   return s_pfn_Get_Process_Memory_Info (h_proc, mem_counters, bufsize);
 }
 
-BOOL WINAPI get_process_working_set_size (
-    HANDLE h_proc,
-    DWORD *minrss,
-    DWORD *maxrss)
+static BOOL WINAPI
+get_process_working_set_size (HANDLE h_proc,
+                             DWORD *minrss,
+                             DWORD *maxrss)
 {
   static GetProcessWorkingSetSize_Proc
     s_pfn_Get_Process_Working_Set_Size = NULL;
@@ -3845,8 +3867,8 @@ BOOL WINAPI get_process_working_set_size (
   return s_pfn_Get_Process_Working_Set_Size (h_proc, minrss, maxrss);
 }
 
-BOOL WINAPI global_memory_status (
-    MEMORYSTATUS *buf)
+static BOOL WINAPI
+global_memory_status (MEMORYSTATUS *buf)
 {
   static GlobalMemoryStatus_Proc s_pfn_Global_Memory_Status = NULL;
 
@@ -3868,8 +3890,8 @@ BOOL WINAPI global_memory_status (
   return s_pfn_Global_Memory_Status (buf);
 }
 
-BOOL WINAPI global_memory_status_ex (
-    MEMORY_STATUS_EX *buf)
+static BOOL WINAPI
+global_memory_status_ex (MEMORY_STATUS_EX *buf)
 {
   static GlobalMemoryStatusEx_Proc s_pfn_Global_Memory_Status_Ex = NULL;
 
@@ -4064,7 +4086,6 @@ system_process_attributes (Lisp_Object pid)
   TOKEN_PRIMARY_GROUP group_token;
   unsigned euid;
   unsigned egid;
-  DWORD sess;
   PROCESS_MEMORY_COUNTERS mem;
   PROCESS_MEMORY_COUNTERS_EX mem_ex;
   DWORD minrss, maxrss;
@@ -4348,8 +4369,6 @@ system_process_attributes (Lisp_Object pid)
 }
 
 \f
-#ifdef HAVE_SOCKETS
-
 /* Wrappers for  winsock functions to map between our file descriptors
    and winsock's handles; also set h_errno for convenience.
 
@@ -4429,7 +4448,6 @@ init_winsock (int load_now)
   if (winsock_lib != NULL)
     return TRUE;
 
-  pfn_SetHandleInformation = NULL;
   pfn_SetHandleInformation
     = (void *) GetProcAddress (GetModuleHandle ("kernel32.dll"),
                               "SetHandleInformation");
@@ -4544,75 +4562,75 @@ struct {
   int errnum;
   char * msg;
 } _wsa_errlist[] = {
-  WSAEINTR                , "Interrupted function call",
-  WSAEBADF                , "Bad file descriptor",
-  WSAEACCES               , "Permission denied",
-  WSAEFAULT               , "Bad address",
-  WSAEINVAL               , "Invalid argument",
-  WSAEMFILE               , "Too many open files",
-
-  WSAEWOULDBLOCK          , "Resource temporarily unavailable",
-  WSAEINPROGRESS          , "Operation now in progress",
-  WSAEALREADY             , "Operation already in progress",
-  WSAENOTSOCK             , "Socket operation on non-socket",
-  WSAEDESTADDRREQ         , "Destination address required",
-  WSAEMSGSIZE             , "Message too long",
-  WSAEPROTOTYPE           , "Protocol wrong type for socket",
-  WSAENOPROTOOPT          , "Bad protocol option",
-  WSAEPROTONOSUPPORT      , "Protocol not supported",
-  WSAESOCKTNOSUPPORT      , "Socket type not supported",
-  WSAEOPNOTSUPP           , "Operation not supported",
-  WSAEPFNOSUPPORT         , "Protocol family not supported",
-  WSAEAFNOSUPPORT         , "Address family not supported by protocol family",
-  WSAEADDRINUSE           , "Address already in use",
-  WSAEADDRNOTAVAIL        , "Cannot assign requested address",
-  WSAENETDOWN             , "Network is down",
-  WSAENETUNREACH          , "Network is unreachable",
-  WSAENETRESET            , "Network dropped connection on reset",
-  WSAECONNABORTED         , "Software caused connection abort",
-  WSAECONNRESET           , "Connection reset by peer",
-  WSAENOBUFS              , "No buffer space available",
-  WSAEISCONN              , "Socket is already connected",
-  WSAENOTCONN             , "Socket is not connected",
-  WSAESHUTDOWN            , "Cannot send after socket shutdown",
-  WSAETOOMANYREFS         , "Too many references",         /* not sure */
-  WSAETIMEDOUT            , "Connection timed out",
-  WSAECONNREFUSED         , "Connection refused",
-  WSAELOOP                , "Network loop",                /* not sure */
-  WSAENAMETOOLONG         , "Name is too long",
-  WSAEHOSTDOWN            , "Host is down",
-  WSAEHOSTUNREACH         , "No route to host",
-  WSAENOTEMPTY            , "Buffer not empty",                    /* not sure */
-  WSAEPROCLIM             , "Too many processes",
-  WSAEUSERS               , "Too many users",              /* not sure */
-  WSAEDQUOT               , "Double quote in host name",    /* really not sure */
-  WSAESTALE               , "Data is stale",               /* not sure */
-  WSAEREMOTE              , "Remote error",                /* not sure */
-
-  WSASYSNOTREADY          , "Network subsystem is unavailable",
-  WSAVERNOTSUPPORTED      , "WINSOCK.DLL version out of range",
-  WSANOTINITIALISED       , "Winsock not initialized successfully",
-  WSAEDISCON              , "Graceful shutdown in progress",
+  {WSAEINTR                , "Interrupted function call"},
+  {WSAEBADF                , "Bad file descriptor"},
+  {WSAEACCES               , "Permission denied"},
+  {WSAEFAULT               , "Bad address"},
+  {WSAEINVAL               , "Invalid argument"},
+  {WSAEMFILE               , "Too many open files"},
+
+  {WSAEWOULDBLOCK          , "Resource temporarily unavailable"},
+  {WSAEINPROGRESS          , "Operation now in progress"},
+  {WSAEALREADY             , "Operation already in progress"},
+  {WSAENOTSOCK             , "Socket operation on non-socket"},
+  {WSAEDESTADDRREQ         , "Destination address required"},
+  {WSAEMSGSIZE             , "Message too long"},
+  {WSAEPROTOTYPE           , "Protocol wrong type for socket"},
+  {WSAENOPROTOOPT          , "Bad protocol option"},
+  {WSAEPROTONOSUPPORT      , "Protocol not supported"},
+  {WSAESOCKTNOSUPPORT      , "Socket type not supported"},
+  {WSAEOPNOTSUPP           , "Operation not supported"},
+  {WSAEPFNOSUPPORT         , "Protocol family not supported"},
+  {WSAEAFNOSUPPORT         , "Address family not supported by protocol family"},
+  {WSAEADDRINUSE           , "Address already in use"},
+  {WSAEADDRNOTAVAIL        , "Cannot assign requested address"},
+  {WSAENETDOWN             , "Network is down"},
+  {WSAENETUNREACH          , "Network is unreachable"},
+  {WSAENETRESET            , "Network dropped connection on reset"},
+  {WSAECONNABORTED         , "Software caused connection abort"},
+  {WSAECONNRESET           , "Connection reset by peer"},
+  {WSAENOBUFS              , "No buffer space available"},
+  {WSAEISCONN              , "Socket is already connected"},
+  {WSAENOTCONN             , "Socket is not connected"},
+  {WSAESHUTDOWN            , "Cannot send after socket shutdown"},
+  {WSAETOOMANYREFS         , "Too many references"},       /* not sure */
+  {WSAETIMEDOUT            , "Connection timed out"},
+  {WSAECONNREFUSED         , "Connection refused"},
+  {WSAELOOP                , "Network loop"},              /* not sure */
+  {WSAENAMETOOLONG         , "Name is too long"},
+  {WSAEHOSTDOWN            , "Host is down"},
+  {WSAEHOSTUNREACH         , "No route to host"},
+  {WSAENOTEMPTY            , "Buffer not empty"},          /* not sure */
+  {WSAEPROCLIM             , "Too many processes"},
+  {WSAEUSERS               , "Too many users"},                    /* not sure */
+  {WSAEDQUOT               , "Double quote in host name"},  /* really not sure */
+  {WSAESTALE               , "Data is stale"},             /* not sure */
+  {WSAEREMOTE              , "Remote error"},              /* not sure */
+
+  {WSASYSNOTREADY          , "Network subsystem is unavailable"},
+  {WSAVERNOTSUPPORTED      , "WINSOCK.DLL version out of range"},
+  {WSANOTINITIALISED       , "Winsock not initialized successfully"},
+  {WSAEDISCON              , "Graceful shutdown in progress"},
 #ifdef WSAENOMORE
-  WSAENOMORE              , "No more operations allowed",   /* not sure */
-  WSAECANCELLED           , "Operation cancelled",         /* not sure */
-  WSAEINVALIDPROCTABLE    , "Invalid procedure table from service provider",
-  WSAEINVALIDPROVIDER     , "Invalid service provider version number",
-  WSAEPROVIDERFAILEDINIT  , "Unable to initialize a service provider",
-  WSASYSCALLFAILURE       , "System call failure",
-  WSASERVICE_NOT_FOUND    , "Service not found",           /* not sure */
-  WSATYPE_NOT_FOUND       , "Class type not found",
-  WSA_E_NO_MORE           , "No more resources available",  /* really not sure */
-  WSA_E_CANCELLED         , "Operation already cancelled",  /* really not sure */
-  WSAEREFUSED             , "Operation refused",           /* not sure */
+  {WSAENOMORE              , "No more operations allowed"}, /* not sure */
+  {WSAECANCELLED           , "Operation cancelled"},       /* not sure */
+  {WSAEINVALIDPROCTABLE    , "Invalid procedure table from service provider"},
+  {WSAEINVALIDPROVIDER     , "Invalid service provider version number"},
+  {WSAEPROVIDERFAILEDINIT  , "Unable to initialize a service provider"},
+  {WSASYSCALLFAILURE       , "System call failure"},
+  {WSASERVICE_NOT_FOUND    , "Service not found"},         /* not sure */
+  {WSATYPE_NOT_FOUND       , "Class type not found"},
+  {WSA_E_NO_MORE           , "No more resources available"}, /* really not sure */
+  {WSA_E_CANCELLED         , "Operation already cancelled"}, /* really not sure */
+  {WSAEREFUSED             , "Operation refused"},         /* not sure */
 #endif
 
-  WSAHOST_NOT_FOUND       , "Host not found",
-  WSATRY_AGAIN            , "Authoritative host not found during name lookup",
-  WSANO_RECOVERY          , "Non-recoverable error during name lookup",
-  WSANO_DATA              , "Valid name, no data record of requested type",
+  {WSAHOST_NOT_FOUND       , "Host not found"},
+  {WSATRY_AGAIN            , "Authoritative host not found during name lookup"},
+  {WSANO_RECOVERY          , "Non-recoverable error during name lookup"},
+  {WSANO_DATA              , "Valid name, no data record of requested type"},
 
-  -1, NULL
+  {-1, NULL}
 };
 
 char *
@@ -4636,15 +4654,9 @@ sys_strerror (int error_no)
    but I believe the method of keeping the socket handle separate (and
    insuring it is not inheritable) is the correct one. */
 
-//#define SOCK_REPLACE_HANDLE
-
-#ifdef SOCK_REPLACE_HANDLE
-#define SOCK_HANDLE(fd) ((SOCKET) _get_osfhandle (fd))
-#else
 #define SOCK_HANDLE(fd) ((SOCKET) fd_info[fd].hnd)
-#endif
 
-int socket_to_fd (SOCKET s);
+static int socket_to_fd (SOCKET s);
 
 int
 sys_socket (int af, int type, int protocol)
@@ -4670,7 +4682,7 @@ sys_socket (int af, int type, int protocol)
 }
 
 /* Convert a SOCKET to a file descriptor.  */
-int
+static int
 socket_to_fd (SOCKET s)
 {
   int fd;
@@ -4686,13 +4698,6 @@ socket_to_fd (SOCKET s)
   fd = _open ("NUL:", _O_RDWR);
   if (fd >= 0)
     {
-#ifdef SOCK_REPLACE_HANDLE
-      /* now replace handle to NUL with our socket handle */
-      CloseHandle ((HANDLE) _get_osfhandle (fd));
-      _free_osfhnd (fd);
-      _set_osfhnd (fd, s);
-      /* setmode (fd, _O_BINARY); */
-#else
       /* Make a non-inheritable copy of the socket handle.  Note
         that it is possible that sockets aren't actually kernel
         handles, which appears to be the case on Windows 9x when
@@ -4738,7 +4743,6 @@ socket_to_fd (SOCKET s)
          }
       }
       fd_info[fd].hnd = (HANDLE) s;
-#endif
 
       /* set our own internal flags */
       fd_info[fd].flags = FILE_SOCKET | FILE_BINARY | FILE_READ | FILE_WRITE;
@@ -4771,7 +4775,6 @@ socket_to_fd (SOCKET s)
   return -1;
 }
 
-
 int
 sys_bind (int s, const struct sockaddr * addr, int namelen)
 {
@@ -4793,7 +4796,6 @@ sys_bind (int s, const struct sockaddr * addr, int namelen)
   return SOCKET_ERROR;
 }
 
-
 int
 sys_connect (int s, const struct sockaddr * name, int namelen)
 {
@@ -4906,7 +4908,6 @@ sys_getpeername (int s, struct sockaddr *addr, int * namelen)
   return SOCKET_ERROR;
 }
 
-
 int
 sys_shutdown (int s, int how)
 {
@@ -5084,7 +5085,7 @@ fcntl (int s, int cmd, int options)
          unsigned long nblock = 1;
          int rc = pfn_ioctlsocket (SOCK_HANDLE (s), FIONBIO, &nblock);
          if (rc == SOCKET_ERROR)
-           set_errno();
+           set_errno ();
          /* Keep track of the fact that we set this to non-blocking.  */
          fd_info[s].flags |= FILE_NDELAY;
          return rc;
@@ -5099,8 +5100,6 @@ fcntl (int s, int cmd, int options)
   return SOCKET_ERROR;
 }
 
-#endif /* HAVE_SOCKETS */
-
 
 /* Shadow main io functions: we need to handle pipes and sockets more
    intelligently, and implement non-blocking mode as well. */
@@ -5135,18 +5134,15 @@ sys_close (int fd)
            }
          if (i == MAXDESC)
            {
-#ifdef HAVE_SOCKETS
              if (fd_info[fd].flags & FILE_SOCKET)
                {
-#ifndef SOCK_REPLACE_HANDLE
                  if (winsock_lib == NULL) abort ();
 
                  pfn_shutdown (SOCK_HANDLE (fd), 2);
                  rc = pfn_closesocket (SOCK_HANDLE (fd));
-#endif
+
                  winsock_inuse--; /* count open sockets */
                }
-#endif
              delete_child (cp);
            }
        }
@@ -5178,7 +5174,6 @@ sys_dup (int fd)
   return new_fd;
 }
 
-
 int
 sys_dup2 (int src, int dst)
 {
@@ -5239,9 +5234,6 @@ sys_pipe (int * phandles)
   return rc;
 }
 
-/* From ntproc.c */
-extern int w32_pipe_read_delay;
-
 /* Function to do blocking read of one byte, needed to implement
    select.  It is only allowed on sockets and pipes. */
 int
@@ -5314,7 +5306,6 @@ _sys_read_ahead (int fd)
            return STATUS_READ_ERROR;
        }
     }
-#ifdef HAVE_SOCKETS
   else if (fd_info[fd].flags & FILE_SOCKET)
     {
       unsigned long nblock = 0;
@@ -5330,7 +5321,6 @@ _sys_read_ahead (int fd)
          pfn_ioctlsocket (SOCK_HANDLE (fd), FIONBIO, &nblock);
        }
     }
-#endif
 
   if (rc == sizeof (char))
     cp->status = STATUS_READ_SUCCEEDED;
@@ -5460,7 +5450,6 @@ sys_read (int fd, char * buffer, unsigned int count)
            {
              HANDLE hnd = fd_info[fd].hnd;
              OVERLAPPED *ovl = &fd_info[fd].cp->ovl_read;
-             DWORD err = 0;
              int rc = 0;
              COMMTIMEOUTS ct;
 
@@ -5502,7 +5491,6 @@ sys_read (int fd, char * buffer, unsigned int count)
                  nchars += rc;
                }
            }
-#ifdef HAVE_SOCKETS
          else /* FILE_SOCKET */
            {
              if (winsock_lib == NULL) abort ();
@@ -5529,7 +5517,6 @@ sys_read (int fd, char * buffer, unsigned int count)
                  nchars += res;
                }
            }
-#endif
        }
       else
        {
@@ -5654,9 +5641,7 @@ sys_write (int fd, const void * buffer, unsigned int count)
            }
        }
     }
-  else
-#ifdef HAVE_SOCKETS
-  if (fd < MAXDESC && fd_info[fd].flags & FILE_SOCKET)
+  else if (fd < MAXDESC && fd_info[fd].flags & FILE_SOCKET)
     {
       unsigned long nblock = 0;
       if (winsock_lib == NULL) abort ();
@@ -5684,7 +5669,6 @@ sys_write (int fd, const void * buffer, unsigned int count)
        }
     }
   else
-#endif
     {
       /* Some networked filesystems don't like too large writes, so
         break them into smaller chunks.  See the Comments section of
@@ -5717,18 +5701,76 @@ sys_write (int fd, const void * buffer, unsigned int count)
   return nchars;
 }
 
+/* The Windows CRT functions are "optimized for speed", so they don't
+   check for timezone and DST changes if they were last called less
+   than 1 minute ago (see http://support.microsoft.com/kb/821231).  So
+   all Emacs features that repeatedly call time functions (e.g.,
+   display-time) are in real danger of missing timezone and DST
+   changes.  Calling tzset before each localtime call fixes that.  */
+struct tm *
+sys_localtime (const time_t *t)
+{
+  tzset ();
+  return localtime (t);
+}
+
+
+\f
+/* Delayed loading of libraries.  */
+
+Lisp_Object Vlibrary_cache;
+
+/* The argument LIBRARIES is an alist that associates a symbol
+   LIBRARY_ID, identifying an external DLL library known to Emacs, to
+   a list of filenames under which the library is usually found.  In
+   most cases, the argument passed as LIBRARIES is the variable
+   `dynamic-library-alist', which is initialized to a list of common
+   library names.  If the function loads the library successfully, it
+   returns the handle of the DLL, and records the filename in the
+   property :loaded-from of LIBRARY_ID; it returns NULL if the library
+   could not be found, or when it was already loaded (because the
+   handle is not recorded anywhere, and so is lost after use).  It
+   would be trivial to save the handle too in :loaded-from, but
+   currently there's no use case for it.  */
+HMODULE
+w32_delayed_load (Lisp_Object libraries, Lisp_Object library_id)
+{
+  HMODULE library_dll = NULL;
+
+  CHECK_SYMBOL (library_id);
+
+  if (CONSP (libraries) && NILP (Fassq (library_id, Vlibrary_cache)))
+    {
+      Lisp_Object found = Qnil;
+      Lisp_Object dlls = Fassq (library_id, libraries);
+
+      if (CONSP (dlls))
+        for (dlls = XCDR (dlls); CONSP (dlls); dlls = XCDR (dlls))
+          {
+            CHECK_STRING_CAR (dlls);
+            if (library_dll = LoadLibrary (SDATA (XCAR (dlls))))
+              {
+                found = XCAR (dlls);
+                break;
+              }
+          }
+
+      Fput (library_id, QCloaded_from, found);
+    }
+
+  return library_dll;
+}
+
+\f
 static void
 check_windows_init_file (void)
 {
-  extern int noninteractive, inhibit_window_system;
-
   /* A common indication that Emacs is not installed properly is when
      it cannot find the Windows installation file.  If this file does
      not exist in the expected place, tell the user.  */
 
   if (!noninteractive && !inhibit_window_system)
     {
-      extern Lisp_Object Vwindow_system, Vload_path, Qfile_exists_p;
       Lisp_Object objs[2];
       Lisp_Object full_load_path;
       Lisp_Object init_file;
@@ -5776,10 +5818,8 @@ check_windows_init_file (void)
 void
 term_ntproc (void)
 {
-#ifdef HAVE_SOCKETS
   /* shutdown the socket interface if necessary */
   term_winsock ();
-#endif
 
   term_w32select ();
 }
@@ -5787,7 +5827,6 @@ term_ntproc (void)
 void
 init_ntproc (void)
 {
-#ifdef HAVE_SOCKETS
   /* Initialise the socket interface now if available and requested by
      the user by defining PRELOAD_WINSOCK; otherwise loading will be
      delayed until open-network-stream is called (w32-has-winsock can
@@ -5801,7 +5840,6 @@ init_ntproc (void)
 
   if (getenv ("PRELOAD_WINSOCK") != NULL)
     init_winsock (TRUE);
-#endif
 
   /* Initial preparation for subprocess support: replace our standard
      handles with non-inheritable versions. */
@@ -5893,7 +5931,7 @@ init_ntproc (void)
         shutdown_handler ensures that buffers' autosave files are
        up to date when the user logs off, or the system shuts down.
 */
-BOOL WINAPI
+static BOOL WINAPI
 shutdown_handler (DWORD type)
 {
   /* Ctrl-C and Ctrl-Break are already suppressed, so don't handle them.  */
@@ -5922,11 +5960,16 @@ globals_of_w32 (void)
   get_process_times_fn = (GetProcessTimes_Proc)
     GetProcAddress (kernel32, "GetProcessTimes");
 
+  QCloaded_from = intern_c_string (":loaded-from");
+  staticpro (&QCloaded_from);
+
+  Vlibrary_cache = Qnil;
+  staticpro (&Vlibrary_cache);
+
   g_b_init_is_windows_9x = 0;
   g_b_init_open_process_token = 0;
   g_b_init_get_token_information = 0;
   g_b_init_lookup_account_sid = 0;
-  g_b_init_get_sid_identifier_authority = 0;
   g_b_init_get_sid_sub_authority = 0;
   g_b_init_get_sid_sub_authority_count = 0;
   g_b_init_get_file_security = 0;
@@ -6000,8 +6043,7 @@ serial_open (char *port)
 
 /* For serial-process-configure  */
 void
-serial_configure (struct Lisp_Process *p,
-                 Lisp_Object contact)
+serial_configure (struct Lisp_Process *p, Lisp_Object contact)
 {
   Lisp_Object childp2 = Qnil;
   Lisp_Object tem = Qnil;
@@ -6150,7 +6192,72 @@ serial_configure (struct Lisp_Process *p,
   p->childp = childp2;
 }
 
-/* end of w32.c */
+#ifdef HAVE_GNUTLS
+
+ssize_t
+emacs_gnutls_pull (gnutls_transport_ptr_t p, void* buf, size_t sz)
+{
+  int n, sc, err;
+  SELECT_TYPE fdset;
+  EMACS_TIME timeout;
+  struct Lisp_Process *process = (struct Lisp_Process *)p;
+  int fd = process->infd;
+
+  for (;;)
+    {
+      n = sys_read(fd, (char*)buf, sz);
+
+      if (n >= 0)
+        return n;
+
+      err = errno;
+
+      if (err == EWOULDBLOCK)
+        {
+          /* Set a small timeout.  */
+          EMACS_SET_SECS_USECS(timeout, 1, 0);
+          FD_ZERO (&fdset);
+          FD_SET ((int)fd, &fdset);
+
+          /* Use select with the timeout to poll the selector.  */
+          sc = select (fd + 1, &fdset, (SELECT_TYPE *)0, (SELECT_TYPE *)0,
+                       &timeout);
+
+          if (sc > 0)
+            continue;  /* Try again.  */
+
+          /* Translate the WSAEWOULDBLOCK alias EWOULDBLOCK to EAGAIN.
+             Also accept select return 0 as an indicator to EAGAIN.  */
+          if (sc == 0 || errno == EWOULDBLOCK)
+            err = EAGAIN;
+          else
+            err = errno; /* Other errors are just passed on.  */
+        }
+
+      emacs_gnutls_transport_set_errno (process->gnutls_state, err);
 
-/* arch-tag: 90442dd3-37be-482b-b272-ac752e3049f1
-   (do not change this comment) */
+      return -1;
+    }
+}
+
+ssize_t
+emacs_gnutls_push (gnutls_transport_ptr_t p, const void* buf, size_t sz)
+{
+  struct Lisp_Process *process = (struct Lisp_Process *)p;
+  int fd = process->outfd;
+  ssize_t n = sys_write(fd, buf, sz);
+
+  /* 0 or more bytes written means everything went fine.  */
+  if (n >= 0)
+    return n;
+
+  /* Negative bytes written means we got an error in errno.
+     Translate the WSAEWOULDBLOCK alias EWOULDBLOCK to EAGAIN.  */
+  emacs_gnutls_transport_set_errno (process->gnutls_state,
+                                    errno == EWOULDBLOCK ? EAGAIN : errno);
+
+  return -1;
+}
+#endif /* HAVE_GNUTLS */
+
+/* end of w32.c */