1 /* Utility and Unix shadow routines for GNU Emacs on the Microsoft W32 API.
2 Copyright (C) 1994, 1995, 2000, 2001 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.
21 Geoff Voelker (voelker@cs.washington.edu) 7-29-94
25 #include <stddef.h> /* for offsetof */
35 #include <sys/utime.h>
37 /* must include CRT headers *before* config.h */
71 #define _ANONYMOUS_UNION
72 #define _ANONYMOUS_STRUCT
76 #ifdef HAVE_SOCKETS /* TCP connection support, if kernel can do it */
77 #include <sys/socket.h>
102 extern Lisp_Object Vw32_downcase_file_names
;
103 extern Lisp_Object Vw32_generate_fake_inodes
;
104 extern Lisp_Object Vw32_get_true_file_attributes
;
105 extern Lisp_Object Vw32_num_mouse_buttons
;
109 BEGIN: Wrapper functions around OpenProcessToken
110 and other functions in advapi32.dll that are only
111 supported in Windows NT / 2k / XP
113 /* ** Function pointer typedefs ** */
114 typedef BOOL (WINAPI
* OpenProcessToken_Proc
) (
115 HANDLE ProcessHandle
,
117 PHANDLE TokenHandle
);
118 typedef BOOL (WINAPI
* GetTokenInformation_Proc
) (
120 TOKEN_INFORMATION_CLASS TokenInformationClass
,
121 LPVOID TokenInformation
,
122 DWORD TokenInformationLength
,
123 PDWORD ReturnLength
);
125 const char * const LookupAccountSid_Name
= "LookupAccountSidW";
127 const char * const LookupAccountSid_Name
= "LookupAccountSidA";
129 typedef BOOL (WINAPI
* LookupAccountSid_Proc
) (
130 LPCTSTR lpSystemName
,
135 LPDWORD cbDomainName
,
136 PSID_NAME_USE peUse
);
137 typedef PSID_IDENTIFIER_AUTHORITY (WINAPI
* GetSidIdentifierAuthority_Proc
) (
140 /* ** A utility function ** */
141 static BOOL
is_windows_9x ()
144 OSVERSIONINFO os_ver
;
145 ZeroMemory(&os_ver
, sizeof(OSVERSIONINFO
));
146 os_ver
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
147 if (GetVersionEx (&os_ver
))
149 b_ret
= (os_ver
.dwPlatformId
== VER_PLATFORM_WIN32_WINDOWS
);
154 /* ** The wrapper functions ** */
156 BOOL WINAPI
open_process_token (
157 HANDLE ProcessHandle
,
161 OpenProcessToken_Proc pfn_Open_Process_Token
= NULL
;
162 HMODULE hm_advapi32
= NULL
;
163 if (is_windows_9x () == TRUE
)
167 hm_advapi32
= LoadLibrary ("Advapi32.dll");
168 pfn_Open_Process_Token
=
169 (OpenProcessToken_Proc
) GetProcAddress (hm_advapi32
, "OpenProcessToken");
170 if (pfn_Open_Process_Token
== NULL
)
175 pfn_Open_Process_Token (
182 BOOL WINAPI
get_token_information (
184 TOKEN_INFORMATION_CLASS TokenInformationClass
,
185 LPVOID TokenInformation
,
186 DWORD TokenInformationLength
,
189 GetTokenInformation_Proc pfn_Get_Token_Information
= NULL
;
190 HMODULE hm_advapi32
= NULL
;
191 if (is_windows_9x () == TRUE
)
195 hm_advapi32
= LoadLibrary ("Advapi32.dll");
196 pfn_Get_Token_Information
=
197 (GetTokenInformation_Proc
) GetProcAddress (hm_advapi32
, "GetTokenInformation");
198 if (pfn_Get_Token_Information
== NULL
)
203 pfn_Get_Token_Information (
205 TokenInformationClass
,
207 TokenInformationLength
,
212 BOOL WINAPI
lookup_account_sid (
213 LPCTSTR lpSystemName
,
218 LPDWORD cbDomainName
,
221 LookupAccountSid_Proc pfn_Lookup_Account_Sid
= NULL
;
222 HMODULE hm_advapi32
= NULL
;
223 if (is_windows_9x () == TRUE
)
227 hm_advapi32
= LoadLibrary ("Advapi32.dll");
228 pfn_Lookup_Account_Sid
=
229 (LookupAccountSid_Proc
) GetProcAddress (hm_advapi32
, LookupAccountSid_Name
);
230 if (pfn_Lookup_Account_Sid
== NULL
)
235 pfn_Lookup_Account_Sid (
246 PSID_IDENTIFIER_AUTHORITY WINAPI
get_sid_identifier_authority (
249 GetSidIdentifierAuthority_Proc pfn_Get_Sid_Identifier_Authority
= NULL
;
250 HMODULE hm_advapi32
= NULL
;
251 if (is_windows_9x () == TRUE
)
255 hm_advapi32
= LoadLibrary ("Advapi32.dll");
256 pfn_Get_Sid_Identifier_Authority
=
257 (GetSidIdentifierAuthority_Proc
) GetProcAddress (
258 hm_advapi32
, "GetSidIdentifierAuthority");
259 if (pfn_Get_Sid_Identifier_Authority
== NULL
)
263 return (pfn_Get_Sid_Identifier_Authority (pSid
));
267 END: Wrapper functions around OpenProcessToken
268 and other functions in advapi32.dll that are only
269 supported in Windows NT / 2k / XP
273 /* Equivalent of strerror for W32 error codes. */
275 w32_strerror (int error_no
)
277 static char buf
[500];
280 error_no
= GetLastError ();
283 if (!FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM
, NULL
,
285 0, /* choose most suitable language */
286 buf
, sizeof (buf
), NULL
))
287 sprintf (buf
, "w32 error %u", error_no
);
291 static char startup_dir
[MAXPATHLEN
];
293 /* Get the current working directory. */
298 if (GetCurrentDirectory (MAXPATHLEN
, dir
) > 0)
302 /* Emacs doesn't actually change directory itself, and we want to
303 force our real wd to be where emacs.exe is to avoid unnecessary
304 conflicts when trying to rename or delete directories. */
305 strcpy (dir
, startup_dir
);
311 /* Emulate gethostname. */
313 gethostname (char *buffer
, int size
)
315 /* NT only allows small host names, so the buffer is
316 certainly large enough. */
317 return !GetComputerName (buffer
, &size
);
319 #endif /* HAVE_SOCKETS */
321 /* Emulate getloadavg. */
323 getloadavg (double loadavg
[], int nelem
)
327 /* A faithful emulation is going to have to be saved for a rainy day. */
328 for (i
= 0; i
< nelem
; i
++)
335 /* Emulate getpwuid, getpwnam and others. */
337 #define PASSWD_FIELD_SIZE 256
339 static char the_passwd_name
[PASSWD_FIELD_SIZE
];
340 static char the_passwd_passwd
[PASSWD_FIELD_SIZE
];
341 static char the_passwd_gecos
[PASSWD_FIELD_SIZE
];
342 static char the_passwd_dir
[PASSWD_FIELD_SIZE
];
343 static char the_passwd_shell
[PASSWD_FIELD_SIZE
];
345 static struct passwd the_passwd
=
360 return the_passwd
.pw_uid
;
366 /* I could imagine arguing for checking to see whether the user is
367 in the Administrators group and returning a UID of 0 for that
368 case, but I don't know how wise that would be in the long run. */
375 return the_passwd
.pw_gid
;
387 if (uid
== the_passwd
.pw_uid
)
393 getpwnam (char *name
)
397 pw
= getpwuid (getuid ());
401 if (stricmp (name
, pw
->pw_name
))
410 /* Find the user's real name by opening the process token and
411 looking up the name associated with the user-sid in that token.
413 Use the relative portion of the identifier authority value from
414 the user-sid as the user id value (same for group id using the
415 primary group sid from the process token). */
417 char user_sid
[256], name
[256], domain
[256];
418 DWORD length
= sizeof (name
), dlength
= sizeof (domain
), trash
;
420 SID_NAME_USE user_type
;
423 open_process_token (GetCurrentProcess (), TOKEN_QUERY
, &token
)
424 && get_token_information (
426 (PVOID
) user_sid
, sizeof (user_sid
), &trash
)
427 && lookup_account_sid (
428 NULL
, *((PSID
*) user_sid
), name
, &length
,
429 domain
, &dlength
, &user_type
)
432 strcpy (the_passwd
.pw_name
, name
);
433 /* Determine a reasonable uid value. */
434 if (stricmp ("administrator", name
) == 0)
436 the_passwd
.pw_uid
= 0;
437 the_passwd
.pw_gid
= 0;
441 SID_IDENTIFIER_AUTHORITY
* pSIA
;
443 pSIA
= get_sid_identifier_authority (*((PSID
*) user_sid
));
444 /* I believe the relative portion is the last 4 bytes (of 6)
446 the_passwd
.pw_uid
= ((pSIA
->Value
[2] << 24) +
447 (pSIA
->Value
[3] << 16) +
448 (pSIA
->Value
[4] << 8) +
449 (pSIA
->Value
[5] << 0));
450 /* restrict to conventional uid range for normal users */
451 the_passwd
.pw_uid
= the_passwd
.pw_uid
% 60001;
454 if (get_token_information (token
, TokenPrimaryGroup
,
455 (PVOID
) user_sid
, sizeof (user_sid
), &trash
))
457 SID_IDENTIFIER_AUTHORITY
* pSIA
;
459 pSIA
= get_sid_identifier_authority (*((PSID
*) user_sid
));
460 the_passwd
.pw_gid
= ((pSIA
->Value
[2] << 24) +
461 (pSIA
->Value
[3] << 16) +
462 (pSIA
->Value
[4] << 8) +
463 (pSIA
->Value
[5] << 0));
464 /* I don't know if this is necessary, but for safety... */
465 the_passwd
.pw_gid
= the_passwd
.pw_gid
% 60001;
468 the_passwd
.pw_gid
= the_passwd
.pw_uid
;
471 /* If security calls are not supported (presumably because we
472 are running under Windows 95), fallback to this. */
473 else if (GetUserName (name
, &length
))
475 strcpy (the_passwd
.pw_name
, name
);
476 if (stricmp ("administrator", name
) == 0)
477 the_passwd
.pw_uid
= 0;
479 the_passwd
.pw_uid
= 123;
480 the_passwd
.pw_gid
= the_passwd
.pw_uid
;
484 strcpy (the_passwd
.pw_name
, "unknown");
485 the_passwd
.pw_uid
= 123;
486 the_passwd
.pw_gid
= 123;
489 /* Ensure HOME and SHELL are defined. */
490 if (getenv ("HOME") == NULL
)
492 if (getenv ("SHELL") == NULL
)
495 /* Set dir and shell from environment variables. */
496 strcpy (the_passwd
.pw_dir
, getenv ("HOME"));
497 strcpy (the_passwd
.pw_shell
, getenv ("SHELL"));
506 /* rand () on NT gives us 15 random bits...hack together 30 bits. */
507 return ((rand () << 15) | rand ());
517 /* Normalize filename by converting all path separators to
518 the specified separator. Also conditionally convert upper
519 case path name components to lower case. */
522 normalize_filename (fp
, path_sep
)
529 /* Always lower-case drive letters a-z, even if the filesystem
530 preserves case in filenames.
531 This is so filenames can be compared by string comparison
532 functions that are case-sensitive. Even case-preserving filesystems
533 do not distinguish case in drive letters. */
534 if (fp
[1] == ':' && *fp
>= 'A' && *fp
<= 'Z')
540 if (NILP (Vw32_downcase_file_names
))
544 if (*fp
== '/' || *fp
== '\\')
551 sep
= path_sep
; /* convert to this path separator */
552 elem
= fp
; /* start of current path element */
555 if (*fp
>= 'a' && *fp
<= 'z')
556 elem
= 0; /* don't convert this element */
558 if (*fp
== 0 || *fp
== ':')
560 sep
= *fp
; /* restore current separator (or 0) */
561 *fp
= '/'; /* after conversion of this element */
564 if (*fp
== '/' || *fp
== '\\')
566 if (elem
&& elem
!= fp
)
568 *fp
= 0; /* temporary end of string */
569 _strlwr (elem
); /* while we convert to lower case */
571 *fp
= sep
; /* convert (or restore) path separator */
572 elem
= fp
+ 1; /* next element starts after separator */
578 /* Destructively turn backslashes into slashes. */
580 dostounix_filename (p
)
583 normalize_filename (p
, '/');
586 /* Destructively turn slashes into backslashes. */
588 unixtodos_filename (p
)
591 normalize_filename (p
, '\\');
594 /* Remove all CR's that are followed by a LF.
595 (From msdos.c...probably should figure out a way to share it,
596 although this code isn't going to ever change.) */
600 register unsigned char *buf
;
602 unsigned char *np
= buf
;
603 unsigned char *startp
= buf
;
604 unsigned char *endp
= buf
+ n
;
608 while (buf
< endp
- 1)
612 if (*(++buf
) != 0x0a)
623 /* Parse the root part of file name, if present. Return length and
624 optionally store pointer to char after root. */
626 parse_root (char * name
, char ** pPath
)
633 /* find the root name of the volume if given */
634 if (isalpha (name
[0]) && name
[1] == ':')
636 /* skip past drive specifier */
638 if (IS_DIRECTORY_SEP (name
[0]))
641 else if (IS_DIRECTORY_SEP (name
[0]) && IS_DIRECTORY_SEP (name
[1]))
647 if (IS_DIRECTORY_SEP (*name
) && --slashes
== 0)
652 if (IS_DIRECTORY_SEP (name
[0]))
662 /* Get long base name for name; name is assumed to be absolute. */
664 get_long_basename (char * name
, char * buf
, int size
)
666 WIN32_FIND_DATA find_data
;
670 /* must be valid filename, no wild cards or other invalid characters */
671 if (strpbrk (name
, "*?|<>\""))
674 dir_handle
= FindFirstFile (name
, &find_data
);
675 if (dir_handle
!= INVALID_HANDLE_VALUE
)
677 if ((len
= strlen (find_data
.cFileName
)) < size
)
678 memcpy (buf
, find_data
.cFileName
, len
+ 1);
681 FindClose (dir_handle
);
686 /* Get long name for file, if possible (assumed to be absolute). */
688 w32_get_long_filename (char * name
, char * buf
, int size
)
693 char full
[ MAX_PATH
];
700 /* Use local copy for destructive modification. */
701 memcpy (full
, name
, len
+1);
702 unixtodos_filename (full
);
704 /* Copy root part verbatim. */
705 len
= parse_root (full
, &p
);
706 memcpy (o
, full
, len
);
711 while (p
!= NULL
&& *p
)
714 p
= strchr (q
, '\\');
716 len
= get_long_basename (full
, o
, size
);
739 is_unc_volume (const char *filename
)
741 const char *ptr
= filename
;
743 if (!IS_DIRECTORY_SEP (ptr
[0]) || !IS_DIRECTORY_SEP (ptr
[1]) || !ptr
[2])
746 if (strpbrk (ptr
+ 2, "*?|<>\"\\/"))
752 /* Routines that are no-ops on NT but are defined to get Emacs to compile. */
755 sigsetmask (int signal_mask
)
779 setpgrp (int pid
, int gid
)
791 unrequest_sigio (void)
802 #define REG_ROOT "SOFTWARE\\GNU\\Emacs"
805 w32_get_resource (key
, lpdwtype
)
810 HKEY hrootkey
= NULL
;
814 /* Check both the current user and the local machine to see if
815 we have any resources. */
817 if (RegOpenKeyEx (HKEY_CURRENT_USER
, REG_ROOT
, 0, KEY_READ
, &hrootkey
) == ERROR_SUCCESS
)
821 if (RegQueryValueEx (hrootkey
, key
, NULL
, NULL
, NULL
, &cbData
) == ERROR_SUCCESS
822 && (lpvalue
= (LPBYTE
) xmalloc (cbData
)) != NULL
823 && RegQueryValueEx (hrootkey
, key
, NULL
, lpdwtype
, lpvalue
, &cbData
) == ERROR_SUCCESS
)
828 if (lpvalue
) xfree (lpvalue
);
830 RegCloseKey (hrootkey
);
833 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE
, REG_ROOT
, 0, KEY_READ
, &hrootkey
) == ERROR_SUCCESS
)
837 if (RegQueryValueEx (hrootkey
, key
, NULL
, NULL
, NULL
, &cbData
) == ERROR_SUCCESS
838 && (lpvalue
= (LPBYTE
) xmalloc (cbData
)) != NULL
839 && RegQueryValueEx (hrootkey
, key
, NULL
, lpdwtype
, lpvalue
, &cbData
) == ERROR_SUCCESS
)
844 if (lpvalue
) xfree (lpvalue
);
846 RegCloseKey (hrootkey
);
852 char *get_emacs_configuration (void);
853 extern Lisp_Object Vsystem_configuration
;
856 init_environment (char ** argv
)
858 static const char * const tempdirs
[] = {
859 "$TMPDIR", "$TEMP", "$TMP", "c:/"
862 const int imax
= sizeof (tempdirs
) / sizeof (tempdirs
[0]);
864 /* Make sure they have a usable $TMPDIR. Many Emacs functions use
865 temporary files and assume "/tmp" if $TMPDIR is unset, which
866 will break on DOS/Windows. Refuse to work if we cannot find
867 a directory, not even "c:/", usable for that purpose. */
868 for (i
= 0; i
< imax
; i
++)
870 const char *tmp
= tempdirs
[i
];
873 tmp
= getenv (tmp
+ 1);
874 /* Note that `access' can lie to us if the directory resides on a
875 read-only filesystem, like CD-ROM or a write-protected floppy.
876 The only way to be really sure is to actually create a file and
877 see if it succeeds. But I think that's too much to ask. */
878 if (tmp
&& _access (tmp
, D_OK
) == 0)
880 char * var
= alloca (strlen (tmp
) + 8);
881 sprintf (var
, "TMPDIR=%s", tmp
);
882 _putenv (strdup (var
));
889 Fcons (build_string ("no usable temporary directories found!!"),
891 "While setting TMPDIR: ");
893 /* Check for environment variables and use registry settings if they
894 don't exist. Fallback on default values where applicable. */
899 char locale_name
[32];
901 static struct env_entry
908 {"PRELOAD_WINSOCK", NULL
},
909 {"emacs_dir", "C:/emacs"},
910 {"EMACSLOADPATH", "%emacs_dir%/site-lisp;%emacs_dir%/../site-lisp;%emacs_dir%/lisp;%emacs_dir%/leim"},
911 {"SHELL", "%emacs_dir%/bin/cmdproxy.exe"},
912 {"EMACSDATA", "%emacs_dir%/etc"},
913 {"EMACSPATH", "%emacs_dir%/bin"},
914 /* We no longer set INFOPATH because Info-default-directory-list
916 /* {"INFOPATH", "%emacs_dir%/info"}, */
917 {"EMACSDOC", "%emacs_dir%/etc"},
922 /* Get default locale info and use it for LANG. */
923 if (GetLocaleInfo (LOCALE_USER_DEFAULT
,
924 LOCALE_SABBREVLANGNAME
| LOCALE_USE_CP_ACP
,
925 locale_name
, sizeof (locale_name
)))
927 for (i
= 0; i
< (sizeof (env_vars
) / sizeof (env_vars
[0])); i
++)
929 if (strcmp (env_vars
[i
].name
, "LANG") == 0)
931 env_vars
[i
].def_value
= locale_name
;
937 #define SET_ENV_BUF_SIZE (4 * MAX_PATH) /* to cover EMACSLOADPATH */
939 /* Treat emacs_dir specially: set it unconditionally based on our
940 location, if it appears that we are running from the bin subdir
941 of a standard installation. */
944 char modname
[MAX_PATH
];
946 if (!GetModuleFileName (NULL
, modname
, MAX_PATH
))
948 if ((p
= strrchr (modname
, '\\')) == NULL
)
952 if ((p
= strrchr (modname
, '\\')) && stricmp (p
, "\\bin") == 0)
954 char buf
[SET_ENV_BUF_SIZE
];
957 for (p
= modname
; *p
; p
++)
958 if (*p
== '\\') *p
= '/';
960 _snprintf (buf
, sizeof(buf
)-1, "emacs_dir=%s", modname
);
961 _putenv (strdup (buf
));
965 for (i
= 0; i
< (sizeof (env_vars
) / sizeof (env_vars
[0])); i
++)
967 if (!getenv (env_vars
[i
].name
))
971 if ((lpval
= w32_get_resource (env_vars
[i
].name
, &dwType
)) == NULL
)
973 lpval
= env_vars
[i
].def_value
;
974 dwType
= REG_EXPAND_SZ
;
980 if (dwType
== REG_EXPAND_SZ
)
982 char buf1
[SET_ENV_BUF_SIZE
], buf2
[SET_ENV_BUF_SIZE
];
984 ExpandEnvironmentStrings ((LPSTR
) lpval
, buf1
, sizeof(buf1
));
985 _snprintf (buf2
, sizeof(buf2
)-1, "%s=%s", env_vars
[i
].name
, buf1
);
986 _putenv (strdup (buf2
));
988 else if (dwType
== REG_SZ
)
990 char buf
[SET_ENV_BUF_SIZE
];
992 _snprintf (buf
, sizeof(buf
)-1, "%s=%s", env_vars
[i
].name
, lpval
);
993 _putenv (strdup (buf
));
1003 /* Rebuild system configuration to reflect invoking system. */
1004 Vsystem_configuration
= build_string (EMACS_CONFIGURATION
);
1006 /* Another special case: on NT, the PATH variable is actually named
1007 "Path" although cmd.exe (perhaps NT itself) arranges for
1008 environment variable lookup and setting to be case insensitive.
1009 However, Emacs assumes a fully case sensitive environment, so we
1010 need to change "Path" to "PATH" to match the expectations of
1011 various elisp packages. We do this by the sneaky method of
1012 modifying the string in the C runtime environ entry.
1014 The same applies to COMSPEC. */
1018 for (envp
= environ
; *envp
; envp
++)
1019 if (_strnicmp (*envp
, "PATH=", 5) == 0)
1020 memcpy (*envp
, "PATH=", 5);
1021 else if (_strnicmp (*envp
, "COMSPEC=", 8) == 0)
1022 memcpy (*envp
, "COMSPEC=", 8);
1025 /* Remember the initial working directory for getwd, then make the
1026 real wd be the location of emacs.exe to avoid conflicts when
1027 renaming or deleting directories. (We also don't call chdir when
1028 running subprocesses for the same reason.) */
1029 if (!GetCurrentDirectory (MAXPATHLEN
, startup_dir
))
1034 static char modname
[MAX_PATH
];
1036 if (!GetModuleFileName (NULL
, modname
, MAX_PATH
))
1038 if ((p
= strrchr (modname
, '\\')) == NULL
)
1042 SetCurrentDirectory (modname
);
1044 /* Ensure argv[0] has the full path to Emacs. */
1049 /* Determine if there is a middle mouse button, to allow parse_button
1050 to decide whether right mouse events should be mouse-2 or
1052 XSETINT (Vw32_num_mouse_buttons
, GetSystemMetrics (SM_CMOUSEBUTTONS
));
1058 emacs_root_dir (void)
1060 static char root_dir
[FILENAME_MAX
];
1063 p
= getenv ("emacs_dir");
1066 strcpy (root_dir
, p
);
1067 root_dir
[parse_root (root_dir
, NULL
)] = '\0';
1068 dostounix_filename (root_dir
);
1072 /* We don't have scripts to automatically determine the system configuration
1073 for Emacs before it's compiled, and we don't want to have to make the
1074 user enter it, so we define EMACS_CONFIGURATION to invoke this runtime
1078 get_emacs_configuration (void)
1080 char *arch
, *oem
, *os
;
1082 static char configuration_buffer
[32];
1084 /* Determine the processor type. */
1085 switch (get_processor_type ())
1088 #ifdef PROCESSOR_INTEL_386
1089 case PROCESSOR_INTEL_386
:
1090 case PROCESSOR_INTEL_486
:
1091 case PROCESSOR_INTEL_PENTIUM
:
1096 #ifdef PROCESSOR_INTEL_860
1097 case PROCESSOR_INTEL_860
:
1102 #ifdef PROCESSOR_MIPS_R2000
1103 case PROCESSOR_MIPS_R2000
:
1104 case PROCESSOR_MIPS_R3000
:
1105 case PROCESSOR_MIPS_R4000
:
1110 #ifdef PROCESSOR_ALPHA_21064
1111 case PROCESSOR_ALPHA_21064
:
1121 /* Use the OEM field to reflect the compiler/library combination. */
1123 #define COMPILER_NAME "msvc"
1126 #define COMPILER_NAME "mingw"
1128 #define COMPILER_NAME "unknown"
1131 oem
= COMPILER_NAME
;
1133 switch (osinfo_cache
.dwPlatformId
) {
1134 case VER_PLATFORM_WIN32_NT
:
1136 build_num
= osinfo_cache
.dwBuildNumber
;
1138 case VER_PLATFORM_WIN32_WINDOWS
:
1139 if (osinfo_cache
.dwMinorVersion
== 0) {
1144 build_num
= LOWORD (osinfo_cache
.dwBuildNumber
);
1146 case VER_PLATFORM_WIN32s
:
1147 /* Not supported, should not happen. */
1149 build_num
= LOWORD (osinfo_cache
.dwBuildNumber
);
1157 if (osinfo_cache
.dwPlatformId
== VER_PLATFORM_WIN32_NT
) {
1158 sprintf (configuration_buffer
, "%s-%s-%s%d.%d.%d", arch
, oem
, os
,
1159 get_w32_major_version (), get_w32_minor_version (), build_num
);
1161 sprintf (configuration_buffer
, "%s-%s-%s.%d", arch
, oem
, os
, build_num
);
1164 return configuration_buffer
;
1168 get_emacs_configuration_options (void)
1170 static char options_buffer
[256];
1172 /* Work out the effective configure options for this build. */
1174 #define COMPILER_VERSION "--with-msvc (%d.%02d)", _MSC_VER / 100, _MSC_VER % 100
1177 #define COMPILER_VERSION "--with-gcc (%d.%d)", __GNUC__, __GNUC_MINOR__
1179 #define COMPILER_VERSION ""
1183 sprintf (options_buffer
, COMPILER_VERSION
);
1185 strcat (options_buffer
, " --no-opt");
1188 strcat (options_buffer
, " --cflags");
1189 strcat (options_buffer
, USER_CFLAGS
);
1192 strcat (options_buffer
, " --ldflags");
1193 strcat (options_buffer
, USER_LDFLAGS
);
1195 return options_buffer
;
1199 #include <sys/timeb.h>
1201 /* Emulate gettimeofday (Ulrich Leodolter, 1/11/95). */
1203 gettimeofday (struct timeval
*tv
, struct timezone
*tz
)
1208 tv
->tv_sec
= tb
.time
;
1209 tv
->tv_usec
= tb
.millitm
* 1000L;
1212 tz
->tz_minuteswest
= tb
.timezone
; /* minutes west of Greenwich */
1213 tz
->tz_dsttime
= tb
.dstflag
; /* type of dst correction */
1217 /* ------------------------------------------------------------------------- */
1218 /* IO support and wrapper functions for W32 API. */
1219 /* ------------------------------------------------------------------------- */
1221 /* Place a wrapper around the MSVC version of ctime. It returns NULL
1222 on network directories, so we handle that case here.
1223 (Ulrich Leodolter, 1/11/95). */
1225 sys_ctime (const time_t *t
)
1227 char *str
= (char *) ctime (t
);
1228 return (str
? str
: "Sun Jan 01 00:00:00 1970");
1231 /* Emulate sleep...we could have done this with a define, but that
1232 would necessitate including windows.h in the files that used it.
1233 This is much easier. */
1235 sys_sleep (int seconds
)
1237 Sleep (seconds
* 1000);
1240 /* Internal MSVC functions for low-level descriptor munging */
1241 extern int __cdecl
_set_osfhnd (int fd
, long h
);
1242 extern int __cdecl
_free_osfhnd (int fd
);
1244 /* parallel array of private info on file handles */
1245 filedesc fd_info
[ MAXDESC
];
1247 typedef struct volume_info_data
{
1248 struct volume_info_data
* next
;
1250 /* time when info was obtained */
1253 /* actual volume info */
1262 /* Global referenced by various functions. */
1263 static volume_info_data volume_info
;
1265 /* Vector to indicate which drives are local and fixed (for which cached
1266 data never expires). */
1267 static BOOL fixed_drives
[26];
1269 /* Consider cached volume information to be stale if older than 10s,
1270 at least for non-local drives. Info for fixed drives is never stale. */
1271 #define DRIVE_INDEX( c ) ( (c) <= 'Z' ? (c) - 'A' : (c) - 'a' )
1272 #define VOLINFO_STILL_VALID( root_dir, info ) \
1273 ( ( isalpha (root_dir[0]) && \
1274 fixed_drives[ DRIVE_INDEX (root_dir[0]) ] ) \
1275 || GetTickCount () - info->timestamp < 10000 )
1277 /* Cache support functions. */
1279 /* Simple linked list with linear search is sufficient. */
1280 static volume_info_data
*volume_cache
= NULL
;
1282 static volume_info_data
*
1283 lookup_volume_info (char * root_dir
)
1285 volume_info_data
* info
;
1287 for (info
= volume_cache
; info
; info
= info
->next
)
1288 if (stricmp (info
->root_dir
, root_dir
) == 0)
1294 add_volume_info (char * root_dir
, volume_info_data
* info
)
1296 info
->root_dir
= xstrdup (root_dir
);
1297 info
->next
= volume_cache
;
1298 volume_cache
= info
;
1302 /* Wrapper for GetVolumeInformation, which uses caching to avoid
1303 performance penalty (~2ms on 486 for local drives, 7.5ms for local
1304 cdrom drive, ~5-10ms or more for remote drives on LAN). */
1306 GetCachedVolumeInformation (char * root_dir
)
1308 volume_info_data
* info
;
1309 char default_root
[ MAX_PATH
];
1311 /* NULL for root_dir means use root from current directory. */
1312 if (root_dir
== NULL
)
1314 if (GetCurrentDirectory (MAX_PATH
, default_root
) == 0)
1316 parse_root (default_root
, &root_dir
);
1318 root_dir
= default_root
;
1321 /* Local fixed drives can be cached permanently. Removable drives
1322 cannot be cached permanently, since the volume name and serial
1323 number (if nothing else) can change. Remote drives should be
1324 treated as if they are removable, since there is no sure way to
1325 tell whether they are or not. Also, the UNC association of drive
1326 letters mapped to remote volumes can be changed at any time (even
1327 by other processes) without notice.
1329 As a compromise, so we can benefit from caching info for remote
1330 volumes, we use a simple expiry mechanism to invalidate cache
1331 entries that are more than ten seconds old. */
1334 /* No point doing this, because WNetGetConnection is even slower than
1335 GetVolumeInformation, consistently taking ~50ms on a 486 (FWIW,
1336 GetDriveType is about the only call of this type which does not
1337 involve network access, and so is extremely quick). */
1339 /* Map drive letter to UNC if remote. */
1340 if ( isalpha( root_dir
[0] ) && !fixed
[ DRIVE_INDEX( root_dir
[0] ) ] )
1342 char remote_name
[ 256 ];
1343 char drive
[3] = { root_dir
[0], ':' };
1345 if (WNetGetConnection (drive
, remote_name
, sizeof (remote_name
))
1347 /* do something */ ;
1351 info
= lookup_volume_info (root_dir
);
1353 if (info
== NULL
|| ! VOLINFO_STILL_VALID (root_dir
, info
))
1361 /* Info is not cached, or is stale. */
1362 if (!GetVolumeInformation (root_dir
,
1363 name
, sizeof (name
),
1367 type
, sizeof (type
)))
1370 /* Cache the volume information for future use, overwriting existing
1371 entry if present. */
1374 info
= (volume_info_data
*) xmalloc (sizeof (volume_info_data
));
1375 add_volume_info (root_dir
, info
);
1383 info
->name
= xstrdup (name
);
1384 info
->serialnum
= serialnum
;
1385 info
->maxcomp
= maxcomp
;
1386 info
->flags
= flags
;
1387 info
->type
= xstrdup (type
);
1388 info
->timestamp
= GetTickCount ();
1394 /* Get information on the volume where name is held; set path pointer to
1395 start of pathname in name (past UNC header\volume header if present). */
1397 get_volume_info (const char * name
, const char ** pPath
)
1399 char temp
[MAX_PATH
];
1400 char *rootname
= NULL
; /* default to current volume */
1401 volume_info_data
* info
;
1406 /* find the root name of the volume if given */
1407 if (isalpha (name
[0]) && name
[1] == ':')
1415 else if (IS_DIRECTORY_SEP (name
[0]) && IS_DIRECTORY_SEP (name
[1]))
1422 if (IS_DIRECTORY_SEP (*name
) && --slashes
== 0)
1435 info
= GetCachedVolumeInformation (rootname
);
1438 /* Set global referenced by other functions. */
1439 volume_info
= *info
;
1445 /* Determine if volume is FAT format (ie. only supports short 8.3
1446 names); also set path pointer to start of pathname in name. */
1448 is_fat_volume (const char * name
, const char ** pPath
)
1450 if (get_volume_info (name
, pPath
))
1451 return (volume_info
.maxcomp
== 12);
1455 /* Map filename to a legal 8.3 name if necessary. */
1457 map_w32_filename (const char * name
, const char ** pPath
)
1459 static char shortname
[MAX_PATH
];
1460 char * str
= shortname
;
1463 const char * save_name
= name
;
1465 if (strlen (name
) >= MAX_PATH
)
1467 /* Return a filename which will cause callers to fail. */
1468 strcpy (shortname
, "?");
1472 if (is_fat_volume (name
, (const char **)&path
)) /* truncate to 8.3 */
1474 register int left
= 8; /* maximum number of chars in part */
1475 register int extn
= 0; /* extension added? */
1476 register int dots
= 2; /* maximum number of dots allowed */
1479 *str
++ = *name
++; /* skip past UNC header */
1481 while ((c
= *name
++))
1488 extn
= 0; /* reset extension flags */
1489 dots
= 2; /* max 2 dots */
1490 left
= 8; /* max length 8 for main part */
1494 extn
= 0; /* reset extension flags */
1495 dots
= 2; /* max 2 dots */
1496 left
= 8; /* max length 8 for main part */
1501 /* Convert path components of the form .xxx to _xxx,
1502 but leave . and .. as they are. This allows .emacs
1503 to be read as _emacs, for example. */
1507 IS_DIRECTORY_SEP (*name
))
1522 extn
= 1; /* we've got an extension */
1523 left
= 3; /* 3 chars in extension */
1527 /* any embedded dots after the first are converted to _ */
1532 case '#': /* don't lose these, they're important */
1534 str
[-1] = c
; /* replace last character of part */
1539 *str
++ = tolower (c
); /* map to lower case (looks nicer) */
1541 dots
= 0; /* started a path component */
1550 strcpy (shortname
, name
);
1551 unixtodos_filename (shortname
);
1555 *pPath
= shortname
+ (path
- save_name
);
1561 is_exec (const char * name
)
1563 char * p
= strrchr (name
, '.');
1566 && (stricmp (p
, ".exe") == 0 ||
1567 stricmp (p
, ".com") == 0 ||
1568 stricmp (p
, ".bat") == 0 ||
1569 stricmp (p
, ".cmd") == 0));
1572 /* Emulate the Unix directory procedures opendir, closedir,
1573 and readdir. We can't use the procedures supplied in sysdep.c,
1574 so we provide them here. */
1576 struct direct dir_static
; /* simulated directory contents */
1577 static HANDLE dir_find_handle
= INVALID_HANDLE_VALUE
;
1578 static int dir_is_fat
;
1579 static char dir_pathname
[MAXPATHLEN
+1];
1580 static WIN32_FIND_DATA dir_find_data
;
1582 /* Support shares on a network resource as subdirectories of a read-only
1584 static HANDLE wnet_enum_handle
= INVALID_HANDLE_VALUE
;
1585 HANDLE
open_unc_volume (char *);
1586 char *read_unc_volume (HANDLE
, char *, int);
1587 void close_unc_volume (HANDLE
);
1590 opendir (char *filename
)
1594 /* Opening is done by FindFirstFile. However, a read is inherent to
1595 this operation, so we defer the open until read time. */
1597 if (dir_find_handle
!= INVALID_HANDLE_VALUE
)
1599 if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
1602 if (is_unc_volume (filename
))
1604 wnet_enum_handle
= open_unc_volume (filename
);
1605 if (wnet_enum_handle
== INVALID_HANDLE_VALUE
)
1609 if (!(dirp
= (DIR *) malloc (sizeof (DIR))))
1616 strncpy (dir_pathname
, map_w32_filename (filename
, NULL
), MAXPATHLEN
);
1617 dir_pathname
[MAXPATHLEN
] = '\0';
1618 dir_is_fat
= is_fat_volume (filename
, NULL
);
1624 closedir (DIR *dirp
)
1626 /* If we have a find-handle open, close it. */
1627 if (dir_find_handle
!= INVALID_HANDLE_VALUE
)
1629 FindClose (dir_find_handle
);
1630 dir_find_handle
= INVALID_HANDLE_VALUE
;
1632 else if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
1634 close_unc_volume (wnet_enum_handle
);
1635 wnet_enum_handle
= INVALID_HANDLE_VALUE
;
1637 xfree ((char *) dirp
);
1643 if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
1645 if (!read_unc_volume (wnet_enum_handle
,
1646 dir_find_data
.cFileName
,
1650 /* If we aren't dir_finding, do a find-first, otherwise do a find-next. */
1651 else if (dir_find_handle
== INVALID_HANDLE_VALUE
)
1653 char filename
[MAXNAMLEN
+ 3];
1656 strcpy (filename
, dir_pathname
);
1657 ln
= strlen (filename
) - 1;
1658 if (!IS_DIRECTORY_SEP (filename
[ln
]))
1659 strcat (filename
, "\\");
1660 strcat (filename
, "*");
1662 dir_find_handle
= FindFirstFile (filename
, &dir_find_data
);
1664 if (dir_find_handle
== INVALID_HANDLE_VALUE
)
1669 if (!FindNextFile (dir_find_handle
, &dir_find_data
))
1673 /* Emacs never uses this value, so don't bother making it match
1674 value returned by stat(). */
1675 dir_static
.d_ino
= 1;
1677 dir_static
.d_reclen
= sizeof (struct direct
) - MAXNAMLEN
+ 3 +
1678 dir_static
.d_namlen
- dir_static
.d_namlen
% 4;
1680 dir_static
.d_namlen
= strlen (dir_find_data
.cFileName
);
1681 strcpy (dir_static
.d_name
, dir_find_data
.cFileName
);
1683 _strlwr (dir_static
.d_name
);
1684 else if (!NILP (Vw32_downcase_file_names
))
1687 for (p
= dir_static
.d_name
; *p
; p
++)
1688 if (*p
>= 'a' && *p
<= 'z')
1691 _strlwr (dir_static
.d_name
);
1698 open_unc_volume (char *path
)
1704 nr
.dwScope
= RESOURCE_GLOBALNET
;
1705 nr
.dwType
= RESOURCETYPE_DISK
;
1706 nr
.dwDisplayType
= RESOURCEDISPLAYTYPE_SERVER
;
1707 nr
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
1708 nr
.lpLocalName
= NULL
;
1709 nr
.lpRemoteName
= map_w32_filename (path
, NULL
);
1710 nr
.lpComment
= NULL
;
1711 nr
.lpProvider
= NULL
;
1713 result
= WNetOpenEnum(RESOURCE_GLOBALNET
, RESOURCETYPE_DISK
,
1714 RESOURCEUSAGE_CONNECTABLE
, &nr
, &henum
);
1716 if (result
== NO_ERROR
)
1719 return INVALID_HANDLE_VALUE
;
1723 read_unc_volume (HANDLE henum
, char *readbuf
, int size
)
1727 DWORD bufsize
= 512;
1732 buffer
= alloca (bufsize
);
1733 result
= WNetEnumResource (wnet_enum_handle
, &count
, buffer
, &bufsize
);
1734 if (result
!= NO_ERROR
)
1737 /* WNetEnumResource returns \\resource\share...skip forward to "share". */
1738 ptr
= ((LPNETRESOURCE
) buffer
)->lpRemoteName
;
1740 while (*ptr
&& !IS_DIRECTORY_SEP (*ptr
)) ptr
++;
1743 strncpy (readbuf
, ptr
, size
);
1748 close_unc_volume (HANDLE henum
)
1750 if (henum
!= INVALID_HANDLE_VALUE
)
1751 WNetCloseEnum (henum
);
1755 unc_volume_file_attributes (char *path
)
1760 henum
= open_unc_volume (path
);
1761 if (henum
== INVALID_HANDLE_VALUE
)
1764 attrs
= FILE_ATTRIBUTE_READONLY
| FILE_ATTRIBUTE_DIRECTORY
;
1766 close_unc_volume (henum
);
1772 /* Shadow some MSVC runtime functions to map requests for long filenames
1773 to reasonable short names if necessary. This was originally added to
1774 permit running Emacs on NT 3.1 on a FAT partition, which doesn't support
1778 sys_access (const char * path
, int mode
)
1782 /* MSVC implementation doesn't recognize D_OK. */
1783 path
= map_w32_filename (path
, NULL
);
1784 if (is_unc_volume (path
))
1786 attributes
= unc_volume_file_attributes (path
);
1787 if (attributes
== -1) {
1792 else if ((attributes
= GetFileAttributes (path
)) == -1)
1794 /* Should try mapping GetLastError to errno; for now just indicate
1795 that path doesn't exist. */
1799 if ((mode
& X_OK
) != 0 && !is_exec (path
))
1804 if ((mode
& W_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_READONLY
) != 0)
1809 if ((mode
& D_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
) == 0)
1818 sys_chdir (const char * path
)
1820 return _chdir (map_w32_filename (path
, NULL
));
1824 sys_chmod (const char * path
, int mode
)
1826 return _chmod (map_w32_filename (path
, NULL
), mode
);
1830 sys_creat (const char * path
, int mode
)
1832 return _creat (map_w32_filename (path
, NULL
), mode
);
1836 sys_fopen(const char * path
, const char * mode
)
1840 const char * mode_save
= mode
;
1842 /* Force all file handles to be non-inheritable. This is necessary to
1843 ensure child processes don't unwittingly inherit handles that might
1844 prevent future file access. */
1848 else if (mode
[0] == 'w' || mode
[0] == 'a')
1849 oflag
= O_WRONLY
| O_CREAT
| O_TRUNC
;
1853 /* Only do simplistic option parsing. */
1857 oflag
&= ~(O_RDONLY
| O_WRONLY
);
1860 else if (mode
[0] == 'b')
1865 else if (mode
[0] == 't')
1872 fd
= _open (map_w32_filename (path
, NULL
), oflag
| _O_NOINHERIT
, 0644);
1876 return _fdopen (fd
, mode_save
);
1879 /* This only works on NTFS volumes, but is useful to have. */
1881 sys_link (const char * old
, const char * new)
1885 char oldname
[MAX_PATH
], newname
[MAX_PATH
];
1887 if (old
== NULL
|| new == NULL
)
1893 strcpy (oldname
, map_w32_filename (old
, NULL
));
1894 strcpy (newname
, map_w32_filename (new, NULL
));
1896 fileh
= CreateFile (oldname
, 0, 0, NULL
, OPEN_EXISTING
,
1897 FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
1898 if (fileh
!= INVALID_HANDLE_VALUE
)
1902 /* Confusingly, the "alternate" stream name field does not apply
1903 when restoring a hard link, and instead contains the actual
1904 stream data for the link (ie. the name of the link to create).
1905 The WIN32_STREAM_ID structure before the cStreamName field is
1906 the stream header, which is then immediately followed by the
1910 WIN32_STREAM_ID wid
;
1911 WCHAR wbuffer
[MAX_PATH
]; /* extra space for link name */
1914 wlen
= MultiByteToWideChar (CP_ACP
, MB_PRECOMPOSED
, newname
, -1,
1915 data
.wid
.cStreamName
, MAX_PATH
);
1918 LPVOID context
= NULL
;
1921 data
.wid
.dwStreamId
= BACKUP_LINK
;
1922 data
.wid
.dwStreamAttributes
= 0;
1923 data
.wid
.Size
.LowPart
= wlen
* sizeof(WCHAR
);
1924 data
.wid
.Size
.HighPart
= 0;
1925 data
.wid
.dwStreamNameSize
= 0;
1927 if (BackupWrite (fileh
, (LPBYTE
)&data
,
1928 offsetof (WIN32_STREAM_ID
, cStreamName
)
1929 + data
.wid
.Size
.LowPart
,
1930 &wbytes
, FALSE
, FALSE
, &context
)
1931 && BackupWrite (fileh
, NULL
, 0, &wbytes
, TRUE
, FALSE
, &context
))
1938 /* Should try mapping GetLastError to errno; for now just
1939 indicate a general error (eg. links not supported). */
1940 errno
= EINVAL
; // perhaps EMLINK?
1944 CloseHandle (fileh
);
1953 sys_mkdir (const char * path
)
1955 return _mkdir (map_w32_filename (path
, NULL
));
1958 /* Because of long name mapping issues, we need to implement this
1959 ourselves. Also, MSVC's _mktemp returns NULL when it can't generate
1960 a unique name, instead of setting the input template to an empty
1963 Standard algorithm seems to be use pid or tid with a letter on the
1964 front (in place of the 6 X's) and cycle through the letters to find a
1965 unique name. We extend that to allow any reasonable character as the
1966 first of the 6 X's. */
1968 sys_mktemp (char * template)
1972 unsigned uid
= GetCurrentThreadId ();
1973 static char first_char
[] = "abcdefghijklmnopqrstuvwyz0123456789!%-_@#";
1975 if (template == NULL
)
1977 p
= template + strlen (template);
1979 /* replace up to the last 5 X's with uid in decimal */
1980 while (--p
>= template && p
[0] == 'X' && --i
>= 0)
1982 p
[0] = '0' + uid
% 10;
1986 if (i
< 0 && p
[0] == 'X')
1991 int save_errno
= errno
;
1992 p
[0] = first_char
[i
];
1993 if (sys_access (template, 0) < 0)
1999 while (++i
< sizeof (first_char
));
2002 /* Template is badly formed or else we can't generate a unique name,
2003 so return empty string */
2009 sys_open (const char * path
, int oflag
, int mode
)
2011 const char* mpath
= map_w32_filename (path
, NULL
);
2012 /* Try to open file without _O_CREAT, to be able to write to hidden
2013 and system files. Force all file handles to be
2015 int res
= _open (mpath
, (oflag
& ~_O_CREAT
) | _O_NOINHERIT
, mode
);
2018 return _open (mpath
, oflag
| _O_NOINHERIT
, mode
);
2022 sys_rename (const char * oldname
, const char * newname
)
2025 char temp
[MAX_PATH
];
2027 /* MoveFile on Windows 95 doesn't correctly change the short file name
2028 alias in a number of circumstances (it is not easy to predict when
2029 just by looking at oldname and newname, unfortunately). In these
2030 cases, renaming through a temporary name avoids the problem.
2032 A second problem on Windows 95 is that renaming through a temp name when
2033 newname is uppercase fails (the final long name ends up in
2034 lowercase, although the short alias might be uppercase) UNLESS the
2035 long temp name is not 8.3.
2037 So, on Windows 95 we always rename through a temp name, and we make sure
2038 the temp name has a long extension to ensure correct renaming. */
2040 strcpy (temp
, map_w32_filename (oldname
, NULL
));
2042 if (os_subtype
== OS_WIN95
)
2048 oldname
= map_w32_filename (oldname
, NULL
);
2049 if (o
= strrchr (oldname
, '\\'))
2052 o
= (char *) oldname
;
2054 if (p
= strrchr (temp
, '\\'))
2061 /* Force temp name to require a manufactured 8.3 alias - this
2062 seems to make the second rename work properly. */
2063 sprintf (p
, "_.%s.%u", o
, i
);
2065 result
= rename (oldname
, temp
);
2067 /* This loop must surely terminate! */
2068 while (result
< 0 && errno
== EEXIST
);
2073 /* Emulate Unix behaviour - newname is deleted if it already exists
2074 (at least if it is a file; don't do this for directories).
2076 Since we mustn't do this if we are just changing the case of the
2077 file name (we would end up deleting the file we are trying to
2078 rename!), we let rename detect if the destination file already
2079 exists - that way we avoid the possible pitfalls of trying to
2080 determine ourselves whether two names really refer to the same
2081 file, which is not always possible in the general case. (Consider
2082 all the permutations of shared or subst'd drives, etc.) */
2084 newname
= map_w32_filename (newname
, NULL
);
2085 result
= rename (temp
, newname
);
2089 && _chmod (newname
, 0666) == 0
2090 && _unlink (newname
) == 0)
2091 result
= rename (temp
, newname
);
2097 sys_rmdir (const char * path
)
2099 return _rmdir (map_w32_filename (path
, NULL
));
2103 sys_unlink (const char * path
)
2105 path
= map_w32_filename (path
, NULL
);
2107 /* On Unix, unlink works without write permission. */
2108 _chmod (path
, 0666);
2109 return _unlink (path
);
2112 static FILETIME utc_base_ft
;
2113 static long double utc_base
;
2114 static int init
= 0;
2117 convert_time (FILETIME ft
)
2123 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
2132 st
.wMilliseconds
= 0;
2134 SystemTimeToFileTime (&st
, &utc_base_ft
);
2135 utc_base
= (long double) utc_base_ft
.dwHighDateTime
2136 * 4096 * 1024 * 1024 + utc_base_ft
.dwLowDateTime
;
2140 if (CompareFileTime (&ft
, &utc_base_ft
) < 0)
2143 ret
= (long double) ft
.dwHighDateTime
* 4096 * 1024 * 1024 + ft
.dwLowDateTime
;
2145 return (time_t) (ret
* 1e-7);
2149 convert_from_time_t (time_t time
, FILETIME
* pft
)
2155 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
2164 st
.wMilliseconds
= 0;
2166 SystemTimeToFileTime (&st
, &utc_base_ft
);
2167 utc_base
= (long double) utc_base_ft
.dwHighDateTime
2168 * 4096 * 1024 * 1024 + utc_base_ft
.dwLowDateTime
;
2172 /* time in 100ns units since 1-Jan-1601 */
2173 tmp
= (long double) time
* 1e7
+ utc_base
;
2174 pft
->dwHighDateTime
= (DWORD
) (tmp
/ (4096.0 * 1024 * 1024));
2175 pft
->dwLowDateTime
= (DWORD
) (tmp
- (4096.0 * 1024 * 1024) * pft
->dwHighDateTime
);
2179 /* No reason to keep this; faking inode values either by hashing or even
2180 using the file index from GetInformationByHandle, is not perfect and
2181 so by default Emacs doesn't use the inode values on Windows.
2182 Instead, we now determine file-truename correctly (except for
2183 possible drive aliasing etc). */
2185 /* Modified version of "PJW" algorithm (see the "Dragon" compiler book). */
2187 hashval (const unsigned char * str
)
2192 h
= (h
<< 4) + *str
++;
2198 /* Return the hash value of the canonical pathname, excluding the
2199 drive/UNC header, to get a hopefully unique inode number. */
2201 generate_inode_val (const char * name
)
2203 char fullname
[ MAX_PATH
];
2207 /* Get the truly canonical filename, if it exists. (Note: this
2208 doesn't resolve aliasing due to subst commands, or recognise hard
2210 if (!w32_get_long_filename ((char *)name
, fullname
, MAX_PATH
))
2213 parse_root (fullname
, &p
);
2214 /* Normal W32 filesystems are still case insensitive. */
2221 /* MSVC stat function can't cope with UNC names and has other bugs, so
2222 replace it with our own. This also allows us to calculate consistent
2223 inode values without hacks in the main Emacs code. */
2225 stat (const char * path
, struct stat
* buf
)
2228 WIN32_FIND_DATA wfd
;
2233 int rootdir
= FALSE
;
2235 if (path
== NULL
|| buf
== NULL
)
2241 name
= (char *) map_w32_filename (path
, &path
);
2242 /* must be valid filename, no wild cards or other invalid characters */
2243 if (strpbrk (name
, "*?|<>\""))
2249 /* If name is "c:/.." or "/.." then stat "c:/" or "/". */
2250 r
= IS_DEVICE_SEP (name
[1]) ? &name
[2] : name
;
2251 if (IS_DIRECTORY_SEP (r
[0]) && r
[1] == '.' && r
[2] == '.' && r
[3] == '\0')
2256 /* Remove trailing directory separator, unless name is the root
2257 directory of a drive or UNC volume in which case ensure there
2258 is a trailing separator. */
2259 len
= strlen (name
);
2260 rootdir
= (path
>= name
+ len
- 1
2261 && (IS_DIRECTORY_SEP (*path
) || *path
== 0));
2262 name
= strcpy (alloca (len
+ 2), name
);
2264 if (is_unc_volume (name
))
2266 DWORD attrs
= unc_volume_file_attributes (name
);
2271 memset (&wfd
, 0, sizeof (wfd
));
2272 wfd
.dwFileAttributes
= attrs
;
2273 wfd
.ftCreationTime
= utc_base_ft
;
2274 wfd
.ftLastAccessTime
= utc_base_ft
;
2275 wfd
.ftLastWriteTime
= utc_base_ft
;
2276 strcpy (wfd
.cFileName
, name
);
2280 if (!IS_DIRECTORY_SEP (name
[len
-1]))
2281 strcat (name
, "\\");
2282 if (GetDriveType (name
) < 2)
2287 memset (&wfd
, 0, sizeof (wfd
));
2288 wfd
.dwFileAttributes
= FILE_ATTRIBUTE_DIRECTORY
;
2289 wfd
.ftCreationTime
= utc_base_ft
;
2290 wfd
.ftLastAccessTime
= utc_base_ft
;
2291 wfd
.ftLastWriteTime
= utc_base_ft
;
2292 strcpy (wfd
.cFileName
, name
);
2296 if (IS_DIRECTORY_SEP (name
[len
-1]))
2299 /* (This is hacky, but helps when doing file completions on
2300 network drives.) Optimize by using information available from
2301 active readdir if possible. */
2302 len
= strlen (dir_pathname
);
2303 if (IS_DIRECTORY_SEP (dir_pathname
[len
-1]))
2305 if (dir_find_handle
!= INVALID_HANDLE_VALUE
2306 && strnicmp (name
, dir_pathname
, len
) == 0
2307 && IS_DIRECTORY_SEP (name
[len
])
2308 && stricmp (name
+ len
+ 1, dir_static
.d_name
) == 0)
2310 /* This was the last entry returned by readdir. */
2311 wfd
= dir_find_data
;
2315 fh
= FindFirstFile (name
, &wfd
);
2316 if (fh
== INVALID_HANDLE_VALUE
)
2325 if (!NILP (Vw32_get_true_file_attributes
)
2326 /* No access rights required to get info. */
2327 && (fh
= CreateFile (name
, 0, 0, NULL
, OPEN_EXISTING
,
2328 FILE_FLAG_BACKUP_SEMANTICS
, NULL
))
2329 != INVALID_HANDLE_VALUE
)
2331 /* This is more accurate in terms of gettting the correct number
2332 of links, but is quite slow (it is noticable when Emacs is
2333 making a list of file name completions). */
2334 BY_HANDLE_FILE_INFORMATION info
;
2336 if (GetFileInformationByHandle (fh
, &info
))
2338 buf
->st_nlink
= info
.nNumberOfLinks
;
2339 /* Might as well use file index to fake inode values, but this
2340 is not guaranteed to be unique unless we keep a handle open
2341 all the time (even then there are situations where it is
2342 not unique). Reputedly, there are at most 48 bits of info
2343 (on NTFS, presumably less on FAT). */
2344 fake_inode
= info
.nFileIndexLow
^ info
.nFileIndexHigh
;
2352 if (wfd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
2354 buf
->st_mode
= _S_IFDIR
;
2358 switch (GetFileType (fh
))
2360 case FILE_TYPE_DISK
:
2361 buf
->st_mode
= _S_IFREG
;
2363 case FILE_TYPE_PIPE
:
2364 buf
->st_mode
= _S_IFIFO
;
2366 case FILE_TYPE_CHAR
:
2367 case FILE_TYPE_UNKNOWN
:
2369 buf
->st_mode
= _S_IFCHR
;
2376 /* Don't bother to make this information more accurate. */
2377 buf
->st_mode
= (wfd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) ?
2378 _S_IFDIR
: _S_IFREG
;
2384 /* Not sure if there is any point in this. */
2385 if (!NILP (Vw32_generate_fake_inodes
))
2386 fake_inode
= generate_inode_val (name
);
2387 else if (fake_inode
== 0)
2389 /* For want of something better, try to make everything unique. */
2390 static DWORD gen_num
= 0;
2391 fake_inode
= ++gen_num
;
2395 /* MSVC defines _ino_t to be short; other libc's might not. */
2396 if (sizeof (buf
->st_ino
) == 2)
2397 buf
->st_ino
= fake_inode
^ (fake_inode
>> 16);
2399 buf
->st_ino
= fake_inode
;
2401 /* consider files to belong to current user */
2402 buf
->st_uid
= the_passwd
.pw_uid
;
2403 buf
->st_gid
= the_passwd
.pw_gid
;
2405 /* volume_info is set indirectly by map_w32_filename */
2406 buf
->st_dev
= volume_info
.serialnum
;
2407 buf
->st_rdev
= volume_info
.serialnum
;
2410 buf
->st_size
= wfd
.nFileSizeLow
;
2412 /* Convert timestamps to Unix format. */
2413 buf
->st_mtime
= convert_time (wfd
.ftLastWriteTime
);
2414 buf
->st_atime
= convert_time (wfd
.ftLastAccessTime
);
2415 if (buf
->st_atime
== 0) buf
->st_atime
= buf
->st_mtime
;
2416 buf
->st_ctime
= convert_time (wfd
.ftCreationTime
);
2417 if (buf
->st_ctime
== 0) buf
->st_ctime
= buf
->st_mtime
;
2419 /* determine rwx permissions */
2420 if (wfd
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
)
2421 permission
= _S_IREAD
;
2423 permission
= _S_IREAD
| _S_IWRITE
;
2425 if (wfd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
2426 permission
|= _S_IEXEC
;
2427 else if (is_exec (name
))
2428 permission
|= _S_IEXEC
;
2430 buf
->st_mode
|= permission
| (permission
>> 3) | (permission
>> 6);
2435 /* Provide fstat and utime as well as stat for consistent handling of
2438 fstat (int desc
, struct stat
* buf
)
2440 HANDLE fh
= (HANDLE
) _get_osfhandle (desc
);
2441 BY_HANDLE_FILE_INFORMATION info
;
2445 switch (GetFileType (fh
) & ~FILE_TYPE_REMOTE
)
2447 case FILE_TYPE_DISK
:
2448 buf
->st_mode
= _S_IFREG
;
2449 if (!GetFileInformationByHandle (fh
, &info
))
2455 case FILE_TYPE_PIPE
:
2456 buf
->st_mode
= _S_IFIFO
;
2458 case FILE_TYPE_CHAR
:
2459 case FILE_TYPE_UNKNOWN
:
2461 buf
->st_mode
= _S_IFCHR
;
2463 memset (&info
, 0, sizeof (info
));
2464 info
.dwFileAttributes
= 0;
2465 info
.ftCreationTime
= utc_base_ft
;
2466 info
.ftLastAccessTime
= utc_base_ft
;
2467 info
.ftLastWriteTime
= utc_base_ft
;
2470 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
2471 buf
->st_mode
= _S_IFDIR
;
2473 buf
->st_nlink
= info
.nNumberOfLinks
;
2474 /* Might as well use file index to fake inode values, but this
2475 is not guaranteed to be unique unless we keep a handle open
2476 all the time (even then there are situations where it is
2477 not unique). Reputedly, there are at most 48 bits of info
2478 (on NTFS, presumably less on FAT). */
2479 fake_inode
= info
.nFileIndexLow
^ info
.nFileIndexHigh
;
2481 /* MSVC defines _ino_t to be short; other libc's might not. */
2482 if (sizeof (buf
->st_ino
) == 2)
2483 buf
->st_ino
= fake_inode
^ (fake_inode
>> 16);
2485 buf
->st_ino
= fake_inode
;
2487 /* consider files to belong to current user */
2491 buf
->st_dev
= info
.dwVolumeSerialNumber
;
2492 buf
->st_rdev
= info
.dwVolumeSerialNumber
;
2494 buf
->st_size
= info
.nFileSizeLow
;
2496 /* Convert timestamps to Unix format. */
2497 buf
->st_mtime
= convert_time (info
.ftLastWriteTime
);
2498 buf
->st_atime
= convert_time (info
.ftLastAccessTime
);
2499 if (buf
->st_atime
== 0) buf
->st_atime
= buf
->st_mtime
;
2500 buf
->st_ctime
= convert_time (info
.ftCreationTime
);
2501 if (buf
->st_ctime
== 0) buf
->st_ctime
= buf
->st_mtime
;
2503 /* determine rwx permissions */
2504 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
)
2505 permission
= _S_IREAD
;
2507 permission
= _S_IREAD
| _S_IWRITE
;
2509 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
2510 permission
|= _S_IEXEC
;
2513 #if 0 /* no way of knowing the filename */
2514 char * p
= strrchr (name
, '.');
2516 (stricmp (p
, ".exe") == 0 ||
2517 stricmp (p
, ".com") == 0 ||
2518 stricmp (p
, ".bat") == 0 ||
2519 stricmp (p
, ".cmd") == 0))
2520 permission
|= _S_IEXEC
;
2524 buf
->st_mode
|= permission
| (permission
>> 3) | (permission
>> 6);
2530 utime (const char *name
, struct utimbuf
*times
)
2532 struct utimbuf deftime
;
2539 deftime
.modtime
= deftime
.actime
= time (NULL
);
2543 /* Need write access to set times. */
2544 fh
= CreateFile (name
, GENERIC_WRITE
, FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2545 0, OPEN_EXISTING
, 0, NULL
);
2548 convert_from_time_t (times
->actime
, &atime
);
2549 convert_from_time_t (times
->modtime
, &mtime
);
2550 if (!SetFileTime (fh
, NULL
, &atime
, &mtime
))
2568 /* Wrappers for winsock functions to map between our file descriptors
2569 and winsock's handles; also set h_errno for convenience.
2571 To allow Emacs to run on systems which don't have winsock support
2572 installed, we dynamically link to winsock on startup if present, and
2573 otherwise provide the minimum necessary functionality
2574 (eg. gethostname). */
2576 /* function pointers for relevant socket functions */
2577 int (PASCAL
*pfn_WSAStartup
) (WORD wVersionRequired
, LPWSADATA lpWSAData
);
2578 void (PASCAL
*pfn_WSASetLastError
) (int iError
);
2579 int (PASCAL
*pfn_WSAGetLastError
) (void);
2580 int (PASCAL
*pfn_socket
) (int af
, int type
, int protocol
);
2581 int (PASCAL
*pfn_bind
) (SOCKET s
, const struct sockaddr
*addr
, int namelen
);
2582 int (PASCAL
*pfn_connect
) (SOCKET s
, const struct sockaddr
*addr
, int namelen
);
2583 int (PASCAL
*pfn_ioctlsocket
) (SOCKET s
, long cmd
, u_long
*argp
);
2584 int (PASCAL
*pfn_recv
) (SOCKET s
, char * buf
, int len
, int flags
);
2585 int (PASCAL
*pfn_send
) (SOCKET s
, const char * buf
, int len
, int flags
);
2586 int (PASCAL
*pfn_closesocket
) (SOCKET s
);
2587 int (PASCAL
*pfn_shutdown
) (SOCKET s
, int how
);
2588 int (PASCAL
*pfn_WSACleanup
) (void);
2590 u_short (PASCAL
*pfn_htons
) (u_short hostshort
);
2591 u_short (PASCAL
*pfn_ntohs
) (u_short netshort
);
2592 unsigned long (PASCAL
*pfn_inet_addr
) (const char * cp
);
2593 int (PASCAL
*pfn_gethostname
) (char * name
, int namelen
);
2594 struct hostent
* (PASCAL
*pfn_gethostbyname
) (const char * name
);
2595 struct servent
* (PASCAL
*pfn_getservbyname
) (const char * name
, const char * proto
);
2596 int (PASCAL
*pfn_getpeername
) (SOCKET s
, struct sockaddr
*addr
, int * namelen
);
2597 int (PASCAL
*pfn_setsockopt
) (SOCKET s
, int level
, int optname
,
2598 const char * optval
, int optlen
);
2599 int (PASCAL
*pfn_listen
) (SOCKET s
, int backlog
);
2600 int (PASCAL
*pfn_getsockname
) (SOCKET s
, struct sockaddr
* name
,
2602 SOCKET (PASCAL
*pfn_accept
) (SOCKET s
, struct sockaddr
* addr
, int * addrlen
);
2603 int (PASCAL
*pfn_recvfrom
) (SOCKET s
, char * buf
, int len
, int flags
,
2604 struct sockaddr
* from
, int * fromlen
);
2605 int (PASCAL
*pfn_sendto
) (SOCKET s
, const char * buf
, int len
, int flags
,
2606 const struct sockaddr
* to
, int tolen
);
2608 /* SetHandleInformation is only needed to make sockets non-inheritable. */
2609 BOOL (WINAPI
*pfn_SetHandleInformation
) (HANDLE object
, DWORD mask
, DWORD flags
);
2610 #ifndef HANDLE_FLAG_INHERIT
2611 #define HANDLE_FLAG_INHERIT 1
2615 static int winsock_inuse
;
2620 if (winsock_lib
!= NULL
&& winsock_inuse
== 0)
2622 /* Not sure what would cause WSAENETDOWN, or even if it can happen
2623 after WSAStartup returns successfully, but it seems reasonable
2624 to allow unloading winsock anyway in that case. */
2625 if (pfn_WSACleanup () == 0 ||
2626 pfn_WSAGetLastError () == WSAENETDOWN
)
2628 if (FreeLibrary (winsock_lib
))
2637 init_winsock (int load_now
)
2639 WSADATA winsockData
;
2641 if (winsock_lib
!= NULL
)
2644 pfn_SetHandleInformation
= NULL
;
2645 pfn_SetHandleInformation
2646 = (void *) GetProcAddress (GetModuleHandle ("kernel32.dll"),
2647 "SetHandleInformation");
2649 winsock_lib
= LoadLibrary ("wsock32.dll");
2651 if (winsock_lib
!= NULL
)
2653 /* dynamically link to socket functions */
2655 #define LOAD_PROC(fn) \
2656 if ((pfn_##fn = (void *) GetProcAddress (winsock_lib, #fn)) == NULL) \
2659 LOAD_PROC( WSAStartup
);
2660 LOAD_PROC( WSASetLastError
);
2661 LOAD_PROC( WSAGetLastError
);
2662 LOAD_PROC( socket
);
2664 LOAD_PROC( connect
);
2665 LOAD_PROC( ioctlsocket
);
2668 LOAD_PROC( closesocket
);
2669 LOAD_PROC( shutdown
);
2672 LOAD_PROC( inet_addr
);
2673 LOAD_PROC( gethostname
);
2674 LOAD_PROC( gethostbyname
);
2675 LOAD_PROC( getservbyname
);
2676 LOAD_PROC( getpeername
);
2677 LOAD_PROC( WSACleanup
);
2678 LOAD_PROC( setsockopt
);
2679 LOAD_PROC( listen
);
2680 LOAD_PROC( getsockname
);
2681 LOAD_PROC( accept
);
2682 LOAD_PROC( recvfrom
);
2683 LOAD_PROC( sendto
);
2686 /* specify version 1.1 of winsock */
2687 if (pfn_WSAStartup (0x101, &winsockData
) == 0)
2689 if (winsockData
.wVersion
!= 0x101)
2694 /* Report that winsock exists and is usable, but leave
2695 socket functions disabled. I am assuming that calling
2696 WSAStartup does not require any network interaction,
2697 and in particular does not cause or require a dial-up
2698 connection to be established. */
2701 FreeLibrary (winsock_lib
);
2709 FreeLibrary (winsock_lib
);
2719 /* function to set h_errno for compatability; map winsock error codes to
2720 normal system codes where they overlap (non-overlapping definitions
2721 are already in <sys/socket.h> */
2722 static void set_errno ()
2724 if (winsock_lib
== NULL
)
2727 h_errno
= pfn_WSAGetLastError ();
2731 case WSAEACCES
: h_errno
= EACCES
; break;
2732 case WSAEBADF
: h_errno
= EBADF
; break;
2733 case WSAEFAULT
: h_errno
= EFAULT
; break;
2734 case WSAEINTR
: h_errno
= EINTR
; break;
2735 case WSAEINVAL
: h_errno
= EINVAL
; break;
2736 case WSAEMFILE
: h_errno
= EMFILE
; break;
2737 case WSAENAMETOOLONG
: h_errno
= ENAMETOOLONG
; break;
2738 case WSAENOTEMPTY
: h_errno
= ENOTEMPTY
; break;
2743 static void check_errno ()
2745 if (h_errno
== 0 && winsock_lib
!= NULL
)
2746 pfn_WSASetLastError (0);
2749 /* Extend strerror to handle the winsock-specific error codes. */
2753 } _wsa_errlist
[] = {
2754 WSAEINTR
, "Interrupted function call",
2755 WSAEBADF
, "Bad file descriptor",
2756 WSAEACCES
, "Permission denied",
2757 WSAEFAULT
, "Bad address",
2758 WSAEINVAL
, "Invalid argument",
2759 WSAEMFILE
, "Too many open files",
2761 WSAEWOULDBLOCK
, "Resource temporarily unavailable",
2762 WSAEINPROGRESS
, "Operation now in progress",
2763 WSAEALREADY
, "Operation already in progress",
2764 WSAENOTSOCK
, "Socket operation on non-socket",
2765 WSAEDESTADDRREQ
, "Destination address required",
2766 WSAEMSGSIZE
, "Message too long",
2767 WSAEPROTOTYPE
, "Protocol wrong type for socket",
2768 WSAENOPROTOOPT
, "Bad protocol option",
2769 WSAEPROTONOSUPPORT
, "Protocol not supported",
2770 WSAESOCKTNOSUPPORT
, "Socket type not supported",
2771 WSAEOPNOTSUPP
, "Operation not supported",
2772 WSAEPFNOSUPPORT
, "Protocol family not supported",
2773 WSAEAFNOSUPPORT
, "Address family not supported by protocol family",
2774 WSAEADDRINUSE
, "Address already in use",
2775 WSAEADDRNOTAVAIL
, "Cannot assign requested address",
2776 WSAENETDOWN
, "Network is down",
2777 WSAENETUNREACH
, "Network is unreachable",
2778 WSAENETRESET
, "Network dropped connection on reset",
2779 WSAECONNABORTED
, "Software caused connection abort",
2780 WSAECONNRESET
, "Connection reset by peer",
2781 WSAENOBUFS
, "No buffer space available",
2782 WSAEISCONN
, "Socket is already connected",
2783 WSAENOTCONN
, "Socket is not connected",
2784 WSAESHUTDOWN
, "Cannot send after socket shutdown",
2785 WSAETOOMANYREFS
, "Too many references", /* not sure */
2786 WSAETIMEDOUT
, "Connection timed out",
2787 WSAECONNREFUSED
, "Connection refused",
2788 WSAELOOP
, "Network loop", /* not sure */
2789 WSAENAMETOOLONG
, "Name is too long",
2790 WSAEHOSTDOWN
, "Host is down",
2791 WSAEHOSTUNREACH
, "No route to host",
2792 WSAENOTEMPTY
, "Buffer not empty", /* not sure */
2793 WSAEPROCLIM
, "Too many processes",
2794 WSAEUSERS
, "Too many users", /* not sure */
2795 WSAEDQUOT
, "Double quote in host name", /* really not sure */
2796 WSAESTALE
, "Data is stale", /* not sure */
2797 WSAEREMOTE
, "Remote error", /* not sure */
2799 WSASYSNOTREADY
, "Network subsystem is unavailable",
2800 WSAVERNOTSUPPORTED
, "WINSOCK.DLL version out of range",
2801 WSANOTINITIALISED
, "Winsock not initialized successfully",
2802 WSAEDISCON
, "Graceful shutdown in progress",
2804 WSAENOMORE
, "No more operations allowed", /* not sure */
2805 WSAECANCELLED
, "Operation cancelled", /* not sure */
2806 WSAEINVALIDPROCTABLE
, "Invalid procedure table from service provider",
2807 WSAEINVALIDPROVIDER
, "Invalid service provider version number",
2808 WSAEPROVIDERFAILEDINIT
, "Unable to initialize a service provider",
2809 WSASYSCALLFAILURE
, "System call failured",
2810 WSASERVICE_NOT_FOUND
, "Service not found", /* not sure */
2811 WSATYPE_NOT_FOUND
, "Class type not found",
2812 WSA_E_NO_MORE
, "No more resources available", /* really not sure */
2813 WSA_E_CANCELLED
, "Operation already cancelled", /* really not sure */
2814 WSAEREFUSED
, "Operation refused", /* not sure */
2817 WSAHOST_NOT_FOUND
, "Host not found",
2818 WSATRY_AGAIN
, "Authoritative host not found during name lookup",
2819 WSANO_RECOVERY
, "Non-recoverable error during name lookup",
2820 WSANO_DATA
, "Valid name, no data record of requested type",
2826 sys_strerror(int error_no
)
2829 static char unknown_msg
[40];
2831 if (error_no
>= 0 && error_no
< sys_nerr
)
2832 return sys_errlist
[error_no
];
2834 for (i
= 0; _wsa_errlist
[i
].errnum
>= 0; i
++)
2835 if (_wsa_errlist
[i
].errnum
== error_no
)
2836 return _wsa_errlist
[i
].msg
;
2838 sprintf(unknown_msg
, "Unidentified error: %d", error_no
);
2842 /* [andrewi 3-May-96] I've had conflicting results using both methods,
2843 but I believe the method of keeping the socket handle separate (and
2844 insuring it is not inheritable) is the correct one. */
2846 //#define SOCK_REPLACE_HANDLE
2848 #ifdef SOCK_REPLACE_HANDLE
2849 #define SOCK_HANDLE(fd) ((SOCKET) _get_osfhandle (fd))
2851 #define SOCK_HANDLE(fd) ((SOCKET) fd_info[fd].hnd)
2854 int socket_to_fd (SOCKET s
);
2857 sys_socket(int af
, int type
, int protocol
)
2861 if (winsock_lib
== NULL
)
2864 return INVALID_SOCKET
;
2869 /* call the real socket function */
2870 s
= pfn_socket (af
, type
, protocol
);
2872 if (s
!= INVALID_SOCKET
)
2873 return socket_to_fd (s
);
2879 /* Convert a SOCKET to a file descriptor. */
2881 socket_to_fd (SOCKET s
)
2886 /* Although under NT 3.5 _open_osfhandle will accept a socket
2887 handle, if opened with SO_OPENTYPE == SO_SYNCHRONOUS_NONALERT,
2888 that does not work under NT 3.1. However, we can get the same
2889 effect by using a backdoor function to replace an existing
2890 descriptor handle with the one we want. */
2892 /* allocate a file descriptor (with appropriate flags) */
2893 fd
= _open ("NUL:", _O_RDWR
);
2896 #ifdef SOCK_REPLACE_HANDLE
2897 /* now replace handle to NUL with our socket handle */
2898 CloseHandle ((HANDLE
) _get_osfhandle (fd
));
2900 _set_osfhnd (fd
, s
);
2901 /* setmode (fd, _O_BINARY); */
2903 /* Make a non-inheritable copy of the socket handle. Note
2904 that it is possible that sockets aren't actually kernel
2905 handles, which appears to be the case on Windows 9x when
2906 the MS Proxy winsock client is installed. */
2908 /* Apparently there is a bug in NT 3.51 with some service
2909 packs, which prevents using DuplicateHandle to make a
2910 socket handle non-inheritable (causes WSACleanup to
2911 hang). The work-around is to use SetHandleInformation
2912 instead if it is available and implemented. */
2913 if (pfn_SetHandleInformation
)
2915 pfn_SetHandleInformation ((HANDLE
) s
, HANDLE_FLAG_INHERIT
, 0);
2919 HANDLE parent
= GetCurrentProcess ();
2920 HANDLE new_s
= INVALID_HANDLE_VALUE
;
2922 if (DuplicateHandle (parent
,
2928 DUPLICATE_SAME_ACCESS
))
2930 /* It is possible that DuplicateHandle succeeds even
2931 though the socket wasn't really a kernel handle,
2932 because a real handle has the same value. So
2933 test whether the new handle really is a socket. */
2934 long nonblocking
= 0;
2935 if (pfn_ioctlsocket ((SOCKET
) new_s
, FIONBIO
, &nonblocking
) == 0)
2937 pfn_closesocket (s
);
2942 CloseHandle (new_s
);
2947 fd_info
[fd
].hnd
= (HANDLE
) s
;
2950 /* set our own internal flags */
2951 fd_info
[fd
].flags
= FILE_SOCKET
| FILE_BINARY
| FILE_READ
| FILE_WRITE
;
2957 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
2959 /* attach child_process to fd_info */
2960 if (fd_info
[ fd
].cp
!= NULL
)
2962 DebPrint (("sys_socket: fd_info[%d] apparently in use!\n", fd
));
2966 fd_info
[ fd
].cp
= cp
;
2969 winsock_inuse
++; /* count open sockets */
2976 pfn_closesocket (s
);
2983 sys_bind (int s
, const struct sockaddr
* addr
, int namelen
)
2985 if (winsock_lib
== NULL
)
2988 return SOCKET_ERROR
;
2992 if (fd_info
[s
].flags
& FILE_SOCKET
)
2994 int rc
= pfn_bind (SOCK_HANDLE (s
), addr
, namelen
);
2995 if (rc
== SOCKET_ERROR
)
3000 return SOCKET_ERROR
;
3005 sys_connect (int s
, const struct sockaddr
* name
, int namelen
)
3007 if (winsock_lib
== NULL
)
3010 return SOCKET_ERROR
;
3014 if (fd_info
[s
].flags
& FILE_SOCKET
)
3016 int rc
= pfn_connect (SOCK_HANDLE (s
), name
, namelen
);
3017 if (rc
== SOCKET_ERROR
)
3022 return SOCKET_ERROR
;
3026 sys_htons (u_short hostshort
)
3028 return (winsock_lib
!= NULL
) ?
3029 pfn_htons (hostshort
) : hostshort
;
3033 sys_ntohs (u_short netshort
)
3035 return (winsock_lib
!= NULL
) ?
3036 pfn_ntohs (netshort
) : netshort
;
3040 sys_inet_addr (const char * cp
)
3042 return (winsock_lib
!= NULL
) ?
3043 pfn_inet_addr (cp
) : INADDR_NONE
;
3047 sys_gethostname (char * name
, int namelen
)
3049 if (winsock_lib
!= NULL
)
3050 return pfn_gethostname (name
, namelen
);
3052 if (namelen
> MAX_COMPUTERNAME_LENGTH
)
3053 return !GetComputerName (name
, (DWORD
*)&namelen
);
3056 return SOCKET_ERROR
;
3060 sys_gethostbyname(const char * name
)
3062 struct hostent
* host
;
3064 if (winsock_lib
== NULL
)
3071 host
= pfn_gethostbyname (name
);
3078 sys_getservbyname(const char * name
, const char * proto
)
3080 struct servent
* serv
;
3082 if (winsock_lib
== NULL
)
3089 serv
= pfn_getservbyname (name
, proto
);
3096 sys_getpeername (int s
, struct sockaddr
*addr
, int * namelen
)
3098 if (winsock_lib
== NULL
)
3101 return SOCKET_ERROR
;
3105 if (fd_info
[s
].flags
& FILE_SOCKET
)
3107 int rc
= pfn_getpeername (SOCK_HANDLE (s
), addr
, namelen
);
3108 if (rc
== SOCKET_ERROR
)
3113 return SOCKET_ERROR
;
3118 sys_shutdown (int s
, int how
)
3120 if (winsock_lib
== NULL
)
3123 return SOCKET_ERROR
;
3127 if (fd_info
[s
].flags
& FILE_SOCKET
)
3129 int rc
= pfn_shutdown (SOCK_HANDLE (s
), how
);
3130 if (rc
== SOCKET_ERROR
)
3135 return SOCKET_ERROR
;
3139 sys_setsockopt (int s
, int level
, int optname
, const char * optval
, int optlen
)
3141 if (winsock_lib
== NULL
)
3144 return SOCKET_ERROR
;
3148 if (fd_info
[s
].flags
& FILE_SOCKET
)
3150 int rc
= pfn_setsockopt (SOCK_HANDLE (s
), level
, optname
,
3152 if (rc
== SOCKET_ERROR
)
3157 return SOCKET_ERROR
;
3161 sys_listen (int s
, int backlog
)
3163 if (winsock_lib
== NULL
)
3166 return SOCKET_ERROR
;
3170 if (fd_info
[s
].flags
& FILE_SOCKET
)
3172 int rc
= pfn_listen (SOCK_HANDLE (s
), backlog
);
3173 if (rc
== SOCKET_ERROR
)
3178 return SOCKET_ERROR
;
3182 sys_getsockname (int s
, struct sockaddr
* name
, int * namelen
)
3184 if (winsock_lib
== NULL
)
3187 return SOCKET_ERROR
;
3191 if (fd_info
[s
].flags
& FILE_SOCKET
)
3193 int rc
= pfn_getsockname (SOCK_HANDLE (s
), name
, namelen
);
3194 if (rc
== SOCKET_ERROR
)
3199 return SOCKET_ERROR
;
3203 sys_accept (int s
, struct sockaddr
* addr
, int * addrlen
)
3205 if (winsock_lib
== NULL
)
3212 if (fd_info
[s
].flags
& FILE_SOCKET
)
3214 SOCKET t
= pfn_accept (SOCK_HANDLE (s
), addr
, addrlen
);
3215 if (t
!= INVALID_SOCKET
)
3216 return socket_to_fd (t
);
3226 sys_recvfrom (int s
, char * buf
, int len
, int flags
,
3227 struct sockaddr
* from
, int * fromlen
)
3229 if (winsock_lib
== NULL
)
3232 return SOCKET_ERROR
;
3236 if (fd_info
[s
].flags
& FILE_SOCKET
)
3238 int rc
= pfn_recvfrom (SOCK_HANDLE (s
), buf
, len
, flags
, from
, fromlen
);
3239 if (rc
== SOCKET_ERROR
)
3244 return SOCKET_ERROR
;
3248 sys_sendto (int s
, const char * buf
, int len
, int flags
,
3249 const struct sockaddr
* to
, int tolen
)
3251 if (winsock_lib
== NULL
)
3254 return SOCKET_ERROR
;
3258 if (fd_info
[s
].flags
& FILE_SOCKET
)
3260 int rc
= pfn_sendto (SOCK_HANDLE (s
), buf
, len
, flags
, to
, tolen
);
3261 if (rc
== SOCKET_ERROR
)
3266 return SOCKET_ERROR
;
3269 /* Windows does not have an fcntl function. Provide an implementation
3270 solely for making sockets non-blocking. */
3272 fcntl (int s
, int cmd
, int options
)
3274 if (winsock_lib
== NULL
)
3281 if (fd_info
[s
].flags
& FILE_SOCKET
)
3283 if (cmd
== F_SETFL
&& options
== O_NDELAY
)
3285 unsigned long nblock
= 1;
3286 int rc
= pfn_ioctlsocket (SOCK_HANDLE (s
), FIONBIO
, &nblock
);
3287 if (rc
== SOCKET_ERROR
)
3289 /* Keep track of the fact that we set this to non-blocking. */
3290 fd_info
[s
].flags
|= FILE_NDELAY
;
3296 return SOCKET_ERROR
;
3300 return SOCKET_ERROR
;
3303 #endif /* HAVE_SOCKETS */
3306 /* Shadow main io functions: we need to handle pipes and sockets more
3307 intelligently, and implement non-blocking mode as well. */
3314 if (fd
< 0 || fd
>= MAXDESC
)
3322 child_process
* cp
= fd_info
[fd
].cp
;
3324 fd_info
[fd
].cp
= NULL
;
3326 if (CHILD_ACTIVE (cp
))
3328 /* if last descriptor to active child_process then cleanup */
3330 for (i
= 0; i
< MAXDESC
; i
++)
3334 if (fd_info
[i
].cp
== cp
)
3340 if (fd_info
[fd
].flags
& FILE_SOCKET
)
3342 #ifndef SOCK_REPLACE_HANDLE
3343 if (winsock_lib
== NULL
) abort ();
3345 pfn_shutdown (SOCK_HANDLE (fd
), 2);
3346 rc
= pfn_closesocket (SOCK_HANDLE (fd
));
3348 winsock_inuse
--; /* count open sockets */
3356 /* Note that sockets do not need special treatment here (at least on
3357 NT and Windows 95 using the standard tcp/ip stacks) - it appears that
3358 closesocket is equivalent to CloseHandle, which is to be expected
3359 because socket handles are fully fledged kernel handles. */
3363 fd_info
[fd
].flags
= 0;
3376 /* duplicate our internal info as well */
3377 fd_info
[new_fd
] = fd_info
[fd
];
3384 sys_dup2 (int src
, int dst
)
3388 if (dst
< 0 || dst
>= MAXDESC
)
3394 /* make sure we close the destination first if it's a pipe or socket */
3395 if (src
!= dst
&& fd_info
[dst
].flags
!= 0)
3398 rc
= _dup2 (src
, dst
);
3401 /* duplicate our internal info as well */
3402 fd_info
[dst
] = fd_info
[src
];
3407 /* Unix pipe() has only one arg */
3409 sys_pipe (int * phandles
)
3414 /* make pipe handles non-inheritable; when we spawn a child, we
3415 replace the relevant handle with an inheritable one. Also put
3416 pipes into binary mode; we will do text mode translation ourselves
3418 rc
= _pipe (phandles
, 0, _O_NOINHERIT
| _O_BINARY
);
3422 flags
= FILE_PIPE
| FILE_READ
| FILE_BINARY
;
3423 fd_info
[phandles
[0]].flags
= flags
;
3425 flags
= FILE_PIPE
| FILE_WRITE
| FILE_BINARY
;
3426 fd_info
[phandles
[1]].flags
= flags
;
3433 extern Lisp_Object Vw32_pipe_read_delay
;
3435 /* Function to do blocking read of one byte, needed to implement
3436 select. It is only allowed on sockets and pipes. */
3438 _sys_read_ahead (int fd
)
3443 if (fd
< 0 || fd
>= MAXDESC
)
3444 return STATUS_READ_ERROR
;
3446 cp
= fd_info
[fd
].cp
;
3448 if (cp
== NULL
|| cp
->fd
!= fd
|| cp
->status
!= STATUS_READ_READY
)
3449 return STATUS_READ_ERROR
;
3451 if ((fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SOCKET
)) == 0
3452 || (fd_info
[fd
].flags
& FILE_READ
) == 0)
3454 DebPrint (("_sys_read_ahead: internal error: fd %d is not a pipe or socket!\n", fd
));
3458 cp
->status
= STATUS_READ_IN_PROGRESS
;
3460 if (fd_info
[fd
].flags
& FILE_PIPE
)
3462 rc
= _read (fd
, &cp
->chr
, sizeof (char));
3464 /* Give subprocess time to buffer some more output for us before
3465 reporting that input is available; we need this because Windows 95
3466 connects DOS programs to pipes by making the pipe appear to be
3467 the normal console stdout - as a result most DOS programs will
3468 write to stdout without buffering, ie. one character at a
3469 time. Even some W32 programs do this - "dir" in a command
3470 shell on NT is very slow if we don't do this. */
3473 int wait
= XINT (Vw32_pipe_read_delay
);
3479 /* Yield remainder of our time slice, effectively giving a
3480 temporary priority boost to the child process. */
3485 else if (fd_info
[fd
].flags
& FILE_SOCKET
)
3487 unsigned long nblock
= 0;
3488 /* We always want this to block, so temporarily disable NDELAY. */
3489 if (fd_info
[fd
].flags
& FILE_NDELAY
)
3490 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
3492 rc
= pfn_recv (SOCK_HANDLE (fd
), &cp
->chr
, sizeof (char), 0);
3494 if (fd_info
[fd
].flags
& FILE_NDELAY
)
3497 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
3502 if (rc
== sizeof (char))
3503 cp
->status
= STATUS_READ_SUCCEEDED
;
3505 cp
->status
= STATUS_READ_FAILED
;
3511 sys_read (int fd
, char * buffer
, unsigned int count
)
3516 char * orig_buffer
= buffer
;
3518 if (fd
< 0 || fd
>= MAXDESC
)
3524 if (fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SOCKET
))
3526 child_process
*cp
= fd_info
[fd
].cp
;
3528 if ((fd_info
[fd
].flags
& FILE_READ
) == 0)
3536 /* re-read CR carried over from last read */
3537 if (fd_info
[fd
].flags
& FILE_LAST_CR
)
3539 if (fd_info
[fd
].flags
& FILE_BINARY
) abort ();
3543 fd_info
[fd
].flags
&= ~FILE_LAST_CR
;
3546 /* presence of a child_process structure means we are operating in
3547 non-blocking mode - otherwise we just call _read directly.
3548 Note that the child_process structure might be missing because
3549 reap_subprocess has been called; in this case the pipe is
3550 already broken, so calling _read on it is okay. */
3553 int current_status
= cp
->status
;
3555 switch (current_status
)
3557 case STATUS_READ_FAILED
:
3558 case STATUS_READ_ERROR
:
3559 /* report normal EOF if nothing in buffer */
3561 fd_info
[fd
].flags
|= FILE_AT_EOF
;
3564 case STATUS_READ_READY
:
3565 case STATUS_READ_IN_PROGRESS
:
3566 DebPrint (("sys_read called when read is in progress\n"));
3567 errno
= EWOULDBLOCK
;
3570 case STATUS_READ_SUCCEEDED
:
3571 /* consume read-ahead char */
3572 *buffer
++ = cp
->chr
;
3575 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
3576 ResetEvent (cp
->char_avail
);
3578 case STATUS_READ_ACKNOWLEDGED
:
3582 DebPrint (("sys_read: bad status %d\n", current_status
));
3587 if (fd_info
[fd
].flags
& FILE_PIPE
)
3589 PeekNamedPipe ((HANDLE
) _get_osfhandle (fd
), NULL
, 0, NULL
, &waiting
, NULL
);
3590 to_read
= min (waiting
, (DWORD
) count
);
3593 nchars
+= _read (fd
, buffer
, to_read
);
3596 else /* FILE_SOCKET */
3598 if (winsock_lib
== NULL
) abort ();
3600 /* do the equivalent of a non-blocking read */
3601 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONREAD
, &waiting
);
3602 if (waiting
== 0 && nchars
== 0)
3604 h_errno
= errno
= EWOULDBLOCK
;
3610 /* always use binary mode for sockets */
3611 int res
= pfn_recv (SOCK_HANDLE (fd
), buffer
, count
, 0);
3612 if (res
== SOCKET_ERROR
)
3614 DebPrint(("sys_read.recv failed with error %d on socket %ld\n",
3615 pfn_WSAGetLastError (), SOCK_HANDLE (fd
)));
3626 int nread
= _read (fd
, buffer
, count
);
3629 else if (nchars
== 0)
3634 fd_info
[fd
].flags
|= FILE_AT_EOF
;
3635 /* Perform text mode translation if required. */
3636 else if ((fd_info
[fd
].flags
& FILE_BINARY
) == 0)
3638 nchars
= crlf_to_lf (nchars
, orig_buffer
);
3639 /* If buffer contains only CR, return that. To be absolutely
3640 sure we should attempt to read the next char, but in
3641 practice a CR to be followed by LF would not appear by
3642 itself in the buffer. */
3643 if (nchars
> 1 && orig_buffer
[nchars
- 1] == 0x0d)
3645 fd_info
[fd
].flags
|= FILE_LAST_CR
;
3651 nchars
= _read (fd
, buffer
, count
);
3656 /* For now, don't bother with a non-blocking mode */
3658 sys_write (int fd
, const void * buffer
, unsigned int count
)
3662 if (fd
< 0 || fd
>= MAXDESC
)
3668 if (fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SOCKET
))
3670 if ((fd_info
[fd
].flags
& FILE_WRITE
) == 0)
3676 /* Perform text mode translation if required. */
3677 if ((fd_info
[fd
].flags
& FILE_BINARY
) == 0)
3679 char * tmpbuf
= alloca (count
* 2);
3680 unsigned char * src
= (void *)buffer
;
3681 unsigned char * dst
= tmpbuf
;
3686 unsigned char *next
;
3687 /* copy next line or remaining bytes */
3688 next
= _memccpy (dst
, src
, '\n', nbytes
);
3691 /* copied one line ending with '\n' */
3692 int copied
= next
- dst
;
3695 /* insert '\r' before '\n' */
3702 /* copied remaining partial line -> now finished */
3710 if (fd_info
[fd
].flags
& FILE_SOCKET
)
3712 if (winsock_lib
== NULL
) abort ();
3713 nchars
= pfn_send (SOCK_HANDLE (fd
), buffer
, count
, 0);
3714 if (nchars
== SOCKET_ERROR
)
3716 DebPrint(("sys_read.send failed with error %d on socket %ld\n",
3717 pfn_WSAGetLastError (), SOCK_HANDLE (fd
)));
3723 nchars
= _write (fd
, buffer
, count
);
3729 check_windows_init_file ()
3731 extern int noninteractive
, inhibit_window_system
;
3733 /* A common indication that Emacs is not installed properly is when
3734 it cannot find the Windows installation file. If this file does
3735 not exist in the expected place, tell the user. */
3737 if (!noninteractive
&& !inhibit_window_system
)
3739 extern Lisp_Object Vwindow_system
, Vload_path
, Qfile_exists_p
;
3740 Lisp_Object objs
[2];
3741 Lisp_Object full_load_path
;
3742 Lisp_Object init_file
;
3745 objs
[0] = Vload_path
;
3746 objs
[1] = decode_env_path (0, (getenv ("EMACSLOADPATH")));
3747 full_load_path
= Fappend (2, objs
);
3748 init_file
= build_string ("term/w32-win");
3749 fd
= openp (full_load_path
, init_file
, Vload_suffixes
, NULL
, Qnil
);
3752 Lisp_Object load_path_print
= Fprin1_to_string (full_load_path
, Qnil
);
3753 char *init_file_name
= SDATA (init_file
);
3754 char *load_path
= SDATA (load_path_print
);
3755 char *buffer
= alloca (1024);
3758 "The Emacs Windows initialization file \"%s.el\" "
3759 "could not be found in your Emacs installation. "
3760 "Emacs checked the following directories for this file:\n"
3762 "When Emacs cannot find this file, it usually means that it "
3763 "was not installed properly, or its distribution file was "
3764 "not unpacked properly.\nSee the README.W32 file in the "
3765 "top-level Emacs directory for more information.",
3766 init_file_name
, load_path
);
3769 "Emacs Abort Dialog",
3770 MB_OK
| MB_ICONEXCLAMATION
| MB_TASKMODAL
);
3771 /* Use the low-level Emacs abort. */
3786 /* shutdown the socket interface if necessary */
3795 /* Initialise the socket interface now if available and requested by
3796 the user by defining PRELOAD_WINSOCK; otherwise loading will be
3797 delayed until open-network-stream is called (w32-has-winsock can
3798 also be used to dynamically load or reload winsock).
3800 Conveniently, init_environment is called before us, so
3801 PRELOAD_WINSOCK can be set in the registry. */
3803 /* Always initialize this correctly. */
3806 if (getenv ("PRELOAD_WINSOCK") != NULL
)
3807 init_winsock (TRUE
);
3810 /* Initial preparation for subprocess support: replace our standard
3811 handles with non-inheritable versions. */
3814 HANDLE stdin_save
= INVALID_HANDLE_VALUE
;
3815 HANDLE stdout_save
= INVALID_HANDLE_VALUE
;
3816 HANDLE stderr_save
= INVALID_HANDLE_VALUE
;
3818 parent
= GetCurrentProcess ();
3820 /* ignore errors when duplicating and closing; typically the
3821 handles will be invalid when running as a gui program. */
3822 DuplicateHandle (parent
,
3823 GetStdHandle (STD_INPUT_HANDLE
),
3828 DUPLICATE_SAME_ACCESS
);
3830 DuplicateHandle (parent
,
3831 GetStdHandle (STD_OUTPUT_HANDLE
),
3836 DUPLICATE_SAME_ACCESS
);
3838 DuplicateHandle (parent
,
3839 GetStdHandle (STD_ERROR_HANDLE
),
3844 DUPLICATE_SAME_ACCESS
);
3850 if (stdin_save
!= INVALID_HANDLE_VALUE
)
3851 _open_osfhandle ((long) stdin_save
, O_TEXT
);
3853 _open ("nul", O_TEXT
| O_NOINHERIT
| O_RDONLY
);
3856 if (stdout_save
!= INVALID_HANDLE_VALUE
)
3857 _open_osfhandle ((long) stdout_save
, O_TEXT
);
3859 _open ("nul", O_TEXT
| O_NOINHERIT
| O_WRONLY
);
3862 if (stderr_save
!= INVALID_HANDLE_VALUE
)
3863 _open_osfhandle ((long) stderr_save
, O_TEXT
);
3865 _open ("nul", O_TEXT
| O_NOINHERIT
| O_WRONLY
);
3869 /* unfortunately, atexit depends on implementation of malloc */
3870 /* atexit (term_ntproc); */
3871 signal (SIGABRT
, term_ntproc
);
3873 /* determine which drives are fixed, for GetCachedVolumeInformation */
3875 /* GetDriveType must have trailing backslash. */
3876 char drive
[] = "A:\\";
3878 /* Loop over all possible drive letters */
3879 while (*drive
<= 'Z')
3881 /* Record if this drive letter refers to a fixed drive. */
3882 fixed_drives
[DRIVE_INDEX (*drive
)] =
3883 (GetDriveType (drive
) == DRIVE_FIXED
);
3888 /* Reset the volume info cache. */
3889 volume_cache
= NULL
;
3892 /* Check to see if Emacs has been installed correctly. */
3893 check_windows_init_file ();