(fill-paragraph-function): Doc fix.
[emacs.git] / src / w32.c
blob87ae9d9f8fdb9ef934b0d17ba3b1e6e6513fa853
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.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA.
22 Geoff Voelker (voelker@cs.washington.edu) 7-29-94
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>
36 /* must include CRT headers *before* config.h */
38 #ifdef HAVE_CONFIG_H
39 #include <config.h>
40 #endif
42 #undef access
43 #undef chdir
44 #undef chmod
45 #undef creat
46 #undef ctime
47 #undef fopen
48 #undef link
49 #undef mkdir
50 #undef mktemp
51 #undef open
52 #undef rename
53 #undef rmdir
54 #undef unlink
56 #undef close
57 #undef dup
58 #undef dup2
59 #undef pipe
60 #undef read
61 #undef write
63 #undef strerror
65 #include "lisp.h"
67 #include <pwd.h>
68 #include <grp.h>
70 #ifdef __GNUC__
71 #define _ANONYMOUS_UNION
72 #define _ANONYMOUS_STRUCT
73 #endif
74 #include <windows.h>
75 #include <shlobj.h>
77 #ifdef HAVE_SOCKETS /* TCP connection support, if kernel can do it */
78 #include <sys/socket.h>
79 #undef socket
80 #undef bind
81 #undef connect
82 #undef htons
83 #undef ntohs
84 #undef inet_addr
85 #undef gethostname
86 #undef gethostbyname
87 #undef getservbyname
88 #undef getpeername
89 #undef shutdown
90 #undef setsockopt
91 #undef listen
92 #undef getsockname
93 #undef accept
94 #undef recvfrom
95 #undef sendto
96 #endif
98 #include "w32.h"
99 #include "ndir.h"
100 #include "w32heap.h"
101 #include "systime.h"
103 typedef HRESULT (WINAPI * ShGetFolderPath_fn)
104 (IN HWND, IN int, IN HANDLE, IN DWORD, OUT char *);
106 void globals_of_w32 ();
108 extern Lisp_Object Vw32_downcase_file_names;
109 extern Lisp_Object Vw32_generate_fake_inodes;
110 extern Lisp_Object Vw32_get_true_file_attributes;
111 extern int w32_num_mouse_buttons;
115 Initialization states
117 static BOOL g_b_init_is_windows_9x;
118 static BOOL g_b_init_open_process_token;
119 static BOOL g_b_init_get_token_information;
120 static BOOL g_b_init_lookup_account_sid;
121 static BOOL g_b_init_get_sid_identifier_authority;
124 BEGIN: Wrapper functions around OpenProcessToken
125 and other functions in advapi32.dll that are only
126 supported in Windows NT / 2k / XP
128 /* ** Function pointer typedefs ** */
129 typedef BOOL (WINAPI * OpenProcessToken_Proc) (
130 HANDLE ProcessHandle,
131 DWORD DesiredAccess,
132 PHANDLE TokenHandle);
133 typedef BOOL (WINAPI * GetTokenInformation_Proc) (
134 HANDLE TokenHandle,
135 TOKEN_INFORMATION_CLASS TokenInformationClass,
136 LPVOID TokenInformation,
137 DWORD TokenInformationLength,
138 PDWORD ReturnLength);
139 #ifdef _UNICODE
140 const char * const LookupAccountSid_Name = "LookupAccountSidW";
141 #else
142 const char * const LookupAccountSid_Name = "LookupAccountSidA";
143 #endif
144 typedef BOOL (WINAPI * LookupAccountSid_Proc) (
145 LPCTSTR lpSystemName,
146 PSID Sid,
147 LPTSTR Name,
148 LPDWORD cbName,
149 LPTSTR DomainName,
150 LPDWORD cbDomainName,
151 PSID_NAME_USE peUse);
152 typedef PSID_IDENTIFIER_AUTHORITY (WINAPI * GetSidIdentifierAuthority_Proc) (
153 PSID pSid);
155 /* ** A utility function ** */
156 static BOOL
157 is_windows_9x ()
159 static BOOL s_b_ret=0;
160 OSVERSIONINFO os_ver;
161 if (g_b_init_is_windows_9x == 0)
163 g_b_init_is_windows_9x = 1;
164 ZeroMemory(&os_ver, sizeof(OSVERSIONINFO));
165 os_ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
166 if (GetVersionEx (&os_ver))
168 s_b_ret = (os_ver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS);
171 return s_b_ret;
174 /* ** The wrapper functions ** */
176 BOOL WINAPI open_process_token (
177 HANDLE ProcessHandle,
178 DWORD DesiredAccess,
179 PHANDLE TokenHandle)
181 static OpenProcessToken_Proc s_pfn_Open_Process_Token = NULL;
182 HMODULE hm_advapi32 = NULL;
183 if (is_windows_9x () == TRUE)
185 return FALSE;
187 if (g_b_init_open_process_token == 0)
189 g_b_init_open_process_token = 1;
190 hm_advapi32 = LoadLibrary ("Advapi32.dll");
191 s_pfn_Open_Process_Token =
192 (OpenProcessToken_Proc) GetProcAddress (hm_advapi32, "OpenProcessToken");
194 if (s_pfn_Open_Process_Token == NULL)
196 return FALSE;
198 return (
199 s_pfn_Open_Process_Token (
200 ProcessHandle,
201 DesiredAccess,
202 TokenHandle)
206 BOOL WINAPI get_token_information (
207 HANDLE TokenHandle,
208 TOKEN_INFORMATION_CLASS TokenInformationClass,
209 LPVOID TokenInformation,
210 DWORD TokenInformationLength,
211 PDWORD ReturnLength)
213 static GetTokenInformation_Proc s_pfn_Get_Token_Information = NULL;
214 HMODULE hm_advapi32 = NULL;
215 if (is_windows_9x () == TRUE)
217 return FALSE;
219 if (g_b_init_get_token_information == 0)
221 g_b_init_get_token_information = 1;
222 hm_advapi32 = LoadLibrary ("Advapi32.dll");
223 s_pfn_Get_Token_Information =
224 (GetTokenInformation_Proc) GetProcAddress (hm_advapi32, "GetTokenInformation");
226 if (s_pfn_Get_Token_Information == NULL)
228 return FALSE;
230 return (
231 s_pfn_Get_Token_Information (
232 TokenHandle,
233 TokenInformationClass,
234 TokenInformation,
235 TokenInformationLength,
236 ReturnLength)
240 BOOL WINAPI lookup_account_sid (
241 LPCTSTR lpSystemName,
242 PSID Sid,
243 LPTSTR Name,
244 LPDWORD cbName,
245 LPTSTR DomainName,
246 LPDWORD cbDomainName,
247 PSID_NAME_USE peUse)
249 static LookupAccountSid_Proc s_pfn_Lookup_Account_Sid = NULL;
250 HMODULE hm_advapi32 = NULL;
251 if (is_windows_9x () == TRUE)
253 return FALSE;
255 if (g_b_init_lookup_account_sid == 0)
257 g_b_init_lookup_account_sid = 1;
258 hm_advapi32 = LoadLibrary ("Advapi32.dll");
259 s_pfn_Lookup_Account_Sid =
260 (LookupAccountSid_Proc) GetProcAddress (hm_advapi32, LookupAccountSid_Name);
262 if (s_pfn_Lookup_Account_Sid == NULL)
264 return FALSE;
266 return (
267 s_pfn_Lookup_Account_Sid (
268 lpSystemName,
269 Sid,
270 Name,
271 cbName,
272 DomainName,
273 cbDomainName,
274 peUse)
278 PSID_IDENTIFIER_AUTHORITY WINAPI get_sid_identifier_authority (
279 PSID pSid)
281 static GetSidIdentifierAuthority_Proc s_pfn_Get_Sid_Identifier_Authority = NULL;
282 HMODULE hm_advapi32 = NULL;
283 if (is_windows_9x () == TRUE)
285 return NULL;
287 if (g_b_init_get_sid_identifier_authority == 0)
289 g_b_init_get_sid_identifier_authority = 1;
290 hm_advapi32 = LoadLibrary ("Advapi32.dll");
291 s_pfn_Get_Sid_Identifier_Authority =
292 (GetSidIdentifierAuthority_Proc) GetProcAddress (
293 hm_advapi32, "GetSidIdentifierAuthority");
295 if (s_pfn_Get_Sid_Identifier_Authority == NULL)
297 return NULL;
299 return (s_pfn_Get_Sid_Identifier_Authority (pSid));
303 END: Wrapper functions around OpenProcessToken
304 and other functions in advapi32.dll that are only
305 supported in Windows NT / 2k / XP
309 /* Equivalent of strerror for W32 error codes. */
310 char *
311 w32_strerror (int error_no)
313 static char buf[500];
315 if (error_no == 0)
316 error_no = GetLastError ();
318 buf[0] = '\0';
319 if (!FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL,
320 error_no,
321 0, /* choose most suitable language */
322 buf, sizeof (buf), NULL))
323 sprintf (buf, "w32 error %u", error_no);
324 return buf;
327 /* Return 1 if P is a valid pointer to an object of size SIZE. Return
328 0 if P is NOT a valid pointer. Return -1 if we cannot validate P.
330 This is called from alloc.c:valid_pointer_p. */
332 w32_valid_pointer_p (void *p, int size)
334 SIZE_T done;
335 HANDLE h = OpenProcess (PROCESS_VM_READ, FALSE, GetCurrentProcessId ());
337 if (h)
339 unsigned char *buf = alloca (size);
340 int retval = ReadProcessMemory (h, p, buf, size, &done);
342 CloseHandle (h);
343 return retval;
345 else
346 return -1;
349 static char startup_dir[MAXPATHLEN];
351 /* Get the current working directory. */
352 char *
353 getwd (char *dir)
355 #if 0
356 if (GetCurrentDirectory (MAXPATHLEN, dir) > 0)
357 return dir;
358 return NULL;
359 #else
360 /* Emacs doesn't actually change directory itself, and we want to
361 force our real wd to be where emacs.exe is to avoid unnecessary
362 conflicts when trying to rename or delete directories. */
363 strcpy (dir, startup_dir);
364 return dir;
365 #endif
368 #ifndef HAVE_SOCKETS
369 /* Emulate gethostname. */
371 gethostname (char *buffer, int size)
373 /* NT only allows small host names, so the buffer is
374 certainly large enough. */
375 return !GetComputerName (buffer, &size);
377 #endif /* HAVE_SOCKETS */
379 /* Emulate getloadavg. */
381 getloadavg (double loadavg[], int nelem)
383 int i;
385 /* A faithful emulation is going to have to be saved for a rainy day. */
386 for (i = 0; i < nelem; i++)
388 loadavg[i] = 0.0;
390 return i;
393 /* Emulate getpwuid, getpwnam and others. */
395 #define PASSWD_FIELD_SIZE 256
397 static char the_passwd_name[PASSWD_FIELD_SIZE];
398 static char the_passwd_passwd[PASSWD_FIELD_SIZE];
399 static char the_passwd_gecos[PASSWD_FIELD_SIZE];
400 static char the_passwd_dir[PASSWD_FIELD_SIZE];
401 static char the_passwd_shell[PASSWD_FIELD_SIZE];
403 static struct passwd the_passwd =
405 the_passwd_name,
406 the_passwd_passwd,
410 the_passwd_gecos,
411 the_passwd_dir,
412 the_passwd_shell,
415 static struct group the_group =
417 /* There are no groups on NT, so we just return "root" as the
418 group name. */
419 "root",
423 getuid ()
425 return the_passwd.pw_uid;
429 geteuid ()
431 /* I could imagine arguing for checking to see whether the user is
432 in the Administrators group and returning a UID of 0 for that
433 case, but I don't know how wise that would be in the long run. */
434 return getuid ();
438 getgid ()
440 return the_passwd.pw_gid;
444 getegid ()
446 return getgid ();
449 struct passwd *
450 getpwuid (int uid)
452 if (uid == the_passwd.pw_uid)
453 return &the_passwd;
454 return NULL;
457 struct group *
458 getgrgid (gid_t gid)
460 return &the_group;
463 struct passwd *
464 getpwnam (char *name)
466 struct passwd *pw;
468 pw = getpwuid (getuid ());
469 if (!pw)
470 return pw;
472 if (stricmp (name, pw->pw_name))
473 return NULL;
475 return pw;
478 void
479 init_user_info ()
481 /* Find the user's real name by opening the process token and
482 looking up the name associated with the user-sid in that token.
484 Use the relative portion of the identifier authority value from
485 the user-sid as the user id value (same for group id using the
486 primary group sid from the process token). */
488 char user_sid[256], name[256], domain[256];
489 DWORD length = sizeof (name), dlength = sizeof (domain), trash;
490 HANDLE token = NULL;
491 SID_NAME_USE user_type;
493 if (
494 open_process_token (GetCurrentProcess (), TOKEN_QUERY, &token)
495 && get_token_information (
496 token, TokenUser,
497 (PVOID) user_sid, sizeof (user_sid), &trash)
498 && lookup_account_sid (
499 NULL, *((PSID *) user_sid), name, &length,
500 domain, &dlength, &user_type)
503 strcpy (the_passwd.pw_name, name);
504 /* Determine a reasonable uid value. */
505 if (stricmp ("administrator", name) == 0)
507 the_passwd.pw_uid = 0;
508 the_passwd.pw_gid = 0;
510 else
512 SID_IDENTIFIER_AUTHORITY * pSIA;
514 pSIA = get_sid_identifier_authority (*((PSID *) user_sid));
515 /* I believe the relative portion is the last 4 bytes (of 6)
516 with msb first. */
517 the_passwd.pw_uid = ((pSIA->Value[2] << 24) +
518 (pSIA->Value[3] << 16) +
519 (pSIA->Value[4] << 8) +
520 (pSIA->Value[5] << 0));
521 /* restrict to conventional uid range for normal users */
522 the_passwd.pw_uid = the_passwd.pw_uid % 60001;
524 /* Get group id */
525 if (get_token_information (token, TokenPrimaryGroup,
526 (PVOID) user_sid, sizeof (user_sid), &trash))
528 SID_IDENTIFIER_AUTHORITY * pSIA;
530 pSIA = get_sid_identifier_authority (*((PSID *) user_sid));
531 the_passwd.pw_gid = ((pSIA->Value[2] << 24) +
532 (pSIA->Value[3] << 16) +
533 (pSIA->Value[4] << 8) +
534 (pSIA->Value[5] << 0));
535 /* I don't know if this is necessary, but for safety... */
536 the_passwd.pw_gid = the_passwd.pw_gid % 60001;
538 else
539 the_passwd.pw_gid = the_passwd.pw_uid;
542 /* If security calls are not supported (presumably because we
543 are running under Windows 95), fallback to this. */
544 else if (GetUserName (name, &length))
546 strcpy (the_passwd.pw_name, name);
547 if (stricmp ("administrator", name) == 0)
548 the_passwd.pw_uid = 0;
549 else
550 the_passwd.pw_uid = 123;
551 the_passwd.pw_gid = the_passwd.pw_uid;
553 else
555 strcpy (the_passwd.pw_name, "unknown");
556 the_passwd.pw_uid = 123;
557 the_passwd.pw_gid = 123;
560 /* Ensure HOME and SHELL are defined. */
561 if (getenv ("HOME") == NULL)
562 abort ();
563 if (getenv ("SHELL") == NULL)
564 abort ();
566 /* Set dir and shell from environment variables. */
567 strcpy (the_passwd.pw_dir, getenv ("HOME"));
568 strcpy (the_passwd.pw_shell, getenv ("SHELL"));
570 if (token)
571 CloseHandle (token);
575 random ()
577 /* rand () on NT gives us 15 random bits...hack together 30 bits. */
578 return ((rand () << 15) | rand ());
581 void
582 srandom (int seed)
584 srand (seed);
588 /* Normalize filename by converting all path separators to
589 the specified separator. Also conditionally convert upper
590 case path name components to lower case. */
592 static void
593 normalize_filename (fp, path_sep)
594 register char *fp;
595 char path_sep;
597 char sep;
598 char *elem;
600 /* Always lower-case drive letters a-z, even if the filesystem
601 preserves case in filenames.
602 This is so filenames can be compared by string comparison
603 functions that are case-sensitive. Even case-preserving filesystems
604 do not distinguish case in drive letters. */
605 if (fp[1] == ':' && *fp >= 'A' && *fp <= 'Z')
607 *fp += 'a' - 'A';
608 fp += 2;
611 if (NILP (Vw32_downcase_file_names))
613 while (*fp)
615 if (*fp == '/' || *fp == '\\')
616 *fp = path_sep;
617 fp++;
619 return;
622 sep = path_sep; /* convert to this path separator */
623 elem = fp; /* start of current path element */
625 do {
626 if (*fp >= 'a' && *fp <= 'z')
627 elem = 0; /* don't convert this element */
629 if (*fp == 0 || *fp == ':')
631 sep = *fp; /* restore current separator (or 0) */
632 *fp = '/'; /* after conversion of this element */
635 if (*fp == '/' || *fp == '\\')
637 if (elem && elem != fp)
639 *fp = 0; /* temporary end of string */
640 _strlwr (elem); /* while we convert to lower case */
642 *fp = sep; /* convert (or restore) path separator */
643 elem = fp + 1; /* next element starts after separator */
644 sep = path_sep;
646 } while (*fp++);
649 /* Destructively turn backslashes into slashes. */
650 void
651 dostounix_filename (p)
652 register char *p;
654 normalize_filename (p, '/');
657 /* Destructively turn slashes into backslashes. */
658 void
659 unixtodos_filename (p)
660 register char *p;
662 normalize_filename (p, '\\');
665 /* Remove all CR's that are followed by a LF.
666 (From msdos.c...probably should figure out a way to share it,
667 although this code isn't going to ever change.) */
669 crlf_to_lf (n, buf)
670 register int n;
671 register unsigned char *buf;
673 unsigned char *np = buf;
674 unsigned char *startp = buf;
675 unsigned char *endp = buf + n;
677 if (n == 0)
678 return n;
679 while (buf < endp - 1)
681 if (*buf == 0x0d)
683 if (*(++buf) != 0x0a)
684 *np++ = 0x0d;
686 else
687 *np++ = *buf++;
689 if (buf < endp)
690 *np++ = *buf++;
691 return np - startp;
694 /* Parse the root part of file name, if present. Return length and
695 optionally store pointer to char after root. */
696 static int
697 parse_root (char * name, char ** pPath)
699 char * start = name;
701 if (name == NULL)
702 return 0;
704 /* find the root name of the volume if given */
705 if (isalpha (name[0]) && name[1] == ':')
707 /* skip past drive specifier */
708 name += 2;
709 if (IS_DIRECTORY_SEP (name[0]))
710 name++;
712 else if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1]))
714 int slashes = 2;
715 name += 2;
718 if (IS_DIRECTORY_SEP (*name) && --slashes == 0)
719 break;
720 name++;
722 while ( *name );
723 if (IS_DIRECTORY_SEP (name[0]))
724 name++;
727 if (pPath)
728 *pPath = name;
730 return name - start;
733 /* Get long base name for name; name is assumed to be absolute. */
734 static int
735 get_long_basename (char * name, char * buf, int size)
737 WIN32_FIND_DATA find_data;
738 HANDLE dir_handle;
739 int len = 0;
741 /* must be valid filename, no wild cards or other invalid characters */
742 if (strpbrk (name, "*?|<>\""))
743 return 0;
745 dir_handle = FindFirstFile (name, &find_data);
746 if (dir_handle != INVALID_HANDLE_VALUE)
748 if ((len = strlen (find_data.cFileName)) < size)
749 memcpy (buf, find_data.cFileName, len + 1);
750 else
751 len = 0;
752 FindClose (dir_handle);
754 return len;
757 /* Get long name for file, if possible (assumed to be absolute). */
758 BOOL
759 w32_get_long_filename (char * name, char * buf, int size)
761 char * o = buf;
762 char * p;
763 char * q;
764 char full[ MAX_PATH ];
765 int len;
767 len = strlen (name);
768 if (len >= MAX_PATH)
769 return FALSE;
771 /* Use local copy for destructive modification. */
772 memcpy (full, name, len+1);
773 unixtodos_filename (full);
775 /* Copy root part verbatim. */
776 len = parse_root (full, &p);
777 memcpy (o, full, len);
778 o += len;
779 *o = '\0';
780 size -= len;
782 while (p != NULL && *p)
784 q = p;
785 p = strchr (q, '\\');
786 if (p) *p = '\0';
787 len = get_long_basename (full, o, size);
788 if (len > 0)
790 o += len;
791 size -= len;
792 if (p != NULL)
794 *p++ = '\\';
795 if (size < 2)
796 return FALSE;
797 *o++ = '\\';
798 size--;
799 *o = '\0';
802 else
803 return FALSE;
806 return TRUE;
810 is_unc_volume (const char *filename)
812 const char *ptr = filename;
814 if (!IS_DIRECTORY_SEP (ptr[0]) || !IS_DIRECTORY_SEP (ptr[1]) || !ptr[2])
815 return 0;
817 if (strpbrk (ptr + 2, "*?|<>\"\\/"))
818 return 0;
820 return 1;
823 /* Routines that are no-ops on NT but are defined to get Emacs to compile. */
826 sigsetmask (int signal_mask)
828 return 0;
832 sigmask (int sig)
834 return 0;
838 sigblock (int sig)
840 return 0;
844 sigunblock (int sig)
846 return 0;
850 setpgrp (int pid, int gid)
852 return 0;
856 alarm (int seconds)
858 return 0;
861 void
862 unrequest_sigio (void)
864 return;
867 void
868 request_sigio (void)
870 return;
873 #define REG_ROOT "SOFTWARE\\GNU\\Emacs"
875 LPBYTE
876 w32_get_resource (key, lpdwtype)
877 char *key;
878 LPDWORD lpdwtype;
880 LPBYTE lpvalue;
881 HKEY hrootkey = NULL;
882 DWORD cbData;
883 BOOL ok = FALSE;
885 /* Check both the current user and the local machine to see if
886 we have any resources. */
888 if (RegOpenKeyEx (HKEY_CURRENT_USER, REG_ROOT, 0, KEY_READ, &hrootkey) == ERROR_SUCCESS)
890 lpvalue = NULL;
892 if (RegQueryValueEx (hrootkey, key, NULL, NULL, NULL, &cbData) == ERROR_SUCCESS
893 && (lpvalue = (LPBYTE) xmalloc (cbData)) != NULL
894 && RegQueryValueEx (hrootkey, key, NULL, lpdwtype, lpvalue, &cbData) == ERROR_SUCCESS)
896 return (lpvalue);
899 if (lpvalue) xfree (lpvalue);
901 RegCloseKey (hrootkey);
904 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, REG_ROOT, 0, KEY_READ, &hrootkey) == ERROR_SUCCESS)
906 lpvalue = NULL;
908 if (RegQueryValueEx (hrootkey, key, NULL, NULL, NULL, &cbData) == ERROR_SUCCESS
909 && (lpvalue = (LPBYTE) xmalloc (cbData)) != NULL
910 && RegQueryValueEx (hrootkey, key, NULL, lpdwtype, lpvalue, &cbData) == ERROR_SUCCESS)
912 return (lpvalue);
915 if (lpvalue) xfree (lpvalue);
917 RegCloseKey (hrootkey);
920 return (NULL);
923 char *get_emacs_configuration (void);
924 extern Lisp_Object Vsystem_configuration;
926 void
927 init_environment (char ** argv)
929 static const char * const tempdirs[] = {
930 "$TMPDIR", "$TEMP", "$TMP", "c:/"
933 int i;
935 const int imax = sizeof (tempdirs) / sizeof (tempdirs[0]);
937 /* Make sure they have a usable $TMPDIR. Many Emacs functions use
938 temporary files and assume "/tmp" if $TMPDIR is unset, which
939 will break on DOS/Windows. Refuse to work if we cannot find
940 a directory, not even "c:/", usable for that purpose. */
941 for (i = 0; i < imax ; i++)
943 const char *tmp = tempdirs[i];
945 if (*tmp == '$')
946 tmp = getenv (tmp + 1);
947 /* Note that `access' can lie to us if the directory resides on a
948 read-only filesystem, like CD-ROM or a write-protected floppy.
949 The only way to be really sure is to actually create a file and
950 see if it succeeds. But I think that's too much to ask. */
951 if (tmp && _access (tmp, D_OK) == 0)
953 char * var = alloca (strlen (tmp) + 8);
954 sprintf (var, "TMPDIR=%s", tmp);
955 _putenv (strdup (var));
956 break;
959 if (i >= imax)
960 cmd_error_internal
961 (Fcons (Qerror,
962 Fcons (build_string ("no usable temporary directories found!!"),
963 Qnil)),
964 "While setting TMPDIR: ");
966 /* Check for environment variables and use registry settings if they
967 don't exist. Fallback on default values where applicable. */
969 int i;
970 LPBYTE lpval;
971 DWORD dwType;
972 char locale_name[32];
973 struct stat ignored;
974 char default_home[MAX_PATH];
976 static const struct env_entry
978 char * name;
979 char * def_value;
980 } dflt_envvars[] =
982 {"HOME", "C:/"},
983 {"PRELOAD_WINSOCK", NULL},
984 {"emacs_dir", "C:/emacs"},
985 {"EMACSLOADPATH", "%emacs_dir%/site-lisp;%emacs_dir%/../site-lisp;%emacs_dir%/lisp;%emacs_dir%/leim"},
986 {"SHELL", "%emacs_dir%/bin/cmdproxy.exe"},
987 {"EMACSDATA", "%emacs_dir%/etc"},
988 {"EMACSPATH", "%emacs_dir%/bin"},
989 /* We no longer set INFOPATH because Info-default-directory-list
990 is then ignored. */
991 /* {"INFOPATH", "%emacs_dir%/info"}, */
992 {"EMACSDOC", "%emacs_dir%/etc"},
993 {"TERM", "cmd"},
994 {"LANG", NULL},
997 #define N_ENV_VARS sizeof(dflt_envvars)/sizeof(dflt_envvars[0])
999 /* We need to copy dflt_envvars[] and work on the copy because we
1000 don't want the dumped Emacs to inherit the values of
1001 environment variables we saw during dumping (which could be on
1002 a different system). The defaults above must be left intact. */
1003 struct env_entry env_vars[N_ENV_VARS];
1005 for (i = 0; i < N_ENV_VARS; i++)
1006 env_vars[i] = dflt_envvars[i];
1008 /* For backwards compatibility, check if a .emacs file exists in C:/
1009 If not, then we can try to default to the appdata directory under the
1010 user's profile, which is more likely to be writable. */
1011 if (stat ("C:/.emacs", &ignored) < 0)
1013 HRESULT profile_result;
1014 /* Dynamically load ShGetFolderPath, as it won't exist on versions
1015 of Windows 95 and NT4 that have not been updated to include
1016 MSIE 5. Also we don't link with shell32.dll by default. */
1017 HMODULE shell32_dll;
1018 ShGetFolderPath_fn get_folder_path;
1019 shell32_dll = GetModuleHandle ("shell32.dll");
1020 get_folder_path = (ShGetFolderPath_fn)
1021 GetProcAddress (shell32_dll, "SHGetFolderPathA");
1023 if (get_folder_path != NULL)
1025 profile_result = get_folder_path (NULL, CSIDL_APPDATA, NULL,
1026 0, default_home);
1028 /* If we can't get the appdata dir, revert to old behaviour. */
1029 if (profile_result == S_OK)
1030 env_vars[0].def_value = default_home;
1033 /* Unload shell32.dll, it is not needed anymore. */
1034 FreeLibrary (shell32_dll);
1037 /* Get default locale info and use it for LANG. */
1038 if (GetLocaleInfo (LOCALE_USER_DEFAULT,
1039 LOCALE_SABBREVLANGNAME | LOCALE_USE_CP_ACP,
1040 locale_name, sizeof (locale_name)))
1042 for (i = 0; i < N_ENV_VARS; i++)
1044 if (strcmp (env_vars[i].name, "LANG") == 0)
1046 env_vars[i].def_value = locale_name;
1047 break;
1052 #define SET_ENV_BUF_SIZE (4 * MAX_PATH) /* to cover EMACSLOADPATH */
1054 /* Treat emacs_dir specially: set it unconditionally based on our
1055 location, if it appears that we are running from the bin subdir
1056 of a standard installation. */
1058 char *p;
1059 char modname[MAX_PATH];
1061 if (!GetModuleFileName (NULL, modname, MAX_PATH))
1062 abort ();
1063 if ((p = strrchr (modname, '\\')) == NULL)
1064 abort ();
1065 *p = 0;
1067 if ((p = strrchr (modname, '\\')) && stricmp (p, "\\bin") == 0)
1069 char buf[SET_ENV_BUF_SIZE];
1071 *p = 0;
1072 for (p = modname; *p; p++)
1073 if (*p == '\\') *p = '/';
1075 _snprintf (buf, sizeof(buf)-1, "emacs_dir=%s", modname);
1076 _putenv (strdup (buf));
1078 /* Handle running emacs from the build directory: src/oo-spd/i386/ */
1080 /* FIXME: should use substring of get_emacs_configuration ().
1081 But I don't think the Windows build supports alpha, mips etc
1082 anymore, so have taken the easy option for now. */
1083 else if (p && stricmp (p, "\\i386") == 0)
1085 *p = 0;
1086 p = strrchr (modname, '\\');
1087 if (p != NULL)
1089 *p = 0;
1090 p = strrchr (modname, '\\');
1091 if (p && stricmp (p, "\\src") == 0)
1093 char buf[SET_ENV_BUF_SIZE];
1095 *p = 0;
1096 for (p = modname; *p; p++)
1097 if (*p == '\\') *p = '/';
1099 _snprintf (buf, sizeof(buf)-1, "emacs_dir=%s", modname);
1100 _putenv (strdup (buf));
1106 for (i = 0; i < N_ENV_VARS; i++)
1108 if (!getenv (env_vars[i].name))
1110 int dont_free = 0;
1112 if ((lpval = w32_get_resource (env_vars[i].name, &dwType)) == NULL)
1114 lpval = env_vars[i].def_value;
1115 dwType = REG_EXPAND_SZ;
1116 dont_free = 1;
1119 if (lpval)
1121 char buf1[SET_ENV_BUF_SIZE], buf2[SET_ENV_BUF_SIZE];
1123 if (dwType == REG_EXPAND_SZ)
1124 ExpandEnvironmentStrings ((LPSTR) lpval, buf1, sizeof(buf1));
1125 else if (dwType == REG_SZ)
1126 strcpy (buf1, lpval);
1127 if (dwType == REG_EXPAND_SZ || dwType == REG_SZ)
1129 _snprintf (buf2, sizeof(buf2)-1, "%s=%s", env_vars[i].name,
1130 buf1);
1131 _putenv (strdup (buf2));
1134 if (!dont_free)
1135 xfree (lpval);
1141 /* Rebuild system configuration to reflect invoking system. */
1142 Vsystem_configuration = build_string (EMACS_CONFIGURATION);
1144 /* Another special case: on NT, the PATH variable is actually named
1145 "Path" although cmd.exe (perhaps NT itself) arranges for
1146 environment variable lookup and setting to be case insensitive.
1147 However, Emacs assumes a fully case sensitive environment, so we
1148 need to change "Path" to "PATH" to match the expectations of
1149 various elisp packages. We do this by the sneaky method of
1150 modifying the string in the C runtime environ entry.
1152 The same applies to COMSPEC. */
1154 char ** envp;
1156 for (envp = environ; *envp; envp++)
1157 if (_strnicmp (*envp, "PATH=", 5) == 0)
1158 memcpy (*envp, "PATH=", 5);
1159 else if (_strnicmp (*envp, "COMSPEC=", 8) == 0)
1160 memcpy (*envp, "COMSPEC=", 8);
1163 /* Remember the initial working directory for getwd, then make the
1164 real wd be the location of emacs.exe to avoid conflicts when
1165 renaming or deleting directories. (We also don't call chdir when
1166 running subprocesses for the same reason.) */
1167 if (!GetCurrentDirectory (MAXPATHLEN, startup_dir))
1168 abort ();
1171 char *p;
1172 static char modname[MAX_PATH];
1174 if (!GetModuleFileName (NULL, modname, MAX_PATH))
1175 abort ();
1176 if ((p = strrchr (modname, '\\')) == NULL)
1177 abort ();
1178 *p = 0;
1180 SetCurrentDirectory (modname);
1182 /* Ensure argv[0] has the full path to Emacs. */
1183 *p = '\\';
1184 argv[0] = modname;
1187 /* Determine if there is a middle mouse button, to allow parse_button
1188 to decide whether right mouse events should be mouse-2 or
1189 mouse-3. */
1190 w32_num_mouse_buttons = GetSystemMetrics (SM_CMOUSEBUTTONS);
1192 init_user_info ();
1195 char *
1196 emacs_root_dir (void)
1198 static char root_dir[FILENAME_MAX];
1199 const char *p;
1201 p = getenv ("emacs_dir");
1202 if (p == NULL)
1203 abort ();
1204 strcpy (root_dir, p);
1205 root_dir[parse_root (root_dir, NULL)] = '\0';
1206 dostounix_filename (root_dir);
1207 return root_dir;
1210 /* We don't have scripts to automatically determine the system configuration
1211 for Emacs before it's compiled, and we don't want to have to make the
1212 user enter it, so we define EMACS_CONFIGURATION to invoke this runtime
1213 routine. */
1215 char *
1216 get_emacs_configuration (void)
1218 char *arch, *oem, *os;
1219 int build_num;
1220 static char configuration_buffer[32];
1222 /* Determine the processor type. */
1223 switch (get_processor_type ())
1226 #ifdef PROCESSOR_INTEL_386
1227 case PROCESSOR_INTEL_386:
1228 case PROCESSOR_INTEL_486:
1229 case PROCESSOR_INTEL_PENTIUM:
1230 arch = "i386";
1231 break;
1232 #endif
1234 #ifdef PROCESSOR_INTEL_860
1235 case PROCESSOR_INTEL_860:
1236 arch = "i860";
1237 break;
1238 #endif
1240 #ifdef PROCESSOR_MIPS_R2000
1241 case PROCESSOR_MIPS_R2000:
1242 case PROCESSOR_MIPS_R3000:
1243 case PROCESSOR_MIPS_R4000:
1244 arch = "mips";
1245 break;
1246 #endif
1248 #ifdef PROCESSOR_ALPHA_21064
1249 case PROCESSOR_ALPHA_21064:
1250 arch = "alpha";
1251 break;
1252 #endif
1254 default:
1255 arch = "unknown";
1256 break;
1259 /* Use the OEM field to reflect the compiler/library combination. */
1260 #ifdef _MSC_VER
1261 #define COMPILER_NAME "msvc"
1262 #else
1263 #ifdef __GNUC__
1264 #define COMPILER_NAME "mingw"
1265 #else
1266 #define COMPILER_NAME "unknown"
1267 #endif
1268 #endif
1269 oem = COMPILER_NAME;
1271 switch (osinfo_cache.dwPlatformId) {
1272 case VER_PLATFORM_WIN32_NT:
1273 os = "nt";
1274 build_num = osinfo_cache.dwBuildNumber;
1275 break;
1276 case VER_PLATFORM_WIN32_WINDOWS:
1277 if (osinfo_cache.dwMinorVersion == 0) {
1278 os = "windows95";
1279 } else {
1280 os = "windows98";
1282 build_num = LOWORD (osinfo_cache.dwBuildNumber);
1283 break;
1284 case VER_PLATFORM_WIN32s:
1285 /* Not supported, should not happen. */
1286 os = "windows32s";
1287 build_num = LOWORD (osinfo_cache.dwBuildNumber);
1288 break;
1289 default:
1290 os = "unknown";
1291 build_num = 0;
1292 break;
1295 if (osinfo_cache.dwPlatformId == VER_PLATFORM_WIN32_NT) {
1296 sprintf (configuration_buffer, "%s-%s-%s%d.%d.%d", arch, oem, os,
1297 get_w32_major_version (), get_w32_minor_version (), build_num);
1298 } else {
1299 sprintf (configuration_buffer, "%s-%s-%s.%d", arch, oem, os, build_num);
1302 return configuration_buffer;
1305 char *
1306 get_emacs_configuration_options (void)
1308 static char options_buffer[256];
1310 /* Work out the effective configure options for this build. */
1311 #ifdef _MSC_VER
1312 #define COMPILER_VERSION "--with-msvc (%d.%02d)", _MSC_VER / 100, _MSC_VER % 100
1313 #else
1314 #ifdef __GNUC__
1315 #define COMPILER_VERSION "--with-gcc (%d.%d)", __GNUC__, __GNUC_MINOR__
1316 #else
1317 #define COMPILER_VERSION ""
1318 #endif
1319 #endif
1321 sprintf (options_buffer, COMPILER_VERSION);
1322 #ifdef EMACSDEBUG
1323 strcat (options_buffer, " --no-opt");
1324 #endif
1325 #ifdef USER_CFLAGS
1326 strcat (options_buffer, " --cflags");
1327 strcat (options_buffer, USER_CFLAGS);
1328 #endif
1329 #ifdef USER_LDFLAGS
1330 strcat (options_buffer, " --ldflags");
1331 strcat (options_buffer, USER_LDFLAGS);
1332 #endif
1333 return options_buffer;
1337 #include <sys/timeb.h>
1339 /* Emulate gettimeofday (Ulrich Leodolter, 1/11/95). */
1340 void
1341 gettimeofday (struct timeval *tv, struct timezone *tz)
1343 struct _timeb tb;
1344 _ftime (&tb);
1346 tv->tv_sec = tb.time;
1347 tv->tv_usec = tb.millitm * 1000L;
1348 if (tz)
1350 tz->tz_minuteswest = tb.timezone; /* minutes west of Greenwich */
1351 tz->tz_dsttime = tb.dstflag; /* type of dst correction */
1355 /* ------------------------------------------------------------------------- */
1356 /* IO support and wrapper functions for W32 API. */
1357 /* ------------------------------------------------------------------------- */
1359 /* Place a wrapper around the MSVC version of ctime. It returns NULL
1360 on network directories, so we handle that case here.
1361 (Ulrich Leodolter, 1/11/95). */
1362 char *
1363 sys_ctime (const time_t *t)
1365 char *str = (char *) ctime (t);
1366 return (str ? str : "Sun Jan 01 00:00:00 1970");
1369 /* Emulate sleep...we could have done this with a define, but that
1370 would necessitate including windows.h in the files that used it.
1371 This is much easier. */
1372 void
1373 sys_sleep (int seconds)
1375 Sleep (seconds * 1000);
1378 /* Internal MSVC functions for low-level descriptor munging */
1379 extern int __cdecl _set_osfhnd (int fd, long h);
1380 extern int __cdecl _free_osfhnd (int fd);
1382 /* parallel array of private info on file handles */
1383 filedesc fd_info [ MAXDESC ];
1385 typedef struct volume_info_data {
1386 struct volume_info_data * next;
1388 /* time when info was obtained */
1389 DWORD timestamp;
1391 /* actual volume info */
1392 char * root_dir;
1393 DWORD serialnum;
1394 DWORD maxcomp;
1395 DWORD flags;
1396 char * name;
1397 char * type;
1398 } volume_info_data;
1400 /* Global referenced by various functions. */
1401 static volume_info_data volume_info;
1403 /* Vector to indicate which drives are local and fixed (for which cached
1404 data never expires). */
1405 static BOOL fixed_drives[26];
1407 /* Consider cached volume information to be stale if older than 10s,
1408 at least for non-local drives. Info for fixed drives is never stale. */
1409 #define DRIVE_INDEX( c ) ( (c) <= 'Z' ? (c) - 'A' : (c) - 'a' )
1410 #define VOLINFO_STILL_VALID( root_dir, info ) \
1411 ( ( isalpha (root_dir[0]) && \
1412 fixed_drives[ DRIVE_INDEX (root_dir[0]) ] ) \
1413 || GetTickCount () - info->timestamp < 10000 )
1415 /* Cache support functions. */
1417 /* Simple linked list with linear search is sufficient. */
1418 static volume_info_data *volume_cache = NULL;
1420 static volume_info_data *
1421 lookup_volume_info (char * root_dir)
1423 volume_info_data * info;
1425 for (info = volume_cache; info; info = info->next)
1426 if (stricmp (info->root_dir, root_dir) == 0)
1427 break;
1428 return info;
1431 static void
1432 add_volume_info (char * root_dir, volume_info_data * info)
1434 info->root_dir = xstrdup (root_dir);
1435 info->next = volume_cache;
1436 volume_cache = info;
1440 /* Wrapper for GetVolumeInformation, which uses caching to avoid
1441 performance penalty (~2ms on 486 for local drives, 7.5ms for local
1442 cdrom drive, ~5-10ms or more for remote drives on LAN). */
1443 volume_info_data *
1444 GetCachedVolumeInformation (char * root_dir)
1446 volume_info_data * info;
1447 char default_root[ MAX_PATH ];
1449 /* NULL for root_dir means use root from current directory. */
1450 if (root_dir == NULL)
1452 if (GetCurrentDirectory (MAX_PATH, default_root) == 0)
1453 return NULL;
1454 parse_root (default_root, &root_dir);
1455 *root_dir = 0;
1456 root_dir = default_root;
1459 /* Local fixed drives can be cached permanently. Removable drives
1460 cannot be cached permanently, since the volume name and serial
1461 number (if nothing else) can change. Remote drives should be
1462 treated as if they are removable, since there is no sure way to
1463 tell whether they are or not. Also, the UNC association of drive
1464 letters mapped to remote volumes can be changed at any time (even
1465 by other processes) without notice.
1467 As a compromise, so we can benefit from caching info for remote
1468 volumes, we use a simple expiry mechanism to invalidate cache
1469 entries that are more than ten seconds old. */
1471 #if 0
1472 /* No point doing this, because WNetGetConnection is even slower than
1473 GetVolumeInformation, consistently taking ~50ms on a 486 (FWIW,
1474 GetDriveType is about the only call of this type which does not
1475 involve network access, and so is extremely quick). */
1477 /* Map drive letter to UNC if remote. */
1478 if ( isalpha( root_dir[0] ) && !fixed[ DRIVE_INDEX( root_dir[0] ) ] )
1480 char remote_name[ 256 ];
1481 char drive[3] = { root_dir[0], ':' };
1483 if (WNetGetConnection (drive, remote_name, sizeof (remote_name))
1484 == NO_ERROR)
1485 /* do something */ ;
1487 #endif
1489 info = lookup_volume_info (root_dir);
1491 if (info == NULL || ! VOLINFO_STILL_VALID (root_dir, info))
1493 char name[ 256 ];
1494 DWORD serialnum;
1495 DWORD maxcomp;
1496 DWORD flags;
1497 char type[ 256 ];
1499 /* Info is not cached, or is stale. */
1500 if (!GetVolumeInformation (root_dir,
1501 name, sizeof (name),
1502 &serialnum,
1503 &maxcomp,
1504 &flags,
1505 type, sizeof (type)))
1506 return NULL;
1508 /* Cache the volume information for future use, overwriting existing
1509 entry if present. */
1510 if (info == NULL)
1512 info = (volume_info_data *) xmalloc (sizeof (volume_info_data));
1513 add_volume_info (root_dir, info);
1515 else
1517 xfree (info->name);
1518 xfree (info->type);
1521 info->name = xstrdup (name);
1522 info->serialnum = serialnum;
1523 info->maxcomp = maxcomp;
1524 info->flags = flags;
1525 info->type = xstrdup (type);
1526 info->timestamp = GetTickCount ();
1529 return info;
1532 /* Get information on the volume where name is held; set path pointer to
1533 start of pathname in name (past UNC header\volume header if present). */
1535 get_volume_info (const char * name, const char ** pPath)
1537 char temp[MAX_PATH];
1538 char *rootname = NULL; /* default to current volume */
1539 volume_info_data * info;
1541 if (name == NULL)
1542 return FALSE;
1544 /* find the root name of the volume if given */
1545 if (isalpha (name[0]) && name[1] == ':')
1547 rootname = temp;
1548 temp[0] = *name++;
1549 temp[1] = *name++;
1550 temp[2] = '\\';
1551 temp[3] = 0;
1553 else if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1]))
1555 char *str = temp;
1556 int slashes = 4;
1557 rootname = temp;
1560 if (IS_DIRECTORY_SEP (*name) && --slashes == 0)
1561 break;
1562 *str++ = *name++;
1564 while ( *name );
1566 *str++ = '\\';
1567 *str = 0;
1570 if (pPath)
1571 *pPath = name;
1573 info = GetCachedVolumeInformation (rootname);
1574 if (info != NULL)
1576 /* Set global referenced by other functions. */
1577 volume_info = *info;
1578 return TRUE;
1580 return FALSE;
1583 /* Determine if volume is FAT format (ie. only supports short 8.3
1584 names); also set path pointer to start of pathname in name. */
1586 is_fat_volume (const char * name, const char ** pPath)
1588 if (get_volume_info (name, pPath))
1589 return (volume_info.maxcomp == 12);
1590 return FALSE;
1593 /* Map filename to a legal 8.3 name if necessary. */
1594 const char *
1595 map_w32_filename (const char * name, const char ** pPath)
1597 static char shortname[MAX_PATH];
1598 char * str = shortname;
1599 char c;
1600 char * path;
1601 const char * save_name = name;
1603 if (strlen (name) >= MAX_PATH)
1605 /* Return a filename which will cause callers to fail. */
1606 strcpy (shortname, "?");
1607 return shortname;
1610 if (is_fat_volume (name, (const char **)&path)) /* truncate to 8.3 */
1612 register int left = 8; /* maximum number of chars in part */
1613 register int extn = 0; /* extension added? */
1614 register int dots = 2; /* maximum number of dots allowed */
1616 while (name < path)
1617 *str++ = *name++; /* skip past UNC header */
1619 while ((c = *name++))
1621 switch ( c )
1623 case '\\':
1624 case '/':
1625 *str++ = '\\';
1626 extn = 0; /* reset extension flags */
1627 dots = 2; /* max 2 dots */
1628 left = 8; /* max length 8 for main part */
1629 break;
1630 case ':':
1631 *str++ = ':';
1632 extn = 0; /* reset extension flags */
1633 dots = 2; /* max 2 dots */
1634 left = 8; /* max length 8 for main part */
1635 break;
1636 case '.':
1637 if ( dots )
1639 /* Convert path components of the form .xxx to _xxx,
1640 but leave . and .. as they are. This allows .emacs
1641 to be read as _emacs, for example. */
1643 if (! *name ||
1644 *name == '.' ||
1645 IS_DIRECTORY_SEP (*name))
1647 *str++ = '.';
1648 dots--;
1650 else
1652 *str++ = '_';
1653 left--;
1654 dots = 0;
1657 else if ( !extn )
1659 *str++ = '.';
1660 extn = 1; /* we've got an extension */
1661 left = 3; /* 3 chars in extension */
1663 else
1665 /* any embedded dots after the first are converted to _ */
1666 *str++ = '_';
1668 break;
1669 case '~':
1670 case '#': /* don't lose these, they're important */
1671 if ( ! left )
1672 str[-1] = c; /* replace last character of part */
1673 /* FALLTHRU */
1674 default:
1675 if ( left )
1677 *str++ = tolower (c); /* map to lower case (looks nicer) */
1678 left--;
1679 dots = 0; /* started a path component */
1681 break;
1684 *str = '\0';
1686 else
1688 strcpy (shortname, name);
1689 unixtodos_filename (shortname);
1692 if (pPath)
1693 *pPath = shortname + (path - save_name);
1695 return shortname;
1698 static int
1699 is_exec (const char * name)
1701 char * p = strrchr (name, '.');
1702 return
1703 (p != NULL
1704 && (stricmp (p, ".exe") == 0 ||
1705 stricmp (p, ".com") == 0 ||
1706 stricmp (p, ".bat") == 0 ||
1707 stricmp (p, ".cmd") == 0));
1710 /* Emulate the Unix directory procedures opendir, closedir,
1711 and readdir. We can't use the procedures supplied in sysdep.c,
1712 so we provide them here. */
1714 struct direct dir_static; /* simulated directory contents */
1715 static HANDLE dir_find_handle = INVALID_HANDLE_VALUE;
1716 static int dir_is_fat;
1717 static char dir_pathname[MAXPATHLEN+1];
1718 static WIN32_FIND_DATA dir_find_data;
1720 /* Support shares on a network resource as subdirectories of a read-only
1721 root directory. */
1722 static HANDLE wnet_enum_handle = INVALID_HANDLE_VALUE;
1723 HANDLE open_unc_volume (const char *);
1724 char *read_unc_volume (HANDLE, char *, int);
1725 void close_unc_volume (HANDLE);
1727 DIR *
1728 opendir (char *filename)
1730 DIR *dirp;
1732 /* Opening is done by FindFirstFile. However, a read is inherent to
1733 this operation, so we defer the open until read time. */
1735 if (dir_find_handle != INVALID_HANDLE_VALUE)
1736 return NULL;
1737 if (wnet_enum_handle != INVALID_HANDLE_VALUE)
1738 return NULL;
1740 if (is_unc_volume (filename))
1742 wnet_enum_handle = open_unc_volume (filename);
1743 if (wnet_enum_handle == INVALID_HANDLE_VALUE)
1744 return NULL;
1747 if (!(dirp = (DIR *) malloc (sizeof (DIR))))
1748 return NULL;
1750 dirp->dd_fd = 0;
1751 dirp->dd_loc = 0;
1752 dirp->dd_size = 0;
1754 strncpy (dir_pathname, map_w32_filename (filename, NULL), MAXPATHLEN);
1755 dir_pathname[MAXPATHLEN] = '\0';
1756 dir_is_fat = is_fat_volume (filename, NULL);
1758 return dirp;
1761 void
1762 closedir (DIR *dirp)
1764 /* If we have a find-handle open, close it. */
1765 if (dir_find_handle != INVALID_HANDLE_VALUE)
1767 FindClose (dir_find_handle);
1768 dir_find_handle = INVALID_HANDLE_VALUE;
1770 else if (wnet_enum_handle != INVALID_HANDLE_VALUE)
1772 close_unc_volume (wnet_enum_handle);
1773 wnet_enum_handle = INVALID_HANDLE_VALUE;
1775 xfree ((char *) dirp);
1778 struct direct *
1779 readdir (DIR *dirp)
1781 if (wnet_enum_handle != INVALID_HANDLE_VALUE)
1783 if (!read_unc_volume (wnet_enum_handle,
1784 dir_find_data.cFileName,
1785 MAX_PATH))
1786 return NULL;
1788 /* If we aren't dir_finding, do a find-first, otherwise do a find-next. */
1789 else if (dir_find_handle == INVALID_HANDLE_VALUE)
1791 char filename[MAXNAMLEN + 3];
1792 int ln;
1794 strcpy (filename, dir_pathname);
1795 ln = strlen (filename) - 1;
1796 if (!IS_DIRECTORY_SEP (filename[ln]))
1797 strcat (filename, "\\");
1798 strcat (filename, "*");
1800 dir_find_handle = FindFirstFile (filename, &dir_find_data);
1802 if (dir_find_handle == INVALID_HANDLE_VALUE)
1803 return NULL;
1805 else
1807 if (!FindNextFile (dir_find_handle, &dir_find_data))
1808 return NULL;
1811 /* Emacs never uses this value, so don't bother making it match
1812 value returned by stat(). */
1813 dir_static.d_ino = 1;
1815 dir_static.d_reclen = sizeof (struct direct) - MAXNAMLEN + 3 +
1816 dir_static.d_namlen - dir_static.d_namlen % 4;
1818 dir_static.d_namlen = strlen (dir_find_data.cFileName);
1819 strcpy (dir_static.d_name, dir_find_data.cFileName);
1820 if (dir_is_fat)
1821 _strlwr (dir_static.d_name);
1822 else if (!NILP (Vw32_downcase_file_names))
1824 register char *p;
1825 for (p = dir_static.d_name; *p; p++)
1826 if (*p >= 'a' && *p <= 'z')
1827 break;
1828 if (!*p)
1829 _strlwr (dir_static.d_name);
1832 return &dir_static;
1835 HANDLE
1836 open_unc_volume (const char *path)
1838 NETRESOURCE nr;
1839 HANDLE henum;
1840 int result;
1842 nr.dwScope = RESOURCE_GLOBALNET;
1843 nr.dwType = RESOURCETYPE_DISK;
1844 nr.dwDisplayType = RESOURCEDISPLAYTYPE_SERVER;
1845 nr.dwUsage = RESOURCEUSAGE_CONTAINER;
1846 nr.lpLocalName = NULL;
1847 nr.lpRemoteName = (LPSTR)map_w32_filename (path, NULL);
1848 nr.lpComment = NULL;
1849 nr.lpProvider = NULL;
1851 result = WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_DISK,
1852 RESOURCEUSAGE_CONNECTABLE, &nr, &henum);
1854 if (result == NO_ERROR)
1855 return henum;
1856 else
1857 return INVALID_HANDLE_VALUE;
1860 char *
1861 read_unc_volume (HANDLE henum, char *readbuf, int size)
1863 DWORD count;
1864 int result;
1865 DWORD bufsize = 512;
1866 char *buffer;
1867 char *ptr;
1869 count = 1;
1870 buffer = alloca (bufsize);
1871 result = WNetEnumResource (wnet_enum_handle, &count, buffer, &bufsize);
1872 if (result != NO_ERROR)
1873 return NULL;
1875 /* WNetEnumResource returns \\resource\share...skip forward to "share". */
1876 ptr = ((LPNETRESOURCE) buffer)->lpRemoteName;
1877 ptr += 2;
1878 while (*ptr && !IS_DIRECTORY_SEP (*ptr)) ptr++;
1879 ptr++;
1881 strncpy (readbuf, ptr, size);
1882 return readbuf;
1885 void
1886 close_unc_volume (HANDLE henum)
1888 if (henum != INVALID_HANDLE_VALUE)
1889 WNetCloseEnum (henum);
1892 DWORD
1893 unc_volume_file_attributes (const char *path)
1895 HANDLE henum;
1896 DWORD attrs;
1898 henum = open_unc_volume (path);
1899 if (henum == INVALID_HANDLE_VALUE)
1900 return -1;
1902 attrs = FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_DIRECTORY;
1904 close_unc_volume (henum);
1906 return attrs;
1910 /* Shadow some MSVC runtime functions to map requests for long filenames
1911 to reasonable short names if necessary. This was originally added to
1912 permit running Emacs on NT 3.1 on a FAT partition, which doesn't support
1913 long file names. */
1916 sys_access (const char * path, int mode)
1918 DWORD attributes;
1920 /* MSVC implementation doesn't recognize D_OK. */
1921 path = map_w32_filename (path, NULL);
1922 if (is_unc_volume (path))
1924 attributes = unc_volume_file_attributes (path);
1925 if (attributes == -1) {
1926 errno = EACCES;
1927 return -1;
1930 else if ((attributes = GetFileAttributes (path)) == -1)
1932 /* Should try mapping GetLastError to errno; for now just indicate
1933 that path doesn't exist. */
1934 errno = EACCES;
1935 return -1;
1937 if ((mode & X_OK) != 0 && !is_exec (path))
1939 errno = EACCES;
1940 return -1;
1942 if ((mode & W_OK) != 0 && (attributes & FILE_ATTRIBUTE_READONLY) != 0)
1944 errno = EACCES;
1945 return -1;
1947 if ((mode & D_OK) != 0 && (attributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
1949 errno = EACCES;
1950 return -1;
1952 return 0;
1956 sys_chdir (const char * path)
1958 return _chdir (map_w32_filename (path, NULL));
1962 sys_chmod (const char * path, int mode)
1964 return _chmod (map_w32_filename (path, NULL), mode);
1968 sys_chown (const char *path, uid_t owner, gid_t group)
1970 if (sys_chmod (path, _S_IREAD) == -1) /* check if file exists */
1971 return -1;
1972 return 0;
1976 sys_creat (const char * path, int mode)
1978 return _creat (map_w32_filename (path, NULL), mode);
1981 FILE *
1982 sys_fopen(const char * path, const char * mode)
1984 int fd;
1985 int oflag;
1986 const char * mode_save = mode;
1988 /* Force all file handles to be non-inheritable. This is necessary to
1989 ensure child processes don't unwittingly inherit handles that might
1990 prevent future file access. */
1992 if (mode[0] == 'r')
1993 oflag = O_RDONLY;
1994 else if (mode[0] == 'w' || mode[0] == 'a')
1995 oflag = O_WRONLY | O_CREAT | O_TRUNC;
1996 else
1997 return NULL;
1999 /* Only do simplistic option parsing. */
2000 while (*++mode)
2001 if (mode[0] == '+')
2003 oflag &= ~(O_RDONLY | O_WRONLY);
2004 oflag |= O_RDWR;
2006 else if (mode[0] == 'b')
2008 oflag &= ~O_TEXT;
2009 oflag |= O_BINARY;
2011 else if (mode[0] == 't')
2013 oflag &= ~O_BINARY;
2014 oflag |= O_TEXT;
2016 else break;
2018 fd = _open (map_w32_filename (path, NULL), oflag | _O_NOINHERIT, 0644);
2019 if (fd < 0)
2020 return NULL;
2022 return _fdopen (fd, mode_save);
2025 /* This only works on NTFS volumes, but is useful to have. */
2027 sys_link (const char * old, const char * new)
2029 HANDLE fileh;
2030 int result = -1;
2031 char oldname[MAX_PATH], newname[MAX_PATH];
2033 if (old == NULL || new == NULL)
2035 errno = ENOENT;
2036 return -1;
2039 strcpy (oldname, map_w32_filename (old, NULL));
2040 strcpy (newname, map_w32_filename (new, NULL));
2042 fileh = CreateFile (oldname, 0, 0, NULL, OPEN_EXISTING,
2043 FILE_FLAG_BACKUP_SEMANTICS, NULL);
2044 if (fileh != INVALID_HANDLE_VALUE)
2046 int wlen;
2048 /* Confusingly, the "alternate" stream name field does not apply
2049 when restoring a hard link, and instead contains the actual
2050 stream data for the link (ie. the name of the link to create).
2051 The WIN32_STREAM_ID structure before the cStreamName field is
2052 the stream header, which is then immediately followed by the
2053 stream data. */
2055 struct {
2056 WIN32_STREAM_ID wid;
2057 WCHAR wbuffer[MAX_PATH]; /* extra space for link name */
2058 } data;
2060 wlen = MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, newname, -1,
2061 data.wid.cStreamName, MAX_PATH);
2062 if (wlen > 0)
2064 LPVOID context = NULL;
2065 DWORD wbytes = 0;
2067 data.wid.dwStreamId = BACKUP_LINK;
2068 data.wid.dwStreamAttributes = 0;
2069 data.wid.Size.LowPart = wlen * sizeof(WCHAR);
2070 data.wid.Size.HighPart = 0;
2071 data.wid.dwStreamNameSize = 0;
2073 if (BackupWrite (fileh, (LPBYTE)&data,
2074 offsetof (WIN32_STREAM_ID, cStreamName)
2075 + data.wid.Size.LowPart,
2076 &wbytes, FALSE, FALSE, &context)
2077 && BackupWrite (fileh, NULL, 0, &wbytes, TRUE, FALSE, &context))
2079 /* succeeded */
2080 result = 0;
2082 else
2084 /* Should try mapping GetLastError to errno; for now just
2085 indicate a general error (eg. links not supported). */
2086 errno = EINVAL; // perhaps EMLINK?
2090 CloseHandle (fileh);
2092 else
2093 errno = ENOENT;
2095 return result;
2099 sys_mkdir (const char * path)
2101 return _mkdir (map_w32_filename (path, NULL));
2104 /* Because of long name mapping issues, we need to implement this
2105 ourselves. Also, MSVC's _mktemp returns NULL when it can't generate
2106 a unique name, instead of setting the input template to an empty
2107 string.
2109 Standard algorithm seems to be use pid or tid with a letter on the
2110 front (in place of the 6 X's) and cycle through the letters to find a
2111 unique name. We extend that to allow any reasonable character as the
2112 first of the 6 X's. */
2113 char *
2114 sys_mktemp (char * template)
2116 char * p;
2117 int i;
2118 unsigned uid = GetCurrentThreadId ();
2119 static char first_char[] = "abcdefghijklmnopqrstuvwyz0123456789!%-_@#";
2121 if (template == NULL)
2122 return NULL;
2123 p = template + strlen (template);
2124 i = 5;
2125 /* replace up to the last 5 X's with uid in decimal */
2126 while (--p >= template && p[0] == 'X' && --i >= 0)
2128 p[0] = '0' + uid % 10;
2129 uid /= 10;
2132 if (i < 0 && p[0] == 'X')
2134 i = 0;
2137 int save_errno = errno;
2138 p[0] = first_char[i];
2139 if (sys_access (template, 0) < 0)
2141 errno = save_errno;
2142 return template;
2145 while (++i < sizeof (first_char));
2148 /* Template is badly formed or else we can't generate a unique name,
2149 so return empty string */
2150 template[0] = 0;
2151 return template;
2155 sys_open (const char * path, int oflag, int mode)
2157 const char* mpath = map_w32_filename (path, NULL);
2158 /* Try to open file without _O_CREAT, to be able to write to hidden
2159 and system files. Force all file handles to be
2160 non-inheritable. */
2161 int res = _open (mpath, (oflag & ~_O_CREAT) | _O_NOINHERIT, mode);
2162 if (res >= 0)
2163 return res;
2164 return _open (mpath, oflag | _O_NOINHERIT, mode);
2168 sys_rename (const char * oldname, const char * newname)
2170 BOOL result;
2171 char temp[MAX_PATH];
2173 /* MoveFile on Windows 95 doesn't correctly change the short file name
2174 alias in a number of circumstances (it is not easy to predict when
2175 just by looking at oldname and newname, unfortunately). In these
2176 cases, renaming through a temporary name avoids the problem.
2178 A second problem on Windows 95 is that renaming through a temp name when
2179 newname is uppercase fails (the final long name ends up in
2180 lowercase, although the short alias might be uppercase) UNLESS the
2181 long temp name is not 8.3.
2183 So, on Windows 95 we always rename through a temp name, and we make sure
2184 the temp name has a long extension to ensure correct renaming. */
2186 strcpy (temp, map_w32_filename (oldname, NULL));
2188 if (os_subtype == OS_WIN95)
2190 char * o;
2191 char * p;
2192 int i = 0;
2194 oldname = map_w32_filename (oldname, NULL);
2195 if (o = strrchr (oldname, '\\'))
2196 o++;
2197 else
2198 o = (char *) oldname;
2200 if (p = strrchr (temp, '\\'))
2201 p++;
2202 else
2203 p = temp;
2207 /* Force temp name to require a manufactured 8.3 alias - this
2208 seems to make the second rename work properly. */
2209 sprintf (p, "_.%s.%u", o, i);
2210 i++;
2211 result = rename (oldname, temp);
2213 /* This loop must surely terminate! */
2214 while (result < 0 && errno == EEXIST);
2215 if (result < 0)
2216 return -1;
2219 /* Emulate Unix behaviour - newname is deleted if it already exists
2220 (at least if it is a file; don't do this for directories).
2222 Since we mustn't do this if we are just changing the case of the
2223 file name (we would end up deleting the file we are trying to
2224 rename!), we let rename detect if the destination file already
2225 exists - that way we avoid the possible pitfalls of trying to
2226 determine ourselves whether two names really refer to the same
2227 file, which is not always possible in the general case. (Consider
2228 all the permutations of shared or subst'd drives, etc.) */
2230 newname = map_w32_filename (newname, NULL);
2231 result = rename (temp, newname);
2233 if (result < 0
2234 && errno == EEXIST
2235 && _chmod (newname, 0666) == 0
2236 && _unlink (newname) == 0)
2237 result = rename (temp, newname);
2239 return result;
2243 sys_rmdir (const char * path)
2245 return _rmdir (map_w32_filename (path, NULL));
2249 sys_unlink (const char * path)
2251 path = map_w32_filename (path, NULL);
2253 /* On Unix, unlink works without write permission. */
2254 _chmod (path, 0666);
2255 return _unlink (path);
2258 static FILETIME utc_base_ft;
2259 static long double utc_base;
2260 static int init = 0;
2262 static time_t
2263 convert_time (FILETIME ft)
2265 long double ret;
2267 if (!init)
2269 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
2270 SYSTEMTIME st;
2272 st.wYear = 1970;
2273 st.wMonth = 1;
2274 st.wDay = 1;
2275 st.wHour = 0;
2276 st.wMinute = 0;
2277 st.wSecond = 0;
2278 st.wMilliseconds = 0;
2280 SystemTimeToFileTime (&st, &utc_base_ft);
2281 utc_base = (long double) utc_base_ft.dwHighDateTime
2282 * 4096.0L * 1024.0L * 1024.0L + utc_base_ft.dwLowDateTime;
2283 init = 1;
2286 if (CompareFileTime (&ft, &utc_base_ft) < 0)
2287 return 0;
2289 ret = (long double) ft.dwHighDateTime
2290 * 4096.0L * 1024.0L * 1024.0L + ft.dwLowDateTime;
2291 ret -= utc_base;
2292 return (time_t) (ret * 1e-7L);
2295 void
2296 convert_from_time_t (time_t time, FILETIME * pft)
2298 long double tmp;
2300 if (!init)
2302 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
2303 SYSTEMTIME st;
2305 st.wYear = 1970;
2306 st.wMonth = 1;
2307 st.wDay = 1;
2308 st.wHour = 0;
2309 st.wMinute = 0;
2310 st.wSecond = 0;
2311 st.wMilliseconds = 0;
2313 SystemTimeToFileTime (&st, &utc_base_ft);
2314 utc_base = (long double) utc_base_ft.dwHighDateTime
2315 * 4096 * 1024 * 1024 + utc_base_ft.dwLowDateTime;
2316 init = 1;
2319 /* time in 100ns units since 1-Jan-1601 */
2320 tmp = (long double) time * 1e7 + utc_base;
2321 pft->dwHighDateTime = (DWORD) (tmp / (4096.0 * 1024 * 1024));
2322 pft->dwLowDateTime = (DWORD) (tmp - (4096.0 * 1024 * 1024) * pft->dwHighDateTime);
2325 #if 0
2326 /* No reason to keep this; faking inode values either by hashing or even
2327 using the file index from GetInformationByHandle, is not perfect and
2328 so by default Emacs doesn't use the inode values on Windows.
2329 Instead, we now determine file-truename correctly (except for
2330 possible drive aliasing etc). */
2332 /* Modified version of "PJW" algorithm (see the "Dragon" compiler book). */
2333 static unsigned
2334 hashval (const unsigned char * str)
2336 unsigned h = 0;
2337 while (*str)
2339 h = (h << 4) + *str++;
2340 h ^= (h >> 28);
2342 return h;
2345 /* Return the hash value of the canonical pathname, excluding the
2346 drive/UNC header, to get a hopefully unique inode number. */
2347 static DWORD
2348 generate_inode_val (const char * name)
2350 char fullname[ MAX_PATH ];
2351 char * p;
2352 unsigned hash;
2354 /* Get the truly canonical filename, if it exists. (Note: this
2355 doesn't resolve aliasing due to subst commands, or recognise hard
2356 links. */
2357 if (!w32_get_long_filename ((char *)name, fullname, MAX_PATH))
2358 abort ();
2360 parse_root (fullname, &p);
2361 /* Normal W32 filesystems are still case insensitive. */
2362 _strlwr (p);
2363 return hashval (p);
2366 #endif
2368 /* MSVC stat function can't cope with UNC names and has other bugs, so
2369 replace it with our own. This also allows us to calculate consistent
2370 inode values without hacks in the main Emacs code. */
2372 stat (const char * path, struct stat * buf)
2374 char *name, *r;
2375 WIN32_FIND_DATA wfd;
2376 HANDLE fh;
2377 DWORD fake_inode;
2378 int permission;
2379 int len;
2380 int rootdir = FALSE;
2382 if (path == NULL || buf == NULL)
2384 errno = EFAULT;
2385 return -1;
2388 name = (char *) map_w32_filename (path, &path);
2389 /* must be valid filename, no wild cards or other invalid characters */
2390 if (strpbrk (name, "*?|<>\""))
2392 errno = ENOENT;
2393 return -1;
2396 /* If name is "c:/.." or "/.." then stat "c:/" or "/". */
2397 r = IS_DEVICE_SEP (name[1]) ? &name[2] : name;
2398 if (IS_DIRECTORY_SEP (r[0]) && r[1] == '.' && r[2] == '.' && r[3] == '\0')
2400 r[1] = r[2] = '\0';
2403 /* Remove trailing directory separator, unless name is the root
2404 directory of a drive or UNC volume in which case ensure there
2405 is a trailing separator. */
2406 len = strlen (name);
2407 rootdir = (path >= name + len - 1
2408 && (IS_DIRECTORY_SEP (*path) || *path == 0));
2409 name = strcpy (alloca (len + 2), name);
2411 if (is_unc_volume (name))
2413 DWORD attrs = unc_volume_file_attributes (name);
2415 if (attrs == -1)
2416 return -1;
2418 memset (&wfd, 0, sizeof (wfd));
2419 wfd.dwFileAttributes = attrs;
2420 wfd.ftCreationTime = utc_base_ft;
2421 wfd.ftLastAccessTime = utc_base_ft;
2422 wfd.ftLastWriteTime = utc_base_ft;
2423 strcpy (wfd.cFileName, name);
2425 else if (rootdir)
2427 if (!IS_DIRECTORY_SEP (name[len-1]))
2428 strcat (name, "\\");
2429 if (GetDriveType (name) < 2)
2431 errno = ENOENT;
2432 return -1;
2434 memset (&wfd, 0, sizeof (wfd));
2435 wfd.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY;
2436 wfd.ftCreationTime = utc_base_ft;
2437 wfd.ftLastAccessTime = utc_base_ft;
2438 wfd.ftLastWriteTime = utc_base_ft;
2439 strcpy (wfd.cFileName, name);
2441 else
2443 if (IS_DIRECTORY_SEP (name[len-1]))
2444 name[len - 1] = 0;
2446 /* (This is hacky, but helps when doing file completions on
2447 network drives.) Optimize by using information available from
2448 active readdir if possible. */
2449 len = strlen (dir_pathname);
2450 if (IS_DIRECTORY_SEP (dir_pathname[len-1]))
2451 len--;
2452 if (dir_find_handle != INVALID_HANDLE_VALUE
2453 && strnicmp (name, dir_pathname, len) == 0
2454 && IS_DIRECTORY_SEP (name[len])
2455 && stricmp (name + len + 1, dir_static.d_name) == 0)
2457 /* This was the last entry returned by readdir. */
2458 wfd = dir_find_data;
2460 else
2462 fh = FindFirstFile (name, &wfd);
2463 if (fh == INVALID_HANDLE_VALUE)
2465 errno = ENOENT;
2466 return -1;
2468 FindClose (fh);
2472 if (!NILP (Vw32_get_true_file_attributes)
2473 /* No access rights required to get info. */
2474 && (fh = CreateFile (name, 0, 0, NULL, OPEN_EXISTING,
2475 FILE_FLAG_BACKUP_SEMANTICS, NULL))
2476 != INVALID_HANDLE_VALUE)
2478 /* This is more accurate in terms of gettting the correct number
2479 of links, but is quite slow (it is noticable when Emacs is
2480 making a list of file name completions). */
2481 BY_HANDLE_FILE_INFORMATION info;
2483 if (GetFileInformationByHandle (fh, &info))
2485 buf->st_nlink = info.nNumberOfLinks;
2486 /* Might as well use file index to fake inode values, but this
2487 is not guaranteed to be unique unless we keep a handle open
2488 all the time (even then there are situations where it is
2489 not unique). Reputedly, there are at most 48 bits of info
2490 (on NTFS, presumably less on FAT). */
2491 fake_inode = info.nFileIndexLow ^ info.nFileIndexHigh;
2493 else
2495 buf->st_nlink = 1;
2496 fake_inode = 0;
2499 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
2501 buf->st_mode = _S_IFDIR;
2503 else
2505 switch (GetFileType (fh))
2507 case FILE_TYPE_DISK:
2508 buf->st_mode = _S_IFREG;
2509 break;
2510 case FILE_TYPE_PIPE:
2511 buf->st_mode = _S_IFIFO;
2512 break;
2513 case FILE_TYPE_CHAR:
2514 case FILE_TYPE_UNKNOWN:
2515 default:
2516 buf->st_mode = _S_IFCHR;
2519 CloseHandle (fh);
2521 else
2523 /* Don't bother to make this information more accurate. */
2524 buf->st_mode = (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ?
2525 _S_IFDIR : _S_IFREG;
2526 buf->st_nlink = 1;
2527 fake_inode = 0;
2530 #if 0
2531 /* Not sure if there is any point in this. */
2532 if (!NILP (Vw32_generate_fake_inodes))
2533 fake_inode = generate_inode_val (name);
2534 else if (fake_inode == 0)
2536 /* For want of something better, try to make everything unique. */
2537 static DWORD gen_num = 0;
2538 fake_inode = ++gen_num;
2540 #endif
2542 /* MSVC defines _ino_t to be short; other libc's might not. */
2543 if (sizeof (buf->st_ino) == 2)
2544 buf->st_ino = fake_inode ^ (fake_inode >> 16);
2545 else
2546 buf->st_ino = fake_inode;
2548 /* consider files to belong to current user */
2549 buf->st_uid = the_passwd.pw_uid;
2550 buf->st_gid = the_passwd.pw_gid;
2552 /* volume_info is set indirectly by map_w32_filename */
2553 buf->st_dev = volume_info.serialnum;
2554 buf->st_rdev = volume_info.serialnum;
2557 buf->st_size = wfd.nFileSizeLow;
2559 /* Convert timestamps to Unix format. */
2560 buf->st_mtime = convert_time (wfd.ftLastWriteTime);
2561 buf->st_atime = convert_time (wfd.ftLastAccessTime);
2562 if (buf->st_atime == 0) buf->st_atime = buf->st_mtime;
2563 buf->st_ctime = convert_time (wfd.ftCreationTime);
2564 if (buf->st_ctime == 0) buf->st_ctime = buf->st_mtime;
2566 /* determine rwx permissions */
2567 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
2568 permission = _S_IREAD;
2569 else
2570 permission = _S_IREAD | _S_IWRITE;
2572 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
2573 permission |= _S_IEXEC;
2574 else if (is_exec (name))
2575 permission |= _S_IEXEC;
2577 buf->st_mode |= permission | (permission >> 3) | (permission >> 6);
2579 return 0;
2582 /* Provide fstat and utime as well as stat for consistent handling of
2583 file timestamps. */
2585 fstat (int desc, struct stat * buf)
2587 HANDLE fh = (HANDLE) _get_osfhandle (desc);
2588 BY_HANDLE_FILE_INFORMATION info;
2589 DWORD fake_inode;
2590 int permission;
2592 switch (GetFileType (fh) & ~FILE_TYPE_REMOTE)
2594 case FILE_TYPE_DISK:
2595 buf->st_mode = _S_IFREG;
2596 if (!GetFileInformationByHandle (fh, &info))
2598 errno = EACCES;
2599 return -1;
2601 break;
2602 case FILE_TYPE_PIPE:
2603 buf->st_mode = _S_IFIFO;
2604 goto non_disk;
2605 case FILE_TYPE_CHAR:
2606 case FILE_TYPE_UNKNOWN:
2607 default:
2608 buf->st_mode = _S_IFCHR;
2609 non_disk:
2610 memset (&info, 0, sizeof (info));
2611 info.dwFileAttributes = 0;
2612 info.ftCreationTime = utc_base_ft;
2613 info.ftLastAccessTime = utc_base_ft;
2614 info.ftLastWriteTime = utc_base_ft;
2617 if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
2618 buf->st_mode = _S_IFDIR;
2620 buf->st_nlink = info.nNumberOfLinks;
2621 /* Might as well use file index to fake inode values, but this
2622 is not guaranteed to be unique unless we keep a handle open
2623 all the time (even then there are situations where it is
2624 not unique). Reputedly, there are at most 48 bits of info
2625 (on NTFS, presumably less on FAT). */
2626 fake_inode = info.nFileIndexLow ^ info.nFileIndexHigh;
2628 /* MSVC defines _ino_t to be short; other libc's might not. */
2629 if (sizeof (buf->st_ino) == 2)
2630 buf->st_ino = fake_inode ^ (fake_inode >> 16);
2631 else
2632 buf->st_ino = fake_inode;
2634 /* consider files to belong to current user */
2635 buf->st_uid = 0;
2636 buf->st_gid = 0;
2638 buf->st_dev = info.dwVolumeSerialNumber;
2639 buf->st_rdev = info.dwVolumeSerialNumber;
2641 buf->st_size = info.nFileSizeLow;
2643 /* Convert timestamps to Unix format. */
2644 buf->st_mtime = convert_time (info.ftLastWriteTime);
2645 buf->st_atime = convert_time (info.ftLastAccessTime);
2646 if (buf->st_atime == 0) buf->st_atime = buf->st_mtime;
2647 buf->st_ctime = convert_time (info.ftCreationTime);
2648 if (buf->st_ctime == 0) buf->st_ctime = buf->st_mtime;
2650 /* determine rwx permissions */
2651 if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
2652 permission = _S_IREAD;
2653 else
2654 permission = _S_IREAD | _S_IWRITE;
2656 if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
2657 permission |= _S_IEXEC;
2658 else
2660 #if 0 /* no way of knowing the filename */
2661 char * p = strrchr (name, '.');
2662 if (p != NULL &&
2663 (stricmp (p, ".exe") == 0 ||
2664 stricmp (p, ".com") == 0 ||
2665 stricmp (p, ".bat") == 0 ||
2666 stricmp (p, ".cmd") == 0))
2667 permission |= _S_IEXEC;
2668 #endif
2671 buf->st_mode |= permission | (permission >> 3) | (permission >> 6);
2673 return 0;
2677 utime (const char *name, struct utimbuf *times)
2679 struct utimbuf deftime;
2680 HANDLE fh;
2681 FILETIME mtime;
2682 FILETIME atime;
2684 if (times == NULL)
2686 deftime.modtime = deftime.actime = time (NULL);
2687 times = &deftime;
2690 /* Need write access to set times. */
2691 fh = CreateFile (name, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
2692 0, OPEN_EXISTING, 0, NULL);
2693 if (fh)
2695 convert_from_time_t (times->actime, &atime);
2696 convert_from_time_t (times->modtime, &mtime);
2697 if (!SetFileTime (fh, NULL, &atime, &mtime))
2699 CloseHandle (fh);
2700 errno = EACCES;
2701 return -1;
2703 CloseHandle (fh);
2705 else
2707 errno = EINVAL;
2708 return -1;
2710 return 0;
2713 #ifdef HAVE_SOCKETS
2715 /* Wrappers for winsock functions to map between our file descriptors
2716 and winsock's handles; also set h_errno for convenience.
2718 To allow Emacs to run on systems which don't have winsock support
2719 installed, we dynamically link to winsock on startup if present, and
2720 otherwise provide the minimum necessary functionality
2721 (eg. gethostname). */
2723 /* function pointers for relevant socket functions */
2724 int (PASCAL *pfn_WSAStartup) (WORD wVersionRequired, LPWSADATA lpWSAData);
2725 void (PASCAL *pfn_WSASetLastError) (int iError);
2726 int (PASCAL *pfn_WSAGetLastError) (void);
2727 int (PASCAL *pfn_WSAEventSelect) (SOCKET s, HANDLE hEventObject, long lNetworkEvents);
2728 HANDLE (PASCAL *pfn_WSACreateEvent) (void);
2729 int (PASCAL *pfn_WSACloseEvent) (HANDLE hEvent);
2730 int (PASCAL *pfn_socket) (int af, int type, int protocol);
2731 int (PASCAL *pfn_bind) (SOCKET s, const struct sockaddr *addr, int namelen);
2732 int (PASCAL *pfn_connect) (SOCKET s, const struct sockaddr *addr, int namelen);
2733 int (PASCAL *pfn_ioctlsocket) (SOCKET s, long cmd, u_long *argp);
2734 int (PASCAL *pfn_recv) (SOCKET s, char * buf, int len, int flags);
2735 int (PASCAL *pfn_send) (SOCKET s, const char * buf, int len, int flags);
2736 int (PASCAL *pfn_closesocket) (SOCKET s);
2737 int (PASCAL *pfn_shutdown) (SOCKET s, int how);
2738 int (PASCAL *pfn_WSACleanup) (void);
2740 u_short (PASCAL *pfn_htons) (u_short hostshort);
2741 u_short (PASCAL *pfn_ntohs) (u_short netshort);
2742 unsigned long (PASCAL *pfn_inet_addr) (const char * cp);
2743 int (PASCAL *pfn_gethostname) (char * name, int namelen);
2744 struct hostent * (PASCAL *pfn_gethostbyname) (const char * name);
2745 struct servent * (PASCAL *pfn_getservbyname) (const char * name, const char * proto);
2746 int (PASCAL *pfn_getpeername) (SOCKET s, struct sockaddr *addr, int * namelen);
2747 int (PASCAL *pfn_setsockopt) (SOCKET s, int level, int optname,
2748 const char * optval, int optlen);
2749 int (PASCAL *pfn_listen) (SOCKET s, int backlog);
2750 int (PASCAL *pfn_getsockname) (SOCKET s, struct sockaddr * name,
2751 int * namelen);
2752 SOCKET (PASCAL *pfn_accept) (SOCKET s, struct sockaddr * addr, int * addrlen);
2753 int (PASCAL *pfn_recvfrom) (SOCKET s, char * buf, int len, int flags,
2754 struct sockaddr * from, int * fromlen);
2755 int (PASCAL *pfn_sendto) (SOCKET s, const char * buf, int len, int flags,
2756 const struct sockaddr * to, int tolen);
2758 /* SetHandleInformation is only needed to make sockets non-inheritable. */
2759 BOOL (WINAPI *pfn_SetHandleInformation) (HANDLE object, DWORD mask, DWORD flags);
2760 #ifndef HANDLE_FLAG_INHERIT
2761 #define HANDLE_FLAG_INHERIT 1
2762 #endif
2764 HANDLE winsock_lib;
2765 static int winsock_inuse;
2767 BOOL
2768 term_winsock (void)
2770 if (winsock_lib != NULL && winsock_inuse == 0)
2772 /* Not sure what would cause WSAENETDOWN, or even if it can happen
2773 after WSAStartup returns successfully, but it seems reasonable
2774 to allow unloading winsock anyway in that case. */
2775 if (pfn_WSACleanup () == 0 ||
2776 pfn_WSAGetLastError () == WSAENETDOWN)
2778 if (FreeLibrary (winsock_lib))
2779 winsock_lib = NULL;
2780 return TRUE;
2783 return FALSE;
2786 BOOL
2787 init_winsock (int load_now)
2789 WSADATA winsockData;
2791 if (winsock_lib != NULL)
2792 return TRUE;
2794 pfn_SetHandleInformation = NULL;
2795 pfn_SetHandleInformation
2796 = (void *) GetProcAddress (GetModuleHandle ("kernel32.dll"),
2797 "SetHandleInformation");
2799 winsock_lib = LoadLibrary ("Ws2_32.dll");
2801 if (winsock_lib != NULL)
2803 /* dynamically link to socket functions */
2805 #define LOAD_PROC(fn) \
2806 if ((pfn_##fn = (void *) GetProcAddress (winsock_lib, #fn)) == NULL) \
2807 goto fail;
2809 LOAD_PROC( WSAStartup );
2810 LOAD_PROC( WSASetLastError );
2811 LOAD_PROC( WSAGetLastError );
2812 LOAD_PROC( WSAEventSelect );
2813 LOAD_PROC( WSACreateEvent );
2814 LOAD_PROC( WSACloseEvent );
2815 LOAD_PROC( socket );
2816 LOAD_PROC( bind );
2817 LOAD_PROC( connect );
2818 LOAD_PROC( ioctlsocket );
2819 LOAD_PROC( recv );
2820 LOAD_PROC( send );
2821 LOAD_PROC( closesocket );
2822 LOAD_PROC( shutdown );
2823 LOAD_PROC( htons );
2824 LOAD_PROC( ntohs );
2825 LOAD_PROC( inet_addr );
2826 LOAD_PROC( gethostname );
2827 LOAD_PROC( gethostbyname );
2828 LOAD_PROC( getservbyname );
2829 LOAD_PROC( getpeername );
2830 LOAD_PROC( WSACleanup );
2831 LOAD_PROC( setsockopt );
2832 LOAD_PROC( listen );
2833 LOAD_PROC( getsockname );
2834 LOAD_PROC( accept );
2835 LOAD_PROC( recvfrom );
2836 LOAD_PROC( sendto );
2837 #undef LOAD_PROC
2839 /* specify version 1.1 of winsock */
2840 if (pfn_WSAStartup (0x101, &winsockData) == 0)
2842 if (winsockData.wVersion != 0x101)
2843 goto fail;
2845 if (!load_now)
2847 /* Report that winsock exists and is usable, but leave
2848 socket functions disabled. I am assuming that calling
2849 WSAStartup does not require any network interaction,
2850 and in particular does not cause or require a dial-up
2851 connection to be established. */
2853 pfn_WSACleanup ();
2854 FreeLibrary (winsock_lib);
2855 winsock_lib = NULL;
2857 winsock_inuse = 0;
2858 return TRUE;
2861 fail:
2862 FreeLibrary (winsock_lib);
2863 winsock_lib = NULL;
2866 return FALSE;
2870 int h_errno = 0;
2872 /* function to set h_errno for compatability; map winsock error codes to
2873 normal system codes where they overlap (non-overlapping definitions
2874 are already in <sys/socket.h> */
2875 static void
2876 set_errno ()
2878 if (winsock_lib == NULL)
2879 h_errno = EINVAL;
2880 else
2881 h_errno = pfn_WSAGetLastError ();
2883 switch (h_errno)
2885 case WSAEACCES: h_errno = EACCES; break;
2886 case WSAEBADF: h_errno = EBADF; break;
2887 case WSAEFAULT: h_errno = EFAULT; break;
2888 case WSAEINTR: h_errno = EINTR; break;
2889 case WSAEINVAL: h_errno = EINVAL; break;
2890 case WSAEMFILE: h_errno = EMFILE; break;
2891 case WSAENAMETOOLONG: h_errno = ENAMETOOLONG; break;
2892 case WSAENOTEMPTY: h_errno = ENOTEMPTY; break;
2894 errno = h_errno;
2897 static void
2898 check_errno ()
2900 if (h_errno == 0 && winsock_lib != NULL)
2901 pfn_WSASetLastError (0);
2904 /* Extend strerror to handle the winsock-specific error codes. */
2905 struct {
2906 int errnum;
2907 char * msg;
2908 } _wsa_errlist[] = {
2909 WSAEINTR , "Interrupted function call",
2910 WSAEBADF , "Bad file descriptor",
2911 WSAEACCES , "Permission denied",
2912 WSAEFAULT , "Bad address",
2913 WSAEINVAL , "Invalid argument",
2914 WSAEMFILE , "Too many open files",
2916 WSAEWOULDBLOCK , "Resource temporarily unavailable",
2917 WSAEINPROGRESS , "Operation now in progress",
2918 WSAEALREADY , "Operation already in progress",
2919 WSAENOTSOCK , "Socket operation on non-socket",
2920 WSAEDESTADDRREQ , "Destination address required",
2921 WSAEMSGSIZE , "Message too long",
2922 WSAEPROTOTYPE , "Protocol wrong type for socket",
2923 WSAENOPROTOOPT , "Bad protocol option",
2924 WSAEPROTONOSUPPORT , "Protocol not supported",
2925 WSAESOCKTNOSUPPORT , "Socket type not supported",
2926 WSAEOPNOTSUPP , "Operation not supported",
2927 WSAEPFNOSUPPORT , "Protocol family not supported",
2928 WSAEAFNOSUPPORT , "Address family not supported by protocol family",
2929 WSAEADDRINUSE , "Address already in use",
2930 WSAEADDRNOTAVAIL , "Cannot assign requested address",
2931 WSAENETDOWN , "Network is down",
2932 WSAENETUNREACH , "Network is unreachable",
2933 WSAENETRESET , "Network dropped connection on reset",
2934 WSAECONNABORTED , "Software caused connection abort",
2935 WSAECONNRESET , "Connection reset by peer",
2936 WSAENOBUFS , "No buffer space available",
2937 WSAEISCONN , "Socket is already connected",
2938 WSAENOTCONN , "Socket is not connected",
2939 WSAESHUTDOWN , "Cannot send after socket shutdown",
2940 WSAETOOMANYREFS , "Too many references", /* not sure */
2941 WSAETIMEDOUT , "Connection timed out",
2942 WSAECONNREFUSED , "Connection refused",
2943 WSAELOOP , "Network loop", /* not sure */
2944 WSAENAMETOOLONG , "Name is too long",
2945 WSAEHOSTDOWN , "Host is down",
2946 WSAEHOSTUNREACH , "No route to host",
2947 WSAENOTEMPTY , "Buffer not empty", /* not sure */
2948 WSAEPROCLIM , "Too many processes",
2949 WSAEUSERS , "Too many users", /* not sure */
2950 WSAEDQUOT , "Double quote in host name", /* really not sure */
2951 WSAESTALE , "Data is stale", /* not sure */
2952 WSAEREMOTE , "Remote error", /* not sure */
2954 WSASYSNOTREADY , "Network subsystem is unavailable",
2955 WSAVERNOTSUPPORTED , "WINSOCK.DLL version out of range",
2956 WSANOTINITIALISED , "Winsock not initialized successfully",
2957 WSAEDISCON , "Graceful shutdown in progress",
2958 #ifdef WSAENOMORE
2959 WSAENOMORE , "No more operations allowed", /* not sure */
2960 WSAECANCELLED , "Operation cancelled", /* not sure */
2961 WSAEINVALIDPROCTABLE , "Invalid procedure table from service provider",
2962 WSAEINVALIDPROVIDER , "Invalid service provider version number",
2963 WSAEPROVIDERFAILEDINIT , "Unable to initialize a service provider",
2964 WSASYSCALLFAILURE , "System call failured",
2965 WSASERVICE_NOT_FOUND , "Service not found", /* not sure */
2966 WSATYPE_NOT_FOUND , "Class type not found",
2967 WSA_E_NO_MORE , "No more resources available", /* really not sure */
2968 WSA_E_CANCELLED , "Operation already cancelled", /* really not sure */
2969 WSAEREFUSED , "Operation refused", /* not sure */
2970 #endif
2972 WSAHOST_NOT_FOUND , "Host not found",
2973 WSATRY_AGAIN , "Authoritative host not found during name lookup",
2974 WSANO_RECOVERY , "Non-recoverable error during name lookup",
2975 WSANO_DATA , "Valid name, no data record of requested type",
2977 -1, NULL
2980 char *
2981 sys_strerror(int error_no)
2983 int i;
2984 static char unknown_msg[40];
2986 if (error_no >= 0 && error_no < sys_nerr)
2987 return sys_errlist[error_no];
2989 for (i = 0; _wsa_errlist[i].errnum >= 0; i++)
2990 if (_wsa_errlist[i].errnum == error_no)
2991 return _wsa_errlist[i].msg;
2993 sprintf(unknown_msg, "Unidentified error: %d", error_no);
2994 return unknown_msg;
2997 /* [andrewi 3-May-96] I've had conflicting results using both methods,
2998 but I believe the method of keeping the socket handle separate (and
2999 insuring it is not inheritable) is the correct one. */
3001 //#define SOCK_REPLACE_HANDLE
3003 #ifdef SOCK_REPLACE_HANDLE
3004 #define SOCK_HANDLE(fd) ((SOCKET) _get_osfhandle (fd))
3005 #else
3006 #define SOCK_HANDLE(fd) ((SOCKET) fd_info[fd].hnd)
3007 #endif
3009 int socket_to_fd (SOCKET s);
3012 sys_socket(int af, int type, int protocol)
3014 SOCKET s;
3016 if (winsock_lib == NULL)
3018 h_errno = ENETDOWN;
3019 return INVALID_SOCKET;
3022 check_errno ();
3024 /* call the real socket function */
3025 s = pfn_socket (af, type, protocol);
3027 if (s != INVALID_SOCKET)
3028 return socket_to_fd (s);
3030 set_errno ();
3031 return -1;
3034 /* Convert a SOCKET to a file descriptor. */
3036 socket_to_fd (SOCKET s)
3038 int fd;
3039 child_process * cp;
3041 /* Although under NT 3.5 _open_osfhandle will accept a socket
3042 handle, if opened with SO_OPENTYPE == SO_SYNCHRONOUS_NONALERT,
3043 that does not work under NT 3.1. However, we can get the same
3044 effect by using a backdoor function to replace an existing
3045 descriptor handle with the one we want. */
3047 /* allocate a file descriptor (with appropriate flags) */
3048 fd = _open ("NUL:", _O_RDWR);
3049 if (fd >= 0)
3051 #ifdef SOCK_REPLACE_HANDLE
3052 /* now replace handle to NUL with our socket handle */
3053 CloseHandle ((HANDLE) _get_osfhandle (fd));
3054 _free_osfhnd (fd);
3055 _set_osfhnd (fd, s);
3056 /* setmode (fd, _O_BINARY); */
3057 #else
3058 /* Make a non-inheritable copy of the socket handle. Note
3059 that it is possible that sockets aren't actually kernel
3060 handles, which appears to be the case on Windows 9x when
3061 the MS Proxy winsock client is installed. */
3063 /* Apparently there is a bug in NT 3.51 with some service
3064 packs, which prevents using DuplicateHandle to make a
3065 socket handle non-inheritable (causes WSACleanup to
3066 hang). The work-around is to use SetHandleInformation
3067 instead if it is available and implemented. */
3068 if (pfn_SetHandleInformation)
3070 pfn_SetHandleInformation ((HANDLE) s, HANDLE_FLAG_INHERIT, 0);
3072 else
3074 HANDLE parent = GetCurrentProcess ();
3075 HANDLE new_s = INVALID_HANDLE_VALUE;
3077 if (DuplicateHandle (parent,
3078 (HANDLE) s,
3079 parent,
3080 &new_s,
3082 FALSE,
3083 DUPLICATE_SAME_ACCESS))
3085 /* It is possible that DuplicateHandle succeeds even
3086 though the socket wasn't really a kernel handle,
3087 because a real handle has the same value. So
3088 test whether the new handle really is a socket. */
3089 long nonblocking = 0;
3090 if (pfn_ioctlsocket ((SOCKET) new_s, FIONBIO, &nonblocking) == 0)
3092 pfn_closesocket (s);
3093 s = (SOCKET) new_s;
3095 else
3097 CloseHandle (new_s);
3102 fd_info[fd].hnd = (HANDLE) s;
3103 #endif
3105 /* set our own internal flags */
3106 fd_info[fd].flags = FILE_SOCKET | FILE_BINARY | FILE_READ | FILE_WRITE;
3108 cp = new_child ();
3109 if (cp)
3111 cp->fd = fd;
3112 cp->status = STATUS_READ_ACKNOWLEDGED;
3114 /* attach child_process to fd_info */
3115 if (fd_info[ fd ].cp != NULL)
3117 DebPrint (("sys_socket: fd_info[%d] apparently in use!\n", fd));
3118 abort ();
3121 fd_info[ fd ].cp = cp;
3123 /* success! */
3124 winsock_inuse++; /* count open sockets */
3125 return fd;
3128 /* clean up */
3129 _close (fd);
3131 pfn_closesocket (s);
3132 h_errno = EMFILE;
3133 return -1;
3138 sys_bind (int s, const struct sockaddr * addr, int namelen)
3140 if (winsock_lib == NULL)
3142 h_errno = ENOTSOCK;
3143 return SOCKET_ERROR;
3146 check_errno ();
3147 if (fd_info[s].flags & FILE_SOCKET)
3149 int rc = pfn_bind (SOCK_HANDLE (s), addr, namelen);
3150 if (rc == SOCKET_ERROR)
3151 set_errno ();
3152 return rc;
3154 h_errno = ENOTSOCK;
3155 return SOCKET_ERROR;
3160 sys_connect (int s, const struct sockaddr * name, int namelen)
3162 if (winsock_lib == NULL)
3164 h_errno = ENOTSOCK;
3165 return SOCKET_ERROR;
3168 check_errno ();
3169 if (fd_info[s].flags & FILE_SOCKET)
3171 int rc = pfn_connect (SOCK_HANDLE (s), name, namelen);
3172 if (rc == SOCKET_ERROR)
3173 set_errno ();
3174 return rc;
3176 h_errno = ENOTSOCK;
3177 return SOCKET_ERROR;
3180 u_short
3181 sys_htons (u_short hostshort)
3183 return (winsock_lib != NULL) ?
3184 pfn_htons (hostshort) : hostshort;
3187 u_short
3188 sys_ntohs (u_short netshort)
3190 return (winsock_lib != NULL) ?
3191 pfn_ntohs (netshort) : netshort;
3194 unsigned long
3195 sys_inet_addr (const char * cp)
3197 return (winsock_lib != NULL) ?
3198 pfn_inet_addr (cp) : INADDR_NONE;
3202 sys_gethostname (char * name, int namelen)
3204 if (winsock_lib != NULL)
3205 return pfn_gethostname (name, namelen);
3207 if (namelen > MAX_COMPUTERNAME_LENGTH)
3208 return !GetComputerName (name, (DWORD *)&namelen);
3210 h_errno = EFAULT;
3211 return SOCKET_ERROR;
3214 struct hostent *
3215 sys_gethostbyname(const char * name)
3217 struct hostent * host;
3219 if (winsock_lib == NULL)
3221 h_errno = ENETDOWN;
3222 return NULL;
3225 check_errno ();
3226 host = pfn_gethostbyname (name);
3227 if (!host)
3228 set_errno ();
3229 return host;
3232 struct servent *
3233 sys_getservbyname(const char * name, const char * proto)
3235 struct servent * serv;
3237 if (winsock_lib == NULL)
3239 h_errno = ENETDOWN;
3240 return NULL;
3243 check_errno ();
3244 serv = pfn_getservbyname (name, proto);
3245 if (!serv)
3246 set_errno ();
3247 return serv;
3251 sys_getpeername (int s, struct sockaddr *addr, int * namelen)
3253 if (winsock_lib == NULL)
3255 h_errno = ENETDOWN;
3256 return SOCKET_ERROR;
3259 check_errno ();
3260 if (fd_info[s].flags & FILE_SOCKET)
3262 int rc = pfn_getpeername (SOCK_HANDLE (s), addr, namelen);
3263 if (rc == SOCKET_ERROR)
3264 set_errno ();
3265 return rc;
3267 h_errno = ENOTSOCK;
3268 return SOCKET_ERROR;
3273 sys_shutdown (int s, int how)
3275 if (winsock_lib == NULL)
3277 h_errno = ENETDOWN;
3278 return SOCKET_ERROR;
3281 check_errno ();
3282 if (fd_info[s].flags & FILE_SOCKET)
3284 int rc = pfn_shutdown (SOCK_HANDLE (s), how);
3285 if (rc == SOCKET_ERROR)
3286 set_errno ();
3287 return rc;
3289 h_errno = ENOTSOCK;
3290 return SOCKET_ERROR;
3294 sys_setsockopt (int s, int level, int optname, const void * optval, int optlen)
3296 if (winsock_lib == NULL)
3298 h_errno = ENETDOWN;
3299 return SOCKET_ERROR;
3302 check_errno ();
3303 if (fd_info[s].flags & FILE_SOCKET)
3305 int rc = pfn_setsockopt (SOCK_HANDLE (s), level, optname,
3306 (const char *)optval, optlen);
3307 if (rc == SOCKET_ERROR)
3308 set_errno ();
3309 return rc;
3311 h_errno = ENOTSOCK;
3312 return SOCKET_ERROR;
3316 sys_listen (int s, int backlog)
3318 if (winsock_lib == NULL)
3320 h_errno = ENETDOWN;
3321 return SOCKET_ERROR;
3324 check_errno ();
3325 if (fd_info[s].flags & FILE_SOCKET)
3327 int rc = pfn_listen (SOCK_HANDLE (s), backlog);
3328 if (rc == SOCKET_ERROR)
3329 set_errno ();
3330 else
3331 fd_info[s].flags |= FILE_LISTEN;
3332 return rc;
3334 h_errno = ENOTSOCK;
3335 return SOCKET_ERROR;
3339 sys_getsockname (int s, struct sockaddr * name, int * namelen)
3341 if (winsock_lib == NULL)
3343 h_errno = ENETDOWN;
3344 return SOCKET_ERROR;
3347 check_errno ();
3348 if (fd_info[s].flags & FILE_SOCKET)
3350 int rc = pfn_getsockname (SOCK_HANDLE (s), name, namelen);
3351 if (rc == SOCKET_ERROR)
3352 set_errno ();
3353 return rc;
3355 h_errno = ENOTSOCK;
3356 return SOCKET_ERROR;
3360 sys_accept (int s, struct sockaddr * addr, int * addrlen)
3362 if (winsock_lib == NULL)
3364 h_errno = ENETDOWN;
3365 return -1;
3368 check_errno ();
3369 if (fd_info[s].flags & FILE_LISTEN)
3371 SOCKET t = pfn_accept (SOCK_HANDLE (s), addr, addrlen);
3372 int fd = -1;
3373 if (t == INVALID_SOCKET)
3374 set_errno ();
3375 else
3376 fd = socket_to_fd (t);
3378 fd_info[s].cp->status = STATUS_READ_ACKNOWLEDGED;
3379 ResetEvent (fd_info[s].cp->char_avail);
3380 return fd;
3382 h_errno = ENOTSOCK;
3383 return -1;
3387 sys_recvfrom (int s, char * buf, int len, int flags,
3388 struct sockaddr * from, int * fromlen)
3390 if (winsock_lib == NULL)
3392 h_errno = ENETDOWN;
3393 return SOCKET_ERROR;
3396 check_errno ();
3397 if (fd_info[s].flags & FILE_SOCKET)
3399 int rc = pfn_recvfrom (SOCK_HANDLE (s), buf, len, flags, from, fromlen);
3400 if (rc == SOCKET_ERROR)
3401 set_errno ();
3402 return rc;
3404 h_errno = ENOTSOCK;
3405 return SOCKET_ERROR;
3409 sys_sendto (int s, const char * buf, int len, int flags,
3410 const struct sockaddr * to, int tolen)
3412 if (winsock_lib == NULL)
3414 h_errno = ENETDOWN;
3415 return SOCKET_ERROR;
3418 check_errno ();
3419 if (fd_info[s].flags & FILE_SOCKET)
3421 int rc = pfn_sendto (SOCK_HANDLE (s), buf, len, flags, to, tolen);
3422 if (rc == SOCKET_ERROR)
3423 set_errno ();
3424 return rc;
3426 h_errno = ENOTSOCK;
3427 return SOCKET_ERROR;
3430 /* Windows does not have an fcntl function. Provide an implementation
3431 solely for making sockets non-blocking. */
3433 fcntl (int s, int cmd, int options)
3435 if (winsock_lib == NULL)
3437 h_errno = ENETDOWN;
3438 return -1;
3441 check_errno ();
3442 if (fd_info[s].flags & FILE_SOCKET)
3444 if (cmd == F_SETFL && options == O_NDELAY)
3446 unsigned long nblock = 1;
3447 int rc = pfn_ioctlsocket (SOCK_HANDLE (s), FIONBIO, &nblock);
3448 if (rc == SOCKET_ERROR)
3449 set_errno();
3450 /* Keep track of the fact that we set this to non-blocking. */
3451 fd_info[s].flags |= FILE_NDELAY;
3452 return rc;
3454 else
3456 h_errno = EINVAL;
3457 return SOCKET_ERROR;
3460 h_errno = ENOTSOCK;
3461 return SOCKET_ERROR;
3464 #endif /* HAVE_SOCKETS */
3467 /* Shadow main io functions: we need to handle pipes and sockets more
3468 intelligently, and implement non-blocking mode as well. */
3471 sys_close (int fd)
3473 int rc;
3475 if (fd < 0)
3477 errno = EBADF;
3478 return -1;
3481 if (fd < MAXDESC && fd_info[fd].cp)
3483 child_process * cp = fd_info[fd].cp;
3485 fd_info[fd].cp = NULL;
3487 if (CHILD_ACTIVE (cp))
3489 /* if last descriptor to active child_process then cleanup */
3490 int i;
3491 for (i = 0; i < MAXDESC; i++)
3493 if (i == fd)
3494 continue;
3495 if (fd_info[i].cp == cp)
3496 break;
3498 if (i == MAXDESC)
3500 #ifdef HAVE_SOCKETS
3501 if (fd_info[fd].flags & FILE_SOCKET)
3503 #ifndef SOCK_REPLACE_HANDLE
3504 if (winsock_lib == NULL) abort ();
3506 pfn_shutdown (SOCK_HANDLE (fd), 2);
3507 rc = pfn_closesocket (SOCK_HANDLE (fd));
3508 #endif
3509 winsock_inuse--; /* count open sockets */
3511 #endif
3512 delete_child (cp);
3517 /* Note that sockets do not need special treatment here (at least on
3518 NT and Windows 95 using the standard tcp/ip stacks) - it appears that
3519 closesocket is equivalent to CloseHandle, which is to be expected
3520 because socket handles are fully fledged kernel handles. */
3521 rc = _close (fd);
3523 if (rc == 0 && fd < MAXDESC)
3524 fd_info[fd].flags = 0;
3526 return rc;
3530 sys_dup (int fd)
3532 int new_fd;
3534 new_fd = _dup (fd);
3535 if (new_fd >= 0 && new_fd < MAXDESC)
3537 /* duplicate our internal info as well */
3538 fd_info[new_fd] = fd_info[fd];
3540 return new_fd;
3545 sys_dup2 (int src, int dst)
3547 int rc;
3549 if (dst < 0 || dst >= MAXDESC)
3551 errno = EBADF;
3552 return -1;
3555 /* make sure we close the destination first if it's a pipe or socket */
3556 if (src != dst && fd_info[dst].flags != 0)
3557 sys_close (dst);
3559 rc = _dup2 (src, dst);
3560 if (rc == 0)
3562 /* duplicate our internal info as well */
3563 fd_info[dst] = fd_info[src];
3565 return rc;
3568 /* Unix pipe() has only one arg */
3570 sys_pipe (int * phandles)
3572 int rc;
3573 unsigned flags;
3575 /* make pipe handles non-inheritable; when we spawn a child, we
3576 replace the relevant handle with an inheritable one. Also put
3577 pipes into binary mode; we will do text mode translation ourselves
3578 if required. */
3579 rc = _pipe (phandles, 0, _O_NOINHERIT | _O_BINARY);
3581 if (rc == 0)
3583 /* Protect against overflow, since Windows can open more handles than
3584 our fd_info array has room for. */
3585 if (phandles[0] >= MAXDESC || phandles[1] >= MAXDESC)
3587 _close (phandles[0]);
3588 _close (phandles[1]);
3589 rc = -1;
3591 else
3593 flags = FILE_PIPE | FILE_READ | FILE_BINARY;
3594 fd_info[phandles[0]].flags = flags;
3596 flags = FILE_PIPE | FILE_WRITE | FILE_BINARY;
3597 fd_info[phandles[1]].flags = flags;
3601 return rc;
3604 /* From ntproc.c */
3605 extern int w32_pipe_read_delay;
3607 /* Function to do blocking read of one byte, needed to implement
3608 select. It is only allowed on sockets and pipes. */
3610 _sys_read_ahead (int fd)
3612 child_process * cp;
3613 int rc;
3615 if (fd < 0 || fd >= MAXDESC)
3616 return STATUS_READ_ERROR;
3618 cp = fd_info[fd].cp;
3620 if (cp == NULL || cp->fd != fd || cp->status != STATUS_READ_READY)
3621 return STATUS_READ_ERROR;
3623 if ((fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET)) == 0
3624 || (fd_info[fd].flags & FILE_READ) == 0)
3626 DebPrint (("_sys_read_ahead: internal error: fd %d is not a pipe or socket!\n", fd));
3627 abort ();
3630 cp->status = STATUS_READ_IN_PROGRESS;
3632 if (fd_info[fd].flags & FILE_PIPE)
3634 rc = _read (fd, &cp->chr, sizeof (char));
3636 /* Give subprocess time to buffer some more output for us before
3637 reporting that input is available; we need this because Windows 95
3638 connects DOS programs to pipes by making the pipe appear to be
3639 the normal console stdout - as a result most DOS programs will
3640 write to stdout without buffering, ie. one character at a
3641 time. Even some W32 programs do this - "dir" in a command
3642 shell on NT is very slow if we don't do this. */
3643 if (rc > 0)
3645 int wait = w32_pipe_read_delay;
3647 if (wait > 0)
3648 Sleep (wait);
3649 else if (wait < 0)
3650 while (++wait <= 0)
3651 /* Yield remainder of our time slice, effectively giving a
3652 temporary priority boost to the child process. */
3653 Sleep (0);
3656 #ifdef HAVE_SOCKETS
3657 else if (fd_info[fd].flags & FILE_SOCKET)
3659 unsigned long nblock = 0;
3660 /* We always want this to block, so temporarily disable NDELAY. */
3661 if (fd_info[fd].flags & FILE_NDELAY)
3662 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONBIO, &nblock);
3664 rc = pfn_recv (SOCK_HANDLE (fd), &cp->chr, sizeof (char), 0);
3666 if (fd_info[fd].flags & FILE_NDELAY)
3668 nblock = 1;
3669 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONBIO, &nblock);
3672 #endif
3674 if (rc == sizeof (char))
3675 cp->status = STATUS_READ_SUCCEEDED;
3676 else
3677 cp->status = STATUS_READ_FAILED;
3679 return cp->status;
3683 _sys_wait_accept (int fd)
3685 HANDLE hEv;
3686 child_process * cp;
3687 int rc;
3689 if (fd < 0 || fd >= MAXDESC)
3690 return STATUS_READ_ERROR;
3692 cp = fd_info[fd].cp;
3694 if (cp == NULL || cp->fd != fd || cp->status != STATUS_READ_READY)
3695 return STATUS_READ_ERROR;
3697 cp->status = STATUS_READ_FAILED;
3699 hEv = pfn_WSACreateEvent ();
3700 rc = pfn_WSAEventSelect (SOCK_HANDLE (fd), hEv, FD_ACCEPT);
3701 if (rc != SOCKET_ERROR)
3703 rc = WaitForSingleObject (hEv, INFINITE);
3704 pfn_WSAEventSelect (SOCK_HANDLE (fd), NULL, 0);
3705 if (rc == WAIT_OBJECT_0)
3706 cp->status = STATUS_READ_SUCCEEDED;
3708 pfn_WSACloseEvent (hEv);
3710 return cp->status;
3714 sys_read (int fd, char * buffer, unsigned int count)
3716 int nchars;
3717 int to_read;
3718 DWORD waiting;
3719 char * orig_buffer = buffer;
3721 if (fd < 0)
3723 errno = EBADF;
3724 return -1;
3727 if (fd < MAXDESC && fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET))
3729 child_process *cp = fd_info[fd].cp;
3731 if ((fd_info[fd].flags & FILE_READ) == 0)
3733 errno = EBADF;
3734 return -1;
3737 nchars = 0;
3739 /* re-read CR carried over from last read */
3740 if (fd_info[fd].flags & FILE_LAST_CR)
3742 if (fd_info[fd].flags & FILE_BINARY) abort ();
3743 *buffer++ = 0x0d;
3744 count--;
3745 nchars++;
3746 fd_info[fd].flags &= ~FILE_LAST_CR;
3749 /* presence of a child_process structure means we are operating in
3750 non-blocking mode - otherwise we just call _read directly.
3751 Note that the child_process structure might be missing because
3752 reap_subprocess has been called; in this case the pipe is
3753 already broken, so calling _read on it is okay. */
3754 if (cp)
3756 int current_status = cp->status;
3758 switch (current_status)
3760 case STATUS_READ_FAILED:
3761 case STATUS_READ_ERROR:
3762 /* report normal EOF if nothing in buffer */
3763 if (nchars <= 0)
3764 fd_info[fd].flags |= FILE_AT_EOF;
3765 return nchars;
3767 case STATUS_READ_READY:
3768 case STATUS_READ_IN_PROGRESS:
3769 DebPrint (("sys_read called when read is in progress\n"));
3770 errno = EWOULDBLOCK;
3771 return -1;
3773 case STATUS_READ_SUCCEEDED:
3774 /* consume read-ahead char */
3775 *buffer++ = cp->chr;
3776 count--;
3777 nchars++;
3778 cp->status = STATUS_READ_ACKNOWLEDGED;
3779 ResetEvent (cp->char_avail);
3781 case STATUS_READ_ACKNOWLEDGED:
3782 break;
3784 default:
3785 DebPrint (("sys_read: bad status %d\n", current_status));
3786 errno = EBADF;
3787 return -1;
3790 if (fd_info[fd].flags & FILE_PIPE)
3792 PeekNamedPipe ((HANDLE) _get_osfhandle (fd), NULL, 0, NULL, &waiting, NULL);
3793 to_read = min (waiting, (DWORD) count);
3795 if (to_read > 0)
3796 nchars += _read (fd, buffer, to_read);
3798 #ifdef HAVE_SOCKETS
3799 else /* FILE_SOCKET */
3801 if (winsock_lib == NULL) abort ();
3803 /* do the equivalent of a non-blocking read */
3804 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONREAD, &waiting);
3805 if (waiting == 0 && nchars == 0)
3807 h_errno = errno = EWOULDBLOCK;
3808 return -1;
3811 if (waiting)
3813 /* always use binary mode for sockets */
3814 int res = pfn_recv (SOCK_HANDLE (fd), buffer, count, 0);
3815 if (res == SOCKET_ERROR)
3817 DebPrint(("sys_read.recv failed with error %d on socket %ld\n",
3818 pfn_WSAGetLastError (), SOCK_HANDLE (fd)));
3819 set_errno ();
3820 return -1;
3822 nchars += res;
3825 #endif
3827 else
3829 int nread = _read (fd, buffer, count);
3830 if (nread >= 0)
3831 nchars += nread;
3832 else if (nchars == 0)
3833 nchars = nread;
3836 if (nchars <= 0)
3837 fd_info[fd].flags |= FILE_AT_EOF;
3838 /* Perform text mode translation if required. */
3839 else if ((fd_info[fd].flags & FILE_BINARY) == 0)
3841 nchars = crlf_to_lf (nchars, orig_buffer);
3842 /* If buffer contains only CR, return that. To be absolutely
3843 sure we should attempt to read the next char, but in
3844 practice a CR to be followed by LF would not appear by
3845 itself in the buffer. */
3846 if (nchars > 1 && orig_buffer[nchars - 1] == 0x0d)
3848 fd_info[fd].flags |= FILE_LAST_CR;
3849 nchars--;
3853 else
3854 nchars = _read (fd, buffer, count);
3856 return nchars;
3859 /* For now, don't bother with a non-blocking mode */
3861 sys_write (int fd, const void * buffer, unsigned int count)
3863 int nchars;
3865 if (fd < 0)
3867 errno = EBADF;
3868 return -1;
3871 if (fd < MAXDESC && fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET))
3873 if ((fd_info[fd].flags & FILE_WRITE) == 0)
3875 errno = EBADF;
3876 return -1;
3879 /* Perform text mode translation if required. */
3880 if ((fd_info[fd].flags & FILE_BINARY) == 0)
3882 char * tmpbuf = alloca (count * 2);
3883 unsigned char * src = (void *)buffer;
3884 unsigned char * dst = tmpbuf;
3885 int nbytes = count;
3887 while (1)
3889 unsigned char *next;
3890 /* copy next line or remaining bytes */
3891 next = _memccpy (dst, src, '\n', nbytes);
3892 if (next)
3894 /* copied one line ending with '\n' */
3895 int copied = next - dst;
3896 nbytes -= copied;
3897 src += copied;
3898 /* insert '\r' before '\n' */
3899 next[-1] = '\r';
3900 next[0] = '\n';
3901 dst = next + 1;
3902 count++;
3904 else
3905 /* copied remaining partial line -> now finished */
3906 break;
3908 buffer = tmpbuf;
3912 #ifdef HAVE_SOCKETS
3913 if (fd < MAXDESC && fd_info[fd].flags & FILE_SOCKET)
3915 unsigned long nblock = 0;
3916 if (winsock_lib == NULL) abort ();
3918 /* TODO: implement select() properly so non-blocking I/O works. */
3919 /* For now, make sure the write blocks. */
3920 if (fd_info[fd].flags & FILE_NDELAY)
3921 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONBIO, &nblock);
3923 nchars = pfn_send (SOCK_HANDLE (fd), buffer, count, 0);
3925 /* Set the socket back to non-blocking if it was before,
3926 for other operations that support it. */
3927 if (fd_info[fd].flags & FILE_NDELAY)
3929 nblock = 1;
3930 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONBIO, &nblock);
3933 if (nchars == SOCKET_ERROR)
3935 DebPrint(("sys_write.send failed with error %d on socket %ld\n",
3936 pfn_WSAGetLastError (), SOCK_HANDLE (fd)));
3937 set_errno ();
3940 else
3941 #endif
3942 nchars = _write (fd, buffer, count);
3944 return nchars;
3947 static void
3948 check_windows_init_file ()
3950 extern int noninteractive, inhibit_window_system;
3952 /* A common indication that Emacs is not installed properly is when
3953 it cannot find the Windows installation file. If this file does
3954 not exist in the expected place, tell the user. */
3956 if (!noninteractive && !inhibit_window_system)
3958 extern Lisp_Object Vwindow_system, Vload_path, Qfile_exists_p;
3959 Lisp_Object objs[2];
3960 Lisp_Object full_load_path;
3961 Lisp_Object init_file;
3962 int fd;
3964 objs[0] = Vload_path;
3965 objs[1] = decode_env_path (0, (getenv ("EMACSLOADPATH")));
3966 full_load_path = Fappend (2, objs);
3967 init_file = build_string ("term/w32-win");
3968 fd = openp (full_load_path, init_file, Fget_load_suffixes (), NULL, Qnil);
3969 if (fd < 0)
3971 Lisp_Object load_path_print = Fprin1_to_string (full_load_path, Qnil);
3972 char *init_file_name = SDATA (init_file);
3973 char *load_path = SDATA (load_path_print);
3974 char *buffer = alloca (1024
3975 + strlen (init_file_name)
3976 + strlen (load_path));
3978 sprintf (buffer,
3979 "The Emacs Windows initialization file \"%s.el\" "
3980 "could not be found in your Emacs installation. "
3981 "Emacs checked the following directories for this file:\n"
3982 "\n%s\n\n"
3983 "When Emacs cannot find this file, it usually means that it "
3984 "was not installed properly, or its distribution file was "
3985 "not unpacked properly.\nSee the README.W32 file in the "
3986 "top-level Emacs directory for more information.",
3987 init_file_name, load_path);
3988 MessageBox (NULL,
3989 buffer,
3990 "Emacs Abort Dialog",
3991 MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL);
3992 /* Use the low-level Emacs abort. */
3993 #undef abort
3994 abort ();
3996 else
3998 _close (fd);
4003 void
4004 term_ntproc ()
4006 #ifdef HAVE_SOCKETS
4007 /* shutdown the socket interface if necessary */
4008 term_winsock ();
4009 #endif
4011 term_w32select ();
4014 void
4015 init_ntproc ()
4017 #ifdef HAVE_SOCKETS
4018 /* Initialise the socket interface now if available and requested by
4019 the user by defining PRELOAD_WINSOCK; otherwise loading will be
4020 delayed until open-network-stream is called (w32-has-winsock can
4021 also be used to dynamically load or reload winsock).
4023 Conveniently, init_environment is called before us, so
4024 PRELOAD_WINSOCK can be set in the registry. */
4026 /* Always initialize this correctly. */
4027 winsock_lib = NULL;
4029 if (getenv ("PRELOAD_WINSOCK") != NULL)
4030 init_winsock (TRUE);
4031 #endif
4033 /* Initial preparation for subprocess support: replace our standard
4034 handles with non-inheritable versions. */
4036 HANDLE parent;
4037 HANDLE stdin_save = INVALID_HANDLE_VALUE;
4038 HANDLE stdout_save = INVALID_HANDLE_VALUE;
4039 HANDLE stderr_save = INVALID_HANDLE_VALUE;
4041 parent = GetCurrentProcess ();
4043 /* ignore errors when duplicating and closing; typically the
4044 handles will be invalid when running as a gui program. */
4045 DuplicateHandle (parent,
4046 GetStdHandle (STD_INPUT_HANDLE),
4047 parent,
4048 &stdin_save,
4050 FALSE,
4051 DUPLICATE_SAME_ACCESS);
4053 DuplicateHandle (parent,
4054 GetStdHandle (STD_OUTPUT_HANDLE),
4055 parent,
4056 &stdout_save,
4058 FALSE,
4059 DUPLICATE_SAME_ACCESS);
4061 DuplicateHandle (parent,
4062 GetStdHandle (STD_ERROR_HANDLE),
4063 parent,
4064 &stderr_save,
4066 FALSE,
4067 DUPLICATE_SAME_ACCESS);
4069 fclose (stdin);
4070 fclose (stdout);
4071 fclose (stderr);
4073 if (stdin_save != INVALID_HANDLE_VALUE)
4074 _open_osfhandle ((long) stdin_save, O_TEXT);
4075 else
4076 _open ("nul", O_TEXT | O_NOINHERIT | O_RDONLY);
4077 _fdopen (0, "r");
4079 if (stdout_save != INVALID_HANDLE_VALUE)
4080 _open_osfhandle ((long) stdout_save, O_TEXT);
4081 else
4082 _open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY);
4083 _fdopen (1, "w");
4085 if (stderr_save != INVALID_HANDLE_VALUE)
4086 _open_osfhandle ((long) stderr_save, O_TEXT);
4087 else
4088 _open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY);
4089 _fdopen (2, "w");
4092 /* unfortunately, atexit depends on implementation of malloc */
4093 /* atexit (term_ntproc); */
4094 signal (SIGABRT, term_ntproc);
4096 /* determine which drives are fixed, for GetCachedVolumeInformation */
4098 /* GetDriveType must have trailing backslash. */
4099 char drive[] = "A:\\";
4101 /* Loop over all possible drive letters */
4102 while (*drive <= 'Z')
4104 /* Record if this drive letter refers to a fixed drive. */
4105 fixed_drives[DRIVE_INDEX (*drive)] =
4106 (GetDriveType (drive) == DRIVE_FIXED);
4108 (*drive)++;
4111 /* Reset the volume info cache. */
4112 volume_cache = NULL;
4115 /* Check to see if Emacs has been installed correctly. */
4116 check_windows_init_file ();
4120 shutdown_handler ensures that buffers' autosave files are
4121 up to date when the user logs off, or the system shuts down.
4123 BOOL WINAPI shutdown_handler(DWORD type)
4125 /* Ctrl-C and Ctrl-Break are already suppressed, so don't handle them. */
4126 if (type == CTRL_CLOSE_EVENT /* User closes console window. */
4127 || type == CTRL_LOGOFF_EVENT /* User logs off. */
4128 || type == CTRL_SHUTDOWN_EVENT) /* User shutsdown. */
4130 /* Shut down cleanly, making sure autosave files are up to date. */
4131 shut_down_emacs (0, 0, Qnil);
4134 /* Allow other handlers to handle this signal. */
4135 return FALSE;
4139 globals_of_w32 is used to initialize those global variables that
4140 must always be initialized on startup even when the global variable
4141 initialized is non zero (see the function main in emacs.c).
4143 void
4144 globals_of_w32 ()
4146 g_b_init_is_windows_9x = 0;
4147 g_b_init_open_process_token = 0;
4148 g_b_init_get_token_information = 0;
4149 g_b_init_lookup_account_sid = 0;
4150 g_b_init_get_sid_identifier_authority = 0;
4151 /* The following sets a handler for shutdown notifications for
4152 console apps. This actually applies to Emacs in both console and
4153 GUI modes, since we had to fool windows into thinking emacs is a
4154 console application to get console mode to work. */
4155 SetConsoleCtrlHandler(shutdown_handler, TRUE);
4158 /* end of nt.c */
4160 /* arch-tag: 90442dd3-37be-482b-b272-ac752e3049f1
4161 (do not change this comment) */