1 /* Utility and Unix shadow routines for GNU Emacs on the Microsoft W32 API.
2 Copyright (C) 1994, 1995, 2000, 2001, 2002, 2003, 2004,
3 2005, 2006, 2007 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA.
22 Geoff Voelker (voelker@cs.washington.edu) 7-29-94
24 #include <stddef.h> /* for offsetof */
34 #include <sys/utime.h>
36 /* must include CRT headers *before* config.h */
71 #define _ANONYMOUS_UNION
72 #define _ANONYMOUS_STRUCT
77 #ifdef HAVE_SOCKETS /* TCP connection support, if kernel can do it */
78 #include <sys/socket.h>
103 typedef HRESULT (WINAPI
* ShGetFolderPath_fn
)
104 (IN HWND
, IN
int, IN HANDLE
, IN DWORD
, OUT
char *);
106 void globals_of_w32 ();
108 extern Lisp_Object Vw32_downcase_file_names
;
109 extern Lisp_Object Vw32_generate_fake_inodes
;
110 extern Lisp_Object Vw32_get_true_file_attributes
;
111 extern int w32_num_mouse_buttons
;
115 Initialization states
117 static BOOL g_b_init_is_windows_9x
;
118 static BOOL g_b_init_open_process_token
;
119 static BOOL g_b_init_get_token_information
;
120 static BOOL g_b_init_lookup_account_sid
;
121 static BOOL g_b_init_get_sid_identifier_authority
;
124 BEGIN: Wrapper functions around OpenProcessToken
125 and other functions in advapi32.dll that are only
126 supported in Windows NT / 2k / XP
128 /* ** Function pointer typedefs ** */
129 typedef BOOL (WINAPI
* OpenProcessToken_Proc
) (
130 HANDLE ProcessHandle
,
132 PHANDLE TokenHandle
);
133 typedef BOOL (WINAPI
* GetTokenInformation_Proc
) (
135 TOKEN_INFORMATION_CLASS TokenInformationClass
,
136 LPVOID TokenInformation
,
137 DWORD TokenInformationLength
,
138 PDWORD ReturnLength
);
140 const char * const LookupAccountSid_Name
= "LookupAccountSidW";
142 const char * const LookupAccountSid_Name
= "LookupAccountSidA";
144 typedef BOOL (WINAPI
* LookupAccountSid_Proc
) (
145 LPCTSTR lpSystemName
,
150 LPDWORD cbDomainName
,
151 PSID_NAME_USE peUse
);
152 typedef PSID_IDENTIFIER_AUTHORITY (WINAPI
* GetSidIdentifierAuthority_Proc
) (
155 /* ** A utility function ** */
159 static BOOL s_b_ret
=0;
160 OSVERSIONINFO os_ver
;
161 if (g_b_init_is_windows_9x
== 0)
163 g_b_init_is_windows_9x
= 1;
164 ZeroMemory(&os_ver
, sizeof(OSVERSIONINFO
));
165 os_ver
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
166 if (GetVersionEx (&os_ver
))
168 s_b_ret
= (os_ver
.dwPlatformId
== VER_PLATFORM_WIN32_WINDOWS
);
174 /* ** The wrapper functions ** */
176 BOOL WINAPI
open_process_token (
177 HANDLE ProcessHandle
,
181 static OpenProcessToken_Proc s_pfn_Open_Process_Token
= NULL
;
182 HMODULE hm_advapi32
= NULL
;
183 if (is_windows_9x () == TRUE
)
187 if (g_b_init_open_process_token
== 0)
189 g_b_init_open_process_token
= 1;
190 hm_advapi32
= LoadLibrary ("Advapi32.dll");
191 s_pfn_Open_Process_Token
=
192 (OpenProcessToken_Proc
) GetProcAddress (hm_advapi32
, "OpenProcessToken");
194 if (s_pfn_Open_Process_Token
== NULL
)
199 s_pfn_Open_Process_Token (
206 BOOL WINAPI
get_token_information (
208 TOKEN_INFORMATION_CLASS TokenInformationClass
,
209 LPVOID TokenInformation
,
210 DWORD TokenInformationLength
,
213 static GetTokenInformation_Proc s_pfn_Get_Token_Information
= NULL
;
214 HMODULE hm_advapi32
= NULL
;
215 if (is_windows_9x () == TRUE
)
219 if (g_b_init_get_token_information
== 0)
221 g_b_init_get_token_information
= 1;
222 hm_advapi32
= LoadLibrary ("Advapi32.dll");
223 s_pfn_Get_Token_Information
=
224 (GetTokenInformation_Proc
) GetProcAddress (hm_advapi32
, "GetTokenInformation");
226 if (s_pfn_Get_Token_Information
== NULL
)
231 s_pfn_Get_Token_Information (
233 TokenInformationClass
,
235 TokenInformationLength
,
240 BOOL WINAPI
lookup_account_sid (
241 LPCTSTR lpSystemName
,
246 LPDWORD cbDomainName
,
249 static LookupAccountSid_Proc s_pfn_Lookup_Account_Sid
= NULL
;
250 HMODULE hm_advapi32
= NULL
;
251 if (is_windows_9x () == TRUE
)
255 if (g_b_init_lookup_account_sid
== 0)
257 g_b_init_lookup_account_sid
= 1;
258 hm_advapi32
= LoadLibrary ("Advapi32.dll");
259 s_pfn_Lookup_Account_Sid
=
260 (LookupAccountSid_Proc
) GetProcAddress (hm_advapi32
, LookupAccountSid_Name
);
262 if (s_pfn_Lookup_Account_Sid
== NULL
)
267 s_pfn_Lookup_Account_Sid (
278 PSID_IDENTIFIER_AUTHORITY WINAPI
get_sid_identifier_authority (
281 static GetSidIdentifierAuthority_Proc s_pfn_Get_Sid_Identifier_Authority
= NULL
;
282 HMODULE hm_advapi32
= NULL
;
283 if (is_windows_9x () == TRUE
)
287 if (g_b_init_get_sid_identifier_authority
== 0)
289 g_b_init_get_sid_identifier_authority
= 1;
290 hm_advapi32
= LoadLibrary ("Advapi32.dll");
291 s_pfn_Get_Sid_Identifier_Authority
=
292 (GetSidIdentifierAuthority_Proc
) GetProcAddress (
293 hm_advapi32
, "GetSidIdentifierAuthority");
295 if (s_pfn_Get_Sid_Identifier_Authority
== NULL
)
299 return (s_pfn_Get_Sid_Identifier_Authority (pSid
));
303 END: Wrapper functions around OpenProcessToken
304 and other functions in advapi32.dll that are only
305 supported in Windows NT / 2k / XP
309 /* Equivalent of strerror for W32 error codes. */
311 w32_strerror (int error_no
)
313 static char buf
[500];
316 error_no
= GetLastError ();
319 if (!FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM
, NULL
,
321 0, /* choose most suitable language */
322 buf
, sizeof (buf
), NULL
))
323 sprintf (buf
, "w32 error %u", error_no
);
327 /* Return 1 if P is a valid pointer to an object of size SIZE. Return
328 0 if P is NOT a valid pointer. Return -1 if we cannot validate P.
330 This is called from alloc.c:valid_pointer_p. */
332 w32_valid_pointer_p (void *p
, int size
)
335 HANDLE h
= OpenProcess (PROCESS_VM_READ
, FALSE
, GetCurrentProcessId ());
339 unsigned char *buf
= alloca (size
);
340 int retval
= ReadProcessMemory (h
, p
, buf
, size
, &done
);
349 static char startup_dir
[MAXPATHLEN
];
351 /* Get the current working directory. */
356 if (GetCurrentDirectory (MAXPATHLEN
, dir
) > 0)
360 /* Emacs doesn't actually change directory itself, and we want to
361 force our real wd to be where emacs.exe is to avoid unnecessary
362 conflicts when trying to rename or delete directories. */
363 strcpy (dir
, startup_dir
);
369 /* Emulate gethostname. */
371 gethostname (char *buffer
, int size
)
373 /* NT only allows small host names, so the buffer is
374 certainly large enough. */
375 return !GetComputerName (buffer
, &size
);
377 #endif /* HAVE_SOCKETS */
379 /* Emulate getloadavg. */
381 getloadavg (double loadavg
[], int nelem
)
385 /* A faithful emulation is going to have to be saved for a rainy day. */
386 for (i
= 0; i
< nelem
; i
++)
393 /* Emulate getpwuid, getpwnam and others. */
395 #define PASSWD_FIELD_SIZE 256
397 static char the_passwd_name
[PASSWD_FIELD_SIZE
];
398 static char the_passwd_passwd
[PASSWD_FIELD_SIZE
];
399 static char the_passwd_gecos
[PASSWD_FIELD_SIZE
];
400 static char the_passwd_dir
[PASSWD_FIELD_SIZE
];
401 static char the_passwd_shell
[PASSWD_FIELD_SIZE
];
403 static struct passwd the_passwd
=
415 static struct group the_group
=
417 /* There are no groups on NT, so we just return "root" as the
425 return the_passwd
.pw_uid
;
431 /* I could imagine arguing for checking to see whether the user is
432 in the Administrators group and returning a UID of 0 for that
433 case, but I don't know how wise that would be in the long run. */
440 return the_passwd
.pw_gid
;
452 if (uid
== the_passwd
.pw_uid
)
464 getpwnam (char *name
)
468 pw
= getpwuid (getuid ());
472 if (stricmp (name
, pw
->pw_name
))
481 /* Find the user's real name by opening the process token and
482 looking up the name associated with the user-sid in that token.
484 Use the relative portion of the identifier authority value from
485 the user-sid as the user id value (same for group id using the
486 primary group sid from the process token). */
488 char user_sid
[256], name
[256], domain
[256];
489 DWORD length
= sizeof (name
), dlength
= sizeof (domain
), trash
;
491 SID_NAME_USE user_type
;
494 open_process_token (GetCurrentProcess (), TOKEN_QUERY
, &token
)
495 && get_token_information (
497 (PVOID
) user_sid
, sizeof (user_sid
), &trash
)
498 && lookup_account_sid (
499 NULL
, *((PSID
*) user_sid
), name
, &length
,
500 domain
, &dlength
, &user_type
)
503 strcpy (the_passwd
.pw_name
, name
);
504 /* Determine a reasonable uid value. */
505 if (stricmp ("administrator", name
) == 0)
507 the_passwd
.pw_uid
= 0;
508 the_passwd
.pw_gid
= 0;
512 SID_IDENTIFIER_AUTHORITY
* pSIA
;
514 pSIA
= get_sid_identifier_authority (*((PSID
*) user_sid
));
515 /* I believe the relative portion is the last 4 bytes (of 6)
517 the_passwd
.pw_uid
= ((pSIA
->Value
[2] << 24) +
518 (pSIA
->Value
[3] << 16) +
519 (pSIA
->Value
[4] << 8) +
520 (pSIA
->Value
[5] << 0));
521 /* restrict to conventional uid range for normal users */
522 the_passwd
.pw_uid
= the_passwd
.pw_uid
% 60001;
525 if (get_token_information (token
, TokenPrimaryGroup
,
526 (PVOID
) user_sid
, sizeof (user_sid
), &trash
))
528 SID_IDENTIFIER_AUTHORITY
* pSIA
;
530 pSIA
= get_sid_identifier_authority (*((PSID
*) user_sid
));
531 the_passwd
.pw_gid
= ((pSIA
->Value
[2] << 24) +
532 (pSIA
->Value
[3] << 16) +
533 (pSIA
->Value
[4] << 8) +
534 (pSIA
->Value
[5] << 0));
535 /* I don't know if this is necessary, but for safety... */
536 the_passwd
.pw_gid
= the_passwd
.pw_gid
% 60001;
539 the_passwd
.pw_gid
= the_passwd
.pw_uid
;
542 /* If security calls are not supported (presumably because we
543 are running under Windows 95), fallback to this. */
544 else if (GetUserName (name
, &length
))
546 strcpy (the_passwd
.pw_name
, name
);
547 if (stricmp ("administrator", name
) == 0)
548 the_passwd
.pw_uid
= 0;
550 the_passwd
.pw_uid
= 123;
551 the_passwd
.pw_gid
= the_passwd
.pw_uid
;
555 strcpy (the_passwd
.pw_name
, "unknown");
556 the_passwd
.pw_uid
= 123;
557 the_passwd
.pw_gid
= 123;
560 /* Ensure HOME and SHELL are defined. */
561 if (getenv ("HOME") == NULL
)
563 if (getenv ("SHELL") == NULL
)
566 /* Set dir and shell from environment variables. */
567 strcpy (the_passwd
.pw_dir
, getenv ("HOME"));
568 strcpy (the_passwd
.pw_shell
, getenv ("SHELL"));
577 /* rand () on NT gives us 15 random bits...hack together 30 bits. */
578 return ((rand () << 15) | rand ());
588 /* Normalize filename by converting all path separators to
589 the specified separator. Also conditionally convert upper
590 case path name components to lower case. */
593 normalize_filename (fp
, path_sep
)
600 /* Always lower-case drive letters a-z, even if the filesystem
601 preserves case in filenames.
602 This is so filenames can be compared by string comparison
603 functions that are case-sensitive. Even case-preserving filesystems
604 do not distinguish case in drive letters. */
605 if (fp
[1] == ':' && *fp
>= 'A' && *fp
<= 'Z')
611 if (NILP (Vw32_downcase_file_names
))
615 if (*fp
== '/' || *fp
== '\\')
622 sep
= path_sep
; /* convert to this path separator */
623 elem
= fp
; /* start of current path element */
626 if (*fp
>= 'a' && *fp
<= 'z')
627 elem
= 0; /* don't convert this element */
629 if (*fp
== 0 || *fp
== ':')
631 sep
= *fp
; /* restore current separator (or 0) */
632 *fp
= '/'; /* after conversion of this element */
635 if (*fp
== '/' || *fp
== '\\')
637 if (elem
&& elem
!= fp
)
639 *fp
= 0; /* temporary end of string */
640 _strlwr (elem
); /* while we convert to lower case */
642 *fp
= sep
; /* convert (or restore) path separator */
643 elem
= fp
+ 1; /* next element starts after separator */
649 /* Destructively turn backslashes into slashes. */
651 dostounix_filename (p
)
654 normalize_filename (p
, '/');
657 /* Destructively turn slashes into backslashes. */
659 unixtodos_filename (p
)
662 normalize_filename (p
, '\\');
665 /* Remove all CR's that are followed by a LF.
666 (From msdos.c...probably should figure out a way to share it,
667 although this code isn't going to ever change.) */
671 register unsigned char *buf
;
673 unsigned char *np
= buf
;
674 unsigned char *startp
= buf
;
675 unsigned char *endp
= buf
+ n
;
679 while (buf
< endp
- 1)
683 if (*(++buf
) != 0x0a)
694 /* Parse the root part of file name, if present. Return length and
695 optionally store pointer to char after root. */
697 parse_root (char * name
, char ** pPath
)
704 /* find the root name of the volume if given */
705 if (isalpha (name
[0]) && name
[1] == ':')
707 /* skip past drive specifier */
709 if (IS_DIRECTORY_SEP (name
[0]))
712 else if (IS_DIRECTORY_SEP (name
[0]) && IS_DIRECTORY_SEP (name
[1]))
718 if (IS_DIRECTORY_SEP (*name
) && --slashes
== 0)
723 if (IS_DIRECTORY_SEP (name
[0]))
733 /* Get long base name for name; name is assumed to be absolute. */
735 get_long_basename (char * name
, char * buf
, int size
)
737 WIN32_FIND_DATA find_data
;
741 /* must be valid filename, no wild cards or other invalid characters */
742 if (strpbrk (name
, "*?|<>\""))
745 dir_handle
= FindFirstFile (name
, &find_data
);
746 if (dir_handle
!= INVALID_HANDLE_VALUE
)
748 if ((len
= strlen (find_data
.cFileName
)) < size
)
749 memcpy (buf
, find_data
.cFileName
, len
+ 1);
752 FindClose (dir_handle
);
757 /* Get long name for file, if possible (assumed to be absolute). */
759 w32_get_long_filename (char * name
, char * buf
, int size
)
764 char full
[ MAX_PATH
];
771 /* Use local copy for destructive modification. */
772 memcpy (full
, name
, len
+1);
773 unixtodos_filename (full
);
775 /* Copy root part verbatim. */
776 len
= parse_root (full
, &p
);
777 memcpy (o
, full
, len
);
782 while (p
!= NULL
&& *p
)
785 p
= strchr (q
, '\\');
787 len
= get_long_basename (full
, o
, size
);
810 is_unc_volume (const char *filename
)
812 const char *ptr
= filename
;
814 if (!IS_DIRECTORY_SEP (ptr
[0]) || !IS_DIRECTORY_SEP (ptr
[1]) || !ptr
[2])
817 if (strpbrk (ptr
+ 2, "*?|<>\"\\/"))
823 /* Routines that are no-ops on NT but are defined to get Emacs to compile. */
826 sigsetmask (int signal_mask
)
850 setpgrp (int pid
, int gid
)
862 unrequest_sigio (void)
873 #define REG_ROOT "SOFTWARE\\GNU\\Emacs"
876 w32_get_resource (key
, lpdwtype
)
881 HKEY hrootkey
= NULL
;
885 /* Check both the current user and the local machine to see if
886 we have any resources. */
888 if (RegOpenKeyEx (HKEY_CURRENT_USER
, REG_ROOT
, 0, KEY_READ
, &hrootkey
) == ERROR_SUCCESS
)
892 if (RegQueryValueEx (hrootkey
, key
, NULL
, NULL
, NULL
, &cbData
) == ERROR_SUCCESS
893 && (lpvalue
= (LPBYTE
) xmalloc (cbData
)) != NULL
894 && RegQueryValueEx (hrootkey
, key
, NULL
, lpdwtype
, lpvalue
, &cbData
) == ERROR_SUCCESS
)
899 if (lpvalue
) xfree (lpvalue
);
901 RegCloseKey (hrootkey
);
904 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE
, REG_ROOT
, 0, KEY_READ
, &hrootkey
) == ERROR_SUCCESS
)
908 if (RegQueryValueEx (hrootkey
, key
, NULL
, NULL
, NULL
, &cbData
) == ERROR_SUCCESS
909 && (lpvalue
= (LPBYTE
) xmalloc (cbData
)) != NULL
910 && RegQueryValueEx (hrootkey
, key
, NULL
, lpdwtype
, lpvalue
, &cbData
) == ERROR_SUCCESS
)
915 if (lpvalue
) xfree (lpvalue
);
917 RegCloseKey (hrootkey
);
923 char *get_emacs_configuration (void);
924 extern Lisp_Object Vsystem_configuration
;
927 init_environment (char ** argv
)
929 static const char * const tempdirs
[] = {
930 "$TMPDIR", "$TEMP", "$TMP", "c:/"
935 const int imax
= sizeof (tempdirs
) / sizeof (tempdirs
[0]);
937 /* Make sure they have a usable $TMPDIR. Many Emacs functions use
938 temporary files and assume "/tmp" if $TMPDIR is unset, which
939 will break on DOS/Windows. Refuse to work if we cannot find
940 a directory, not even "c:/", usable for that purpose. */
941 for (i
= 0; i
< imax
; i
++)
943 const char *tmp
= tempdirs
[i
];
946 tmp
= getenv (tmp
+ 1);
947 /* Note that `access' can lie to us if the directory resides on a
948 read-only filesystem, like CD-ROM or a write-protected floppy.
949 The only way to be really sure is to actually create a file and
950 see if it succeeds. But I think that's too much to ask. */
951 if (tmp
&& _access (tmp
, D_OK
) == 0)
953 char * var
= alloca (strlen (tmp
) + 8);
954 sprintf (var
, "TMPDIR=%s", tmp
);
955 _putenv (strdup (var
));
962 Fcons (build_string ("no usable temporary directories found!!"),
964 "While setting TMPDIR: ");
966 /* Check for environment variables and use registry settings if they
967 don't exist. Fallback on default values where applicable. */
972 char locale_name
[32];
974 char default_home
[MAX_PATH
];
976 static const struct env_entry
983 {"PRELOAD_WINSOCK", NULL
},
984 {"emacs_dir", "C:/emacs"},
985 {"EMACSLOADPATH", "%emacs_dir%/site-lisp;%emacs_dir%/../site-lisp;%emacs_dir%/lisp;%emacs_dir%/leim"},
986 {"SHELL", "%emacs_dir%/bin/cmdproxy.exe"},
987 {"EMACSDATA", "%emacs_dir%/etc"},
988 {"EMACSPATH", "%emacs_dir%/bin"},
989 /* We no longer set INFOPATH because Info-default-directory-list
991 /* {"INFOPATH", "%emacs_dir%/info"}, */
992 {"EMACSDOC", "%emacs_dir%/etc"},
997 #define N_ENV_VARS sizeof(dflt_envvars)/sizeof(dflt_envvars[0])
999 /* We need to copy dflt_envvars[] and work on the copy because we
1000 don't want the dumped Emacs to inherit the values of
1001 environment variables we saw during dumping (which could be on
1002 a different system). The defaults above must be left intact. */
1003 struct env_entry env_vars
[N_ENV_VARS
];
1005 for (i
= 0; i
< N_ENV_VARS
; i
++)
1006 env_vars
[i
] = dflt_envvars
[i
];
1008 /* For backwards compatibility, check if a .emacs file exists in C:/
1009 If not, then we can try to default to the appdata directory under the
1010 user's profile, which is more likely to be writable. */
1011 if (stat ("C:/.emacs", &ignored
) < 0)
1013 HRESULT profile_result
;
1014 /* Dynamically load ShGetFolderPath, as it won't exist on versions
1015 of Windows 95 and NT4 that have not been updated to include
1016 MSIE 5. Also we don't link with shell32.dll by default. */
1017 HMODULE shell32_dll
;
1018 ShGetFolderPath_fn get_folder_path
;
1019 shell32_dll
= GetModuleHandle ("shell32.dll");
1020 get_folder_path
= (ShGetFolderPath_fn
)
1021 GetProcAddress (shell32_dll
, "SHGetFolderPathA");
1023 if (get_folder_path
!= NULL
)
1025 profile_result
= get_folder_path (NULL
, CSIDL_APPDATA
, NULL
,
1028 /* If we can't get the appdata dir, revert to old behaviour. */
1029 if (profile_result
== S_OK
)
1030 env_vars
[0].def_value
= default_home
;
1033 /* Unload shell32.dll, it is not needed anymore. */
1034 FreeLibrary (shell32_dll
);
1037 /* Get default locale info and use it for LANG. */
1038 if (GetLocaleInfo (LOCALE_USER_DEFAULT
,
1039 LOCALE_SABBREVLANGNAME
| LOCALE_USE_CP_ACP
,
1040 locale_name
, sizeof (locale_name
)))
1042 for (i
= 0; i
< N_ENV_VARS
; i
++)
1044 if (strcmp (env_vars
[i
].name
, "LANG") == 0)
1046 env_vars
[i
].def_value
= locale_name
;
1052 #define SET_ENV_BUF_SIZE (4 * MAX_PATH) /* to cover EMACSLOADPATH */
1054 /* Treat emacs_dir specially: set it unconditionally based on our
1055 location, if it appears that we are running from the bin subdir
1056 of a standard installation. */
1059 char modname
[MAX_PATH
];
1061 if (!GetModuleFileName (NULL
, modname
, MAX_PATH
))
1063 if ((p
= strrchr (modname
, '\\')) == NULL
)
1067 if ((p
= strrchr (modname
, '\\')) && stricmp (p
, "\\bin") == 0)
1069 char buf
[SET_ENV_BUF_SIZE
];
1072 for (p
= modname
; *p
; p
++)
1073 if (*p
== '\\') *p
= '/';
1075 _snprintf (buf
, sizeof(buf
)-1, "emacs_dir=%s", modname
);
1076 _putenv (strdup (buf
));
1078 /* Handle running emacs from the build directory: src/oo-spd/i386/ */
1080 /* FIXME: should use substring of get_emacs_configuration ().
1081 But I don't think the Windows build supports alpha, mips etc
1082 anymore, so have taken the easy option for now. */
1083 else if (p
&& stricmp (p
, "\\i386") == 0)
1086 p
= strrchr (modname
, '\\');
1090 p
= strrchr (modname
, '\\');
1091 if (p
&& stricmp (p
, "\\src") == 0)
1093 char buf
[SET_ENV_BUF_SIZE
];
1096 for (p
= modname
; *p
; p
++)
1097 if (*p
== '\\') *p
= '/';
1099 _snprintf (buf
, sizeof(buf
)-1, "emacs_dir=%s", modname
);
1100 _putenv (strdup (buf
));
1106 for (i
= 0; i
< N_ENV_VARS
; i
++)
1108 if (!getenv (env_vars
[i
].name
))
1112 if ((lpval
= w32_get_resource (env_vars
[i
].name
, &dwType
)) == NULL
)
1114 lpval
= env_vars
[i
].def_value
;
1115 dwType
= REG_EXPAND_SZ
;
1121 char buf1
[SET_ENV_BUF_SIZE
], buf2
[SET_ENV_BUF_SIZE
];
1123 if (dwType
== REG_EXPAND_SZ
)
1124 ExpandEnvironmentStrings ((LPSTR
) lpval
, buf1
, sizeof(buf1
));
1125 else if (dwType
== REG_SZ
)
1126 strcpy (buf1
, lpval
);
1127 if (dwType
== REG_EXPAND_SZ
|| dwType
== REG_SZ
)
1129 _snprintf (buf2
, sizeof(buf2
)-1, "%s=%s", env_vars
[i
].name
,
1131 _putenv (strdup (buf2
));
1141 /* Rebuild system configuration to reflect invoking system. */
1142 Vsystem_configuration
= build_string (EMACS_CONFIGURATION
);
1144 /* Another special case: on NT, the PATH variable is actually named
1145 "Path" although cmd.exe (perhaps NT itself) arranges for
1146 environment variable lookup and setting to be case insensitive.
1147 However, Emacs assumes a fully case sensitive environment, so we
1148 need to change "Path" to "PATH" to match the expectations of
1149 various elisp packages. We do this by the sneaky method of
1150 modifying the string in the C runtime environ entry.
1152 The same applies to COMSPEC. */
1156 for (envp
= environ
; *envp
; envp
++)
1157 if (_strnicmp (*envp
, "PATH=", 5) == 0)
1158 memcpy (*envp
, "PATH=", 5);
1159 else if (_strnicmp (*envp
, "COMSPEC=", 8) == 0)
1160 memcpy (*envp
, "COMSPEC=", 8);
1163 /* Remember the initial working directory for getwd, then make the
1164 real wd be the location of emacs.exe to avoid conflicts when
1165 renaming or deleting directories. (We also don't call chdir when
1166 running subprocesses for the same reason.) */
1167 if (!GetCurrentDirectory (MAXPATHLEN
, startup_dir
))
1172 static char modname
[MAX_PATH
];
1174 if (!GetModuleFileName (NULL
, modname
, MAX_PATH
))
1176 if ((p
= strrchr (modname
, '\\')) == NULL
)
1180 SetCurrentDirectory (modname
);
1182 /* Ensure argv[0] has the full path to Emacs. */
1187 /* Determine if there is a middle mouse button, to allow parse_button
1188 to decide whether right mouse events should be mouse-2 or
1190 w32_num_mouse_buttons
= GetSystemMetrics (SM_CMOUSEBUTTONS
);
1196 emacs_root_dir (void)
1198 static char root_dir
[FILENAME_MAX
];
1201 p
= getenv ("emacs_dir");
1204 strcpy (root_dir
, p
);
1205 root_dir
[parse_root (root_dir
, NULL
)] = '\0';
1206 dostounix_filename (root_dir
);
1210 /* We don't have scripts to automatically determine the system configuration
1211 for Emacs before it's compiled, and we don't want to have to make the
1212 user enter it, so we define EMACS_CONFIGURATION to invoke this runtime
1216 get_emacs_configuration (void)
1218 char *arch
, *oem
, *os
;
1220 static char configuration_buffer
[32];
1222 /* Determine the processor type. */
1223 switch (get_processor_type ())
1226 #ifdef PROCESSOR_INTEL_386
1227 case PROCESSOR_INTEL_386
:
1228 case PROCESSOR_INTEL_486
:
1229 case PROCESSOR_INTEL_PENTIUM
:
1234 #ifdef PROCESSOR_INTEL_860
1235 case PROCESSOR_INTEL_860
:
1240 #ifdef PROCESSOR_MIPS_R2000
1241 case PROCESSOR_MIPS_R2000
:
1242 case PROCESSOR_MIPS_R3000
:
1243 case PROCESSOR_MIPS_R4000
:
1248 #ifdef PROCESSOR_ALPHA_21064
1249 case PROCESSOR_ALPHA_21064
:
1259 /* Use the OEM field to reflect the compiler/library combination. */
1261 #define COMPILER_NAME "msvc"
1264 #define COMPILER_NAME "mingw"
1266 #define COMPILER_NAME "unknown"
1269 oem
= COMPILER_NAME
;
1271 switch (osinfo_cache
.dwPlatformId
) {
1272 case VER_PLATFORM_WIN32_NT
:
1274 build_num
= osinfo_cache
.dwBuildNumber
;
1276 case VER_PLATFORM_WIN32_WINDOWS
:
1277 if (osinfo_cache
.dwMinorVersion
== 0) {
1282 build_num
= LOWORD (osinfo_cache
.dwBuildNumber
);
1284 case VER_PLATFORM_WIN32s
:
1285 /* Not supported, should not happen. */
1287 build_num
= LOWORD (osinfo_cache
.dwBuildNumber
);
1295 if (osinfo_cache
.dwPlatformId
== VER_PLATFORM_WIN32_NT
) {
1296 sprintf (configuration_buffer
, "%s-%s-%s%d.%d.%d", arch
, oem
, os
,
1297 get_w32_major_version (), get_w32_minor_version (), build_num
);
1299 sprintf (configuration_buffer
, "%s-%s-%s.%d", arch
, oem
, os
, build_num
);
1302 return configuration_buffer
;
1306 get_emacs_configuration_options (void)
1308 static char options_buffer
[256];
1310 /* Work out the effective configure options for this build. */
1312 #define COMPILER_VERSION "--with-msvc (%d.%02d)", _MSC_VER / 100, _MSC_VER % 100
1315 #define COMPILER_VERSION "--with-gcc (%d.%d)", __GNUC__, __GNUC_MINOR__
1317 #define COMPILER_VERSION ""
1321 sprintf (options_buffer
, COMPILER_VERSION
);
1323 strcat (options_buffer
, " --no-opt");
1326 strcat (options_buffer
, " --cflags");
1327 strcat (options_buffer
, USER_CFLAGS
);
1330 strcat (options_buffer
, " --ldflags");
1331 strcat (options_buffer
, USER_LDFLAGS
);
1333 return options_buffer
;
1337 #include <sys/timeb.h>
1339 /* Emulate gettimeofday (Ulrich Leodolter, 1/11/95). */
1341 gettimeofday (struct timeval
*tv
, struct timezone
*tz
)
1346 tv
->tv_sec
= tb
.time
;
1347 tv
->tv_usec
= tb
.millitm
* 1000L;
1350 tz
->tz_minuteswest
= tb
.timezone
; /* minutes west of Greenwich */
1351 tz
->tz_dsttime
= tb
.dstflag
; /* type of dst correction */
1355 /* ------------------------------------------------------------------------- */
1356 /* IO support and wrapper functions for W32 API. */
1357 /* ------------------------------------------------------------------------- */
1359 /* Place a wrapper around the MSVC version of ctime. It returns NULL
1360 on network directories, so we handle that case here.
1361 (Ulrich Leodolter, 1/11/95). */
1363 sys_ctime (const time_t *t
)
1365 char *str
= (char *) ctime (t
);
1366 return (str
? str
: "Sun Jan 01 00:00:00 1970");
1369 /* Emulate sleep...we could have done this with a define, but that
1370 would necessitate including windows.h in the files that used it.
1371 This is much easier. */
1373 sys_sleep (int seconds
)
1375 Sleep (seconds
* 1000);
1378 /* Internal MSVC functions for low-level descriptor munging */
1379 extern int __cdecl
_set_osfhnd (int fd
, long h
);
1380 extern int __cdecl
_free_osfhnd (int fd
);
1382 /* parallel array of private info on file handles */
1383 filedesc fd_info
[ MAXDESC
];
1385 typedef struct volume_info_data
{
1386 struct volume_info_data
* next
;
1388 /* time when info was obtained */
1391 /* actual volume info */
1400 /* Global referenced by various functions. */
1401 static volume_info_data volume_info
;
1403 /* Vector to indicate which drives are local and fixed (for which cached
1404 data never expires). */
1405 static BOOL fixed_drives
[26];
1407 /* Consider cached volume information to be stale if older than 10s,
1408 at least for non-local drives. Info for fixed drives is never stale. */
1409 #define DRIVE_INDEX( c ) ( (c) <= 'Z' ? (c) - 'A' : (c) - 'a' )
1410 #define VOLINFO_STILL_VALID( root_dir, info ) \
1411 ( ( isalpha (root_dir[0]) && \
1412 fixed_drives[ DRIVE_INDEX (root_dir[0]) ] ) \
1413 || GetTickCount () - info->timestamp < 10000 )
1415 /* Cache support functions. */
1417 /* Simple linked list with linear search is sufficient. */
1418 static volume_info_data
*volume_cache
= NULL
;
1420 static volume_info_data
*
1421 lookup_volume_info (char * root_dir
)
1423 volume_info_data
* info
;
1425 for (info
= volume_cache
; info
; info
= info
->next
)
1426 if (stricmp (info
->root_dir
, root_dir
) == 0)
1432 add_volume_info (char * root_dir
, volume_info_data
* info
)
1434 info
->root_dir
= xstrdup (root_dir
);
1435 info
->next
= volume_cache
;
1436 volume_cache
= info
;
1440 /* Wrapper for GetVolumeInformation, which uses caching to avoid
1441 performance penalty (~2ms on 486 for local drives, 7.5ms for local
1442 cdrom drive, ~5-10ms or more for remote drives on LAN). */
1444 GetCachedVolumeInformation (char * root_dir
)
1446 volume_info_data
* info
;
1447 char default_root
[ MAX_PATH
];
1449 /* NULL for root_dir means use root from current directory. */
1450 if (root_dir
== NULL
)
1452 if (GetCurrentDirectory (MAX_PATH
, default_root
) == 0)
1454 parse_root (default_root
, &root_dir
);
1456 root_dir
= default_root
;
1459 /* Local fixed drives can be cached permanently. Removable drives
1460 cannot be cached permanently, since the volume name and serial
1461 number (if nothing else) can change. Remote drives should be
1462 treated as if they are removable, since there is no sure way to
1463 tell whether they are or not. Also, the UNC association of drive
1464 letters mapped to remote volumes can be changed at any time (even
1465 by other processes) without notice.
1467 As a compromise, so we can benefit from caching info for remote
1468 volumes, we use a simple expiry mechanism to invalidate cache
1469 entries that are more than ten seconds old. */
1472 /* No point doing this, because WNetGetConnection is even slower than
1473 GetVolumeInformation, consistently taking ~50ms on a 486 (FWIW,
1474 GetDriveType is about the only call of this type which does not
1475 involve network access, and so is extremely quick). */
1477 /* Map drive letter to UNC if remote. */
1478 if ( isalpha( root_dir
[0] ) && !fixed
[ DRIVE_INDEX( root_dir
[0] ) ] )
1480 char remote_name
[ 256 ];
1481 char drive
[3] = { root_dir
[0], ':' };
1483 if (WNetGetConnection (drive
, remote_name
, sizeof (remote_name
))
1485 /* do something */ ;
1489 info
= lookup_volume_info (root_dir
);
1491 if (info
== NULL
|| ! VOLINFO_STILL_VALID (root_dir
, info
))
1499 /* Info is not cached, or is stale. */
1500 if (!GetVolumeInformation (root_dir
,
1501 name
, sizeof (name
),
1505 type
, sizeof (type
)))
1508 /* Cache the volume information for future use, overwriting existing
1509 entry if present. */
1512 info
= (volume_info_data
*) xmalloc (sizeof (volume_info_data
));
1513 add_volume_info (root_dir
, info
);
1521 info
->name
= xstrdup (name
);
1522 info
->serialnum
= serialnum
;
1523 info
->maxcomp
= maxcomp
;
1524 info
->flags
= flags
;
1525 info
->type
= xstrdup (type
);
1526 info
->timestamp
= GetTickCount ();
1532 /* Get information on the volume where name is held; set path pointer to
1533 start of pathname in name (past UNC header\volume header if present). */
1535 get_volume_info (const char * name
, const char ** pPath
)
1537 char temp
[MAX_PATH
];
1538 char *rootname
= NULL
; /* default to current volume */
1539 volume_info_data
* info
;
1544 /* find the root name of the volume if given */
1545 if (isalpha (name
[0]) && name
[1] == ':')
1553 else if (IS_DIRECTORY_SEP (name
[0]) && IS_DIRECTORY_SEP (name
[1]))
1560 if (IS_DIRECTORY_SEP (*name
) && --slashes
== 0)
1573 info
= GetCachedVolumeInformation (rootname
);
1576 /* Set global referenced by other functions. */
1577 volume_info
= *info
;
1583 /* Determine if volume is FAT format (ie. only supports short 8.3
1584 names); also set path pointer to start of pathname in name. */
1586 is_fat_volume (const char * name
, const char ** pPath
)
1588 if (get_volume_info (name
, pPath
))
1589 return (volume_info
.maxcomp
== 12);
1593 /* Map filename to a legal 8.3 name if necessary. */
1595 map_w32_filename (const char * name
, const char ** pPath
)
1597 static char shortname
[MAX_PATH
];
1598 char * str
= shortname
;
1601 const char * save_name
= name
;
1603 if (strlen (name
) >= MAX_PATH
)
1605 /* Return a filename which will cause callers to fail. */
1606 strcpy (shortname
, "?");
1610 if (is_fat_volume (name
, (const char **)&path
)) /* truncate to 8.3 */
1612 register int left
= 8; /* maximum number of chars in part */
1613 register int extn
= 0; /* extension added? */
1614 register int dots
= 2; /* maximum number of dots allowed */
1617 *str
++ = *name
++; /* skip past UNC header */
1619 while ((c
= *name
++))
1626 extn
= 0; /* reset extension flags */
1627 dots
= 2; /* max 2 dots */
1628 left
= 8; /* max length 8 for main part */
1632 extn
= 0; /* reset extension flags */
1633 dots
= 2; /* max 2 dots */
1634 left
= 8; /* max length 8 for main part */
1639 /* Convert path components of the form .xxx to _xxx,
1640 but leave . and .. as they are. This allows .emacs
1641 to be read as _emacs, for example. */
1645 IS_DIRECTORY_SEP (*name
))
1660 extn
= 1; /* we've got an extension */
1661 left
= 3; /* 3 chars in extension */
1665 /* any embedded dots after the first are converted to _ */
1670 case '#': /* don't lose these, they're important */
1672 str
[-1] = c
; /* replace last character of part */
1677 *str
++ = tolower (c
); /* map to lower case (looks nicer) */
1679 dots
= 0; /* started a path component */
1688 strcpy (shortname
, name
);
1689 unixtodos_filename (shortname
);
1693 *pPath
= shortname
+ (path
- save_name
);
1699 is_exec (const char * name
)
1701 char * p
= strrchr (name
, '.');
1704 && (stricmp (p
, ".exe") == 0 ||
1705 stricmp (p
, ".com") == 0 ||
1706 stricmp (p
, ".bat") == 0 ||
1707 stricmp (p
, ".cmd") == 0));
1710 /* Emulate the Unix directory procedures opendir, closedir,
1711 and readdir. We can't use the procedures supplied in sysdep.c,
1712 so we provide them here. */
1714 struct direct dir_static
; /* simulated directory contents */
1715 static HANDLE dir_find_handle
= INVALID_HANDLE_VALUE
;
1716 static int dir_is_fat
;
1717 static char dir_pathname
[MAXPATHLEN
+1];
1718 static WIN32_FIND_DATA dir_find_data
;
1720 /* Support shares on a network resource as subdirectories of a read-only
1722 static HANDLE wnet_enum_handle
= INVALID_HANDLE_VALUE
;
1723 HANDLE
open_unc_volume (const char *);
1724 char *read_unc_volume (HANDLE
, char *, int);
1725 void close_unc_volume (HANDLE
);
1728 opendir (char *filename
)
1732 /* Opening is done by FindFirstFile. However, a read is inherent to
1733 this operation, so we defer the open until read time. */
1735 if (dir_find_handle
!= INVALID_HANDLE_VALUE
)
1737 if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
1740 if (is_unc_volume (filename
))
1742 wnet_enum_handle
= open_unc_volume (filename
);
1743 if (wnet_enum_handle
== INVALID_HANDLE_VALUE
)
1747 if (!(dirp
= (DIR *) malloc (sizeof (DIR))))
1754 strncpy (dir_pathname
, map_w32_filename (filename
, NULL
), MAXPATHLEN
);
1755 dir_pathname
[MAXPATHLEN
] = '\0';
1756 dir_is_fat
= is_fat_volume (filename
, NULL
);
1762 closedir (DIR *dirp
)
1764 /* If we have a find-handle open, close it. */
1765 if (dir_find_handle
!= INVALID_HANDLE_VALUE
)
1767 FindClose (dir_find_handle
);
1768 dir_find_handle
= INVALID_HANDLE_VALUE
;
1770 else if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
1772 close_unc_volume (wnet_enum_handle
);
1773 wnet_enum_handle
= INVALID_HANDLE_VALUE
;
1775 xfree ((char *) dirp
);
1781 if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
1783 if (!read_unc_volume (wnet_enum_handle
,
1784 dir_find_data
.cFileName
,
1788 /* If we aren't dir_finding, do a find-first, otherwise do a find-next. */
1789 else if (dir_find_handle
== INVALID_HANDLE_VALUE
)
1791 char filename
[MAXNAMLEN
+ 3];
1794 strcpy (filename
, dir_pathname
);
1795 ln
= strlen (filename
) - 1;
1796 if (!IS_DIRECTORY_SEP (filename
[ln
]))
1797 strcat (filename
, "\\");
1798 strcat (filename
, "*");
1800 dir_find_handle
= FindFirstFile (filename
, &dir_find_data
);
1802 if (dir_find_handle
== INVALID_HANDLE_VALUE
)
1807 if (!FindNextFile (dir_find_handle
, &dir_find_data
))
1811 /* Emacs never uses this value, so don't bother making it match
1812 value returned by stat(). */
1813 dir_static
.d_ino
= 1;
1815 dir_static
.d_reclen
= sizeof (struct direct
) - MAXNAMLEN
+ 3 +
1816 dir_static
.d_namlen
- dir_static
.d_namlen
% 4;
1818 dir_static
.d_namlen
= strlen (dir_find_data
.cFileName
);
1819 strcpy (dir_static
.d_name
, dir_find_data
.cFileName
);
1821 _strlwr (dir_static
.d_name
);
1822 else if (!NILP (Vw32_downcase_file_names
))
1825 for (p
= dir_static
.d_name
; *p
; p
++)
1826 if (*p
>= 'a' && *p
<= 'z')
1829 _strlwr (dir_static
.d_name
);
1836 open_unc_volume (const char *path
)
1842 nr
.dwScope
= RESOURCE_GLOBALNET
;
1843 nr
.dwType
= RESOURCETYPE_DISK
;
1844 nr
.dwDisplayType
= RESOURCEDISPLAYTYPE_SERVER
;
1845 nr
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
1846 nr
.lpLocalName
= NULL
;
1847 nr
.lpRemoteName
= (LPSTR
)map_w32_filename (path
, NULL
);
1848 nr
.lpComment
= NULL
;
1849 nr
.lpProvider
= NULL
;
1851 result
= WNetOpenEnum(RESOURCE_GLOBALNET
, RESOURCETYPE_DISK
,
1852 RESOURCEUSAGE_CONNECTABLE
, &nr
, &henum
);
1854 if (result
== NO_ERROR
)
1857 return INVALID_HANDLE_VALUE
;
1861 read_unc_volume (HANDLE henum
, char *readbuf
, int size
)
1865 DWORD bufsize
= 512;
1870 buffer
= alloca (bufsize
);
1871 result
= WNetEnumResource (wnet_enum_handle
, &count
, buffer
, &bufsize
);
1872 if (result
!= NO_ERROR
)
1875 /* WNetEnumResource returns \\resource\share...skip forward to "share". */
1876 ptr
= ((LPNETRESOURCE
) buffer
)->lpRemoteName
;
1878 while (*ptr
&& !IS_DIRECTORY_SEP (*ptr
)) ptr
++;
1881 strncpy (readbuf
, ptr
, size
);
1886 close_unc_volume (HANDLE henum
)
1888 if (henum
!= INVALID_HANDLE_VALUE
)
1889 WNetCloseEnum (henum
);
1893 unc_volume_file_attributes (const char *path
)
1898 henum
= open_unc_volume (path
);
1899 if (henum
== INVALID_HANDLE_VALUE
)
1902 attrs
= FILE_ATTRIBUTE_READONLY
| FILE_ATTRIBUTE_DIRECTORY
;
1904 close_unc_volume (henum
);
1910 /* Shadow some MSVC runtime functions to map requests for long filenames
1911 to reasonable short names if necessary. This was originally added to
1912 permit running Emacs on NT 3.1 on a FAT partition, which doesn't support
1916 sys_access (const char * path
, int mode
)
1920 /* MSVC implementation doesn't recognize D_OK. */
1921 path
= map_w32_filename (path
, NULL
);
1922 if (is_unc_volume (path
))
1924 attributes
= unc_volume_file_attributes (path
);
1925 if (attributes
== -1) {
1930 else if ((attributes
= GetFileAttributes (path
)) == -1)
1932 /* Should try mapping GetLastError to errno; for now just indicate
1933 that path doesn't exist. */
1937 if ((mode
& X_OK
) != 0 && !is_exec (path
))
1942 if ((mode
& W_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_READONLY
) != 0)
1947 if ((mode
& D_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
) == 0)
1956 sys_chdir (const char * path
)
1958 return _chdir (map_w32_filename (path
, NULL
));
1962 sys_chmod (const char * path
, int mode
)
1964 return _chmod (map_w32_filename (path
, NULL
), mode
);
1968 sys_chown (const char *path
, uid_t owner
, gid_t group
)
1970 if (sys_chmod (path
, _S_IREAD
) == -1) /* check if file exists */
1976 sys_creat (const char * path
, int mode
)
1978 return _creat (map_w32_filename (path
, NULL
), mode
);
1982 sys_fopen(const char * path
, const char * mode
)
1986 const char * mode_save
= mode
;
1988 /* Force all file handles to be non-inheritable. This is necessary to
1989 ensure child processes don't unwittingly inherit handles that might
1990 prevent future file access. */
1994 else if (mode
[0] == 'w' || mode
[0] == 'a')
1995 oflag
= O_WRONLY
| O_CREAT
| O_TRUNC
;
1999 /* Only do simplistic option parsing. */
2003 oflag
&= ~(O_RDONLY
| O_WRONLY
);
2006 else if (mode
[0] == 'b')
2011 else if (mode
[0] == 't')
2018 fd
= _open (map_w32_filename (path
, NULL
), oflag
| _O_NOINHERIT
, 0644);
2022 return _fdopen (fd
, mode_save
);
2025 /* This only works on NTFS volumes, but is useful to have. */
2027 sys_link (const char * old
, const char * new)
2031 char oldname
[MAX_PATH
], newname
[MAX_PATH
];
2033 if (old
== NULL
|| new == NULL
)
2039 strcpy (oldname
, map_w32_filename (old
, NULL
));
2040 strcpy (newname
, map_w32_filename (new, NULL
));
2042 fileh
= CreateFile (oldname
, 0, 0, NULL
, OPEN_EXISTING
,
2043 FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
2044 if (fileh
!= INVALID_HANDLE_VALUE
)
2048 /* Confusingly, the "alternate" stream name field does not apply
2049 when restoring a hard link, and instead contains the actual
2050 stream data for the link (ie. the name of the link to create).
2051 The WIN32_STREAM_ID structure before the cStreamName field is
2052 the stream header, which is then immediately followed by the
2056 WIN32_STREAM_ID wid
;
2057 WCHAR wbuffer
[MAX_PATH
]; /* extra space for link name */
2060 wlen
= MultiByteToWideChar (CP_ACP
, MB_PRECOMPOSED
, newname
, -1,
2061 data
.wid
.cStreamName
, MAX_PATH
);
2064 LPVOID context
= NULL
;
2067 data
.wid
.dwStreamId
= BACKUP_LINK
;
2068 data
.wid
.dwStreamAttributes
= 0;
2069 data
.wid
.Size
.LowPart
= wlen
* sizeof(WCHAR
);
2070 data
.wid
.Size
.HighPart
= 0;
2071 data
.wid
.dwStreamNameSize
= 0;
2073 if (BackupWrite (fileh
, (LPBYTE
)&data
,
2074 offsetof (WIN32_STREAM_ID
, cStreamName
)
2075 + data
.wid
.Size
.LowPart
,
2076 &wbytes
, FALSE
, FALSE
, &context
)
2077 && BackupWrite (fileh
, NULL
, 0, &wbytes
, TRUE
, FALSE
, &context
))
2084 /* Should try mapping GetLastError to errno; for now just
2085 indicate a general error (eg. links not supported). */
2086 errno
= EINVAL
; // perhaps EMLINK?
2090 CloseHandle (fileh
);
2099 sys_mkdir (const char * path
)
2101 return _mkdir (map_w32_filename (path
, NULL
));
2104 /* Because of long name mapping issues, we need to implement this
2105 ourselves. Also, MSVC's _mktemp returns NULL when it can't generate
2106 a unique name, instead of setting the input template to an empty
2109 Standard algorithm seems to be use pid or tid with a letter on the
2110 front (in place of the 6 X's) and cycle through the letters to find a
2111 unique name. We extend that to allow any reasonable character as the
2112 first of the 6 X's. */
2114 sys_mktemp (char * template)
2118 unsigned uid
= GetCurrentThreadId ();
2119 static char first_char
[] = "abcdefghijklmnopqrstuvwyz0123456789!%-_@#";
2121 if (template == NULL
)
2123 p
= template + strlen (template);
2125 /* replace up to the last 5 X's with uid in decimal */
2126 while (--p
>= template && p
[0] == 'X' && --i
>= 0)
2128 p
[0] = '0' + uid
% 10;
2132 if (i
< 0 && p
[0] == 'X')
2137 int save_errno
= errno
;
2138 p
[0] = first_char
[i
];
2139 if (sys_access (template, 0) < 0)
2145 while (++i
< sizeof (first_char
));
2148 /* Template is badly formed or else we can't generate a unique name,
2149 so return empty string */
2155 sys_open (const char * path
, int oflag
, int mode
)
2157 const char* mpath
= map_w32_filename (path
, NULL
);
2158 /* Try to open file without _O_CREAT, to be able to write to hidden
2159 and system files. Force all file handles to be
2161 int res
= _open (mpath
, (oflag
& ~_O_CREAT
) | _O_NOINHERIT
, mode
);
2164 return _open (mpath
, oflag
| _O_NOINHERIT
, mode
);
2168 sys_rename (const char * oldname
, const char * newname
)
2171 char temp
[MAX_PATH
];
2173 /* MoveFile on Windows 95 doesn't correctly change the short file name
2174 alias in a number of circumstances (it is not easy to predict when
2175 just by looking at oldname and newname, unfortunately). In these
2176 cases, renaming through a temporary name avoids the problem.
2178 A second problem on Windows 95 is that renaming through a temp name when
2179 newname is uppercase fails (the final long name ends up in
2180 lowercase, although the short alias might be uppercase) UNLESS the
2181 long temp name is not 8.3.
2183 So, on Windows 95 we always rename through a temp name, and we make sure
2184 the temp name has a long extension to ensure correct renaming. */
2186 strcpy (temp
, map_w32_filename (oldname
, NULL
));
2188 if (os_subtype
== OS_WIN95
)
2194 oldname
= map_w32_filename (oldname
, NULL
);
2195 if (o
= strrchr (oldname
, '\\'))
2198 o
= (char *) oldname
;
2200 if (p
= strrchr (temp
, '\\'))
2207 /* Force temp name to require a manufactured 8.3 alias - this
2208 seems to make the second rename work properly. */
2209 sprintf (p
, "_.%s.%u", o
, i
);
2211 result
= rename (oldname
, temp
);
2213 /* This loop must surely terminate! */
2214 while (result
< 0 && errno
== EEXIST
);
2219 /* Emulate Unix behaviour - newname is deleted if it already exists
2220 (at least if it is a file; don't do this for directories).
2222 Since we mustn't do this if we are just changing the case of the
2223 file name (we would end up deleting the file we are trying to
2224 rename!), we let rename detect if the destination file already
2225 exists - that way we avoid the possible pitfalls of trying to
2226 determine ourselves whether two names really refer to the same
2227 file, which is not always possible in the general case. (Consider
2228 all the permutations of shared or subst'd drives, etc.) */
2230 newname
= map_w32_filename (newname
, NULL
);
2231 result
= rename (temp
, newname
);
2235 && _chmod (newname
, 0666) == 0
2236 && _unlink (newname
) == 0)
2237 result
= rename (temp
, newname
);
2243 sys_rmdir (const char * path
)
2245 return _rmdir (map_w32_filename (path
, NULL
));
2249 sys_unlink (const char * path
)
2251 path
= map_w32_filename (path
, NULL
);
2253 /* On Unix, unlink works without write permission. */
2254 _chmod (path
, 0666);
2255 return _unlink (path
);
2258 static FILETIME utc_base_ft
;
2259 static long double utc_base
;
2260 static int init
= 0;
2263 convert_time (FILETIME ft
)
2269 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
2278 st
.wMilliseconds
= 0;
2280 SystemTimeToFileTime (&st
, &utc_base_ft
);
2281 utc_base
= (long double) utc_base_ft
.dwHighDateTime
2282 * 4096.0L * 1024.0L * 1024.0L + utc_base_ft
.dwLowDateTime
;
2286 if (CompareFileTime (&ft
, &utc_base_ft
) < 0)
2289 ret
= (long double) ft
.dwHighDateTime
2290 * 4096.0L * 1024.0L * 1024.0L + ft
.dwLowDateTime
;
2292 return (time_t) (ret
* 1e-7L);
2296 convert_from_time_t (time_t time
, FILETIME
* pft
)
2302 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
2311 st
.wMilliseconds
= 0;
2313 SystemTimeToFileTime (&st
, &utc_base_ft
);
2314 utc_base
= (long double) utc_base_ft
.dwHighDateTime
2315 * 4096 * 1024 * 1024 + utc_base_ft
.dwLowDateTime
;
2319 /* time in 100ns units since 1-Jan-1601 */
2320 tmp
= (long double) time
* 1e7
+ utc_base
;
2321 pft
->dwHighDateTime
= (DWORD
) (tmp
/ (4096.0 * 1024 * 1024));
2322 pft
->dwLowDateTime
= (DWORD
) (tmp
- (4096.0 * 1024 * 1024) * pft
->dwHighDateTime
);
2326 /* No reason to keep this; faking inode values either by hashing or even
2327 using the file index from GetInformationByHandle, is not perfect and
2328 so by default Emacs doesn't use the inode values on Windows.
2329 Instead, we now determine file-truename correctly (except for
2330 possible drive aliasing etc). */
2332 /* Modified version of "PJW" algorithm (see the "Dragon" compiler book). */
2334 hashval (const unsigned char * str
)
2339 h
= (h
<< 4) + *str
++;
2345 /* Return the hash value of the canonical pathname, excluding the
2346 drive/UNC header, to get a hopefully unique inode number. */
2348 generate_inode_val (const char * name
)
2350 char fullname
[ MAX_PATH
];
2354 /* Get the truly canonical filename, if it exists. (Note: this
2355 doesn't resolve aliasing due to subst commands, or recognise hard
2357 if (!w32_get_long_filename ((char *)name
, fullname
, MAX_PATH
))
2360 parse_root (fullname
, &p
);
2361 /* Normal W32 filesystems are still case insensitive. */
2368 /* MSVC stat function can't cope with UNC names and has other bugs, so
2369 replace it with our own. This also allows us to calculate consistent
2370 inode values without hacks in the main Emacs code. */
2372 stat (const char * path
, struct stat
* buf
)
2375 WIN32_FIND_DATA wfd
;
2380 int rootdir
= FALSE
;
2382 if (path
== NULL
|| buf
== NULL
)
2388 name
= (char *) map_w32_filename (path
, &path
);
2389 /* must be valid filename, no wild cards or other invalid characters */
2390 if (strpbrk (name
, "*?|<>\""))
2396 /* If name is "c:/.." or "/.." then stat "c:/" or "/". */
2397 r
= IS_DEVICE_SEP (name
[1]) ? &name
[2] : name
;
2398 if (IS_DIRECTORY_SEP (r
[0]) && r
[1] == '.' && r
[2] == '.' && r
[3] == '\0')
2403 /* Remove trailing directory separator, unless name is the root
2404 directory of a drive or UNC volume in which case ensure there
2405 is a trailing separator. */
2406 len
= strlen (name
);
2407 rootdir
= (path
>= name
+ len
- 1
2408 && (IS_DIRECTORY_SEP (*path
) || *path
== 0));
2409 name
= strcpy (alloca (len
+ 2), name
);
2411 if (is_unc_volume (name
))
2413 DWORD attrs
= unc_volume_file_attributes (name
);
2418 memset (&wfd
, 0, sizeof (wfd
));
2419 wfd
.dwFileAttributes
= attrs
;
2420 wfd
.ftCreationTime
= utc_base_ft
;
2421 wfd
.ftLastAccessTime
= utc_base_ft
;
2422 wfd
.ftLastWriteTime
= utc_base_ft
;
2423 strcpy (wfd
.cFileName
, name
);
2427 if (!IS_DIRECTORY_SEP (name
[len
-1]))
2428 strcat (name
, "\\");
2429 if (GetDriveType (name
) < 2)
2434 memset (&wfd
, 0, sizeof (wfd
));
2435 wfd
.dwFileAttributes
= FILE_ATTRIBUTE_DIRECTORY
;
2436 wfd
.ftCreationTime
= utc_base_ft
;
2437 wfd
.ftLastAccessTime
= utc_base_ft
;
2438 wfd
.ftLastWriteTime
= utc_base_ft
;
2439 strcpy (wfd
.cFileName
, name
);
2443 if (IS_DIRECTORY_SEP (name
[len
-1]))
2446 /* (This is hacky, but helps when doing file completions on
2447 network drives.) Optimize by using information available from
2448 active readdir if possible. */
2449 len
= strlen (dir_pathname
);
2450 if (IS_DIRECTORY_SEP (dir_pathname
[len
-1]))
2452 if (dir_find_handle
!= INVALID_HANDLE_VALUE
2453 && strnicmp (name
, dir_pathname
, len
) == 0
2454 && IS_DIRECTORY_SEP (name
[len
])
2455 && stricmp (name
+ len
+ 1, dir_static
.d_name
) == 0)
2457 /* This was the last entry returned by readdir. */
2458 wfd
= dir_find_data
;
2462 fh
= FindFirstFile (name
, &wfd
);
2463 if (fh
== INVALID_HANDLE_VALUE
)
2472 if (!NILP (Vw32_get_true_file_attributes
)
2473 /* No access rights required to get info. */
2474 && (fh
= CreateFile (name
, 0, 0, NULL
, OPEN_EXISTING
,
2475 FILE_FLAG_BACKUP_SEMANTICS
, NULL
))
2476 != INVALID_HANDLE_VALUE
)
2478 /* This is more accurate in terms of gettting the correct number
2479 of links, but is quite slow (it is noticable when Emacs is
2480 making a list of file name completions). */
2481 BY_HANDLE_FILE_INFORMATION info
;
2483 if (GetFileInformationByHandle (fh
, &info
))
2485 buf
->st_nlink
= info
.nNumberOfLinks
;
2486 /* Might as well use file index to fake inode values, but this
2487 is not guaranteed to be unique unless we keep a handle open
2488 all the time (even then there are situations where it is
2489 not unique). Reputedly, there are at most 48 bits of info
2490 (on NTFS, presumably less on FAT). */
2491 fake_inode
= info
.nFileIndexLow
^ info
.nFileIndexHigh
;
2499 if (wfd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
2501 buf
->st_mode
= _S_IFDIR
;
2505 switch (GetFileType (fh
))
2507 case FILE_TYPE_DISK
:
2508 buf
->st_mode
= _S_IFREG
;
2510 case FILE_TYPE_PIPE
:
2511 buf
->st_mode
= _S_IFIFO
;
2513 case FILE_TYPE_CHAR
:
2514 case FILE_TYPE_UNKNOWN
:
2516 buf
->st_mode
= _S_IFCHR
;
2523 /* Don't bother to make this information more accurate. */
2524 buf
->st_mode
= (wfd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) ?
2525 _S_IFDIR
: _S_IFREG
;
2531 /* Not sure if there is any point in this. */
2532 if (!NILP (Vw32_generate_fake_inodes
))
2533 fake_inode
= generate_inode_val (name
);
2534 else if (fake_inode
== 0)
2536 /* For want of something better, try to make everything unique. */
2537 static DWORD gen_num
= 0;
2538 fake_inode
= ++gen_num
;
2542 /* MSVC defines _ino_t to be short; other libc's might not. */
2543 if (sizeof (buf
->st_ino
) == 2)
2544 buf
->st_ino
= fake_inode
^ (fake_inode
>> 16);
2546 buf
->st_ino
= fake_inode
;
2548 /* consider files to belong to current user */
2549 buf
->st_uid
= the_passwd
.pw_uid
;
2550 buf
->st_gid
= the_passwd
.pw_gid
;
2552 /* volume_info is set indirectly by map_w32_filename */
2553 buf
->st_dev
= volume_info
.serialnum
;
2554 buf
->st_rdev
= volume_info
.serialnum
;
2557 buf
->st_size
= wfd
.nFileSizeLow
;
2559 /* Convert timestamps to Unix format. */
2560 buf
->st_mtime
= convert_time (wfd
.ftLastWriteTime
);
2561 buf
->st_atime
= convert_time (wfd
.ftLastAccessTime
);
2562 if (buf
->st_atime
== 0) buf
->st_atime
= buf
->st_mtime
;
2563 buf
->st_ctime
= convert_time (wfd
.ftCreationTime
);
2564 if (buf
->st_ctime
== 0) buf
->st_ctime
= buf
->st_mtime
;
2566 /* determine rwx permissions */
2567 if (wfd
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
)
2568 permission
= _S_IREAD
;
2570 permission
= _S_IREAD
| _S_IWRITE
;
2572 if (wfd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
2573 permission
|= _S_IEXEC
;
2574 else if (is_exec (name
))
2575 permission
|= _S_IEXEC
;
2577 buf
->st_mode
|= permission
| (permission
>> 3) | (permission
>> 6);
2582 /* Provide fstat and utime as well as stat for consistent handling of
2585 fstat (int desc
, struct stat
* buf
)
2587 HANDLE fh
= (HANDLE
) _get_osfhandle (desc
);
2588 BY_HANDLE_FILE_INFORMATION info
;
2592 switch (GetFileType (fh
) & ~FILE_TYPE_REMOTE
)
2594 case FILE_TYPE_DISK
:
2595 buf
->st_mode
= _S_IFREG
;
2596 if (!GetFileInformationByHandle (fh
, &info
))
2602 case FILE_TYPE_PIPE
:
2603 buf
->st_mode
= _S_IFIFO
;
2605 case FILE_TYPE_CHAR
:
2606 case FILE_TYPE_UNKNOWN
:
2608 buf
->st_mode
= _S_IFCHR
;
2610 memset (&info
, 0, sizeof (info
));
2611 info
.dwFileAttributes
= 0;
2612 info
.ftCreationTime
= utc_base_ft
;
2613 info
.ftLastAccessTime
= utc_base_ft
;
2614 info
.ftLastWriteTime
= utc_base_ft
;
2617 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
2618 buf
->st_mode
= _S_IFDIR
;
2620 buf
->st_nlink
= info
.nNumberOfLinks
;
2621 /* Might as well use file index to fake inode values, but this
2622 is not guaranteed to be unique unless we keep a handle open
2623 all the time (even then there are situations where it is
2624 not unique). Reputedly, there are at most 48 bits of info
2625 (on NTFS, presumably less on FAT). */
2626 fake_inode
= info
.nFileIndexLow
^ info
.nFileIndexHigh
;
2628 /* MSVC defines _ino_t to be short; other libc's might not. */
2629 if (sizeof (buf
->st_ino
) == 2)
2630 buf
->st_ino
= fake_inode
^ (fake_inode
>> 16);
2632 buf
->st_ino
= fake_inode
;
2634 /* consider files to belong to current user */
2638 buf
->st_dev
= info
.dwVolumeSerialNumber
;
2639 buf
->st_rdev
= info
.dwVolumeSerialNumber
;
2641 buf
->st_size
= info
.nFileSizeLow
;
2643 /* Convert timestamps to Unix format. */
2644 buf
->st_mtime
= convert_time (info
.ftLastWriteTime
);
2645 buf
->st_atime
= convert_time (info
.ftLastAccessTime
);
2646 if (buf
->st_atime
== 0) buf
->st_atime
= buf
->st_mtime
;
2647 buf
->st_ctime
= convert_time (info
.ftCreationTime
);
2648 if (buf
->st_ctime
== 0) buf
->st_ctime
= buf
->st_mtime
;
2650 /* determine rwx permissions */
2651 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
)
2652 permission
= _S_IREAD
;
2654 permission
= _S_IREAD
| _S_IWRITE
;
2656 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
2657 permission
|= _S_IEXEC
;
2660 #if 0 /* no way of knowing the filename */
2661 char * p
= strrchr (name
, '.');
2663 (stricmp (p
, ".exe") == 0 ||
2664 stricmp (p
, ".com") == 0 ||
2665 stricmp (p
, ".bat") == 0 ||
2666 stricmp (p
, ".cmd") == 0))
2667 permission
|= _S_IEXEC
;
2671 buf
->st_mode
|= permission
| (permission
>> 3) | (permission
>> 6);
2677 utime (const char *name
, struct utimbuf
*times
)
2679 struct utimbuf deftime
;
2686 deftime
.modtime
= deftime
.actime
= time (NULL
);
2690 /* Need write access to set times. */
2691 fh
= CreateFile (name
, GENERIC_WRITE
, FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2692 0, OPEN_EXISTING
, 0, NULL
);
2695 convert_from_time_t (times
->actime
, &atime
);
2696 convert_from_time_t (times
->modtime
, &mtime
);
2697 if (!SetFileTime (fh
, NULL
, &atime
, &mtime
))
2715 /* Wrappers for winsock functions to map between our file descriptors
2716 and winsock's handles; also set h_errno for convenience.
2718 To allow Emacs to run on systems which don't have winsock support
2719 installed, we dynamically link to winsock on startup if present, and
2720 otherwise provide the minimum necessary functionality
2721 (eg. gethostname). */
2723 /* function pointers for relevant socket functions */
2724 int (PASCAL
*pfn_WSAStartup
) (WORD wVersionRequired
, LPWSADATA lpWSAData
);
2725 void (PASCAL
*pfn_WSASetLastError
) (int iError
);
2726 int (PASCAL
*pfn_WSAGetLastError
) (void);
2727 int (PASCAL
*pfn_WSAEventSelect
) (SOCKET s
, HANDLE hEventObject
, long lNetworkEvents
);
2728 HANDLE (PASCAL
*pfn_WSACreateEvent
) (void);
2729 int (PASCAL
*pfn_WSACloseEvent
) (HANDLE hEvent
);
2730 int (PASCAL
*pfn_socket
) (int af
, int type
, int protocol
);
2731 int (PASCAL
*pfn_bind
) (SOCKET s
, const struct sockaddr
*addr
, int namelen
);
2732 int (PASCAL
*pfn_connect
) (SOCKET s
, const struct sockaddr
*addr
, int namelen
);
2733 int (PASCAL
*pfn_ioctlsocket
) (SOCKET s
, long cmd
, u_long
*argp
);
2734 int (PASCAL
*pfn_recv
) (SOCKET s
, char * buf
, int len
, int flags
);
2735 int (PASCAL
*pfn_send
) (SOCKET s
, const char * buf
, int len
, int flags
);
2736 int (PASCAL
*pfn_closesocket
) (SOCKET s
);
2737 int (PASCAL
*pfn_shutdown
) (SOCKET s
, int how
);
2738 int (PASCAL
*pfn_WSACleanup
) (void);
2740 u_short (PASCAL
*pfn_htons
) (u_short hostshort
);
2741 u_short (PASCAL
*pfn_ntohs
) (u_short netshort
);
2742 unsigned long (PASCAL
*pfn_inet_addr
) (const char * cp
);
2743 int (PASCAL
*pfn_gethostname
) (char * name
, int namelen
);
2744 struct hostent
* (PASCAL
*pfn_gethostbyname
) (const char * name
);
2745 struct servent
* (PASCAL
*pfn_getservbyname
) (const char * name
, const char * proto
);
2746 int (PASCAL
*pfn_getpeername
) (SOCKET s
, struct sockaddr
*addr
, int * namelen
);
2747 int (PASCAL
*pfn_setsockopt
) (SOCKET s
, int level
, int optname
,
2748 const char * optval
, int optlen
);
2749 int (PASCAL
*pfn_listen
) (SOCKET s
, int backlog
);
2750 int (PASCAL
*pfn_getsockname
) (SOCKET s
, struct sockaddr
* name
,
2752 SOCKET (PASCAL
*pfn_accept
) (SOCKET s
, struct sockaddr
* addr
, int * addrlen
);
2753 int (PASCAL
*pfn_recvfrom
) (SOCKET s
, char * buf
, int len
, int flags
,
2754 struct sockaddr
* from
, int * fromlen
);
2755 int (PASCAL
*pfn_sendto
) (SOCKET s
, const char * buf
, int len
, int flags
,
2756 const struct sockaddr
* to
, int tolen
);
2758 /* SetHandleInformation is only needed to make sockets non-inheritable. */
2759 BOOL (WINAPI
*pfn_SetHandleInformation
) (HANDLE object
, DWORD mask
, DWORD flags
);
2760 #ifndef HANDLE_FLAG_INHERIT
2761 #define HANDLE_FLAG_INHERIT 1
2765 static int winsock_inuse
;
2770 if (winsock_lib
!= NULL
&& winsock_inuse
== 0)
2772 /* Not sure what would cause WSAENETDOWN, or even if it can happen
2773 after WSAStartup returns successfully, but it seems reasonable
2774 to allow unloading winsock anyway in that case. */
2775 if (pfn_WSACleanup () == 0 ||
2776 pfn_WSAGetLastError () == WSAENETDOWN
)
2778 if (FreeLibrary (winsock_lib
))
2787 init_winsock (int load_now
)
2789 WSADATA winsockData
;
2791 if (winsock_lib
!= NULL
)
2794 pfn_SetHandleInformation
= NULL
;
2795 pfn_SetHandleInformation
2796 = (void *) GetProcAddress (GetModuleHandle ("kernel32.dll"),
2797 "SetHandleInformation");
2799 winsock_lib
= LoadLibrary ("Ws2_32.dll");
2801 if (winsock_lib
!= NULL
)
2803 /* dynamically link to socket functions */
2805 #define LOAD_PROC(fn) \
2806 if ((pfn_##fn = (void *) GetProcAddress (winsock_lib, #fn)) == NULL) \
2809 LOAD_PROC( WSAStartup
);
2810 LOAD_PROC( WSASetLastError
);
2811 LOAD_PROC( WSAGetLastError
);
2812 LOAD_PROC( WSAEventSelect
);
2813 LOAD_PROC( WSACreateEvent
);
2814 LOAD_PROC( WSACloseEvent
);
2815 LOAD_PROC( socket
);
2817 LOAD_PROC( connect
);
2818 LOAD_PROC( ioctlsocket
);
2821 LOAD_PROC( closesocket
);
2822 LOAD_PROC( shutdown
);
2825 LOAD_PROC( inet_addr
);
2826 LOAD_PROC( gethostname
);
2827 LOAD_PROC( gethostbyname
);
2828 LOAD_PROC( getservbyname
);
2829 LOAD_PROC( getpeername
);
2830 LOAD_PROC( WSACleanup
);
2831 LOAD_PROC( setsockopt
);
2832 LOAD_PROC( listen
);
2833 LOAD_PROC( getsockname
);
2834 LOAD_PROC( accept
);
2835 LOAD_PROC( recvfrom
);
2836 LOAD_PROC( sendto
);
2839 /* specify version 1.1 of winsock */
2840 if (pfn_WSAStartup (0x101, &winsockData
) == 0)
2842 if (winsockData
.wVersion
!= 0x101)
2847 /* Report that winsock exists and is usable, but leave
2848 socket functions disabled. I am assuming that calling
2849 WSAStartup does not require any network interaction,
2850 and in particular does not cause or require a dial-up
2851 connection to be established. */
2854 FreeLibrary (winsock_lib
);
2862 FreeLibrary (winsock_lib
);
2872 /* function to set h_errno for compatability; map winsock error codes to
2873 normal system codes where they overlap (non-overlapping definitions
2874 are already in <sys/socket.h> */
2878 if (winsock_lib
== NULL
)
2881 h_errno
= pfn_WSAGetLastError ();
2885 case WSAEACCES
: h_errno
= EACCES
; break;
2886 case WSAEBADF
: h_errno
= EBADF
; break;
2887 case WSAEFAULT
: h_errno
= EFAULT
; break;
2888 case WSAEINTR
: h_errno
= EINTR
; break;
2889 case WSAEINVAL
: h_errno
= EINVAL
; break;
2890 case WSAEMFILE
: h_errno
= EMFILE
; break;
2891 case WSAENAMETOOLONG
: h_errno
= ENAMETOOLONG
; break;
2892 case WSAENOTEMPTY
: h_errno
= ENOTEMPTY
; break;
2900 if (h_errno
== 0 && winsock_lib
!= NULL
)
2901 pfn_WSASetLastError (0);
2904 /* Extend strerror to handle the winsock-specific error codes. */
2908 } _wsa_errlist
[] = {
2909 WSAEINTR
, "Interrupted function call",
2910 WSAEBADF
, "Bad file descriptor",
2911 WSAEACCES
, "Permission denied",
2912 WSAEFAULT
, "Bad address",
2913 WSAEINVAL
, "Invalid argument",
2914 WSAEMFILE
, "Too many open files",
2916 WSAEWOULDBLOCK
, "Resource temporarily unavailable",
2917 WSAEINPROGRESS
, "Operation now in progress",
2918 WSAEALREADY
, "Operation already in progress",
2919 WSAENOTSOCK
, "Socket operation on non-socket",
2920 WSAEDESTADDRREQ
, "Destination address required",
2921 WSAEMSGSIZE
, "Message too long",
2922 WSAEPROTOTYPE
, "Protocol wrong type for socket",
2923 WSAENOPROTOOPT
, "Bad protocol option",
2924 WSAEPROTONOSUPPORT
, "Protocol not supported",
2925 WSAESOCKTNOSUPPORT
, "Socket type not supported",
2926 WSAEOPNOTSUPP
, "Operation not supported",
2927 WSAEPFNOSUPPORT
, "Protocol family not supported",
2928 WSAEAFNOSUPPORT
, "Address family not supported by protocol family",
2929 WSAEADDRINUSE
, "Address already in use",
2930 WSAEADDRNOTAVAIL
, "Cannot assign requested address",
2931 WSAENETDOWN
, "Network is down",
2932 WSAENETUNREACH
, "Network is unreachable",
2933 WSAENETRESET
, "Network dropped connection on reset",
2934 WSAECONNABORTED
, "Software caused connection abort",
2935 WSAECONNRESET
, "Connection reset by peer",
2936 WSAENOBUFS
, "No buffer space available",
2937 WSAEISCONN
, "Socket is already connected",
2938 WSAENOTCONN
, "Socket is not connected",
2939 WSAESHUTDOWN
, "Cannot send after socket shutdown",
2940 WSAETOOMANYREFS
, "Too many references", /* not sure */
2941 WSAETIMEDOUT
, "Connection timed out",
2942 WSAECONNREFUSED
, "Connection refused",
2943 WSAELOOP
, "Network loop", /* not sure */
2944 WSAENAMETOOLONG
, "Name is too long",
2945 WSAEHOSTDOWN
, "Host is down",
2946 WSAEHOSTUNREACH
, "No route to host",
2947 WSAENOTEMPTY
, "Buffer not empty", /* not sure */
2948 WSAEPROCLIM
, "Too many processes",
2949 WSAEUSERS
, "Too many users", /* not sure */
2950 WSAEDQUOT
, "Double quote in host name", /* really not sure */
2951 WSAESTALE
, "Data is stale", /* not sure */
2952 WSAEREMOTE
, "Remote error", /* not sure */
2954 WSASYSNOTREADY
, "Network subsystem is unavailable",
2955 WSAVERNOTSUPPORTED
, "WINSOCK.DLL version out of range",
2956 WSANOTINITIALISED
, "Winsock not initialized successfully",
2957 WSAEDISCON
, "Graceful shutdown in progress",
2959 WSAENOMORE
, "No more operations allowed", /* not sure */
2960 WSAECANCELLED
, "Operation cancelled", /* not sure */
2961 WSAEINVALIDPROCTABLE
, "Invalid procedure table from service provider",
2962 WSAEINVALIDPROVIDER
, "Invalid service provider version number",
2963 WSAEPROVIDERFAILEDINIT
, "Unable to initialize a service provider",
2964 WSASYSCALLFAILURE
, "System call failured",
2965 WSASERVICE_NOT_FOUND
, "Service not found", /* not sure */
2966 WSATYPE_NOT_FOUND
, "Class type not found",
2967 WSA_E_NO_MORE
, "No more resources available", /* really not sure */
2968 WSA_E_CANCELLED
, "Operation already cancelled", /* really not sure */
2969 WSAEREFUSED
, "Operation refused", /* not sure */
2972 WSAHOST_NOT_FOUND
, "Host not found",
2973 WSATRY_AGAIN
, "Authoritative host not found during name lookup",
2974 WSANO_RECOVERY
, "Non-recoverable error during name lookup",
2975 WSANO_DATA
, "Valid name, no data record of requested type",
2981 sys_strerror(int error_no
)
2984 static char unknown_msg
[40];
2986 if (error_no
>= 0 && error_no
< sys_nerr
)
2987 return sys_errlist
[error_no
];
2989 for (i
= 0; _wsa_errlist
[i
].errnum
>= 0; i
++)
2990 if (_wsa_errlist
[i
].errnum
== error_no
)
2991 return _wsa_errlist
[i
].msg
;
2993 sprintf(unknown_msg
, "Unidentified error: %d", error_no
);
2997 /* [andrewi 3-May-96] I've had conflicting results using both methods,
2998 but I believe the method of keeping the socket handle separate (and
2999 insuring it is not inheritable) is the correct one. */
3001 //#define SOCK_REPLACE_HANDLE
3003 #ifdef SOCK_REPLACE_HANDLE
3004 #define SOCK_HANDLE(fd) ((SOCKET) _get_osfhandle (fd))
3006 #define SOCK_HANDLE(fd) ((SOCKET) fd_info[fd].hnd)
3009 int socket_to_fd (SOCKET s
);
3012 sys_socket(int af
, int type
, int protocol
)
3016 if (winsock_lib
== NULL
)
3019 return INVALID_SOCKET
;
3024 /* call the real socket function */
3025 s
= pfn_socket (af
, type
, protocol
);
3027 if (s
!= INVALID_SOCKET
)
3028 return socket_to_fd (s
);
3034 /* Convert a SOCKET to a file descriptor. */
3036 socket_to_fd (SOCKET s
)
3041 /* Although under NT 3.5 _open_osfhandle will accept a socket
3042 handle, if opened with SO_OPENTYPE == SO_SYNCHRONOUS_NONALERT,
3043 that does not work under NT 3.1. However, we can get the same
3044 effect by using a backdoor function to replace an existing
3045 descriptor handle with the one we want. */
3047 /* allocate a file descriptor (with appropriate flags) */
3048 fd
= _open ("NUL:", _O_RDWR
);
3051 #ifdef SOCK_REPLACE_HANDLE
3052 /* now replace handle to NUL with our socket handle */
3053 CloseHandle ((HANDLE
) _get_osfhandle (fd
));
3055 _set_osfhnd (fd
, s
);
3056 /* setmode (fd, _O_BINARY); */
3058 /* Make a non-inheritable copy of the socket handle. Note
3059 that it is possible that sockets aren't actually kernel
3060 handles, which appears to be the case on Windows 9x when
3061 the MS Proxy winsock client is installed. */
3063 /* Apparently there is a bug in NT 3.51 with some service
3064 packs, which prevents using DuplicateHandle to make a
3065 socket handle non-inheritable (causes WSACleanup to
3066 hang). The work-around is to use SetHandleInformation
3067 instead if it is available and implemented. */
3068 if (pfn_SetHandleInformation
)
3070 pfn_SetHandleInformation ((HANDLE
) s
, HANDLE_FLAG_INHERIT
, 0);
3074 HANDLE parent
= GetCurrentProcess ();
3075 HANDLE new_s
= INVALID_HANDLE_VALUE
;
3077 if (DuplicateHandle (parent
,
3083 DUPLICATE_SAME_ACCESS
))
3085 /* It is possible that DuplicateHandle succeeds even
3086 though the socket wasn't really a kernel handle,
3087 because a real handle has the same value. So
3088 test whether the new handle really is a socket. */
3089 long nonblocking
= 0;
3090 if (pfn_ioctlsocket ((SOCKET
) new_s
, FIONBIO
, &nonblocking
) == 0)
3092 pfn_closesocket (s
);
3097 CloseHandle (new_s
);
3102 fd_info
[fd
].hnd
= (HANDLE
) s
;
3105 /* set our own internal flags */
3106 fd_info
[fd
].flags
= FILE_SOCKET
| FILE_BINARY
| FILE_READ
| FILE_WRITE
;
3112 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
3114 /* attach child_process to fd_info */
3115 if (fd_info
[ fd
].cp
!= NULL
)
3117 DebPrint (("sys_socket: fd_info[%d] apparently in use!\n", fd
));
3121 fd_info
[ fd
].cp
= cp
;
3124 winsock_inuse
++; /* count open sockets */
3131 pfn_closesocket (s
);
3138 sys_bind (int s
, const struct sockaddr
* addr
, int namelen
)
3140 if (winsock_lib
== NULL
)
3143 return SOCKET_ERROR
;
3147 if (fd_info
[s
].flags
& FILE_SOCKET
)
3149 int rc
= pfn_bind (SOCK_HANDLE (s
), addr
, namelen
);
3150 if (rc
== SOCKET_ERROR
)
3155 return SOCKET_ERROR
;
3160 sys_connect (int s
, const struct sockaddr
* name
, int namelen
)
3162 if (winsock_lib
== NULL
)
3165 return SOCKET_ERROR
;
3169 if (fd_info
[s
].flags
& FILE_SOCKET
)
3171 int rc
= pfn_connect (SOCK_HANDLE (s
), name
, namelen
);
3172 if (rc
== SOCKET_ERROR
)
3177 return SOCKET_ERROR
;
3181 sys_htons (u_short hostshort
)
3183 return (winsock_lib
!= NULL
) ?
3184 pfn_htons (hostshort
) : hostshort
;
3188 sys_ntohs (u_short netshort
)
3190 return (winsock_lib
!= NULL
) ?
3191 pfn_ntohs (netshort
) : netshort
;
3195 sys_inet_addr (const char * cp
)
3197 return (winsock_lib
!= NULL
) ?
3198 pfn_inet_addr (cp
) : INADDR_NONE
;
3202 sys_gethostname (char * name
, int namelen
)
3204 if (winsock_lib
!= NULL
)
3205 return pfn_gethostname (name
, namelen
);
3207 if (namelen
> MAX_COMPUTERNAME_LENGTH
)
3208 return !GetComputerName (name
, (DWORD
*)&namelen
);
3211 return SOCKET_ERROR
;
3215 sys_gethostbyname(const char * name
)
3217 struct hostent
* host
;
3219 if (winsock_lib
== NULL
)
3226 host
= pfn_gethostbyname (name
);
3233 sys_getservbyname(const char * name
, const char * proto
)
3235 struct servent
* serv
;
3237 if (winsock_lib
== NULL
)
3244 serv
= pfn_getservbyname (name
, proto
);
3251 sys_getpeername (int s
, struct sockaddr
*addr
, int * namelen
)
3253 if (winsock_lib
== NULL
)
3256 return SOCKET_ERROR
;
3260 if (fd_info
[s
].flags
& FILE_SOCKET
)
3262 int rc
= pfn_getpeername (SOCK_HANDLE (s
), addr
, namelen
);
3263 if (rc
== SOCKET_ERROR
)
3268 return SOCKET_ERROR
;
3273 sys_shutdown (int s
, int how
)
3275 if (winsock_lib
== NULL
)
3278 return SOCKET_ERROR
;
3282 if (fd_info
[s
].flags
& FILE_SOCKET
)
3284 int rc
= pfn_shutdown (SOCK_HANDLE (s
), how
);
3285 if (rc
== SOCKET_ERROR
)
3290 return SOCKET_ERROR
;
3294 sys_setsockopt (int s
, int level
, int optname
, const void * optval
, int optlen
)
3296 if (winsock_lib
== NULL
)
3299 return SOCKET_ERROR
;
3303 if (fd_info
[s
].flags
& FILE_SOCKET
)
3305 int rc
= pfn_setsockopt (SOCK_HANDLE (s
), level
, optname
,
3306 (const char *)optval
, optlen
);
3307 if (rc
== SOCKET_ERROR
)
3312 return SOCKET_ERROR
;
3316 sys_listen (int s
, int backlog
)
3318 if (winsock_lib
== NULL
)
3321 return SOCKET_ERROR
;
3325 if (fd_info
[s
].flags
& FILE_SOCKET
)
3327 int rc
= pfn_listen (SOCK_HANDLE (s
), backlog
);
3328 if (rc
== SOCKET_ERROR
)
3331 fd_info
[s
].flags
|= FILE_LISTEN
;
3335 return SOCKET_ERROR
;
3339 sys_getsockname (int s
, struct sockaddr
* name
, int * namelen
)
3341 if (winsock_lib
== NULL
)
3344 return SOCKET_ERROR
;
3348 if (fd_info
[s
].flags
& FILE_SOCKET
)
3350 int rc
= pfn_getsockname (SOCK_HANDLE (s
), name
, namelen
);
3351 if (rc
== SOCKET_ERROR
)
3356 return SOCKET_ERROR
;
3360 sys_accept (int s
, struct sockaddr
* addr
, int * addrlen
)
3362 if (winsock_lib
== NULL
)
3369 if (fd_info
[s
].flags
& FILE_LISTEN
)
3371 SOCKET t
= pfn_accept (SOCK_HANDLE (s
), addr
, addrlen
);
3373 if (t
== INVALID_SOCKET
)
3376 fd
= socket_to_fd (t
);
3378 fd_info
[s
].cp
->status
= STATUS_READ_ACKNOWLEDGED
;
3379 ResetEvent (fd_info
[s
].cp
->char_avail
);
3387 sys_recvfrom (int s
, char * buf
, int len
, int flags
,
3388 struct sockaddr
* from
, int * fromlen
)
3390 if (winsock_lib
== NULL
)
3393 return SOCKET_ERROR
;
3397 if (fd_info
[s
].flags
& FILE_SOCKET
)
3399 int rc
= pfn_recvfrom (SOCK_HANDLE (s
), buf
, len
, flags
, from
, fromlen
);
3400 if (rc
== SOCKET_ERROR
)
3405 return SOCKET_ERROR
;
3409 sys_sendto (int s
, const char * buf
, int len
, int flags
,
3410 const struct sockaddr
* to
, int tolen
)
3412 if (winsock_lib
== NULL
)
3415 return SOCKET_ERROR
;
3419 if (fd_info
[s
].flags
& FILE_SOCKET
)
3421 int rc
= pfn_sendto (SOCK_HANDLE (s
), buf
, len
, flags
, to
, tolen
);
3422 if (rc
== SOCKET_ERROR
)
3427 return SOCKET_ERROR
;
3430 /* Windows does not have an fcntl function. Provide an implementation
3431 solely for making sockets non-blocking. */
3433 fcntl (int s
, int cmd
, int options
)
3435 if (winsock_lib
== NULL
)
3442 if (fd_info
[s
].flags
& FILE_SOCKET
)
3444 if (cmd
== F_SETFL
&& options
== O_NDELAY
)
3446 unsigned long nblock
= 1;
3447 int rc
= pfn_ioctlsocket (SOCK_HANDLE (s
), FIONBIO
, &nblock
);
3448 if (rc
== SOCKET_ERROR
)
3450 /* Keep track of the fact that we set this to non-blocking. */
3451 fd_info
[s
].flags
|= FILE_NDELAY
;
3457 return SOCKET_ERROR
;
3461 return SOCKET_ERROR
;
3464 #endif /* HAVE_SOCKETS */
3467 /* Shadow main io functions: we need to handle pipes and sockets more
3468 intelligently, and implement non-blocking mode as well. */
3481 if (fd
< MAXDESC
&& fd_info
[fd
].cp
)
3483 child_process
* cp
= fd_info
[fd
].cp
;
3485 fd_info
[fd
].cp
= NULL
;
3487 if (CHILD_ACTIVE (cp
))
3489 /* if last descriptor to active child_process then cleanup */
3491 for (i
= 0; i
< MAXDESC
; i
++)
3495 if (fd_info
[i
].cp
== cp
)
3501 if (fd_info
[fd
].flags
& FILE_SOCKET
)
3503 #ifndef SOCK_REPLACE_HANDLE
3504 if (winsock_lib
== NULL
) abort ();
3506 pfn_shutdown (SOCK_HANDLE (fd
), 2);
3507 rc
= pfn_closesocket (SOCK_HANDLE (fd
));
3509 winsock_inuse
--; /* count open sockets */
3517 /* Note that sockets do not need special treatment here (at least on
3518 NT and Windows 95 using the standard tcp/ip stacks) - it appears that
3519 closesocket is equivalent to CloseHandle, which is to be expected
3520 because socket handles are fully fledged kernel handles. */
3523 if (rc
== 0 && fd
< MAXDESC
)
3524 fd_info
[fd
].flags
= 0;
3535 if (new_fd
>= 0 && new_fd
< MAXDESC
)
3537 /* duplicate our internal info as well */
3538 fd_info
[new_fd
] = fd_info
[fd
];
3545 sys_dup2 (int src
, int dst
)
3549 if (dst
< 0 || dst
>= MAXDESC
)
3555 /* make sure we close the destination first if it's a pipe or socket */
3556 if (src
!= dst
&& fd_info
[dst
].flags
!= 0)
3559 rc
= _dup2 (src
, dst
);
3562 /* duplicate our internal info as well */
3563 fd_info
[dst
] = fd_info
[src
];
3568 /* Unix pipe() has only one arg */
3570 sys_pipe (int * phandles
)
3575 /* make pipe handles non-inheritable; when we spawn a child, we
3576 replace the relevant handle with an inheritable one. Also put
3577 pipes into binary mode; we will do text mode translation ourselves
3579 rc
= _pipe (phandles
, 0, _O_NOINHERIT
| _O_BINARY
);
3583 /* Protect against overflow, since Windows can open more handles than
3584 our fd_info array has room for. */
3585 if (phandles
[0] >= MAXDESC
|| phandles
[1] >= MAXDESC
)
3587 _close (phandles
[0]);
3588 _close (phandles
[1]);
3593 flags
= FILE_PIPE
| FILE_READ
| FILE_BINARY
;
3594 fd_info
[phandles
[0]].flags
= flags
;
3596 flags
= FILE_PIPE
| FILE_WRITE
| FILE_BINARY
;
3597 fd_info
[phandles
[1]].flags
= flags
;
3605 extern int w32_pipe_read_delay
;
3607 /* Function to do blocking read of one byte, needed to implement
3608 select. It is only allowed on sockets and pipes. */
3610 _sys_read_ahead (int fd
)
3615 if (fd
< 0 || fd
>= MAXDESC
)
3616 return STATUS_READ_ERROR
;
3618 cp
= fd_info
[fd
].cp
;
3620 if (cp
== NULL
|| cp
->fd
!= fd
|| cp
->status
!= STATUS_READ_READY
)
3621 return STATUS_READ_ERROR
;
3623 if ((fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SOCKET
)) == 0
3624 || (fd_info
[fd
].flags
& FILE_READ
) == 0)
3626 DebPrint (("_sys_read_ahead: internal error: fd %d is not a pipe or socket!\n", fd
));
3630 cp
->status
= STATUS_READ_IN_PROGRESS
;
3632 if (fd_info
[fd
].flags
& FILE_PIPE
)
3634 rc
= _read (fd
, &cp
->chr
, sizeof (char));
3636 /* Give subprocess time to buffer some more output for us before
3637 reporting that input is available; we need this because Windows 95
3638 connects DOS programs to pipes by making the pipe appear to be
3639 the normal console stdout - as a result most DOS programs will
3640 write to stdout without buffering, ie. one character at a
3641 time. Even some W32 programs do this - "dir" in a command
3642 shell on NT is very slow if we don't do this. */
3645 int wait
= w32_pipe_read_delay
;
3651 /* Yield remainder of our time slice, effectively giving a
3652 temporary priority boost to the child process. */
3657 else if (fd_info
[fd
].flags
& FILE_SOCKET
)
3659 unsigned long nblock
= 0;
3660 /* We always want this to block, so temporarily disable NDELAY. */
3661 if (fd_info
[fd
].flags
& FILE_NDELAY
)
3662 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
3664 rc
= pfn_recv (SOCK_HANDLE (fd
), &cp
->chr
, sizeof (char), 0);
3666 if (fd_info
[fd
].flags
& FILE_NDELAY
)
3669 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
3674 if (rc
== sizeof (char))
3675 cp
->status
= STATUS_READ_SUCCEEDED
;
3677 cp
->status
= STATUS_READ_FAILED
;
3683 _sys_wait_accept (int fd
)
3689 if (fd
< 0 || fd
>= MAXDESC
)
3690 return STATUS_READ_ERROR
;
3692 cp
= fd_info
[fd
].cp
;
3694 if (cp
== NULL
|| cp
->fd
!= fd
|| cp
->status
!= STATUS_READ_READY
)
3695 return STATUS_READ_ERROR
;
3697 cp
->status
= STATUS_READ_FAILED
;
3699 hEv
= pfn_WSACreateEvent ();
3700 rc
= pfn_WSAEventSelect (SOCK_HANDLE (fd
), hEv
, FD_ACCEPT
);
3701 if (rc
!= SOCKET_ERROR
)
3703 rc
= WaitForSingleObject (hEv
, INFINITE
);
3704 pfn_WSAEventSelect (SOCK_HANDLE (fd
), NULL
, 0);
3705 if (rc
== WAIT_OBJECT_0
)
3706 cp
->status
= STATUS_READ_SUCCEEDED
;
3708 pfn_WSACloseEvent (hEv
);
3714 sys_read (int fd
, char * buffer
, unsigned int count
)
3719 char * orig_buffer
= buffer
;
3727 if (fd
< MAXDESC
&& fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SOCKET
))
3729 child_process
*cp
= fd_info
[fd
].cp
;
3731 if ((fd_info
[fd
].flags
& FILE_READ
) == 0)
3739 /* re-read CR carried over from last read */
3740 if (fd_info
[fd
].flags
& FILE_LAST_CR
)
3742 if (fd_info
[fd
].flags
& FILE_BINARY
) abort ();
3746 fd_info
[fd
].flags
&= ~FILE_LAST_CR
;
3749 /* presence of a child_process structure means we are operating in
3750 non-blocking mode - otherwise we just call _read directly.
3751 Note that the child_process structure might be missing because
3752 reap_subprocess has been called; in this case the pipe is
3753 already broken, so calling _read on it is okay. */
3756 int current_status
= cp
->status
;
3758 switch (current_status
)
3760 case STATUS_READ_FAILED
:
3761 case STATUS_READ_ERROR
:
3762 /* report normal EOF if nothing in buffer */
3764 fd_info
[fd
].flags
|= FILE_AT_EOF
;
3767 case STATUS_READ_READY
:
3768 case STATUS_READ_IN_PROGRESS
:
3769 DebPrint (("sys_read called when read is in progress\n"));
3770 errno
= EWOULDBLOCK
;
3773 case STATUS_READ_SUCCEEDED
:
3774 /* consume read-ahead char */
3775 *buffer
++ = cp
->chr
;
3778 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
3779 ResetEvent (cp
->char_avail
);
3781 case STATUS_READ_ACKNOWLEDGED
:
3785 DebPrint (("sys_read: bad status %d\n", current_status
));
3790 if (fd_info
[fd
].flags
& FILE_PIPE
)
3792 PeekNamedPipe ((HANDLE
) _get_osfhandle (fd
), NULL
, 0, NULL
, &waiting
, NULL
);
3793 to_read
= min (waiting
, (DWORD
) count
);
3796 nchars
+= _read (fd
, buffer
, to_read
);
3799 else /* FILE_SOCKET */
3801 if (winsock_lib
== NULL
) abort ();
3803 /* do the equivalent of a non-blocking read */
3804 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONREAD
, &waiting
);
3805 if (waiting
== 0 && nchars
== 0)
3807 h_errno
= errno
= EWOULDBLOCK
;
3813 /* always use binary mode for sockets */
3814 int res
= pfn_recv (SOCK_HANDLE (fd
), buffer
, count
, 0);
3815 if (res
== SOCKET_ERROR
)
3817 DebPrint(("sys_read.recv failed with error %d on socket %ld\n",
3818 pfn_WSAGetLastError (), SOCK_HANDLE (fd
)));
3829 int nread
= _read (fd
, buffer
, count
);
3832 else if (nchars
== 0)
3837 fd_info
[fd
].flags
|= FILE_AT_EOF
;
3838 /* Perform text mode translation if required. */
3839 else if ((fd_info
[fd
].flags
& FILE_BINARY
) == 0)
3841 nchars
= crlf_to_lf (nchars
, orig_buffer
);
3842 /* If buffer contains only CR, return that. To be absolutely
3843 sure we should attempt to read the next char, but in
3844 practice a CR to be followed by LF would not appear by
3845 itself in the buffer. */
3846 if (nchars
> 1 && orig_buffer
[nchars
- 1] == 0x0d)
3848 fd_info
[fd
].flags
|= FILE_LAST_CR
;
3854 nchars
= _read (fd
, buffer
, count
);
3859 /* For now, don't bother with a non-blocking mode */
3861 sys_write (int fd
, const void * buffer
, unsigned int count
)
3871 if (fd
< MAXDESC
&& fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SOCKET
))
3873 if ((fd_info
[fd
].flags
& FILE_WRITE
) == 0)
3879 /* Perform text mode translation if required. */
3880 if ((fd_info
[fd
].flags
& FILE_BINARY
) == 0)
3882 char * tmpbuf
= alloca (count
* 2);
3883 unsigned char * src
= (void *)buffer
;
3884 unsigned char * dst
= tmpbuf
;
3889 unsigned char *next
;
3890 /* copy next line or remaining bytes */
3891 next
= _memccpy (dst
, src
, '\n', nbytes
);
3894 /* copied one line ending with '\n' */
3895 int copied
= next
- dst
;
3898 /* insert '\r' before '\n' */
3905 /* copied remaining partial line -> now finished */
3913 if (fd
< MAXDESC
&& fd_info
[fd
].flags
& FILE_SOCKET
)
3915 unsigned long nblock
= 0;
3916 if (winsock_lib
== NULL
) abort ();
3918 /* TODO: implement select() properly so non-blocking I/O works. */
3919 /* For now, make sure the write blocks. */
3920 if (fd_info
[fd
].flags
& FILE_NDELAY
)
3921 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
3923 nchars
= pfn_send (SOCK_HANDLE (fd
), buffer
, count
, 0);
3925 /* Set the socket back to non-blocking if it was before,
3926 for other operations that support it. */
3927 if (fd_info
[fd
].flags
& FILE_NDELAY
)
3930 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
3933 if (nchars
== SOCKET_ERROR
)
3935 DebPrint(("sys_write.send failed with error %d on socket %ld\n",
3936 pfn_WSAGetLastError (), SOCK_HANDLE (fd
)));
3942 nchars
= _write (fd
, buffer
, count
);
3948 check_windows_init_file ()
3950 extern int noninteractive
, inhibit_window_system
;
3952 /* A common indication that Emacs is not installed properly is when
3953 it cannot find the Windows installation file. If this file does
3954 not exist in the expected place, tell the user. */
3956 if (!noninteractive
&& !inhibit_window_system
)
3958 extern Lisp_Object Vwindow_system
, Vload_path
, Qfile_exists_p
;
3959 Lisp_Object objs
[2];
3960 Lisp_Object full_load_path
;
3961 Lisp_Object init_file
;
3964 objs
[0] = Vload_path
;
3965 objs
[1] = decode_env_path (0, (getenv ("EMACSLOADPATH")));
3966 full_load_path
= Fappend (2, objs
);
3967 init_file
= build_string ("term/w32-win");
3968 fd
= openp (full_load_path
, init_file
, Fget_load_suffixes (), NULL
, Qnil
);
3971 Lisp_Object load_path_print
= Fprin1_to_string (full_load_path
, Qnil
);
3972 char *init_file_name
= SDATA (init_file
);
3973 char *load_path
= SDATA (load_path_print
);
3974 char *buffer
= alloca (1024
3975 + strlen (init_file_name
)
3976 + strlen (load_path
));
3979 "The Emacs Windows initialization file \"%s.el\" "
3980 "could not be found in your Emacs installation. "
3981 "Emacs checked the following directories for this file:\n"
3983 "When Emacs cannot find this file, it usually means that it "
3984 "was not installed properly, or its distribution file was "
3985 "not unpacked properly.\nSee the README.W32 file in the "
3986 "top-level Emacs directory for more information.",
3987 init_file_name
, load_path
);
3990 "Emacs Abort Dialog",
3991 MB_OK
| MB_ICONEXCLAMATION
| MB_TASKMODAL
);
3992 /* Use the low-level Emacs abort. */
4007 /* shutdown the socket interface if necessary */
4018 /* Initialise the socket interface now if available and requested by
4019 the user by defining PRELOAD_WINSOCK; otherwise loading will be
4020 delayed until open-network-stream is called (w32-has-winsock can
4021 also be used to dynamically load or reload winsock).
4023 Conveniently, init_environment is called before us, so
4024 PRELOAD_WINSOCK can be set in the registry. */
4026 /* Always initialize this correctly. */
4029 if (getenv ("PRELOAD_WINSOCK") != NULL
)
4030 init_winsock (TRUE
);
4033 /* Initial preparation for subprocess support: replace our standard
4034 handles with non-inheritable versions. */
4037 HANDLE stdin_save
= INVALID_HANDLE_VALUE
;
4038 HANDLE stdout_save
= INVALID_HANDLE_VALUE
;
4039 HANDLE stderr_save
= INVALID_HANDLE_VALUE
;
4041 parent
= GetCurrentProcess ();
4043 /* ignore errors when duplicating and closing; typically the
4044 handles will be invalid when running as a gui program. */
4045 DuplicateHandle (parent
,
4046 GetStdHandle (STD_INPUT_HANDLE
),
4051 DUPLICATE_SAME_ACCESS
);
4053 DuplicateHandle (parent
,
4054 GetStdHandle (STD_OUTPUT_HANDLE
),
4059 DUPLICATE_SAME_ACCESS
);
4061 DuplicateHandle (parent
,
4062 GetStdHandle (STD_ERROR_HANDLE
),
4067 DUPLICATE_SAME_ACCESS
);
4073 if (stdin_save
!= INVALID_HANDLE_VALUE
)
4074 _open_osfhandle ((long) stdin_save
, O_TEXT
);
4076 _open ("nul", O_TEXT
| O_NOINHERIT
| O_RDONLY
);
4079 if (stdout_save
!= INVALID_HANDLE_VALUE
)
4080 _open_osfhandle ((long) stdout_save
, O_TEXT
);
4082 _open ("nul", O_TEXT
| O_NOINHERIT
| O_WRONLY
);
4085 if (stderr_save
!= INVALID_HANDLE_VALUE
)
4086 _open_osfhandle ((long) stderr_save
, O_TEXT
);
4088 _open ("nul", O_TEXT
| O_NOINHERIT
| O_WRONLY
);
4092 /* unfortunately, atexit depends on implementation of malloc */
4093 /* atexit (term_ntproc); */
4094 signal (SIGABRT
, term_ntproc
);
4096 /* determine which drives are fixed, for GetCachedVolumeInformation */
4098 /* GetDriveType must have trailing backslash. */
4099 char drive
[] = "A:\\";
4101 /* Loop over all possible drive letters */
4102 while (*drive
<= 'Z')
4104 /* Record if this drive letter refers to a fixed drive. */
4105 fixed_drives
[DRIVE_INDEX (*drive
)] =
4106 (GetDriveType (drive
) == DRIVE_FIXED
);
4111 /* Reset the volume info cache. */
4112 volume_cache
= NULL
;
4115 /* Check to see if Emacs has been installed correctly. */
4116 check_windows_init_file ();
4120 shutdown_handler ensures that buffers' autosave files are
4121 up to date when the user logs off, or the system shuts down.
4123 BOOL WINAPI
shutdown_handler(DWORD type
)
4125 /* Ctrl-C and Ctrl-Break are already suppressed, so don't handle them. */
4126 if (type
== CTRL_CLOSE_EVENT
/* User closes console window. */
4127 || type
== CTRL_LOGOFF_EVENT
/* User logs off. */
4128 || type
== CTRL_SHUTDOWN_EVENT
) /* User shutsdown. */
4130 /* Shut down cleanly, making sure autosave files are up to date. */
4131 shut_down_emacs (0, 0, Qnil
);
4134 /* Allow other handlers to handle this signal. */
4139 globals_of_w32 is used to initialize those global variables that
4140 must always be initialized on startup even when the global variable
4141 initialized is non zero (see the function main in emacs.c).
4146 g_b_init_is_windows_9x
= 0;
4147 g_b_init_open_process_token
= 0;
4148 g_b_init_get_token_information
= 0;
4149 g_b_init_lookup_account_sid
= 0;
4150 g_b_init_get_sid_identifier_authority
= 0;
4151 /* The following sets a handler for shutdown notifications for
4152 console apps. This actually applies to Emacs in both console and
4153 GUI modes, since we had to fool windows into thinking emacs is a
4154 console application to get console mode to work. */
4155 SetConsoleCtrlHandler(shutdown_handler
, TRUE
);
4160 /* arch-tag: 90442dd3-37be-482b-b272-ac752e3049f1
4161 (do not change this comment) */