]> code.delx.au - gnu-emacs/blobdiff - src/w32.c
* gtkutil.c (USE_NEW_GTK_FONT_CHOOSER) [HAVE_FREETYPE]:
[gnu-emacs] / src / w32.c
index 7d63c73eb18cd7701fc8035741d5974de88088c1..e48078aec99cf6702741261496aacd924634c7e1 100644 (file)
--- a/src/w32.c
+++ b/src/w32.c
@@ -19,6 +19,8 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 /*
    Geoff Voelker (voelker@cs.washington.edu)                         7-29-94
 */
+
+#include <mingw_time.h>
 #include <stddef.h> /* for offsetof */
 #include <stdlib.h>
 #include <stdio.h>
@@ -47,7 +49,6 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #undef fopen
 #undef link
 #undef mkdir
-#undef mktemp
 #undef open
 #undef rename
 #undef rmdir
@@ -90,6 +91,21 @@ typedef struct _MEMORY_STATUS_EX {
   DWORDLONG ullAvailExtendedVirtual;
 } MEMORY_STATUS_EX,*LPMEMORY_STATUS_EX;
 
+/* These are here so that GDB would know about these data types.  This
+   allows to attach GDB to Emacs when a fatal exception is triggered
+   and Windows pops up the "application needs to be closed" dialog.
+   At that point, _gnu_exception_handler, the top-level exception
+   handler installed by the MinGW startup code, is somewhere on the
+   call-stack of the main thread, so going to that call frame and
+   looking at the argument to _gnu_exception_handler, which is a
+   PEXCEPTION_POINTERS pointer, can reveal the exception code
+   (excptr->ExceptionRecord->ExceptionCode) and the address where the
+   exception happened (excptr->ExceptionRecord->ExceptionAddress), as
+   well as some additional information specific to the exception.  */
+PEXCEPTION_POINTERS excptr;
+PEXCEPTION_RECORD excprec;
+PCONTEXT ctxrec;
+
 #include <lmcons.h>
 #include <shlobj.h>
 
@@ -202,6 +218,8 @@ typedef struct _REPARSE_DATA_BUFFER {
 #undef recvfrom
 #undef sendto
 
+#include <iphlpapi.h>  /* should be after winsock2.h */
+
 #include "w32.h"
 #include <dirent.h>
 #include "w32common.h"
@@ -233,7 +251,9 @@ 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 *);
+                      struct timespec *, void *);
+extern int sys_dup (int);
+
 
 
 \f
@@ -278,6 +298,7 @@ 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;
+static BOOL g_b_init_get_adapters_info;
 
 /*
   BEGIN: Wrapper functions around OpenProcessToken
@@ -420,6 +441,9 @@ typedef BOOL (WINAPI *ConvertSecurityDescriptorToStringSecurityDescriptor_Proc)
     LPTSTR  *StringSecurityDescriptor,
     PULONG StringSecurityDescriptorLen);
 typedef BOOL (WINAPI *IsValidSecurityDescriptor_Proc) (PSECURITY_DESCRIPTOR);
+typedef DWORD (WINAPI *GetAdaptersInfo_Proc) (
+    PIP_ADAPTER_INFO pAdapterInfo,
+    PULONG pOutBufLen);
 
   /* ** A utility function ** */
 static BOOL
@@ -1112,6 +1136,28 @@ convert_sddl_to_sd (LPCTSTR StringSecurityDescriptor,
   return retval;
 }
 
+static DWORD WINAPI
+get_adapters_info (PIP_ADAPTER_INFO pAdapterInfo, PULONG pOutBufLen)
+{
+  static GetAdaptersInfo_Proc s_pfn_Get_Adapters_Info = NULL;
+  HMODULE hm_iphlpapi = NULL;
+
+  if (is_windows_9x () == TRUE)
+    return ERROR_NOT_SUPPORTED;
+
+  if (g_b_init_get_adapters_info == 0)
+    {
+      g_b_init_get_adapters_info = 1;
+      hm_iphlpapi = LoadLibrary ("Iphlpapi.dll");
+      if (hm_iphlpapi)
+       s_pfn_Get_Adapters_Info = (GetAdaptersInfo_Proc)
+         GetProcAddress (hm_iphlpapi, "GetAdaptersInfo");
+    }
+  if (s_pfn_Get_Adapters_Info == NULL)
+    return ERROR_NOT_SUPPORTED;
+  return s_pfn_Get_Adapters_Info (pAdapterInfo, pOutBufLen);
+}
+
 \f
 
 /* Return 1 if P is a valid pointer to an object of size SIZE.  Return
@@ -2042,7 +2088,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 (!check_existing ("C:/.emacs"))
+    if (faccessat (AT_FDCWD, "C:/.emacs", F_OK, AT_EACCESS) != 0)
       {
        HRESULT profile_result;
        /* Dynamically load ShGetFolderPath, as it won't exist on versions
@@ -2180,7 +2226,8 @@ init_environment (char ** argv)
                          strcpy (&fname[pend - pstart + 1], "cmdproxy.exe");
                          ExpandEnvironmentStrings ((LPSTR) fname, bufc,
                                                    sizeof (bufc));
-                         if (check_existing (bufc))
+                         if (faccessat (AT_FDCWD, bufc, F_OK, AT_EACCESS)
+                             == 0)
                            {
                              lpval = bufc;
                              dwType = REG_SZ;
@@ -2452,7 +2499,7 @@ get_emacs_configuration_options (void)
 
 /* Emulate gettimeofday (Ulrich Leodolter, 1/11/95).  */
 int
-gettimeofday (struct timeval *restrict tv, struct timezone *restrict tz)
+gettimeofday (struct timeval *__restrict tv, struct timezone *__restrict tz)
 {
   struct _timeb tb;
   _ftime (&tb);
@@ -2487,8 +2534,6 @@ gettimeofday (struct timeval *restrict tv, struct timezone *restrict tz)
 int
 fdutimens (int fd, char const *file, struct timespec const timespec[2])
 {
-  struct _utimbuf ut;
-
   if (!timespec)
     {
       errno = ENOSYS;
@@ -2499,12 +2544,28 @@ fdutimens (int fd, char const *file, struct timespec const timespec[2])
       errno = EBADF;
       return -1;
     }
-  ut.actime = timespec[0].tv_sec;
-  ut.modtime = timespec[1].tv_sec;
+  /* _futime's prototype defines 2nd arg as having the type 'struct
+     _utimbuf', while utime needs to accept 'struct utimbuf' for
+     compatibility with Posix.  So we need to use 2 different (but
+     equivalent) types to avoid compiler warnings, sigh.  */
   if (fd >= 0)
-    return _futime (fd, &ut);
+    {
+      struct _utimbuf _ut;
+
+      _ut.actime = timespec[0].tv_sec;
+      _ut.modtime = timespec[1].tv_sec;
+      return _futime (fd, &_ut);
+    }
   else
-    return _utime (file, &ut);
+    {
+      struct utimbuf ut;
+
+      ut.actime = timespec[0].tv_sec;
+      ut.modtime = timespec[1].tv_sec;
+      /* Call 'utime', which is implemented below, not the MS library
+        function, which fails on directories.  */
+      return utime (file, &ut);
+    }
 }
 
 
@@ -3412,25 +3473,46 @@ sys_mkdir (const char * path)
   return _mkdir (map_w32_filename (path, NULL));
 }
 
-/* Because of long name mapping issues, we need to implement this
-   ourselves.  Also, MSVC's _mktemp returns NULL when it can't generate
-   a unique name, instead of setting the input template to an empty
-   string.
+int
+sys_open (const char * path, int oflag, int mode)
+{
+  const char* mpath = map_w32_filename (path, NULL);
+  int res = -1;
 
-   Standard algorithm seems to be use pid or tid with a letter on the
-   front (in place of the 6 X's) and cycle through the letters to find a
-   unique name.  We extend that to allow any reasonable character as the
-   first of the 6 X's.  */
-char *
-sys_mktemp (char * template)
+  /* If possible, try to open file without _O_CREAT, to be able to
+     write to existing hidden and system files.  Force all file
+     handles to be non-inheritable. */
+  if ((oflag & (_O_CREAT | _O_EXCL)) != (_O_CREAT | _O_EXCL))
+    res = _open (mpath, (oflag & ~_O_CREAT) | _O_NOINHERIT, mode);
+  if (res < 0)
+    res = _open (mpath, oflag | _O_NOINHERIT, mode);
+
+  return res;
+}
+
+/* Implementation of mkostemp for MS-Windows, to avoid race conditions
+   when using mktemp.
+
+   Standard algorithm for generating a temporary file name seems to be
+   use pid or tid with a letter on the front (in place of the 6 X's)
+   and cycle through the letters to find a unique name.  We extend
+   that to allow any reasonable character as the first of the 6 X's,
+   so that the number of simultaneously used temporary files will be
+   greater.  */
+
+int
+mkostemp (char * template, int flags)
 {
   char * p;
-  int i;
+  int i, fd = -1;
   unsigned uid = GetCurrentThreadId ();
+  int save_errno = errno;
   static char first_char[] = "abcdefghijklmnopqrstuvwyz0123456789!%-_@#";
 
+  errno = EINVAL;
   if (template == NULL)
-    return NULL;
+    return -1;
+
   p = template + strlen (template);
   i = 5;
   /* replace up to the last 5 X's with uid in decimal */
@@ -3445,38 +3527,22 @@ sys_mktemp (char * template)
       i = 0;
       do
        {
-         int save_errno = errno;
          p[0] = first_char[i];
-         if (faccessat (AT_FDCWD, template, F_OK, AT_EACCESS) < 0)
+         if ((fd = sys_open (template,
+                             flags | _O_CREAT | _O_EXCL | _O_RDWR,
+                             S_IRUSR | S_IWUSR)) >= 0
+             || errno != EEXIST)
            {
-             errno = save_errno;
-             return template;
+             if (fd >= 0)
+               errno = save_errno;
+             return fd;
            }
        }
       while (++i < sizeof (first_char));
     }
 
-  /* Template is badly formed or else we can't generate a unique name,
-     so return empty string */
-  template[0] = 0;
-  return template;
-}
-
-int
-sys_open (const char * path, int oflag, int mode)
-{
-  const char* mpath = map_w32_filename (path, NULL);
-  int res = -1;
-
-  /* If possible, try to open file without _O_CREAT, to be able to
-     write to existing hidden and system files.  Force all file
-     handles to be non-inheritable. */
-  if ((oflag & (_O_CREAT | _O_EXCL)) != (_O_CREAT | _O_EXCL))
-    res = _open (mpath, (oflag & ~_O_CREAT) | _O_NOINHERIT, mode);
-  if (res < 0)
-    res = _open (mpath, oflag | _O_NOINHERIT, mode);
-
-  return res;
+  /* Template is badly formed or else we can't generate a unique name.  */
+  return -1;
 }
 
 int
@@ -3785,12 +3851,6 @@ get_rid (PSID sid)
 
 /* Caching SID and account values for faster lokup.  */
 
-#ifdef __GNUC__
-# define FLEXIBLE_ARRAY_MEMBER
-#else
-# define FLEXIBLE_ARRAY_MEMBER 1
-#endif
-
 struct w32_id {
   unsigned rid;
   struct w32_id *next;
@@ -4486,6 +4546,9 @@ fstat (int desc, struct stat * buf)
   return 0;
 }
 
+/* A version of 'utime' which handles directories as well as
+   files.  */
+
 int
 utime (const char *name, struct utimbuf *times)
 {
@@ -5754,8 +5817,8 @@ system_process_attributes (Lisp_Object pid)
                {
                  /* Decode the command name from locale-specific
                     encoding.  */
-                 cmd_str = make_unibyte_string (pe.szExeFile,
-                                                strlen (pe.szExeFile));
+                 cmd_str = build_unibyte_string (pe.szExeFile);
+
                  decoded_cmd =
                    code_convert_string_norecord (cmd_str,
                                                  Vlocale_coding_system, 0);
@@ -6060,6 +6123,7 @@ term_winsock (void)
 {
   if (winsock_lib != NULL && winsock_inuse == 0)
     {
+      release_listen_threads ();
       /* Not sure what would cause WSAENETDOWN, or even if it can happen
         after WSAStartup returns successfully, but it seems reasonable
         to allow unloading winsock anyway in that case. */
@@ -6725,10 +6789,16 @@ sys_sendto (int s, const char * buf, int len, int flags,
 }
 
 /* Windows does not have an fcntl function.  Provide an implementation
-   solely for making sockets non-blocking.  */
+   good enough for Emacs.  */
 int
 fcntl (int s, int cmd, int options)
 {
+  /* In the w32 Emacs port, fcntl (fd, F_DUPFD_CLOEXEC, fd1) is always
+     invoked in a context where fd1 is closed and all descriptors less
+     than fd1 are open, so sys_dup is an adequate implementation.  */
+  if (cmd == F_DUPFD_CLOEXEC)
+    return sys_dup (s);
+
   if (winsock_lib == NULL)
     {
       errno = ENETDOWN;
@@ -6870,13 +6940,14 @@ sys_dup2 (int src, int dst)
   return rc;
 }
 
-/* Unix pipe() has only one arg */
 int
-sys_pipe (int * phandles)
+pipe2 (int * phandles, int pipe2_flags)
 {
   int rc;
   unsigned flags;
 
+  eassert (pipe2_flags == O_CLOEXEC);
+
   /* make pipe handles non-inheritable; when we spawn a child, we
      replace the relevant handle with an inheritable one.  Also put
      pipes into binary mode; we will do text mode translation ourselves
@@ -7037,7 +7108,12 @@ _sys_wait_accept (int fd)
   rc = pfn_WSAEventSelect (SOCK_HANDLE (fd), hEv, FD_ACCEPT);
   if (rc != SOCKET_ERROR)
     {
-      rc = WaitForSingleObject (hEv, INFINITE);
+      do {
+       rc = WaitForSingleObject (hEv, 500);
+       Sleep (5);
+      } while (rc == WAIT_TIMEOUT
+              && cp->status != STATUS_READ_ERROR
+              && cp->char_avail);
       pfn_WSAEventSelect (SOCK_HANDLE (fd), NULL, 0);
       if (rc == WAIT_OBJECT_0)
        cp->status = STATUS_READ_SUCCEEDED;
@@ -7387,6 +7463,269 @@ sys_write (int fd, const void * buffer, unsigned int count)
   return nchars;
 }
 
+\f
+/* Emulation of SIOCGIFCONF and getifaddrs, see process.c.  */
+
+extern Lisp_Object conv_sockaddr_to_lisp (struct sockaddr *, int);
+
+/* Return information about network interface IFNAME, or about all
+   interfaces (if IFNAME is nil).  */
+static Lisp_Object
+network_interface_get_info (Lisp_Object ifname)
+{
+  ULONG ainfo_len = sizeof (IP_ADAPTER_INFO);
+  IP_ADAPTER_INFO *adapter, *ainfo = xmalloc (ainfo_len);
+  DWORD retval = get_adapters_info (ainfo, &ainfo_len);
+  Lisp_Object res = Qnil;
+
+  if (retval == ERROR_BUFFER_OVERFLOW)
+    {
+      ainfo = xrealloc (ainfo, ainfo_len);
+      retval = get_adapters_info (ainfo, &ainfo_len);
+    }
+
+  if (retval == ERROR_SUCCESS)
+    {
+      int eth_count = 0, tr_count = 0, fddi_count = 0, ppp_count = 0;
+      int sl_count = 0, wlan_count = 0, lo_count = 0, ifx_count = 0;
+      int if_num;
+      struct sockaddr_in sa;
+
+      /* For the below, we need some winsock functions, so make sure
+        the winsock DLL is loaded.  If we cannot successfully load
+        it, they will have no use of the information we provide,
+        anyway, so punt.  */
+      if (!winsock_lib && !init_winsock (1))
+       goto done;
+
+      for (adapter = ainfo; adapter; adapter = adapter->Next)
+       {
+         char namebuf[MAX_ADAPTER_NAME_LENGTH + 4];
+         u_long ip_addr;
+         /* Present Unix-compatible interface names, instead of the
+            Windows names, which are really GUIDs not readable by
+            humans.  */
+         static const char *ifmt[] = {
+           "eth%d", "tr%d", "fddi%d", "ppp%d", "sl%d", "wlan%d",
+           "lo", "ifx%d"
+         };
+         enum {
+           NONE = -1,
+           ETHERNET = 0,
+           TOKENRING = 1,
+           FDDI = 2,
+           PPP = 3,
+           SLIP = 4,
+           WLAN = 5,
+           LOOPBACK = 6,
+           OTHER_IF = 7
+         } ifmt_idx;
+
+         switch (adapter->Type)
+           {
+           case MIB_IF_TYPE_ETHERNET:
+             /* Windows before Vista reports wireless adapters as
+                Ethernet.  Work around by looking at the Description
+                string.  */
+             if (strstr (adapter->Description, "Wireless "))
+               {
+                 ifmt_idx = WLAN;
+                 if_num = wlan_count++;
+               }
+             else
+               {
+                 ifmt_idx = ETHERNET;
+                 if_num = eth_count++;
+               }
+             break;
+           case MIB_IF_TYPE_TOKENRING:
+             ifmt_idx = TOKENRING;
+             if_num = tr_count++;
+             break;
+           case MIB_IF_TYPE_FDDI:
+             ifmt_idx = FDDI;
+             if_num = fddi_count++;
+             break;
+           case MIB_IF_TYPE_PPP:
+             ifmt_idx = PPP;
+             if_num = ppp_count++;
+             break;
+           case MIB_IF_TYPE_SLIP:
+             ifmt_idx = SLIP;
+             if_num = sl_count++;
+             break;
+           case IF_TYPE_IEEE80211:
+             ifmt_idx = WLAN;
+             if_num = wlan_count++;
+             break;
+           case MIB_IF_TYPE_LOOPBACK:
+             if (lo_count < 0)
+               {
+                 ifmt_idx = LOOPBACK;
+                 if_num = lo_count++;
+               }
+             else
+               ifmt_idx = NONE;
+             break;
+           default:
+             ifmt_idx = OTHER_IF;
+             if_num = ifx_count++;
+             break;
+           }
+         if (ifmt_idx == NONE)
+           continue;
+         sprintf (namebuf, ifmt[ifmt_idx], if_num);
+
+         sa.sin_family = AF_INET;
+         ip_addr = sys_inet_addr (adapter->IpAddressList.IpAddress.String);
+         if (ip_addr == INADDR_NONE)
+           {
+             /* Bogus address, skip this interface.  */
+             continue;
+           }
+         sa.sin_addr.s_addr = ip_addr;
+         sa.sin_port = 0;
+         if (NILP (ifname))
+           res = Fcons (Fcons (build_string (namebuf),
+                               conv_sockaddr_to_lisp ((struct sockaddr*) &sa,
+                                                      sizeof (struct sockaddr))),
+                        res);
+         else if (strcmp (namebuf, SSDATA (ifname)) == 0)
+           {
+             Lisp_Object hwaddr = Fmake_vector (make_number (6), Qnil);
+             register struct Lisp_Vector *p = XVECTOR (hwaddr);
+             Lisp_Object flags = Qnil;
+             int n;
+             u_long net_mask;
+
+             /* Flags.  We guess most of them by type, since the
+                Windows flags are different and hard to get by.  */
+             flags = Fcons (intern ("up"), flags);
+             if (ifmt_idx == ETHERNET || ifmt_idx == WLAN)
+               {
+                 flags = Fcons (intern ("broadcast"), flags);
+                 flags = Fcons (intern ("multicast"), flags);
+               }
+             flags = Fcons (intern ("running"), flags);
+             if (ifmt_idx == PPP)
+               {
+                 flags = Fcons (intern ("pointopoint"), flags);
+                 flags = Fcons (intern ("noarp"), flags);
+               }
+             if (adapter->HaveWins)
+               flags = Fcons (intern ("WINS"), flags);
+             if (adapter->DhcpEnabled)
+               flags = Fcons (intern ("dynamic"), flags);
+
+             res = Fcons (flags, res);
+
+             /* Hardware address and its family.  */
+             for (n = 0; n < adapter->AddressLength; n++)
+               p->contents[n] = make_number ((int) adapter->Address[n]);
+             /* Windows does not support AF_LINK or AF_PACKET family
+                of addresses.  Use an arbitrary family number that is
+                identical to what GNU/Linux returns.  */
+             res = Fcons (Fcons (make_number (1), hwaddr), res);
+
+             /* Network mask.  */
+             sa.sin_family = AF_INET;
+             net_mask = sys_inet_addr (adapter->IpAddressList.IpMask.String);
+             if (net_mask != INADDR_NONE)
+               {
+                 sa.sin_addr.s_addr = net_mask;
+                 sa.sin_port = 0;
+                 res = Fcons (conv_sockaddr_to_lisp ((struct sockaddr *) &sa,
+                                                     sizeof (struct sockaddr)),
+                              res);
+               }
+             else
+               res = Fcons (Qnil, res);
+
+             sa.sin_family = AF_INET;
+             if (ip_addr != INADDR_NONE)
+               {
+                 /* Broadcast address is only reported by
+                    GetAdaptersAddresses, which is of limited
+                    availability.  Generate it on our own.  */
+                 u_long bcast_addr = (ip_addr & net_mask) | ~net_mask;
+
+                 sa.sin_addr.s_addr = bcast_addr;
+                 sa.sin_port = 0;
+                 res = Fcons (conv_sockaddr_to_lisp ((struct sockaddr *) &sa,
+                                                     sizeof (struct sockaddr)),
+                              res);
+
+                 /* IP address.  */
+                 sa.sin_addr.s_addr = ip_addr;
+                 sa.sin_port = 0;
+                 res = Fcons (conv_sockaddr_to_lisp ((struct sockaddr *) &sa,
+                                                     sizeof (struct sockaddr)),
+                              res);
+               }
+             else
+               res = Fcons (Qnil, Fcons (Qnil, res));
+           }
+       }
+      /* GetAdaptersInfo is documented to not report loopback
+        interfaces, so we generate one out of thin air.  */
+      if (!lo_count)
+       {
+         sa.sin_family = AF_INET;
+         sa.sin_port = 0;
+         if (NILP (ifname))
+           {
+             sa.sin_addr.s_addr = sys_inet_addr ("127.0.0.1");
+             res = Fcons (Fcons (build_string ("lo"),
+                                 conv_sockaddr_to_lisp ((struct sockaddr*) &sa,
+                                                        sizeof (struct sockaddr))),
+                          res);
+           }
+         else if (strcmp (SSDATA (ifname), "lo") == 0)
+           {
+             res = Fcons (Fcons (intern ("running"),
+                                 Fcons (intern ("loopback"),
+                                        Fcons (intern ("up"), Qnil))), Qnil);
+             /* 772 is what 3 different GNU/Linux systems report for
+                the loopback interface.  */
+             res = Fcons (Fcons (make_number (772),
+                                 Fmake_vector (make_number (6),
+                                               make_number (0))),
+                          res);
+             sa.sin_addr.s_addr = sys_inet_addr ("255.0.0.0");
+             res = Fcons (conv_sockaddr_to_lisp ((struct sockaddr *) &sa,
+                                                 sizeof (struct sockaddr)),
+                          res);
+             sa.sin_addr.s_addr = sys_inet_addr ("0.0.0.0");
+             res = Fcons (conv_sockaddr_to_lisp ((struct sockaddr *) &sa,
+                                                 sizeof (struct sockaddr)),
+                          res);
+             sa.sin_addr.s_addr = sys_inet_addr ("127.0.0.1");
+             res = Fcons (conv_sockaddr_to_lisp ((struct sockaddr *) &sa,
+                                                 sizeof (struct sockaddr)),
+                          res);
+           }
+
+       }
+    }
+
+ done:
+  xfree (ainfo);
+  return res;
+}
+
+Lisp_Object
+network_interface_list (void)
+{
+  return network_interface_get_info (Qnil);
+}
+
+Lisp_Object
+network_interface_info (Lisp_Object ifname)
+{
+  return network_interface_get_info (ifname);
+}
+
+\f
 /* 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
@@ -7688,6 +8027,7 @@ globals_of_w32 (void)
   g_b_init_convert_sddl_to_sd = 0;
   g_b_init_is_valid_security_descriptor = 0;
   g_b_init_set_file_security = 0;
+  g_b_init_get_adapters_info = 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
@@ -7704,8 +8044,9 @@ globals_of_w32 (void)
 
 /* For make-serial-process  */
 int
-serial_open (char *port)
+serial_open (Lisp_Object port_obj)
 {
+  char *port = SSDATA (port_obj);
   HANDLE hnd;
   child_process *cp;
   int fd = -1;
@@ -7899,7 +8240,7 @@ emacs_gnutls_pull (gnutls_transport_ptr_t p, void* buf, size_t sz)
 {
   int n, err;
   SELECT_TYPE fdset;
-  EMACS_TIME timeout;
+  struct timespec timeout;
   struct Lisp_Process *process = (struct Lisp_Process *)p;
   int fd = process->infd;