(WIN32_KEY_SHIFTED): Macro undefined.
[bpt/emacs.git] / src / w32.c
index 2a091d4..600d308 100644 (file)
--- a/src/w32.c
+++ b/src/w32.c
@@ -1,25 +1,63 @@
 /* Utility and Unix shadow routines for GNU Emacs on Windows NT.
-   Copyright (C) 1994 Free Software Foundation, Inc.
+   Copyright (C) 1994, 1995 Free Software Foundation, Inc.
 
-   This file is part of GNU Emacs.
+This file is part of GNU Emacs.
 
-   GNU Emacs is free software; you can redistribute it and/or modify it
-   under the terms of the GNU General Public License as published by the
-   Free Software Foundation; either version 1, or (at your option) any later
-   version.
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
 
-   GNU Emacs is distributed in the hope that it will be useful, but WITHOUT
-   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-   more details.
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
 
-   You should have received a copy of the GNU General Public License along
-   with GNU Emacs; see the file COPYING.  If not, write to the Free Software
-   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+You should have received a copy of the GNU General Public License
+along with GNU Emacs; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
 
    Geoff Voelker (voelker@cs.washington.edu)                         7-29-94
 */
 
+/* Define stat before including config.h.  */
+#include <string.h>
+#include <sys/stat.h>
+int
+nt_stat (char *filename, struct stat *statbuf)
+{
+  int r, l = strlen (filename);
+  char *str = NULL;
+  extern long *xmalloc ();
+  extern void xfree ();
+
+  /* stat has a bug when passed a name of a directory with a trailing
+     backslash (but a trailing forward slash works fine).  */
+  if (filename[l - 1] == '\\') 
+    {
+      str = (char *) xmalloc (l + 1);
+      strcpy (str, filename);
+      str[l - 1] = '/';
+      r = stat (str, statbuf);
+      xfree (str);
+      return r;
+    }
+  else
+    return stat (filename, statbuf);
+}
+
+/* Place a wrapper around the NT version of ctime.  It returns NULL
+   on network directories, so we handle that case here.  
+   Define it before including config.h.  (Ulrich Leodolter, 1/11/95).  */
+char *
+nt_ctime (const time_t *t)
+{
+  char *str = (char *) ctime (t);
+  return (str ? str : "Sun Jan 01 00:00:00 1970");
+}
+
+#include <config.h>
 #include <windows.h>
 #include <stdlib.h>
 #include <stdio.h>
@@ -27,7 +65,6 @@
 #include <fcntl.h>
 #include <ctype.h>
 
-#include "config.h"
 #define getwd _getwd
 #include "lisp.h"
 #undef getwd
@@ -153,15 +190,6 @@ readdir (DIR *dirp)
        return NULL;
     }
   
-  /* Don't return . or .. since it doesn't look like any of the
-     readdir calling code expects them.  */
-  while (strcmp (find_data.cFileName, ".") == 0
-        || strcmp (find_data.cFileName, "..") == 0)
-    {
-      if (!FindNextFile (dir_find_handle, &find_data))
-       return 0;
-    }
-  
   /* NT's unique ID for a file is 64 bits, so we have to fake it here.  
      This should work as long as we never use 0.  */
   dir_static.d_ino = 1;
@@ -179,11 +207,13 @@ readdir (DIR *dirp)
 
 int getuid (); /* forward declaration */
 
-static char the_passwd_name[256];
-static char the_passwd_passwd[256];
-static char the_passwd_gecos[256];
-static char the_passwd_dir[256];
-static char the_passwd_shell[256];
+#define PASSWD_FIELD_SIZE 256
+
+static char the_passwd_name[PASSWD_FIELD_SIZE];
+static char the_passwd_passwd[PASSWD_FIELD_SIZE];
+static char the_passwd_gecos[PASSWD_FIELD_SIZE];
+static char the_passwd_dir[PASSWD_FIELD_SIZE];
+static char the_passwd_shell[PASSWD_FIELD_SIZE];
 
 static struct passwd the_passwd = 
 {
@@ -200,7 +230,7 @@ static struct passwd the_passwd =
 struct passwd *
 getpwuid (int uid)
 {
-  int size = 256;
+  int size = PASSWD_FIELD_SIZE;
   
   if (!GetUserName (the_passwd.pw_name, &size))
     return NULL;
@@ -236,43 +266,62 @@ getpwnam (char *name)
    user enter it, so we define EMACS_CONFIGURATION to invoke this runtime
    routine.  */
 
-static char configuration_buffer[16];
+static char configuration_buffer[32];
 
 char *
 get_emacs_configuration (void)
 {
-    char *arch, *oem;
+  char *arch, *oem, *os;
 
-    /* Determine the processor type.  */
-    switch (get_processor_type ()) 
-      {
-      case PROCESSOR_INTEL_386:
-      case PROCESSOR_INTEL_486:
-      case PROCESSOR_INTEL_PENTIUM:
-       arch = "i386";
-       break;
-      case PROCESSOR_INTEL_860:
-       arch = "i860";
-       break;
-      case PROCESSOR_MIPS_R2000:
-      case PROCESSOR_MIPS_R3000:
-      case PROCESSOR_MIPS_R4000:
-       arch = "mips";
-       break;
-      case PROCESSOR_ALPHA_21064:
-       arch = "alpha";
-       break;
-      default:
-       arch = "unknown";
-       break;
-      }
-
-    /* Let oem be "*" until we figure out how to decode the OEM field.  */
-    oem = "*";
-
-    sprintf (configuration_buffer, "%s-%s-nt%d.%d", arch, oem,
-            get_nt_major_version (), get_nt_minor_version ());
-    return configuration_buffer;
+  /* Determine the processor type.  */
+  switch (get_processor_type ()) 
+    {
+
+#ifdef PROCESSOR_INTEL_386
+    case PROCESSOR_INTEL_386:
+    case PROCESSOR_INTEL_486:
+    case PROCESSOR_INTEL_PENTIUM:
+      arch = "i386";
+      break;
+#endif
+
+#ifdef PROCESSOR_INTEL_860
+    case PROCESSOR_INTEL_860:
+      arch = "i860";
+      break;
+#endif
+
+#ifdef PROCESSOR_MIPS_R2000
+    case PROCESSOR_MIPS_R2000:
+    case PROCESSOR_MIPS_R3000:
+    case PROCESSOR_MIPS_R4000:
+      arch = "mips";
+      break;
+#endif
+
+#ifdef PROCESSOR_ALPHA_21064
+    case PROCESSOR_ALPHA_21064:
+      arch = "alpha";
+      break;
+#endif
+
+    default:
+      arch = "unknown";
+      break;
+    }
+
+  /* Let oem be "*" until we figure out how to decode the OEM field.  */
+  oem = "*";
+
+#ifdef WINDOWS95
+  os = "win";
+#else
+  os = "nt";
+#endif
+
+  sprintf (configuration_buffer, "%s-%s-%s%d.%d", arch, oem, os,
+          get_nt_major_version (), get_nt_minor_version ());
+  return configuration_buffer;
 }
 
 /* Conjure up inode and device numbers that will serve the purpose
@@ -290,8 +339,23 @@ get_inode_and_device_vals (Lisp_Object filename, Lisp_Object *p_inode,
 
   HANDLE handle;
   BOOL result;
+  DWORD attrs;
   BY_HANDLE_FILE_INFORMATION info;
 
+  /* We have to stat files and directories differently, so check
+     to see what filename references.  */
+  attrs = GetFileAttributes (XSTRING (filename)->data);
+  if (attrs == 0xFFFFFFFF) {
+    return 0;
+  }
+  if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
+    /* Conjure up bogus, but unique, values.  */
+    attrs = GetTickCount ();
+    *p_inode = make_number (attrs);
+    *p_device = make_number (attrs);
+    return 1;
+  }
+
   /* FIXME:  It shouldn't be opened without READ access, but NT on x86
      doesn't allow GetFileInfo in that case (NT on mips does).  */
      
@@ -380,8 +444,22 @@ void
 prepare_standard_handles (int in, int out, int err, HANDLE handles[4])
 {
   HANDLE parent, stdin_save, stdout_save, stderr_save, err_handle;
-  
+
+#ifdef WINDOWS95
+  /* The Win95 beta doesn't set the standard handles correctly.
+     Handicap subprocesses until we get a version that works correctly.  
+     Undefining the subprocesses macro reveals other incompatibilities,
+     so, since we're expecting subprocs to work in the near future, 
+     disable them here.  */
+  report_file_error ("Subprocesses currently disabled on Win95", Qnil);
+#endif
+
   parent = GetCurrentProcess ();
+  stdin_save = GetStdHandle (STD_INPUT_HANDLE);
+  stdout_save = GetStdHandle (STD_OUTPUT_HANDLE);
+  stderr_save = GetStdHandle (STD_ERROR_HANDLE);
+
+#ifndef HAVE_NTGUI
   if (!DuplicateHandle (parent, 
                       GetStdHandle (STD_INPUT_HANDLE), 
                       parent,
@@ -408,6 +486,7 @@ prepare_standard_handles (int in, int out, int err, HANDLE handles[4])
                       FALSE,
                       DUPLICATE_SAME_ACCESS))
     report_file_error ("Duplicating parent's error handle", Qnil);
+#endif /* !HAVE_NTGUI */
   
   if (!SetStdHandle (STD_INPUT_HANDLE, (HANDLE) _get_osfhandle (in)))
     report_file_error ("Changing stdin handle", Qnil);
@@ -450,15 +529,21 @@ reset_standard_handles (int in, int out, int err, HANDLE handles[4])
   HANDLE stdout_save = handles[1];
   HANDLE stderr_save = handles[2];
   HANDLE err_handle = handles[3];
-  
+  int i;
+
+#ifndef HAVE_NTGUI
   if (!SetStdHandle (STD_INPUT_HANDLE, stdin_save))
     report_file_error ("Resetting input handle", Qnil);
   
   if (!SetStdHandle (STD_OUTPUT_HANDLE, stdout_save))
-    report_file_error ("Resetting output handle", Qnil);
+    {
+      i = GetLastError ();
+      report_file_error ("Resetting output handle", Qnil);
+    }
   
   if (!SetStdHandle (STD_ERROR_HANDLE, stderr_save))
     report_file_error ("Resetting error handle", Qnil);
+#endif /* !HAVE_NTGUI */
   
   if (out == err) 
     {
@@ -470,6 +555,19 @@ reset_standard_handles (int in, int out, int err, HANDLE handles[4])
     }
 }
 
+int
+random ()
+{
+  /* rand () on NT gives us 15 random bits...hack together 30 bits.  */
+  return ((rand () << 15) | rand ());
+}
+
+void
+srandom (int seed)
+{
+  srand (seed);
+}
+
 /* Destructively turn backslashes into slashes.  */
 void
 dostounix_filename (p)
@@ -531,13 +629,27 @@ request_sigio (void)
 int 
 getuid () 
 { 
-  return 0; 
+  char buffer[256];
+  int size = 256;
+
+  if (!GetUserName (buffer, &size))
+    /* Assume all powers upon failure.  */
+    return 0;
+
+  if (!stricmp ("administrator", buffer))
+    return 0;
+  else
+    /* A complete fabrication...is there anything to base it on? */
+    return 123;
 }
 
 int 
 geteuid () 
 { 
-  return 0; 
+  /* I could imagine arguing for checking to see whether the user is
+     in the Administrators group and returning a UID of 0 for that
+     case, but I don't know how wise that would be in the long run.  */
+  return getuid (); 
 }
 
 /* Remove all CR's that are followed by a LF.
@@ -569,6 +681,129 @@ crlf_to_lf (n, buf)
   return np - startp;
 }
 
+#define REG_ROOT "SOFTWARE\\GNU\\Emacs\\"
+
+LPBYTE 
+nt_get_resource (key, lpdwtype)
+    char *key;
+    LPDWORD lpdwtype;
+{
+  LPBYTE lpvalue;
+  HKEY hrootkey = NULL;
+  DWORD cbData;
+  BOOL ok = FALSE;
+  
+  /* Check both the current user and the local machine to see if 
+     we have any resources.  */
+  
+  if (RegOpenKeyEx (HKEY_CURRENT_USER, REG_ROOT, 0, KEY_READ, &hrootkey) == ERROR_SUCCESS)
+    {
+      lpvalue = NULL;
+
+      if (RegQueryValueEx (hrootkey, key, NULL, NULL, NULL, &cbData) == ERROR_SUCCESS 
+         && (lpvalue = (LPBYTE) xmalloc (cbData)) != NULL 
+         && RegQueryValueEx (hrootkey, key, NULL, lpdwtype, lpvalue, &cbData) == ERROR_SUCCESS)
+       {
+         return (lpvalue);
+       }
+
+      if (lpvalue) xfree (lpvalue);
+       
+      RegCloseKey (hrootkey);
+    } 
+  
+  if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, REG_ROOT, 0, KEY_READ, &hrootkey) == ERROR_SUCCESS)
+    {
+      lpvalue = NULL;
+       
+      if (RegQueryValueEx (hrootkey, key, NULL, NULL, NULL, &cbData) == ERROR_SUCCESS &&
+         (lpvalue = (LPBYTE) xmalloc (cbData)) != NULL &&
+         RegQueryValueEx (hrootkey, key, NULL, lpdwtype, lpvalue, &cbData) == ERROR_SUCCESS)
+       {
+         return (lpvalue);
+       }
+       
+      if (lpvalue) xfree (lpvalue);
+       
+      RegCloseKey (hrootkey);
+    } 
+  
+  return (NULL);
+}
+
+void
+init_environment ()
+{
+  /* Open a console window to display messages during dumping. */
+  if (!initialized)
+    AllocConsole ();
+
+  /* Check for environment variables and use registry if they don't exist */
+  {
+      int i;
+      LPBYTE lpval;
+      DWORD dwType;
+
+      static char * env_vars[] = 
+      {
+         "emacs_path",
+         "EMACSLOADPATH",
+         "SHELL",
+         "EMACSDATA",
+         "EMACSPATH",
+         "EMACSLOCKDIR",
+         "INFOPATH",
+         "EMACSDOC",
+         "TERM",
+      };
+
+      for (i = 0; i < (sizeof (env_vars) / sizeof (env_vars[0])); i++) 
+       {
+         if (!getenv (env_vars[i]) &&
+             (lpval = nt_get_resource (env_vars[i], &dwType)) != NULL)
+           {
+             if (dwType == REG_EXPAND_SZ)
+               {
+                 char buf1[500], buf2[500];
+
+                 ExpandEnvironmentStrings ((LPSTR) lpval, buf1, 500);
+                 _snprintf (buf2, 499, "%s=%s", env_vars[i], buf1);
+                 putenv (strdup (buf2));
+               }
+             else if (dwType == REG_SZ)
+               {
+                 char buf[500];
+                 
+                 _snprintf (buf, 499, "%s=%s", env_vars[i], lpval);
+                 putenv (strdup (buf));
+               }
+
+             xfree (lpval);
+           }
+       }
+    }
+}
+
+#ifdef HAVE_TIMEVAL
+#include <sys/timeb.h>
+
+/* Emulate gettimeofday (Ulrich Leodolter, 1/11/95).  */
+void 
+gettimeofday (struct timeval *tv, struct timezone *tz)
+{
+  struct _timeb tb;
+  _ftime (&tb);
+
+  tv->tv_sec = tb.time;
+  tv->tv_usec = tb.millitm * 1000L;
+  if (tz) 
+    {
+      tz->tz_minuteswest = tb.timezone;        /* minutes west of Greenwich  */
+      tz->tz_dsttime = tb.dstflag;     /* type of dst correction  */
+    }
+}
+#endif /* HAVE_TIMEVAL */
+
 
 #ifdef PIGSFLY
 Keep this around...we might need it later.
@@ -585,25 +820,25 @@ Keep this around...we might need it later.
   SID_NAME_USE    User;
 
   if (1)
-    Vuser_real_name = build_string ("foo");
+    Vuser_real_login_name = build_string ("foo");
   else if (!OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &Token))
     {
-      Vuser_real_name = build_string ("unknown");
+      Vuser_real_login_name = build_string ("unknown");
     }
   else if (!GetTokenInformation (Token, TokenUser, (PVOID)b, 256,
                                 &trash))
     {
       CloseHandle (Token);
-      Vuser_real_name = build_string ("unknown");
+      Vuser_real_login_name = build_string ("unknown");
     }
   else if (!LookupAccountSid ((void *)0, (PSID)b, Name, &length, RefD,
                              &rlength, &User))
     {
       CloseHandle (Token);
-      Vuser_real_name = build_string ("unknown");
+      Vuser_real_login_name = build_string ("unknown");
     }
   else
-    Vuser_real_name = build_string (Name);
+    Vuser_real_login_name = build_string (Name);
 }
 #else   /* not WINDOWSNT */
 #endif  /* not WINDOWSNT */