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 */
72 #define _ANONYMOUS_UNION
73 #define _ANONYMOUS_STRUCT
77 #ifdef HAVE_SOCKETS /* TCP connection support, if kernel can do it */
78 #include <sys/socket.h>
103 void globals_of_w32 ();
105 extern Lisp_Object Vw32_downcase_file_names
;
106 extern Lisp_Object Vw32_generate_fake_inodes
;
107 extern Lisp_Object Vw32_get_true_file_attributes
;
108 extern int w32_num_mouse_buttons
;
112 Initialization states
114 static BOOL g_b_init_is_windows_9x
;
115 static BOOL g_b_init_open_process_token
;
116 static BOOL g_b_init_get_token_information
;
117 static BOOL g_b_init_lookup_account_sid
;
118 static BOOL g_b_init_get_sid_identifier_authority
;
121 BEGIN: Wrapper functions around OpenProcessToken
122 and other functions in advapi32.dll that are only
123 supported in Windows NT / 2k / XP
125 /* ** Function pointer typedefs ** */
126 typedef BOOL (WINAPI
* OpenProcessToken_Proc
) (
127 HANDLE ProcessHandle
,
129 PHANDLE TokenHandle
);
130 typedef BOOL (WINAPI
* GetTokenInformation_Proc
) (
132 TOKEN_INFORMATION_CLASS TokenInformationClass
,
133 LPVOID TokenInformation
,
134 DWORD TokenInformationLength
,
135 PDWORD ReturnLength
);
137 const char * const LookupAccountSid_Name
= "LookupAccountSidW";
139 const char * const LookupAccountSid_Name
= "LookupAccountSidA";
141 typedef BOOL (WINAPI
* LookupAccountSid_Proc
) (
142 LPCTSTR lpSystemName
,
147 LPDWORD cbDomainName
,
148 PSID_NAME_USE peUse
);
149 typedef PSID_IDENTIFIER_AUTHORITY (WINAPI
* GetSidIdentifierAuthority_Proc
) (
152 /* ** A utility function ** */
153 static BOOL
is_windows_9x ()
155 static BOOL s_b_ret
=0;
156 OSVERSIONINFO os_ver
;
157 if (g_b_init_is_windows_9x
== 0)
159 g_b_init_is_windows_9x
= 1;
160 ZeroMemory(&os_ver
, sizeof(OSVERSIONINFO
));
161 os_ver
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
162 if (GetVersionEx (&os_ver
))
164 s_b_ret
= (os_ver
.dwPlatformId
== VER_PLATFORM_WIN32_WINDOWS
);
170 /* ** The wrapper functions ** */
172 BOOL WINAPI
open_process_token (
173 HANDLE ProcessHandle
,
177 static OpenProcessToken_Proc s_pfn_Open_Process_Token
= NULL
;
178 HMODULE hm_advapi32
= NULL
;
179 if (is_windows_9x () == TRUE
)
183 if (g_b_init_open_process_token
== 0)
185 g_b_init_open_process_token
= 1;
186 hm_advapi32
= LoadLibrary ("Advapi32.dll");
187 s_pfn_Open_Process_Token
=
188 (OpenProcessToken_Proc
) GetProcAddress (hm_advapi32
, "OpenProcessToken");
190 if (s_pfn_Open_Process_Token
== NULL
)
195 s_pfn_Open_Process_Token (
202 BOOL WINAPI
get_token_information (
204 TOKEN_INFORMATION_CLASS TokenInformationClass
,
205 LPVOID TokenInformation
,
206 DWORD TokenInformationLength
,
209 static GetTokenInformation_Proc s_pfn_Get_Token_Information
= NULL
;
210 HMODULE hm_advapi32
= NULL
;
211 if (is_windows_9x () == TRUE
)
215 if (g_b_init_get_token_information
== 0)
217 g_b_init_get_token_information
= 1;
218 hm_advapi32
= LoadLibrary ("Advapi32.dll");
219 s_pfn_Get_Token_Information
=
220 (GetTokenInformation_Proc
) GetProcAddress (hm_advapi32
, "GetTokenInformation");
222 if (s_pfn_Get_Token_Information
== NULL
)
227 s_pfn_Get_Token_Information (
229 TokenInformationClass
,
231 TokenInformationLength
,
236 BOOL WINAPI
lookup_account_sid (
237 LPCTSTR lpSystemName
,
242 LPDWORD cbDomainName
,
245 static LookupAccountSid_Proc s_pfn_Lookup_Account_Sid
= NULL
;
246 HMODULE hm_advapi32
= NULL
;
247 if (is_windows_9x () == TRUE
)
251 if (g_b_init_lookup_account_sid
== 0)
253 g_b_init_lookup_account_sid
= 1;
254 hm_advapi32
= LoadLibrary ("Advapi32.dll");
255 s_pfn_Lookup_Account_Sid
=
256 (LookupAccountSid_Proc
) GetProcAddress (hm_advapi32
, LookupAccountSid_Name
);
258 if (s_pfn_Lookup_Account_Sid
== NULL
)
263 s_pfn_Lookup_Account_Sid (
274 PSID_IDENTIFIER_AUTHORITY WINAPI
get_sid_identifier_authority (
277 static GetSidIdentifierAuthority_Proc s_pfn_Get_Sid_Identifier_Authority
= NULL
;
278 HMODULE hm_advapi32
= NULL
;
279 if (is_windows_9x () == TRUE
)
283 if (g_b_init_get_sid_identifier_authority
== 0)
285 g_b_init_get_sid_identifier_authority
= 1;
286 hm_advapi32
= LoadLibrary ("Advapi32.dll");
287 s_pfn_Get_Sid_Identifier_Authority
=
288 (GetSidIdentifierAuthority_Proc
) GetProcAddress (
289 hm_advapi32
, "GetSidIdentifierAuthority");
291 if (s_pfn_Get_Sid_Identifier_Authority
== NULL
)
295 return (s_pfn_Get_Sid_Identifier_Authority (pSid
));
299 END: Wrapper functions around OpenProcessToken
300 and other functions in advapi32.dll that are only
301 supported in Windows NT / 2k / XP
305 /* Equivalent of strerror for W32 error codes. */
307 w32_strerror (int error_no
)
309 static char buf
[500];
312 error_no
= GetLastError ();
315 if (!FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM
, NULL
,
317 0, /* choose most suitable language */
318 buf
, sizeof (buf
), NULL
))
319 sprintf (buf
, "w32 error %u", error_no
);
323 static char startup_dir
[MAXPATHLEN
];
325 /* Get the current working directory. */
330 if (GetCurrentDirectory (MAXPATHLEN
, dir
) > 0)
334 /* Emacs doesn't actually change directory itself, and we want to
335 force our real wd to be where emacs.exe is to avoid unnecessary
336 conflicts when trying to rename or delete directories. */
337 strcpy (dir
, startup_dir
);
343 /* Emulate gethostname. */
345 gethostname (char *buffer
, int size
)
347 /* NT only allows small host names, so the buffer is
348 certainly large enough. */
349 return !GetComputerName (buffer
, &size
);
351 #endif /* HAVE_SOCKETS */
353 /* Emulate getloadavg. */
355 getloadavg (double loadavg
[], int nelem
)
359 /* A faithful emulation is going to have to be saved for a rainy day. */
360 for (i
= 0; i
< nelem
; i
++)
367 /* Emulate getpwuid, getpwnam and others. */
369 #define PASSWD_FIELD_SIZE 256
371 static char the_passwd_name
[PASSWD_FIELD_SIZE
];
372 static char the_passwd_passwd
[PASSWD_FIELD_SIZE
];
373 static char the_passwd_gecos
[PASSWD_FIELD_SIZE
];
374 static char the_passwd_dir
[PASSWD_FIELD_SIZE
];
375 static char the_passwd_shell
[PASSWD_FIELD_SIZE
];
377 static struct passwd the_passwd
=
389 static struct group the_group
=
391 /* There are no groups on NT, so we just return "root" as the
399 return the_passwd
.pw_uid
;
405 /* I could imagine arguing for checking to see whether the user is
406 in the Administrators group and returning a UID of 0 for that
407 case, but I don't know how wise that would be in the long run. */
414 return the_passwd
.pw_gid
;
426 if (uid
== the_passwd
.pw_uid
)
438 getpwnam (char *name
)
442 pw
= getpwuid (getuid ());
446 if (stricmp (name
, pw
->pw_name
))
455 /* Find the user's real name by opening the process token and
456 looking up the name associated with the user-sid in that token.
458 Use the relative portion of the identifier authority value from
459 the user-sid as the user id value (same for group id using the
460 primary group sid from the process token). */
462 char user_sid
[256], name
[256], domain
[256];
463 DWORD length
= sizeof (name
), dlength
= sizeof (domain
), trash
;
465 SID_NAME_USE user_type
;
468 open_process_token (GetCurrentProcess (), TOKEN_QUERY
, &token
)
469 && get_token_information (
471 (PVOID
) user_sid
, sizeof (user_sid
), &trash
)
472 && lookup_account_sid (
473 NULL
, *((PSID
*) user_sid
), name
, &length
,
474 domain
, &dlength
, &user_type
)
477 strcpy (the_passwd
.pw_name
, name
);
478 /* Determine a reasonable uid value. */
479 if (stricmp ("administrator", name
) == 0)
481 the_passwd
.pw_uid
= 0;
482 the_passwd
.pw_gid
= 0;
486 SID_IDENTIFIER_AUTHORITY
* pSIA
;
488 pSIA
= get_sid_identifier_authority (*((PSID
*) user_sid
));
489 /* I believe the relative portion is the last 4 bytes (of 6)
491 the_passwd
.pw_uid
= ((pSIA
->Value
[2] << 24) +
492 (pSIA
->Value
[3] << 16) +
493 (pSIA
->Value
[4] << 8) +
494 (pSIA
->Value
[5] << 0));
495 /* restrict to conventional uid range for normal users */
496 the_passwd
.pw_uid
= the_passwd
.pw_uid
% 60001;
499 if (get_token_information (token
, TokenPrimaryGroup
,
500 (PVOID
) user_sid
, sizeof (user_sid
), &trash
))
502 SID_IDENTIFIER_AUTHORITY
* pSIA
;
504 pSIA
= get_sid_identifier_authority (*((PSID
*) user_sid
));
505 the_passwd
.pw_gid
= ((pSIA
->Value
[2] << 24) +
506 (pSIA
->Value
[3] << 16) +
507 (pSIA
->Value
[4] << 8) +
508 (pSIA
->Value
[5] << 0));
509 /* I don't know if this is necessary, but for safety... */
510 the_passwd
.pw_gid
= the_passwd
.pw_gid
% 60001;
513 the_passwd
.pw_gid
= the_passwd
.pw_uid
;
516 /* If security calls are not supported (presumably because we
517 are running under Windows 95), fallback to this. */
518 else if (GetUserName (name
, &length
))
520 strcpy (the_passwd
.pw_name
, name
);
521 if (stricmp ("administrator", name
) == 0)
522 the_passwd
.pw_uid
= 0;
524 the_passwd
.pw_uid
= 123;
525 the_passwd
.pw_gid
= the_passwd
.pw_uid
;
529 strcpy (the_passwd
.pw_name
, "unknown");
530 the_passwd
.pw_uid
= 123;
531 the_passwd
.pw_gid
= 123;
534 /* Ensure HOME and SHELL are defined. */
535 if (getenv ("HOME") == NULL
)
537 if (getenv ("SHELL") == NULL
)
540 /* Set dir and shell from environment variables. */
541 strcpy (the_passwd
.pw_dir
, getenv ("HOME"));
542 strcpy (the_passwd
.pw_shell
, getenv ("SHELL"));
551 /* rand () on NT gives us 15 random bits...hack together 30 bits. */
552 return ((rand () << 15) | rand ());
562 /* Normalize filename by converting all path separators to
563 the specified separator. Also conditionally convert upper
564 case path name components to lower case. */
567 normalize_filename (fp
, path_sep
)
574 /* Always lower-case drive letters a-z, even if the filesystem
575 preserves case in filenames.
576 This is so filenames can be compared by string comparison
577 functions that are case-sensitive. Even case-preserving filesystems
578 do not distinguish case in drive letters. */
579 if (fp
[1] == ':' && *fp
>= 'A' && *fp
<= 'Z')
585 if (NILP (Vw32_downcase_file_names
))
589 if (*fp
== '/' || *fp
== '\\')
596 sep
= path_sep
; /* convert to this path separator */
597 elem
= fp
; /* start of current path element */
600 if (*fp
>= 'a' && *fp
<= 'z')
601 elem
= 0; /* don't convert this element */
603 if (*fp
== 0 || *fp
== ':')
605 sep
= *fp
; /* restore current separator (or 0) */
606 *fp
= '/'; /* after conversion of this element */
609 if (*fp
== '/' || *fp
== '\\')
611 if (elem
&& elem
!= fp
)
613 *fp
= 0; /* temporary end of string */
614 _strlwr (elem
); /* while we convert to lower case */
616 *fp
= sep
; /* convert (or restore) path separator */
617 elem
= fp
+ 1; /* next element starts after separator */
623 /* Destructively turn backslashes into slashes. */
625 dostounix_filename (p
)
628 normalize_filename (p
, '/');
631 /* Destructively turn slashes into backslashes. */
633 unixtodos_filename (p
)
636 normalize_filename (p
, '\\');
639 /* Remove all CR's that are followed by a LF.
640 (From msdos.c...probably should figure out a way to share it,
641 although this code isn't going to ever change.) */
645 register unsigned char *buf
;
647 unsigned char *np
= buf
;
648 unsigned char *startp
= buf
;
649 unsigned char *endp
= buf
+ n
;
653 while (buf
< endp
- 1)
657 if (*(++buf
) != 0x0a)
668 /* Parse the root part of file name, if present. Return length and
669 optionally store pointer to char after root. */
671 parse_root (char * name
, char ** pPath
)
678 /* find the root name of the volume if given */
679 if (isalpha (name
[0]) && name
[1] == ':')
681 /* skip past drive specifier */
683 if (IS_DIRECTORY_SEP (name
[0]))
686 else if (IS_DIRECTORY_SEP (name
[0]) && IS_DIRECTORY_SEP (name
[1]))
692 if (IS_DIRECTORY_SEP (*name
) && --slashes
== 0)
697 if (IS_DIRECTORY_SEP (name
[0]))
707 /* Get long base name for name; name is assumed to be absolute. */
709 get_long_basename (char * name
, char * buf
, int size
)
711 WIN32_FIND_DATA find_data
;
715 /* must be valid filename, no wild cards or other invalid characters */
716 if (strpbrk (name
, "*?|<>\""))
719 dir_handle
= FindFirstFile (name
, &find_data
);
720 if (dir_handle
!= INVALID_HANDLE_VALUE
)
722 if ((len
= strlen (find_data
.cFileName
)) < size
)
723 memcpy (buf
, find_data
.cFileName
, len
+ 1);
726 FindClose (dir_handle
);
731 /* Get long name for file, if possible (assumed to be absolute). */
733 w32_get_long_filename (char * name
, char * buf
, int size
)
738 char full
[ MAX_PATH
];
745 /* Use local copy for destructive modification. */
746 memcpy (full
, name
, len
+1);
747 unixtodos_filename (full
);
749 /* Copy root part verbatim. */
750 len
= parse_root (full
, &p
);
751 memcpy (o
, full
, len
);
756 while (p
!= NULL
&& *p
)
759 p
= strchr (q
, '\\');
761 len
= get_long_basename (full
, o
, size
);
784 is_unc_volume (const char *filename
)
786 const char *ptr
= filename
;
788 if (!IS_DIRECTORY_SEP (ptr
[0]) || !IS_DIRECTORY_SEP (ptr
[1]) || !ptr
[2])
791 if (strpbrk (ptr
+ 2, "*?|<>\"\\/"))
797 /* Routines that are no-ops on NT but are defined to get Emacs to compile. */
800 sigsetmask (int signal_mask
)
824 setpgrp (int pid
, int gid
)
836 unrequest_sigio (void)
847 #define REG_ROOT "SOFTWARE\\GNU\\Emacs"
850 w32_get_resource (key
, lpdwtype
)
855 HKEY hrootkey
= NULL
;
859 /* Check both the current user and the local machine to see if
860 we have any resources. */
862 if (RegOpenKeyEx (HKEY_CURRENT_USER
, REG_ROOT
, 0, KEY_READ
, &hrootkey
) == ERROR_SUCCESS
)
866 if (RegQueryValueEx (hrootkey
, key
, NULL
, NULL
, NULL
, &cbData
) == ERROR_SUCCESS
867 && (lpvalue
= (LPBYTE
) xmalloc (cbData
)) != NULL
868 && RegQueryValueEx (hrootkey
, key
, NULL
, lpdwtype
, lpvalue
, &cbData
) == ERROR_SUCCESS
)
873 if (lpvalue
) xfree (lpvalue
);
875 RegCloseKey (hrootkey
);
878 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE
, REG_ROOT
, 0, KEY_READ
, &hrootkey
) == ERROR_SUCCESS
)
882 if (RegQueryValueEx (hrootkey
, key
, NULL
, NULL
, NULL
, &cbData
) == ERROR_SUCCESS
883 && (lpvalue
= (LPBYTE
) xmalloc (cbData
)) != NULL
884 && RegQueryValueEx (hrootkey
, key
, NULL
, lpdwtype
, lpvalue
, &cbData
) == ERROR_SUCCESS
)
889 if (lpvalue
) xfree (lpvalue
);
891 RegCloseKey (hrootkey
);
897 char *get_emacs_configuration (void);
898 extern Lisp_Object Vsystem_configuration
;
901 init_environment (char ** argv
)
903 static const char * const tempdirs
[] = {
904 "$TMPDIR", "$TEMP", "$TMP", "c:/"
907 const int imax
= sizeof (tempdirs
) / sizeof (tempdirs
[0]);
909 /* Make sure they have a usable $TMPDIR. Many Emacs functions use
910 temporary files and assume "/tmp" if $TMPDIR is unset, which
911 will break on DOS/Windows. Refuse to work if we cannot find
912 a directory, not even "c:/", usable for that purpose. */
913 for (i
= 0; i
< imax
; i
++)
915 const char *tmp
= tempdirs
[i
];
918 tmp
= getenv (tmp
+ 1);
919 /* Note that `access' can lie to us if the directory resides on a
920 read-only filesystem, like CD-ROM or a write-protected floppy.
921 The only way to be really sure is to actually create a file and
922 see if it succeeds. But I think that's too much to ask. */
923 if (tmp
&& _access (tmp
, D_OK
) == 0)
925 char * var
= alloca (strlen (tmp
) + 8);
926 sprintf (var
, "TMPDIR=%s", tmp
);
927 _putenv (strdup (var
));
934 Fcons (build_string ("no usable temporary directories found!!"),
936 "While setting TMPDIR: ");
938 /* Check for environment variables and use registry settings if they
939 don't exist. Fallback on default values where applicable. */
944 char locale_name
[32];
946 static struct env_entry
953 {"PRELOAD_WINSOCK", NULL
},
954 {"emacs_dir", "C:/emacs"},
955 {"EMACSLOADPATH", "%emacs_dir%/site-lisp;%emacs_dir%/../site-lisp;%emacs_dir%/lisp;%emacs_dir%/leim"},
956 {"SHELL", "%emacs_dir%/bin/cmdproxy.exe"},
957 {"EMACSDATA", "%emacs_dir%/etc"},
958 {"EMACSPATH", "%emacs_dir%/bin"},
959 /* We no longer set INFOPATH because Info-default-directory-list
961 /* {"INFOPATH", "%emacs_dir%/info"}, */
962 {"EMACSDOC", "%emacs_dir%/etc"},
967 /* Get default locale info and use it for LANG. */
968 if (GetLocaleInfo (LOCALE_USER_DEFAULT
,
969 LOCALE_SABBREVLANGNAME
| LOCALE_USE_CP_ACP
,
970 locale_name
, sizeof (locale_name
)))
972 for (i
= 0; i
< (sizeof (env_vars
) / sizeof (env_vars
[0])); i
++)
974 if (strcmp (env_vars
[i
].name
, "LANG") == 0)
976 env_vars
[i
].def_value
= locale_name
;
982 #define SET_ENV_BUF_SIZE (4 * MAX_PATH) /* to cover EMACSLOADPATH */
984 /* Treat emacs_dir specially: set it unconditionally based on our
985 location, if it appears that we are running from the bin subdir
986 of a standard installation. */
989 char modname
[MAX_PATH
];
991 if (!GetModuleFileName (NULL
, modname
, MAX_PATH
))
993 if ((p
= strrchr (modname
, '\\')) == NULL
)
997 if ((p
= strrchr (modname
, '\\')) && stricmp (p
, "\\bin") == 0)
999 char buf
[SET_ENV_BUF_SIZE
];
1002 for (p
= modname
; *p
; p
++)
1003 if (*p
== '\\') *p
= '/';
1005 _snprintf (buf
, sizeof(buf
)-1, "emacs_dir=%s", modname
);
1006 _putenv (strdup (buf
));
1008 /* Handle running emacs from the build directory: src/oo-spd/i386/ */
1010 /* FIXME: should use substring of get_emacs_configuration ().
1011 But I don't think the Windows build supports alpha, mips etc
1012 anymore, so have taken the easy option for now. */
1013 else if (p
&& stricmp (p
, "\\i386") == 0)
1016 p
= strrchr (modname
, '\\');
1020 p
= strrchr (modname
, '\\');
1021 if (p
&& stricmp (p
, "\\src") == 0)
1023 char buf
[SET_ENV_BUF_SIZE
];
1026 for (p
= modname
; *p
; p
++)
1027 if (*p
== '\\') *p
= '/';
1029 _snprintf (buf
, sizeof(buf
)-1, "emacs_dir=%s", modname
);
1030 _putenv (strdup (buf
));
1036 for (i
= 0; i
< (sizeof (env_vars
) / sizeof (env_vars
[0])); i
++)
1038 if (!getenv (env_vars
[i
].name
))
1042 if ((lpval
= w32_get_resource (env_vars
[i
].name
, &dwType
)) == NULL
)
1044 lpval
= env_vars
[i
].def_value
;
1045 dwType
= REG_EXPAND_SZ
;
1051 if (dwType
== REG_EXPAND_SZ
)
1053 char buf1
[SET_ENV_BUF_SIZE
], buf2
[SET_ENV_BUF_SIZE
];
1055 ExpandEnvironmentStrings ((LPSTR
) lpval
, buf1
, sizeof(buf1
));
1056 _snprintf (buf2
, sizeof(buf2
)-1, "%s=%s", env_vars
[i
].name
, buf1
);
1057 _putenv (strdup (buf2
));
1059 else if (dwType
== REG_SZ
)
1061 char buf
[SET_ENV_BUF_SIZE
];
1063 _snprintf (buf
, sizeof(buf
)-1, "%s=%s", env_vars
[i
].name
, lpval
);
1064 _putenv (strdup (buf
));
1074 /* Rebuild system configuration to reflect invoking system. */
1075 Vsystem_configuration
= build_string (EMACS_CONFIGURATION
);
1077 /* Another special case: on NT, the PATH variable is actually named
1078 "Path" although cmd.exe (perhaps NT itself) arranges for
1079 environment variable lookup and setting to be case insensitive.
1080 However, Emacs assumes a fully case sensitive environment, so we
1081 need to change "Path" to "PATH" to match the expectations of
1082 various elisp packages. We do this by the sneaky method of
1083 modifying the string in the C runtime environ entry.
1085 The same applies to COMSPEC. */
1089 for (envp
= environ
; *envp
; envp
++)
1090 if (_strnicmp (*envp
, "PATH=", 5) == 0)
1091 memcpy (*envp
, "PATH=", 5);
1092 else if (_strnicmp (*envp
, "COMSPEC=", 8) == 0)
1093 memcpy (*envp
, "COMSPEC=", 8);
1096 /* Remember the initial working directory for getwd, then make the
1097 real wd be the location of emacs.exe to avoid conflicts when
1098 renaming or deleting directories. (We also don't call chdir when
1099 running subprocesses for the same reason.) */
1100 if (!GetCurrentDirectory (MAXPATHLEN
, startup_dir
))
1105 static char modname
[MAX_PATH
];
1107 if (!GetModuleFileName (NULL
, modname
, MAX_PATH
))
1109 if ((p
= strrchr (modname
, '\\')) == NULL
)
1113 SetCurrentDirectory (modname
);
1115 /* Ensure argv[0] has the full path to Emacs. */
1120 /* Determine if there is a middle mouse button, to allow parse_button
1121 to decide whether right mouse events should be mouse-2 or
1123 w32_num_mouse_buttons
= GetSystemMetrics (SM_CMOUSEBUTTONS
);
1129 emacs_root_dir (void)
1131 static char root_dir
[FILENAME_MAX
];
1134 p
= getenv ("emacs_dir");
1137 strcpy (root_dir
, p
);
1138 root_dir
[parse_root (root_dir
, NULL
)] = '\0';
1139 dostounix_filename (root_dir
);
1143 /* We don't have scripts to automatically determine the system configuration
1144 for Emacs before it's compiled, and we don't want to have to make the
1145 user enter it, so we define EMACS_CONFIGURATION to invoke this runtime
1149 get_emacs_configuration (void)
1151 char *arch
, *oem
, *os
;
1153 static char configuration_buffer
[32];
1155 /* Determine the processor type. */
1156 switch (get_processor_type ())
1159 #ifdef PROCESSOR_INTEL_386
1160 case PROCESSOR_INTEL_386
:
1161 case PROCESSOR_INTEL_486
:
1162 case PROCESSOR_INTEL_PENTIUM
:
1167 #ifdef PROCESSOR_INTEL_860
1168 case PROCESSOR_INTEL_860
:
1173 #ifdef PROCESSOR_MIPS_R2000
1174 case PROCESSOR_MIPS_R2000
:
1175 case PROCESSOR_MIPS_R3000
:
1176 case PROCESSOR_MIPS_R4000
:
1181 #ifdef PROCESSOR_ALPHA_21064
1182 case PROCESSOR_ALPHA_21064
:
1192 /* Use the OEM field to reflect the compiler/library combination. */
1194 #define COMPILER_NAME "msvc"
1197 #define COMPILER_NAME "mingw"
1199 #define COMPILER_NAME "unknown"
1202 oem
= COMPILER_NAME
;
1204 switch (osinfo_cache
.dwPlatformId
) {
1205 case VER_PLATFORM_WIN32_NT
:
1207 build_num
= osinfo_cache
.dwBuildNumber
;
1209 case VER_PLATFORM_WIN32_WINDOWS
:
1210 if (osinfo_cache
.dwMinorVersion
== 0) {
1215 build_num
= LOWORD (osinfo_cache
.dwBuildNumber
);
1217 case VER_PLATFORM_WIN32s
:
1218 /* Not supported, should not happen. */
1220 build_num
= LOWORD (osinfo_cache
.dwBuildNumber
);
1228 if (osinfo_cache
.dwPlatformId
== VER_PLATFORM_WIN32_NT
) {
1229 sprintf (configuration_buffer
, "%s-%s-%s%d.%d.%d", arch
, oem
, os
,
1230 get_w32_major_version (), get_w32_minor_version (), build_num
);
1232 sprintf (configuration_buffer
, "%s-%s-%s.%d", arch
, oem
, os
, build_num
);
1235 return configuration_buffer
;
1239 get_emacs_configuration_options (void)
1241 static char options_buffer
[256];
1243 /* Work out the effective configure options for this build. */
1245 #define COMPILER_VERSION "--with-msvc (%d.%02d)", _MSC_VER / 100, _MSC_VER % 100
1248 #define COMPILER_VERSION "--with-gcc (%d.%d)", __GNUC__, __GNUC_MINOR__
1250 #define COMPILER_VERSION ""
1254 sprintf (options_buffer
, COMPILER_VERSION
);
1256 strcat (options_buffer
, " --no-opt");
1259 strcat (options_buffer
, " --cflags");
1260 strcat (options_buffer
, USER_CFLAGS
);
1263 strcat (options_buffer
, " --ldflags");
1264 strcat (options_buffer
, USER_LDFLAGS
);
1266 return options_buffer
;
1270 #include <sys/timeb.h>
1272 /* Emulate gettimeofday (Ulrich Leodolter, 1/11/95). */
1274 gettimeofday (struct timeval
*tv
, struct timezone
*tz
)
1279 tv
->tv_sec
= tb
.time
;
1280 tv
->tv_usec
= tb
.millitm
* 1000L;
1283 tz
->tz_minuteswest
= tb
.timezone
; /* minutes west of Greenwich */
1284 tz
->tz_dsttime
= tb
.dstflag
; /* type of dst correction */
1288 /* ------------------------------------------------------------------------- */
1289 /* IO support and wrapper functions for W32 API. */
1290 /* ------------------------------------------------------------------------- */
1292 /* Place a wrapper around the MSVC version of ctime. It returns NULL
1293 on network directories, so we handle that case here.
1294 (Ulrich Leodolter, 1/11/95). */
1296 sys_ctime (const time_t *t
)
1298 char *str
= (char *) ctime (t
);
1299 return (str
? str
: "Sun Jan 01 00:00:00 1970");
1302 /* Emulate sleep...we could have done this with a define, but that
1303 would necessitate including windows.h in the files that used it.
1304 This is much easier. */
1306 sys_sleep (int seconds
)
1308 Sleep (seconds
* 1000);
1311 /* Internal MSVC functions for low-level descriptor munging */
1312 extern int __cdecl
_set_osfhnd (int fd
, long h
);
1313 extern int __cdecl
_free_osfhnd (int fd
);
1315 /* parallel array of private info on file handles */
1316 filedesc fd_info
[ MAXDESC
];
1318 typedef struct volume_info_data
{
1319 struct volume_info_data
* next
;
1321 /* time when info was obtained */
1324 /* actual volume info */
1333 /* Global referenced by various functions. */
1334 static volume_info_data volume_info
;
1336 /* Vector to indicate which drives are local and fixed (for which cached
1337 data never expires). */
1338 static BOOL fixed_drives
[26];
1340 /* Consider cached volume information to be stale if older than 10s,
1341 at least for non-local drives. Info for fixed drives is never stale. */
1342 #define DRIVE_INDEX( c ) ( (c) <= 'Z' ? (c) - 'A' : (c) - 'a' )
1343 #define VOLINFO_STILL_VALID( root_dir, info ) \
1344 ( ( isalpha (root_dir[0]) && \
1345 fixed_drives[ DRIVE_INDEX (root_dir[0]) ] ) \
1346 || GetTickCount () - info->timestamp < 10000 )
1348 /* Cache support functions. */
1350 /* Simple linked list with linear search is sufficient. */
1351 static volume_info_data
*volume_cache
= NULL
;
1353 static volume_info_data
*
1354 lookup_volume_info (char * root_dir
)
1356 volume_info_data
* info
;
1358 for (info
= volume_cache
; info
; info
= info
->next
)
1359 if (stricmp (info
->root_dir
, root_dir
) == 0)
1365 add_volume_info (char * root_dir
, volume_info_data
* info
)
1367 info
->root_dir
= xstrdup (root_dir
);
1368 info
->next
= volume_cache
;
1369 volume_cache
= info
;
1373 /* Wrapper for GetVolumeInformation, which uses caching to avoid
1374 performance penalty (~2ms on 486 for local drives, 7.5ms for local
1375 cdrom drive, ~5-10ms or more for remote drives on LAN). */
1377 GetCachedVolumeInformation (char * root_dir
)
1379 volume_info_data
* info
;
1380 char default_root
[ MAX_PATH
];
1382 /* NULL for root_dir means use root from current directory. */
1383 if (root_dir
== NULL
)
1385 if (GetCurrentDirectory (MAX_PATH
, default_root
) == 0)
1387 parse_root (default_root
, &root_dir
);
1389 root_dir
= default_root
;
1392 /* Local fixed drives can be cached permanently. Removable drives
1393 cannot be cached permanently, since the volume name and serial
1394 number (if nothing else) can change. Remote drives should be
1395 treated as if they are removable, since there is no sure way to
1396 tell whether they are or not. Also, the UNC association of drive
1397 letters mapped to remote volumes can be changed at any time (even
1398 by other processes) without notice.
1400 As a compromise, so we can benefit from caching info for remote
1401 volumes, we use a simple expiry mechanism to invalidate cache
1402 entries that are more than ten seconds old. */
1405 /* No point doing this, because WNetGetConnection is even slower than
1406 GetVolumeInformation, consistently taking ~50ms on a 486 (FWIW,
1407 GetDriveType is about the only call of this type which does not
1408 involve network access, and so is extremely quick). */
1410 /* Map drive letter to UNC if remote. */
1411 if ( isalpha( root_dir
[0] ) && !fixed
[ DRIVE_INDEX( root_dir
[0] ) ] )
1413 char remote_name
[ 256 ];
1414 char drive
[3] = { root_dir
[0], ':' };
1416 if (WNetGetConnection (drive
, remote_name
, sizeof (remote_name
))
1418 /* do something */ ;
1422 info
= lookup_volume_info (root_dir
);
1424 if (info
== NULL
|| ! VOLINFO_STILL_VALID (root_dir
, info
))
1432 /* Info is not cached, or is stale. */
1433 if (!GetVolumeInformation (root_dir
,
1434 name
, sizeof (name
),
1438 type
, sizeof (type
)))
1441 /* Cache the volume information for future use, overwriting existing
1442 entry if present. */
1445 info
= (volume_info_data
*) xmalloc (sizeof (volume_info_data
));
1446 add_volume_info (root_dir
, info
);
1454 info
->name
= xstrdup (name
);
1455 info
->serialnum
= serialnum
;
1456 info
->maxcomp
= maxcomp
;
1457 info
->flags
= flags
;
1458 info
->type
= xstrdup (type
);
1459 info
->timestamp
= GetTickCount ();
1465 /* Get information on the volume where name is held; set path pointer to
1466 start of pathname in name (past UNC header\volume header if present). */
1468 get_volume_info (const char * name
, const char ** pPath
)
1470 char temp
[MAX_PATH
];
1471 char *rootname
= NULL
; /* default to current volume */
1472 volume_info_data
* info
;
1477 /* find the root name of the volume if given */
1478 if (isalpha (name
[0]) && name
[1] == ':')
1486 else if (IS_DIRECTORY_SEP (name
[0]) && IS_DIRECTORY_SEP (name
[1]))
1493 if (IS_DIRECTORY_SEP (*name
) && --slashes
== 0)
1506 info
= GetCachedVolumeInformation (rootname
);
1509 /* Set global referenced by other functions. */
1510 volume_info
= *info
;
1516 /* Determine if volume is FAT format (ie. only supports short 8.3
1517 names); also set path pointer to start of pathname in name. */
1519 is_fat_volume (const char * name
, const char ** pPath
)
1521 if (get_volume_info (name
, pPath
))
1522 return (volume_info
.maxcomp
== 12);
1526 /* Map filename to a legal 8.3 name if necessary. */
1528 map_w32_filename (const char * name
, const char ** pPath
)
1530 static char shortname
[MAX_PATH
];
1531 char * str
= shortname
;
1534 const char * save_name
= name
;
1536 if (strlen (name
) >= MAX_PATH
)
1538 /* Return a filename which will cause callers to fail. */
1539 strcpy (shortname
, "?");
1543 if (is_fat_volume (name
, (const char **)&path
)) /* truncate to 8.3 */
1545 register int left
= 8; /* maximum number of chars in part */
1546 register int extn
= 0; /* extension added? */
1547 register int dots
= 2; /* maximum number of dots allowed */
1550 *str
++ = *name
++; /* skip past UNC header */
1552 while ((c
= *name
++))
1559 extn
= 0; /* reset extension flags */
1560 dots
= 2; /* max 2 dots */
1561 left
= 8; /* max length 8 for main part */
1565 extn
= 0; /* reset extension flags */
1566 dots
= 2; /* max 2 dots */
1567 left
= 8; /* max length 8 for main part */
1572 /* Convert path components of the form .xxx to _xxx,
1573 but leave . and .. as they are. This allows .emacs
1574 to be read as _emacs, for example. */
1578 IS_DIRECTORY_SEP (*name
))
1593 extn
= 1; /* we've got an extension */
1594 left
= 3; /* 3 chars in extension */
1598 /* any embedded dots after the first are converted to _ */
1603 case '#': /* don't lose these, they're important */
1605 str
[-1] = c
; /* replace last character of part */
1610 *str
++ = tolower (c
); /* map to lower case (looks nicer) */
1612 dots
= 0; /* started a path component */
1621 strcpy (shortname
, name
);
1622 unixtodos_filename (shortname
);
1626 *pPath
= shortname
+ (path
- save_name
);
1632 is_exec (const char * name
)
1634 char * p
= strrchr (name
, '.');
1637 && (stricmp (p
, ".exe") == 0 ||
1638 stricmp (p
, ".com") == 0 ||
1639 stricmp (p
, ".bat") == 0 ||
1640 stricmp (p
, ".cmd") == 0));
1643 /* Emulate the Unix directory procedures opendir, closedir,
1644 and readdir. We can't use the procedures supplied in sysdep.c,
1645 so we provide them here. */
1647 struct direct dir_static
; /* simulated directory contents */
1648 static HANDLE dir_find_handle
= INVALID_HANDLE_VALUE
;
1649 static int dir_is_fat
;
1650 static char dir_pathname
[MAXPATHLEN
+1];
1651 static WIN32_FIND_DATA dir_find_data
;
1653 /* Support shares on a network resource as subdirectories of a read-only
1655 static HANDLE wnet_enum_handle
= INVALID_HANDLE_VALUE
;
1656 HANDLE
open_unc_volume (const char *);
1657 char *read_unc_volume (HANDLE
, char *, int);
1658 void close_unc_volume (HANDLE
);
1661 opendir (char *filename
)
1665 /* Opening is done by FindFirstFile. However, a read is inherent to
1666 this operation, so we defer the open until read time. */
1668 if (dir_find_handle
!= INVALID_HANDLE_VALUE
)
1670 if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
1673 if (is_unc_volume (filename
))
1675 wnet_enum_handle
= open_unc_volume (filename
);
1676 if (wnet_enum_handle
== INVALID_HANDLE_VALUE
)
1680 if (!(dirp
= (DIR *) malloc (sizeof (DIR))))
1687 strncpy (dir_pathname
, map_w32_filename (filename
, NULL
), MAXPATHLEN
);
1688 dir_pathname
[MAXPATHLEN
] = '\0';
1689 dir_is_fat
= is_fat_volume (filename
, NULL
);
1695 closedir (DIR *dirp
)
1697 /* If we have a find-handle open, close it. */
1698 if (dir_find_handle
!= INVALID_HANDLE_VALUE
)
1700 FindClose (dir_find_handle
);
1701 dir_find_handle
= INVALID_HANDLE_VALUE
;
1703 else if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
1705 close_unc_volume (wnet_enum_handle
);
1706 wnet_enum_handle
= INVALID_HANDLE_VALUE
;
1708 xfree ((char *) dirp
);
1714 if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
1716 if (!read_unc_volume (wnet_enum_handle
,
1717 dir_find_data
.cFileName
,
1721 /* If we aren't dir_finding, do a find-first, otherwise do a find-next. */
1722 else if (dir_find_handle
== INVALID_HANDLE_VALUE
)
1724 char filename
[MAXNAMLEN
+ 3];
1727 strcpy (filename
, dir_pathname
);
1728 ln
= strlen (filename
) - 1;
1729 if (!IS_DIRECTORY_SEP (filename
[ln
]))
1730 strcat (filename
, "\\");
1731 strcat (filename
, "*");
1733 dir_find_handle
= FindFirstFile (filename
, &dir_find_data
);
1735 if (dir_find_handle
== INVALID_HANDLE_VALUE
)
1740 if (!FindNextFile (dir_find_handle
, &dir_find_data
))
1744 /* Emacs never uses this value, so don't bother making it match
1745 value returned by stat(). */
1746 dir_static
.d_ino
= 1;
1748 dir_static
.d_reclen
= sizeof (struct direct
) - MAXNAMLEN
+ 3 +
1749 dir_static
.d_namlen
- dir_static
.d_namlen
% 4;
1751 dir_static
.d_namlen
= strlen (dir_find_data
.cFileName
);
1752 strcpy (dir_static
.d_name
, dir_find_data
.cFileName
);
1754 _strlwr (dir_static
.d_name
);
1755 else if (!NILP (Vw32_downcase_file_names
))
1758 for (p
= dir_static
.d_name
; *p
; p
++)
1759 if (*p
>= 'a' && *p
<= 'z')
1762 _strlwr (dir_static
.d_name
);
1769 open_unc_volume (const char *path
)
1775 nr
.dwScope
= RESOURCE_GLOBALNET
;
1776 nr
.dwType
= RESOURCETYPE_DISK
;
1777 nr
.dwDisplayType
= RESOURCEDISPLAYTYPE_SERVER
;
1778 nr
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
1779 nr
.lpLocalName
= NULL
;
1780 nr
.lpRemoteName
= (LPSTR
)map_w32_filename (path
, NULL
);
1781 nr
.lpComment
= NULL
;
1782 nr
.lpProvider
= NULL
;
1784 result
= WNetOpenEnum(RESOURCE_GLOBALNET
, RESOURCETYPE_DISK
,
1785 RESOURCEUSAGE_CONNECTABLE
, &nr
, &henum
);
1787 if (result
== NO_ERROR
)
1790 return INVALID_HANDLE_VALUE
;
1794 read_unc_volume (HANDLE henum
, char *readbuf
, int size
)
1798 DWORD bufsize
= 512;
1803 buffer
= alloca (bufsize
);
1804 result
= WNetEnumResource (wnet_enum_handle
, &count
, buffer
, &bufsize
);
1805 if (result
!= NO_ERROR
)
1808 /* WNetEnumResource returns \\resource\share...skip forward to "share". */
1809 ptr
= ((LPNETRESOURCE
) buffer
)->lpRemoteName
;
1811 while (*ptr
&& !IS_DIRECTORY_SEP (*ptr
)) ptr
++;
1814 strncpy (readbuf
, ptr
, size
);
1819 close_unc_volume (HANDLE henum
)
1821 if (henum
!= INVALID_HANDLE_VALUE
)
1822 WNetCloseEnum (henum
);
1826 unc_volume_file_attributes (const char *path
)
1831 henum
= open_unc_volume (path
);
1832 if (henum
== INVALID_HANDLE_VALUE
)
1835 attrs
= FILE_ATTRIBUTE_READONLY
| FILE_ATTRIBUTE_DIRECTORY
;
1837 close_unc_volume (henum
);
1843 /* Shadow some MSVC runtime functions to map requests for long filenames
1844 to reasonable short names if necessary. This was originally added to
1845 permit running Emacs on NT 3.1 on a FAT partition, which doesn't support
1849 sys_access (const char * path
, int mode
)
1853 /* MSVC implementation doesn't recognize D_OK. */
1854 path
= map_w32_filename (path
, NULL
);
1855 if (is_unc_volume (path
))
1857 attributes
= unc_volume_file_attributes (path
);
1858 if (attributes
== -1) {
1863 else if ((attributes
= GetFileAttributes (path
)) == -1)
1865 /* Should try mapping GetLastError to errno; for now just indicate
1866 that path doesn't exist. */
1870 if ((mode
& X_OK
) != 0 && !is_exec (path
))
1875 if ((mode
& W_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_READONLY
) != 0)
1880 if ((mode
& D_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
) == 0)
1889 sys_chdir (const char * path
)
1891 return _chdir (map_w32_filename (path
, NULL
));
1895 sys_chmod (const char * path
, int mode
)
1897 return _chmod (map_w32_filename (path
, NULL
), mode
);
1901 sys_chown (const char *path
, uid_t owner
, gid_t group
)
1903 if (sys_chmod (path
, _S_IREAD
) == -1) /* check if file exists */
1909 sys_creat (const char * path
, int mode
)
1911 return _creat (map_w32_filename (path
, NULL
), mode
);
1915 sys_fopen(const char * path
, const char * mode
)
1919 const char * mode_save
= mode
;
1921 /* Force all file handles to be non-inheritable. This is necessary to
1922 ensure child processes don't unwittingly inherit handles that might
1923 prevent future file access. */
1927 else if (mode
[0] == 'w' || mode
[0] == 'a')
1928 oflag
= O_WRONLY
| O_CREAT
| O_TRUNC
;
1932 /* Only do simplistic option parsing. */
1936 oflag
&= ~(O_RDONLY
| O_WRONLY
);
1939 else if (mode
[0] == 'b')
1944 else if (mode
[0] == 't')
1951 fd
= _open (map_w32_filename (path
, NULL
), oflag
| _O_NOINHERIT
, 0644);
1955 return _fdopen (fd
, mode_save
);
1958 /* This only works on NTFS volumes, but is useful to have. */
1960 sys_link (const char * old
, const char * new)
1964 char oldname
[MAX_PATH
], newname
[MAX_PATH
];
1966 if (old
== NULL
|| new == NULL
)
1972 strcpy (oldname
, map_w32_filename (old
, NULL
));
1973 strcpy (newname
, map_w32_filename (new, NULL
));
1975 fileh
= CreateFile (oldname
, 0, 0, NULL
, OPEN_EXISTING
,
1976 FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
1977 if (fileh
!= INVALID_HANDLE_VALUE
)
1981 /* Confusingly, the "alternate" stream name field does not apply
1982 when restoring a hard link, and instead contains the actual
1983 stream data for the link (ie. the name of the link to create).
1984 The WIN32_STREAM_ID structure before the cStreamName field is
1985 the stream header, which is then immediately followed by the
1989 WIN32_STREAM_ID wid
;
1990 WCHAR wbuffer
[MAX_PATH
]; /* extra space for link name */
1993 wlen
= MultiByteToWideChar (CP_ACP
, MB_PRECOMPOSED
, newname
, -1,
1994 data
.wid
.cStreamName
, MAX_PATH
);
1997 LPVOID context
= NULL
;
2000 data
.wid
.dwStreamId
= BACKUP_LINK
;
2001 data
.wid
.dwStreamAttributes
= 0;
2002 data
.wid
.Size
.LowPart
= wlen
* sizeof(WCHAR
);
2003 data
.wid
.Size
.HighPart
= 0;
2004 data
.wid
.dwStreamNameSize
= 0;
2006 if (BackupWrite (fileh
, (LPBYTE
)&data
,
2007 offsetof (WIN32_STREAM_ID
, cStreamName
)
2008 + data
.wid
.Size
.LowPart
,
2009 &wbytes
, FALSE
, FALSE
, &context
)
2010 && BackupWrite (fileh
, NULL
, 0, &wbytes
, TRUE
, FALSE
, &context
))
2017 /* Should try mapping GetLastError to errno; for now just
2018 indicate a general error (eg. links not supported). */
2019 errno
= EINVAL
; // perhaps EMLINK?
2023 CloseHandle (fileh
);
2032 sys_mkdir (const char * path
)
2034 return _mkdir (map_w32_filename (path
, NULL
));
2037 /* Because of long name mapping issues, we need to implement this
2038 ourselves. Also, MSVC's _mktemp returns NULL when it can't generate
2039 a unique name, instead of setting the input template to an empty
2042 Standard algorithm seems to be use pid or tid with a letter on the
2043 front (in place of the 6 X's) and cycle through the letters to find a
2044 unique name. We extend that to allow any reasonable character as the
2045 first of the 6 X's. */
2047 sys_mktemp (char * template)
2051 unsigned uid
= GetCurrentThreadId ();
2052 static char first_char
[] = "abcdefghijklmnopqrstuvwyz0123456789!%-_@#";
2054 if (template == NULL
)
2056 p
= template + strlen (template);
2058 /* replace up to the last 5 X's with uid in decimal */
2059 while (--p
>= template && p
[0] == 'X' && --i
>= 0)
2061 p
[0] = '0' + uid
% 10;
2065 if (i
< 0 && p
[0] == 'X')
2070 int save_errno
= errno
;
2071 p
[0] = first_char
[i
];
2072 if (sys_access (template, 0) < 0)
2078 while (++i
< sizeof (first_char
));
2081 /* Template is badly formed or else we can't generate a unique name,
2082 so return empty string */
2088 sys_open (const char * path
, int oflag
, int mode
)
2090 const char* mpath
= map_w32_filename (path
, NULL
);
2091 /* Try to open file without _O_CREAT, to be able to write to hidden
2092 and system files. Force all file handles to be
2094 int res
= _open (mpath
, (oflag
& ~_O_CREAT
) | _O_NOINHERIT
, mode
);
2097 return _open (mpath
, oflag
| _O_NOINHERIT
, mode
);
2101 sys_rename (const char * oldname
, const char * newname
)
2104 char temp
[MAX_PATH
];
2106 /* MoveFile on Windows 95 doesn't correctly change the short file name
2107 alias in a number of circumstances (it is not easy to predict when
2108 just by looking at oldname and newname, unfortunately). In these
2109 cases, renaming through a temporary name avoids the problem.
2111 A second problem on Windows 95 is that renaming through a temp name when
2112 newname is uppercase fails (the final long name ends up in
2113 lowercase, although the short alias might be uppercase) UNLESS the
2114 long temp name is not 8.3.
2116 So, on Windows 95 we always rename through a temp name, and we make sure
2117 the temp name has a long extension to ensure correct renaming. */
2119 strcpy (temp
, map_w32_filename (oldname
, NULL
));
2121 if (os_subtype
== OS_WIN95
)
2127 oldname
= map_w32_filename (oldname
, NULL
);
2128 if (o
= strrchr (oldname
, '\\'))
2131 o
= (char *) oldname
;
2133 if (p
= strrchr (temp
, '\\'))
2140 /* Force temp name to require a manufactured 8.3 alias - this
2141 seems to make the second rename work properly. */
2142 sprintf (p
, "_.%s.%u", o
, i
);
2144 result
= rename (oldname
, temp
);
2146 /* This loop must surely terminate! */
2147 while (result
< 0 && errno
== EEXIST
);
2152 /* Emulate Unix behaviour - newname is deleted if it already exists
2153 (at least if it is a file; don't do this for directories).
2155 Since we mustn't do this if we are just changing the case of the
2156 file name (we would end up deleting the file we are trying to
2157 rename!), we let rename detect if the destination file already
2158 exists - that way we avoid the possible pitfalls of trying to
2159 determine ourselves whether two names really refer to the same
2160 file, which is not always possible in the general case. (Consider
2161 all the permutations of shared or subst'd drives, etc.) */
2163 newname
= map_w32_filename (newname
, NULL
);
2164 result
= rename (temp
, newname
);
2168 && _chmod (newname
, 0666) == 0
2169 && _unlink (newname
) == 0)
2170 result
= rename (temp
, newname
);
2176 sys_rmdir (const char * path
)
2178 return _rmdir (map_w32_filename (path
, NULL
));
2182 sys_unlink (const char * path
)
2184 path
= map_w32_filename (path
, NULL
);
2186 /* On Unix, unlink works without write permission. */
2187 _chmod (path
, 0666);
2188 return _unlink (path
);
2191 static FILETIME utc_base_ft
;
2192 static long double utc_base
;
2193 static int init
= 0;
2196 convert_time (FILETIME ft
)
2202 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
2211 st
.wMilliseconds
= 0;
2213 SystemTimeToFileTime (&st
, &utc_base_ft
);
2214 utc_base
= (long double) utc_base_ft
.dwHighDateTime
2215 * 4096 * 1024 * 1024 + utc_base_ft
.dwLowDateTime
;
2219 if (CompareFileTime (&ft
, &utc_base_ft
) < 0)
2222 ret
= (long double) ft
.dwHighDateTime
* 4096 * 1024 * 1024 + ft
.dwLowDateTime
;
2224 return (time_t) (ret
* 1e-7);
2228 convert_from_time_t (time_t time
, FILETIME
* pft
)
2234 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
2243 st
.wMilliseconds
= 0;
2245 SystemTimeToFileTime (&st
, &utc_base_ft
);
2246 utc_base
= (long double) utc_base_ft
.dwHighDateTime
2247 * 4096 * 1024 * 1024 + utc_base_ft
.dwLowDateTime
;
2251 /* time in 100ns units since 1-Jan-1601 */
2252 tmp
= (long double) time
* 1e7
+ utc_base
;
2253 pft
->dwHighDateTime
= (DWORD
) (tmp
/ (4096.0 * 1024 * 1024));
2254 pft
->dwLowDateTime
= (DWORD
) (tmp
- (4096.0 * 1024 * 1024) * pft
->dwHighDateTime
);
2258 /* No reason to keep this; faking inode values either by hashing or even
2259 using the file index from GetInformationByHandle, is not perfect and
2260 so by default Emacs doesn't use the inode values on Windows.
2261 Instead, we now determine file-truename correctly (except for
2262 possible drive aliasing etc). */
2264 /* Modified version of "PJW" algorithm (see the "Dragon" compiler book). */
2266 hashval (const unsigned char * str
)
2271 h
= (h
<< 4) + *str
++;
2277 /* Return the hash value of the canonical pathname, excluding the
2278 drive/UNC header, to get a hopefully unique inode number. */
2280 generate_inode_val (const char * name
)
2282 char fullname
[ MAX_PATH
];
2286 /* Get the truly canonical filename, if it exists. (Note: this
2287 doesn't resolve aliasing due to subst commands, or recognise hard
2289 if (!w32_get_long_filename ((char *)name
, fullname
, MAX_PATH
))
2292 parse_root (fullname
, &p
);
2293 /* Normal W32 filesystems are still case insensitive. */
2300 /* MSVC stat function can't cope with UNC names and has other bugs, so
2301 replace it with our own. This also allows us to calculate consistent
2302 inode values without hacks in the main Emacs code. */
2304 stat (const char * path
, struct stat
* buf
)
2307 WIN32_FIND_DATA wfd
;
2312 int rootdir
= FALSE
;
2314 if (path
== NULL
|| buf
== NULL
)
2320 name
= (char *) map_w32_filename (path
, &path
);
2321 /* must be valid filename, no wild cards or other invalid characters */
2322 if (strpbrk (name
, "*?|<>\""))
2328 /* If name is "c:/.." or "/.." then stat "c:/" or "/". */
2329 r
= IS_DEVICE_SEP (name
[1]) ? &name
[2] : name
;
2330 if (IS_DIRECTORY_SEP (r
[0]) && r
[1] == '.' && r
[2] == '.' && r
[3] == '\0')
2335 /* Remove trailing directory separator, unless name is the root
2336 directory of a drive or UNC volume in which case ensure there
2337 is a trailing separator. */
2338 len
= strlen (name
);
2339 rootdir
= (path
>= name
+ len
- 1
2340 && (IS_DIRECTORY_SEP (*path
) || *path
== 0));
2341 name
= strcpy (alloca (len
+ 2), name
);
2343 if (is_unc_volume (name
))
2345 DWORD attrs
= unc_volume_file_attributes (name
);
2350 memset (&wfd
, 0, sizeof (wfd
));
2351 wfd
.dwFileAttributes
= attrs
;
2352 wfd
.ftCreationTime
= utc_base_ft
;
2353 wfd
.ftLastAccessTime
= utc_base_ft
;
2354 wfd
.ftLastWriteTime
= utc_base_ft
;
2355 strcpy (wfd
.cFileName
, name
);
2359 if (!IS_DIRECTORY_SEP (name
[len
-1]))
2360 strcat (name
, "\\");
2361 if (GetDriveType (name
) < 2)
2366 memset (&wfd
, 0, sizeof (wfd
));
2367 wfd
.dwFileAttributes
= FILE_ATTRIBUTE_DIRECTORY
;
2368 wfd
.ftCreationTime
= utc_base_ft
;
2369 wfd
.ftLastAccessTime
= utc_base_ft
;
2370 wfd
.ftLastWriteTime
= utc_base_ft
;
2371 strcpy (wfd
.cFileName
, name
);
2375 if (IS_DIRECTORY_SEP (name
[len
-1]))
2378 /* (This is hacky, but helps when doing file completions on
2379 network drives.) Optimize by using information available from
2380 active readdir if possible. */
2381 len
= strlen (dir_pathname
);
2382 if (IS_DIRECTORY_SEP (dir_pathname
[len
-1]))
2384 if (dir_find_handle
!= INVALID_HANDLE_VALUE
2385 && strnicmp (name
, dir_pathname
, len
) == 0
2386 && IS_DIRECTORY_SEP (name
[len
])
2387 && stricmp (name
+ len
+ 1, dir_static
.d_name
) == 0)
2389 /* This was the last entry returned by readdir. */
2390 wfd
= dir_find_data
;
2394 fh
= FindFirstFile (name
, &wfd
);
2395 if (fh
== INVALID_HANDLE_VALUE
)
2404 if (!NILP (Vw32_get_true_file_attributes
)
2405 /* No access rights required to get info. */
2406 && (fh
= CreateFile (name
, 0, 0, NULL
, OPEN_EXISTING
,
2407 FILE_FLAG_BACKUP_SEMANTICS
, NULL
))
2408 != INVALID_HANDLE_VALUE
)
2410 /* This is more accurate in terms of gettting the correct number
2411 of links, but is quite slow (it is noticable when Emacs is
2412 making a list of file name completions). */
2413 BY_HANDLE_FILE_INFORMATION info
;
2415 if (GetFileInformationByHandle (fh
, &info
))
2417 buf
->st_nlink
= info
.nNumberOfLinks
;
2418 /* Might as well use file index to fake inode values, but this
2419 is not guaranteed to be unique unless we keep a handle open
2420 all the time (even then there are situations where it is
2421 not unique). Reputedly, there are at most 48 bits of info
2422 (on NTFS, presumably less on FAT). */
2423 fake_inode
= info
.nFileIndexLow
^ info
.nFileIndexHigh
;
2431 if (wfd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
2433 buf
->st_mode
= _S_IFDIR
;
2437 switch (GetFileType (fh
))
2439 case FILE_TYPE_DISK
:
2440 buf
->st_mode
= _S_IFREG
;
2442 case FILE_TYPE_PIPE
:
2443 buf
->st_mode
= _S_IFIFO
;
2445 case FILE_TYPE_CHAR
:
2446 case FILE_TYPE_UNKNOWN
:
2448 buf
->st_mode
= _S_IFCHR
;
2455 /* Don't bother to make this information more accurate. */
2456 buf
->st_mode
= (wfd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) ?
2457 _S_IFDIR
: _S_IFREG
;
2463 /* Not sure if there is any point in this. */
2464 if (!NILP (Vw32_generate_fake_inodes
))
2465 fake_inode
= generate_inode_val (name
);
2466 else if (fake_inode
== 0)
2468 /* For want of something better, try to make everything unique. */
2469 static DWORD gen_num
= 0;
2470 fake_inode
= ++gen_num
;
2474 /* MSVC defines _ino_t to be short; other libc's might not. */
2475 if (sizeof (buf
->st_ino
) == 2)
2476 buf
->st_ino
= fake_inode
^ (fake_inode
>> 16);
2478 buf
->st_ino
= fake_inode
;
2480 /* consider files to belong to current user */
2481 buf
->st_uid
= the_passwd
.pw_uid
;
2482 buf
->st_gid
= the_passwd
.pw_gid
;
2484 /* volume_info is set indirectly by map_w32_filename */
2485 buf
->st_dev
= volume_info
.serialnum
;
2486 buf
->st_rdev
= volume_info
.serialnum
;
2489 buf
->st_size
= wfd
.nFileSizeLow
;
2491 /* Convert timestamps to Unix format. */
2492 buf
->st_mtime
= convert_time (wfd
.ftLastWriteTime
);
2493 buf
->st_atime
= convert_time (wfd
.ftLastAccessTime
);
2494 if (buf
->st_atime
== 0) buf
->st_atime
= buf
->st_mtime
;
2495 buf
->st_ctime
= convert_time (wfd
.ftCreationTime
);
2496 if (buf
->st_ctime
== 0) buf
->st_ctime
= buf
->st_mtime
;
2498 /* determine rwx permissions */
2499 if (wfd
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
)
2500 permission
= _S_IREAD
;
2502 permission
= _S_IREAD
| _S_IWRITE
;
2504 if (wfd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
2505 permission
|= _S_IEXEC
;
2506 else if (is_exec (name
))
2507 permission
|= _S_IEXEC
;
2509 buf
->st_mode
|= permission
| (permission
>> 3) | (permission
>> 6);
2514 /* Provide fstat and utime as well as stat for consistent handling of
2517 fstat (int desc
, struct stat
* buf
)
2519 HANDLE fh
= (HANDLE
) _get_osfhandle (desc
);
2520 BY_HANDLE_FILE_INFORMATION info
;
2524 switch (GetFileType (fh
) & ~FILE_TYPE_REMOTE
)
2526 case FILE_TYPE_DISK
:
2527 buf
->st_mode
= _S_IFREG
;
2528 if (!GetFileInformationByHandle (fh
, &info
))
2534 case FILE_TYPE_PIPE
:
2535 buf
->st_mode
= _S_IFIFO
;
2537 case FILE_TYPE_CHAR
:
2538 case FILE_TYPE_UNKNOWN
:
2540 buf
->st_mode
= _S_IFCHR
;
2542 memset (&info
, 0, sizeof (info
));
2543 info
.dwFileAttributes
= 0;
2544 info
.ftCreationTime
= utc_base_ft
;
2545 info
.ftLastAccessTime
= utc_base_ft
;
2546 info
.ftLastWriteTime
= utc_base_ft
;
2549 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
2550 buf
->st_mode
= _S_IFDIR
;
2552 buf
->st_nlink
= info
.nNumberOfLinks
;
2553 /* Might as well use file index to fake inode values, but this
2554 is not guaranteed to be unique unless we keep a handle open
2555 all the time (even then there are situations where it is
2556 not unique). Reputedly, there are at most 48 bits of info
2557 (on NTFS, presumably less on FAT). */
2558 fake_inode
= info
.nFileIndexLow
^ info
.nFileIndexHigh
;
2560 /* MSVC defines _ino_t to be short; other libc's might not. */
2561 if (sizeof (buf
->st_ino
) == 2)
2562 buf
->st_ino
= fake_inode
^ (fake_inode
>> 16);
2564 buf
->st_ino
= fake_inode
;
2566 /* consider files to belong to current user */
2570 buf
->st_dev
= info
.dwVolumeSerialNumber
;
2571 buf
->st_rdev
= info
.dwVolumeSerialNumber
;
2573 buf
->st_size
= info
.nFileSizeLow
;
2575 /* Convert timestamps to Unix format. */
2576 buf
->st_mtime
= convert_time (info
.ftLastWriteTime
);
2577 buf
->st_atime
= convert_time (info
.ftLastAccessTime
);
2578 if (buf
->st_atime
== 0) buf
->st_atime
= buf
->st_mtime
;
2579 buf
->st_ctime
= convert_time (info
.ftCreationTime
);
2580 if (buf
->st_ctime
== 0) buf
->st_ctime
= buf
->st_mtime
;
2582 /* determine rwx permissions */
2583 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
)
2584 permission
= _S_IREAD
;
2586 permission
= _S_IREAD
| _S_IWRITE
;
2588 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
2589 permission
|= _S_IEXEC
;
2592 #if 0 /* no way of knowing the filename */
2593 char * p
= strrchr (name
, '.');
2595 (stricmp (p
, ".exe") == 0 ||
2596 stricmp (p
, ".com") == 0 ||
2597 stricmp (p
, ".bat") == 0 ||
2598 stricmp (p
, ".cmd") == 0))
2599 permission
|= _S_IEXEC
;
2603 buf
->st_mode
|= permission
| (permission
>> 3) | (permission
>> 6);
2609 utime (const char *name
, struct utimbuf
*times
)
2611 struct utimbuf deftime
;
2618 deftime
.modtime
= deftime
.actime
= time (NULL
);
2622 /* Need write access to set times. */
2623 fh
= CreateFile (name
, GENERIC_WRITE
, FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2624 0, OPEN_EXISTING
, 0, NULL
);
2627 convert_from_time_t (times
->actime
, &atime
);
2628 convert_from_time_t (times
->modtime
, &mtime
);
2629 if (!SetFileTime (fh
, NULL
, &atime
, &mtime
))
2647 /* Wrappers for winsock functions to map between our file descriptors
2648 and winsock's handles; also set h_errno for convenience.
2650 To allow Emacs to run on systems which don't have winsock support
2651 installed, we dynamically link to winsock on startup if present, and
2652 otherwise provide the minimum necessary functionality
2653 (eg. gethostname). */
2655 /* function pointers for relevant socket functions */
2656 int (PASCAL
*pfn_WSAStartup
) (WORD wVersionRequired
, LPWSADATA lpWSAData
);
2657 void (PASCAL
*pfn_WSASetLastError
) (int iError
);
2658 int (PASCAL
*pfn_WSAGetLastError
) (void);
2659 int (PASCAL
*pfn_socket
) (int af
, int type
, int protocol
);
2660 int (PASCAL
*pfn_bind
) (SOCKET s
, const struct sockaddr
*addr
, int namelen
);
2661 int (PASCAL
*pfn_connect
) (SOCKET s
, const struct sockaddr
*addr
, int namelen
);
2662 int (PASCAL
*pfn_ioctlsocket
) (SOCKET s
, long cmd
, u_long
*argp
);
2663 int (PASCAL
*pfn_recv
) (SOCKET s
, char * buf
, int len
, int flags
);
2664 int (PASCAL
*pfn_send
) (SOCKET s
, const char * buf
, int len
, int flags
);
2665 int (PASCAL
*pfn_closesocket
) (SOCKET s
);
2666 int (PASCAL
*pfn_shutdown
) (SOCKET s
, int how
);
2667 int (PASCAL
*pfn_WSACleanup
) (void);
2669 u_short (PASCAL
*pfn_htons
) (u_short hostshort
);
2670 u_short (PASCAL
*pfn_ntohs
) (u_short netshort
);
2671 unsigned long (PASCAL
*pfn_inet_addr
) (const char * cp
);
2672 int (PASCAL
*pfn_gethostname
) (char * name
, int namelen
);
2673 struct hostent
* (PASCAL
*pfn_gethostbyname
) (const char * name
);
2674 struct servent
* (PASCAL
*pfn_getservbyname
) (const char * name
, const char * proto
);
2675 int (PASCAL
*pfn_getpeername
) (SOCKET s
, struct sockaddr
*addr
, int * namelen
);
2676 int (PASCAL
*pfn_setsockopt
) (SOCKET s
, int level
, int optname
,
2677 const char * optval
, int optlen
);
2678 int (PASCAL
*pfn_listen
) (SOCKET s
, int backlog
);
2679 int (PASCAL
*pfn_getsockname
) (SOCKET s
, struct sockaddr
* name
,
2681 SOCKET (PASCAL
*pfn_accept
) (SOCKET s
, struct sockaddr
* addr
, int * addrlen
);
2682 int (PASCAL
*pfn_recvfrom
) (SOCKET s
, char * buf
, int len
, int flags
,
2683 struct sockaddr
* from
, int * fromlen
);
2684 int (PASCAL
*pfn_sendto
) (SOCKET s
, const char * buf
, int len
, int flags
,
2685 const struct sockaddr
* to
, int tolen
);
2687 /* SetHandleInformation is only needed to make sockets non-inheritable. */
2688 BOOL (WINAPI
*pfn_SetHandleInformation
) (HANDLE object
, DWORD mask
, DWORD flags
);
2689 #ifndef HANDLE_FLAG_INHERIT
2690 #define HANDLE_FLAG_INHERIT 1
2694 static int winsock_inuse
;
2699 if (winsock_lib
!= NULL
&& winsock_inuse
== 0)
2701 /* Not sure what would cause WSAENETDOWN, or even if it can happen
2702 after WSAStartup returns successfully, but it seems reasonable
2703 to allow unloading winsock anyway in that case. */
2704 if (pfn_WSACleanup () == 0 ||
2705 pfn_WSAGetLastError () == WSAENETDOWN
)
2707 if (FreeLibrary (winsock_lib
))
2716 init_winsock (int load_now
)
2718 WSADATA winsockData
;
2720 if (winsock_lib
!= NULL
)
2723 pfn_SetHandleInformation
= NULL
;
2724 pfn_SetHandleInformation
2725 = (void *) GetProcAddress (GetModuleHandle ("kernel32.dll"),
2726 "SetHandleInformation");
2728 winsock_lib
= LoadLibrary ("wsock32.dll");
2730 if (winsock_lib
!= NULL
)
2732 /* dynamically link to socket functions */
2734 #define LOAD_PROC(fn) \
2735 if ((pfn_##fn = (void *) GetProcAddress (winsock_lib, #fn)) == NULL) \
2738 LOAD_PROC( WSAStartup
);
2739 LOAD_PROC( WSASetLastError
);
2740 LOAD_PROC( WSAGetLastError
);
2741 LOAD_PROC( socket
);
2743 LOAD_PROC( connect
);
2744 LOAD_PROC( ioctlsocket
);
2747 LOAD_PROC( closesocket
);
2748 LOAD_PROC( shutdown
);
2751 LOAD_PROC( inet_addr
);
2752 LOAD_PROC( gethostname
);
2753 LOAD_PROC( gethostbyname
);
2754 LOAD_PROC( getservbyname
);
2755 LOAD_PROC( getpeername
);
2756 LOAD_PROC( WSACleanup
);
2757 LOAD_PROC( setsockopt
);
2758 LOAD_PROC( listen
);
2759 LOAD_PROC( getsockname
);
2760 LOAD_PROC( accept
);
2761 LOAD_PROC( recvfrom
);
2762 LOAD_PROC( sendto
);
2765 /* specify version 1.1 of winsock */
2766 if (pfn_WSAStartup (0x101, &winsockData
) == 0)
2768 if (winsockData
.wVersion
!= 0x101)
2773 /* Report that winsock exists and is usable, but leave
2774 socket functions disabled. I am assuming that calling
2775 WSAStartup does not require any network interaction,
2776 and in particular does not cause or require a dial-up
2777 connection to be established. */
2780 FreeLibrary (winsock_lib
);
2788 FreeLibrary (winsock_lib
);
2798 /* function to set h_errno for compatability; map winsock error codes to
2799 normal system codes where they overlap (non-overlapping definitions
2800 are already in <sys/socket.h> */
2801 static void set_errno ()
2803 if (winsock_lib
== NULL
)
2806 h_errno
= pfn_WSAGetLastError ();
2810 case WSAEACCES
: h_errno
= EACCES
; break;
2811 case WSAEBADF
: h_errno
= EBADF
; break;
2812 case WSAEFAULT
: h_errno
= EFAULT
; break;
2813 case WSAEINTR
: h_errno
= EINTR
; break;
2814 case WSAEINVAL
: h_errno
= EINVAL
; break;
2815 case WSAEMFILE
: h_errno
= EMFILE
; break;
2816 case WSAENAMETOOLONG
: h_errno
= ENAMETOOLONG
; break;
2817 case WSAENOTEMPTY
: h_errno
= ENOTEMPTY
; break;
2822 static void check_errno ()
2824 if (h_errno
== 0 && winsock_lib
!= NULL
)
2825 pfn_WSASetLastError (0);
2828 /* Extend strerror to handle the winsock-specific error codes. */
2832 } _wsa_errlist
[] = {
2833 WSAEINTR
, "Interrupted function call",
2834 WSAEBADF
, "Bad file descriptor",
2835 WSAEACCES
, "Permission denied",
2836 WSAEFAULT
, "Bad address",
2837 WSAEINVAL
, "Invalid argument",
2838 WSAEMFILE
, "Too many open files",
2840 WSAEWOULDBLOCK
, "Resource temporarily unavailable",
2841 WSAEINPROGRESS
, "Operation now in progress",
2842 WSAEALREADY
, "Operation already in progress",
2843 WSAENOTSOCK
, "Socket operation on non-socket",
2844 WSAEDESTADDRREQ
, "Destination address required",
2845 WSAEMSGSIZE
, "Message too long",
2846 WSAEPROTOTYPE
, "Protocol wrong type for socket",
2847 WSAENOPROTOOPT
, "Bad protocol option",
2848 WSAEPROTONOSUPPORT
, "Protocol not supported",
2849 WSAESOCKTNOSUPPORT
, "Socket type not supported",
2850 WSAEOPNOTSUPP
, "Operation not supported",
2851 WSAEPFNOSUPPORT
, "Protocol family not supported",
2852 WSAEAFNOSUPPORT
, "Address family not supported by protocol family",
2853 WSAEADDRINUSE
, "Address already in use",
2854 WSAEADDRNOTAVAIL
, "Cannot assign requested address",
2855 WSAENETDOWN
, "Network is down",
2856 WSAENETUNREACH
, "Network is unreachable",
2857 WSAENETRESET
, "Network dropped connection on reset",
2858 WSAECONNABORTED
, "Software caused connection abort",
2859 WSAECONNRESET
, "Connection reset by peer",
2860 WSAENOBUFS
, "No buffer space available",
2861 WSAEISCONN
, "Socket is already connected",
2862 WSAENOTCONN
, "Socket is not connected",
2863 WSAESHUTDOWN
, "Cannot send after socket shutdown",
2864 WSAETOOMANYREFS
, "Too many references", /* not sure */
2865 WSAETIMEDOUT
, "Connection timed out",
2866 WSAECONNREFUSED
, "Connection refused",
2867 WSAELOOP
, "Network loop", /* not sure */
2868 WSAENAMETOOLONG
, "Name is too long",
2869 WSAEHOSTDOWN
, "Host is down",
2870 WSAEHOSTUNREACH
, "No route to host",
2871 WSAENOTEMPTY
, "Buffer not empty", /* not sure */
2872 WSAEPROCLIM
, "Too many processes",
2873 WSAEUSERS
, "Too many users", /* not sure */
2874 WSAEDQUOT
, "Double quote in host name", /* really not sure */
2875 WSAESTALE
, "Data is stale", /* not sure */
2876 WSAEREMOTE
, "Remote error", /* not sure */
2878 WSASYSNOTREADY
, "Network subsystem is unavailable",
2879 WSAVERNOTSUPPORTED
, "WINSOCK.DLL version out of range",
2880 WSANOTINITIALISED
, "Winsock not initialized successfully",
2881 WSAEDISCON
, "Graceful shutdown in progress",
2883 WSAENOMORE
, "No more operations allowed", /* not sure */
2884 WSAECANCELLED
, "Operation cancelled", /* not sure */
2885 WSAEINVALIDPROCTABLE
, "Invalid procedure table from service provider",
2886 WSAEINVALIDPROVIDER
, "Invalid service provider version number",
2887 WSAEPROVIDERFAILEDINIT
, "Unable to initialize a service provider",
2888 WSASYSCALLFAILURE
, "System call failured",
2889 WSASERVICE_NOT_FOUND
, "Service not found", /* not sure */
2890 WSATYPE_NOT_FOUND
, "Class type not found",
2891 WSA_E_NO_MORE
, "No more resources available", /* really not sure */
2892 WSA_E_CANCELLED
, "Operation already cancelled", /* really not sure */
2893 WSAEREFUSED
, "Operation refused", /* not sure */
2896 WSAHOST_NOT_FOUND
, "Host not found",
2897 WSATRY_AGAIN
, "Authoritative host not found during name lookup",
2898 WSANO_RECOVERY
, "Non-recoverable error during name lookup",
2899 WSANO_DATA
, "Valid name, no data record of requested type",
2905 sys_strerror(int error_no
)
2908 static char unknown_msg
[40];
2910 if (error_no
>= 0 && error_no
< sys_nerr
)
2911 return sys_errlist
[error_no
];
2913 for (i
= 0; _wsa_errlist
[i
].errnum
>= 0; i
++)
2914 if (_wsa_errlist
[i
].errnum
== error_no
)
2915 return _wsa_errlist
[i
].msg
;
2917 sprintf(unknown_msg
, "Unidentified error: %d", error_no
);
2921 /* [andrewi 3-May-96] I've had conflicting results using both methods,
2922 but I believe the method of keeping the socket handle separate (and
2923 insuring it is not inheritable) is the correct one. */
2925 //#define SOCK_REPLACE_HANDLE
2927 #ifdef SOCK_REPLACE_HANDLE
2928 #define SOCK_HANDLE(fd) ((SOCKET) _get_osfhandle (fd))
2930 #define SOCK_HANDLE(fd) ((SOCKET) fd_info[fd].hnd)
2933 int socket_to_fd (SOCKET s
);
2936 sys_socket(int af
, int type
, int protocol
)
2940 if (winsock_lib
== NULL
)
2943 return INVALID_SOCKET
;
2948 /* call the real socket function */
2949 s
= pfn_socket (af
, type
, protocol
);
2951 if (s
!= INVALID_SOCKET
)
2952 return socket_to_fd (s
);
2958 /* Convert a SOCKET to a file descriptor. */
2960 socket_to_fd (SOCKET s
)
2965 /* Although under NT 3.5 _open_osfhandle will accept a socket
2966 handle, if opened with SO_OPENTYPE == SO_SYNCHRONOUS_NONALERT,
2967 that does not work under NT 3.1. However, we can get the same
2968 effect by using a backdoor function to replace an existing
2969 descriptor handle with the one we want. */
2971 /* allocate a file descriptor (with appropriate flags) */
2972 fd
= _open ("NUL:", _O_RDWR
);
2975 #ifdef SOCK_REPLACE_HANDLE
2976 /* now replace handle to NUL with our socket handle */
2977 CloseHandle ((HANDLE
) _get_osfhandle (fd
));
2979 _set_osfhnd (fd
, s
);
2980 /* setmode (fd, _O_BINARY); */
2982 /* Make a non-inheritable copy of the socket handle. Note
2983 that it is possible that sockets aren't actually kernel
2984 handles, which appears to be the case on Windows 9x when
2985 the MS Proxy winsock client is installed. */
2987 /* Apparently there is a bug in NT 3.51 with some service
2988 packs, which prevents using DuplicateHandle to make a
2989 socket handle non-inheritable (causes WSACleanup to
2990 hang). The work-around is to use SetHandleInformation
2991 instead if it is available and implemented. */
2992 if (pfn_SetHandleInformation
)
2994 pfn_SetHandleInformation ((HANDLE
) s
, HANDLE_FLAG_INHERIT
, 0);
2998 HANDLE parent
= GetCurrentProcess ();
2999 HANDLE new_s
= INVALID_HANDLE_VALUE
;
3001 if (DuplicateHandle (parent
,
3007 DUPLICATE_SAME_ACCESS
))
3009 /* It is possible that DuplicateHandle succeeds even
3010 though the socket wasn't really a kernel handle,
3011 because a real handle has the same value. So
3012 test whether the new handle really is a socket. */
3013 long nonblocking
= 0;
3014 if (pfn_ioctlsocket ((SOCKET
) new_s
, FIONBIO
, &nonblocking
) == 0)
3016 pfn_closesocket (s
);
3021 CloseHandle (new_s
);
3026 fd_info
[fd
].hnd
= (HANDLE
) s
;
3029 /* set our own internal flags */
3030 fd_info
[fd
].flags
= FILE_SOCKET
| FILE_BINARY
| FILE_READ
| FILE_WRITE
;
3036 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
3038 /* attach child_process to fd_info */
3039 if (fd_info
[ fd
].cp
!= NULL
)
3041 DebPrint (("sys_socket: fd_info[%d] apparently in use!\n", fd
));
3045 fd_info
[ fd
].cp
= cp
;
3048 winsock_inuse
++; /* count open sockets */
3055 pfn_closesocket (s
);
3062 sys_bind (int s
, const struct sockaddr
* addr
, int namelen
)
3064 if (winsock_lib
== NULL
)
3067 return SOCKET_ERROR
;
3071 if (fd_info
[s
].flags
& FILE_SOCKET
)
3073 int rc
= pfn_bind (SOCK_HANDLE (s
), addr
, namelen
);
3074 if (rc
== SOCKET_ERROR
)
3079 return SOCKET_ERROR
;
3084 sys_connect (int s
, const struct sockaddr
* name
, int namelen
)
3086 if (winsock_lib
== NULL
)
3089 return SOCKET_ERROR
;
3093 if (fd_info
[s
].flags
& FILE_SOCKET
)
3095 int rc
= pfn_connect (SOCK_HANDLE (s
), name
, namelen
);
3096 if (rc
== SOCKET_ERROR
)
3101 return SOCKET_ERROR
;
3105 sys_htons (u_short hostshort
)
3107 return (winsock_lib
!= NULL
) ?
3108 pfn_htons (hostshort
) : hostshort
;
3112 sys_ntohs (u_short netshort
)
3114 return (winsock_lib
!= NULL
) ?
3115 pfn_ntohs (netshort
) : netshort
;
3119 sys_inet_addr (const char * cp
)
3121 return (winsock_lib
!= NULL
) ?
3122 pfn_inet_addr (cp
) : INADDR_NONE
;
3126 sys_gethostname (char * name
, int namelen
)
3128 if (winsock_lib
!= NULL
)
3129 return pfn_gethostname (name
, namelen
);
3131 if (namelen
> MAX_COMPUTERNAME_LENGTH
)
3132 return !GetComputerName (name
, (DWORD
*)&namelen
);
3135 return SOCKET_ERROR
;
3139 sys_gethostbyname(const char * name
)
3141 struct hostent
* host
;
3143 if (winsock_lib
== NULL
)
3150 host
= pfn_gethostbyname (name
);
3157 sys_getservbyname(const char * name
, const char * proto
)
3159 struct servent
* serv
;
3161 if (winsock_lib
== NULL
)
3168 serv
= pfn_getservbyname (name
, proto
);
3175 sys_getpeername (int s
, struct sockaddr
*addr
, int * namelen
)
3177 if (winsock_lib
== NULL
)
3180 return SOCKET_ERROR
;
3184 if (fd_info
[s
].flags
& FILE_SOCKET
)
3186 int rc
= pfn_getpeername (SOCK_HANDLE (s
), addr
, namelen
);
3187 if (rc
== SOCKET_ERROR
)
3192 return SOCKET_ERROR
;
3197 sys_shutdown (int s
, int how
)
3199 if (winsock_lib
== NULL
)
3202 return SOCKET_ERROR
;
3206 if (fd_info
[s
].flags
& FILE_SOCKET
)
3208 int rc
= pfn_shutdown (SOCK_HANDLE (s
), how
);
3209 if (rc
== SOCKET_ERROR
)
3214 return SOCKET_ERROR
;
3218 sys_setsockopt (int s
, int level
, int optname
, const void * optval
, int optlen
)
3220 if (winsock_lib
== NULL
)
3223 return SOCKET_ERROR
;
3227 if (fd_info
[s
].flags
& FILE_SOCKET
)
3229 int rc
= pfn_setsockopt (SOCK_HANDLE (s
), level
, optname
,
3230 (const char *)optval
, optlen
);
3231 if (rc
== SOCKET_ERROR
)
3236 return SOCKET_ERROR
;
3240 sys_listen (int s
, int backlog
)
3242 if (winsock_lib
== NULL
)
3245 return SOCKET_ERROR
;
3249 if (fd_info
[s
].flags
& FILE_SOCKET
)
3251 int rc
= pfn_listen (SOCK_HANDLE (s
), backlog
);
3252 if (rc
== SOCKET_ERROR
)
3257 return SOCKET_ERROR
;
3261 sys_getsockname (int s
, struct sockaddr
* name
, int * namelen
)
3263 if (winsock_lib
== NULL
)
3266 return SOCKET_ERROR
;
3270 if (fd_info
[s
].flags
& FILE_SOCKET
)
3272 int rc
= pfn_getsockname (SOCK_HANDLE (s
), name
, namelen
);
3273 if (rc
== SOCKET_ERROR
)
3278 return SOCKET_ERROR
;
3282 sys_accept (int s
, struct sockaddr
* addr
, int * addrlen
)
3284 if (winsock_lib
== NULL
)
3291 if (fd_info
[s
].flags
& FILE_SOCKET
)
3293 SOCKET t
= pfn_accept (SOCK_HANDLE (s
), addr
, addrlen
);
3294 if (t
!= INVALID_SOCKET
)
3295 return socket_to_fd (t
);
3305 sys_recvfrom (int s
, char * buf
, int len
, int flags
,
3306 struct sockaddr
* from
, int * fromlen
)
3308 if (winsock_lib
== NULL
)
3311 return SOCKET_ERROR
;
3315 if (fd_info
[s
].flags
& FILE_SOCKET
)
3317 int rc
= pfn_recvfrom (SOCK_HANDLE (s
), buf
, len
, flags
, from
, fromlen
);
3318 if (rc
== SOCKET_ERROR
)
3323 return SOCKET_ERROR
;
3327 sys_sendto (int s
, const char * buf
, int len
, int flags
,
3328 const struct sockaddr
* to
, int tolen
)
3330 if (winsock_lib
== NULL
)
3333 return SOCKET_ERROR
;
3337 if (fd_info
[s
].flags
& FILE_SOCKET
)
3339 int rc
= pfn_sendto (SOCK_HANDLE (s
), buf
, len
, flags
, to
, tolen
);
3340 if (rc
== SOCKET_ERROR
)
3345 return SOCKET_ERROR
;
3348 /* Windows does not have an fcntl function. Provide an implementation
3349 solely for making sockets non-blocking. */
3351 fcntl (int s
, int cmd
, int options
)
3353 if (winsock_lib
== NULL
)
3360 if (fd_info
[s
].flags
& FILE_SOCKET
)
3362 if (cmd
== F_SETFL
&& options
== O_NDELAY
)
3364 unsigned long nblock
= 1;
3365 int rc
= pfn_ioctlsocket (SOCK_HANDLE (s
), FIONBIO
, &nblock
);
3366 if (rc
== SOCKET_ERROR
)
3368 /* Keep track of the fact that we set this to non-blocking. */
3369 fd_info
[s
].flags
|= FILE_NDELAY
;
3375 return SOCKET_ERROR
;
3379 return SOCKET_ERROR
;
3382 #endif /* HAVE_SOCKETS */
3385 /* Shadow main io functions: we need to handle pipes and sockets more
3386 intelligently, and implement non-blocking mode as well. */
3393 if (fd
< 0 || fd
>= MAXDESC
)
3401 child_process
* cp
= fd_info
[fd
].cp
;
3403 fd_info
[fd
].cp
= NULL
;
3405 if (CHILD_ACTIVE (cp
))
3407 /* if last descriptor to active child_process then cleanup */
3409 for (i
= 0; i
< MAXDESC
; i
++)
3413 if (fd_info
[i
].cp
== cp
)
3419 if (fd_info
[fd
].flags
& FILE_SOCKET
)
3421 #ifndef SOCK_REPLACE_HANDLE
3422 if (winsock_lib
== NULL
) abort ();
3424 pfn_shutdown (SOCK_HANDLE (fd
), 2);
3425 rc
= pfn_closesocket (SOCK_HANDLE (fd
));
3427 winsock_inuse
--; /* count open sockets */
3435 /* Note that sockets do not need special treatment here (at least on
3436 NT and Windows 95 using the standard tcp/ip stacks) - it appears that
3437 closesocket is equivalent to CloseHandle, which is to be expected
3438 because socket handles are fully fledged kernel handles. */
3442 fd_info
[fd
].flags
= 0;
3455 /* duplicate our internal info as well */
3456 fd_info
[new_fd
] = fd_info
[fd
];
3463 sys_dup2 (int src
, int dst
)
3467 if (dst
< 0 || dst
>= MAXDESC
)
3473 /* make sure we close the destination first if it's a pipe or socket */
3474 if (src
!= dst
&& fd_info
[dst
].flags
!= 0)
3477 rc
= _dup2 (src
, dst
);
3480 /* duplicate our internal info as well */
3481 fd_info
[dst
] = fd_info
[src
];
3486 /* Unix pipe() has only one arg */
3488 sys_pipe (int * phandles
)
3493 /* make pipe handles non-inheritable; when we spawn a child, we
3494 replace the relevant handle with an inheritable one. Also put
3495 pipes into binary mode; we will do text mode translation ourselves
3497 rc
= _pipe (phandles
, 0, _O_NOINHERIT
| _O_BINARY
);
3501 /* Protect against overflow, since Windows can open more handles than
3502 our fd_info array has room for. */
3503 if (phandles
[0] >= MAXDESC
|| phandles
[1] >= MAXDESC
)
3505 _close (phandles
[0]);
3506 _close (phandles
[1]);
3511 flags
= FILE_PIPE
| FILE_READ
| FILE_BINARY
;
3512 fd_info
[phandles
[0]].flags
= flags
;
3514 flags
= FILE_PIPE
| FILE_WRITE
| FILE_BINARY
;
3515 fd_info
[phandles
[1]].flags
= flags
;
3523 extern int w32_pipe_read_delay
;
3525 /* Function to do blocking read of one byte, needed to implement
3526 select. It is only allowed on sockets and pipes. */
3528 _sys_read_ahead (int fd
)
3533 if (fd
< 0 || fd
>= MAXDESC
)
3534 return STATUS_READ_ERROR
;
3536 cp
= fd_info
[fd
].cp
;
3538 if (cp
== NULL
|| cp
->fd
!= fd
|| cp
->status
!= STATUS_READ_READY
)
3539 return STATUS_READ_ERROR
;
3541 if ((fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SOCKET
)) == 0
3542 || (fd_info
[fd
].flags
& FILE_READ
) == 0)
3544 DebPrint (("_sys_read_ahead: internal error: fd %d is not a pipe or socket!\n", fd
));
3548 cp
->status
= STATUS_READ_IN_PROGRESS
;
3550 if (fd_info
[fd
].flags
& FILE_PIPE
)
3552 rc
= _read (fd
, &cp
->chr
, sizeof (char));
3554 /* Give subprocess time to buffer some more output for us before
3555 reporting that input is available; we need this because Windows 95
3556 connects DOS programs to pipes by making the pipe appear to be
3557 the normal console stdout - as a result most DOS programs will
3558 write to stdout without buffering, ie. one character at a
3559 time. Even some W32 programs do this - "dir" in a command
3560 shell on NT is very slow if we don't do this. */
3563 int wait
= w32_pipe_read_delay
;
3569 /* Yield remainder of our time slice, effectively giving a
3570 temporary priority boost to the child process. */
3575 else if (fd_info
[fd
].flags
& FILE_SOCKET
)
3577 unsigned long nblock
= 0;
3578 /* We always want this to block, so temporarily disable NDELAY. */
3579 if (fd_info
[fd
].flags
& FILE_NDELAY
)
3580 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
3582 rc
= pfn_recv (SOCK_HANDLE (fd
), &cp
->chr
, sizeof (char), 0);
3584 if (fd_info
[fd
].flags
& FILE_NDELAY
)
3587 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
3592 if (rc
== sizeof (char))
3593 cp
->status
= STATUS_READ_SUCCEEDED
;
3595 cp
->status
= STATUS_READ_FAILED
;
3601 sys_read (int fd
, char * buffer
, unsigned int count
)
3606 char * orig_buffer
= buffer
;
3608 if (fd
< 0 || fd
>= MAXDESC
)
3614 if (fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SOCKET
))
3616 child_process
*cp
= fd_info
[fd
].cp
;
3618 if ((fd_info
[fd
].flags
& FILE_READ
) == 0)
3626 /* re-read CR carried over from last read */
3627 if (fd_info
[fd
].flags
& FILE_LAST_CR
)
3629 if (fd_info
[fd
].flags
& FILE_BINARY
) abort ();
3633 fd_info
[fd
].flags
&= ~FILE_LAST_CR
;
3636 /* presence of a child_process structure means we are operating in
3637 non-blocking mode - otherwise we just call _read directly.
3638 Note that the child_process structure might be missing because
3639 reap_subprocess has been called; in this case the pipe is
3640 already broken, so calling _read on it is okay. */
3643 int current_status
= cp
->status
;
3645 switch (current_status
)
3647 case STATUS_READ_FAILED
:
3648 case STATUS_READ_ERROR
:
3649 /* report normal EOF if nothing in buffer */
3651 fd_info
[fd
].flags
|= FILE_AT_EOF
;
3654 case STATUS_READ_READY
:
3655 case STATUS_READ_IN_PROGRESS
:
3656 DebPrint (("sys_read called when read is in progress\n"));
3657 errno
= EWOULDBLOCK
;
3660 case STATUS_READ_SUCCEEDED
:
3661 /* consume read-ahead char */
3662 *buffer
++ = cp
->chr
;
3665 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
3666 ResetEvent (cp
->char_avail
);
3668 case STATUS_READ_ACKNOWLEDGED
:
3672 DebPrint (("sys_read: bad status %d\n", current_status
));
3677 if (fd_info
[fd
].flags
& FILE_PIPE
)
3679 PeekNamedPipe ((HANDLE
) _get_osfhandle (fd
), NULL
, 0, NULL
, &waiting
, NULL
);
3680 to_read
= min (waiting
, (DWORD
) count
);
3683 nchars
+= _read (fd
, buffer
, to_read
);
3686 else /* FILE_SOCKET */
3688 if (winsock_lib
== NULL
) abort ();
3690 /* do the equivalent of a non-blocking read */
3691 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONREAD
, &waiting
);
3692 if (waiting
== 0 && nchars
== 0)
3694 h_errno
= errno
= EWOULDBLOCK
;
3700 /* always use binary mode for sockets */
3701 int res
= pfn_recv (SOCK_HANDLE (fd
), buffer
, count
, 0);
3702 if (res
== SOCKET_ERROR
)
3704 DebPrint(("sys_read.recv failed with error %d on socket %ld\n",
3705 pfn_WSAGetLastError (), SOCK_HANDLE (fd
)));
3716 int nread
= _read (fd
, buffer
, count
);
3719 else if (nchars
== 0)
3724 fd_info
[fd
].flags
|= FILE_AT_EOF
;
3725 /* Perform text mode translation if required. */
3726 else if ((fd_info
[fd
].flags
& FILE_BINARY
) == 0)
3728 nchars
= crlf_to_lf (nchars
, orig_buffer
);
3729 /* If buffer contains only CR, return that. To be absolutely
3730 sure we should attempt to read the next char, but in
3731 practice a CR to be followed by LF would not appear by
3732 itself in the buffer. */
3733 if (nchars
> 1 && orig_buffer
[nchars
- 1] == 0x0d)
3735 fd_info
[fd
].flags
|= FILE_LAST_CR
;
3741 nchars
= _read (fd
, buffer
, count
);
3746 /* For now, don't bother with a non-blocking mode */
3748 sys_write (int fd
, const void * buffer
, unsigned int count
)
3752 if (fd
< 0 || fd
>= MAXDESC
)
3758 if (fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SOCKET
))
3760 if ((fd_info
[fd
].flags
& FILE_WRITE
) == 0)
3766 /* Perform text mode translation if required. */
3767 if ((fd_info
[fd
].flags
& FILE_BINARY
) == 0)
3769 char * tmpbuf
= alloca (count
* 2);
3770 unsigned char * src
= (void *)buffer
;
3771 unsigned char * dst
= tmpbuf
;
3776 unsigned char *next
;
3777 /* copy next line or remaining bytes */
3778 next
= _memccpy (dst
, src
, '\n', nbytes
);
3781 /* copied one line ending with '\n' */
3782 int copied
= next
- dst
;
3785 /* insert '\r' before '\n' */
3792 /* copied remaining partial line -> now finished */
3800 if (fd_info
[fd
].flags
& FILE_SOCKET
)
3802 unsigned long nblock
= 0;
3803 if (winsock_lib
== NULL
) abort ();
3805 /* TODO: implement select() properly so non-blocking I/O works. */
3806 /* For now, make sure the write blocks. */
3807 if (fd_info
[fd
].flags
& FILE_NDELAY
)
3808 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
3810 nchars
= pfn_send (SOCK_HANDLE (fd
), buffer
, count
, 0);
3812 /* Set the socket back to non-blocking if it was before,
3813 for other operations that support it. */
3814 if (fd_info
[fd
].flags
& FILE_NDELAY
)
3817 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
3820 if (nchars
== SOCKET_ERROR
)
3822 DebPrint(("sys_write.send failed with error %d on socket %ld\n",
3823 pfn_WSAGetLastError (), SOCK_HANDLE (fd
)));
3829 nchars
= _write (fd
, buffer
, count
);
3835 check_windows_init_file ()
3837 extern int noninteractive
, inhibit_window_system
;
3839 /* A common indication that Emacs is not installed properly is when
3840 it cannot find the Windows installation file. If this file does
3841 not exist in the expected place, tell the user. */
3843 if (!noninteractive
&& !inhibit_window_system
)
3845 extern Lisp_Object Vwindow_system
, Vload_path
, Qfile_exists_p
;
3846 Lisp_Object objs
[2];
3847 Lisp_Object full_load_path
;
3848 Lisp_Object init_file
;
3851 objs
[0] = Vload_path
;
3852 objs
[1] = decode_env_path (0, (getenv ("EMACSLOADPATH")));
3853 full_load_path
= Fappend (2, objs
);
3854 init_file
= build_string ("term/w32-win");
3855 fd
= openp (full_load_path
, init_file
, Vload_suffixes
, NULL
, Qnil
);
3858 Lisp_Object load_path_print
= Fprin1_to_string (full_load_path
, Qnil
);
3859 char *init_file_name
= SDATA (init_file
);
3860 char *load_path
= SDATA (load_path_print
);
3861 char *buffer
= alloca (1024);
3864 "The Emacs Windows initialization file \"%s.el\" "
3865 "could not be found in your Emacs installation. "
3866 "Emacs checked the following directories for this file:\n"
3868 "When Emacs cannot find this file, it usually means that it "
3869 "was not installed properly, or its distribution file was "
3870 "not unpacked properly.\nSee the README.W32 file in the "
3871 "top-level Emacs directory for more information.",
3872 init_file_name
, load_path
);
3875 "Emacs Abort Dialog",
3876 MB_OK
| MB_ICONEXCLAMATION
| MB_TASKMODAL
);
3877 /* Use the low-level Emacs abort. */
3892 /* shutdown the socket interface if necessary */
3903 /* Initialise the socket interface now if available and requested by
3904 the user by defining PRELOAD_WINSOCK; otherwise loading will be
3905 delayed until open-network-stream is called (w32-has-winsock can
3906 also be used to dynamically load or reload winsock).
3908 Conveniently, init_environment is called before us, so
3909 PRELOAD_WINSOCK can be set in the registry. */
3911 /* Always initialize this correctly. */
3914 if (getenv ("PRELOAD_WINSOCK") != NULL
)
3915 init_winsock (TRUE
);
3918 /* Initial preparation for subprocess support: replace our standard
3919 handles with non-inheritable versions. */
3922 HANDLE stdin_save
= INVALID_HANDLE_VALUE
;
3923 HANDLE stdout_save
= INVALID_HANDLE_VALUE
;
3924 HANDLE stderr_save
= INVALID_HANDLE_VALUE
;
3926 parent
= GetCurrentProcess ();
3928 /* ignore errors when duplicating and closing; typically the
3929 handles will be invalid when running as a gui program. */
3930 DuplicateHandle (parent
,
3931 GetStdHandle (STD_INPUT_HANDLE
),
3936 DUPLICATE_SAME_ACCESS
);
3938 DuplicateHandle (parent
,
3939 GetStdHandle (STD_OUTPUT_HANDLE
),
3944 DUPLICATE_SAME_ACCESS
);
3946 DuplicateHandle (parent
,
3947 GetStdHandle (STD_ERROR_HANDLE
),
3952 DUPLICATE_SAME_ACCESS
);
3958 if (stdin_save
!= INVALID_HANDLE_VALUE
)
3959 _open_osfhandle ((long) stdin_save
, O_TEXT
);
3961 _open ("nul", O_TEXT
| O_NOINHERIT
| O_RDONLY
);
3964 if (stdout_save
!= INVALID_HANDLE_VALUE
)
3965 _open_osfhandle ((long) stdout_save
, O_TEXT
);
3967 _open ("nul", O_TEXT
| O_NOINHERIT
| O_WRONLY
);
3970 if (stderr_save
!= INVALID_HANDLE_VALUE
)
3971 _open_osfhandle ((long) stderr_save
, O_TEXT
);
3973 _open ("nul", O_TEXT
| O_NOINHERIT
| O_WRONLY
);
3977 /* unfortunately, atexit depends on implementation of malloc */
3978 /* atexit (term_ntproc); */
3979 signal (SIGABRT
, term_ntproc
);
3981 /* determine which drives are fixed, for GetCachedVolumeInformation */
3983 /* GetDriveType must have trailing backslash. */
3984 char drive
[] = "A:\\";
3986 /* Loop over all possible drive letters */
3987 while (*drive
<= 'Z')
3989 /* Record if this drive letter refers to a fixed drive. */
3990 fixed_drives
[DRIVE_INDEX (*drive
)] =
3991 (GetDriveType (drive
) == DRIVE_FIXED
);
3996 /* Reset the volume info cache. */
3997 volume_cache
= NULL
;
4000 /* Check to see if Emacs has been installed correctly. */
4001 check_windows_init_file ();
4005 globals_of_w32 is used to initialize those global variables that
4006 must always be initialized on startup even when the global variable
4007 initialized is non zero (see the function main in emacs.c).
4009 void globals_of_w32 ()
4011 g_b_init_is_windows_9x
= 0;
4012 g_b_init_open_process_token
= 0;
4013 g_b_init_get_token_information
= 0;
4014 g_b_init_lookup_account_sid
= 0;
4015 g_b_init_get_sid_identifier_authority
= 0;
4020 /* arch-tag: 90442dd3-37be-482b-b272-ac752e3049f1
4021 (do not change this comment) */