]> code.delx.au - gnu-emacs/blobdiff - src/w32.c
Possibly fix bug #13086 with losing track of subprocesses on MS-Windows.
[gnu-emacs] / src / w32.c
index 810ae024173b05f8945a94cbad4eceffef03f3dc..edb9b1b6189277a8cb13272aded9476dbd185c81 100644 (file)
--- a/src/w32.c
+++ b/src/w32.c
@@ -31,14 +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 <setjmp.h>
 #include <time.h>
 
 /* must include CRT headers *before* config.h */
 
 #include <config.h>
+#include <mbstring.h>  /* for _mbspbrk */
 
 #undef access
 #undef chdir
@@ -102,17 +101,17 @@ 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
 
@@ -120,9 +119,10 @@ typedef struct _PROCESS_MEMORY_COUNTERS_EX {
 #include <aclapi.h>
 
 #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;
@@ -150,6 +150,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.  */
@@ -174,7 +188,9 @@ typedef struct _REPARSE_DATA_BUFFER {
 
 #include "w32.h"
 #include "ndir.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 */
@@ -198,6 +214,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.
 
@@ -329,8 +351,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) (
@@ -867,23 +889,6 @@ create_symbolic_link (LPTSTR lpSymlinkFilename,
   return retval;
 }
 \f
-/* Equivalent of strerror for W32 error codes.  */
-char *
-w32_strerror (int error_no)
-{
-  static char buf[500];
-
-  if (error_no == 0)
-    error_no = GetLastError ();
-
-  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;
-}
 
 /* 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.
@@ -1273,9 +1278,9 @@ init_user_info (void)
 
   /* Ensure HOME and SHELL are defined. */
   if (getenv ("HOME") == NULL)
-    abort ();
+    emacs_abort ();
   if (getenv ("SHELL") == NULL)
-    abort ();
+    emacs_abort ();
 
   /* Set dir and shell from environment variables. */
   strcpy (dflt_passwd.pw_dir, getenv ("HOME"));
@@ -1529,76 +1534,6 @@ is_unc_volume (const char *filename)
   return 1;
 }
 
-/* Routines that are no-ops on NT but are defined to get Emacs to compile.  */
-
-int
-sigsetmask (int signal_mask)
-{
-  return 0;
-}
-
-int
-sigmask (int sig)
-{
-  return 0;
-}
-
-int
-sigblock (int sig)
-{
-  return 0;
-}
-
-int
-sigunblock (int sig)
-{
-  return 0;
-}
-
-int
-sigemptyset (sigset_t *set)
-{
-  return 0;
-}
-
-int
-sigaddset (sigset_t *set, int signo)
-{
-  return 0;
-}
-
-int
-sigfillset (sigset_t *set)
-{
-  return 0;
-}
-
-int
-sigprocmask (int how, const sigset_t *set, sigset_t *oset)
-{
-  return 0;
-}
-
-int
-pthread_sigmask (int how, const sigset_t *set, sigset_t *oset)
-{
-  if (sigprocmask (how, set, oset) == -1)
-    return EINVAL;
-  return 0;
-}
-
-int
-setpgrp (int pid, int gid)
-{
-  return 0;
-}
-
-int
-alarm (int seconds)
-{
-  return 0;
-}
-
 #define REG_ROOT "SOFTWARE\\GNU\\Emacs"
 
 LPBYTE
@@ -1699,7 +1634,6 @@ init_environment (char ** argv)
     LPBYTE lpval;
     DWORD dwType;
     char locale_name[32];
-    struct stat ignored;
     char default_home[MAX_PATH];
     int appdata = 0;
 
@@ -1740,7 +1674,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
@@ -1788,9 +1722,9 @@ init_environment (char ** argv)
       char modname[MAX_PATH];
 
       if (!GetModuleFileName (NULL, modname, MAX_PATH))
-       abort ();
+       emacs_abort ();
       if ((p = strrchr (modname, '\\')) == NULL)
-       abort ();
+       emacs_abort ();
       *p = 0;
 
       if ((p = strrchr (modname, '\\')) && xstrcasecmp (p, "\\bin") == 0)
@@ -1809,7 +1743,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, '\\');
@@ -1902,13 +1837,13 @@ init_environment (char ** argv)
   /* FIXME: Do we need to resolve possible symlinks in startup_dir?
      Does it matter anywhere in Emacs?  */
   if (!GetCurrentDirectory (MAXPATHLEN, startup_dir))
-    abort ();
+    emacs_abort ();
 
   {
     static char modname[MAX_PATH];
 
     if (!GetModuleFileName (NULL, modname, MAX_PATH))
-      abort ();
+      emacs_abort ();
     argv[0] = modname;
   }
 
@@ -1930,7 +1865,7 @@ emacs_root_dir (void)
 
   p = getenv ("emacs_dir");
   if (p == NULL)
-    abort ();
+    emacs_abort ();
   strcpy (root_dir, p);
   root_dir[parse_root (root_dir, NULL)] = '\0';
   dostounix_filename (root_dir);
@@ -1957,7 +1892,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
 
@@ -2395,7 +2339,6 @@ map_w32_filename (const char * name, const char ** pPath)
   char c;
   char * path;
   const char * save_name = name;
-  int is_fat = 0;
 
   if (strlen (name) >= MAX_PATH)
     {
@@ -3288,7 +3231,7 @@ generate_inode_val (const char * name)
      doesn't resolve aliasing due to subst commands, or recognize hard
      links.  */
   if (!w32_get_long_filename ((char *)name, fullname, MAX_PATH))
-    abort ();
+    emacs_abort ();
 
   parse_root (fullname, &p);
   /* Normal W32 filesystems are still case insensitive. */
@@ -3419,8 +3362,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];
@@ -3430,7 +3372,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;
 
@@ -3445,22 +3386,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;
@@ -3475,9 +3401,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;
 
@@ -3488,9 +3412,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
@@ -3712,19 +3636,19 @@ stat_worker (const char * path, struct stat * buf, int follow_symlinks)
        psd = get_file_security_desc_by_handle (fh);
       if (psd)
        {
-         get_file_owner_and_group (psd, name, buf);
+         get_file_owner_and_group (psd, buf);
          LocalFree (psd);
        }
       else if (is_windows_9x () == TRUE)
-       get_file_owner_and_group (NULL, name, buf);
+       get_file_owner_and_group (NULL, buf);
       else if (!(is_a_symlink && follow_symlinks))
        {
          psd = get_file_security_desc_by_name (name);
-         get_file_owner_and_group (psd, name, buf);
+         get_file_owner_and_group (psd, buf);
          xfree (psd);
        }
       else
-       get_file_owner_and_group (NULL, name, buf);
+       get_file_owner_and_group (NULL, buf);
       CloseHandle (fh);
     }
   else
@@ -3832,7 +3756,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
@@ -4014,9 +3938,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);
@@ -4099,7 +4027,7 @@ symlink (char const *filename, char const *linkname)
     dir_access = sys_access (filename, D_OK);
 
   /* Since Windows distinguishes between symlinks to directories and
-     to files, we provide a kludgey feature: if FILENAME doesn't
+     to files, we provide a kludgy feature: if FILENAME doesn't
      exist, but ends in a slash, we create a symlink to directory.  If
      FILENAME exists and is a directory, we always create a symlink to
      directory.  */
@@ -4166,7 +4094,7 @@ symlink (char const *filename, char const *linkname)
    whether the underlying volume actually supports symlinks, by
    testing the FILE_SUPPORTS_REPARSE_POINTS bit in volume's flags, and
    avoid the call to this function if it doesn't.  That's because the
-   call to GetFileAttributes takes a non-negligible time, expecially
+   call to GetFileAttributes takes a non-negligible time, especially
    on non-local or removable filesystems.  See stat_worker for an
    example of how to do that.  */
 static int
@@ -4433,7 +4361,7 @@ chase_symlinks (const char *file)
       {
        target[res] = '\0';
        if (!(IS_DEVICE_SEP (target[1])
-             || IS_DIRECTORY_SEP (target[0]) && IS_DIRECTORY_SEP (target[1])))
+             || (IS_DIRECTORY_SEP (target[0]) && IS_DIRECTORY_SEP (target[1]))))
          {
            /* Target is relative.  Append it to the directory part of
               the symlink, then copy the result back to target.  */
@@ -4673,8 +4601,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;
@@ -4919,7 +4847,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;
@@ -5147,7 +5075,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)),
@@ -5162,7 +5090,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)),
@@ -5588,7 +5516,7 @@ socket_to_fd (SOCKET s)
          if (fd_info[ fd ].cp != NULL)
            {
              DebPrint (("sys_socket: fd_info[%d] apparently in use!\n", fd));
-             abort ();
+             emacs_abort ();
            }
 
          fd_info[ fd ].cp = cp;
@@ -5967,7 +5895,7 @@ sys_close (int fd)
            {
              if (fd_info[fd].flags & FILE_SOCKET)
                {
-                 if (winsock_lib == NULL) abort ();
+                 if (winsock_lib == NULL) emacs_abort ();
 
                  pfn_shutdown (SOCK_HANDLE (fd), 2);
                  rc = pfn_closesocket (SOCK_HANDLE (fd));
@@ -6085,7 +6013,7 @@ _sys_read_ahead (int fd)
       || (fd_info[fd].flags & FILE_READ) == 0)
     {
       DebPrint (("_sys_read_ahead: internal error: fd %d is not a pipe, serial port, or socket!\n", fd));
-      abort ();
+      emacs_abort ();
     }
 
   cp->status = STATUS_READ_IN_PROGRESS;
@@ -6221,7 +6149,7 @@ sys_read (int fd, char * buffer, unsigned int count)
       /* re-read CR carried over from last read */
       if (fd_info[fd].flags & FILE_LAST_CR)
        {
-         if (fd_info[fd].flags & FILE_BINARY) abort ();
+         if (fd_info[fd].flags & FILE_BINARY) emacs_abort ();
          *buffer++ = 0x0d;
          count--;
          nchars++;
@@ -6324,7 +6252,7 @@ sys_read (int fd, char * buffer, unsigned int count)
            }
          else /* FILE_SOCKET */
            {
-             if (winsock_lib == NULL) abort ();
+             if (winsock_lib == NULL) emacs_abort ();
 
              /* do the equivalent of a non-blocking read */
              pfn_ioctlsocket (SOCK_HANDLE (fd), FIONREAD, &waiting);
@@ -6475,7 +6403,7 @@ sys_write (int fd, const void * buffer, unsigned int count)
   else if (fd < MAXDESC && fd_info[fd].flags & FILE_SOCKET)
     {
       unsigned long nblock = 0;
-      if (winsock_lib == NULL) abort ();
+      if (winsock_lib == NULL) emacs_abort ();
 
       /* TODO: implement select() properly so non-blocking I/O works. */
       /* For now, make sure the write blocks.  */
@@ -6547,33 +6475,27 @@ sys_localtime (const time_t *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.  */
+/* 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
+   property :loaded-from of LIBRARY_ID.  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), return NULL.
+
+   We could also save the handle in :loaded-from, but currently
+   there's no use case for it.  */
 HMODULE
-w32_delayed_load (Lisp_Object libraries, Lisp_Object library_id)
+w32_delayed_load (Lisp_Object library_id)
 {
   HMODULE library_dll = NULL;
 
   CHECK_SYMBOL (library_id);
 
-  if (CONSP (libraries) && NILP (Fassq (library_id, Vlibrary_cache)))
+  if (CONSP (Vdynamic_library_alist)
+      && NILP (Fassq (library_id, Vlibrary_cache)))
     {
       Lisp_Object found = Qnil;
-      Lisp_Object dlls = Fassq (library_id, libraries);
+      Lisp_Object dlls = Fassq (library_id, Vdynamic_library_alist);
 
       if (CONSP (dlls))
         for (dlls = XCDR (dlls); CONSP (dlls); dlls = XCDR (dlls))
@@ -6641,8 +6563,7 @@ check_windows_init_file (void)
                      buffer,
                      "Emacs Abort Dialog",
                      MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL);
-      /* Use the low-level Emacs abort. */
-#undef abort
+         /* Use the low-level system abort. */
          abort ();
        }
       else
@@ -6653,8 +6574,12 @@ check_windows_init_file (void)
 }
 
 void
-term_ntproc (void)
+term_ntproc (int ignored)
 {
+  (void)ignored;
+
+  term_timers ();
+
   /* shutdown the socket interface if necessary */
   term_winsock ();
 
@@ -6662,8 +6587,10 @@ term_ntproc (void)
 }
 
 void
-init_ntproc (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
@@ -6719,19 +6646,19 @@ init_ntproc (void)
     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");
@@ -6739,7 +6666,13 @@ init_ntproc (void)
 
   /* unfortunately, atexit depends on implementation of malloc */
   /* atexit (term_ntproc); */
-  signal (SIGABRT, term_ntproc);
+  if (!dumping)
+    {
+      /* 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 */
   {
@@ -6774,7 +6707,7 @@ shutdown_handler (DWORD type)
       || type == CTRL_SHUTDOWN_EVENT) /* User shutsdown.  */
     {
       /* Shut down cleanly, making sure autosave files are up to date.  */
-      shut_down_emacs (0, 0, Qnil);
+      shut_down_emacs (0, Qnil);
     }
 
   /* Allow other handlers to handle this signal.  */
@@ -6796,9 +6729,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;
@@ -6849,7 +6779,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);
 
@@ -6891,7 +6821,7 @@ serial_configure (struct Lisp_Process *p, Lisp_Object contact)
     error ("Not a serial process");
   hnd = fd_info[ p->outfd ].hnd;
 
-  childp2 = Fcopy_sequence (PGET (p, childp));
+  childp2 = Fcopy_sequence (p->childp);
 
   /* Initialize timeouts for blocking read and blocking write.  */
   if (!GetCommTimeouts (hnd, &ct))
@@ -6920,7 +6850,7 @@ serial_configure (struct Lisp_Process *p, Lisp_Object contact)
   if (!NILP (Fplist_member (contact, QCspeed)))
     tem = Fplist_get (contact, QCspeed);
   else
-    tem = Fplist_get (PGET (p, childp), QCspeed);
+    tem = Fplist_get (p->childp, QCspeed);
   CHECK_NUMBER (tem);
   dcb.BaudRate = XINT (tem);
   childp2 = Fplist_put (childp2, QCspeed, tem);
@@ -6929,7 +6859,7 @@ serial_configure (struct Lisp_Process *p, Lisp_Object contact)
   if (!NILP (Fplist_member (contact, QCbytesize)))
     tem = Fplist_get (contact, QCbytesize);
   else
-    tem = Fplist_get (PGET (p, childp), QCbytesize);
+    tem = Fplist_get (p->childp, QCbytesize);
   if (NILP (tem))
     tem = make_number (8);
   CHECK_NUMBER (tem);
@@ -6943,7 +6873,7 @@ serial_configure (struct Lisp_Process *p, Lisp_Object contact)
   if (!NILP (Fplist_member (contact, QCparity)))
     tem = Fplist_get (contact, QCparity);
   else
-    tem = Fplist_get (PGET (p, childp), QCparity);
+    tem = Fplist_get (p->childp, QCparity);
   if (!NILP (tem) && !EQ (tem, Qeven) && !EQ (tem, Qodd))
     error (":parity must be nil (no parity), `even', or `odd'");
   dcb.fParity = FALSE;
@@ -6973,7 +6903,7 @@ serial_configure (struct Lisp_Process *p, Lisp_Object contact)
   if (!NILP (Fplist_member (contact, QCstopbits)))
     tem = Fplist_get (contact, QCstopbits);
   else
-    tem = Fplist_get (PGET (p, childp), QCstopbits);
+    tem = Fplist_get (p->childp, QCstopbits);
   if (NILP (tem))
     tem = make_number (1);
   CHECK_NUMBER (tem);
@@ -6990,7 +6920,7 @@ serial_configure (struct Lisp_Process *p, Lisp_Object contact)
   if (!NILP (Fplist_member (contact, QCflowcontrol)))
     tem = Fplist_get (contact, QCflowcontrol);
   else
-    tem = Fplist_get (PGET (p, childp), QCflowcontrol);
+    tem = Fplist_get (p->childp, QCflowcontrol);
   if (!NILP (tem) && !EQ (tem, Qhw) && !EQ (tem, Qsw))
     error (":flowcontrol must be nil (no flowcontrol), `hw', or `sw'");
   dcb.fOutxCtsFlow     = FALSE;
@@ -7024,7 +6954,7 @@ serial_configure (struct Lisp_Process *p, Lisp_Object contact)
     error ("SetCommState() failed");
 
   childp2 = Fplist_put (childp2, QCsummary, build_string (summary));
-  PSET (p, childp, childp2);
+  pset_childp (p, childp2);
 }
 
 #ifdef HAVE_GNUTLS
@@ -7034,7 +6964,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;
 
@@ -7050,8 +6980,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);