1/* Utility and Unix shadow routines for GNU Emacs on the Microsoft W32 API.
2   Copyright (C) 1994, 1995, 2000, 2001, 2002, 2003, 2004,
3                 2005, 2006, 2007 Free Software Foundation, Inc.
4
5This file is part of GNU Emacs.
6
7GNU Emacs is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Emacs; see the file COPYING.  If not, write to
19the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20Boston, MA 02110-1301, USA.
21
22   Geoff Voelker (voelker@cs.washington.edu)                         7-29-94
23*/
24#include <stddef.h> /* for offsetof */
25#include <stdlib.h>
26#include <stdio.h>
27#include <io.h>
28#include <errno.h>
29#include <fcntl.h>
30#include <ctype.h>
31#include <signal.h>
32#include <sys/file.h>
33#include <sys/time.h>
34#include <sys/utime.h>
35#include <mbstring.h>	/* for _mbspbrk */
36
37/* must include CRT headers *before* config.h */
38
39#ifdef HAVE_CONFIG_H
40#include <config.h>
41#endif
42
43#undef access
44#undef chdir
45#undef chmod
46#undef creat
47#undef ctime
48#undef fopen
49#undef link
50#undef mkdir
51#undef mktemp
52#undef open
53#undef rename
54#undef rmdir
55#undef unlink
56
57#undef close
58#undef dup
59#undef dup2
60#undef pipe
61#undef read
62#undef write
63
64#undef strerror
65
66#include "lisp.h"
67
68#include <pwd.h>
69#include <grp.h>
70
71#ifdef __GNUC__
72#define _ANONYMOUS_UNION
73#define _ANONYMOUS_STRUCT
74#endif
75#include <windows.h>
76#include <shlobj.h>
77
78#ifdef HAVE_SOCKETS	/* TCP connection support, if kernel can do it */
79#include <sys/socket.h>
80#undef socket
81#undef bind
82#undef connect
83#undef htons
84#undef ntohs
85#undef inet_addr
86#undef gethostname
87#undef gethostbyname
88#undef getservbyname
89#undef getpeername
90#undef shutdown
91#undef setsockopt
92#undef listen
93#undef getsockname
94#undef accept
95#undef recvfrom
96#undef sendto
97#endif
98
99#include "w32.h"
100#include "ndir.h"
101#include "w32heap.h"
102#include "systime.h"
103
104typedef HRESULT (WINAPI * ShGetFolderPath_fn)
105  (IN HWND, IN int, IN HANDLE, IN DWORD, OUT char *);
106
107void globals_of_w32 ();
108
109extern Lisp_Object Vw32_downcase_file_names;
110extern Lisp_Object Vw32_generate_fake_inodes;
111extern Lisp_Object Vw32_get_true_file_attributes;
112extern int w32_num_mouse_buttons;
113
114
115/*
116	Initialization states
117 */
118static BOOL g_b_init_is_windows_9x;
119static BOOL g_b_init_open_process_token;
120static BOOL g_b_init_get_token_information;
121static BOOL g_b_init_lookup_account_sid;
122static BOOL g_b_init_get_sid_identifier_authority;
123
124/*
125  BEGIN: Wrapper functions around OpenProcessToken
126  and other functions in advapi32.dll that are only
127  supported in Windows NT / 2k / XP
128*/
129  /* ** Function pointer typedefs ** */
130typedef BOOL (WINAPI * OpenProcessToken_Proc) (
131    HANDLE ProcessHandle,
132    DWORD DesiredAccess,
133    PHANDLE TokenHandle);
134typedef BOOL (WINAPI * GetTokenInformation_Proc) (
135    HANDLE TokenHandle,
136    TOKEN_INFORMATION_CLASS TokenInformationClass,
137    LPVOID TokenInformation,
138    DWORD TokenInformationLength,
139    PDWORD ReturnLength);
140#ifdef _UNICODE
141const char * const LookupAccountSid_Name = "LookupAccountSidW";
142#else
143const char * const LookupAccountSid_Name = "LookupAccountSidA";
144#endif
145typedef BOOL (WINAPI * LookupAccountSid_Proc) (
146    LPCTSTR lpSystemName,
147    PSID Sid,
148    LPTSTR Name,
149    LPDWORD cbName,
150    LPTSTR DomainName,
151    LPDWORD cbDomainName,
152    PSID_NAME_USE peUse);
153typedef PSID_IDENTIFIER_AUTHORITY (WINAPI * GetSidIdentifierAuthority_Proc) (
154    PSID pSid);
155
156  /* ** A utility function ** */
157static BOOL
158is_windows_9x ()
159{
160  static BOOL s_b_ret=0;
161  OSVERSIONINFO os_ver;
162  if (g_b_init_is_windows_9x == 0)
163    {
164      g_b_init_is_windows_9x = 1;
165      ZeroMemory(&os_ver, sizeof(OSVERSIONINFO));
166      os_ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
167      if (GetVersionEx (&os_ver))
168        {
169          s_b_ret = (os_ver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS);
170        }
171    }
172  return s_b_ret;
173}
174
175  /* ** The wrapper functions ** */
176
177BOOL WINAPI open_process_token (
178    HANDLE ProcessHandle,
179    DWORD DesiredAccess,
180    PHANDLE TokenHandle)
181{
182  static OpenProcessToken_Proc s_pfn_Open_Process_Token = NULL;
183  HMODULE hm_advapi32 = NULL;
184  if (is_windows_9x () == TRUE)
185    {
186      return FALSE;
187    }
188  if (g_b_init_open_process_token == 0)
189    {
190      g_b_init_open_process_token = 1;
191      hm_advapi32 = LoadLibrary ("Advapi32.dll");
192      s_pfn_Open_Process_Token =
193        (OpenProcessToken_Proc) GetProcAddress (hm_advapi32, "OpenProcessToken");
194    }
195  if (s_pfn_Open_Process_Token == NULL)
196    {
197      return FALSE;
198    }
199  return (
200      s_pfn_Open_Process_Token (
201          ProcessHandle,
202          DesiredAccess,
203          TokenHandle)
204      );
205}
206
207BOOL WINAPI get_token_information (
208    HANDLE TokenHandle,
209    TOKEN_INFORMATION_CLASS TokenInformationClass,
210    LPVOID TokenInformation,
211    DWORD TokenInformationLength,
212    PDWORD ReturnLength)
213{
214  static GetTokenInformation_Proc s_pfn_Get_Token_Information = NULL;
215  HMODULE hm_advapi32 = NULL;
216  if (is_windows_9x () == TRUE)
217    {
218      return FALSE;
219    }
220  if (g_b_init_get_token_information == 0)
221    {
222      g_b_init_get_token_information = 1;
223      hm_advapi32 = LoadLibrary ("Advapi32.dll");
224      s_pfn_Get_Token_Information =
225        (GetTokenInformation_Proc) GetProcAddress (hm_advapi32, "GetTokenInformation");
226    }
227  if (s_pfn_Get_Token_Information == NULL)
228    {
229      return FALSE;
230    }
231  return (
232      s_pfn_Get_Token_Information (
233          TokenHandle,
234          TokenInformationClass,
235          TokenInformation,
236          TokenInformationLength,
237          ReturnLength)
238      );
239}
240
241BOOL WINAPI lookup_account_sid (
242    LPCTSTR lpSystemName,
243    PSID Sid,
244    LPTSTR Name,
245    LPDWORD cbName,
246    LPTSTR DomainName,
247    LPDWORD cbDomainName,
248    PSID_NAME_USE peUse)
249{
250  static LookupAccountSid_Proc s_pfn_Lookup_Account_Sid = NULL;
251  HMODULE hm_advapi32 = NULL;
252  if (is_windows_9x () == TRUE)
253    {
254      return FALSE;
255    }
256  if (g_b_init_lookup_account_sid == 0)
257    {
258      g_b_init_lookup_account_sid = 1;
259      hm_advapi32 = LoadLibrary ("Advapi32.dll");
260      s_pfn_Lookup_Account_Sid =
261        (LookupAccountSid_Proc) GetProcAddress (hm_advapi32, LookupAccountSid_Name);
262    }
263  if (s_pfn_Lookup_Account_Sid == NULL)
264    {
265      return FALSE;
266    }
267  return (
268      s_pfn_Lookup_Account_Sid (
269          lpSystemName,
270          Sid,
271          Name,
272          cbName,
273          DomainName,
274          cbDomainName,
275          peUse)
276      );
277}
278
279PSID_IDENTIFIER_AUTHORITY WINAPI get_sid_identifier_authority (
280    PSID pSid)
281{
282  static GetSidIdentifierAuthority_Proc s_pfn_Get_Sid_Identifier_Authority = NULL;
283  HMODULE hm_advapi32 = NULL;
284  if (is_windows_9x () == TRUE)
285    {
286      return NULL;
287    }
288  if (g_b_init_get_sid_identifier_authority == 0)
289    {
290      g_b_init_get_sid_identifier_authority = 1;
291      hm_advapi32 = LoadLibrary ("Advapi32.dll");
292      s_pfn_Get_Sid_Identifier_Authority =
293        (GetSidIdentifierAuthority_Proc) GetProcAddress (
294            hm_advapi32, "GetSidIdentifierAuthority");
295    }
296  if (s_pfn_Get_Sid_Identifier_Authority == NULL)
297    {
298      return NULL;
299    }
300  return (s_pfn_Get_Sid_Identifier_Authority (pSid));
301}
302
303/*
304  END: Wrapper functions around OpenProcessToken
305  and other functions in advapi32.dll that are only
306  supported in Windows NT / 2k / XP
307*/
308
309
310/* Equivalent of strerror for W32 error codes.  */
311char *
312w32_strerror (int error_no)
313{
314  static char buf[500];
315
316  if (error_no == 0)
317    error_no = GetLastError ();
318
319  buf[0] = '\0';
320  if (!FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL,
321		      error_no,
322		      0, /* choose most suitable language */
323		      buf, sizeof (buf), NULL))
324    sprintf (buf, "w32 error %u", error_no);
325  return buf;
326}
327
328/* Return 1 if P is a valid pointer to an object of size SIZE.  Return
329   0 if P is NOT a valid pointer.  Return -1 if we cannot validate P.
330
331   This is called from alloc.c:valid_pointer_p.  */
332int
333w32_valid_pointer_p (void *p, int size)
334{
335  SIZE_T done;
336  HANDLE h = OpenProcess (PROCESS_VM_READ, FALSE, GetCurrentProcessId ());
337
338  if (h)
339    {
340      unsigned char *buf = alloca (size);
341      int retval = ReadProcessMemory (h, p, buf, size, &done);
342
343      CloseHandle (h);
344      return retval;
345    }
346  else
347    return -1;
348}
349
350static char startup_dir[MAXPATHLEN];
351
352/* Get the current working directory.  */
353char *
354getwd (char *dir)
355{
356#if 0
357  if (GetCurrentDirectory (MAXPATHLEN, dir) > 0)
358    return dir;
359  return NULL;
360#else
361  /* Emacs doesn't actually change directory itself, and we want to
362     force our real wd to be where emacs.exe is to avoid unnecessary
363     conflicts when trying to rename or delete directories.  */
364  strcpy (dir, startup_dir);
365  return dir;
366#endif
367}
368
369#ifndef HAVE_SOCKETS
370/* Emulate gethostname.  */
371int
372gethostname (char *buffer, int size)
373{
374  /* NT only allows small host names, so the buffer is
375     certainly large enough.  */
376  return !GetComputerName (buffer, &size);
377}
378#endif /* HAVE_SOCKETS */
379
380/* Emulate getloadavg.  */
381int
382getloadavg (double loadavg[], int nelem)
383{
384  int i;
385
386  /* A faithful emulation is going to have to be saved for a rainy day.  */
387  for (i = 0; i < nelem; i++)
388    {
389      loadavg[i] = 0.0;
390    }
391  return i;
392}
393
394/* Emulate getpwuid, getpwnam and others.  */
395
396#define PASSWD_FIELD_SIZE 256
397
398static char the_passwd_name[PASSWD_FIELD_SIZE];
399static char the_passwd_passwd[PASSWD_FIELD_SIZE];
400static char the_passwd_gecos[PASSWD_FIELD_SIZE];
401static char the_passwd_dir[PASSWD_FIELD_SIZE];
402static char the_passwd_shell[PASSWD_FIELD_SIZE];
403
404static struct passwd the_passwd =
405{
406  the_passwd_name,
407  the_passwd_passwd,
408  0,
409  0,
410  0,
411  the_passwd_gecos,
412  the_passwd_dir,
413  the_passwd_shell,
414};
415
416static struct group the_group =
417{
418  /* There are no groups on NT, so we just return "root" as the
419     group name.  */
420  "root",
421};
422
423int
424getuid ()
425{
426  return the_passwd.pw_uid;
427}
428
429int
430geteuid ()
431{
432  /* I could imagine arguing for checking to see whether the user is
433     in the Administrators group and returning a UID of 0 for that
434     case, but I don't know how wise that would be in the long run.  */
435  return getuid ();
436}
437
438int
439getgid ()
440{
441  return the_passwd.pw_gid;
442}
443
444int
445getegid ()
446{
447  return getgid ();
448}
449
450struct passwd *
451getpwuid (int uid)
452{
453  if (uid == the_passwd.pw_uid)
454    return &the_passwd;
455  return NULL;
456}
457
458struct group *
459getgrgid (gid_t gid)
460{
461  return &the_group;
462}
463
464struct passwd *
465getpwnam (char *name)
466{
467  struct passwd *pw;
468
469  pw = getpwuid (getuid ());
470  if (!pw)
471    return pw;
472
473  if (stricmp (name, pw->pw_name))
474    return NULL;
475
476  return pw;
477}
478
479void
480init_user_info ()
481{
482  /* Find the user's real name by opening the process token and
483     looking up the name associated with the user-sid in that token.
484
485     Use the relative portion of the identifier authority value from
486     the user-sid as the user id value (same for group id using the
487     primary group sid from the process token). */
488
489  char            user_sid[256], name[256], domain[256];
490  DWORD           length = sizeof (name), dlength = sizeof (domain), trash;
491  HANDLE          token = NULL;
492  SID_NAME_USE    user_type;
493
494  if (
495			open_process_token (GetCurrentProcess (), TOKEN_QUERY, &token)
496      && get_token_information (
497					token, TokenUser,
498			      (PVOID) user_sid, sizeof (user_sid), &trash)
499      && lookup_account_sid (
500					NULL, *((PSID *) user_sid), name, &length,
501			   domain, &dlength, &user_type)
502			)
503    {
504      strcpy (the_passwd.pw_name, name);
505      /* Determine a reasonable uid value. */
506      if (stricmp ("administrator", name) == 0)
507	{
508	  the_passwd.pw_uid = 0;
509	  the_passwd.pw_gid = 0;
510	}
511      else
512	{
513	  SID_IDENTIFIER_AUTHORITY * pSIA;
514
515	  pSIA = get_sid_identifier_authority (*((PSID *) user_sid));
516	  /* I believe the relative portion is the last 4 bytes (of 6)
517	     with msb first. */
518	  the_passwd.pw_uid = ((pSIA->Value[2] << 24) +
519			       (pSIA->Value[3] << 16) +
520			       (pSIA->Value[4] << 8)  +
521			       (pSIA->Value[5] << 0));
522	  /* restrict to conventional uid range for normal users */
523	  the_passwd.pw_uid = the_passwd.pw_uid % 60001;
524
525	  /* Get group id */
526	  if (get_token_information (token, TokenPrimaryGroup,
527				   (PVOID) user_sid, sizeof (user_sid), &trash))
528	    {
529	      SID_IDENTIFIER_AUTHORITY * pSIA;
530
531	      pSIA = get_sid_identifier_authority (*((PSID *) user_sid));
532	      the_passwd.pw_gid = ((pSIA->Value[2] << 24) +
533				   (pSIA->Value[3] << 16) +
534				   (pSIA->Value[4] << 8)  +
535				   (pSIA->Value[5] << 0));
536	      /* I don't know if this is necessary, but for safety... */
537	      the_passwd.pw_gid = the_passwd.pw_gid % 60001;
538	    }
539	  else
540	    the_passwd.pw_gid = the_passwd.pw_uid;
541	}
542    }
543  /* If security calls are not supported (presumably because we
544       are running under Windows 95), fallback to this. */
545  else if (GetUserName (name, &length))
546    {
547      strcpy (the_passwd.pw_name, name);
548      if (stricmp ("administrator", name) == 0)
549	the_passwd.pw_uid = 0;
550      else
551	the_passwd.pw_uid = 123;
552      the_passwd.pw_gid = the_passwd.pw_uid;
553    }
554  else
555    {
556      strcpy (the_passwd.pw_name, "unknown");
557      the_passwd.pw_uid = 123;
558      the_passwd.pw_gid = 123;
559    }
560
561  /* Ensure HOME and SHELL are defined. */
562  if (getenv ("HOME") == NULL)
563    abort ();
564  if (getenv ("SHELL") == NULL)
565    abort ();
566
567  /* Set dir and shell from environment variables. */
568  strcpy (the_passwd.pw_dir, getenv ("HOME"));
569  strcpy (the_passwd.pw_shell, getenv ("SHELL"));
570
571  if (token)
572    CloseHandle (token);
573}
574
575int
576random ()
577{
578  /* rand () on NT gives us 15 random bits...hack together 30 bits.  */
579  return ((rand () << 15) | rand ());
580}
581
582void
583srandom (int seed)
584{
585  srand (seed);
586}
587
588
589/* Normalize filename by converting all path separators to
590   the specified separator.  Also conditionally convert upper
591   case path name components to lower case.  */
592
593static void
594normalize_filename (fp, path_sep)
595     register char *fp;
596     char path_sep;
597{
598  char sep;
599  char *elem;
600
601  /* Always lower-case drive letters a-z, even if the filesystem
602     preserves case in filenames.
603     This is so filenames can be compared by string comparison
604     functions that are case-sensitive.  Even case-preserving filesystems
605     do not distinguish case in drive letters.  */
606  if (fp[1] == ':' && *fp >= 'A' && *fp <= 'Z')
607    {
608      *fp += 'a' - 'A';
609      fp += 2;
610    }
611
612  if (NILP (Vw32_downcase_file_names))
613    {
614      while (*fp)
615	{
616	  if (*fp == '/' || *fp == '\\')
617	    *fp = path_sep;
618	  fp++;
619	}
620      return;
621    }
622
623  sep = path_sep;		/* convert to this path separator */
624  elem = fp;			/* start of current path element */
625
626  do {
627    if (*fp >= 'a' && *fp <= 'z')
628      elem = 0;			/* don't convert this element */
629
630    if (*fp == 0 || *fp == ':')
631      {
632	sep = *fp;		/* restore current separator (or 0) */
633	*fp = '/';		/* after conversion of this element */
634      }
635
636    if (*fp == '/' || *fp == '\\')
637      {
638	if (elem && elem != fp)
639	  {
640	    *fp = 0;		/* temporary end of string */
641	    _strlwr (elem);	/* while we convert to lower case */
642	  }
643	*fp = sep;		/* convert (or restore) path separator */
644	elem = fp + 1;		/* next element starts after separator */
645	sep = path_sep;
646      }
647  } while (*fp++);
648}
649
650/* Destructively turn backslashes into slashes.  */
651void
652dostounix_filename (p)
653     register char *p;
654{
655  normalize_filename (p, '/');
656}
657
658/* Destructively turn slashes into backslashes.  */
659void
660unixtodos_filename (p)
661     register char *p;
662{
663  normalize_filename (p, '\\');
664}
665
666/* Remove all CR's that are followed by a LF.
667   (From msdos.c...probably should figure out a way to share it,
668   although this code isn't going to ever change.)  */
669int
670crlf_to_lf (n, buf)
671     register int n;
672     register unsigned char *buf;
673{
674  unsigned char *np = buf;
675  unsigned char *startp = buf;
676  unsigned char *endp = buf + n;
677
678  if (n == 0)
679    return n;
680  while (buf < endp - 1)
681    {
682      if (*buf == 0x0d)
683	{
684	  if (*(++buf) != 0x0a)
685	    *np++ = 0x0d;
686	}
687      else
688	*np++ = *buf++;
689    }
690  if (buf < endp)
691    *np++ = *buf++;
692  return np - startp;
693}
694
695/* Parse the root part of file name, if present.  Return length and
696    optionally store pointer to char after root.  */
697static int
698parse_root (char * name, char ** pPath)
699{
700  char * start = name;
701
702  if (name == NULL)
703    return 0;
704
705  /* find the root name of the volume if given */
706  if (isalpha (name[0]) && name[1] == ':')
707    {
708      /* skip past drive specifier */
709      name += 2;
710      if (IS_DIRECTORY_SEP (name[0]))
711	name++;
712    }
713  else if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1]))
714    {
715      int slashes = 2;
716      name += 2;
717      do
718        {
719	  if (IS_DIRECTORY_SEP (*name) && --slashes == 0)
720	    break;
721	  name++;
722	}
723      while ( *name );
724      if (IS_DIRECTORY_SEP (name[0]))
725	name++;
726    }
727
728  if (pPath)
729    *pPath = name;
730
731  return name - start;
732}
733
734/* Get long base name for name; name is assumed to be absolute.  */
735static int
736get_long_basename (char * name, char * buf, int size)
737{
738  WIN32_FIND_DATA find_data;
739  HANDLE dir_handle;
740  int len = 0;
741
742  /* must be valid filename, no wild cards or other invalid characters */
743  if (_mbspbrk (name, "*?|<>\""))
744    return 0;
745
746  dir_handle = FindFirstFile (name, &find_data);
747  if (dir_handle != INVALID_HANDLE_VALUE)
748    {
749      if ((len = strlen (find_data.cFileName)) < size)
750	memcpy (buf, find_data.cFileName, len + 1);
751      else
752	len = 0;
753      FindClose (dir_handle);
754    }
755  return len;
756}
757
758/* Get long name for file, if possible (assumed to be absolute).  */
759BOOL
760w32_get_long_filename (char * name, char * buf, int size)
761{
762  char * o = buf;
763  char * p;
764  char * q;
765  char full[ MAX_PATH ];
766  int len;
767
768  len = strlen (name);
769  if (len >= MAX_PATH)
770    return FALSE;
771
772  /* Use local copy for destructive modification.  */
773  memcpy (full, name, len+1);
774  unixtodos_filename (full);
775
776  /* Copy root part verbatim.  */
777  len = parse_root (full, &p);
778  memcpy (o, full, len);
779  o += len;
780  *o = '\0';
781  size -= len;
782
783  while (p != NULL && *p)
784    {
785      q = p;
786      p = strchr (q, '\\');
787      if (p) *p = '\0';
788      len = get_long_basename (full, o, size);
789      if (len > 0)
790	{
791	  o += len;
792	  size -= len;
793	  if (p != NULL)
794	    {
795	      *p++ = '\\';
796	      if (size < 2)
797		return FALSE;
798	      *o++ = '\\';
799	      size--;
800	      *o = '\0';
801	    }
802	}
803      else
804	return FALSE;
805    }
806
807  return TRUE;
808}
809
810int
811is_unc_volume (const char *filename)
812{
813  const char *ptr = filename;
814
815  if (!IS_DIRECTORY_SEP (ptr[0]) || !IS_DIRECTORY_SEP (ptr[1]) || !ptr[2])
816    return 0;
817
818  if (_mbspbrk (ptr + 2, "*?|<>\"\\/"))
819    return 0;
820
821  return 1;
822}
823
824/* Routines that are no-ops on NT but are defined to get Emacs to compile.  */
825
826int
827sigsetmask (int signal_mask)
828{
829  return 0;
830}
831
832int
833sigmask (int sig)
834{
835  return 0;
836}
837
838int
839sigblock (int sig)
840{
841  return 0;
842}
843
844int
845sigunblock (int sig)
846{
847  return 0;
848}
849
850int
851setpgrp (int pid, int gid)
852{
853  return 0;
854}
855
856int
857alarm (int seconds)
858{
859  return 0;
860}
861
862void
863unrequest_sigio (void)
864{
865  return;
866}
867
868void
869request_sigio (void)
870{
871  return;
872}
873
874#define REG_ROOT "SOFTWARE\\GNU\\Emacs"
875
876LPBYTE
877w32_get_resource (key, lpdwtype)
878    char *key;
879    LPDWORD lpdwtype;
880{
881  LPBYTE lpvalue;
882  HKEY hrootkey = NULL;
883  DWORD cbData;
884  BOOL ok = FALSE;
885
886  /* Check both the current user and the local machine to see if
887     we have any resources.  */
888
889  if (RegOpenKeyEx (HKEY_CURRENT_USER, REG_ROOT, 0, KEY_READ, &hrootkey) == ERROR_SUCCESS)
890    {
891      lpvalue = NULL;
892
893      if (RegQueryValueEx (hrootkey, key, NULL, NULL, NULL, &cbData) == ERROR_SUCCESS
894	  && (lpvalue = (LPBYTE) xmalloc (cbData)) != NULL
895	  && RegQueryValueEx (hrootkey, key, NULL, lpdwtype, lpvalue, &cbData) == ERROR_SUCCESS)
896	{
897	  return (lpvalue);
898	}
899
900      if (lpvalue) xfree (lpvalue);
901
902      RegCloseKey (hrootkey);
903    }
904
905  if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, REG_ROOT, 0, KEY_READ, &hrootkey) == ERROR_SUCCESS)
906    {
907      lpvalue = NULL;
908
909      if (RegQueryValueEx (hrootkey, key, NULL, NULL, NULL, &cbData) == ERROR_SUCCESS
910	  && (lpvalue = (LPBYTE) xmalloc (cbData)) != NULL
911	  && RegQueryValueEx (hrootkey, key, NULL, lpdwtype, lpvalue, &cbData) == ERROR_SUCCESS)
912	{
913	  return (lpvalue);
914	}
915
916      if (lpvalue) xfree (lpvalue);
917
918      RegCloseKey (hrootkey);
919    }
920
921  return (NULL);
922}
923
924char *get_emacs_configuration (void);
925extern Lisp_Object Vsystem_configuration;
926
927void
928init_environment (char ** argv)
929{
930  static const char * const tempdirs[] = {
931    "$TMPDIR", "$TEMP", "$TMP", "c:/"
932  };
933
934  int i;
935
936  const int imax = sizeof (tempdirs) / sizeof (tempdirs[0]);
937
938  /* Make sure they have a usable $TMPDIR.  Many Emacs functions use
939     temporary files and assume "/tmp" if $TMPDIR is unset, which
940     will break on DOS/Windows.  Refuse to work if we cannot find
941     a directory, not even "c:/", usable for that purpose.  */
942  for (i = 0; i < imax ; i++)
943    {
944      const char *tmp = tempdirs[i];
945
946      if (*tmp == '$')
947	tmp = getenv (tmp + 1);
948      /* Note that `access' can lie to us if the directory resides on a
949	 read-only filesystem, like CD-ROM or a write-protected floppy.
950	 The only way to be really sure is to actually create a file and
951	 see if it succeeds.  But I think that's too much to ask.  */
952      if (tmp && _access (tmp, D_OK) == 0)
953	{
954	  char * var = alloca (strlen (tmp) + 8);
955	  sprintf (var, "TMPDIR=%s", tmp);
956	  _putenv (strdup (var));
957	  break;
958	}
959    }
960  if (i >= imax)
961    cmd_error_internal
962      (Fcons (Qerror,
963	      Fcons (build_string ("no usable temporary directories found!!"),
964		     Qnil)),
965       "While setting TMPDIR: ");
966
967  /* Check for environment variables and use registry settings if they
968     don't exist.  Fallback on default values where applicable.  */
969  {
970    int i;
971    LPBYTE lpval;
972    DWORD dwType;
973    char locale_name[32];
974    struct stat ignored;
975    char default_home[MAX_PATH];
976
977    static const struct env_entry
978    {
979      char * name;
980      char * def_value;
981    } dflt_envvars[] =
982    {
983      {"HOME", "C:/"},
984      {"PRELOAD_WINSOCK", NULL},
985      {"emacs_dir", "C:/emacs"},
986      {"EMACSLOADPATH", "%emacs_dir%/site-lisp;%emacs_dir%/../site-lisp;%emacs_dir%/lisp;%emacs_dir%/leim"},
987      {"SHELL", "%emacs_dir%/bin/cmdproxy.exe"},
988      {"EMACSDATA", "%emacs_dir%/etc"},
989      {"EMACSPATH", "%emacs_dir%/bin"},
990      /* We no longer set INFOPATH because Info-default-directory-list
991	 is then ignored.  */
992      /*  {"INFOPATH", "%emacs_dir%/info"},  */
993      {"EMACSDOC", "%emacs_dir%/etc"},
994      {"TERM", "cmd"},
995      {"LANG", NULL},
996    };
997
998#define N_ENV_VARS sizeof(dflt_envvars)/sizeof(dflt_envvars[0])
999
1000    /* We need to copy dflt_envvars[] and work on the copy because we
1001       don't want the dumped Emacs to inherit the values of
1002       environment variables we saw during dumping (which could be on
1003       a different system).  The defaults above must be left intact.  */
1004    struct env_entry env_vars[N_ENV_VARS];
1005
1006    for (i = 0; i < N_ENV_VARS; i++)
1007      env_vars[i] = dflt_envvars[i];
1008
1009    /* For backwards compatibility, check if a .emacs file exists in C:/
1010       If not, then we can try to default to the appdata directory under the
1011       user's profile, which is more likely to be writable.   */
1012    if (stat ("C:/.emacs", &ignored) < 0)
1013    {
1014      HRESULT profile_result;
1015      /* Dynamically load ShGetFolderPath, as it won't exist on versions
1016	 of Windows 95 and NT4 that have not been updated to include
1017	 MSIE 5.  Also we don't link with shell32.dll by default.  */
1018      HMODULE shell32_dll;
1019      ShGetFolderPath_fn get_folder_path;
1020      shell32_dll = GetModuleHandle ("shell32.dll");
1021      get_folder_path = (ShGetFolderPath_fn)
1022	GetProcAddress (shell32_dll, "SHGetFolderPathA");
1023
1024      if (get_folder_path != NULL)
1025	{
1026	  profile_result = get_folder_path (NULL, CSIDL_APPDATA, NULL,
1027					    0, default_home);
1028
1029	  /* If we can't get the appdata dir, revert to old behaviour.  */
1030	  if (profile_result == S_OK)
1031	    env_vars[0].def_value = default_home;
1032	}
1033
1034      /* Unload shell32.dll, it is not needed anymore.  */
1035      FreeLibrary (shell32_dll);
1036    }
1037
1038  /* Get default locale info and use it for LANG.  */
1039  if (GetLocaleInfo (LOCALE_USER_DEFAULT,
1040                     LOCALE_SABBREVLANGNAME | LOCALE_USE_CP_ACP,
1041                     locale_name, sizeof (locale_name)))
1042    {
1043      for (i = 0; i < N_ENV_VARS; i++)
1044        {
1045          if (strcmp (env_vars[i].name, "LANG") == 0)
1046            {
1047              env_vars[i].def_value = locale_name;
1048              break;
1049            }
1050        }
1051    }
1052
1053#define SET_ENV_BUF_SIZE (4 * MAX_PATH)	/* to cover EMACSLOADPATH */
1054
1055    /* Treat emacs_dir specially: set it unconditionally based on our
1056       location, if it appears that we are running from the bin subdir
1057       of a standard installation.  */
1058    {
1059      char *p;
1060      char modname[MAX_PATH];
1061
1062      if (!GetModuleFileName (NULL, modname, MAX_PATH))
1063	abort ();
1064      if ((p = strrchr (modname, '\\')) == NULL)
1065	abort ();
1066      *p = 0;
1067
1068      if ((p = strrchr (modname, '\\')) && stricmp (p, "\\bin") == 0)
1069	{
1070	  char buf[SET_ENV_BUF_SIZE];
1071
1072	  *p = 0;
1073	  for (p = modname; *p; p++)
1074	    if (*p == '\\') *p = '/';
1075
1076	  _snprintf (buf, sizeof(buf)-1, "emacs_dir=%s", modname);
1077	  _putenv (strdup (buf));
1078	}
1079      /* Handle running emacs from the build directory: src/oo-spd/i386/  */
1080
1081      /* FIXME: should use substring of get_emacs_configuration ().
1082	 But I don't think the Windows build supports alpha, mips etc
1083         anymore, so have taken the easy option for now.  */
1084      else if (p && stricmp (p, "\\i386") == 0)
1085	{
1086	  *p = 0;
1087	  p = strrchr (modname, '\\');
1088	  if (p != NULL)
1089	    {
1090	      *p = 0;
1091	      p = strrchr (modname, '\\');
1092	      if (p && stricmp (p, "\\src") == 0)
1093		{
1094		  char buf[SET_ENV_BUF_SIZE];
1095
1096		  *p = 0;
1097		  for (p = modname; *p; p++)
1098		    if (*p == '\\') *p = '/';
1099
1100		  _snprintf (buf, sizeof(buf)-1, "emacs_dir=%s", modname);
1101		  _putenv (strdup (buf));
1102		}
1103	    }
1104	}
1105    }
1106
1107    for (i = 0; i < N_ENV_VARS; i++)
1108      {
1109	if (!getenv (env_vars[i].name))
1110	  {
1111	    int dont_free = 0;
1112
1113	    if ((lpval = w32_get_resource (env_vars[i].name, &dwType)) == NULL)
1114	      {
1115		lpval = env_vars[i].def_value;
1116		dwType = REG_EXPAND_SZ;
1117		dont_free = 1;
1118	      }
1119
1120	    if (lpval)
1121	      {
1122		char buf1[SET_ENV_BUF_SIZE], buf2[SET_ENV_BUF_SIZE];
1123
1124		if (dwType == REG_EXPAND_SZ)
1125		  ExpandEnvironmentStrings ((LPSTR) lpval, buf1, sizeof(buf1));
1126		else if (dwType == REG_SZ)
1127		  strcpy (buf1, lpval);
1128		if (dwType == REG_EXPAND_SZ || dwType == REG_SZ)
1129		  {
1130		    _snprintf (buf2, sizeof(buf2)-1, "%s=%s", env_vars[i].name,
1131			       buf1);
1132		    _putenv (strdup (buf2));
1133		  }
1134
1135		if (!dont_free)
1136		  xfree (lpval);
1137	      }
1138	  }
1139      }
1140  }
1141
1142  /* Rebuild system configuration to reflect invoking system.  */
1143  Vsystem_configuration = build_string (EMACS_CONFIGURATION);
1144
1145  /* Another special case: on NT, the PATH variable is actually named
1146     "Path" although cmd.exe (perhaps NT itself) arranges for
1147     environment variable lookup and setting to be case insensitive.
1148     However, Emacs assumes a fully case sensitive environment, so we
1149     need to change "Path" to "PATH" to match the expectations of
1150     various elisp packages.  We do this by the sneaky method of
1151     modifying the string in the C runtime environ entry.
1152
1153     The same applies to COMSPEC.  */
1154  {
1155    char ** envp;
1156
1157    for (envp = environ; *envp; envp++)
1158      if (_strnicmp (*envp, "PATH=", 5) == 0)
1159	memcpy (*envp, "PATH=", 5);
1160      else if (_strnicmp (*envp, "COMSPEC=", 8) == 0)
1161	memcpy (*envp, "COMSPEC=", 8);
1162  }
1163
1164  /* Remember the initial working directory for getwd, then make the
1165     real wd be the location of emacs.exe to avoid conflicts when
1166     renaming or deleting directories.  (We also don't call chdir when
1167     running subprocesses for the same reason.)  */
1168  if (!GetCurrentDirectory (MAXPATHLEN, startup_dir))
1169    abort ();
1170
1171  {
1172    char *p;
1173    static char modname[MAX_PATH];
1174
1175    if (!GetModuleFileName (NULL, modname, MAX_PATH))
1176      abort ();
1177    if ((p = strrchr (modname, '\\')) == NULL)
1178      abort ();
1179    *p = 0;
1180
1181    SetCurrentDirectory (modname);
1182
1183    /* Ensure argv[0] has the full path to Emacs.  */
1184    *p = '\\';
1185    argv[0] = modname;
1186  }
1187
1188  /* Determine if there is a middle mouse button, to allow parse_button
1189     to decide whether right mouse events should be mouse-2 or
1190     mouse-3. */
1191  w32_num_mouse_buttons = GetSystemMetrics (SM_CMOUSEBUTTONS);
1192
1193  init_user_info ();
1194}
1195
1196char *
1197emacs_root_dir (void)
1198{
1199  static char root_dir[FILENAME_MAX];
1200  const char *p;
1201
1202  p = getenv ("emacs_dir");
1203  if (p == NULL)
1204    abort ();
1205  strcpy (root_dir, p);
1206  root_dir[parse_root (root_dir, NULL)] = '\0';
1207  dostounix_filename (root_dir);
1208  return root_dir;
1209}
1210
1211/* We don't have scripts to automatically determine the system configuration
1212   for Emacs before it's compiled, and we don't want to have to make the
1213   user enter it, so we define EMACS_CONFIGURATION to invoke this runtime
1214   routine.  */
1215
1216char *
1217get_emacs_configuration (void)
1218{
1219  char *arch, *oem, *os;
1220  int build_num;
1221  static char configuration_buffer[32];
1222
1223  /* Determine the processor type.  */
1224  switch (get_processor_type ())
1225    {
1226
1227#ifdef PROCESSOR_INTEL_386
1228    case PROCESSOR_INTEL_386:
1229    case PROCESSOR_INTEL_486:
1230    case PROCESSOR_INTEL_PENTIUM:
1231      arch = "i386";
1232      break;
1233#endif
1234
1235#ifdef PROCESSOR_INTEL_860
1236    case PROCESSOR_INTEL_860:
1237      arch = "i860";
1238      break;
1239#endif
1240
1241#ifdef PROCESSOR_MIPS_R2000
1242    case PROCESSOR_MIPS_R2000:
1243    case PROCESSOR_MIPS_R3000:
1244    case PROCESSOR_MIPS_R4000:
1245      arch = "mips";
1246      break;
1247#endif
1248
1249#ifdef PROCESSOR_ALPHA_21064
1250    case PROCESSOR_ALPHA_21064:
1251      arch = "alpha";
1252      break;
1253#endif
1254
1255    default:
1256      arch = "unknown";
1257      break;
1258    }
1259
1260  /* Use the OEM field to reflect the compiler/library combination.  */
1261#ifdef _MSC_VER
1262#define COMPILER_NAME	"msvc"
1263#else
1264#ifdef __GNUC__
1265#define COMPILER_NAME	"mingw"
1266#else
1267#define COMPILER_NAME	"unknown"
1268#endif
1269#endif
1270  oem = COMPILER_NAME;
1271
1272  switch (osinfo_cache.dwPlatformId) {
1273  case VER_PLATFORM_WIN32_NT:
1274    os = "nt";
1275    build_num = osinfo_cache.dwBuildNumber;
1276    break;
1277  case VER_PLATFORM_WIN32_WINDOWS:
1278    if (osinfo_cache.dwMinorVersion == 0) {
1279      os = "windows95";
1280    } else {
1281      os = "windows98";
1282    }
1283    build_num = LOWORD (osinfo_cache.dwBuildNumber);
1284    break;
1285  case VER_PLATFORM_WIN32s:
1286    /* Not supported, should not happen. */
1287    os = "windows32s";
1288    build_num = LOWORD (osinfo_cache.dwBuildNumber);
1289    break;
1290  default:
1291    os = "unknown";
1292    build_num = 0;
1293    break;
1294  }
1295
1296  if (osinfo_cache.dwPlatformId == VER_PLATFORM_WIN32_NT) {
1297    sprintf (configuration_buffer, "%s-%s-%s%d.%d.%d", arch, oem, os,
1298	     get_w32_major_version (), get_w32_minor_version (), build_num);
1299  } else {
1300    sprintf (configuration_buffer, "%s-%s-%s.%d", arch, oem, os, build_num);
1301  }
1302
1303  return configuration_buffer;
1304}
1305
1306char *
1307get_emacs_configuration_options (void)
1308{
1309  static char options_buffer[256];
1310
1311/* Work out the effective configure options for this build.  */
1312#ifdef _MSC_VER
1313#define COMPILER_VERSION	"--with-msvc (%d.%02d)", _MSC_VER / 100, _MSC_VER % 100
1314#else
1315#ifdef __GNUC__
1316#define COMPILER_VERSION	"--with-gcc (%d.%d)", __GNUC__, __GNUC_MINOR__
1317#else
1318#define COMPILER_VERSION	""
1319#endif
1320#endif
1321
1322  sprintf (options_buffer, COMPILER_VERSION);
1323#ifdef EMACSDEBUG
1324  strcat (options_buffer, " --no-opt");
1325#endif
1326#ifdef USER_CFLAGS
1327  strcat (options_buffer, " --cflags");
1328  strcat (options_buffer, USER_CFLAGS);
1329#endif
1330#ifdef USER_LDFLAGS
1331  strcat (options_buffer, " --ldflags");
1332  strcat (options_buffer, USER_LDFLAGS);
1333#endif
1334  return options_buffer;
1335}
1336
1337
1338#include <sys/timeb.h>
1339
1340/* Emulate gettimeofday (Ulrich Leodolter, 1/11/95).  */
1341void
1342gettimeofday (struct timeval *tv, struct timezone *tz)
1343{
1344  struct _timeb tb;
1345  _ftime (&tb);
1346
1347  tv->tv_sec = tb.time;
1348  tv->tv_usec = tb.millitm * 1000L;
1349  if (tz)
1350    {
1351      tz->tz_minuteswest = tb.timezone;	/* minutes west of Greenwich  */
1352      tz->tz_dsttime = tb.dstflag;	/* type of dst correction  */
1353    }
1354}
1355
1356/* ------------------------------------------------------------------------- */
1357/* IO support and wrapper functions for W32 API. */
1358/* ------------------------------------------------------------------------- */
1359
1360/* Place a wrapper around the MSVC version of ctime.  It returns NULL
1361   on network directories, so we handle that case here.
1362   (Ulrich Leodolter, 1/11/95).  */
1363char *
1364sys_ctime (const time_t *t)
1365{
1366  char *str = (char *) ctime (t);
1367  return (str ? str : "Sun Jan 01 00:00:00 1970");
1368}
1369
1370/* Emulate sleep...we could have done this with a define, but that
1371   would necessitate including windows.h in the files that used it.
1372   This is much easier.  */
1373void
1374sys_sleep (int seconds)
1375{
1376  Sleep (seconds * 1000);
1377}
1378
1379/* Internal MSVC functions for low-level descriptor munging */
1380extern int __cdecl _set_osfhnd (int fd, long h);
1381extern int __cdecl _free_osfhnd (int fd);
1382
1383/* parallel array of private info on file handles */
1384filedesc fd_info [ MAXDESC ];
1385
1386typedef struct volume_info_data {
1387  struct volume_info_data * next;
1388
1389  /* time when info was obtained */
1390  DWORD     timestamp;
1391
1392  /* actual volume info */
1393  char *    root_dir;
1394  DWORD     serialnum;
1395  DWORD     maxcomp;
1396  DWORD     flags;
1397  char *    name;
1398  char *    type;
1399} volume_info_data;
1400
1401/* Global referenced by various functions.  */
1402static volume_info_data volume_info;
1403
1404/* Vector to indicate which drives are local and fixed (for which cached
1405   data never expires).  */
1406static BOOL fixed_drives[26];
1407
1408/* Consider cached volume information to be stale if older than 10s,
1409   at least for non-local drives.  Info for fixed drives is never stale.  */
1410#define DRIVE_INDEX( c ) ( (c) <= 'Z' ? (c) - 'A' : (c) - 'a' )
1411#define VOLINFO_STILL_VALID( root_dir, info )		\
1412  ( ( isalpha (root_dir[0]) &&				\
1413      fixed_drives[ DRIVE_INDEX (root_dir[0]) ] )	\
1414    || GetTickCount () - info->timestamp < 10000 )
1415
1416/* Cache support functions.  */
1417
1418/* Simple linked list with linear search is sufficient.  */
1419static volume_info_data *volume_cache = NULL;
1420
1421static volume_info_data *
1422lookup_volume_info (char * root_dir)
1423{
1424  volume_info_data * info;
1425
1426  for (info = volume_cache; info; info = info->next)
1427    if (stricmp (info->root_dir, root_dir) == 0)
1428      break;
1429  return info;
1430}
1431
1432static void
1433add_volume_info (char * root_dir, volume_info_data * info)
1434{
1435  info->root_dir = xstrdup (root_dir);
1436  info->next = volume_cache;
1437  volume_cache = info;
1438}
1439
1440
1441/* Wrapper for GetVolumeInformation, which uses caching to avoid
1442   performance penalty (~2ms on 486 for local drives, 7.5ms for local
1443   cdrom drive, ~5-10ms or more for remote drives on LAN).  */
1444volume_info_data *
1445GetCachedVolumeInformation (char * root_dir)
1446{
1447  volume_info_data * info;
1448  char default_root[ MAX_PATH ];
1449
1450  /* NULL for root_dir means use root from current directory.  */
1451  if (root_dir == NULL)
1452    {
1453      if (GetCurrentDirectory (MAX_PATH, default_root) == 0)
1454	return NULL;
1455      parse_root (default_root, &root_dir);
1456      *root_dir = 0;
1457      root_dir = default_root;
1458    }
1459
1460  /* Local fixed drives can be cached permanently.  Removable drives
1461     cannot be cached permanently, since the volume name and serial
1462     number (if nothing else) can change.  Remote drives should be
1463     treated as if they are removable, since there is no sure way to
1464     tell whether they are or not.  Also, the UNC association of drive
1465     letters mapped to remote volumes can be changed at any time (even
1466     by other processes) without notice.
1467
1468     As a compromise, so we can benefit from caching info for remote
1469     volumes, we use a simple expiry mechanism to invalidate cache
1470     entries that are more than ten seconds old.  */
1471
1472#if 0
1473  /* No point doing this, because WNetGetConnection is even slower than
1474     GetVolumeInformation, consistently taking ~50ms on a 486 (FWIW,
1475     GetDriveType is about the only call of this type which does not
1476     involve network access, and so is extremely quick).  */
1477
1478  /* Map drive letter to UNC if remote. */
1479  if ( isalpha( root_dir[0] ) && !fixed[ DRIVE_INDEX( root_dir[0] ) ] )
1480    {
1481      char remote_name[ 256 ];
1482      char drive[3] = { root_dir[0], ':' };
1483
1484      if (WNetGetConnection (drive, remote_name, sizeof (remote_name))
1485	  == NO_ERROR)
1486	/* do something */ ;
1487    }
1488#endif
1489
1490  info = lookup_volume_info (root_dir);
1491
1492  if (info == NULL || ! VOLINFO_STILL_VALID (root_dir, info))
1493  {
1494    char  name[ 256 ];
1495    DWORD serialnum;
1496    DWORD maxcomp;
1497    DWORD flags;
1498    char  type[ 256 ];
1499
1500    /* Info is not cached, or is stale. */
1501    if (!GetVolumeInformation (root_dir,
1502			       name, sizeof (name),
1503			       &serialnum,
1504			       &maxcomp,
1505			       &flags,
1506			       type, sizeof (type)))
1507      return NULL;
1508
1509    /* Cache the volume information for future use, overwriting existing
1510       entry if present.  */
1511    if (info == NULL)
1512      {
1513	info = (volume_info_data *) xmalloc (sizeof (volume_info_data));
1514	add_volume_info (root_dir, info);
1515      }
1516    else
1517      {
1518	xfree (info->name);
1519	xfree (info->type);
1520      }
1521
1522    info->name = xstrdup (name);
1523    info->serialnum = serialnum;
1524    info->maxcomp = maxcomp;
1525    info->flags = flags;
1526    info->type = xstrdup (type);
1527    info->timestamp = GetTickCount ();
1528  }
1529
1530  return info;
1531}
1532
1533/* Get information on the volume where name is held; set path pointer to
1534   start of pathname in name (past UNC header\volume header if present).  */
1535int
1536get_volume_info (const char * name, const char ** pPath)
1537{
1538  char temp[MAX_PATH];
1539  char *rootname = NULL;  /* default to current volume */
1540  volume_info_data * info;
1541
1542  if (name == NULL)
1543    return FALSE;
1544
1545  /* find the root name of the volume if given */
1546  if (isalpha (name[0]) && name[1] == ':')
1547    {
1548      rootname = temp;
1549      temp[0] = *name++;
1550      temp[1] = *name++;
1551      temp[2] = '\\';
1552      temp[3] = 0;
1553    }
1554  else if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1]))
1555    {
1556      char *str = temp;
1557      int slashes = 4;
1558      rootname = temp;
1559      do
1560        {
1561	  if (IS_DIRECTORY_SEP (*name) && --slashes == 0)
1562	    break;
1563	  *str++ = *name++;
1564	}
1565      while ( *name );
1566
1567      *str++ = '\\';
1568      *str = 0;
1569    }
1570
1571  if (pPath)
1572    *pPath = name;
1573
1574  info = GetCachedVolumeInformation (rootname);
1575  if (info != NULL)
1576    {
1577      /* Set global referenced by other functions.  */
1578      volume_info = *info;
1579      return TRUE;
1580    }
1581  return FALSE;
1582}
1583
1584/* Determine if volume is FAT format (ie. only supports short 8.3
1585   names); also set path pointer to start of pathname in name.  */
1586int
1587is_fat_volume (const char * name, const char ** pPath)
1588{
1589  if (get_volume_info (name, pPath))
1590    return (volume_info.maxcomp == 12);
1591  return FALSE;
1592}
1593
1594/* Map filename to a legal 8.3 name if necessary. */
1595const char *
1596map_w32_filename (const char * name, const char ** pPath)
1597{
1598  static char shortname[MAX_PATH];
1599  char * str = shortname;
1600  char c;
1601  char * path;
1602  const char * save_name = name;
1603
1604  if (strlen (name) >= MAX_PATH)
1605    {
1606      /* Return a filename which will cause callers to fail.  */
1607      strcpy (shortname, "?");
1608      return shortname;
1609    }
1610
1611  if (is_fat_volume (name, (const char **)&path)) /* truncate to 8.3 */
1612    {
1613      register int left = 8;	/* maximum number of chars in part */
1614      register int extn = 0;	/* extension added? */
1615      register int dots = 2;	/* maximum number of dots allowed */
1616
1617      while (name < path)
1618	*str++ = *name++;	/* skip past UNC header */
1619
1620      while ((c = *name++))
1621        {
1622	  switch ( c )
1623	    {
1624	    case '\\':
1625	    case '/':
1626	      *str++ = '\\';
1627	      extn = 0;		/* reset extension flags */
1628	      dots = 2;		/* max 2 dots */
1629	      left = 8;		/* max length 8 for main part */
1630	      break;
1631	    case ':':
1632	      *str++ = ':';
1633	      extn = 0;		/* reset extension flags */
1634	      dots = 2;		/* max 2 dots */
1635	      left = 8;		/* max length 8 for main part */
1636	      break;
1637	    case '.':
1638	      if ( dots )
1639	        {
1640		  /* Convert path components of the form .xxx to _xxx,
1641		     but leave . and .. as they are.  This allows .emacs
1642		     to be read as _emacs, for example.  */
1643
1644		  if (! *name ||
1645		      *name == '.' ||
1646		      IS_DIRECTORY_SEP (*name))
1647		    {
1648		      *str++ = '.';
1649		      dots--;
1650		    }
1651		  else
1652		    {
1653		      *str++ = '_';
1654		      left--;
1655		      dots = 0;
1656		    }
1657		}
1658	      else if ( !extn )
1659	        {
1660		  *str++ = '.';
1661		  extn = 1;		/* we've got an extension */
1662		  left = 3;		/* 3 chars in extension */
1663		}
1664	      else
1665	        {
1666		  /* any embedded dots after the first are converted to _ */
1667		  *str++ = '_';
1668		}
1669	      break;
1670	    case '~':
1671	    case '#':			/* don't lose these, they're important */
1672	      if ( ! left )
1673		str[-1] = c;		/* replace last character of part */
1674	      /* FALLTHRU */
1675	    default:
1676	      if ( left )
1677	        {
1678		  *str++ = tolower (c);	/* map to lower case (looks nicer) */
1679		  left--;
1680		  dots = 0;		/* started a path component */
1681		}
1682	      break;
1683	    }
1684	}
1685      *str = '\0';
1686    }
1687  else
1688    {
1689      strcpy (shortname, name);
1690      unixtodos_filename (shortname);
1691    }
1692
1693  if (pPath)
1694    *pPath = shortname + (path - save_name);
1695
1696  return shortname;
1697}
1698
1699static int
1700is_exec (const char * name)
1701{
1702  char * p = strrchr (name, '.');
1703  return
1704    (p != NULL
1705     && (stricmp (p, ".exe") == 0 ||
1706	 stricmp (p, ".com") == 0 ||
1707	 stricmp (p, ".bat") == 0 ||
1708	 stricmp (p, ".cmd") == 0));
1709}
1710
1711/* Emulate the Unix directory procedures opendir, closedir,
1712   and readdir.  We can't use the procedures supplied in sysdep.c,
1713   so we provide them here.  */
1714
1715struct direct dir_static;       /* simulated directory contents */
1716static HANDLE dir_find_handle = INVALID_HANDLE_VALUE;
1717static int    dir_is_fat;
1718static char   dir_pathname[MAXPATHLEN+1];
1719static WIN32_FIND_DATA dir_find_data;
1720
1721/* Support shares on a network resource as subdirectories of a read-only
1722   root directory. */
1723static HANDLE wnet_enum_handle = INVALID_HANDLE_VALUE;
1724HANDLE open_unc_volume (const char *);
1725char  *read_unc_volume (HANDLE, char *, int);
1726void   close_unc_volume (HANDLE);
1727
1728DIR *
1729opendir (char *filename)
1730{
1731  DIR *dirp;
1732
1733  /* Opening is done by FindFirstFile.  However, a read is inherent to
1734     this operation, so we defer the open until read time.  */
1735
1736  if (dir_find_handle != INVALID_HANDLE_VALUE)
1737    return NULL;
1738  if (wnet_enum_handle != INVALID_HANDLE_VALUE)
1739    return NULL;
1740
1741  if (is_unc_volume (filename))
1742    {
1743      wnet_enum_handle = open_unc_volume (filename);
1744      if (wnet_enum_handle == INVALID_HANDLE_VALUE)
1745	return NULL;
1746    }
1747
1748  if (!(dirp = (DIR *) malloc (sizeof (DIR))))
1749    return NULL;
1750
1751  dirp->dd_fd = 0;
1752  dirp->dd_loc = 0;
1753  dirp->dd_size = 0;
1754
1755  strncpy (dir_pathname, map_w32_filename (filename, NULL), MAXPATHLEN);
1756  dir_pathname[MAXPATHLEN] = '\0';
1757  dir_is_fat = is_fat_volume (filename, NULL);
1758
1759  return dirp;
1760}
1761
1762void
1763closedir (DIR *dirp)
1764{
1765  /* If we have a find-handle open, close it.  */
1766  if (dir_find_handle != INVALID_HANDLE_VALUE)
1767    {
1768      FindClose (dir_find_handle);
1769      dir_find_handle = INVALID_HANDLE_VALUE;
1770    }
1771  else if (wnet_enum_handle != INVALID_HANDLE_VALUE)
1772    {
1773      close_unc_volume (wnet_enum_handle);
1774      wnet_enum_handle = INVALID_HANDLE_VALUE;
1775    }
1776  xfree ((char *) dirp);
1777}
1778
1779struct direct *
1780readdir (DIR *dirp)
1781{
1782  if (wnet_enum_handle != INVALID_HANDLE_VALUE)
1783    {
1784      if (!read_unc_volume (wnet_enum_handle,
1785			      dir_find_data.cFileName,
1786			      MAX_PATH))
1787	return NULL;
1788    }
1789  /* If we aren't dir_finding, do a find-first, otherwise do a find-next. */
1790  else if (dir_find_handle == INVALID_HANDLE_VALUE)
1791    {
1792      char filename[MAXNAMLEN + 3];
1793      int ln;
1794
1795      strcpy (filename, dir_pathname);
1796      ln = strlen (filename) - 1;
1797      if (!IS_DIRECTORY_SEP (filename[ln]))
1798	strcat (filename, "\\");
1799      strcat (filename, "*");
1800
1801      dir_find_handle = FindFirstFile (filename, &dir_find_data);
1802
1803      if (dir_find_handle == INVALID_HANDLE_VALUE)
1804	return NULL;
1805    }
1806  else
1807    {
1808      if (!FindNextFile (dir_find_handle, &dir_find_data))
1809	return NULL;
1810    }
1811
1812  /* Emacs never uses this value, so don't bother making it match
1813     value returned by stat().  */
1814  dir_static.d_ino = 1;
1815
1816  dir_static.d_reclen = sizeof (struct direct) - MAXNAMLEN + 3 +
1817    dir_static.d_namlen - dir_static.d_namlen % 4;
1818
1819  dir_static.d_namlen = strlen (dir_find_data.cFileName);
1820  strcpy (dir_static.d_name, dir_find_data.cFileName);
1821  if (dir_is_fat)
1822    _strlwr (dir_static.d_name);
1823  else if (!NILP (Vw32_downcase_file_names))
1824    {
1825      register char *p;
1826      for (p = dir_static.d_name; *p; p++)
1827	if (*p >= 'a' && *p <= 'z')
1828	  break;
1829      if (!*p)
1830	_strlwr (dir_static.d_name);
1831    }
1832
1833  return &dir_static;
1834}
1835
1836HANDLE
1837open_unc_volume (const char *path)
1838{
1839  NETRESOURCE nr;
1840  HANDLE henum;
1841  int result;
1842
1843  nr.dwScope = RESOURCE_GLOBALNET;
1844  nr.dwType = RESOURCETYPE_DISK;
1845  nr.dwDisplayType = RESOURCEDISPLAYTYPE_SERVER;
1846  nr.dwUsage = RESOURCEUSAGE_CONTAINER;
1847  nr.lpLocalName = NULL;
1848  nr.lpRemoteName = (LPSTR)map_w32_filename (path, NULL);
1849  nr.lpComment = NULL;
1850  nr.lpProvider = NULL;
1851
1852  result = WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_DISK,
1853			RESOURCEUSAGE_CONNECTABLE, &nr, &henum);
1854
1855  if (result == NO_ERROR)
1856    return henum;
1857  else
1858    return INVALID_HANDLE_VALUE;
1859}
1860
1861char *
1862read_unc_volume (HANDLE henum, char *readbuf, int size)
1863{
1864  DWORD count;
1865  int result;
1866  DWORD bufsize = 512;
1867  char *buffer;
1868  char *ptr;
1869
1870  count = 1;
1871  buffer = alloca (bufsize);
1872  result = WNetEnumResource (wnet_enum_handle, &count, buffer, &bufsize);
1873  if (result != NO_ERROR)
1874    return NULL;
1875
1876  /* WNetEnumResource returns \\resource\share...skip forward to "share". */
1877  ptr = ((LPNETRESOURCE) buffer)->lpRemoteName;
1878  ptr += 2;
1879  while (*ptr && !IS_DIRECTORY_SEP (*ptr)) ptr++;
1880  ptr++;
1881
1882  strncpy (readbuf, ptr, size);
1883  return readbuf;
1884}
1885
1886void
1887close_unc_volume (HANDLE henum)
1888{
1889  if (henum != INVALID_HANDLE_VALUE)
1890    WNetCloseEnum (henum);
1891}
1892
1893DWORD
1894unc_volume_file_attributes (const char *path)
1895{
1896  HANDLE henum;
1897  DWORD attrs;
1898
1899  henum = open_unc_volume (path);
1900  if (henum == INVALID_HANDLE_VALUE)
1901    return -1;
1902
1903  attrs = FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_DIRECTORY;
1904
1905  close_unc_volume (henum);
1906
1907  return attrs;
1908}
1909
1910
1911/* Shadow some MSVC runtime functions to map requests for long filenames
1912   to reasonable short names if necessary.  This was originally added to
1913   permit running Emacs on NT 3.1 on a FAT partition, which doesn't support
1914   long file names.  */
1915
1916int
1917sys_access (const char * path, int mode)
1918{
1919  DWORD attributes;
1920
1921  /* MSVC implementation doesn't recognize D_OK.  */
1922  path = map_w32_filename (path, NULL);
1923  if (is_unc_volume (path))
1924    {
1925      attributes = unc_volume_file_attributes (path);
1926      if (attributes == -1) {
1927	errno = EACCES;
1928	return -1;
1929      }
1930    }
1931  else if ((attributes = GetFileAttributes (path)) == -1)
1932    {
1933      /* Should try mapping GetLastError to errno; for now just indicate
1934	 that path doesn't exist.  */
1935      errno = EACCES;
1936      return -1;
1937    }
1938  if ((mode & X_OK) != 0 && !is_exec (path))
1939    {
1940      errno = EACCES;
1941      return -1;
1942    }
1943  if ((mode & W_OK) != 0 && (attributes & FILE_ATTRIBUTE_READONLY) != 0)
1944    {
1945      errno = EACCES;
1946      return -1;
1947    }
1948  if ((mode & D_OK) != 0 && (attributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
1949    {
1950      errno = EACCES;
1951      return -1;
1952    }
1953  return 0;
1954}
1955
1956int
1957sys_chdir (const char * path)
1958{
1959  return _chdir (map_w32_filename (path, NULL));
1960}
1961
1962int
1963sys_chmod (const char * path, int mode)
1964{
1965  return _chmod (map_w32_filename (path, NULL), mode);
1966}
1967
1968int
1969sys_chown (const char *path, uid_t owner, gid_t group)
1970{
1971  if (sys_chmod (path, _S_IREAD) == -1) /* check if file exists */
1972    return -1;
1973  return 0;
1974}
1975
1976int
1977sys_creat (const char * path, int mode)
1978{
1979  return _creat (map_w32_filename (path, NULL), mode);
1980}
1981
1982FILE *
1983sys_fopen(const char * path, const char * mode)
1984{
1985  int fd;
1986  int oflag;
1987  const char * mode_save = mode;
1988
1989  /* Force all file handles to be non-inheritable.  This is necessary to
1990     ensure child processes don't unwittingly inherit handles that might
1991     prevent future file access. */
1992
1993  if (mode[0] == 'r')
1994    oflag = O_RDONLY;
1995  else if (mode[0] == 'w' || mode[0] == 'a')
1996    oflag = O_WRONLY | O_CREAT | O_TRUNC;
1997  else
1998    return NULL;
1999
2000  /* Only do simplistic option parsing. */
2001  while (*++mode)
2002    if (mode[0] == '+')
2003      {
2004	oflag &= ~(O_RDONLY | O_WRONLY);
2005	oflag |= O_RDWR;
2006      }
2007    else if (mode[0] == 'b')
2008      {
2009	oflag &= ~O_TEXT;
2010	oflag |= O_BINARY;
2011      }
2012    else if (mode[0] == 't')
2013      {
2014	oflag &= ~O_BINARY;
2015	oflag |= O_TEXT;
2016      }
2017    else break;
2018
2019  fd = _open (map_w32_filename (path, NULL), oflag | _O_NOINHERIT, 0644);
2020  if (fd < 0)
2021    return NULL;
2022
2023  return _fdopen (fd, mode_save);
2024}
2025
2026/* This only works on NTFS volumes, but is useful to have.  */
2027int
2028sys_link (const char * old, const char * new)
2029{
2030  HANDLE fileh;
2031  int   result = -1;
2032  char oldname[MAX_PATH], newname[MAX_PATH];
2033
2034  if (old == NULL || new == NULL)
2035    {
2036      errno = ENOENT;
2037      return -1;
2038    }
2039
2040  strcpy (oldname, map_w32_filename (old, NULL));
2041  strcpy (newname, map_w32_filename (new, NULL));
2042
2043  fileh = CreateFile (oldname, 0, 0, NULL, OPEN_EXISTING,
2044		      FILE_FLAG_BACKUP_SEMANTICS, NULL);
2045  if (fileh != INVALID_HANDLE_VALUE)
2046    {
2047      int wlen;
2048
2049      /* Confusingly, the "alternate" stream name field does not apply
2050         when restoring a hard link, and instead contains the actual
2051         stream data for the link (ie. the name of the link to create).
2052         The WIN32_STREAM_ID structure before the cStreamName field is
2053         the stream header, which is then immediately followed by the
2054         stream data.  */
2055
2056      struct {
2057	WIN32_STREAM_ID wid;
2058	WCHAR wbuffer[MAX_PATH];	/* extra space for link name */
2059      } data;
2060
2061      wlen = MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, newname, -1,
2062				  data.wid.cStreamName, MAX_PATH);
2063      if (wlen > 0)
2064	{
2065	  LPVOID context = NULL;
2066	  DWORD wbytes = 0;
2067
2068	  data.wid.dwStreamId = BACKUP_LINK;
2069	  data.wid.dwStreamAttributes = 0;
2070	  data.wid.Size.LowPart = wlen * sizeof(WCHAR);
2071	  data.wid.Size.HighPart = 0;
2072	  data.wid.dwStreamNameSize = 0;
2073
2074	  if (BackupWrite (fileh, (LPBYTE)&data,
2075			   offsetof (WIN32_STREAM_ID, cStreamName)
2076			   + data.wid.Size.LowPart,
2077			   &wbytes, FALSE, FALSE, &context)
2078	      && BackupWrite (fileh, NULL, 0, &wbytes, TRUE, FALSE, &context))
2079	    {
2080	      /* succeeded */
2081	      result = 0;
2082	    }
2083	  else
2084	    {
2085	      /* Should try mapping GetLastError to errno; for now just
2086		 indicate a general error (eg. links not supported).  */
2087	      errno = EINVAL;  // perhaps EMLINK?
2088	    }
2089	}
2090
2091      CloseHandle (fileh);
2092    }
2093  else
2094    errno = ENOENT;
2095
2096  return result;
2097}
2098
2099int
2100sys_mkdir (const char * path)
2101{
2102  return _mkdir (map_w32_filename (path, NULL));
2103}
2104
2105/* Because of long name mapping issues, we need to implement this
2106   ourselves.  Also, MSVC's _mktemp returns NULL when it can't generate
2107   a unique name, instead of setting the input template to an empty
2108   string.
2109
2110   Standard algorithm seems to be use pid or tid with a letter on the
2111   front (in place of the 6 X's) and cycle through the letters to find a
2112   unique name.  We extend that to allow any reasonable character as the
2113   first of the 6 X's.  */
2114char *
2115sys_mktemp (char * template)
2116{
2117  char * p;
2118  int i;
2119  unsigned uid = GetCurrentThreadId ();
2120  static char first_char[] = "abcdefghijklmnopqrstuvwyz0123456789!%-_@#";
2121
2122  if (template == NULL)
2123    return NULL;
2124  p = template + strlen (template);
2125  i = 5;
2126  /* replace up to the last 5 X's with uid in decimal */
2127  while (--p >= template && p[0] == 'X' && --i >= 0)
2128    {
2129      p[0] = '0' + uid % 10;
2130      uid /= 10;
2131    }
2132
2133  if (i < 0 && p[0] == 'X')
2134    {
2135      i = 0;
2136      do
2137	{
2138	  int save_errno = errno;
2139	  p[0] = first_char[i];
2140	  if (sys_access (template, 0) < 0)
2141	    {
2142	      errno = save_errno;
2143	      return template;
2144	    }
2145	}
2146      while (++i < sizeof (first_char));
2147    }
2148
2149  /* Template is badly formed or else we can't generate a unique name,
2150     so return empty string */
2151  template[0] = 0;
2152  return template;
2153}
2154
2155int
2156sys_open (const char * path, int oflag, int mode)
2157{
2158  const char* mpath = map_w32_filename (path, NULL);
2159  /* Try to open file without _O_CREAT, to be able to write to hidden
2160     and system files. Force all file handles to be
2161     non-inheritable. */
2162  int res = _open (mpath, (oflag & ~_O_CREAT) | _O_NOINHERIT, mode);
2163  if (res >= 0)
2164    return res;
2165  return _open (mpath, oflag | _O_NOINHERIT, mode);
2166}
2167
2168int
2169sys_rename (const char * oldname, const char * newname)
2170{
2171  BOOL result;
2172  char temp[MAX_PATH];
2173
2174  /* MoveFile on Windows 95 doesn't correctly change the short file name
2175     alias in a number of circumstances (it is not easy to predict when
2176     just by looking at oldname and newname, unfortunately).  In these
2177     cases, renaming through a temporary name avoids the problem.
2178
2179     A second problem on Windows 95 is that renaming through a temp name when
2180     newname is uppercase fails (the final long name ends up in
2181     lowercase, although the short alias might be uppercase) UNLESS the
2182     long temp name is not 8.3.
2183
2184     So, on Windows 95 we always rename through a temp name, and we make sure
2185     the temp name has a long extension to ensure correct renaming.  */
2186
2187  strcpy (temp, map_w32_filename (oldname, NULL));
2188
2189  if (os_subtype == OS_WIN95)
2190    {
2191      char * o;
2192      char * p;
2193      int    i = 0;
2194
2195      oldname = map_w32_filename (oldname, NULL);
2196      if (o = strrchr (oldname, '\\'))
2197	o++;
2198      else
2199	o = (char *) oldname;
2200
2201      if (p = strrchr (temp, '\\'))
2202	p++;
2203      else
2204	p = temp;
2205
2206      do
2207	{
2208	  /* Force temp name to require a manufactured 8.3 alias - this
2209	     seems to make the second rename work properly.  */
2210	  sprintf (p, "_.%s.%u", o, i);
2211	  i++;
2212	  result = rename (oldname, temp);
2213	}
2214      /* This loop must surely terminate!  */
2215      while (result < 0 && errno == EEXIST);
2216      if (result < 0)
2217	return -1;
2218    }
2219
2220  /* Emulate Unix behaviour - newname is deleted if it already exists
2221     (at least if it is a file; don't do this for directories).
2222
2223     Since we mustn't do this if we are just changing the case of the
2224     file name (we would end up deleting the file we are trying to
2225     rename!), we let rename detect if the destination file already
2226     exists - that way we avoid the possible pitfalls of trying to
2227     determine ourselves whether two names really refer to the same
2228     file, which is not always possible in the general case.  (Consider
2229     all the permutations of shared or subst'd drives, etc.)  */
2230
2231  newname = map_w32_filename (newname, NULL);
2232  result = rename (temp, newname);
2233
2234  if (result < 0
2235      && errno == EEXIST
2236      && _chmod (newname, 0666) == 0
2237      && _unlink (newname) == 0)
2238    result = rename (temp, newname);
2239
2240  return result;
2241}
2242
2243int
2244sys_rmdir (const char * path)
2245{
2246  return _rmdir (map_w32_filename (path, NULL));
2247}
2248
2249int
2250sys_unlink (const char * path)
2251{
2252  path = map_w32_filename (path, NULL);
2253
2254  /* On Unix, unlink works without write permission. */
2255  _chmod (path, 0666);
2256  return _unlink (path);
2257}
2258
2259static FILETIME utc_base_ft;
2260static long double utc_base;
2261static int init = 0;
2262
2263static time_t
2264convert_time (FILETIME ft)
2265{
2266  long double ret;
2267
2268  if (!init)
2269    {
2270      /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
2271      SYSTEMTIME st;
2272
2273      st.wYear = 1970;
2274      st.wMonth = 1;
2275      st.wDay = 1;
2276      st.wHour = 0;
2277      st.wMinute = 0;
2278      st.wSecond = 0;
2279      st.wMilliseconds = 0;
2280
2281      SystemTimeToFileTime (&st, &utc_base_ft);
2282      utc_base = (long double) utc_base_ft.dwHighDateTime
2283	* 4096.0L * 1024.0L * 1024.0L + utc_base_ft.dwLowDateTime;
2284      init = 1;
2285    }
2286
2287  if (CompareFileTime (&ft, &utc_base_ft) < 0)
2288    return 0;
2289
2290  ret = (long double) ft.dwHighDateTime
2291    * 4096.0L * 1024.0L * 1024.0L + ft.dwLowDateTime;
2292  ret -= utc_base;
2293  return (time_t) (ret * 1e-7L);
2294}
2295
2296void
2297convert_from_time_t (time_t time, FILETIME * pft)
2298{
2299  long double tmp;
2300
2301  if (!init)
2302    {
2303      /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
2304      SYSTEMTIME st;
2305
2306      st.wYear = 1970;
2307      st.wMonth = 1;
2308      st.wDay = 1;
2309      st.wHour = 0;
2310      st.wMinute = 0;
2311      st.wSecond = 0;
2312      st.wMilliseconds = 0;
2313
2314      SystemTimeToFileTime (&st, &utc_base_ft);
2315      utc_base = (long double) utc_base_ft.dwHighDateTime
2316	* 4096 * 1024 * 1024 + utc_base_ft.dwLowDateTime;
2317      init = 1;
2318    }
2319
2320  /* time in 100ns units since 1-Jan-1601 */
2321  tmp = (long double) time * 1e7 + utc_base;
2322  pft->dwHighDateTime = (DWORD) (tmp / (4096.0 * 1024 * 1024));
2323  pft->dwLowDateTime = (DWORD) (tmp - (4096.0 * 1024 * 1024) * pft->dwHighDateTime);
2324}
2325
2326#if 0
2327/* No reason to keep this; faking inode values either by hashing or even
2328   using the file index from GetInformationByHandle, is not perfect and
2329   so by default Emacs doesn't use the inode values on Windows.
2330   Instead, we now determine file-truename correctly (except for
2331   possible drive aliasing etc).  */
2332
2333/*  Modified version of "PJW" algorithm (see the "Dragon" compiler book). */
2334static unsigned
2335hashval (const unsigned char * str)
2336{
2337  unsigned h = 0;
2338  while (*str)
2339    {
2340      h = (h << 4) + *str++;
2341      h ^= (h >> 28);
2342    }
2343  return h;
2344}
2345
2346/* Return the hash value of the canonical pathname, excluding the
2347   drive/UNC header, to get a hopefully unique inode number. */
2348static DWORD
2349generate_inode_val (const char * name)
2350{
2351  char fullname[ MAX_PATH ];
2352  char * p;
2353  unsigned hash;
2354
2355  /* Get the truly canonical filename, if it exists.  (Note: this
2356     doesn't resolve aliasing due to subst commands, or recognise hard
2357     links.  */
2358  if (!w32_get_long_filename ((char *)name, fullname, MAX_PATH))
2359    abort ();
2360
2361  parse_root (fullname, &p);
2362  /* Normal W32 filesystems are still case insensitive. */
2363  _strlwr (p);
2364  return hashval (p);
2365}
2366
2367#endif
2368
2369/* MSVC stat function can't cope with UNC names and has other bugs, so
2370   replace it with our own.  This also allows us to calculate consistent
2371   inode values without hacks in the main Emacs code. */
2372int
2373stat (const char * path, struct stat * buf)
2374{
2375  char *name, *r;
2376  WIN32_FIND_DATA wfd;
2377  HANDLE fh;
2378  DWORD fake_inode;
2379  int permission;
2380  int len;
2381  int rootdir = FALSE;
2382
2383  if (path == NULL || buf == NULL)
2384    {
2385      errno = EFAULT;
2386      return -1;
2387    }
2388
2389  name = (char *) map_w32_filename (path, &path);
2390  /* Must be valid filename, no wild cards or other invalid
2391     characters.  We use _mbspbrk to support multibyte strings that
2392     might look to strpbrk as if they included literal *, ?, and other
2393     characters mentioned below that are disallowed by Windows
2394     filesystems.  */
2395  if (_mbspbrk (name, "*?|<>\""))
2396    {
2397      errno = ENOENT;
2398      return -1;
2399    }
2400
2401  /* If name is "c:/.." or "/.." then stat "c:/" or "/".  */
2402  r = IS_DEVICE_SEP (name[1]) ? &name[2] : name;
2403  if (IS_DIRECTORY_SEP (r[0]) && r[1] == '.' && r[2] == '.' && r[3] == '\0')
2404    {
2405      r[1] = r[2] = '\0';
2406    }
2407
2408  /* Remove trailing directory separator, unless name is the root
2409     directory of a drive or UNC volume in which case ensure there
2410     is a trailing separator. */
2411  len = strlen (name);
2412  rootdir = (path >= name + len - 1
2413	     && (IS_DIRECTORY_SEP (*path) || *path == 0));
2414  name = strcpy (alloca (len + 2), name);
2415
2416  if (is_unc_volume (name))
2417    {
2418      DWORD attrs = unc_volume_file_attributes (name);
2419
2420      if (attrs == -1)
2421	return -1;
2422
2423      memset (&wfd, 0, sizeof (wfd));
2424      wfd.dwFileAttributes = attrs;
2425      wfd.ftCreationTime = utc_base_ft;
2426      wfd.ftLastAccessTime = utc_base_ft;
2427      wfd.ftLastWriteTime = utc_base_ft;
2428      strcpy (wfd.cFileName, name);
2429    }
2430  else if (rootdir)
2431    {
2432      if (!IS_DIRECTORY_SEP (name[len-1]))
2433	strcat (name, "\\");
2434      if (GetDriveType (name) < 2)
2435	{
2436	  errno = ENOENT;
2437	  return -1;
2438	}
2439      memset (&wfd, 0, sizeof (wfd));
2440      wfd.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY;
2441      wfd.ftCreationTime = utc_base_ft;
2442      wfd.ftLastAccessTime = utc_base_ft;
2443      wfd.ftLastWriteTime = utc_base_ft;
2444      strcpy (wfd.cFileName, name);
2445    }
2446  else
2447    {
2448      if (IS_DIRECTORY_SEP (name[len-1]))
2449	name[len - 1] = 0;
2450
2451      /* (This is hacky, but helps when doing file completions on
2452	 network drives.)  Optimize by using information available from
2453	 active readdir if possible.  */
2454      len = strlen (dir_pathname);
2455      if (IS_DIRECTORY_SEP (dir_pathname[len-1]))
2456	len--;
2457      if (dir_find_handle != INVALID_HANDLE_VALUE
2458	  && strnicmp (name, dir_pathname, len) == 0
2459	  && IS_DIRECTORY_SEP (name[len])
2460	  && stricmp (name + len + 1, dir_static.d_name) == 0)
2461	{
2462	  /* This was the last entry returned by readdir.  */
2463	  wfd = dir_find_data;
2464	}
2465      else
2466	{
2467	  fh = FindFirstFile (name, &wfd);
2468	  if (fh == INVALID_HANDLE_VALUE)
2469	    {
2470	      errno = ENOENT;
2471	      return -1;
2472	    }
2473	  FindClose (fh);
2474	}
2475    }
2476
2477  if (!NILP (Vw32_get_true_file_attributes)
2478      /* No access rights required to get info.  */
2479      && (fh = CreateFile (name, 0, 0, NULL, OPEN_EXISTING,
2480			   FILE_FLAG_BACKUP_SEMANTICS, NULL))
2481         != INVALID_HANDLE_VALUE)
2482    {
2483      /* This is more accurate in terms of gettting the correct number
2484	 of links, but is quite slow (it is noticable when Emacs is
2485	 making a list of file name completions). */
2486      BY_HANDLE_FILE_INFORMATION info;
2487
2488      if (GetFileInformationByHandle (fh, &info))
2489	{
2490	  buf->st_nlink = info.nNumberOfLinks;
2491	  /* Might as well use file index to fake inode values, but this
2492	     is not guaranteed to be unique unless we keep a handle open
2493	     all the time (even then there are situations where it is
2494	     not unique).  Reputedly, there are at most 48 bits of info
2495	     (on NTFS, presumably less on FAT). */
2496	  fake_inode = info.nFileIndexLow ^ info.nFileIndexHigh;
2497	}
2498      else
2499	{
2500	  buf->st_nlink = 1;
2501	  fake_inode = 0;
2502	}
2503
2504      if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
2505	{
2506	  buf->st_mode = _S_IFDIR;
2507	}
2508      else
2509	{
2510	  switch (GetFileType (fh))
2511	    {
2512	    case FILE_TYPE_DISK:
2513	      buf->st_mode = _S_IFREG;
2514	      break;
2515	    case FILE_TYPE_PIPE:
2516	      buf->st_mode = _S_IFIFO;
2517	      break;
2518	    case FILE_TYPE_CHAR:
2519	    case FILE_TYPE_UNKNOWN:
2520	    default:
2521	      buf->st_mode = _S_IFCHR;
2522	    }
2523	}
2524      CloseHandle (fh);
2525    }
2526  else
2527    {
2528      /* Don't bother to make this information more accurate.  */
2529      buf->st_mode = (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ?
2530	_S_IFDIR : _S_IFREG;
2531      buf->st_nlink = 1;
2532      fake_inode = 0;
2533    }
2534
2535#if 0
2536  /* Not sure if there is any point in this.  */
2537  if (!NILP (Vw32_generate_fake_inodes))
2538    fake_inode = generate_inode_val (name);
2539  else if (fake_inode == 0)
2540    {
2541      /* For want of something better, try to make everything unique.  */
2542      static DWORD gen_num = 0;
2543      fake_inode = ++gen_num;
2544    }
2545#endif
2546
2547  /* MSVC defines _ino_t to be short; other libc's might not.  */
2548  if (sizeof (buf->st_ino) == 2)
2549    buf->st_ino = fake_inode ^ (fake_inode >> 16);
2550  else
2551    buf->st_ino = fake_inode;
2552
2553  /* consider files to belong to current user */
2554  buf->st_uid = the_passwd.pw_uid;
2555  buf->st_gid = the_passwd.pw_gid;
2556
2557  /* volume_info is set indirectly by map_w32_filename */
2558  buf->st_dev = volume_info.serialnum;
2559  buf->st_rdev = volume_info.serialnum;
2560
2561
2562  buf->st_size = wfd.nFileSizeLow;
2563
2564  /* Convert timestamps to Unix format. */
2565  buf->st_mtime = convert_time (wfd.ftLastWriteTime);
2566  buf->st_atime = convert_time (wfd.ftLastAccessTime);
2567  if (buf->st_atime == 0) buf->st_atime = buf->st_mtime;
2568  buf->st_ctime = convert_time (wfd.ftCreationTime);
2569  if (buf->st_ctime == 0) buf->st_ctime = buf->st_mtime;
2570
2571  /* determine rwx permissions */
2572  if (wfd.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
2573    permission = _S_IREAD;
2574  else
2575    permission = _S_IREAD | _S_IWRITE;
2576
2577  if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
2578    permission |= _S_IEXEC;
2579  else if (is_exec (name))
2580    permission |= _S_IEXEC;
2581
2582  buf->st_mode |= permission | (permission >> 3) | (permission >> 6);
2583
2584  return 0;
2585}
2586
2587/* Provide fstat and utime as well as stat for consistent handling of
2588   file timestamps. */
2589int
2590fstat (int desc, struct stat * buf)
2591{
2592  HANDLE fh = (HANDLE) _get_osfhandle (desc);
2593  BY_HANDLE_FILE_INFORMATION info;
2594  DWORD fake_inode;
2595  int permission;
2596
2597  switch (GetFileType (fh) & ~FILE_TYPE_REMOTE)
2598    {
2599    case FILE_TYPE_DISK:
2600      buf->st_mode = _S_IFREG;
2601      if (!GetFileInformationByHandle (fh, &info))
2602	{
2603	  errno = EACCES;
2604	  return -1;
2605	}
2606      break;
2607    case FILE_TYPE_PIPE:
2608      buf->st_mode = _S_IFIFO;
2609      goto non_disk;
2610    case FILE_TYPE_CHAR:
2611    case FILE_TYPE_UNKNOWN:
2612    default:
2613      buf->st_mode = _S_IFCHR;
2614    non_disk:
2615      memset (&info, 0, sizeof (info));
2616      info.dwFileAttributes = 0;
2617      info.ftCreationTime = utc_base_ft;
2618      info.ftLastAccessTime = utc_base_ft;
2619      info.ftLastWriteTime = utc_base_ft;
2620    }
2621
2622  if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
2623      buf->st_mode = _S_IFDIR;
2624
2625  buf->st_nlink = info.nNumberOfLinks;
2626  /* Might as well use file index to fake inode values, but this
2627     is not guaranteed to be unique unless we keep a handle open
2628     all the time (even then there are situations where it is
2629     not unique).  Reputedly, there are at most 48 bits of info
2630     (on NTFS, presumably less on FAT). */
2631  fake_inode = info.nFileIndexLow ^ info.nFileIndexHigh;
2632
2633  /* MSVC defines _ino_t to be short; other libc's might not.  */
2634  if (sizeof (buf->st_ino) == 2)
2635    buf->st_ino = fake_inode ^ (fake_inode >> 16);
2636  else
2637    buf->st_ino = fake_inode;
2638
2639  /* consider files to belong to current user */
2640  buf->st_uid = 0;
2641  buf->st_gid = 0;
2642
2643  buf->st_dev = info.dwVolumeSerialNumber;
2644  buf->st_rdev = info.dwVolumeSerialNumber;
2645
2646  buf->st_size = info.nFileSizeLow;
2647
2648  /* Convert timestamps to Unix format. */
2649  buf->st_mtime = convert_time (info.ftLastWriteTime);
2650  buf->st_atime = convert_time (info.ftLastAccessTime);
2651  if (buf->st_atime == 0) buf->st_atime = buf->st_mtime;
2652  buf->st_ctime = convert_time (info.ftCreationTime);
2653  if (buf->st_ctime == 0) buf->st_ctime = buf->st_mtime;
2654
2655  /* determine rwx permissions */
2656  if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
2657    permission = _S_IREAD;
2658  else
2659    permission = _S_IREAD | _S_IWRITE;
2660
2661  if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
2662    permission |= _S_IEXEC;
2663  else
2664    {
2665#if 0 /* no way of knowing the filename */
2666      char * p = strrchr (name, '.');
2667      if (p != NULL &&
2668	  (stricmp (p, ".exe") == 0 ||
2669	   stricmp (p, ".com") == 0 ||
2670	   stricmp (p, ".bat") == 0 ||
2671	   stricmp (p, ".cmd") == 0))
2672	permission |= _S_IEXEC;
2673#endif
2674    }
2675
2676  buf->st_mode |= permission | (permission >> 3) | (permission >> 6);
2677
2678  return 0;
2679}
2680
2681int
2682utime (const char *name, struct utimbuf *times)
2683{
2684  struct utimbuf deftime;
2685  HANDLE fh;
2686  FILETIME mtime;
2687  FILETIME atime;
2688
2689  if (times == NULL)
2690    {
2691      deftime.modtime = deftime.actime = time (NULL);
2692      times = &deftime;
2693    }
2694
2695  /* Need write access to set times.  */
2696  fh = CreateFile (name, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
2697		   0, OPEN_EXISTING, 0, NULL);
2698  if (fh)
2699    {
2700      convert_from_time_t (times->actime, &atime);
2701      convert_from_time_t (times->modtime, &mtime);
2702      if (!SetFileTime (fh, NULL, &atime, &mtime))
2703	{
2704	  CloseHandle (fh);
2705	  errno = EACCES;
2706	  return -1;
2707	}
2708      CloseHandle (fh);
2709    }
2710  else
2711    {
2712      errno = EINVAL;
2713      return -1;
2714    }
2715  return 0;
2716}
2717
2718#ifdef HAVE_SOCKETS
2719
2720/* Wrappers for  winsock functions to map between our file descriptors
2721   and winsock's handles; also set h_errno for convenience.
2722
2723   To allow Emacs to run on systems which don't have winsock support
2724   installed, we dynamically link to winsock on startup if present, and
2725   otherwise provide the minimum necessary functionality
2726   (eg. gethostname). */
2727
2728/* function pointers for relevant socket functions */
2729int (PASCAL *pfn_WSAStartup) (WORD wVersionRequired, LPWSADATA lpWSAData);
2730void (PASCAL *pfn_WSASetLastError) (int iError);
2731int (PASCAL *pfn_WSAGetLastError) (void);
2732int (PASCAL *pfn_WSAEventSelect) (SOCKET s, HANDLE hEventObject, long lNetworkEvents);
2733HANDLE (PASCAL *pfn_WSACreateEvent) (void);
2734int (PASCAL *pfn_WSACloseEvent) (HANDLE hEvent);
2735int (PASCAL *pfn_socket) (int af, int type, int protocol);
2736int (PASCAL *pfn_bind) (SOCKET s, const struct sockaddr *addr, int namelen);
2737int (PASCAL *pfn_connect) (SOCKET s, const struct sockaddr *addr, int namelen);
2738int (PASCAL *pfn_ioctlsocket) (SOCKET s, long cmd, u_long *argp);
2739int (PASCAL *pfn_recv) (SOCKET s, char * buf, int len, int flags);
2740int (PASCAL *pfn_send) (SOCKET s, const char * buf, int len, int flags);
2741int (PASCAL *pfn_closesocket) (SOCKET s);
2742int (PASCAL *pfn_shutdown) (SOCKET s, int how);
2743int (PASCAL *pfn_WSACleanup) (void);
2744
2745u_short (PASCAL *pfn_htons) (u_short hostshort);
2746u_short (PASCAL *pfn_ntohs) (u_short netshort);
2747unsigned long (PASCAL *pfn_inet_addr) (const char * cp);
2748int (PASCAL *pfn_gethostname) (char * name, int namelen);
2749struct hostent * (PASCAL *pfn_gethostbyname) (const char * name);
2750struct servent * (PASCAL *pfn_getservbyname) (const char * name, const char * proto);
2751int (PASCAL *pfn_getpeername) (SOCKET s, struct sockaddr *addr, int * namelen);
2752int (PASCAL *pfn_setsockopt) (SOCKET s, int level, int optname,
2753			      const char * optval, int optlen);
2754int (PASCAL *pfn_listen) (SOCKET s, int backlog);
2755int (PASCAL *pfn_getsockname) (SOCKET s, struct sockaddr * name,
2756			       int * namelen);
2757SOCKET (PASCAL *pfn_accept) (SOCKET s, struct sockaddr * addr, int * addrlen);
2758int (PASCAL *pfn_recvfrom) (SOCKET s, char * buf, int len, int flags,
2759		       struct sockaddr * from, int * fromlen);
2760int (PASCAL *pfn_sendto) (SOCKET s, const char * buf, int len, int flags,
2761			  const struct sockaddr * to, int tolen);
2762
2763/* SetHandleInformation is only needed to make sockets non-inheritable. */
2764BOOL (WINAPI *pfn_SetHandleInformation) (HANDLE object, DWORD mask, DWORD flags);
2765#ifndef HANDLE_FLAG_INHERIT
2766#define HANDLE_FLAG_INHERIT	1
2767#endif
2768
2769HANDLE winsock_lib;
2770static int winsock_inuse;
2771
2772BOOL
2773term_winsock (void)
2774{
2775  if (winsock_lib != NULL && winsock_inuse == 0)
2776    {
2777      /* Not sure what would cause WSAENETDOWN, or even if it can happen
2778	 after WSAStartup returns successfully, but it seems reasonable
2779	 to allow unloading winsock anyway in that case. */
2780      if (pfn_WSACleanup () == 0 ||
2781	  pfn_WSAGetLastError () == WSAENETDOWN)
2782	{
2783	  if (FreeLibrary (winsock_lib))
2784	  winsock_lib = NULL;
2785	  return TRUE;
2786	}
2787    }
2788  return FALSE;
2789}
2790
2791BOOL
2792init_winsock (int load_now)
2793{
2794  WSADATA  winsockData;
2795
2796  if (winsock_lib != NULL)
2797    return TRUE;
2798
2799  pfn_SetHandleInformation = NULL;
2800  pfn_SetHandleInformation
2801    = (void *) GetProcAddress (GetModuleHandle ("kernel32.dll"),
2802			       "SetHandleInformation");
2803
2804  winsock_lib = LoadLibrary ("Ws2_32.dll");
2805
2806  if (winsock_lib != NULL)
2807    {
2808      /* dynamically link to socket functions */
2809
2810#define LOAD_PROC(fn) \
2811      if ((pfn_##fn = (void *) GetProcAddress (winsock_lib, #fn)) == NULL) \
2812        goto fail;
2813
2814      LOAD_PROC( WSAStartup );
2815      LOAD_PROC( WSASetLastError );
2816      LOAD_PROC( WSAGetLastError );
2817      LOAD_PROC( WSAEventSelect );
2818      LOAD_PROC( WSACreateEvent );
2819      LOAD_PROC( WSACloseEvent );
2820      LOAD_PROC( socket );
2821      LOAD_PROC( bind );
2822      LOAD_PROC( connect );
2823      LOAD_PROC( ioctlsocket );
2824      LOAD_PROC( recv );
2825      LOAD_PROC( send );
2826      LOAD_PROC( closesocket );
2827      LOAD_PROC( shutdown );
2828      LOAD_PROC( htons );
2829      LOAD_PROC( ntohs );
2830      LOAD_PROC( inet_addr );
2831      LOAD_PROC( gethostname );
2832      LOAD_PROC( gethostbyname );
2833      LOAD_PROC( getservbyname );
2834      LOAD_PROC( getpeername );
2835      LOAD_PROC( WSACleanup );
2836      LOAD_PROC( setsockopt );
2837      LOAD_PROC( listen );
2838      LOAD_PROC( getsockname );
2839      LOAD_PROC( accept );
2840      LOAD_PROC( recvfrom );
2841      LOAD_PROC( sendto );
2842#undef LOAD_PROC
2843
2844      /* specify version 1.1 of winsock */
2845      if (pfn_WSAStartup (0x101, &winsockData) == 0)
2846        {
2847	  if (winsockData.wVersion != 0x101)
2848	    goto fail;
2849
2850	  if (!load_now)
2851	    {
2852	      /* Report that winsock exists and is usable, but leave
2853		 socket functions disabled.  I am assuming that calling
2854		 WSAStartup does not require any network interaction,
2855		 and in particular does not cause or require a dial-up
2856		 connection to be established. */
2857
2858	      pfn_WSACleanup ();
2859	      FreeLibrary (winsock_lib);
2860	      winsock_lib = NULL;
2861	    }
2862	  winsock_inuse = 0;
2863	  return TRUE;
2864	}
2865
2866    fail:
2867      FreeLibrary (winsock_lib);
2868      winsock_lib = NULL;
2869    }
2870
2871  return FALSE;
2872}
2873
2874
2875int h_errno = 0;
2876
2877/* function to set h_errno for compatability; map winsock error codes to
2878   normal system codes where they overlap (non-overlapping definitions
2879   are already in <sys/socket.h> */
2880static void
2881set_errno ()
2882{
2883  if (winsock_lib == NULL)
2884    h_errno = EINVAL;
2885  else
2886    h_errno = pfn_WSAGetLastError ();
2887
2888  switch (h_errno)
2889    {
2890    case WSAEACCES:		h_errno = EACCES; break;
2891    case WSAEBADF: 		h_errno = EBADF; break;
2892    case WSAEFAULT:		h_errno = EFAULT; break;
2893    case WSAEINTR: 		h_errno = EINTR; break;
2894    case WSAEINVAL:		h_errno = EINVAL; break;
2895    case WSAEMFILE:		h_errno = EMFILE; break;
2896    case WSAENAMETOOLONG: 	h_errno = ENAMETOOLONG; break;
2897    case WSAENOTEMPTY:		h_errno = ENOTEMPTY; break;
2898    }
2899  errno = h_errno;
2900}
2901
2902static void
2903check_errno ()
2904{
2905  if (h_errno == 0 && winsock_lib != NULL)
2906    pfn_WSASetLastError (0);
2907}
2908
2909/* Extend strerror to handle the winsock-specific error codes.  */
2910struct {
2911  int errnum;
2912  char * msg;
2913} _wsa_errlist[] = {
2914  WSAEINTR                , "Interrupted function call",
2915  WSAEBADF                , "Bad file descriptor",
2916  WSAEACCES               , "Permission denied",
2917  WSAEFAULT               , "Bad address",
2918  WSAEINVAL               , "Invalid argument",
2919  WSAEMFILE               , "Too many open files",
2920
2921  WSAEWOULDBLOCK          , "Resource temporarily unavailable",
2922  WSAEINPROGRESS          , "Operation now in progress",
2923  WSAEALREADY             , "Operation already in progress",
2924  WSAENOTSOCK             , "Socket operation on non-socket",
2925  WSAEDESTADDRREQ         , "Destination address required",
2926  WSAEMSGSIZE             , "Message too long",
2927  WSAEPROTOTYPE           , "Protocol wrong type for socket",
2928  WSAENOPROTOOPT          , "Bad protocol option",
2929  WSAEPROTONOSUPPORT      , "Protocol not supported",
2930  WSAESOCKTNOSUPPORT      , "Socket type not supported",
2931  WSAEOPNOTSUPP           , "Operation not supported",
2932  WSAEPFNOSUPPORT         , "Protocol family not supported",
2933  WSAEAFNOSUPPORT         , "Address family not supported by protocol family",
2934  WSAEADDRINUSE           , "Address already in use",
2935  WSAEADDRNOTAVAIL        , "Cannot assign requested address",
2936  WSAENETDOWN             , "Network is down",
2937  WSAENETUNREACH          , "Network is unreachable",
2938  WSAENETRESET            , "Network dropped connection on reset",
2939  WSAECONNABORTED         , "Software caused connection abort",
2940  WSAECONNRESET           , "Connection reset by peer",
2941  WSAENOBUFS              , "No buffer space available",
2942  WSAEISCONN              , "Socket is already connected",
2943  WSAENOTCONN             , "Socket is not connected",
2944  WSAESHUTDOWN            , "Cannot send after socket shutdown",
2945  WSAETOOMANYREFS         , "Too many references",	    /* not sure */
2946  WSAETIMEDOUT            , "Connection timed out",
2947  WSAECONNREFUSED         , "Connection refused",
2948  WSAELOOP                , "Network loop",		    /* not sure */
2949  WSAENAMETOOLONG         , "Name is too long",
2950  WSAEHOSTDOWN            , "Host is down",
2951  WSAEHOSTUNREACH         , "No route to host",
2952  WSAENOTEMPTY            , "Buffer not empty",		    /* not sure */
2953  WSAEPROCLIM             , "Too many processes",
2954  WSAEUSERS               , "Too many users",		    /* not sure */
2955  WSAEDQUOT               , "Double quote in host name",    /* really not sure */
2956  WSAESTALE               , "Data is stale",		    /* not sure */
2957  WSAEREMOTE              , "Remote error",		    /* not sure */
2958
2959  WSASYSNOTREADY          , "Network subsystem is unavailable",
2960  WSAVERNOTSUPPORTED      , "WINSOCK.DLL version out of range",
2961  WSANOTINITIALISED       , "Winsock not initialized successfully",
2962  WSAEDISCON              , "Graceful shutdown in progress",
2963#ifdef WSAENOMORE
2964  WSAENOMORE              , "No more operations allowed",   /* not sure */
2965  WSAECANCELLED           , "Operation cancelled",	    /* not sure */
2966  WSAEINVALIDPROCTABLE    , "Invalid procedure table from service provider",
2967  WSAEINVALIDPROVIDER     , "Invalid service provider version number",
2968  WSAEPROVIDERFAILEDINIT  , "Unable to initialize a service provider",
2969  WSASYSCALLFAILURE       , "System call failured",
2970  WSASERVICE_NOT_FOUND    , "Service not found",	    /* not sure */
2971  WSATYPE_NOT_FOUND       , "Class type not found",
2972  WSA_E_NO_MORE           , "No more resources available",  /* really not sure */
2973  WSA_E_CANCELLED         , "Operation already cancelled",  /* really not sure */
2974  WSAEREFUSED             , "Operation refused",	    /* not sure */
2975#endif
2976
2977  WSAHOST_NOT_FOUND       , "Host not found",
2978  WSATRY_AGAIN            , "Authoritative host not found during name lookup",
2979  WSANO_RECOVERY          , "Non-recoverable error during name lookup",
2980  WSANO_DATA              , "Valid name, no data record of requested type",
2981
2982  -1, NULL
2983};
2984
2985char *
2986sys_strerror(int error_no)
2987{
2988  int i;
2989  static char unknown_msg[40];
2990
2991  if (error_no >= 0 && error_no < sys_nerr)
2992    return sys_errlist[error_no];
2993
2994  for (i = 0; _wsa_errlist[i].errnum >= 0; i++)
2995    if (_wsa_errlist[i].errnum == error_no)
2996      return _wsa_errlist[i].msg;
2997
2998  sprintf(unknown_msg, "Unidentified error: %d", error_no);
2999  return unknown_msg;
3000}
3001
3002/* [andrewi 3-May-96] I've had conflicting results using both methods,
3003   but I believe the method of keeping the socket handle separate (and
3004   insuring it is not inheritable) is the correct one. */
3005
3006//#define SOCK_REPLACE_HANDLE
3007
3008#ifdef SOCK_REPLACE_HANDLE
3009#define SOCK_HANDLE(fd) ((SOCKET) _get_osfhandle (fd))
3010#else
3011#define SOCK_HANDLE(fd) ((SOCKET) fd_info[fd].hnd)
3012#endif
3013
3014int socket_to_fd (SOCKET s);
3015
3016int
3017sys_socket(int af, int type, int protocol)
3018{
3019  SOCKET s;
3020
3021  if (winsock_lib == NULL)
3022    {
3023      h_errno = ENETDOWN;
3024      return INVALID_SOCKET;
3025    }
3026
3027  check_errno ();
3028
3029  /* call the real socket function */
3030  s = pfn_socket (af, type, protocol);
3031
3032  if (s != INVALID_SOCKET)
3033    return socket_to_fd (s);
3034
3035  set_errno ();
3036  return -1;
3037}
3038
3039/* Convert a SOCKET to a file descriptor.  */
3040int
3041socket_to_fd (SOCKET s)
3042{
3043  int fd;
3044  child_process * cp;
3045
3046  /* Although under NT 3.5 _open_osfhandle will accept a socket
3047     handle, if opened with SO_OPENTYPE == SO_SYNCHRONOUS_NONALERT,
3048     that does not work under NT 3.1.  However, we can get the same
3049     effect by using a backdoor function to replace an existing
3050     descriptor handle with the one we want. */
3051
3052  /* allocate a file descriptor (with appropriate flags) */
3053  fd = _open ("NUL:", _O_RDWR);
3054  if (fd >= 0)
3055    {
3056#ifdef SOCK_REPLACE_HANDLE
3057      /* now replace handle to NUL with our socket handle */
3058      CloseHandle ((HANDLE) _get_osfhandle (fd));
3059      _free_osfhnd (fd);
3060      _set_osfhnd (fd, s);
3061      /* setmode (fd, _O_BINARY); */
3062#else
3063      /* Make a non-inheritable copy of the socket handle.  Note
3064	 that it is possible that sockets aren't actually kernel
3065	 handles, which appears to be the case on Windows 9x when
3066	 the MS Proxy winsock client is installed.  */
3067      {
3068	/* Apparently there is a bug in NT 3.51 with some service
3069	   packs, which prevents using DuplicateHandle to make a
3070	   socket handle non-inheritable (causes WSACleanup to
3071	   hang).  The work-around is to use SetHandleInformation
3072	   instead if it is available and implemented. */
3073	if (pfn_SetHandleInformation)
3074	  {
3075	    pfn_SetHandleInformation ((HANDLE) s, HANDLE_FLAG_INHERIT, 0);
3076	  }
3077	else
3078	  {
3079	    HANDLE parent = GetCurrentProcess ();
3080	    HANDLE new_s = INVALID_HANDLE_VALUE;
3081
3082	    if (DuplicateHandle (parent,
3083				 (HANDLE) s,
3084				 parent,
3085				 &new_s,
3086				 0,
3087				 FALSE,
3088				 DUPLICATE_SAME_ACCESS))
3089	      {
3090		/* It is possible that DuplicateHandle succeeds even
3091		   though the socket wasn't really a kernel handle,
3092		   because a real handle has the same value.  So
3093		   test whether the new handle really is a socket.  */
3094		long nonblocking = 0;
3095		if (pfn_ioctlsocket ((SOCKET) new_s, FIONBIO, &nonblocking) == 0)
3096		  {
3097		    pfn_closesocket (s);
3098		    s = (SOCKET) new_s;
3099		  }
3100		else
3101		  {
3102		    CloseHandle (new_s);
3103		  }
3104	      }
3105	  }
3106      }
3107      fd_info[fd].hnd = (HANDLE) s;
3108#endif
3109
3110      /* set our own internal flags */
3111      fd_info[fd].flags = FILE_SOCKET | FILE_BINARY | FILE_READ | FILE_WRITE;
3112
3113      cp = new_child ();
3114      if (cp)
3115	{
3116	  cp->fd = fd;
3117	  cp->status = STATUS_READ_ACKNOWLEDGED;
3118
3119	  /* attach child_process to fd_info */
3120	  if (fd_info[ fd ].cp != NULL)
3121	    {
3122	      DebPrint (("sys_socket: fd_info[%d] apparently in use!\n", fd));
3123	      abort ();
3124	    }
3125
3126	  fd_info[ fd ].cp = cp;
3127
3128	  /* success! */
3129	  winsock_inuse++;	/* count open sockets */
3130	  return fd;
3131	}
3132
3133      /* clean up */
3134      _close (fd);
3135    }
3136  pfn_closesocket (s);
3137  h_errno = EMFILE;
3138  return -1;
3139}
3140
3141
3142int
3143sys_bind (int s, const struct sockaddr * addr, int namelen)
3144{
3145  if (winsock_lib == NULL)
3146    {
3147      h_errno = ENOTSOCK;
3148      return SOCKET_ERROR;
3149    }
3150
3151  check_errno ();
3152  if (fd_info[s].flags & FILE_SOCKET)
3153    {
3154      int rc = pfn_bind (SOCK_HANDLE (s), addr, namelen);
3155      if (rc == SOCKET_ERROR)
3156	set_errno ();
3157      return rc;
3158    }
3159  h_errno = ENOTSOCK;
3160  return SOCKET_ERROR;
3161}
3162
3163
3164int
3165sys_connect (int s, const struct sockaddr * name, int namelen)
3166{
3167  if (winsock_lib == NULL)
3168    {
3169      h_errno = ENOTSOCK;
3170      return SOCKET_ERROR;
3171    }
3172
3173  check_errno ();
3174  if (fd_info[s].flags & FILE_SOCKET)
3175    {
3176      int rc = pfn_connect (SOCK_HANDLE (s), name, namelen);
3177      if (rc == SOCKET_ERROR)
3178	set_errno ();
3179      return rc;
3180    }
3181  h_errno = ENOTSOCK;
3182  return SOCKET_ERROR;
3183}
3184
3185u_short
3186sys_htons (u_short hostshort)
3187{
3188  return (winsock_lib != NULL) ?
3189    pfn_htons (hostshort) : hostshort;
3190}
3191
3192u_short
3193sys_ntohs (u_short netshort)
3194{
3195  return (winsock_lib != NULL) ?
3196    pfn_ntohs (netshort) : netshort;
3197}
3198
3199unsigned long
3200sys_inet_addr (const char * cp)
3201{
3202  return (winsock_lib != NULL) ?
3203    pfn_inet_addr (cp) : INADDR_NONE;
3204}
3205
3206int
3207sys_gethostname (char * name, int namelen)
3208{
3209  if (winsock_lib != NULL)
3210    return pfn_gethostname (name, namelen);
3211
3212  if (namelen > MAX_COMPUTERNAME_LENGTH)
3213    return !GetComputerName (name, (DWORD *)&namelen);
3214
3215  h_errno = EFAULT;
3216  return SOCKET_ERROR;
3217}
3218
3219struct hostent *
3220sys_gethostbyname(const char * name)
3221{
3222  struct hostent * host;
3223
3224  if (winsock_lib == NULL)
3225    {
3226      h_errno = ENETDOWN;
3227      return NULL;
3228    }
3229
3230  check_errno ();
3231  host = pfn_gethostbyname (name);
3232  if (!host)
3233    set_errno ();
3234  return host;
3235}
3236
3237struct servent *
3238sys_getservbyname(const char * name, const char * proto)
3239{
3240  struct servent * serv;
3241
3242  if (winsock_lib == NULL)
3243    {
3244      h_errno = ENETDOWN;
3245      return NULL;
3246    }
3247
3248  check_errno ();
3249  serv = pfn_getservbyname (name, proto);
3250  if (!serv)
3251    set_errno ();
3252  return serv;
3253}
3254
3255int
3256sys_getpeername (int s, struct sockaddr *addr, int * namelen)
3257{
3258  if (winsock_lib == NULL)
3259    {
3260      h_errno = ENETDOWN;
3261      return SOCKET_ERROR;
3262    }
3263
3264  check_errno ();
3265  if (fd_info[s].flags & FILE_SOCKET)
3266    {
3267      int rc = pfn_getpeername (SOCK_HANDLE (s), addr, namelen);
3268      if (rc == SOCKET_ERROR)
3269	set_errno ();
3270      return rc;
3271    }
3272  h_errno = ENOTSOCK;
3273  return SOCKET_ERROR;
3274}
3275
3276
3277int
3278sys_shutdown (int s, int how)
3279{
3280  if (winsock_lib == NULL)
3281    {
3282      h_errno = ENETDOWN;
3283      return SOCKET_ERROR;
3284    }
3285
3286  check_errno ();
3287  if (fd_info[s].flags & FILE_SOCKET)
3288    {
3289      int rc = pfn_shutdown (SOCK_HANDLE (s), how);
3290      if (rc == SOCKET_ERROR)
3291	set_errno ();
3292      return rc;
3293    }
3294  h_errno = ENOTSOCK;
3295  return SOCKET_ERROR;
3296}
3297
3298int
3299sys_setsockopt (int s, int level, int optname, const void * optval, int optlen)
3300{
3301  if (winsock_lib == NULL)
3302    {
3303      h_errno = ENETDOWN;
3304      return SOCKET_ERROR;
3305    }
3306
3307  check_errno ();
3308  if (fd_info[s].flags & FILE_SOCKET)
3309    {
3310      int rc = pfn_setsockopt (SOCK_HANDLE (s), level, optname,
3311			       (const char *)optval, optlen);
3312      if (rc == SOCKET_ERROR)
3313	set_errno ();
3314      return rc;
3315    }
3316  h_errno = ENOTSOCK;
3317  return SOCKET_ERROR;
3318}
3319
3320int
3321sys_listen (int s, int backlog)
3322{
3323  if (winsock_lib == NULL)
3324    {
3325      h_errno = ENETDOWN;
3326      return SOCKET_ERROR;
3327    }
3328
3329  check_errno ();
3330  if (fd_info[s].flags & FILE_SOCKET)
3331    {
3332      int rc = pfn_listen (SOCK_HANDLE (s), backlog);
3333      if (rc == SOCKET_ERROR)
3334	set_errno ();
3335      else
3336	fd_info[s].flags |= FILE_LISTEN;
3337      return rc;
3338    }
3339  h_errno = ENOTSOCK;
3340  return SOCKET_ERROR;
3341}
3342
3343int
3344sys_getsockname (int s, struct sockaddr * name, int * namelen)
3345{
3346  if (winsock_lib == NULL)
3347    {
3348      h_errno = ENETDOWN;
3349      return SOCKET_ERROR;
3350    }
3351
3352  check_errno ();
3353  if (fd_info[s].flags & FILE_SOCKET)
3354    {
3355      int rc = pfn_getsockname (SOCK_HANDLE (s), name, namelen);
3356      if (rc == SOCKET_ERROR)
3357	set_errno ();
3358      return rc;
3359    }
3360  h_errno = ENOTSOCK;
3361  return SOCKET_ERROR;
3362}
3363
3364int
3365sys_accept (int s, struct sockaddr * addr, int * addrlen)
3366{
3367  if (winsock_lib == NULL)
3368    {
3369      h_errno = ENETDOWN;
3370      return -1;
3371    }
3372
3373  check_errno ();
3374  if (fd_info[s].flags & FILE_LISTEN)
3375    {
3376      SOCKET t = pfn_accept (SOCK_HANDLE (s), addr, addrlen);
3377      int fd = -1;
3378      if (t == INVALID_SOCKET)
3379	set_errno ();
3380      else
3381	fd = socket_to_fd (t);
3382
3383      fd_info[s].cp->status = STATUS_READ_ACKNOWLEDGED;
3384      ResetEvent (fd_info[s].cp->char_avail);
3385      return fd;
3386    }
3387  h_errno = ENOTSOCK;
3388  return -1;
3389}
3390
3391int
3392sys_recvfrom (int s, char * buf, int len, int flags,
3393	  struct sockaddr * from, int * fromlen)
3394{
3395  if (winsock_lib == NULL)
3396    {
3397      h_errno = ENETDOWN;
3398      return SOCKET_ERROR;
3399    }
3400
3401  check_errno ();
3402  if (fd_info[s].flags & FILE_SOCKET)
3403    {
3404      int rc = pfn_recvfrom (SOCK_HANDLE (s), buf, len, flags, from, fromlen);
3405      if (rc == SOCKET_ERROR)
3406	set_errno ();
3407      return rc;
3408    }
3409  h_errno = ENOTSOCK;
3410  return SOCKET_ERROR;
3411}
3412
3413int
3414sys_sendto (int s, const char * buf, int len, int flags,
3415	    const struct sockaddr * to, int tolen)
3416{
3417  if (winsock_lib == NULL)
3418    {
3419      h_errno = ENETDOWN;
3420      return SOCKET_ERROR;
3421    }
3422
3423  check_errno ();
3424  if (fd_info[s].flags & FILE_SOCKET)
3425    {
3426      int rc = pfn_sendto (SOCK_HANDLE (s), buf, len, flags, to, tolen);
3427      if (rc == SOCKET_ERROR)
3428	set_errno ();
3429      return rc;
3430    }
3431  h_errno = ENOTSOCK;
3432  return SOCKET_ERROR;
3433}
3434
3435/* Windows does not have an fcntl function.  Provide an implementation
3436   solely for making sockets non-blocking.  */
3437int
3438fcntl (int s, int cmd, int options)
3439{
3440  if (winsock_lib == NULL)
3441    {
3442      h_errno = ENETDOWN;
3443      return -1;
3444    }
3445
3446  check_errno ();
3447  if (fd_info[s].flags & FILE_SOCKET)
3448    {
3449      if (cmd == F_SETFL && options == O_NDELAY)
3450	{
3451	  unsigned long nblock = 1;
3452	  int rc = pfn_ioctlsocket (SOCK_HANDLE (s), FIONBIO, &nblock);
3453	  if (rc == SOCKET_ERROR)
3454	    set_errno();
3455	  /* Keep track of the fact that we set this to non-blocking.  */
3456	  fd_info[s].flags |= FILE_NDELAY;
3457	  return rc;
3458	}
3459      else
3460	{
3461	  h_errno = EINVAL;
3462	  return SOCKET_ERROR;
3463	}
3464    }
3465  h_errno = ENOTSOCK;
3466  return SOCKET_ERROR;
3467}
3468
3469#endif /* HAVE_SOCKETS */
3470
3471
3472/* Shadow main io functions: we need to handle pipes and sockets more
3473   intelligently, and implement non-blocking mode as well. */
3474
3475int
3476sys_close (int fd)
3477{
3478  int rc;
3479
3480  if (fd < 0)
3481    {
3482      errno = EBADF;
3483      return -1;
3484    }
3485
3486  if (fd < MAXDESC && fd_info[fd].cp)
3487    {
3488      child_process * cp = fd_info[fd].cp;
3489
3490      fd_info[fd].cp = NULL;
3491
3492      if (CHILD_ACTIVE (cp))
3493        {
3494	  /* if last descriptor to active child_process then cleanup */
3495	  int i;
3496	  for (i = 0; i < MAXDESC; i++)
3497	    {
3498	      if (i == fd)
3499		continue;
3500	      if (fd_info[i].cp == cp)
3501		break;
3502	    }
3503	  if (i == MAXDESC)
3504	    {
3505#ifdef HAVE_SOCKETS
3506	      if (fd_info[fd].flags & FILE_SOCKET)
3507		{
3508#ifndef SOCK_REPLACE_HANDLE
3509		  if (winsock_lib == NULL) abort ();
3510
3511		  pfn_shutdown (SOCK_HANDLE (fd), 2);
3512		  rc = pfn_closesocket (SOCK_HANDLE (fd));
3513#endif
3514		  winsock_inuse--; /* count open sockets */
3515		}
3516#endif
3517	      delete_child (cp);
3518	    }
3519	}
3520    }
3521
3522  /* Note that sockets do not need special treatment here (at least on
3523     NT and Windows 95 using the standard tcp/ip stacks) - it appears that
3524     closesocket is equivalent to CloseHandle, which is to be expected
3525     because socket handles are fully fledged kernel handles. */
3526  rc = _close (fd);
3527
3528  if (rc == 0 && fd < MAXDESC)
3529    fd_info[fd].flags = 0;
3530
3531  return rc;
3532}
3533
3534int
3535sys_dup (int fd)
3536{
3537  int new_fd;
3538
3539  new_fd = _dup (fd);
3540  if (new_fd >= 0 && new_fd < MAXDESC)
3541    {
3542      /* duplicate our internal info as well */
3543      fd_info[new_fd] = fd_info[fd];
3544    }
3545  return new_fd;
3546}
3547
3548
3549int
3550sys_dup2 (int src, int dst)
3551{
3552  int rc;
3553
3554  if (dst < 0 || dst >= MAXDESC)
3555    {
3556      errno = EBADF;
3557      return -1;
3558    }
3559
3560  /* make sure we close the destination first if it's a pipe or socket */
3561  if (src != dst && fd_info[dst].flags != 0)
3562    sys_close (dst);
3563
3564  rc = _dup2 (src, dst);
3565  if (rc == 0)
3566    {
3567      /* duplicate our internal info as well */
3568      fd_info[dst] = fd_info[src];
3569    }
3570  return rc;
3571}
3572
3573/* Unix pipe() has only one arg */
3574int
3575sys_pipe (int * phandles)
3576{
3577  int rc;
3578  unsigned flags;
3579
3580  /* make pipe handles non-inheritable; when we spawn a child, we
3581     replace the relevant handle with an inheritable one.  Also put
3582     pipes into binary mode; we will do text mode translation ourselves
3583     if required.  */
3584  rc = _pipe (phandles, 0, _O_NOINHERIT | _O_BINARY);
3585
3586  if (rc == 0)
3587    {
3588      /* Protect against overflow, since Windows can open more handles than
3589	 our fd_info array has room for.  */
3590      if (phandles[0] >= MAXDESC || phandles[1] >= MAXDESC)
3591	{
3592	  _close (phandles[0]);
3593	  _close (phandles[1]);
3594	  rc = -1;
3595	}
3596      else
3597	{
3598	  flags = FILE_PIPE | FILE_READ | FILE_BINARY;
3599	  fd_info[phandles[0]].flags = flags;
3600
3601	  flags = FILE_PIPE | FILE_WRITE | FILE_BINARY;
3602	  fd_info[phandles[1]].flags = flags;
3603	}
3604    }
3605
3606  return rc;
3607}
3608
3609/* From ntproc.c */
3610extern int w32_pipe_read_delay;
3611
3612/* Function to do blocking read of one byte, needed to implement
3613   select.  It is only allowed on sockets and pipes. */
3614int
3615_sys_read_ahead (int fd)
3616{
3617  child_process * cp;
3618  int rc;
3619
3620  if (fd < 0 || fd >= MAXDESC)
3621    return STATUS_READ_ERROR;
3622
3623  cp = fd_info[fd].cp;
3624
3625  if (cp == NULL || cp->fd != fd || cp->status != STATUS_READ_READY)
3626    return STATUS_READ_ERROR;
3627
3628  if ((fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET)) == 0
3629      || (fd_info[fd].flags & FILE_READ) == 0)
3630    {
3631      DebPrint (("_sys_read_ahead: internal error: fd %d is not a pipe or socket!\n", fd));
3632      abort ();
3633    }
3634
3635  cp->status = STATUS_READ_IN_PROGRESS;
3636
3637  if (fd_info[fd].flags & FILE_PIPE)
3638    {
3639      rc = _read (fd, &cp->chr, sizeof (char));
3640
3641      /* Give subprocess time to buffer some more output for us before
3642	 reporting that input is available; we need this because Windows 95
3643	 connects DOS programs to pipes by making the pipe appear to be
3644	 the normal console stdout - as a result most DOS programs will
3645	 write to stdout without buffering, ie.  one character at a
3646	 time.  Even some W32 programs do this - "dir" in a command
3647	 shell on NT is very slow if we don't do this. */
3648      if (rc > 0)
3649	{
3650	  int wait = w32_pipe_read_delay;
3651
3652	  if (wait > 0)
3653	    Sleep (wait);
3654	  else if (wait < 0)
3655	    while (++wait <= 0)
3656	      /* Yield remainder of our time slice, effectively giving a
3657		 temporary priority boost to the child process. */
3658	      Sleep (0);
3659	}
3660    }
3661#ifdef HAVE_SOCKETS
3662  else if (fd_info[fd].flags & FILE_SOCKET)
3663    {
3664      unsigned long nblock = 0;
3665      /* We always want this to block, so temporarily disable NDELAY.  */
3666      if (fd_info[fd].flags & FILE_NDELAY)
3667	pfn_ioctlsocket (SOCK_HANDLE (fd), FIONBIO, &nblock);
3668
3669      rc = pfn_recv (SOCK_HANDLE (fd), &cp->chr, sizeof (char), 0);
3670
3671      if (fd_info[fd].flags & FILE_NDELAY)
3672	{
3673	  nblock = 1;
3674	  pfn_ioctlsocket (SOCK_HANDLE (fd), FIONBIO, &nblock);
3675	}
3676    }
3677#endif
3678
3679  if (rc == sizeof (char))
3680    cp->status = STATUS_READ_SUCCEEDED;
3681  else
3682    cp->status = STATUS_READ_FAILED;
3683
3684  return cp->status;
3685}
3686
3687int
3688_sys_wait_accept (int fd)
3689{
3690  HANDLE hEv;
3691  child_process * cp;
3692  int rc;
3693
3694  if (fd < 0 || fd >= MAXDESC)
3695    return STATUS_READ_ERROR;
3696
3697  cp = fd_info[fd].cp;
3698
3699  if (cp == NULL || cp->fd != fd || cp->status != STATUS_READ_READY)
3700    return STATUS_READ_ERROR;
3701
3702  cp->status = STATUS_READ_FAILED;
3703
3704  hEv = pfn_WSACreateEvent ();
3705  rc = pfn_WSAEventSelect (SOCK_HANDLE (fd), hEv, FD_ACCEPT);
3706  if (rc != SOCKET_ERROR)
3707    {
3708      rc = WaitForSingleObject (hEv, INFINITE);
3709      pfn_WSAEventSelect (SOCK_HANDLE (fd), NULL, 0);
3710      if (rc == WAIT_OBJECT_0)
3711	cp->status = STATUS_READ_SUCCEEDED;
3712    }
3713  pfn_WSACloseEvent (hEv);
3714
3715  return cp->status;
3716}
3717
3718int
3719sys_read (int fd, char * buffer, unsigned int count)
3720{
3721  int nchars;
3722  int to_read;
3723  DWORD waiting;
3724  char * orig_buffer = buffer;
3725
3726  if (fd < 0)
3727    {
3728      errno = EBADF;
3729      return -1;
3730    }
3731
3732  if (fd < MAXDESC && fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET))
3733    {
3734      child_process *cp = fd_info[fd].cp;
3735
3736      if ((fd_info[fd].flags & FILE_READ) == 0)
3737        {
3738	  errno = EBADF;
3739	  return -1;
3740	}
3741
3742      nchars = 0;
3743
3744      /* re-read CR carried over from last read */
3745      if (fd_info[fd].flags & FILE_LAST_CR)
3746	{
3747	  if (fd_info[fd].flags & FILE_BINARY) abort ();
3748	  *buffer++ = 0x0d;
3749	  count--;
3750	  nchars++;
3751	  fd_info[fd].flags &= ~FILE_LAST_CR;
3752	}
3753
3754      /* presence of a child_process structure means we are operating in
3755	 non-blocking mode - otherwise we just call _read directly.
3756	 Note that the child_process structure might be missing because
3757	 reap_subprocess has been called; in this case the pipe is
3758	 already broken, so calling _read on it is okay. */
3759      if (cp)
3760        {
3761	  int current_status = cp->status;
3762
3763	  switch (current_status)
3764	    {
3765	    case STATUS_READ_FAILED:
3766	    case STATUS_READ_ERROR:
3767	      /* report normal EOF if nothing in buffer */
3768	      if (nchars <= 0)
3769		fd_info[fd].flags |= FILE_AT_EOF;
3770	      return nchars;
3771
3772	    case STATUS_READ_READY:
3773	    case STATUS_READ_IN_PROGRESS:
3774	      DebPrint (("sys_read called when read is in progress\n"));
3775	      errno = EWOULDBLOCK;
3776	      return -1;
3777
3778	    case STATUS_READ_SUCCEEDED:
3779	      /* consume read-ahead char */
3780	      *buffer++ = cp->chr;
3781	      count--;
3782	      nchars++;
3783	      cp->status = STATUS_READ_ACKNOWLEDGED;
3784	      ResetEvent (cp->char_avail);
3785
3786	    case STATUS_READ_ACKNOWLEDGED:
3787	      break;
3788
3789	    default:
3790	      DebPrint (("sys_read: bad status %d\n", current_status));
3791	      errno = EBADF;
3792	      return -1;
3793	    }
3794
3795	  if (fd_info[fd].flags & FILE_PIPE)
3796	    {
3797	      PeekNamedPipe ((HANDLE) _get_osfhandle (fd), NULL, 0, NULL, &waiting, NULL);
3798	      to_read = min (waiting, (DWORD) count);
3799
3800	      if (to_read > 0)
3801		nchars += _read (fd, buffer, to_read);
3802	    }
3803#ifdef HAVE_SOCKETS
3804	  else /* FILE_SOCKET */
3805	    {
3806	      if (winsock_lib == NULL) abort ();
3807
3808	      /* do the equivalent of a non-blocking read */
3809	      pfn_ioctlsocket (SOCK_HANDLE (fd), FIONREAD, &waiting);
3810	      if (waiting == 0 && nchars == 0)
3811	        {
3812		  h_errno = errno = EWOULDBLOCK;
3813		  return -1;
3814		}
3815
3816	      if (waiting)
3817	        {
3818		  /* always use binary mode for sockets */
3819		  int res = pfn_recv (SOCK_HANDLE (fd), buffer, count, 0);
3820		  if (res == SOCKET_ERROR)
3821		    {
3822		      DebPrint(("sys_read.recv failed with error %d on socket %ld\n",
3823				pfn_WSAGetLastError (), SOCK_HANDLE (fd)));
3824		      set_errno ();
3825		      return -1;
3826		    }
3827		  nchars += res;
3828		}
3829	    }
3830#endif
3831	}
3832      else
3833	{
3834	  int nread = _read (fd, buffer, count);
3835	  if (nread >= 0)
3836	    nchars += nread;
3837	  else if (nchars == 0)
3838	    nchars = nread;
3839	}
3840
3841      if (nchars <= 0)
3842	fd_info[fd].flags |= FILE_AT_EOF;
3843      /* Perform text mode translation if required.  */
3844      else if ((fd_info[fd].flags & FILE_BINARY) == 0)
3845	{
3846	  nchars = crlf_to_lf (nchars, orig_buffer);
3847	  /* If buffer contains only CR, return that.  To be absolutely
3848	     sure we should attempt to read the next char, but in
3849	     practice a CR to be followed by LF would not appear by
3850	     itself in the buffer.  */
3851	  if (nchars > 1 && orig_buffer[nchars - 1] == 0x0d)
3852	    {
3853	      fd_info[fd].flags |= FILE_LAST_CR;
3854	      nchars--;
3855	    }
3856	}
3857    }
3858  else
3859    nchars = _read (fd, buffer, count);
3860
3861  return nchars;
3862}
3863
3864/* For now, don't bother with a non-blocking mode */
3865int
3866sys_write (int fd, const void * buffer, unsigned int count)
3867{
3868  int nchars;
3869
3870  if (fd < 0)
3871    {
3872      errno = EBADF;
3873      return -1;
3874    }
3875
3876  if (fd < MAXDESC && fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET))
3877    {
3878      if ((fd_info[fd].flags & FILE_WRITE) == 0)
3879	{
3880	  errno = EBADF;
3881	  return -1;
3882	}
3883
3884      /* Perform text mode translation if required.  */
3885      if ((fd_info[fd].flags & FILE_BINARY) == 0)
3886	{
3887	  char * tmpbuf = alloca (count * 2);
3888	  unsigned char * src = (void *)buffer;
3889	  unsigned char * dst = tmpbuf;
3890	  int nbytes = count;
3891
3892	  while (1)
3893	    {
3894	      unsigned char *next;
3895	      /* copy next line or remaining bytes */
3896	      next = _memccpy (dst, src, '\n', nbytes);
3897	      if (next)
3898		{
3899		  /* copied one line ending with '\n' */
3900		  int copied = next - dst;
3901		  nbytes -= copied;
3902		  src += copied;
3903		  /* insert '\r' before '\n' */
3904		  next[-1] = '\r';
3905		  next[0] = '\n';
3906		  dst = next + 1;
3907		  count++;
3908		}
3909	      else
3910		/* copied remaining partial line -> now finished */
3911		break;
3912	    }
3913	  buffer = tmpbuf;
3914	}
3915    }
3916
3917#ifdef HAVE_SOCKETS
3918  if (fd < MAXDESC && fd_info[fd].flags & FILE_SOCKET)
3919    {
3920      unsigned long nblock = 0;
3921      if (winsock_lib == NULL) abort ();
3922
3923      /* TODO: implement select() properly so non-blocking I/O works. */
3924      /* For now, make sure the write blocks.  */
3925      if (fd_info[fd].flags & FILE_NDELAY)
3926	pfn_ioctlsocket (SOCK_HANDLE (fd), FIONBIO, &nblock);
3927
3928      nchars =  pfn_send (SOCK_HANDLE (fd), buffer, count, 0);
3929
3930      /* Set the socket back to non-blocking if it was before,
3931	 for other operations that support it.  */
3932      if (fd_info[fd].flags & FILE_NDELAY)
3933	{
3934	  nblock = 1;
3935	  pfn_ioctlsocket (SOCK_HANDLE (fd), FIONBIO, &nblock);
3936	}
3937
3938      if (nchars == SOCKET_ERROR)
3939        {
3940	  DebPrint(("sys_write.send failed with error %d on socket %ld\n",
3941		    pfn_WSAGetLastError (), SOCK_HANDLE (fd)));
3942	  set_errno ();
3943	}
3944    }
3945  else
3946#endif
3947    nchars = _write (fd, buffer, count);
3948
3949  return nchars;
3950}
3951
3952static void
3953check_windows_init_file ()
3954{
3955  extern int noninteractive, inhibit_window_system;
3956
3957  /* A common indication that Emacs is not installed properly is when
3958     it cannot find the Windows installation file.  If this file does
3959     not exist in the expected place, tell the user.  */
3960
3961  if (!noninteractive && !inhibit_window_system)
3962    {
3963      extern Lisp_Object Vwindow_system, Vload_path, Qfile_exists_p;
3964      Lisp_Object objs[2];
3965      Lisp_Object full_load_path;
3966      Lisp_Object init_file;
3967      int fd;
3968
3969      objs[0] = Vload_path;
3970      objs[1] = decode_env_path (0, (getenv ("EMACSLOADPATH")));
3971      full_load_path = Fappend (2, objs);
3972      init_file = build_string ("term/w32-win");
3973      fd = openp (full_load_path, init_file, Fget_load_suffixes (), NULL, Qnil);
3974      if (fd < 0)
3975	{
3976	  Lisp_Object load_path_print = Fprin1_to_string (full_load_path, Qnil);
3977	  char *init_file_name = SDATA (init_file);
3978	  char *load_path = SDATA (load_path_print);
3979	  char *buffer = alloca (1024
3980				 + strlen (init_file_name)
3981				 + strlen (load_path));
3982
3983	  sprintf (buffer,
3984		   "The Emacs Windows initialization file \"%s.el\" "
3985		   "could not be found in your Emacs installation.  "
3986		   "Emacs checked the following directories for this file:\n"
3987		   "\n%s\n\n"
3988		   "When Emacs cannot find this file, it usually means that it "
3989		   "was not installed properly, or its distribution file was "
3990		   "not unpacked properly.\nSee the README.W32 file in the "
3991		   "top-level Emacs directory for more information.",
3992		   init_file_name, load_path);
3993	  MessageBox (NULL,
3994		      buffer,
3995		      "Emacs Abort Dialog",
3996		      MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL);
3997      /* Use the low-level Emacs abort. */
3998#undef abort
3999	  abort ();
4000	}
4001      else
4002	{
4003	  _close (fd);
4004	}
4005    }
4006}
4007
4008void
4009term_ntproc ()
4010{
4011#ifdef HAVE_SOCKETS
4012  /* shutdown the socket interface if necessary */
4013  term_winsock ();
4014#endif
4015
4016  term_w32select ();
4017}
4018
4019void
4020init_ntproc ()
4021{
4022#ifdef HAVE_SOCKETS
4023  /* Initialise the socket interface now if available and requested by
4024     the user by defining PRELOAD_WINSOCK; otherwise loading will be
4025     delayed until open-network-stream is called (w32-has-winsock can
4026     also be used to dynamically load or reload winsock).
4027
4028     Conveniently, init_environment is called before us, so
4029     PRELOAD_WINSOCK can be set in the registry. */
4030
4031  /* Always initialize this correctly. */
4032  winsock_lib = NULL;
4033
4034  if (getenv ("PRELOAD_WINSOCK") != NULL)
4035    init_winsock (TRUE);
4036#endif
4037
4038  /* Initial preparation for subprocess support: replace our standard
4039     handles with non-inheritable versions. */
4040  {
4041    HANDLE parent;
4042    HANDLE stdin_save =  INVALID_HANDLE_VALUE;
4043    HANDLE stdout_save = INVALID_HANDLE_VALUE;
4044    HANDLE stderr_save = INVALID_HANDLE_VALUE;
4045
4046    parent = GetCurrentProcess ();
4047
4048    /* ignore errors when duplicating and closing; typically the
4049       handles will be invalid when running as a gui program. */
4050    DuplicateHandle (parent,
4051		     GetStdHandle (STD_INPUT_HANDLE),
4052		     parent,
4053		     &stdin_save,
4054		     0,
4055		     FALSE,
4056		     DUPLICATE_SAME_ACCESS);
4057
4058    DuplicateHandle (parent,
4059		     GetStdHandle (STD_OUTPUT_HANDLE),
4060		     parent,
4061		     &stdout_save,
4062		     0,
4063		     FALSE,
4064		     DUPLICATE_SAME_ACCESS);
4065
4066    DuplicateHandle (parent,
4067		     GetStdHandle (STD_ERROR_HANDLE),
4068		     parent,
4069		     &stderr_save,
4070		     0,
4071		     FALSE,
4072		     DUPLICATE_SAME_ACCESS);
4073
4074    fclose (stdin);
4075    fclose (stdout);
4076    fclose (stderr);
4077
4078    if (stdin_save != INVALID_HANDLE_VALUE)
4079      _open_osfhandle ((long) stdin_save, O_TEXT);
4080    else
4081      _open ("nul", O_TEXT | O_NOINHERIT | O_RDONLY);
4082    _fdopen (0, "r");
4083
4084    if (stdout_save != INVALID_HANDLE_VALUE)
4085      _open_osfhandle ((long) stdout_save, O_TEXT);
4086    else
4087      _open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY);
4088    _fdopen (1, "w");
4089
4090    if (stderr_save != INVALID_HANDLE_VALUE)
4091      _open_osfhandle ((long) stderr_save, O_TEXT);
4092    else
4093      _open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY);
4094    _fdopen (2, "w");
4095  }
4096
4097  /* unfortunately, atexit depends on implementation of malloc */
4098  /* atexit (term_ntproc); */
4099  signal (SIGABRT, term_ntproc);
4100
4101  /* determine which drives are fixed, for GetCachedVolumeInformation */
4102  {
4103    /* GetDriveType must have trailing backslash. */
4104    char drive[] = "A:\\";
4105
4106    /* Loop over all possible drive letters */
4107    while (*drive <= 'Z')
4108    {
4109      /* Record if this drive letter refers to a fixed drive. */
4110      fixed_drives[DRIVE_INDEX (*drive)] =
4111	(GetDriveType (drive) == DRIVE_FIXED);
4112
4113      (*drive)++;
4114    }
4115
4116    /* Reset the volume info cache.  */
4117    volume_cache = NULL;
4118  }
4119
4120  /* Check to see if Emacs has been installed correctly.  */
4121  check_windows_init_file ();
4122}
4123
4124/*
4125        shutdown_handler ensures that buffers' autosave files are
4126	up to date when the user logs off, or the system shuts down.
4127*/
4128BOOL WINAPI shutdown_handler(DWORD type)
4129{
4130  /* Ctrl-C and Ctrl-Break are already suppressed, so don't handle them.  */
4131  if (type == CTRL_CLOSE_EVENT        /* User closes console window.  */
4132      || type == CTRL_LOGOFF_EVENT    /* User logs off.  */
4133      || type == CTRL_SHUTDOWN_EVENT) /* User shutsdown.  */
4134    {
4135      /* Shut down cleanly, making sure autosave files are up to date.  */
4136      shut_down_emacs (0, 0, Qnil);
4137    }
4138
4139  /* Allow other handlers to handle this signal.  */
4140  return FALSE;
4141}
4142
4143/*
4144	globals_of_w32 is used to initialize those global variables that
4145	must always be initialized on startup even when the global variable
4146	initialized is non zero (see the function main in emacs.c).
4147*/
4148void
4149globals_of_w32 ()
4150{
4151  g_b_init_is_windows_9x = 0;
4152  g_b_init_open_process_token = 0;
4153  g_b_init_get_token_information = 0;
4154  g_b_init_lookup_account_sid = 0;
4155  g_b_init_get_sid_identifier_authority = 0;
4156  /* The following sets a handler for shutdown notifications for
4157     console apps. This actually applies to Emacs in both console and
4158     GUI modes, since we had to fool windows into thinking emacs is a
4159     console application to get console mode to work.  */
4160  SetConsoleCtrlHandler(shutdown_handler, TRUE);
4161}
4162
4163/* end of nt.c */
4164
4165/* arch-tag: 90442dd3-37be-482b-b272-ac752e3049f1
4166   (do not change this comment) */
4167