]> code.delx.au - gnu-emacs/blobdiff - src/w32.c
Merge from emacs-24; up to 2012-12-06T01:39:03Z!monnier@iro.umontreal.ca
[gnu-emacs] / src / w32.c
index f7e16354791708c34779b15b1f32f9ecc67cb867..55581a17de5e07f6527154e4a455a19697385dcd 100644 (file)
--- a/src/w32.c
+++ b/src/w32.c
@@ -1,5 +1,5 @@
 /* Utility and Unix shadow routines for GNU Emacs on the Microsoft Windows API.
-   Copyright (C) 1994-1995, 2000-201 Free Software Foundation, Inc.
+   Copyright (C) 1994-1995, 2000-2013 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -31,13 +31,13 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <sys/file.h>
 #include <sys/time.h>
 #include <sys/utime.h>
-#include <mbstring.h>  /* for _mbspbrk */
 #include <math.h>
 #include <time.h>
 
 /* must include CRT headers *before* config.h */
 
 #include <config.h>
+#include <mbstring.h>  /* for _mbspbrk */
 
 #undef access
 #undef chdir
@@ -101,27 +101,37 @@ typedef struct _MEMORY_STATUS_EX {
    _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;
+  SIZE_T PeakWorkingSetSize;
+  SIZE_T WorkingSetSize;
+  SIZE_T QuotaPeakPagedPoolUsage;
+  SIZE_T QuotaPagedPoolUsage;
+  SIZE_T QuotaPeakNonPagedPoolUsage;
+  SIZE_T QuotaNonPagedPoolUsage;
+  SIZE_T PagefileUsage;
+  SIZE_T PeakPagefileUsage;
+  SIZE_T PrivateUsage;
 } PROCESS_MEMORY_COUNTERS_EX,*PPROCESS_MEMORY_COUNTERS_EX;
 #endif
 
 #include <winioctl.h>
 #include <aclapi.h>
+#include <sddl.h>
+
+#include <sys/acl.h>
+
+/* This is not in MinGW's sddl.h (but they are in MSVC headers), so we
+   define them by hand if not already defined.  */
+#ifndef SDDL_REVISION_1
+#define SDDL_REVISION_1        1
+#endif /* SDDL_REVISION_1 */
 
 #ifdef _MSC_VER
-/* MSVC doesn't provide the definition of REPARSE_DATA_BUFFER, except
-   on ntifs.h, which cannot be included because it triggers conflicts
-   with other Windows API headers.  So we define it here by hand.  */
+/* MSVC doesn't provide the definition of REPARSE_DATA_BUFFER and the
+   associated macros, except on ntifs.h, which cannot be included
+   because it triggers conflicts with other Windows API headers.  So
+   we define it here by hand.  */
 
 typedef struct _REPARSE_DATA_BUFFER {
     ULONG  ReparseTag;
@@ -149,6 +159,20 @@ typedef struct _REPARSE_DATA_BUFFER {
     } DUMMYUNIONNAME;
 } REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
 
+#ifndef FILE_DEVICE_FILE_SYSTEM
+#define FILE_DEVICE_FILE_SYSTEM        9
+#endif
+#ifndef METHOD_BUFFERED
+#define METHOD_BUFFERED                0
+#endif
+#ifndef FILE_ANY_ACCESS
+#define FILE_ANY_ACCESS                0x00000000
+#endif
+#ifndef CTL_CODE
+#define CTL_CODE(t,f,m,a)       (((t)<<16)|((a)<<14)|((f)<<2)|(m))
+#endif
+#define FSCTL_GET_REPARSE_POINT \
+  CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS)
 #endif
 
 /* TCP connection support.  */
@@ -172,8 +196,10 @@ typedef struct _REPARSE_DATA_BUFFER {
 #undef sendto
 
 #include "w32.h"
-#include "ndir.h"
+#include <dirent.h>
+#include "w32common.h"
 #include "w32heap.h"
+#include "w32select.h"
 #include "systime.h"
 #include "dispextern.h"                /* for xstrcasecmp */
 #include "coding.h"            /* for Vlocale_coding_system */
@@ -197,6 +223,12 @@ static int enable_privilege (LPCTSTR, BOOL, TOKEN_PRIVILEGES *);
 static int restore_privilege (TOKEN_PRIVILEGES *);
 static BOOL WINAPI revert_to_self (void);
 
+extern int sys_access (const char *, int);
+extern void *e_malloc (size_t);
+extern int sys_select (int, SELECT_TYPE *, SELECT_TYPE *, SELECT_TYPE *,
+                      EMACS_TIME *, void *);
+
+
 \f
 /* Initialization states.
 
@@ -234,6 +266,11 @@ static BOOL g_b_init_copy_sid;
 static BOOL g_b_init_get_native_system_info;
 static BOOL g_b_init_get_system_times;
 static BOOL g_b_init_create_symbolic_link;
+static BOOL g_b_init_get_security_descriptor_dacl;
+static BOOL g_b_init_convert_sd_to_sddl;
+static BOOL g_b_init_convert_sddl_to_sd;
+static BOOL g_b_init_is_valid_security_descriptor;
+static BOOL g_b_init_set_file_security;
 
 /*
   BEGIN: Wrapper functions around OpenProcessToken
@@ -263,9 +300,11 @@ GetProcessTimes_Proc get_process_times_fn = NULL;
 #ifdef _UNICODE
 const char * const LookupAccountSid_Name = "LookupAccountSidW";
 const char * const GetFileSecurity_Name =  "GetFileSecurityW";
+const char * const SetFileSecurity_Name =  "SetFileSecurityW";
 #else
 const char * const LookupAccountSid_Name = "LookupAccountSidA";
 const char * const GetFileSecurity_Name =  "GetFileSecurityA";
+const char * const SetFileSecurity_Name =  "SetFileSecurityA";
 #endif
 typedef BOOL (WINAPI * LookupAccountSid_Proc) (
     LPCTSTR lpSystemName,
@@ -295,6 +334,10 @@ typedef BOOL (WINAPI * GetFileSecurity_Proc) (
     PSECURITY_DESCRIPTOR pSecurityDescriptor,
     DWORD nLength,
     LPDWORD lpnLengthNeeded);
+typedef BOOL (WINAPI *SetFileSecurity_Proc) (
+    LPCTSTR lpFileName,
+    SECURITY_INFORMATION SecurityInformation,
+    PSECURITY_DESCRIPTOR pSecurityDescriptor);
 typedef BOOL (WINAPI * GetSecurityDescriptorOwner_Proc) (
     PSECURITY_DESCRIPTOR pSecurityDescriptor,
     PSID *pOwner,
@@ -303,6 +346,11 @@ typedef BOOL (WINAPI * GetSecurityDescriptorGroup_Proc) (
     PSECURITY_DESCRIPTOR pSecurityDescriptor,
     PSID *pGroup,
     LPBOOL lpbGroupDefaulted);
+typedef BOOL (WINAPI *GetSecurityDescriptorDacl_Proc) (
+    PSECURITY_DESCRIPTOR pSecurityDescriptor,
+    LPBOOL lpbDaclPresent,
+    PACL *pDacl,
+    LPBOOL lpbDaclDefaulted);
 typedef BOOL (WINAPI * IsValidSid_Proc) (
     PSID sid);
 typedef HANDLE (WINAPI * CreateToolhelp32Snapshot_Proc) (
@@ -328,8 +376,8 @@ typedef BOOL (WINAPI * GetProcessMemoryInfo_Proc) (
     DWORD cb);
 typedef BOOL (WINAPI * GetProcessWorkingSetSize_Proc) (
     HANDLE hProcess,
-    DWORD * lpMinimumWorkingSetSize,
-    DWORD * lpMaximumWorkingSetSize);
+    PSIZE_T lpMinimumWorkingSetSize,
+    PSIZE_T lpMaximumWorkingSetSize);
 typedef BOOL (WINAPI * GlobalMemoryStatus_Proc) (
     LPMEMORYSTATUS lpBuffer);
 typedef BOOL (WINAPI * GlobalMemoryStatusEx_Proc) (
@@ -353,6 +401,18 @@ typedef BOOLEAN (WINAPI *CreateSymbolicLink_Proc) (
     LPTSTR lpSymlinkFileName,
     LPTSTR lpTargetFileName,
     DWORD  dwFlags);
+typedef BOOL (WINAPI *ConvertStringSecurityDescriptorToSecurityDescriptor_Proc) (
+    LPCTSTR StringSecurityDescriptor,
+    DWORD StringSDRevision,
+    PSECURITY_DESCRIPTOR  *SecurityDescriptor,
+    PULONG  SecurityDescriptorSize);
+typedef BOOL (WINAPI *ConvertSecurityDescriptorToStringSecurityDescriptor_Proc) (
+    PSECURITY_DESCRIPTOR  SecurityDescriptor,
+    DWORD RequestedStringSDRevision,
+    SECURITY_INFORMATION SecurityInformation,
+    LPTSTR  *StringSecurityDescriptor,
+    PULONG StringSecurityDescriptorLen);
+typedef BOOL (WINAPI *IsValidSecurityDescriptor_Proc) (PSECURITY_DESCRIPTOR);
 
   /* ** A utility function ** */
 static BOOL
@@ -598,6 +658,7 @@ get_file_security (LPCTSTR lpFileName,
   HMODULE hm_advapi32 = NULL;
   if (is_windows_9x () == TRUE)
     {
+      errno = ENOTSUP;
       return FALSE;
     }
   if (g_b_init_get_file_security == 0)
@@ -610,6 +671,7 @@ get_file_security (LPCTSTR lpFileName,
     }
   if (s_pfn_Get_File_Security == NULL)
     {
+      errno = ENOTSUP;
       return FALSE;
     }
   return (s_pfn_Get_File_Security (lpFileName, RequestedInformation,
@@ -617,6 +679,35 @@ get_file_security (LPCTSTR lpFileName,
                                   lpnLengthNeeded));
 }
 
+static BOOL WINAPI
+set_file_security (LPCTSTR lpFileName,
+                  SECURITY_INFORMATION SecurityInformation,
+                  PSECURITY_DESCRIPTOR pSecurityDescriptor)
+{
+  static SetFileSecurity_Proc s_pfn_Set_File_Security = NULL;
+  HMODULE hm_advapi32 = NULL;
+  if (is_windows_9x () == TRUE)
+    {
+      errno = ENOTSUP;
+      return FALSE;
+    }
+  if (g_b_init_set_file_security == 0)
+    {
+      g_b_init_set_file_security = 1;
+      hm_advapi32 = LoadLibrary ("Advapi32.dll");
+      s_pfn_Set_File_Security =
+        (SetFileSecurity_Proc) GetProcAddress (
+            hm_advapi32, SetFileSecurity_Name);
+    }
+  if (s_pfn_Set_File_Security == NULL)
+    {
+      errno = ENOTSUP;
+      return FALSE;
+    }
+  return (s_pfn_Set_File_Security (lpFileName, SecurityInformation,
+                                  pSecurityDescriptor));
+}
+
 static BOOL WINAPI
 get_security_descriptor_owner (PSECURITY_DESCRIPTOR pSecurityDescriptor,
                               PSID *pOwner,
@@ -626,6 +717,7 @@ get_security_descriptor_owner (PSECURITY_DESCRIPTOR pSecurityDescriptor,
   HMODULE hm_advapi32 = NULL;
   if (is_windows_9x () == TRUE)
     {
+      errno = ENOTSUP;
       return FALSE;
     }
   if (g_b_init_get_security_descriptor_owner == 0)
@@ -638,6 +730,7 @@ get_security_descriptor_owner (PSECURITY_DESCRIPTOR pSecurityDescriptor,
     }
   if (s_pfn_Get_Security_Descriptor_Owner == NULL)
     {
+      errno = ENOTSUP;
       return FALSE;
     }
   return (s_pfn_Get_Security_Descriptor_Owner (pSecurityDescriptor, pOwner,
@@ -653,6 +746,7 @@ get_security_descriptor_group (PSECURITY_DESCRIPTOR pSecurityDescriptor,
   HMODULE hm_advapi32 = NULL;
   if (is_windows_9x () == TRUE)
     {
+      errno = ENOTSUP;
       return FALSE;
     }
   if (g_b_init_get_security_descriptor_group == 0)
@@ -665,12 +759,44 @@ get_security_descriptor_group (PSECURITY_DESCRIPTOR pSecurityDescriptor,
     }
   if (s_pfn_Get_Security_Descriptor_Group == NULL)
     {
+      errno = ENOTSUP;
       return FALSE;
     }
   return (s_pfn_Get_Security_Descriptor_Group (pSecurityDescriptor, pGroup,
                                               lpbGroupDefaulted));
 }
 
+static BOOL WINAPI
+get_security_descriptor_dacl (PSECURITY_DESCRIPTOR pSecurityDescriptor,
+                             LPBOOL lpbDaclPresent,
+                             PACL *pDacl,
+                             LPBOOL lpbDaclDefaulted)
+{
+  static GetSecurityDescriptorDacl_Proc s_pfn_Get_Security_Descriptor_Dacl = NULL;
+  HMODULE hm_advapi32 = NULL;
+  if (is_windows_9x () == TRUE)
+    {
+      errno = ENOTSUP;
+      return FALSE;
+    }
+  if (g_b_init_get_security_descriptor_dacl == 0)
+    {
+      g_b_init_get_security_descriptor_dacl = 1;
+      hm_advapi32 = LoadLibrary ("Advapi32.dll");
+      s_pfn_Get_Security_Descriptor_Dacl =
+        (GetSecurityDescriptorDacl_Proc) GetProcAddress (
+            hm_advapi32, "GetSecurityDescriptorDacl");
+    }
+  if (s_pfn_Get_Security_Descriptor_Dacl == NULL)
+    {
+      errno = ENOTSUP;
+      return FALSE;
+    }
+  return (s_pfn_Get_Security_Descriptor_Dacl (pSecurityDescriptor,
+                                             lpbDaclPresent, pDacl,
+                                             lpbDaclDefaulted));
+}
+
 static BOOL WINAPI
 is_valid_sid (PSID sid)
 {
@@ -865,25 +991,122 @@ create_symbolic_link (LPTSTR lpSymlinkFilename,
     }
   return retval;
 }
-\f
-/* Equivalent of strerror for W32 error codes.  */
-char *
-w32_strerror (int error_no)
+
+static BOOL WINAPI
+is_valid_security_descriptor (PSECURITY_DESCRIPTOR pSecurityDescriptor)
 {
-  static char buf[500];
+  static IsValidSecurityDescriptor_Proc s_pfn_Is_Valid_Security_Descriptor_Proc = NULL;
 
-  if (error_no == 0)
-    error_no = GetLastError ();
+  if (is_windows_9x () == TRUE)
+    {
+      errno = ENOTSUP;
+      return FALSE;
+    }
 
-  buf[0] = '\0';
-  if (!FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL,
-                     error_no,
-                     0, /* choose most suitable language */
-                     buf, sizeof (buf), NULL))
-    sprintf (buf, "w32 error %u", error_no);
-  return buf;
+  if (g_b_init_is_valid_security_descriptor == 0)
+    {
+      g_b_init_is_valid_security_descriptor = 1;
+      s_pfn_Is_Valid_Security_Descriptor_Proc =
+       (IsValidSecurityDescriptor_Proc)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
+                                                       "IsValidSecurityDescriptor");
+    }
+  if (s_pfn_Is_Valid_Security_Descriptor_Proc == NULL)
+    {
+      errno = ENOTSUP;
+      return FALSE;
+    }
+
+  return s_pfn_Is_Valid_Security_Descriptor_Proc (pSecurityDescriptor);
 }
 
+static BOOL WINAPI
+convert_sd_to_sddl (PSECURITY_DESCRIPTOR SecurityDescriptor,
+                   DWORD RequestedStringSDRevision,
+                   SECURITY_INFORMATION SecurityInformation,
+                   LPTSTR  *StringSecurityDescriptor,
+                   PULONG StringSecurityDescriptorLen)
+{
+  static ConvertSecurityDescriptorToStringSecurityDescriptor_Proc s_pfn_Convert_SD_To_SDDL = NULL;
+  BOOL retval;
+
+  if (is_windows_9x () == TRUE)
+    {
+      errno = ENOTSUP;
+      return FALSE;
+    }
+
+  if (g_b_init_convert_sd_to_sddl == 0)
+    {
+      g_b_init_convert_sd_to_sddl = 1;
+#ifdef _UNICODE
+      s_pfn_Convert_SD_To_SDDL =
+       (ConvertSecurityDescriptorToStringSecurityDescriptor_Proc)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
+                                                                                 "ConvertSecurityDescriptorToStringSecurityDescriptorW");
+#else
+      s_pfn_Convert_SD_To_SDDL =
+       (ConvertSecurityDescriptorToStringSecurityDescriptor_Proc)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
+                                                                                 "ConvertSecurityDescriptorToStringSecurityDescriptorA");
+#endif
+    }
+  if (s_pfn_Convert_SD_To_SDDL == NULL)
+    {
+      errno = ENOTSUP;
+      return FALSE;
+    }
+
+  retval = s_pfn_Convert_SD_To_SDDL (SecurityDescriptor,
+                                    RequestedStringSDRevision,
+                                    SecurityInformation,
+                                    StringSecurityDescriptor,
+                                    StringSecurityDescriptorLen);
+
+  return retval;
+}
+
+static BOOL WINAPI
+convert_sddl_to_sd (LPCTSTR StringSecurityDescriptor,
+                   DWORD StringSDRevision,
+                   PSECURITY_DESCRIPTOR  *SecurityDescriptor,
+                   PULONG  SecurityDescriptorSize)
+{
+  static ConvertStringSecurityDescriptorToSecurityDescriptor_Proc s_pfn_Convert_SDDL_To_SD = NULL;
+  BOOL retval;
+
+  if (is_windows_9x () == TRUE)
+    {
+      errno = ENOTSUP;
+      return FALSE;
+    }
+
+  if (g_b_init_convert_sddl_to_sd == 0)
+    {
+      g_b_init_convert_sddl_to_sd = 1;
+#ifdef _UNICODE
+      s_pfn_Convert_SDDL_To_SD =
+       (ConvertStringSecurityDescriptorToSecurityDescriptor_Proc)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
+                                                                                 "ConvertStringSecurityDescriptorToSecurityDescriptorW");
+#else
+      s_pfn_Convert_SDDL_To_SD =
+       (ConvertStringSecurityDescriptorToSecurityDescriptor_Proc)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
+                                                                                 "ConvertStringSecurityDescriptorToSecurityDescriptorA");
+#endif
+    }
+  if (s_pfn_Convert_SDDL_To_SD == NULL)
+    {
+      errno = ENOTSUP;
+      return FALSE;
+    }
+
+  retval = s_pfn_Convert_SDDL_To_SD (StringSecurityDescriptor,
+                                    StringSDRevision,
+                                    SecurityDescriptor,
+                                    SecurityDescriptorSize);
+
+  return retval;
+}
+
+\f
+
 /* Return 1 if P is a valid pointer to an object of size SIZE.  Return
    0 if P is NOT a valid pointer.  Return -1 if we cannot validate P.
 
@@ -910,8 +1133,18 @@ static char startup_dir[MAXPATHLEN];
 
 /* Get the current working directory.  */
 char *
-getwd (char *dir)
+getcwd (char *dir, int dirsize)
 {
+  if (!dirsize)
+    {
+      errno = EINVAL;
+      return NULL;
+    }
+  if (dirsize <= strlen (startup_dir))
+    {
+      errno = ERANGE;
+      return NULL;
+    }
 #if 0
   if (GetCurrentDirectory (MAXPATHLEN, dir) > 0)
     return dir;
@@ -1528,50 +1761,49 @@ is_unc_volume (const char *filename)
   return 1;
 }
 
-/* Routines that are no-ops on NT but are defined to get Emacs to compile.  */
+/* Emulate the Posix unsetenv.  */
 int
-sigemptyset (sigset_t *set)
+unsetenv (const char *name)
 {
-  *set = 0;
-  return 0;
-}
-
-int
-sigaddset (sigset_t *set, int signo)
-{
-  return 0;
-}
+  char *var;
+  size_t name_len;
+  int retval;
 
-int
-sigfillset (sigset_t *set)
-{
-  return 0;
+  if (name == NULL || *name == '\0' || strchr (name, '=') != NULL)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+  name_len = strlen (name);
+  /* MS docs says an environment variable cannot be longer than 32K.  */
+  if (name_len > 32767)
+    {
+      errno = ENOMEM;
+      return 0;
+    }
+  /* It is safe to use 'alloca' with 32K size, since the stack is at
+     least 2MB, and we set it to 8MB in the link command line.  */
+  var = alloca (name_len + 2);
+  strncpy (var, name, name_len);
+  var[name_len++] = '=';
+  var[name_len] = '\0';
+  return _putenv (var);
 }
 
+/* MS _putenv doesn't support removing a variable when the argument
+   does not include the '=' character, so we fix that here.  */
 int
-sigprocmask (int how, const sigset_t *set, sigset_t *oset)
+sys_putenv (char *str)
 {
-  return 0;
-}
+  const char *const name_end = strchr (str, '=');
 
-int
-pthread_sigmask (int how, const sigset_t *set, sigset_t *oset)
-{
-  if (sigprocmask (how, set, oset) == -1)
-    return EINVAL;
-  return 0;
-}
+  if (name_end == NULL)
+    {
+      /* Remove the variable from the environment.  */
+      return unsetenv (str);
+    }
 
-int
-setpgrp (int pid, int gid)
-{
-  return 0;
-}
-
-int
-alarm (int seconds)
-{
-  return 0;
+  return _putenv (str);
 }
 
 #define REG_ROOT "SOFTWARE\\GNU\\Emacs"
@@ -1652,7 +1884,7 @@ init_environment (char ** argv)
         see if it succeeds.  But I think that's too much to ask.  */
 
       /* MSVCRT's _access crashes with D_OK.  */
-      if (tmp && sys_access (tmp, D_OK) == 0)
+      if (tmp && faccessat (AT_FDCWD, tmp, D_OK, AT_EACCESS) == 0)
        {
          char * var = alloca (strlen (tmp) + 8);
          sprintf (var, "TMPDIR=%s", tmp);
@@ -1674,7 +1906,6 @@ init_environment (char ** argv)
     LPBYTE lpval;
     DWORD dwType;
     char locale_name[32];
-    struct stat ignored;
     char default_home[MAX_PATH];
     int appdata = 0;
 
@@ -1715,7 +1946,7 @@ init_environment (char ** argv)
     /* For backwards compatibility, check if a .emacs file exists in C:/
        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)
+    if (!check_existing ("C:/.emacs"))
       {
        HRESULT profile_result;
        /* Dynamically load ShGetFolderPath, as it won't exist on versions
@@ -1784,7 +2015,8 @@ init_environment (char ** argv)
       /* FIXME: should use substring of get_emacs_configuration ().
         But I don't think the Windows build supports alpha, mips etc
          anymore, so have taken the easy option for now.  */
-      else if (p && xstrcasecmp (p, "\\i386") == 0)
+      else if (p && (xstrcasecmp (p, "\\i386") == 0
+                     || xstrcasecmp (p, "\\AMD64") == 0))
        {
          *p = 0;
          p = strrchr (modname, '\\');
@@ -1873,7 +2105,7 @@ init_environment (char ** argv)
        memcpy (*envp, "COMSPEC=", 8);
   }
 
-  /* Remember the initial working directory for getwd.  */
+  /* Remember the initial working directory for getcwd.  */
   /* FIXME: Do we need to resolve possible symlinks in startup_dir?
      Does it matter anywhere in Emacs?  */
   if (!GetCurrentDirectory (MAXPATHLEN, startup_dir))
@@ -1932,7 +2164,16 @@ get_emacs_configuration (void)
     case PROCESSOR_INTEL_386:
     case PROCESSOR_INTEL_486:
     case PROCESSOR_INTEL_PENTIUM:
+#ifdef _WIN64
+      arch = "amd64";
+#else
       arch = "i386";
+#endif
+      break;
+#endif
+#ifdef PROCESSOR_AMD_X8664
+    case PROCESSOR_AMD_X8664:
+      arch = "amd64";
       break;
 #endif
 
@@ -2477,7 +2718,7 @@ is_exec (const char * name)
    and readdir.  We can't use the procedures supplied in sysdep.c,
    so we provide them here.  */
 
-struct direct dir_static;       /* simulated directory contents */
+struct dirent dir_static;       /* simulated directory contents */
 static HANDLE dir_find_handle = INVALID_HANDLE_VALUE;
 static int    dir_is_fat;
 static char   dir_pathname[MAXPATHLEN+1];
@@ -2547,7 +2788,7 @@ closedir (DIR *dirp)
   xfree ((char *) dirp);
 }
 
-struct direct *
+struct dirent *
 readdir (DIR *dirp)
 {
   int downcase = !NILP (Vw32_downcase_file_names);
@@ -2601,7 +2842,7 @@ readdir (DIR *dirp)
       downcase = 1;    /* 8+3 aliases are returned in all caps */
     }
   dir_static.d_namlen = strlen (dir_static.d_name);
-  dir_static.d_reclen = sizeof (struct direct) - MAXNAMLEN + 3 +
+  dir_static.d_reclen = sizeof (struct dirent) - MAXNAMLEN + 3 +
     dir_static.d_namlen - dir_static.d_namlen % 4;
 
   /* If the file name in cFileName[] includes `?' characters, it means
@@ -2754,16 +2995,20 @@ logon_network_drive (const char *path)
   WNetAddConnection2 (&resource, NULL, NULL, CONNECT_INTERACTIVE);
 }
 
-/* Shadow some MSVC runtime functions to map requests for long filenames
-   to reasonable short names if necessary.  This was originally added to
-   permit running Emacs on NT 3.1 on a FAT partition, which doesn't support
-   long file names.  */
-
+/* Emulate faccessat(2).  */
 int
-sys_access (const char * path, int mode)
+faccessat (int dirfd, const char * path, int mode, int flags)
 {
   DWORD attributes;
 
+  if (dirfd != AT_FDCWD
+      && !(IS_DIRECTORY_SEP (path[0])
+          || IS_DEVICE_SEP (path[1])))
+    {
+      errno = EBADF;
+      return -1;
+    }
+
   /* MSVCRT implementation of 'access' doesn't recognize D_OK, and its
      newer versions blow up when passed D_OK.  */
   path = map_w32_filename (path, NULL);
@@ -2771,7 +3016,8 @@ sys_access (const char * path, int mode)
      to get the attributes of its target file.  Note: any symlinks in
      PATH elements other than the last one are transparently resolved
      by GetFileAttributes below.  */
-  if ((volume_info.flags & FILE_SUPPORTS_REPARSE_POINTS) != 0)
+  if ((volume_info.flags & FILE_SUPPORTS_REPARSE_POINTS) != 0
+      && (flags & AT_SYMLINK_NOFOLLOW) == 0)
     path = chase_symlinks (path);
 
   if ((attributes = GetFileAttributes (path)) == -1)
@@ -2803,7 +3049,8 @@ sys_access (const char * path, int mode)
        }
       return -1;
     }
-  if ((mode & X_OK) != 0 && !is_exec (path))
+  if ((mode & X_OK) != 0
+      && !(is_exec (path) || (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0))
     {
       errno = EACCES;
       return -1;
@@ -2821,6 +3068,11 @@ sys_access (const char * path, int mode)
   return 0;
 }
 
+/* Shadow some MSVC runtime functions to map requests for long filenames
+   to reasonable short names if necessary.  This was originally added to
+   permit running Emacs on NT 3.1 on a FAT partition, which doesn't support
+   long file names.  */
+
 int
 sys_chdir (const char * path)
 {
@@ -3006,7 +3258,7 @@ sys_mktemp (char * template)
        {
          int save_errno = errno;
          p[0] = first_char[i];
-         if (sys_access (template, 0) < 0)
+         if (faccessat (AT_FDCWD, template, F_OK, AT_EACCESS) < 0)
            {
              errno = save_errno;
              return template;
@@ -3393,8 +3645,7 @@ w32_add_to_cache (PSID sid, unsigned id, char *name)
 #define GID 2
 
 static int
-get_name_and_id (PSECURITY_DESCRIPTOR psd, const char *fname,
-                unsigned *id, char *nm, int what)
+get_name_and_id (PSECURITY_DESCRIPTOR psd, unsigned *id, char *nm, int what)
 {
   PSID sid = NULL;
   char machine[MAX_COMPUTERNAME_LENGTH+1];
@@ -3404,7 +3655,6 @@ get_name_and_id (PSECURITY_DESCRIPTOR psd, const char *fname,
   DWORD name_len = sizeof (name);
   char domain[1024];
   DWORD domain_len = sizeof (domain);
-  char *mp = NULL;
   int use_dflt = 0;
   int result;
 
@@ -3419,22 +3669,7 @@ get_name_and_id (PSECURITY_DESCRIPTOR psd, const char *fname,
     use_dflt = 1;
   else if (!w32_cached_id (sid, id, nm))
     {
-      /* If FNAME is a UNC, we need to lookup account on the
-        specified machine.  */
-      if (IS_DIRECTORY_SEP (fname[0]) && IS_DIRECTORY_SEP (fname[1])
-         && fname[2] != '\0')
-       {
-         const char *s;
-         char *p;
-
-         for (s = fname + 2, p = machine;
-              *s && !IS_DIRECTORY_SEP (*s); s++, p++)
-           *p = *s;
-         *p = '\0';
-         mp = machine;
-       }
-
-      if (!lookup_account_sid (mp, sid, name, &name_len,
+      if (!lookup_account_sid (NULL, sid, name, &name_len,
                               domain, &domain_len, &ignore)
          || name_len > UNLEN+1)
        use_dflt = 1;
@@ -3449,9 +3684,7 @@ 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, struct stat *st)
 {
   int dflt_usr = 0, dflt_grp = 0;
 
@@ -3462,9 +3695,9 @@ get_file_owner_and_group (PSECURITY_DESCRIPTOR psd,
     }
   else
     {
-      if (get_name_and_id (psd, fname, &st->st_uid, st->st_uname, UID))
+      if (get_name_and_id (psd, &st->st_uid, st->st_uname, UID))
        dflt_usr = 1;
-      if (get_name_and_id (psd, fname, &st->st_gid, st->st_gname, GID))
+      if (get_name_and_id (psd, &st->st_gid, st->st_gname, GID))
        dflt_grp = 1;
     }
   /* Consider files to belong to current user/group, if we cannot get
@@ -3503,6 +3736,10 @@ is_slow_fs (const char *name)
   return !(devtype == DRIVE_FIXED || devtype == DRIVE_RAMDISK);
 }
 
+/* If this is non-zero, the caller wants accurate information about
+   file's owner and group, which could be expensive to get.  */
+int w32_stat_get_owner_group;
+
 /* 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 and owner/group without hacks in the main Emacs code. */
@@ -3674,6 +3911,7 @@ stat_worker (const char * path, struct stat * buf, int follow_symlinks)
       /* We produce the fallback owner and group data, based on the
         current user that runs Emacs, in the following cases:
 
+         . caller didn't request owner and group info
          . this is Windows 9X
          . getting security by handle failed, and we need to produce
            information for the target of a symlink (this is better
@@ -3682,23 +3920,25 @@ stat_worker (const char * path, struct stat * buf, int follow_symlinks)
 
         If getting security by handle fails, and we don't need to
         resolve symlinks, we try getting security by name.  */
-      if (is_windows_9x () != TRUE)
-       psd = get_file_security_desc_by_handle (fh);
-      if (psd)
-       {
-         get_file_owner_and_group (psd, name, buf);
-         LocalFree (psd);
-       }
-      else if (is_windows_9x () == TRUE)
-       get_file_owner_and_group (NULL, name, buf);
-      else if (!(is_a_symlink && follow_symlinks))
+      if (!w32_stat_get_owner_group || is_windows_9x () == TRUE)
+       get_file_owner_and_group (NULL, buf);
+      else
        {
-         psd = get_file_security_desc_by_name (name);
-         get_file_owner_and_group (psd, name, buf);
-         xfree (psd);
+         psd = get_file_security_desc_by_handle (fh);
+         if (psd)
+           {
+             get_file_owner_and_group (psd, buf);
+             LocalFree (psd);
+           }
+         else if (!(is_a_symlink && follow_symlinks))
+           {
+             psd = get_file_security_desc_by_name (name);
+             get_file_owner_and_group (psd, buf);
+             xfree (psd);
+           }
+         else
+           get_file_owner_and_group (NULL, buf);
        }
-      else
-       get_file_owner_and_group (NULL, name, buf);
       CloseHandle (fh);
     }
   else
@@ -3806,7 +4046,7 @@ stat_worker (const char * path, struct stat * buf, int follow_symlinks)
       else
        buf->st_mode = S_IFREG;
 
-      get_file_owner_and_group (NULL, name, buf);
+      get_file_owner_and_group (NULL, buf);
     }
 
 #if 0
@@ -3988,9 +4228,13 @@ utime (const char *name, struct utimbuf *times)
     }
 
   /* Need write access to set times.  */
-  fh = CreateFile (name, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
-                  0, OPEN_EXISTING, 0, NULL);
-  if (fh)
+  fh = CreateFile (name, FILE_WRITE_ATTRIBUTES,
+                  /* If NAME specifies a directory, FILE_SHARE_DELETE
+                     allows other processes to delete files inside it,
+                     while we have the directory open.  */
+                  FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+                  0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
+  if (fh != INVALID_HANDLE_VALUE)
     {
       convert_from_time_t (times->actime, &atime);
       convert_from_time_t (times->modtime, &mtime);
@@ -4053,7 +4297,7 @@ symlink (char const *filename, char const *linkname)
     {
       /* Non-absolute FILENAME is understood as being relative to
         LINKNAME's directory.  We need to prepend that directory to
-        FILENAME to get correct results from sys_access below, since
+        FILENAME to get correct results from faccessat below, since
         otherwise it will interpret FILENAME relative to the
         directory where the Emacs process runs.  Note that
         make-symbolic-link always makes sure LINKNAME is a fully
@@ -4067,10 +4311,10 @@ symlink (char const *filename, char const *linkname)
        strncpy (tem, linkfn, p - linkfn);
       tem[p - linkfn] = '\0';
       strcat (tem, filename);
-      dir_access = sys_access (tem, D_OK);
+      dir_access = faccessat (AT_FDCWD, tem, D_OK, AT_EACCESS);
     }
   else
-    dir_access = sys_access (filename, D_OK);
+    dir_access = faccessat (AT_FDCWD, filename, D_OK, AT_EACCESS);
 
   /* Since Windows distinguishes between symlinks to directories and
      to files, we provide a kludgy feature: if FILENAME doesn't
@@ -4256,7 +4500,7 @@ readlink (const char *name, char *buf, size_t buf_size)
        errno = EINVAL;
       else
        {
-         /* Copy the link target name, in wide characters, fro
+         /* Copy the link target name, in wide characters, from
             reparse_data, then convert it to multibyte encoding in
             the current locale's codepage.  */
          WCHAR *lwname;
@@ -4432,6 +4676,239 @@ chase_symlinks (const char *file)
   return target;
 }
 
+\f
+/* Posix ACL emulation.  */
+
+int
+acl_valid (acl_t acl)
+{
+  return is_valid_security_descriptor ((PSECURITY_DESCRIPTOR)acl) ? 0 : -1;
+}
+
+char *
+acl_to_text (acl_t acl, ssize_t *size)
+{
+  LPTSTR str_acl;
+  SECURITY_INFORMATION flags =
+    OWNER_SECURITY_INFORMATION |
+    GROUP_SECURITY_INFORMATION |
+    DACL_SECURITY_INFORMATION;
+  char *retval = NULL;
+  ULONG local_size;
+  int e = errno;
+
+  errno = 0;
+
+  if (convert_sd_to_sddl ((PSECURITY_DESCRIPTOR)acl, SDDL_REVISION_1, flags, &str_acl, &local_size))
+    {
+      errno = e;
+      /* We don't want to mix heaps, so we duplicate the string in our
+        heap and free the one allocated by the API.  */
+      retval = xstrdup (str_acl);
+      if (size)
+       *size = local_size;
+      LocalFree (str_acl);
+    }
+  else if (errno != ENOTSUP)
+    errno = EINVAL;
+
+  return retval;
+}
+
+acl_t
+acl_from_text (const char *acl_str)
+{
+  PSECURITY_DESCRIPTOR psd, retval = NULL;
+  ULONG sd_size;
+  int e = errno;
+
+  errno = 0;
+
+  if (convert_sddl_to_sd (acl_str, SDDL_REVISION_1, &psd, &sd_size))
+    {
+      errno = e;
+      retval = xmalloc (sd_size);
+      memcpy (retval, psd, sd_size);
+      LocalFree (psd);
+    }
+  else if (errno != ENOTSUP)
+    errno = EINVAL;
+
+  return retval;
+}
+
+int
+acl_free (void *ptr)
+{
+  xfree (ptr);
+  return 0;
+}
+
+acl_t
+acl_get_file (const char *fname, acl_type_t type)
+{
+  PSECURITY_DESCRIPTOR psd = NULL;
+  const char *filename;
+
+  if (type == ACL_TYPE_ACCESS)
+    {
+      DWORD sd_len, err;
+      SECURITY_INFORMATION si =
+       OWNER_SECURITY_INFORMATION |
+       GROUP_SECURITY_INFORMATION |
+       DACL_SECURITY_INFORMATION ;
+      int e = errno;
+
+      filename = map_w32_filename (fname, NULL);
+      if ((volume_info.flags & FILE_SUPPORTS_REPARSE_POINTS) != 0)
+       fname = chase_symlinks (filename);
+      else
+       fname = filename;
+
+      errno = 0;
+      if (!get_file_security (fname, si, psd, 0, &sd_len)
+         && errno != ENOTSUP)
+       {
+         err = GetLastError ();
+         if (err == ERROR_INSUFFICIENT_BUFFER)
+           {
+             psd = xmalloc (sd_len);
+             if (!get_file_security (fname, si, psd, sd_len, &sd_len))
+               {
+                 xfree (psd);
+                 errno = EIO;
+                 psd = NULL;
+               }
+           }
+         else if (err == ERROR_FILE_NOT_FOUND
+                  || err == ERROR_PATH_NOT_FOUND)
+           errno = ENOENT;
+         else
+           errno = EIO;
+       }
+      else if (!errno)
+       errno = e;
+    }
+  else if (type != ACL_TYPE_DEFAULT)
+    errno = EINVAL;
+
+  return psd;
+}
+
+int
+acl_set_file (const char *fname, acl_type_t type, acl_t acl)
+{
+  TOKEN_PRIVILEGES old1, old2;
+  DWORD err;
+  BOOL res;
+  int st = 0, retval = -1;
+  SECURITY_INFORMATION flags = 0;
+  PSID psid;
+  PACL pacl;
+  BOOL dflt;
+  BOOL dacl_present;
+  int e;
+  const char *filename;
+
+  if (acl_valid (acl) != 0
+      || (type != ACL_TYPE_DEFAULT && type != ACL_TYPE_ACCESS))
+    {
+      errno = EINVAL;
+      return -1;
+    }
+
+  if (type == ACL_TYPE_DEFAULT)
+    {
+      errno = ENOSYS;
+      return -1;
+    }
+
+  filename = map_w32_filename (fname, NULL);
+  if ((volume_info.flags & FILE_SUPPORTS_REPARSE_POINTS) != 0)
+    fname = chase_symlinks (filename);
+  else
+    fname = filename;
+
+  if (get_security_descriptor_owner ((PSECURITY_DESCRIPTOR)acl, &psid, &dflt)
+      && psid)
+    flags |= OWNER_SECURITY_INFORMATION;
+  if (get_security_descriptor_group ((PSECURITY_DESCRIPTOR)acl, &psid, &dflt)
+      && psid)
+    flags |= GROUP_SECURITY_INFORMATION;
+  if (get_security_descriptor_dacl ((PSECURITY_DESCRIPTOR)acl, &dacl_present,
+                                   &pacl, &dflt)
+      && dacl_present)
+    flags |= DACL_SECURITY_INFORMATION;
+  if (!flags)
+    return 0;
+
+  /* According to KB-245153, setting the owner will succeed if either:
+     (1) the caller is the user who will be the new owner, and has the
+         SE_TAKE_OWNERSHIP privilege, or
+     (2) the caller has the SE_RESTORE privilege, in which case she can
+         set any valid user or group as the owner
+
+     We request below both SE_TAKE_OWNERSHIP and SE_RESTORE
+     privileges, and disregard any failures in obtaining them.  If
+     these privileges cannot be obtained, and do not already exist in
+     the calling thread's security token, this function could fail
+     with EPERM.  */
+  if (enable_privilege (SE_TAKE_OWNERSHIP_NAME, TRUE, &old1))
+    st++;
+  if (enable_privilege (SE_RESTORE_NAME, TRUE, &old2))
+    st++;
+
+  e = errno;
+  errno = 0;
+  set_file_security ((char *)fname, flags, (PSECURITY_DESCRIPTOR)acl);
+  err = GetLastError ();
+  if (st)
+    {
+      if (st >= 2)
+       restore_privilege (&old2);
+      restore_privilege (&old1);
+      revert_to_self ();
+    }
+
+  if (errno == ENOTSUP)
+    ;
+  else if (err == ERROR_SUCCESS)
+    {
+      retval = 0;
+      errno = e;
+    }
+  else if (err == ERROR_INVALID_OWNER || err == ERROR_NOT_ALL_ASSIGNED)
+    {
+      /* Maybe the requested ACL and the one the file already has are
+        identical, in which case we can silently ignore the
+        failure.  (And no, Windows doesn't.)  */
+      acl_t current_acl = acl_get_file (fname, ACL_TYPE_ACCESS);
+
+      errno = EPERM;
+      if (current_acl)
+       {
+         char *acl_from = acl_to_text (current_acl, NULL);
+         char *acl_to = acl_to_text (acl, NULL);
+
+         if (acl_from && acl_to && xstrcasecmp (acl_from, acl_to) == 0)
+           {
+             retval = 0;
+             errno = e;
+           }
+         if (acl_from)
+           acl_free (acl_from);
+         if (acl_to)
+           acl_free (acl_to);
+         acl_free (current_acl);
+       }
+    }
+  else if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND)
+    errno = ENOENT;
+
+  return retval;
+}
+
+\f
 /* MS-Windows version of careadlinkat (cf. ../lib/careadlinkat.c).  We
    have a fixed max size for file names, so we don't need the kind of
    alloc/malloc/realloc dance the gnulib version does.  We also don't
@@ -4647,8 +5124,8 @@ get_process_memory_info (HANDLE h_proc,
 
 static BOOL WINAPI
 get_process_working_set_size (HANDLE h_proc,
-                             DWORD *minrss,
-                             DWORD *maxrss)
+                             PSIZE_T minrss,
+                             PSIZE_T maxrss)
 {
   static GetProcessWorkingSetSize_Proc
     s_pfn_Get_Process_Working_Set_Size = NULL;
@@ -4893,7 +5370,7 @@ system_process_attributes (Lisp_Object pid)
   unsigned egid;
   PROCESS_MEMORY_COUNTERS mem;
   PROCESS_MEMORY_COUNTERS_EX mem_ex;
-  DWORD minrss, maxrss;
+  SIZE_T minrss, maxrss;
   MEMORYSTATUS memst;
   MEMORY_STATUS_EX memstex;
   double totphys = 0.0;
@@ -5121,7 +5598,7 @@ system_process_attributes (Lisp_Object pid)
       && get_process_memory_info (h_proc, (PROCESS_MEMORY_COUNTERS *)&mem_ex,
                                  sizeof (mem_ex)))
     {
-      DWORD rss = mem_ex.WorkingSetSize / 1024;
+      SIZE_T rss = mem_ex.WorkingSetSize / 1024;
 
       attrs = Fcons (Fcons (Qmajflt,
                            make_fixnum_or_float (mem_ex.PageFaultCount)),
@@ -5136,7 +5613,7 @@ system_process_attributes (Lisp_Object pid)
   else if (h_proc
           && get_process_memory_info (h_proc, &mem, sizeof (mem)))
     {
-      DWORD rss = mem_ex.WorkingSetSize / 1024;
+      SIZE_T rss = mem_ex.WorkingSetSize / 1024;
 
       attrs = Fcons (Fcons (Qmajflt,
                            make_fixnum_or_float (mem.PageFaultCount)),
@@ -5885,7 +6362,7 @@ fcntl (int s, int cmd, int options)
   check_errno ();
   if (fd_info[s].flags & FILE_SOCKET)
     {
-      if (cmd == F_SETFL && options == O_NDELAY)
+      if (cmd == F_SETFL && options == O_NONBLOCK)
        {
          unsigned long nblock = 1;
          int rc = pfn_ioctlsocket (SOCK_HANDLE (s), FIONBIO, &nblock);
@@ -5948,7 +6425,21 @@ sys_close (int fd)
 
                  winsock_inuse--; /* count open sockets */
                }
-             delete_child (cp);
+             /* If the process handle is NULL, it's either a socket
+                or serial connection, or a subprocess that was
+                already reaped by reap_subprocess, but whose
+                resources were not yet freed, because its output was
+                not fully read yet by the time it was reaped.  (This
+                usually happens with async subprocesses whose output
+                is being read by Emacs.)  Otherwise, this process was
+                not reaped yet, so we set its FD to a negative value
+                to make sure sys_select will eventually get to
+                calling the SIGCHLD handler for it, which will then
+                invoke waitpid and reap_subprocess.  */
+             if (cp->procinfo.hProcess == NULL)
+               delete_child (cp);
+             else
+               cp->fd = -1;
            }
        }
     }
@@ -6040,7 +6531,8 @@ sys_pipe (int * phandles)
 }
 
 /* Function to do blocking read of one byte, needed to implement
-   select.  It is only allowed on sockets and pipes. */
+   select.  It is only allowed on communication ports, sockets, or
+   pipes. */
 int
 _sys_read_ahead (int fd)
 {
@@ -6521,10 +7013,6 @@ sys_localtime (const time_t *t)
 
 
 \f
-/* Delayed loading of libraries.  */
-
-Lisp_Object Vlibrary_cache;
-
 /* Try loading LIBRARY_ID from the file(s) specified in
    Vdynamic_library_alist.  If the library is loaded successfully,
    return the handle of the DLL, and record the filename in the
@@ -6627,6 +7115,9 @@ void
 term_ntproc (int ignored)
 {
   (void)ignored;
+
+  term_timers ();
+
   /* shutdown the socket interface if necessary */
   term_winsock ();
 
@@ -6636,6 +7127,8 @@ term_ntproc (int ignored)
 void
 init_ntproc (int dumping)
 {
+  sigset_t initial_mask = 0;
+
   /* Initialize 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
@@ -6691,19 +7184,19 @@ init_ntproc (int dumping)
     fclose (stderr);
 
     if (stdin_save != INVALID_HANDLE_VALUE)
-      _open_osfhandle ((long) stdin_save, O_TEXT);
+      _open_osfhandle ((intptr_t) stdin_save, O_TEXT);
     else
       _open ("nul", O_TEXT | O_NOINHERIT | O_RDONLY);
     _fdopen (0, "r");
 
     if (stdout_save != INVALID_HANDLE_VALUE)
-      _open_osfhandle ((long) stdout_save, O_TEXT);
+      _open_osfhandle ((intptr_t) stdout_save, O_TEXT);
     else
       _open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY);
     _fdopen (1, "w");
 
     if (stderr_save != INVALID_HANDLE_VALUE)
-      _open_osfhandle ((long) stderr_save, O_TEXT);
+      _open_osfhandle ((intptr_t) stderr_save, O_TEXT);
     else
       _open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY);
     _fdopen (2, "w");
@@ -6712,7 +7205,12 @@ init_ntproc (int dumping)
   /* unfortunately, atexit depends on implementation of malloc */
   /* atexit (term_ntproc); */
   if (!dumping)
-    signal (SIGABRT, term_ntproc);
+    {
+      /* Make sure we start with all signals unblocked.  */
+      sigprocmask (SIG_SETMASK, &initial_mask, NULL);
+      signal (SIGABRT, term_ntproc);
+    }
+  init_timers ();
 
   /* determine which drives are fixed, for GetCachedVolumeInformation */
   {
@@ -6769,9 +7267,6 @@ globals_of_w32 (void)
 
   DEFSYM (QCloaded_from, ":loaded-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;
@@ -6799,6 +7294,11 @@ globals_of_w32 (void)
   g_b_init_get_native_system_info = 0;
   g_b_init_get_system_times = 0;
   g_b_init_create_symbolic_link = 0;
+  g_b_init_get_security_descriptor_dacl = 0;
+  g_b_init_convert_sd_to_sddl = 0;
+  g_b_init_convert_sddl_to_sd = 0;
+  g_b_init_is_valid_security_descriptor = 0;
+  g_b_init_set_file_security = 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
@@ -6808,6 +7308,9 @@ globals_of_w32 (void)
 
   /* "None" is the default group name on standalone workstations.  */
   strcpy (dflt_group_name, "None");
+
+  /* Reset, in case it has some value inherited from dump time.  */
+  w32_stat_get_owner_group = 0;
 }
 
 /* For make-serial-process  */
@@ -6822,7 +7325,7 @@ serial_open (char *port)
                    OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
   if (hnd == INVALID_HANDLE_VALUE)
     error ("Could not open %s", port);
-  fd = (int) _open_osfhandle ((int) hnd, 0);
+  fd = (int) _open_osfhandle ((intptr_t) hnd, 0);
   if (fd == -1)
     error ("Could not open %s", port);
 
@@ -7007,7 +7510,7 @@ emacs_gnutls_pull (gnutls_transport_ptr_t p, void* buf, size_t sz)
 {
   int n, sc, err;
   SELECT_TYPE fdset;
-  struct timeval timeout;
+  EMACS_TIME timeout;
   struct Lisp_Process *process = (struct Lisp_Process *)p;
   int fd = process->infd;
 
@@ -7023,8 +7526,7 @@ emacs_gnutls_pull (gnutls_transport_ptr_t p, void* buf, size_t sz)
       if (err == EWOULDBLOCK)
         {
           /* Set a small timeout.  */
-         timeout.tv_sec = 1;
-         timeout.tv_usec = 0;
+         timeout = make_emacs_time (1, 0);
           FD_ZERO (&fdset);
           FD_SET ((int)fd, &fdset);