Improve index entry. Remove redundant one.
[bpt/emacs.git] / src / w32.c
index 10b9127..9ad82c7 100644 (file)
--- a/src/w32.c
+++ b/src/w32.c
@@ -1,6 +1,6 @@
 /* Utility and Unix shadow routines for GNU Emacs on the Microsoft W32 API.
    Copyright (C) 1994, 1995, 2000, 2001, 2002, 2003, 2004,
-                 2005, 2006 Free Software Foundation, Inc.
+                 2005, 2006, 2007 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -32,6 +32,7 @@ Boston, MA 02110-1301, USA.
 #include <sys/file.h>
 #include <sys/time.h>
 #include <sys/utime.h>
+#include <mbstring.h>  /* for _mbspbrk */
 
 /* must include CRT headers *before* config.h */
 
@@ -153,7 +154,8 @@ typedef PSID_IDENTIFIER_AUTHORITY (WINAPI * GetSidIdentifierAuthority_Proc) (
     PSID pSid);
 
   /* ** A utility function ** */
-static BOOL is_windows_9x ()
+static BOOL
+is_windows_9x ()
 {
   static BOOL s_b_ret=0;
   OSVERSIONINFO os_ver;
@@ -323,6 +325,28 @@ w32_strerror (int 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.
+
+   This is called from alloc.c:valid_pointer_p.  */
+int
+w32_valid_pointer_p (void *p, int size)
+{
+  SIZE_T done;
+  HANDLE h = OpenProcess (PROCESS_VM_READ, FALSE, GetCurrentProcessId ());
+
+  if (h)
+    {
+      unsigned char *buf = alloca (size);
+      int retval = ReadProcessMemory (h, p, buf, size, &done);
+
+      CloseHandle (h);
+      return retval;
+    }
+  else
+    return -1;
+}
+
 static char startup_dir[MAXPATHLEN];
 
 /* Get the current working directory.  */
@@ -716,7 +740,7 @@ get_long_basename (char * name, char * buf, int size)
   int len = 0;
 
   /* must be valid filename, no wild cards or other invalid characters */
-  if (strpbrk (name, "*?|<>\""))
+  if (_mbspbrk (name, "*?|<>\""))
     return 0;
 
   dir_handle = FindFirstFile (name, &find_data);
@@ -791,7 +815,7 @@ is_unc_volume (const char *filename)
   if (!IS_DIRECTORY_SEP (ptr[0]) || !IS_DIRECTORY_SEP (ptr[1]) || !ptr[2])
     return 0;
 
-  if (strpbrk (ptr + 2, "*?|<>\"\\/"))
+  if (_mbspbrk (ptr + 2, "*?|<>\"\\/"))
     return 0;
 
   return 1;
@@ -2256,16 +2280,17 @@ convert_time (FILETIME ft)
 
       SystemTimeToFileTime (&st, &utc_base_ft);
       utc_base = (long double) utc_base_ft.dwHighDateTime
-       * 4096 * 1024 * 1024 + utc_base_ft.dwLowDateTime;
+       * 4096.0L * 1024.0L * 1024.0L + utc_base_ft.dwLowDateTime;
       init = 1;
     }
 
   if (CompareFileTime (&ft, &utc_base_ft) < 0)
     return 0;
 
-  ret = (long double) ft.dwHighDateTime * 4096 * 1024 * 1024 + ft.dwLowDateTime;
+  ret = (long double) ft.dwHighDateTime
+    * 4096.0L * 1024.0L * 1024.0L + ft.dwLowDateTime;
   ret -= utc_base;
-  return (time_t) (ret * 1e-7);
+  return (time_t) (ret * 1e-7L);
 }
 
 void
@@ -2362,8 +2387,12 @@ stat (const char * path, struct stat * buf)
     }
 
   name = (char *) map_w32_filename (path, &path);
-  /* must be valid filename, no wild cards or other invalid characters */
-  if (strpbrk (name, "*?|<>\""))
+  /* Must be valid filename, no wild cards or other invalid
+     characters.  We use _mbspbrk to support multibyte strings that
+     might look to strpbrk as if they included literal *, ?, and other
+     characters mentioned below that are disallowed by Windows
+     filesystems.  */
+  if (_mbspbrk (name, "*?|<>\""))
     {
       errno = ENOENT;
       return -1;
@@ -2701,6 +2730,8 @@ int (PASCAL *pfn_WSAStartup) (WORD wVersionRequired, LPWSADATA lpWSAData);
 void (PASCAL *pfn_WSASetLastError) (int iError);
 int (PASCAL *pfn_WSAGetLastError) (void);
 int (PASCAL *pfn_WSAEventSelect) (SOCKET s, HANDLE hEventObject, long lNetworkEvents);
+HANDLE (PASCAL *pfn_WSACreateEvent) (void);
+int (PASCAL *pfn_WSACloseEvent) (HANDLE hEvent);
 int (PASCAL *pfn_socket) (int af, int type, int protocol);
 int (PASCAL *pfn_bind) (SOCKET s, const struct sockaddr *addr, int namelen);
 int (PASCAL *pfn_connect) (SOCKET s, const struct sockaddr *addr, int namelen);
@@ -2770,7 +2801,7 @@ init_winsock (int load_now)
     = (void *) GetProcAddress (GetModuleHandle ("kernel32.dll"),
                               "SetHandleInformation");
 
-  winsock_lib = LoadLibrary ("wsock32.dll");
+  winsock_lib = LoadLibrary ("Ws2_32.dll");
 
   if (winsock_lib != NULL)
     {
@@ -2784,6 +2815,8 @@ init_winsock (int load_now)
       LOAD_PROC( WSASetLastError );
       LOAD_PROC( WSAGetLastError );
       LOAD_PROC( WSAEventSelect );
+      LOAD_PROC( WSACreateEvent );
+      LOAD_PROC( WSACloseEvent );
       LOAD_PROC( socket );
       LOAD_PROC( bind );
       LOAD_PROC( connect );
@@ -2844,7 +2877,8 @@ int h_errno = 0;
 /* function to set h_errno for compatability; map winsock error codes to
    normal system codes where they overlap (non-overlapping definitions
    are already in <sys/socket.h> */
-static void set_errno ()
+static void
+set_errno ()
 {
   if (winsock_lib == NULL)
     h_errno = EINVAL;
@@ -2865,7 +2899,8 @@ static void set_errno ()
   errno = h_errno;
 }
 
-static void check_errno ()
+static void
+check_errno ()
 {
   if (h_errno == 0 && winsock_lib != NULL)
     pfn_WSASetLastError (0);
@@ -3298,10 +3333,7 @@ sys_listen (int s, int backlog)
       if (rc == SOCKET_ERROR)
        set_errno ();
       else
-       {
-         fd_info[s].flags |= FILE_LISTEN;
-         pfn_WSAEventSelect (SOCK_HANDLE (s), fd_info[s].cp->char_avail, FD_ACCEPT);
-       }
+       fd_info[s].flags |= FILE_LISTEN;
       return rc;
     }
   h_errno = ENOTSOCK;
@@ -3342,16 +3374,15 @@ sys_accept (int s, struct sockaddr * addr, int * addrlen)
   if (fd_info[s].flags & FILE_LISTEN)
     {
       SOCKET t = pfn_accept (SOCK_HANDLE (s), addr, addrlen);
-      if (t != INVALID_SOCKET)
-       {
-         int fd = socket_to_fd (t);
-         if (fd >= 0)
-           pfn_WSAEventSelect (SOCK_HANDLE (fd), fd_info[fd].cp->char_avail, FD_READ | FD_CLOSE);
-         return fd;
-       }
+      int fd = -1;
+      if (t == INVALID_SOCKET)
+       set_errno ();
+      else
+       fd = socket_to_fd (t);
 
-      set_errno ();
-      return -1;
+      fd_info[s].cp->status = STATUS_READ_ACKNOWLEDGED;
+      ResetEvent (fd_info[s].cp->char_avail);
+      return fd;
     }
   h_errno = ENOTSOCK;
   return -1;
@@ -3653,6 +3684,37 @@ _sys_read_ahead (int fd)
   return cp->status;
 }
 
+int
+_sys_wait_accept (int fd)
+{
+  HANDLE hEv;
+  child_process * cp;
+  int rc;
+
+  if (fd < 0 || fd >= MAXDESC)
+    return STATUS_READ_ERROR;
+
+  cp = fd_info[fd].cp;
+
+  if (cp == NULL || cp->fd != fd || cp->status != STATUS_READ_READY)
+    return STATUS_READ_ERROR;
+
+  cp->status = STATUS_READ_FAILED;
+
+  hEv = pfn_WSACreateEvent ();
+  rc = pfn_WSAEventSelect (SOCK_HANDLE (fd), hEv, FD_ACCEPT);
+  if (rc != SOCKET_ERROR)
+    {
+      rc = WaitForSingleObject (hEv, INFINITE);
+      pfn_WSAEventSelect (SOCK_HANDLE (fd), NULL, 0);
+      if (rc == WAIT_OBJECT_0)
+       cp->status = STATUS_READ_SUCCEEDED;
+    }
+  pfn_WSACloseEvent (hEv);
+
+  return cp->status;
+}
+
 int
 sys_read (int fd, char * buffer, unsigned int count)
 {
@@ -4059,18 +4121,43 @@ init_ntproc ()
   check_windows_init_file ();
 }
 
+/*
+        shutdown_handler ensures that buffers' autosave files are
+       up to date when the user logs off, or the system shuts down.
+*/
+BOOL WINAPI shutdown_handler(DWORD type)
+{
+  /* Ctrl-C and Ctrl-Break are already suppressed, so don't handle them.  */
+  if (type == CTRL_CLOSE_EVENT        /* User closes console window.  */
+      || type == CTRL_LOGOFF_EVENT    /* User logs off.  */
+      || type == CTRL_SHUTDOWN_EVENT) /* User shutsdown.  */
+    {
+      /* Shut down cleanly, making sure autosave files are up to date.  */
+      shut_down_emacs (0, 0, Qnil);
+    }
+
+  /* Allow other handlers to handle this signal.  */
+  return FALSE;
+}
+
 /*
        globals_of_w32 is used to initialize those global variables that
        must always be initialized on startup even when the global variable
        initialized is non zero (see the function main in emacs.c).
 */
-void globals_of_w32 ()
+void
+globals_of_w32 ()
 {
   g_b_init_is_windows_9x = 0;
   g_b_init_open_process_token = 0;
   g_b_init_get_token_information = 0;
   g_b_init_lookup_account_sid = 0;
   g_b_init_get_sid_identifier_authority = 0;
+  /* The following sets a handler for shutdown notifications for
+     console apps. This actually applies to Emacs in both console and
+     GUI modes, since we had to fool windows into thinking emacs is a
+     console application to get console mode to work.  */
+  SetConsoleCtrlHandler(shutdown_handler, TRUE);
 }
 
 /* end of nt.c */