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 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 ** */
156 static BOOL
is_windows_9x ()
158 static BOOL s_b_ret
=0;
159 OSVERSIONINFO os_ver
;
160 if (g_b_init_is_windows_9x
== 0)
162 g_b_init_is_windows_9x
= 1;
163 ZeroMemory(&os_ver
, sizeof(OSVERSIONINFO
));
164 os_ver
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
165 if (GetVersionEx (&os_ver
))
167 s_b_ret
= (os_ver
.dwPlatformId
== VER_PLATFORM_WIN32_WINDOWS
);
173 /* ** The wrapper functions ** */
175 BOOL WINAPI
open_process_token (
176 HANDLE ProcessHandle
,
180 static OpenProcessToken_Proc s_pfn_Open_Process_Token
= NULL
;
181 HMODULE hm_advapi32
= NULL
;
182 if (is_windows_9x () == TRUE
)
186 if (g_b_init_open_process_token
== 0)
188 g_b_init_open_process_token
= 1;
189 hm_advapi32
= LoadLibrary ("Advapi32.dll");
190 s_pfn_Open_Process_Token
=
191 (OpenProcessToken_Proc
) GetProcAddress (hm_advapi32
, "OpenProcessToken");
193 if (s_pfn_Open_Process_Token
== NULL
)
198 s_pfn_Open_Process_Token (
205 BOOL WINAPI
get_token_information (
207 TOKEN_INFORMATION_CLASS TokenInformationClass
,
208 LPVOID TokenInformation
,
209 DWORD TokenInformationLength
,
212 static GetTokenInformation_Proc s_pfn_Get_Token_Information
= NULL
;
213 HMODULE hm_advapi32
= NULL
;
214 if (is_windows_9x () == TRUE
)
218 if (g_b_init_get_token_information
== 0)
220 g_b_init_get_token_information
= 1;
221 hm_advapi32
= LoadLibrary ("Advapi32.dll");
222 s_pfn_Get_Token_Information
=
223 (GetTokenInformation_Proc
) GetProcAddress (hm_advapi32
, "GetTokenInformation");
225 if (s_pfn_Get_Token_Information
== NULL
)
230 s_pfn_Get_Token_Information (
232 TokenInformationClass
,
234 TokenInformationLength
,
239 BOOL WINAPI
lookup_account_sid (
240 LPCTSTR lpSystemName
,
245 LPDWORD cbDomainName
,
248 static LookupAccountSid_Proc s_pfn_Lookup_Account_Sid
= NULL
;
249 HMODULE hm_advapi32
= NULL
;
250 if (is_windows_9x () == TRUE
)
254 if (g_b_init_lookup_account_sid
== 0)
256 g_b_init_lookup_account_sid
= 1;
257 hm_advapi32
= LoadLibrary ("Advapi32.dll");
258 s_pfn_Lookup_Account_Sid
=
259 (LookupAccountSid_Proc
) GetProcAddress (hm_advapi32
, LookupAccountSid_Name
);
261 if (s_pfn_Lookup_Account_Sid
== NULL
)
266 s_pfn_Lookup_Account_Sid (
277 PSID_IDENTIFIER_AUTHORITY WINAPI
get_sid_identifier_authority (
280 static GetSidIdentifierAuthority_Proc s_pfn_Get_Sid_Identifier_Authority
= NULL
;
281 HMODULE hm_advapi32
= NULL
;
282 if (is_windows_9x () == TRUE
)
286 if (g_b_init_get_sid_identifier_authority
== 0)
288 g_b_init_get_sid_identifier_authority
= 1;
289 hm_advapi32
= LoadLibrary ("Advapi32.dll");
290 s_pfn_Get_Sid_Identifier_Authority
=
291 (GetSidIdentifierAuthority_Proc
) GetProcAddress (
292 hm_advapi32
, "GetSidIdentifierAuthority");
294 if (s_pfn_Get_Sid_Identifier_Authority
== NULL
)
298 return (s_pfn_Get_Sid_Identifier_Authority (pSid
));
302 END: Wrapper functions around OpenProcessToken
303 and other functions in advapi32.dll that are only
304 supported in Windows NT / 2k / XP
308 /* Equivalent of strerror for W32 error codes. */
310 w32_strerror (int error_no
)
312 static char buf
[500];
315 error_no
= GetLastError ();
318 if (!FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM
, NULL
,
320 0, /* choose most suitable language */
321 buf
, sizeof (buf
), NULL
))
322 sprintf (buf
, "w32 error %u", error_no
);
326 static char startup_dir
[MAXPATHLEN
];
328 /* Get the current working directory. */
333 if (GetCurrentDirectory (MAXPATHLEN
, dir
) > 0)
337 /* Emacs doesn't actually change directory itself, and we want to
338 force our real wd to be where emacs.exe is to avoid unnecessary
339 conflicts when trying to rename or delete directories. */
340 strcpy (dir
, startup_dir
);
346 /* Emulate gethostname. */
348 gethostname (char *buffer
, int size
)
350 /* NT only allows small host names, so the buffer is
351 certainly large enough. */
352 return !GetComputerName (buffer
, &size
);
354 #endif /* HAVE_SOCKETS */
356 /* Emulate getloadavg. */
358 getloadavg (double loadavg
[], int nelem
)
362 /* A faithful emulation is going to have to be saved for a rainy day. */
363 for (i
= 0; i
< nelem
; i
++)
370 /* Emulate getpwuid, getpwnam and others. */
372 #define PASSWD_FIELD_SIZE 256
374 static char the_passwd_name
[PASSWD_FIELD_SIZE
];
375 static char the_passwd_passwd
[PASSWD_FIELD_SIZE
];
376 static char the_passwd_gecos
[PASSWD_FIELD_SIZE
];
377 static char the_passwd_dir
[PASSWD_FIELD_SIZE
];
378 static char the_passwd_shell
[PASSWD_FIELD_SIZE
];
380 static struct passwd the_passwd
=
392 static struct group the_group
=
394 /* There are no groups on NT, so we just return "root" as the
402 return the_passwd
.pw_uid
;
408 /* I could imagine arguing for checking to see whether the user is
409 in the Administrators group and returning a UID of 0 for that
410 case, but I don't know how wise that would be in the long run. */
417 return the_passwd
.pw_gid
;
429 if (uid
== the_passwd
.pw_uid
)
441 getpwnam (char *name
)
445 pw
= getpwuid (getuid ());
449 if (stricmp (name
, pw
->pw_name
))
458 /* Find the user's real name by opening the process token and
459 looking up the name associated with the user-sid in that token.
461 Use the relative portion of the identifier authority value from
462 the user-sid as the user id value (same for group id using the
463 primary group sid from the process token). */
465 char user_sid
[256], name
[256], domain
[256];
466 DWORD length
= sizeof (name
), dlength
= sizeof (domain
), trash
;
468 SID_NAME_USE user_type
;
471 open_process_token (GetCurrentProcess (), TOKEN_QUERY
, &token
)
472 && get_token_information (
474 (PVOID
) user_sid
, sizeof (user_sid
), &trash
)
475 && lookup_account_sid (
476 NULL
, *((PSID
*) user_sid
), name
, &length
,
477 domain
, &dlength
, &user_type
)
480 strcpy (the_passwd
.pw_name
, name
);
481 /* Determine a reasonable uid value. */
482 if (stricmp ("administrator", name
) == 0)
484 the_passwd
.pw_uid
= 0;
485 the_passwd
.pw_gid
= 0;
489 SID_IDENTIFIER_AUTHORITY
* pSIA
;
491 pSIA
= get_sid_identifier_authority (*((PSID
*) user_sid
));
492 /* I believe the relative portion is the last 4 bytes (of 6)
494 the_passwd
.pw_uid
= ((pSIA
->Value
[2] << 24) +
495 (pSIA
->Value
[3] << 16) +
496 (pSIA
->Value
[4] << 8) +
497 (pSIA
->Value
[5] << 0));
498 /* restrict to conventional uid range for normal users */
499 the_passwd
.pw_uid
= the_passwd
.pw_uid
% 60001;
502 if (get_token_information (token
, TokenPrimaryGroup
,
503 (PVOID
) user_sid
, sizeof (user_sid
), &trash
))
505 SID_IDENTIFIER_AUTHORITY
* pSIA
;
507 pSIA
= get_sid_identifier_authority (*((PSID
*) user_sid
));
508 the_passwd
.pw_gid
= ((pSIA
->Value
[2] << 24) +
509 (pSIA
->Value
[3] << 16) +
510 (pSIA
->Value
[4] << 8) +
511 (pSIA
->Value
[5] << 0));
512 /* I don't know if this is necessary, but for safety... */
513 the_passwd
.pw_gid
= the_passwd
.pw_gid
% 60001;
516 the_passwd
.pw_gid
= the_passwd
.pw_uid
;
519 /* If security calls are not supported (presumably because we
520 are running under Windows 95), fallback to this. */
521 else if (GetUserName (name
, &length
))
523 strcpy (the_passwd
.pw_name
, name
);
524 if (stricmp ("administrator", name
) == 0)
525 the_passwd
.pw_uid
= 0;
527 the_passwd
.pw_uid
= 123;
528 the_passwd
.pw_gid
= the_passwd
.pw_uid
;
532 strcpy (the_passwd
.pw_name
, "unknown");
533 the_passwd
.pw_uid
= 123;
534 the_passwd
.pw_gid
= 123;
537 /* Ensure HOME and SHELL are defined. */
538 if (getenv ("HOME") == NULL
)
540 if (getenv ("SHELL") == NULL
)
543 /* Set dir and shell from environment variables. */
544 strcpy (the_passwd
.pw_dir
, getenv ("HOME"));
545 strcpy (the_passwd
.pw_shell
, getenv ("SHELL"));
554 /* rand () on NT gives us 15 random bits...hack together 30 bits. */
555 return ((rand () << 15) | rand ());
565 /* Normalize filename by converting all path separators to
566 the specified separator. Also conditionally convert upper
567 case path name components to lower case. */
570 normalize_filename (fp
, path_sep
)
577 /* Always lower-case drive letters a-z, even if the filesystem
578 preserves case in filenames.
579 This is so filenames can be compared by string comparison
580 functions that are case-sensitive. Even case-preserving filesystems
581 do not distinguish case in drive letters. */
582 if (fp
[1] == ':' && *fp
>= 'A' && *fp
<= 'Z')
588 if (NILP (Vw32_downcase_file_names
))
592 if (*fp
== '/' || *fp
== '\\')
599 sep
= path_sep
; /* convert to this path separator */
600 elem
= fp
; /* start of current path element */
603 if (*fp
>= 'a' && *fp
<= 'z')
604 elem
= 0; /* don't convert this element */
606 if (*fp
== 0 || *fp
== ':')
608 sep
= *fp
; /* restore current separator (or 0) */
609 *fp
= '/'; /* after conversion of this element */
612 if (*fp
== '/' || *fp
== '\\')
614 if (elem
&& elem
!= fp
)
616 *fp
= 0; /* temporary end of string */
617 _strlwr (elem
); /* while we convert to lower case */
619 *fp
= sep
; /* convert (or restore) path separator */
620 elem
= fp
+ 1; /* next element starts after separator */
626 /* Destructively turn backslashes into slashes. */
628 dostounix_filename (p
)
631 normalize_filename (p
, '/');
634 /* Destructively turn slashes into backslashes. */
636 unixtodos_filename (p
)
639 normalize_filename (p
, '\\');
642 /* Remove all CR's that are followed by a LF.
643 (From msdos.c...probably should figure out a way to share it,
644 although this code isn't going to ever change.) */
648 register unsigned char *buf
;
650 unsigned char *np
= buf
;
651 unsigned char *startp
= buf
;
652 unsigned char *endp
= buf
+ n
;
656 while (buf
< endp
- 1)
660 if (*(++buf
) != 0x0a)
671 /* Parse the root part of file name, if present. Return length and
672 optionally store pointer to char after root. */
674 parse_root (char * name
, char ** pPath
)
681 /* find the root name of the volume if given */
682 if (isalpha (name
[0]) && name
[1] == ':')
684 /* skip past drive specifier */
686 if (IS_DIRECTORY_SEP (name
[0]))
689 else if (IS_DIRECTORY_SEP (name
[0]) && IS_DIRECTORY_SEP (name
[1]))
695 if (IS_DIRECTORY_SEP (*name
) && --slashes
== 0)
700 if (IS_DIRECTORY_SEP (name
[0]))
710 /* Get long base name for name; name is assumed to be absolute. */
712 get_long_basename (char * name
, char * buf
, int size
)
714 WIN32_FIND_DATA find_data
;
718 /* must be valid filename, no wild cards or other invalid characters */
719 if (strpbrk (name
, "*?|<>\""))
722 dir_handle
= FindFirstFile (name
, &find_data
);
723 if (dir_handle
!= INVALID_HANDLE_VALUE
)
725 if ((len
= strlen (find_data
.cFileName
)) < size
)
726 memcpy (buf
, find_data
.cFileName
, len
+ 1);
729 FindClose (dir_handle
);
734 /* Get long name for file, if possible (assumed to be absolute). */
736 w32_get_long_filename (char * name
, char * buf
, int size
)
741 char full
[ MAX_PATH
];
748 /* Use local copy for destructive modification. */
749 memcpy (full
, name
, len
+1);
750 unixtodos_filename (full
);
752 /* Copy root part verbatim. */
753 len
= parse_root (full
, &p
);
754 memcpy (o
, full
, len
);
759 while (p
!= NULL
&& *p
)
762 p
= strchr (q
, '\\');
764 len
= get_long_basename (full
, o
, size
);
787 is_unc_volume (const char *filename
)
789 const char *ptr
= filename
;
791 if (!IS_DIRECTORY_SEP (ptr
[0]) || !IS_DIRECTORY_SEP (ptr
[1]) || !ptr
[2])
794 if (strpbrk (ptr
+ 2, "*?|<>\"\\/"))
800 /* Routines that are no-ops on NT but are defined to get Emacs to compile. */
803 sigsetmask (int signal_mask
)
827 setpgrp (int pid
, int gid
)
839 unrequest_sigio (void)
850 #define REG_ROOT "SOFTWARE\\GNU\\Emacs"
853 w32_get_resource (key
, lpdwtype
)
858 HKEY hrootkey
= NULL
;
862 /* Check both the current user and the local machine to see if
863 we have any resources. */
865 if (RegOpenKeyEx (HKEY_CURRENT_USER
, REG_ROOT
, 0, KEY_READ
, &hrootkey
) == ERROR_SUCCESS
)
869 if (RegQueryValueEx (hrootkey
, key
, NULL
, NULL
, NULL
, &cbData
) == ERROR_SUCCESS
870 && (lpvalue
= (LPBYTE
) xmalloc (cbData
)) != NULL
871 && RegQueryValueEx (hrootkey
, key
, NULL
, lpdwtype
, lpvalue
, &cbData
) == ERROR_SUCCESS
)
876 if (lpvalue
) xfree (lpvalue
);
878 RegCloseKey (hrootkey
);
881 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE
, REG_ROOT
, 0, KEY_READ
, &hrootkey
) == ERROR_SUCCESS
)
885 if (RegQueryValueEx (hrootkey
, key
, NULL
, NULL
, NULL
, &cbData
) == ERROR_SUCCESS
886 && (lpvalue
= (LPBYTE
) xmalloc (cbData
)) != NULL
887 && RegQueryValueEx (hrootkey
, key
, NULL
, lpdwtype
, lpvalue
, &cbData
) == ERROR_SUCCESS
)
892 if (lpvalue
) xfree (lpvalue
);
894 RegCloseKey (hrootkey
);
900 char *get_emacs_configuration (void);
901 extern Lisp_Object Vsystem_configuration
;
904 init_environment (char ** argv
)
906 static const char * const tempdirs
[] = {
907 "$TMPDIR", "$TEMP", "$TMP", "c:/"
912 const int imax
= sizeof (tempdirs
) / sizeof (tempdirs
[0]);
914 /* Make sure they have a usable $TMPDIR. Many Emacs functions use
915 temporary files and assume "/tmp" if $TMPDIR is unset, which
916 will break on DOS/Windows. Refuse to work if we cannot find
917 a directory, not even "c:/", usable for that purpose. */
918 for (i
= 0; i
< imax
; i
++)
920 const char *tmp
= tempdirs
[i
];
923 tmp
= getenv (tmp
+ 1);
924 /* Note that `access' can lie to us if the directory resides on a
925 read-only filesystem, like CD-ROM or a write-protected floppy.
926 The only way to be really sure is to actually create a file and
927 see if it succeeds. But I think that's too much to ask. */
928 if (tmp
&& _access (tmp
, D_OK
) == 0)
930 char * var
= alloca (strlen (tmp
) + 8);
931 sprintf (var
, "TMPDIR=%s", tmp
);
932 _putenv (strdup (var
));
939 Fcons (build_string ("no usable temporary directories found!!"),
941 "While setting TMPDIR: ");
943 /* Check for environment variables and use registry settings if they
944 don't exist. Fallback on default values where applicable. */
949 char locale_name
[32];
951 char default_home
[MAX_PATH
];
953 static const struct env_entry
960 {"PRELOAD_WINSOCK", NULL
},
961 {"emacs_dir", "C:/emacs"},
962 {"EMACSLOADPATH", "%emacs_dir%/site-lisp;%emacs_dir%/../site-lisp;%emacs_dir%/lisp;%emacs_dir%/leim"},
963 {"SHELL", "%emacs_dir%/bin/cmdproxy.exe"},
964 {"EMACSDATA", "%emacs_dir%/etc"},
965 {"EMACSPATH", "%emacs_dir%/bin"},
966 /* We no longer set INFOPATH because Info-default-directory-list
968 /* {"INFOPATH", "%emacs_dir%/info"}, */
969 {"EMACSDOC", "%emacs_dir%/etc"},
974 #define N_ENV_VARS sizeof(dflt_envvars)/sizeof(dflt_envvars[0])
976 /* We need to copy dflt_envvars[] and work on the copy because we
977 don't want the dumped Emacs to inherit the values of
978 environment variables we saw during dumping (which could be on
979 a different system). The defaults above must be left intact. */
980 struct env_entry env_vars
[N_ENV_VARS
];
982 for (i
= 0; i
< N_ENV_VARS
; i
++)
983 env_vars
[i
] = dflt_envvars
[i
];
985 /* For backwards compatibility, check if a .emacs file exists in C:/
986 If not, then we can try to default to the appdata directory under the
987 user's profile, which is more likely to be writable. */
988 if (stat ("C:/.emacs", &ignored
) < 0)
990 HRESULT profile_result
;
991 /* Dynamically load ShGetFolderPath, as it won't exist on versions
992 of Windows 95 and NT4 that have not been updated to include
993 MSIE 5. Also we don't link with shell32.dll by default. */
995 ShGetFolderPath_fn get_folder_path
;
996 shell32_dll
= GetModuleHandle ("shell32.dll");
997 get_folder_path
= (ShGetFolderPath_fn
)
998 GetProcAddress (shell32_dll
, "SHGetFolderPathA");
1000 if (get_folder_path
!= NULL
)
1002 profile_result
= get_folder_path (NULL
, CSIDL_APPDATA
, NULL
,
1005 /* If we can't get the appdata dir, revert to old behaviour. */
1006 if (profile_result
== S_OK
)
1007 env_vars
[0].def_value
= default_home
;
1010 /* Unload shell32.dll, it is not needed anymore. */
1011 FreeLibrary (shell32_dll
);
1014 /* Get default locale info and use it for LANG. */
1015 if (GetLocaleInfo (LOCALE_USER_DEFAULT
,
1016 LOCALE_SABBREVLANGNAME
| LOCALE_USE_CP_ACP
,
1017 locale_name
, sizeof (locale_name
)))
1019 for (i
= 0; i
< N_ENV_VARS
; i
++)
1021 if (strcmp (env_vars
[i
].name
, "LANG") == 0)
1023 env_vars
[i
].def_value
= locale_name
;
1029 #define SET_ENV_BUF_SIZE (4 * MAX_PATH) /* to cover EMACSLOADPATH */
1031 /* Treat emacs_dir specially: set it unconditionally based on our
1032 location, if it appears that we are running from the bin subdir
1033 of a standard installation. */
1036 char modname
[MAX_PATH
];
1038 if (!GetModuleFileName (NULL
, modname
, MAX_PATH
))
1040 if ((p
= strrchr (modname
, '\\')) == NULL
)
1044 if ((p
= strrchr (modname
, '\\')) && stricmp (p
, "\\bin") == 0)
1046 char buf
[SET_ENV_BUF_SIZE
];
1049 for (p
= modname
; *p
; p
++)
1050 if (*p
== '\\') *p
= '/';
1052 _snprintf (buf
, sizeof(buf
)-1, "emacs_dir=%s", modname
);
1053 _putenv (strdup (buf
));
1055 /* Handle running emacs from the build directory: src/oo-spd/i386/ */
1057 /* FIXME: should use substring of get_emacs_configuration ().
1058 But I don't think the Windows build supports alpha, mips etc
1059 anymore, so have taken the easy option for now. */
1060 else if (p
&& stricmp (p
, "\\i386") == 0)
1063 p
= strrchr (modname
, '\\');
1067 p
= strrchr (modname
, '\\');
1068 if (p
&& stricmp (p
, "\\src") == 0)
1070 char buf
[SET_ENV_BUF_SIZE
];
1073 for (p
= modname
; *p
; p
++)
1074 if (*p
== '\\') *p
= '/';
1076 _snprintf (buf
, sizeof(buf
)-1, "emacs_dir=%s", modname
);
1077 _putenv (strdup (buf
));
1083 for (i
= 0; i
< N_ENV_VARS
; i
++)
1085 if (!getenv (env_vars
[i
].name
))
1089 if ((lpval
= w32_get_resource (env_vars
[i
].name
, &dwType
)) == NULL
)
1091 lpval
= env_vars
[i
].def_value
;
1092 dwType
= REG_EXPAND_SZ
;
1098 char buf1
[SET_ENV_BUF_SIZE
], buf2
[SET_ENV_BUF_SIZE
];
1100 if (dwType
== REG_EXPAND_SZ
)
1101 ExpandEnvironmentStrings ((LPSTR
) lpval
, buf1
, sizeof(buf1
));
1102 else if (dwType
== REG_SZ
)
1103 strcpy (buf1
, lpval
);
1104 if (dwType
== REG_EXPAND_SZ
|| dwType
== REG_SZ
)
1106 _snprintf (buf2
, sizeof(buf2
)-1, "%s=%s", env_vars
[i
].name
,
1108 _putenv (strdup (buf2
));
1118 /* Rebuild system configuration to reflect invoking system. */
1119 Vsystem_configuration
= build_string (EMACS_CONFIGURATION
);
1121 /* Another special case: on NT, the PATH variable is actually named
1122 "Path" although cmd.exe (perhaps NT itself) arranges for
1123 environment variable lookup and setting to be case insensitive.
1124 However, Emacs assumes a fully case sensitive environment, so we
1125 need to change "Path" to "PATH" to match the expectations of
1126 various elisp packages. We do this by the sneaky method of
1127 modifying the string in the C runtime environ entry.
1129 The same applies to COMSPEC. */
1133 for (envp
= environ
; *envp
; envp
++)
1134 if (_strnicmp (*envp
, "PATH=", 5) == 0)
1135 memcpy (*envp
, "PATH=", 5);
1136 else if (_strnicmp (*envp
, "COMSPEC=", 8) == 0)
1137 memcpy (*envp
, "COMSPEC=", 8);
1140 /* Remember the initial working directory for getwd, then make the
1141 real wd be the location of emacs.exe to avoid conflicts when
1142 renaming or deleting directories. (We also don't call chdir when
1143 running subprocesses for the same reason.) */
1144 if (!GetCurrentDirectory (MAXPATHLEN
, startup_dir
))
1149 static char modname
[MAX_PATH
];
1151 if (!GetModuleFileName (NULL
, modname
, MAX_PATH
))
1153 if ((p
= strrchr (modname
, '\\')) == NULL
)
1157 SetCurrentDirectory (modname
);
1159 /* Ensure argv[0] has the full path to Emacs. */
1164 /* Determine if there is a middle mouse button, to allow parse_button
1165 to decide whether right mouse events should be mouse-2 or
1167 w32_num_mouse_buttons
= GetSystemMetrics (SM_CMOUSEBUTTONS
);
1173 emacs_root_dir (void)
1175 static char root_dir
[FILENAME_MAX
];
1178 p
= getenv ("emacs_dir");
1181 strcpy (root_dir
, p
);
1182 root_dir
[parse_root (root_dir
, NULL
)] = '\0';
1183 dostounix_filename (root_dir
);
1187 /* We don't have scripts to automatically determine the system configuration
1188 for Emacs before it's compiled, and we don't want to have to make the
1189 user enter it, so we define EMACS_CONFIGURATION to invoke this runtime
1193 get_emacs_configuration (void)
1195 char *arch
, *oem
, *os
;
1197 static char configuration_buffer
[32];
1199 /* Determine the processor type. */
1200 switch (get_processor_type ())
1203 #ifdef PROCESSOR_INTEL_386
1204 case PROCESSOR_INTEL_386
:
1205 case PROCESSOR_INTEL_486
:
1206 case PROCESSOR_INTEL_PENTIUM
:
1211 #ifdef PROCESSOR_INTEL_860
1212 case PROCESSOR_INTEL_860
:
1217 #ifdef PROCESSOR_MIPS_R2000
1218 case PROCESSOR_MIPS_R2000
:
1219 case PROCESSOR_MIPS_R3000
:
1220 case PROCESSOR_MIPS_R4000
:
1225 #ifdef PROCESSOR_ALPHA_21064
1226 case PROCESSOR_ALPHA_21064
:
1236 /* Use the OEM field to reflect the compiler/library combination. */
1238 #define COMPILER_NAME "msvc"
1241 #define COMPILER_NAME "mingw"
1243 #define COMPILER_NAME "unknown"
1246 oem
= COMPILER_NAME
;
1248 switch (osinfo_cache
.dwPlatformId
) {
1249 case VER_PLATFORM_WIN32_NT
:
1251 build_num
= osinfo_cache
.dwBuildNumber
;
1253 case VER_PLATFORM_WIN32_WINDOWS
:
1254 if (osinfo_cache
.dwMinorVersion
== 0) {
1259 build_num
= LOWORD (osinfo_cache
.dwBuildNumber
);
1261 case VER_PLATFORM_WIN32s
:
1262 /* Not supported, should not happen. */
1264 build_num
= LOWORD (osinfo_cache
.dwBuildNumber
);
1272 if (osinfo_cache
.dwPlatformId
== VER_PLATFORM_WIN32_NT
) {
1273 sprintf (configuration_buffer
, "%s-%s-%s%d.%d.%d", arch
, oem
, os
,
1274 get_w32_major_version (), get_w32_minor_version (), build_num
);
1276 sprintf (configuration_buffer
, "%s-%s-%s.%d", arch
, oem
, os
, build_num
);
1279 return configuration_buffer
;
1283 get_emacs_configuration_options (void)
1285 static char options_buffer
[256];
1287 /* Work out the effective configure options for this build. */
1289 #define COMPILER_VERSION "--with-msvc (%d.%02d)", _MSC_VER / 100, _MSC_VER % 100
1292 #define COMPILER_VERSION "--with-gcc (%d.%d)", __GNUC__, __GNUC_MINOR__
1294 #define COMPILER_VERSION ""
1298 sprintf (options_buffer
, COMPILER_VERSION
);
1300 strcat (options_buffer
, " --no-opt");
1303 strcat (options_buffer
, " --cflags");
1304 strcat (options_buffer
, USER_CFLAGS
);
1307 strcat (options_buffer
, " --ldflags");
1308 strcat (options_buffer
, USER_LDFLAGS
);
1310 return options_buffer
;
1314 #include <sys/timeb.h>
1316 /* Emulate gettimeofday (Ulrich Leodolter, 1/11/95). */
1318 gettimeofday (struct timeval
*tv
, struct timezone
*tz
)
1323 tv
->tv_sec
= tb
.time
;
1324 tv
->tv_usec
= tb
.millitm
* 1000L;
1327 tz
->tz_minuteswest
= tb
.timezone
; /* minutes west of Greenwich */
1328 tz
->tz_dsttime
= tb
.dstflag
; /* type of dst correction */
1332 /* ------------------------------------------------------------------------- */
1333 /* IO support and wrapper functions for W32 API. */
1334 /* ------------------------------------------------------------------------- */
1336 /* Place a wrapper around the MSVC version of ctime. It returns NULL
1337 on network directories, so we handle that case here.
1338 (Ulrich Leodolter, 1/11/95). */
1340 sys_ctime (const time_t *t
)
1342 char *str
= (char *) ctime (t
);
1343 return (str
? str
: "Sun Jan 01 00:00:00 1970");
1346 /* Emulate sleep...we could have done this with a define, but that
1347 would necessitate including windows.h in the files that used it.
1348 This is much easier. */
1350 sys_sleep (int seconds
)
1352 Sleep (seconds
* 1000);
1355 /* Internal MSVC functions for low-level descriptor munging */
1356 extern int __cdecl
_set_osfhnd (int fd
, long h
);
1357 extern int __cdecl
_free_osfhnd (int fd
);
1359 /* parallel array of private info on file handles */
1360 filedesc fd_info
[ MAXDESC
];
1362 typedef struct volume_info_data
{
1363 struct volume_info_data
* next
;
1365 /* time when info was obtained */
1368 /* actual volume info */
1377 /* Global referenced by various functions. */
1378 static volume_info_data volume_info
;
1380 /* Vector to indicate which drives are local and fixed (for which cached
1381 data never expires). */
1382 static BOOL fixed_drives
[26];
1384 /* Consider cached volume information to be stale if older than 10s,
1385 at least for non-local drives. Info for fixed drives is never stale. */
1386 #define DRIVE_INDEX( c ) ( (c) <= 'Z' ? (c) - 'A' : (c) - 'a' )
1387 #define VOLINFO_STILL_VALID( root_dir, info ) \
1388 ( ( isalpha (root_dir[0]) && \
1389 fixed_drives[ DRIVE_INDEX (root_dir[0]) ] ) \
1390 || GetTickCount () - info->timestamp < 10000 )
1392 /* Cache support functions. */
1394 /* Simple linked list with linear search is sufficient. */
1395 static volume_info_data
*volume_cache
= NULL
;
1397 static volume_info_data
*
1398 lookup_volume_info (char * root_dir
)
1400 volume_info_data
* info
;
1402 for (info
= volume_cache
; info
; info
= info
->next
)
1403 if (stricmp (info
->root_dir
, root_dir
) == 0)
1409 add_volume_info (char * root_dir
, volume_info_data
* info
)
1411 info
->root_dir
= xstrdup (root_dir
);
1412 info
->next
= volume_cache
;
1413 volume_cache
= info
;
1417 /* Wrapper for GetVolumeInformation, which uses caching to avoid
1418 performance penalty (~2ms on 486 for local drives, 7.5ms for local
1419 cdrom drive, ~5-10ms or more for remote drives on LAN). */
1421 GetCachedVolumeInformation (char * root_dir
)
1423 volume_info_data
* info
;
1424 char default_root
[ MAX_PATH
];
1426 /* NULL for root_dir means use root from current directory. */
1427 if (root_dir
== NULL
)
1429 if (GetCurrentDirectory (MAX_PATH
, default_root
) == 0)
1431 parse_root (default_root
, &root_dir
);
1433 root_dir
= default_root
;
1436 /* Local fixed drives can be cached permanently. Removable drives
1437 cannot be cached permanently, since the volume name and serial
1438 number (if nothing else) can change. Remote drives should be
1439 treated as if they are removable, since there is no sure way to
1440 tell whether they are or not. Also, the UNC association of drive
1441 letters mapped to remote volumes can be changed at any time (even
1442 by other processes) without notice.
1444 As a compromise, so we can benefit from caching info for remote
1445 volumes, we use a simple expiry mechanism to invalidate cache
1446 entries that are more than ten seconds old. */
1449 /* No point doing this, because WNetGetConnection is even slower than
1450 GetVolumeInformation, consistently taking ~50ms on a 486 (FWIW,
1451 GetDriveType is about the only call of this type which does not
1452 involve network access, and so is extremely quick). */
1454 /* Map drive letter to UNC if remote. */
1455 if ( isalpha( root_dir
[0] ) && !fixed
[ DRIVE_INDEX( root_dir
[0] ) ] )
1457 char remote_name
[ 256 ];
1458 char drive
[3] = { root_dir
[0], ':' };
1460 if (WNetGetConnection (drive
, remote_name
, sizeof (remote_name
))
1462 /* do something */ ;
1466 info
= lookup_volume_info (root_dir
);
1468 if (info
== NULL
|| ! VOLINFO_STILL_VALID (root_dir
, info
))
1476 /* Info is not cached, or is stale. */
1477 if (!GetVolumeInformation (root_dir
,
1478 name
, sizeof (name
),
1482 type
, sizeof (type
)))
1485 /* Cache the volume information for future use, overwriting existing
1486 entry if present. */
1489 info
= (volume_info_data
*) xmalloc (sizeof (volume_info_data
));
1490 add_volume_info (root_dir
, info
);
1498 info
->name
= xstrdup (name
);
1499 info
->serialnum
= serialnum
;
1500 info
->maxcomp
= maxcomp
;
1501 info
->flags
= flags
;
1502 info
->type
= xstrdup (type
);
1503 info
->timestamp
= GetTickCount ();
1509 /* Get information on the volume where name is held; set path pointer to
1510 start of pathname in name (past UNC header\volume header if present). */
1512 get_volume_info (const char * name
, const char ** pPath
)
1514 char temp
[MAX_PATH
];
1515 char *rootname
= NULL
; /* default to current volume */
1516 volume_info_data
* info
;
1521 /* find the root name of the volume if given */
1522 if (isalpha (name
[0]) && name
[1] == ':')
1530 else if (IS_DIRECTORY_SEP (name
[0]) && IS_DIRECTORY_SEP (name
[1]))
1537 if (IS_DIRECTORY_SEP (*name
) && --slashes
== 0)
1550 info
= GetCachedVolumeInformation (rootname
);
1553 /* Set global referenced by other functions. */
1554 volume_info
= *info
;
1560 /* Determine if volume is FAT format (ie. only supports short 8.3
1561 names); also set path pointer to start of pathname in name. */
1563 is_fat_volume (const char * name
, const char ** pPath
)
1565 if (get_volume_info (name
, pPath
))
1566 return (volume_info
.maxcomp
== 12);
1570 /* Map filename to a legal 8.3 name if necessary. */
1572 map_w32_filename (const char * name
, const char ** pPath
)
1574 static char shortname
[MAX_PATH
];
1575 char * str
= shortname
;
1578 const char * save_name
= name
;
1580 if (strlen (name
) >= MAX_PATH
)
1582 /* Return a filename which will cause callers to fail. */
1583 strcpy (shortname
, "?");
1587 if (is_fat_volume (name
, (const char **)&path
)) /* truncate to 8.3 */
1589 register int left
= 8; /* maximum number of chars in part */
1590 register int extn
= 0; /* extension added? */
1591 register int dots
= 2; /* maximum number of dots allowed */
1594 *str
++ = *name
++; /* skip past UNC header */
1596 while ((c
= *name
++))
1603 extn
= 0; /* reset extension flags */
1604 dots
= 2; /* max 2 dots */
1605 left
= 8; /* max length 8 for main part */
1609 extn
= 0; /* reset extension flags */
1610 dots
= 2; /* max 2 dots */
1611 left
= 8; /* max length 8 for main part */
1616 /* Convert path components of the form .xxx to _xxx,
1617 but leave . and .. as they are. This allows .emacs
1618 to be read as _emacs, for example. */
1622 IS_DIRECTORY_SEP (*name
))
1637 extn
= 1; /* we've got an extension */
1638 left
= 3; /* 3 chars in extension */
1642 /* any embedded dots after the first are converted to _ */
1647 case '#': /* don't lose these, they're important */
1649 str
[-1] = c
; /* replace last character of part */
1654 *str
++ = tolower (c
); /* map to lower case (looks nicer) */
1656 dots
= 0; /* started a path component */
1665 strcpy (shortname
, name
);
1666 unixtodos_filename (shortname
);
1670 *pPath
= shortname
+ (path
- save_name
);
1676 is_exec (const char * name
)
1678 char * p
= strrchr (name
, '.');
1681 && (stricmp (p
, ".exe") == 0 ||
1682 stricmp (p
, ".com") == 0 ||
1683 stricmp (p
, ".bat") == 0 ||
1684 stricmp (p
, ".cmd") == 0));
1687 /* Emulate the Unix directory procedures opendir, closedir,
1688 and readdir. We can't use the procedures supplied in sysdep.c,
1689 so we provide them here. */
1691 struct direct dir_static
; /* simulated directory contents */
1692 static HANDLE dir_find_handle
= INVALID_HANDLE_VALUE
;
1693 static int dir_is_fat
;
1694 static char dir_pathname
[MAXPATHLEN
+1];
1695 static WIN32_FIND_DATA dir_find_data
;
1697 /* Support shares on a network resource as subdirectories of a read-only
1699 static HANDLE wnet_enum_handle
= INVALID_HANDLE_VALUE
;
1700 HANDLE
open_unc_volume (const char *);
1701 char *read_unc_volume (HANDLE
, char *, int);
1702 void close_unc_volume (HANDLE
);
1705 opendir (char *filename
)
1709 /* Opening is done by FindFirstFile. However, a read is inherent to
1710 this operation, so we defer the open until read time. */
1712 if (dir_find_handle
!= INVALID_HANDLE_VALUE
)
1714 if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
1717 if (is_unc_volume (filename
))
1719 wnet_enum_handle
= open_unc_volume (filename
);
1720 if (wnet_enum_handle
== INVALID_HANDLE_VALUE
)
1724 if (!(dirp
= (DIR *) malloc (sizeof (DIR))))
1731 strncpy (dir_pathname
, map_w32_filename (filename
, NULL
), MAXPATHLEN
);
1732 dir_pathname
[MAXPATHLEN
] = '\0';
1733 dir_is_fat
= is_fat_volume (filename
, NULL
);
1739 closedir (DIR *dirp
)
1741 /* If we have a find-handle open, close it. */
1742 if (dir_find_handle
!= INVALID_HANDLE_VALUE
)
1744 FindClose (dir_find_handle
);
1745 dir_find_handle
= INVALID_HANDLE_VALUE
;
1747 else if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
1749 close_unc_volume (wnet_enum_handle
);
1750 wnet_enum_handle
= INVALID_HANDLE_VALUE
;
1752 xfree ((char *) dirp
);
1758 if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
1760 if (!read_unc_volume (wnet_enum_handle
,
1761 dir_find_data
.cFileName
,
1765 /* If we aren't dir_finding, do a find-first, otherwise do a find-next. */
1766 else if (dir_find_handle
== INVALID_HANDLE_VALUE
)
1768 char filename
[MAXNAMLEN
+ 3];
1771 strcpy (filename
, dir_pathname
);
1772 ln
= strlen (filename
) - 1;
1773 if (!IS_DIRECTORY_SEP (filename
[ln
]))
1774 strcat (filename
, "\\");
1775 strcat (filename
, "*");
1777 dir_find_handle
= FindFirstFile (filename
, &dir_find_data
);
1779 if (dir_find_handle
== INVALID_HANDLE_VALUE
)
1784 if (!FindNextFile (dir_find_handle
, &dir_find_data
))
1788 /* Emacs never uses this value, so don't bother making it match
1789 value returned by stat(). */
1790 dir_static
.d_ino
= 1;
1792 dir_static
.d_reclen
= sizeof (struct direct
) - MAXNAMLEN
+ 3 +
1793 dir_static
.d_namlen
- dir_static
.d_namlen
% 4;
1795 dir_static
.d_namlen
= strlen (dir_find_data
.cFileName
);
1796 strcpy (dir_static
.d_name
, dir_find_data
.cFileName
);
1798 _strlwr (dir_static
.d_name
);
1799 else if (!NILP (Vw32_downcase_file_names
))
1802 for (p
= dir_static
.d_name
; *p
; p
++)
1803 if (*p
>= 'a' && *p
<= 'z')
1806 _strlwr (dir_static
.d_name
);
1813 open_unc_volume (const char *path
)
1819 nr
.dwScope
= RESOURCE_GLOBALNET
;
1820 nr
.dwType
= RESOURCETYPE_DISK
;
1821 nr
.dwDisplayType
= RESOURCEDISPLAYTYPE_SERVER
;
1822 nr
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
1823 nr
.lpLocalName
= NULL
;
1824 nr
.lpRemoteName
= (LPSTR
)map_w32_filename (path
, NULL
);
1825 nr
.lpComment
= NULL
;
1826 nr
.lpProvider
= NULL
;
1828 result
= WNetOpenEnum(RESOURCE_GLOBALNET
, RESOURCETYPE_DISK
,
1829 RESOURCEUSAGE_CONNECTABLE
, &nr
, &henum
);
1831 if (result
== NO_ERROR
)
1834 return INVALID_HANDLE_VALUE
;
1838 read_unc_volume (HANDLE henum
, char *readbuf
, int size
)
1842 DWORD bufsize
= 512;
1847 buffer
= alloca (bufsize
);
1848 result
= WNetEnumResource (wnet_enum_handle
, &count
, buffer
, &bufsize
);
1849 if (result
!= NO_ERROR
)
1852 /* WNetEnumResource returns \\resource\share...skip forward to "share". */
1853 ptr
= ((LPNETRESOURCE
) buffer
)->lpRemoteName
;
1855 while (*ptr
&& !IS_DIRECTORY_SEP (*ptr
)) ptr
++;
1858 strncpy (readbuf
, ptr
, size
);
1863 close_unc_volume (HANDLE henum
)
1865 if (henum
!= INVALID_HANDLE_VALUE
)
1866 WNetCloseEnum (henum
);
1870 unc_volume_file_attributes (const char *path
)
1875 henum
= open_unc_volume (path
);
1876 if (henum
== INVALID_HANDLE_VALUE
)
1879 attrs
= FILE_ATTRIBUTE_READONLY
| FILE_ATTRIBUTE_DIRECTORY
;
1881 close_unc_volume (henum
);
1887 /* Shadow some MSVC runtime functions to map requests for long filenames
1888 to reasonable short names if necessary. This was originally added to
1889 permit running Emacs on NT 3.1 on a FAT partition, which doesn't support
1893 sys_access (const char * path
, int mode
)
1897 /* MSVC implementation doesn't recognize D_OK. */
1898 path
= map_w32_filename (path
, NULL
);
1899 if (is_unc_volume (path
))
1901 attributes
= unc_volume_file_attributes (path
);
1902 if (attributes
== -1) {
1907 else if ((attributes
= GetFileAttributes (path
)) == -1)
1909 /* Should try mapping GetLastError to errno; for now just indicate
1910 that path doesn't exist. */
1914 if ((mode
& X_OK
) != 0 && !is_exec (path
))
1919 if ((mode
& W_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_READONLY
) != 0)
1924 if ((mode
& D_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
) == 0)
1933 sys_chdir (const char * path
)
1935 return _chdir (map_w32_filename (path
, NULL
));
1939 sys_chmod (const char * path
, int mode
)
1941 return _chmod (map_w32_filename (path
, NULL
), mode
);
1945 sys_chown (const char *path
, uid_t owner
, gid_t group
)
1947 if (sys_chmod (path
, _S_IREAD
) == -1) /* check if file exists */
1953 sys_creat (const char * path
, int mode
)
1955 return _creat (map_w32_filename (path
, NULL
), mode
);
1959 sys_fopen(const char * path
, const char * mode
)
1963 const char * mode_save
= mode
;
1965 /* Force all file handles to be non-inheritable. This is necessary to
1966 ensure child processes don't unwittingly inherit handles that might
1967 prevent future file access. */
1971 else if (mode
[0] == 'w' || mode
[0] == 'a')
1972 oflag
= O_WRONLY
| O_CREAT
| O_TRUNC
;
1976 /* Only do simplistic option parsing. */
1980 oflag
&= ~(O_RDONLY
| O_WRONLY
);
1983 else if (mode
[0] == 'b')
1988 else if (mode
[0] == 't')
1995 fd
= _open (map_w32_filename (path
, NULL
), oflag
| _O_NOINHERIT
, 0644);
1999 return _fdopen (fd
, mode_save
);
2002 /* This only works on NTFS volumes, but is useful to have. */
2004 sys_link (const char * old
, const char * new)
2008 char oldname
[MAX_PATH
], newname
[MAX_PATH
];
2010 if (old
== NULL
|| new == NULL
)
2016 strcpy (oldname
, map_w32_filename (old
, NULL
));
2017 strcpy (newname
, map_w32_filename (new, NULL
));
2019 fileh
= CreateFile (oldname
, 0, 0, NULL
, OPEN_EXISTING
,
2020 FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
2021 if (fileh
!= INVALID_HANDLE_VALUE
)
2025 /* Confusingly, the "alternate" stream name field does not apply
2026 when restoring a hard link, and instead contains the actual
2027 stream data for the link (ie. the name of the link to create).
2028 The WIN32_STREAM_ID structure before the cStreamName field is
2029 the stream header, which is then immediately followed by the
2033 WIN32_STREAM_ID wid
;
2034 WCHAR wbuffer
[MAX_PATH
]; /* extra space for link name */
2037 wlen
= MultiByteToWideChar (CP_ACP
, MB_PRECOMPOSED
, newname
, -1,
2038 data
.wid
.cStreamName
, MAX_PATH
);
2041 LPVOID context
= NULL
;
2044 data
.wid
.dwStreamId
= BACKUP_LINK
;
2045 data
.wid
.dwStreamAttributes
= 0;
2046 data
.wid
.Size
.LowPart
= wlen
* sizeof(WCHAR
);
2047 data
.wid
.Size
.HighPart
= 0;
2048 data
.wid
.dwStreamNameSize
= 0;
2050 if (BackupWrite (fileh
, (LPBYTE
)&data
,
2051 offsetof (WIN32_STREAM_ID
, cStreamName
)
2052 + data
.wid
.Size
.LowPart
,
2053 &wbytes
, FALSE
, FALSE
, &context
)
2054 && BackupWrite (fileh
, NULL
, 0, &wbytes
, TRUE
, FALSE
, &context
))
2061 /* Should try mapping GetLastError to errno; for now just
2062 indicate a general error (eg. links not supported). */
2063 errno
= EINVAL
; // perhaps EMLINK?
2067 CloseHandle (fileh
);
2076 sys_mkdir (const char * path
)
2078 return _mkdir (map_w32_filename (path
, NULL
));
2081 /* Because of long name mapping issues, we need to implement this
2082 ourselves. Also, MSVC's _mktemp returns NULL when it can't generate
2083 a unique name, instead of setting the input template to an empty
2086 Standard algorithm seems to be use pid or tid with a letter on the
2087 front (in place of the 6 X's) and cycle through the letters to find a
2088 unique name. We extend that to allow any reasonable character as the
2089 first of the 6 X's. */
2091 sys_mktemp (char * template)
2095 unsigned uid
= GetCurrentThreadId ();
2096 static char first_char
[] = "abcdefghijklmnopqrstuvwyz0123456789!%-_@#";
2098 if (template == NULL
)
2100 p
= template + strlen (template);
2102 /* replace up to the last 5 X's with uid in decimal */
2103 while (--p
>= template && p
[0] == 'X' && --i
>= 0)
2105 p
[0] = '0' + uid
% 10;
2109 if (i
< 0 && p
[0] == 'X')
2114 int save_errno
= errno
;
2115 p
[0] = first_char
[i
];
2116 if (sys_access (template, 0) < 0)
2122 while (++i
< sizeof (first_char
));
2125 /* Template is badly formed or else we can't generate a unique name,
2126 so return empty string */
2132 sys_open (const char * path
, int oflag
, int mode
)
2134 const char* mpath
= map_w32_filename (path
, NULL
);
2135 /* Try to open file without _O_CREAT, to be able to write to hidden
2136 and system files. Force all file handles to be
2138 int res
= _open (mpath
, (oflag
& ~_O_CREAT
) | _O_NOINHERIT
, mode
);
2141 return _open (mpath
, oflag
| _O_NOINHERIT
, mode
);
2145 sys_rename (const char * oldname
, const char * newname
)
2148 char temp
[MAX_PATH
];
2150 /* MoveFile on Windows 95 doesn't correctly change the short file name
2151 alias in a number of circumstances (it is not easy to predict when
2152 just by looking at oldname and newname, unfortunately). In these
2153 cases, renaming through a temporary name avoids the problem.
2155 A second problem on Windows 95 is that renaming through a temp name when
2156 newname is uppercase fails (the final long name ends up in
2157 lowercase, although the short alias might be uppercase) UNLESS the
2158 long temp name is not 8.3.
2160 So, on Windows 95 we always rename through a temp name, and we make sure
2161 the temp name has a long extension to ensure correct renaming. */
2163 strcpy (temp
, map_w32_filename (oldname
, NULL
));
2165 if (os_subtype
== OS_WIN95
)
2171 oldname
= map_w32_filename (oldname
, NULL
);
2172 if (o
= strrchr (oldname
, '\\'))
2175 o
= (char *) oldname
;
2177 if (p
= strrchr (temp
, '\\'))
2184 /* Force temp name to require a manufactured 8.3 alias - this
2185 seems to make the second rename work properly. */
2186 sprintf (p
, "_.%s.%u", o
, i
);
2188 result
= rename (oldname
, temp
);
2190 /* This loop must surely terminate! */
2191 while (result
< 0 && errno
== EEXIST
);
2196 /* Emulate Unix behaviour - newname is deleted if it already exists
2197 (at least if it is a file; don't do this for directories).
2199 Since we mustn't do this if we are just changing the case of the
2200 file name (we would end up deleting the file we are trying to
2201 rename!), we let rename detect if the destination file already
2202 exists - that way we avoid the possible pitfalls of trying to
2203 determine ourselves whether two names really refer to the same
2204 file, which is not always possible in the general case. (Consider
2205 all the permutations of shared or subst'd drives, etc.) */
2207 newname
= map_w32_filename (newname
, NULL
);
2208 result
= rename (temp
, newname
);
2212 && _chmod (newname
, 0666) == 0
2213 && _unlink (newname
) == 0)
2214 result
= rename (temp
, newname
);
2220 sys_rmdir (const char * path
)
2222 return _rmdir (map_w32_filename (path
, NULL
));
2226 sys_unlink (const char * path
)
2228 path
= map_w32_filename (path
, NULL
);
2230 /* On Unix, unlink works without write permission. */
2231 _chmod (path
, 0666);
2232 return _unlink (path
);
2235 static FILETIME utc_base_ft
;
2236 static long double utc_base
;
2237 static int init
= 0;
2240 convert_time (FILETIME ft
)
2246 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
2255 st
.wMilliseconds
= 0;
2257 SystemTimeToFileTime (&st
, &utc_base_ft
);
2258 utc_base
= (long double) utc_base_ft
.dwHighDateTime
2259 * 4096.0L * 1024.0L * 1024.0L + utc_base_ft
.dwLowDateTime
;
2263 if (CompareFileTime (&ft
, &utc_base_ft
) < 0)
2266 ret
= (long double) ft
.dwHighDateTime
2267 * 4096.0L * 1024.0L * 1024.0L + ft
.dwLowDateTime
;
2269 return (time_t) (ret
* 1e-7L);
2273 convert_from_time_t (time_t time
, FILETIME
* pft
)
2279 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
2288 st
.wMilliseconds
= 0;
2290 SystemTimeToFileTime (&st
, &utc_base_ft
);
2291 utc_base
= (long double) utc_base_ft
.dwHighDateTime
2292 * 4096 * 1024 * 1024 + utc_base_ft
.dwLowDateTime
;
2296 /* time in 100ns units since 1-Jan-1601 */
2297 tmp
= (long double) time
* 1e7
+ utc_base
;
2298 pft
->dwHighDateTime
= (DWORD
) (tmp
/ (4096.0 * 1024 * 1024));
2299 pft
->dwLowDateTime
= (DWORD
) (tmp
- (4096.0 * 1024 * 1024) * pft
->dwHighDateTime
);
2303 /* No reason to keep this; faking inode values either by hashing or even
2304 using the file index from GetInformationByHandle, is not perfect and
2305 so by default Emacs doesn't use the inode values on Windows.
2306 Instead, we now determine file-truename correctly (except for
2307 possible drive aliasing etc). */
2309 /* Modified version of "PJW" algorithm (see the "Dragon" compiler book). */
2311 hashval (const unsigned char * str
)
2316 h
= (h
<< 4) + *str
++;
2322 /* Return the hash value of the canonical pathname, excluding the
2323 drive/UNC header, to get a hopefully unique inode number. */
2325 generate_inode_val (const char * name
)
2327 char fullname
[ MAX_PATH
];
2331 /* Get the truly canonical filename, if it exists. (Note: this
2332 doesn't resolve aliasing due to subst commands, or recognise hard
2334 if (!w32_get_long_filename ((char *)name
, fullname
, MAX_PATH
))
2337 parse_root (fullname
, &p
);
2338 /* Normal W32 filesystems are still case insensitive. */
2345 /* MSVC stat function can't cope with UNC names and has other bugs, so
2346 replace it with our own. This also allows us to calculate consistent
2347 inode values without hacks in the main Emacs code. */
2349 stat (const char * path
, struct stat
* buf
)
2352 WIN32_FIND_DATA wfd
;
2357 int rootdir
= FALSE
;
2359 if (path
== NULL
|| buf
== NULL
)
2365 name
= (char *) map_w32_filename (path
, &path
);
2366 /* must be valid filename, no wild cards or other invalid characters */
2367 if (strpbrk (name
, "*?|<>\""))
2373 /* If name is "c:/.." or "/.." then stat "c:/" or "/". */
2374 r
= IS_DEVICE_SEP (name
[1]) ? &name
[2] : name
;
2375 if (IS_DIRECTORY_SEP (r
[0]) && r
[1] == '.' && r
[2] == '.' && r
[3] == '\0')
2380 /* Remove trailing directory separator, unless name is the root
2381 directory of a drive or UNC volume in which case ensure there
2382 is a trailing separator. */
2383 len
= strlen (name
);
2384 rootdir
= (path
>= name
+ len
- 1
2385 && (IS_DIRECTORY_SEP (*path
) || *path
== 0));
2386 name
= strcpy (alloca (len
+ 2), name
);
2388 if (is_unc_volume (name
))
2390 DWORD attrs
= unc_volume_file_attributes (name
);
2395 memset (&wfd
, 0, sizeof (wfd
));
2396 wfd
.dwFileAttributes
= attrs
;
2397 wfd
.ftCreationTime
= utc_base_ft
;
2398 wfd
.ftLastAccessTime
= utc_base_ft
;
2399 wfd
.ftLastWriteTime
= utc_base_ft
;
2400 strcpy (wfd
.cFileName
, name
);
2404 if (!IS_DIRECTORY_SEP (name
[len
-1]))
2405 strcat (name
, "\\");
2406 if (GetDriveType (name
) < 2)
2411 memset (&wfd
, 0, sizeof (wfd
));
2412 wfd
.dwFileAttributes
= FILE_ATTRIBUTE_DIRECTORY
;
2413 wfd
.ftCreationTime
= utc_base_ft
;
2414 wfd
.ftLastAccessTime
= utc_base_ft
;
2415 wfd
.ftLastWriteTime
= utc_base_ft
;
2416 strcpy (wfd
.cFileName
, name
);
2420 if (IS_DIRECTORY_SEP (name
[len
-1]))
2423 /* (This is hacky, but helps when doing file completions on
2424 network drives.) Optimize by using information available from
2425 active readdir if possible. */
2426 len
= strlen (dir_pathname
);
2427 if (IS_DIRECTORY_SEP (dir_pathname
[len
-1]))
2429 if (dir_find_handle
!= INVALID_HANDLE_VALUE
2430 && strnicmp (name
, dir_pathname
, len
) == 0
2431 && IS_DIRECTORY_SEP (name
[len
])
2432 && stricmp (name
+ len
+ 1, dir_static
.d_name
) == 0)
2434 /* This was the last entry returned by readdir. */
2435 wfd
= dir_find_data
;
2439 fh
= FindFirstFile (name
, &wfd
);
2440 if (fh
== INVALID_HANDLE_VALUE
)
2449 if (!NILP (Vw32_get_true_file_attributes
)
2450 /* No access rights required to get info. */
2451 && (fh
= CreateFile (name
, 0, 0, NULL
, OPEN_EXISTING
,
2452 FILE_FLAG_BACKUP_SEMANTICS
, NULL
))
2453 != INVALID_HANDLE_VALUE
)
2455 /* This is more accurate in terms of gettting the correct number
2456 of links, but is quite slow (it is noticable when Emacs is
2457 making a list of file name completions). */
2458 BY_HANDLE_FILE_INFORMATION info
;
2460 if (GetFileInformationByHandle (fh
, &info
))
2462 buf
->st_nlink
= info
.nNumberOfLinks
;
2463 /* Might as well use file index to fake inode values, but this
2464 is not guaranteed to be unique unless we keep a handle open
2465 all the time (even then there are situations where it is
2466 not unique). Reputedly, there are at most 48 bits of info
2467 (on NTFS, presumably less on FAT). */
2468 fake_inode
= info
.nFileIndexLow
^ info
.nFileIndexHigh
;
2476 if (wfd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
2478 buf
->st_mode
= _S_IFDIR
;
2482 switch (GetFileType (fh
))
2484 case FILE_TYPE_DISK
:
2485 buf
->st_mode
= _S_IFREG
;
2487 case FILE_TYPE_PIPE
:
2488 buf
->st_mode
= _S_IFIFO
;
2490 case FILE_TYPE_CHAR
:
2491 case FILE_TYPE_UNKNOWN
:
2493 buf
->st_mode
= _S_IFCHR
;
2500 /* Don't bother to make this information more accurate. */
2501 buf
->st_mode
= (wfd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) ?
2502 _S_IFDIR
: _S_IFREG
;
2508 /* Not sure if there is any point in this. */
2509 if (!NILP (Vw32_generate_fake_inodes
))
2510 fake_inode
= generate_inode_val (name
);
2511 else if (fake_inode
== 0)
2513 /* For want of something better, try to make everything unique. */
2514 static DWORD gen_num
= 0;
2515 fake_inode
= ++gen_num
;
2519 /* MSVC defines _ino_t to be short; other libc's might not. */
2520 if (sizeof (buf
->st_ino
) == 2)
2521 buf
->st_ino
= fake_inode
^ (fake_inode
>> 16);
2523 buf
->st_ino
= fake_inode
;
2525 /* consider files to belong to current user */
2526 buf
->st_uid
= the_passwd
.pw_uid
;
2527 buf
->st_gid
= the_passwd
.pw_gid
;
2529 /* volume_info is set indirectly by map_w32_filename */
2530 buf
->st_dev
= volume_info
.serialnum
;
2531 buf
->st_rdev
= volume_info
.serialnum
;
2534 buf
->st_size
= wfd
.nFileSizeLow
;
2536 /* Convert timestamps to Unix format. */
2537 buf
->st_mtime
= convert_time (wfd
.ftLastWriteTime
);
2538 buf
->st_atime
= convert_time (wfd
.ftLastAccessTime
);
2539 if (buf
->st_atime
== 0) buf
->st_atime
= buf
->st_mtime
;
2540 buf
->st_ctime
= convert_time (wfd
.ftCreationTime
);
2541 if (buf
->st_ctime
== 0) buf
->st_ctime
= buf
->st_mtime
;
2543 /* determine rwx permissions */
2544 if (wfd
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
)
2545 permission
= _S_IREAD
;
2547 permission
= _S_IREAD
| _S_IWRITE
;
2549 if (wfd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
2550 permission
|= _S_IEXEC
;
2551 else if (is_exec (name
))
2552 permission
|= _S_IEXEC
;
2554 buf
->st_mode
|= permission
| (permission
>> 3) | (permission
>> 6);
2559 /* Provide fstat and utime as well as stat for consistent handling of
2562 fstat (int desc
, struct stat
* buf
)
2564 HANDLE fh
= (HANDLE
) _get_osfhandle (desc
);
2565 BY_HANDLE_FILE_INFORMATION info
;
2569 switch (GetFileType (fh
) & ~FILE_TYPE_REMOTE
)
2571 case FILE_TYPE_DISK
:
2572 buf
->st_mode
= _S_IFREG
;
2573 if (!GetFileInformationByHandle (fh
, &info
))
2579 case FILE_TYPE_PIPE
:
2580 buf
->st_mode
= _S_IFIFO
;
2582 case FILE_TYPE_CHAR
:
2583 case FILE_TYPE_UNKNOWN
:
2585 buf
->st_mode
= _S_IFCHR
;
2587 memset (&info
, 0, sizeof (info
));
2588 info
.dwFileAttributes
= 0;
2589 info
.ftCreationTime
= utc_base_ft
;
2590 info
.ftLastAccessTime
= utc_base_ft
;
2591 info
.ftLastWriteTime
= utc_base_ft
;
2594 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
2595 buf
->st_mode
= _S_IFDIR
;
2597 buf
->st_nlink
= info
.nNumberOfLinks
;
2598 /* Might as well use file index to fake inode values, but this
2599 is not guaranteed to be unique unless we keep a handle open
2600 all the time (even then there are situations where it is
2601 not unique). Reputedly, there are at most 48 bits of info
2602 (on NTFS, presumably less on FAT). */
2603 fake_inode
= info
.nFileIndexLow
^ info
.nFileIndexHigh
;
2605 /* MSVC defines _ino_t to be short; other libc's might not. */
2606 if (sizeof (buf
->st_ino
) == 2)
2607 buf
->st_ino
= fake_inode
^ (fake_inode
>> 16);
2609 buf
->st_ino
= fake_inode
;
2611 /* consider files to belong to current user */
2615 buf
->st_dev
= info
.dwVolumeSerialNumber
;
2616 buf
->st_rdev
= info
.dwVolumeSerialNumber
;
2618 buf
->st_size
= info
.nFileSizeLow
;
2620 /* Convert timestamps to Unix format. */
2621 buf
->st_mtime
= convert_time (info
.ftLastWriteTime
);
2622 buf
->st_atime
= convert_time (info
.ftLastAccessTime
);
2623 if (buf
->st_atime
== 0) buf
->st_atime
= buf
->st_mtime
;
2624 buf
->st_ctime
= convert_time (info
.ftCreationTime
);
2625 if (buf
->st_ctime
== 0) buf
->st_ctime
= buf
->st_mtime
;
2627 /* determine rwx permissions */
2628 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
)
2629 permission
= _S_IREAD
;
2631 permission
= _S_IREAD
| _S_IWRITE
;
2633 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
2634 permission
|= _S_IEXEC
;
2637 #if 0 /* no way of knowing the filename */
2638 char * p
= strrchr (name
, '.');
2640 (stricmp (p
, ".exe") == 0 ||
2641 stricmp (p
, ".com") == 0 ||
2642 stricmp (p
, ".bat") == 0 ||
2643 stricmp (p
, ".cmd") == 0))
2644 permission
|= _S_IEXEC
;
2648 buf
->st_mode
|= permission
| (permission
>> 3) | (permission
>> 6);
2654 utime (const char *name
, struct utimbuf
*times
)
2656 struct utimbuf deftime
;
2663 deftime
.modtime
= deftime
.actime
= time (NULL
);
2667 /* Need write access to set times. */
2668 fh
= CreateFile (name
, GENERIC_WRITE
, FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2669 0, OPEN_EXISTING
, 0, NULL
);
2672 convert_from_time_t (times
->actime
, &atime
);
2673 convert_from_time_t (times
->modtime
, &mtime
);
2674 if (!SetFileTime (fh
, NULL
, &atime
, &mtime
))
2692 /* Wrappers for winsock functions to map between our file descriptors
2693 and winsock's handles; also set h_errno for convenience.
2695 To allow Emacs to run on systems which don't have winsock support
2696 installed, we dynamically link to winsock on startup if present, and
2697 otherwise provide the minimum necessary functionality
2698 (eg. gethostname). */
2700 /* function pointers for relevant socket functions */
2701 int (PASCAL
*pfn_WSAStartup
) (WORD wVersionRequired
, LPWSADATA lpWSAData
);
2702 void (PASCAL
*pfn_WSASetLastError
) (int iError
);
2703 int (PASCAL
*pfn_WSAGetLastError
) (void);
2704 int (PASCAL
*pfn_WSAEventSelect
) (SOCKET s
, HANDLE hEventObject
, long lNetworkEvents
);
2705 HANDLE (PASCAL
*pfn_WSACreateEvent
) (void);
2706 int (PASCAL
*pfn_WSACloseEvent
) (HANDLE hEvent
);
2707 int (PASCAL
*pfn_socket
) (int af
, int type
, int protocol
);
2708 int (PASCAL
*pfn_bind
) (SOCKET s
, const struct sockaddr
*addr
, int namelen
);
2709 int (PASCAL
*pfn_connect
) (SOCKET s
, const struct sockaddr
*addr
, int namelen
);
2710 int (PASCAL
*pfn_ioctlsocket
) (SOCKET s
, long cmd
, u_long
*argp
);
2711 int (PASCAL
*pfn_recv
) (SOCKET s
, char * buf
, int len
, int flags
);
2712 int (PASCAL
*pfn_send
) (SOCKET s
, const char * buf
, int len
, int flags
);
2713 int (PASCAL
*pfn_closesocket
) (SOCKET s
);
2714 int (PASCAL
*pfn_shutdown
) (SOCKET s
, int how
);
2715 int (PASCAL
*pfn_WSACleanup
) (void);
2717 u_short (PASCAL
*pfn_htons
) (u_short hostshort
);
2718 u_short (PASCAL
*pfn_ntohs
) (u_short netshort
);
2719 unsigned long (PASCAL
*pfn_inet_addr
) (const char * cp
);
2720 int (PASCAL
*pfn_gethostname
) (char * name
, int namelen
);
2721 struct hostent
* (PASCAL
*pfn_gethostbyname
) (const char * name
);
2722 struct servent
* (PASCAL
*pfn_getservbyname
) (const char * name
, const char * proto
);
2723 int (PASCAL
*pfn_getpeername
) (SOCKET s
, struct sockaddr
*addr
, int * namelen
);
2724 int (PASCAL
*pfn_setsockopt
) (SOCKET s
, int level
, int optname
,
2725 const char * optval
, int optlen
);
2726 int (PASCAL
*pfn_listen
) (SOCKET s
, int backlog
);
2727 int (PASCAL
*pfn_getsockname
) (SOCKET s
, struct sockaddr
* name
,
2729 SOCKET (PASCAL
*pfn_accept
) (SOCKET s
, struct sockaddr
* addr
, int * addrlen
);
2730 int (PASCAL
*pfn_recvfrom
) (SOCKET s
, char * buf
, int len
, int flags
,
2731 struct sockaddr
* from
, int * fromlen
);
2732 int (PASCAL
*pfn_sendto
) (SOCKET s
, const char * buf
, int len
, int flags
,
2733 const struct sockaddr
* to
, int tolen
);
2735 /* SetHandleInformation is only needed to make sockets non-inheritable. */
2736 BOOL (WINAPI
*pfn_SetHandleInformation
) (HANDLE object
, DWORD mask
, DWORD flags
);
2737 #ifndef HANDLE_FLAG_INHERIT
2738 #define HANDLE_FLAG_INHERIT 1
2742 static int winsock_inuse
;
2747 if (winsock_lib
!= NULL
&& winsock_inuse
== 0)
2749 /* Not sure what would cause WSAENETDOWN, or even if it can happen
2750 after WSAStartup returns successfully, but it seems reasonable
2751 to allow unloading winsock anyway in that case. */
2752 if (pfn_WSACleanup () == 0 ||
2753 pfn_WSAGetLastError () == WSAENETDOWN
)
2755 if (FreeLibrary (winsock_lib
))
2764 init_winsock (int load_now
)
2766 WSADATA winsockData
;
2768 if (winsock_lib
!= NULL
)
2771 pfn_SetHandleInformation
= NULL
;
2772 pfn_SetHandleInformation
2773 = (void *) GetProcAddress (GetModuleHandle ("kernel32.dll"),
2774 "SetHandleInformation");
2776 winsock_lib
= LoadLibrary ("Ws2_32.dll");
2778 if (winsock_lib
!= NULL
)
2780 /* dynamically link to socket functions */
2782 #define LOAD_PROC(fn) \
2783 if ((pfn_##fn = (void *) GetProcAddress (winsock_lib, #fn)) == NULL) \
2786 LOAD_PROC( WSAStartup
);
2787 LOAD_PROC( WSASetLastError
);
2788 LOAD_PROC( WSAGetLastError
);
2789 LOAD_PROC( WSAEventSelect
);
2790 LOAD_PROC( WSACreateEvent
);
2791 LOAD_PROC( WSACloseEvent
);
2792 LOAD_PROC( socket
);
2794 LOAD_PROC( connect
);
2795 LOAD_PROC( ioctlsocket
);
2798 LOAD_PROC( closesocket
);
2799 LOAD_PROC( shutdown
);
2802 LOAD_PROC( inet_addr
);
2803 LOAD_PROC( gethostname
);
2804 LOAD_PROC( gethostbyname
);
2805 LOAD_PROC( getservbyname
);
2806 LOAD_PROC( getpeername
);
2807 LOAD_PROC( WSACleanup
);
2808 LOAD_PROC( setsockopt
);
2809 LOAD_PROC( listen
);
2810 LOAD_PROC( getsockname
);
2811 LOAD_PROC( accept
);
2812 LOAD_PROC( recvfrom
);
2813 LOAD_PROC( sendto
);
2816 /* specify version 1.1 of winsock */
2817 if (pfn_WSAStartup (0x101, &winsockData
) == 0)
2819 if (winsockData
.wVersion
!= 0x101)
2824 /* Report that winsock exists and is usable, but leave
2825 socket functions disabled. I am assuming that calling
2826 WSAStartup does not require any network interaction,
2827 and in particular does not cause or require a dial-up
2828 connection to be established. */
2831 FreeLibrary (winsock_lib
);
2839 FreeLibrary (winsock_lib
);
2849 /* function to set h_errno for compatability; map winsock error codes to
2850 normal system codes where they overlap (non-overlapping definitions
2851 are already in <sys/socket.h> */
2852 static void set_errno ()
2854 if (winsock_lib
== NULL
)
2857 h_errno
= pfn_WSAGetLastError ();
2861 case WSAEACCES
: h_errno
= EACCES
; break;
2862 case WSAEBADF
: h_errno
= EBADF
; break;
2863 case WSAEFAULT
: h_errno
= EFAULT
; break;
2864 case WSAEINTR
: h_errno
= EINTR
; break;
2865 case WSAEINVAL
: h_errno
= EINVAL
; break;
2866 case WSAEMFILE
: h_errno
= EMFILE
; break;
2867 case WSAENAMETOOLONG
: h_errno
= ENAMETOOLONG
; break;
2868 case WSAENOTEMPTY
: h_errno
= ENOTEMPTY
; break;
2873 static void check_errno ()
2875 if (h_errno
== 0 && winsock_lib
!= NULL
)
2876 pfn_WSASetLastError (0);
2879 /* Extend strerror to handle the winsock-specific error codes. */
2883 } _wsa_errlist
[] = {
2884 WSAEINTR
, "Interrupted function call",
2885 WSAEBADF
, "Bad file descriptor",
2886 WSAEACCES
, "Permission denied",
2887 WSAEFAULT
, "Bad address",
2888 WSAEINVAL
, "Invalid argument",
2889 WSAEMFILE
, "Too many open files",
2891 WSAEWOULDBLOCK
, "Resource temporarily unavailable",
2892 WSAEINPROGRESS
, "Operation now in progress",
2893 WSAEALREADY
, "Operation already in progress",
2894 WSAENOTSOCK
, "Socket operation on non-socket",
2895 WSAEDESTADDRREQ
, "Destination address required",
2896 WSAEMSGSIZE
, "Message too long",
2897 WSAEPROTOTYPE
, "Protocol wrong type for socket",
2898 WSAENOPROTOOPT
, "Bad protocol option",
2899 WSAEPROTONOSUPPORT
, "Protocol not supported",
2900 WSAESOCKTNOSUPPORT
, "Socket type not supported",
2901 WSAEOPNOTSUPP
, "Operation not supported",
2902 WSAEPFNOSUPPORT
, "Protocol family not supported",
2903 WSAEAFNOSUPPORT
, "Address family not supported by protocol family",
2904 WSAEADDRINUSE
, "Address already in use",
2905 WSAEADDRNOTAVAIL
, "Cannot assign requested address",
2906 WSAENETDOWN
, "Network is down",
2907 WSAENETUNREACH
, "Network is unreachable",
2908 WSAENETRESET
, "Network dropped connection on reset",
2909 WSAECONNABORTED
, "Software caused connection abort",
2910 WSAECONNRESET
, "Connection reset by peer",
2911 WSAENOBUFS
, "No buffer space available",
2912 WSAEISCONN
, "Socket is already connected",
2913 WSAENOTCONN
, "Socket is not connected",
2914 WSAESHUTDOWN
, "Cannot send after socket shutdown",
2915 WSAETOOMANYREFS
, "Too many references", /* not sure */
2916 WSAETIMEDOUT
, "Connection timed out",
2917 WSAECONNREFUSED
, "Connection refused",
2918 WSAELOOP
, "Network loop", /* not sure */
2919 WSAENAMETOOLONG
, "Name is too long",
2920 WSAEHOSTDOWN
, "Host is down",
2921 WSAEHOSTUNREACH
, "No route to host",
2922 WSAENOTEMPTY
, "Buffer not empty", /* not sure */
2923 WSAEPROCLIM
, "Too many processes",
2924 WSAEUSERS
, "Too many users", /* not sure */
2925 WSAEDQUOT
, "Double quote in host name", /* really not sure */
2926 WSAESTALE
, "Data is stale", /* not sure */
2927 WSAEREMOTE
, "Remote error", /* not sure */
2929 WSASYSNOTREADY
, "Network subsystem is unavailable",
2930 WSAVERNOTSUPPORTED
, "WINSOCK.DLL version out of range",
2931 WSANOTINITIALISED
, "Winsock not initialized successfully",
2932 WSAEDISCON
, "Graceful shutdown in progress",
2934 WSAENOMORE
, "No more operations allowed", /* not sure */
2935 WSAECANCELLED
, "Operation cancelled", /* not sure */
2936 WSAEINVALIDPROCTABLE
, "Invalid procedure table from service provider",
2937 WSAEINVALIDPROVIDER
, "Invalid service provider version number",
2938 WSAEPROVIDERFAILEDINIT
, "Unable to initialize a service provider",
2939 WSASYSCALLFAILURE
, "System call failured",
2940 WSASERVICE_NOT_FOUND
, "Service not found", /* not sure */
2941 WSATYPE_NOT_FOUND
, "Class type not found",
2942 WSA_E_NO_MORE
, "No more resources available", /* really not sure */
2943 WSA_E_CANCELLED
, "Operation already cancelled", /* really not sure */
2944 WSAEREFUSED
, "Operation refused", /* not sure */
2947 WSAHOST_NOT_FOUND
, "Host not found",
2948 WSATRY_AGAIN
, "Authoritative host not found during name lookup",
2949 WSANO_RECOVERY
, "Non-recoverable error during name lookup",
2950 WSANO_DATA
, "Valid name, no data record of requested type",
2956 sys_strerror(int error_no
)
2959 static char unknown_msg
[40];
2961 if (error_no
>= 0 && error_no
< sys_nerr
)
2962 return sys_errlist
[error_no
];
2964 for (i
= 0; _wsa_errlist
[i
].errnum
>= 0; i
++)
2965 if (_wsa_errlist
[i
].errnum
== error_no
)
2966 return _wsa_errlist
[i
].msg
;
2968 sprintf(unknown_msg
, "Unidentified error: %d", error_no
);
2972 /* [andrewi 3-May-96] I've had conflicting results using both methods,
2973 but I believe the method of keeping the socket handle separate (and
2974 insuring it is not inheritable) is the correct one. */
2976 //#define SOCK_REPLACE_HANDLE
2978 #ifdef SOCK_REPLACE_HANDLE
2979 #define SOCK_HANDLE(fd) ((SOCKET) _get_osfhandle (fd))
2981 #define SOCK_HANDLE(fd) ((SOCKET) fd_info[fd].hnd)
2984 int socket_to_fd (SOCKET s
);
2987 sys_socket(int af
, int type
, int protocol
)
2991 if (winsock_lib
== NULL
)
2994 return INVALID_SOCKET
;
2999 /* call the real socket function */
3000 s
= pfn_socket (af
, type
, protocol
);
3002 if (s
!= INVALID_SOCKET
)
3003 return socket_to_fd (s
);
3009 /* Convert a SOCKET to a file descriptor. */
3011 socket_to_fd (SOCKET s
)
3016 /* Although under NT 3.5 _open_osfhandle will accept a socket
3017 handle, if opened with SO_OPENTYPE == SO_SYNCHRONOUS_NONALERT,
3018 that does not work under NT 3.1. However, we can get the same
3019 effect by using a backdoor function to replace an existing
3020 descriptor handle with the one we want. */
3022 /* allocate a file descriptor (with appropriate flags) */
3023 fd
= _open ("NUL:", _O_RDWR
);
3026 #ifdef SOCK_REPLACE_HANDLE
3027 /* now replace handle to NUL with our socket handle */
3028 CloseHandle ((HANDLE
) _get_osfhandle (fd
));
3030 _set_osfhnd (fd
, s
);
3031 /* setmode (fd, _O_BINARY); */
3033 /* Make a non-inheritable copy of the socket handle. Note
3034 that it is possible that sockets aren't actually kernel
3035 handles, which appears to be the case on Windows 9x when
3036 the MS Proxy winsock client is installed. */
3038 /* Apparently there is a bug in NT 3.51 with some service
3039 packs, which prevents using DuplicateHandle to make a
3040 socket handle non-inheritable (causes WSACleanup to
3041 hang). The work-around is to use SetHandleInformation
3042 instead if it is available and implemented. */
3043 if (pfn_SetHandleInformation
)
3045 pfn_SetHandleInformation ((HANDLE
) s
, HANDLE_FLAG_INHERIT
, 0);
3049 HANDLE parent
= GetCurrentProcess ();
3050 HANDLE new_s
= INVALID_HANDLE_VALUE
;
3052 if (DuplicateHandle (parent
,
3058 DUPLICATE_SAME_ACCESS
))
3060 /* It is possible that DuplicateHandle succeeds even
3061 though the socket wasn't really a kernel handle,
3062 because a real handle has the same value. So
3063 test whether the new handle really is a socket. */
3064 long nonblocking
= 0;
3065 if (pfn_ioctlsocket ((SOCKET
) new_s
, FIONBIO
, &nonblocking
) == 0)
3067 pfn_closesocket (s
);
3072 CloseHandle (new_s
);
3077 fd_info
[fd
].hnd
= (HANDLE
) s
;
3080 /* set our own internal flags */
3081 fd_info
[fd
].flags
= FILE_SOCKET
| FILE_BINARY
| FILE_READ
| FILE_WRITE
;
3087 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
3089 /* attach child_process to fd_info */
3090 if (fd_info
[ fd
].cp
!= NULL
)
3092 DebPrint (("sys_socket: fd_info[%d] apparently in use!\n", fd
));
3096 fd_info
[ fd
].cp
= cp
;
3099 winsock_inuse
++; /* count open sockets */
3106 pfn_closesocket (s
);
3113 sys_bind (int s
, const struct sockaddr
* addr
, int namelen
)
3115 if (winsock_lib
== NULL
)
3118 return SOCKET_ERROR
;
3122 if (fd_info
[s
].flags
& FILE_SOCKET
)
3124 int rc
= pfn_bind (SOCK_HANDLE (s
), addr
, namelen
);
3125 if (rc
== SOCKET_ERROR
)
3130 return SOCKET_ERROR
;
3135 sys_connect (int s
, const struct sockaddr
* name
, int namelen
)
3137 if (winsock_lib
== NULL
)
3140 return SOCKET_ERROR
;
3144 if (fd_info
[s
].flags
& FILE_SOCKET
)
3146 int rc
= pfn_connect (SOCK_HANDLE (s
), name
, namelen
);
3147 if (rc
== SOCKET_ERROR
)
3152 return SOCKET_ERROR
;
3156 sys_htons (u_short hostshort
)
3158 return (winsock_lib
!= NULL
) ?
3159 pfn_htons (hostshort
) : hostshort
;
3163 sys_ntohs (u_short netshort
)
3165 return (winsock_lib
!= NULL
) ?
3166 pfn_ntohs (netshort
) : netshort
;
3170 sys_inet_addr (const char * cp
)
3172 return (winsock_lib
!= NULL
) ?
3173 pfn_inet_addr (cp
) : INADDR_NONE
;
3177 sys_gethostname (char * name
, int namelen
)
3179 if (winsock_lib
!= NULL
)
3180 return pfn_gethostname (name
, namelen
);
3182 if (namelen
> MAX_COMPUTERNAME_LENGTH
)
3183 return !GetComputerName (name
, (DWORD
*)&namelen
);
3186 return SOCKET_ERROR
;
3190 sys_gethostbyname(const char * name
)
3192 struct hostent
* host
;
3194 if (winsock_lib
== NULL
)
3201 host
= pfn_gethostbyname (name
);
3208 sys_getservbyname(const char * name
, const char * proto
)
3210 struct servent
* serv
;
3212 if (winsock_lib
== NULL
)
3219 serv
= pfn_getservbyname (name
, proto
);
3226 sys_getpeername (int s
, struct sockaddr
*addr
, int * namelen
)
3228 if (winsock_lib
== NULL
)
3231 return SOCKET_ERROR
;
3235 if (fd_info
[s
].flags
& FILE_SOCKET
)
3237 int rc
= pfn_getpeername (SOCK_HANDLE (s
), addr
, namelen
);
3238 if (rc
== SOCKET_ERROR
)
3243 return SOCKET_ERROR
;
3248 sys_shutdown (int s
, int how
)
3250 if (winsock_lib
== NULL
)
3253 return SOCKET_ERROR
;
3257 if (fd_info
[s
].flags
& FILE_SOCKET
)
3259 int rc
= pfn_shutdown (SOCK_HANDLE (s
), how
);
3260 if (rc
== SOCKET_ERROR
)
3265 return SOCKET_ERROR
;
3269 sys_setsockopt (int s
, int level
, int optname
, const void * optval
, int optlen
)
3271 if (winsock_lib
== NULL
)
3274 return SOCKET_ERROR
;
3278 if (fd_info
[s
].flags
& FILE_SOCKET
)
3280 int rc
= pfn_setsockopt (SOCK_HANDLE (s
), level
, optname
,
3281 (const char *)optval
, optlen
);
3282 if (rc
== SOCKET_ERROR
)
3287 return SOCKET_ERROR
;
3291 sys_listen (int s
, int backlog
)
3293 if (winsock_lib
== NULL
)
3296 return SOCKET_ERROR
;
3300 if (fd_info
[s
].flags
& FILE_SOCKET
)
3302 int rc
= pfn_listen (SOCK_HANDLE (s
), backlog
);
3303 if (rc
== SOCKET_ERROR
)
3306 fd_info
[s
].flags
|= FILE_LISTEN
;
3310 return SOCKET_ERROR
;
3314 sys_getsockname (int s
, struct sockaddr
* name
, int * namelen
)
3316 if (winsock_lib
== NULL
)
3319 return SOCKET_ERROR
;
3323 if (fd_info
[s
].flags
& FILE_SOCKET
)
3325 int rc
= pfn_getsockname (SOCK_HANDLE (s
), name
, namelen
);
3326 if (rc
== SOCKET_ERROR
)
3331 return SOCKET_ERROR
;
3335 sys_accept (int s
, struct sockaddr
* addr
, int * addrlen
)
3337 if (winsock_lib
== NULL
)
3344 if (fd_info
[s
].flags
& FILE_LISTEN
)
3346 SOCKET t
= pfn_accept (SOCK_HANDLE (s
), addr
, addrlen
);
3348 if (t
== INVALID_SOCKET
)
3351 fd
= socket_to_fd (t
);
3353 fd_info
[s
].cp
->status
= STATUS_READ_ACKNOWLEDGED
;
3354 ResetEvent (fd_info
[s
].cp
->char_avail
);
3362 sys_recvfrom (int s
, char * buf
, int len
, int flags
,
3363 struct sockaddr
* from
, int * fromlen
)
3365 if (winsock_lib
== NULL
)
3368 return SOCKET_ERROR
;
3372 if (fd_info
[s
].flags
& FILE_SOCKET
)
3374 int rc
= pfn_recvfrom (SOCK_HANDLE (s
), buf
, len
, flags
, from
, fromlen
);
3375 if (rc
== SOCKET_ERROR
)
3380 return SOCKET_ERROR
;
3384 sys_sendto (int s
, const char * buf
, int len
, int flags
,
3385 const struct sockaddr
* to
, int tolen
)
3387 if (winsock_lib
== NULL
)
3390 return SOCKET_ERROR
;
3394 if (fd_info
[s
].flags
& FILE_SOCKET
)
3396 int rc
= pfn_sendto (SOCK_HANDLE (s
), buf
, len
, flags
, to
, tolen
);
3397 if (rc
== SOCKET_ERROR
)
3402 return SOCKET_ERROR
;
3405 /* Windows does not have an fcntl function. Provide an implementation
3406 solely for making sockets non-blocking. */
3408 fcntl (int s
, int cmd
, int options
)
3410 if (winsock_lib
== NULL
)
3417 if (fd_info
[s
].flags
& FILE_SOCKET
)
3419 if (cmd
== F_SETFL
&& options
== O_NDELAY
)
3421 unsigned long nblock
= 1;
3422 int rc
= pfn_ioctlsocket (SOCK_HANDLE (s
), FIONBIO
, &nblock
);
3423 if (rc
== SOCKET_ERROR
)
3425 /* Keep track of the fact that we set this to non-blocking. */
3426 fd_info
[s
].flags
|= FILE_NDELAY
;
3432 return SOCKET_ERROR
;
3436 return SOCKET_ERROR
;
3439 #endif /* HAVE_SOCKETS */
3442 /* Shadow main io functions: we need to handle pipes and sockets more
3443 intelligently, and implement non-blocking mode as well. */
3456 if (fd
< MAXDESC
&& fd_info
[fd
].cp
)
3458 child_process
* cp
= fd_info
[fd
].cp
;
3460 fd_info
[fd
].cp
= NULL
;
3462 if (CHILD_ACTIVE (cp
))
3464 /* if last descriptor to active child_process then cleanup */
3466 for (i
= 0; i
< MAXDESC
; i
++)
3470 if (fd_info
[i
].cp
== cp
)
3476 if (fd_info
[fd
].flags
& FILE_SOCKET
)
3478 #ifndef SOCK_REPLACE_HANDLE
3479 if (winsock_lib
== NULL
) abort ();
3481 pfn_shutdown (SOCK_HANDLE (fd
), 2);
3482 rc
= pfn_closesocket (SOCK_HANDLE (fd
));
3484 winsock_inuse
--; /* count open sockets */
3492 /* Note that sockets do not need special treatment here (at least on
3493 NT and Windows 95 using the standard tcp/ip stacks) - it appears that
3494 closesocket is equivalent to CloseHandle, which is to be expected
3495 because socket handles are fully fledged kernel handles. */
3498 if (rc
== 0 && fd
< MAXDESC
)
3499 fd_info
[fd
].flags
= 0;
3510 if (new_fd
>= 0 && new_fd
< MAXDESC
)
3512 /* duplicate our internal info as well */
3513 fd_info
[new_fd
] = fd_info
[fd
];
3520 sys_dup2 (int src
, int dst
)
3524 if (dst
< 0 || dst
>= MAXDESC
)
3530 /* make sure we close the destination first if it's a pipe or socket */
3531 if (src
!= dst
&& fd_info
[dst
].flags
!= 0)
3534 rc
= _dup2 (src
, dst
);
3537 /* duplicate our internal info as well */
3538 fd_info
[dst
] = fd_info
[src
];
3543 /* Unix pipe() has only one arg */
3545 sys_pipe (int * phandles
)
3550 /* make pipe handles non-inheritable; when we spawn a child, we
3551 replace the relevant handle with an inheritable one. Also put
3552 pipes into binary mode; we will do text mode translation ourselves
3554 rc
= _pipe (phandles
, 0, _O_NOINHERIT
| _O_BINARY
);
3558 /* Protect against overflow, since Windows can open more handles than
3559 our fd_info array has room for. */
3560 if (phandles
[0] >= MAXDESC
|| phandles
[1] >= MAXDESC
)
3562 _close (phandles
[0]);
3563 _close (phandles
[1]);
3568 flags
= FILE_PIPE
| FILE_READ
| FILE_BINARY
;
3569 fd_info
[phandles
[0]].flags
= flags
;
3571 flags
= FILE_PIPE
| FILE_WRITE
| FILE_BINARY
;
3572 fd_info
[phandles
[1]].flags
= flags
;
3580 extern int w32_pipe_read_delay
;
3582 /* Function to do blocking read of one byte, needed to implement
3583 select. It is only allowed on sockets and pipes. */
3585 _sys_read_ahead (int fd
)
3590 if (fd
< 0 || fd
>= MAXDESC
)
3591 return STATUS_READ_ERROR
;
3593 cp
= fd_info
[fd
].cp
;
3595 if (cp
== NULL
|| cp
->fd
!= fd
|| cp
->status
!= STATUS_READ_READY
)
3596 return STATUS_READ_ERROR
;
3598 if ((fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SOCKET
)) == 0
3599 || (fd_info
[fd
].flags
& FILE_READ
) == 0)
3601 DebPrint (("_sys_read_ahead: internal error: fd %d is not a pipe or socket!\n", fd
));
3605 cp
->status
= STATUS_READ_IN_PROGRESS
;
3607 if (fd_info
[fd
].flags
& FILE_PIPE
)
3609 rc
= _read (fd
, &cp
->chr
, sizeof (char));
3611 /* Give subprocess time to buffer some more output for us before
3612 reporting that input is available; we need this because Windows 95
3613 connects DOS programs to pipes by making the pipe appear to be
3614 the normal console stdout - as a result most DOS programs will
3615 write to stdout without buffering, ie. one character at a
3616 time. Even some W32 programs do this - "dir" in a command
3617 shell on NT is very slow if we don't do this. */
3620 int wait
= w32_pipe_read_delay
;
3626 /* Yield remainder of our time slice, effectively giving a
3627 temporary priority boost to the child process. */
3632 else if (fd_info
[fd
].flags
& FILE_SOCKET
)
3634 unsigned long nblock
= 0;
3635 /* We always want this to block, so temporarily disable NDELAY. */
3636 if (fd_info
[fd
].flags
& FILE_NDELAY
)
3637 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
3639 rc
= pfn_recv (SOCK_HANDLE (fd
), &cp
->chr
, sizeof (char), 0);
3641 if (fd_info
[fd
].flags
& FILE_NDELAY
)
3644 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
3649 if (rc
== sizeof (char))
3650 cp
->status
= STATUS_READ_SUCCEEDED
;
3652 cp
->status
= STATUS_READ_FAILED
;
3657 int _sys_wait_accept (int fd
)
3663 if (fd
< 0 || fd
>= MAXDESC
)
3664 return STATUS_READ_ERROR
;
3666 cp
= fd_info
[fd
].cp
;
3668 if (cp
== NULL
|| cp
->fd
!= fd
|| cp
->status
!= STATUS_READ_READY
)
3669 return STATUS_READ_ERROR
;
3671 cp
->status
= STATUS_READ_FAILED
;
3673 hEv
= pfn_WSACreateEvent ();
3674 rc
= pfn_WSAEventSelect (SOCK_HANDLE (fd
), hEv
, FD_ACCEPT
);
3675 if (rc
!= SOCKET_ERROR
)
3677 rc
= WaitForSingleObject (hEv
, INFINITE
);
3678 pfn_WSAEventSelect (SOCK_HANDLE (fd
), NULL
, 0);
3679 pfn_WSACloseEvent (hEv
);
3680 if (rc
== WAIT_OBJECT_0
)
3681 cp
->status
= STATUS_READ_SUCCEEDED
;
3688 sys_read (int fd
, char * buffer
, unsigned int count
)
3693 char * orig_buffer
= buffer
;
3701 if (fd
< MAXDESC
&& fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SOCKET
))
3703 child_process
*cp
= fd_info
[fd
].cp
;
3705 if ((fd_info
[fd
].flags
& FILE_READ
) == 0)
3713 /* re-read CR carried over from last read */
3714 if (fd_info
[fd
].flags
& FILE_LAST_CR
)
3716 if (fd_info
[fd
].flags
& FILE_BINARY
) abort ();
3720 fd_info
[fd
].flags
&= ~FILE_LAST_CR
;
3723 /* presence of a child_process structure means we are operating in
3724 non-blocking mode - otherwise we just call _read directly.
3725 Note that the child_process structure might be missing because
3726 reap_subprocess has been called; in this case the pipe is
3727 already broken, so calling _read on it is okay. */
3730 int current_status
= cp
->status
;
3732 switch (current_status
)
3734 case STATUS_READ_FAILED
:
3735 case STATUS_READ_ERROR
:
3736 /* report normal EOF if nothing in buffer */
3738 fd_info
[fd
].flags
|= FILE_AT_EOF
;
3741 case STATUS_READ_READY
:
3742 case STATUS_READ_IN_PROGRESS
:
3743 DebPrint (("sys_read called when read is in progress\n"));
3744 errno
= EWOULDBLOCK
;
3747 case STATUS_READ_SUCCEEDED
:
3748 /* consume read-ahead char */
3749 *buffer
++ = cp
->chr
;
3752 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
3753 ResetEvent (cp
->char_avail
);
3755 case STATUS_READ_ACKNOWLEDGED
:
3759 DebPrint (("sys_read: bad status %d\n", current_status
));
3764 if (fd_info
[fd
].flags
& FILE_PIPE
)
3766 PeekNamedPipe ((HANDLE
) _get_osfhandle (fd
), NULL
, 0, NULL
, &waiting
, NULL
);
3767 to_read
= min (waiting
, (DWORD
) count
);
3770 nchars
+= _read (fd
, buffer
, to_read
);
3773 else /* FILE_SOCKET */
3775 if (winsock_lib
== NULL
) abort ();
3777 /* do the equivalent of a non-blocking read */
3778 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONREAD
, &waiting
);
3779 if (waiting
== 0 && nchars
== 0)
3781 h_errno
= errno
= EWOULDBLOCK
;
3787 /* always use binary mode for sockets */
3788 int res
= pfn_recv (SOCK_HANDLE (fd
), buffer
, count
, 0);
3789 if (res
== SOCKET_ERROR
)
3791 DebPrint(("sys_read.recv failed with error %d on socket %ld\n",
3792 pfn_WSAGetLastError (), SOCK_HANDLE (fd
)));
3803 int nread
= _read (fd
, buffer
, count
);
3806 else if (nchars
== 0)
3811 fd_info
[fd
].flags
|= FILE_AT_EOF
;
3812 /* Perform text mode translation if required. */
3813 else if ((fd_info
[fd
].flags
& FILE_BINARY
) == 0)
3815 nchars
= crlf_to_lf (nchars
, orig_buffer
);
3816 /* If buffer contains only CR, return that. To be absolutely
3817 sure we should attempt to read the next char, but in
3818 practice a CR to be followed by LF would not appear by
3819 itself in the buffer. */
3820 if (nchars
> 1 && orig_buffer
[nchars
- 1] == 0x0d)
3822 fd_info
[fd
].flags
|= FILE_LAST_CR
;
3828 nchars
= _read (fd
, buffer
, count
);
3833 /* For now, don't bother with a non-blocking mode */
3835 sys_write (int fd
, const void * buffer
, unsigned int count
)
3845 if (fd
< MAXDESC
&& fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SOCKET
))
3847 if ((fd_info
[fd
].flags
& FILE_WRITE
) == 0)
3853 /* Perform text mode translation if required. */
3854 if ((fd_info
[fd
].flags
& FILE_BINARY
) == 0)
3856 char * tmpbuf
= alloca (count
* 2);
3857 unsigned char * src
= (void *)buffer
;
3858 unsigned char * dst
= tmpbuf
;
3863 unsigned char *next
;
3864 /* copy next line or remaining bytes */
3865 next
= _memccpy (dst
, src
, '\n', nbytes
);
3868 /* copied one line ending with '\n' */
3869 int copied
= next
- dst
;
3872 /* insert '\r' before '\n' */
3879 /* copied remaining partial line -> now finished */
3887 if (fd
< MAXDESC
&& fd_info
[fd
].flags
& FILE_SOCKET
)
3889 unsigned long nblock
= 0;
3890 if (winsock_lib
== NULL
) abort ();
3892 /* TODO: implement select() properly so non-blocking I/O works. */
3893 /* For now, make sure the write blocks. */
3894 if (fd_info
[fd
].flags
& FILE_NDELAY
)
3895 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
3897 nchars
= pfn_send (SOCK_HANDLE (fd
), buffer
, count
, 0);
3899 /* Set the socket back to non-blocking if it was before,
3900 for other operations that support it. */
3901 if (fd_info
[fd
].flags
& FILE_NDELAY
)
3904 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
3907 if (nchars
== SOCKET_ERROR
)
3909 DebPrint(("sys_write.send failed with error %d on socket %ld\n",
3910 pfn_WSAGetLastError (), SOCK_HANDLE (fd
)));
3916 nchars
= _write (fd
, buffer
, count
);
3922 check_windows_init_file ()
3924 extern int noninteractive
, inhibit_window_system
;
3926 /* A common indication that Emacs is not installed properly is when
3927 it cannot find the Windows installation file. If this file does
3928 not exist in the expected place, tell the user. */
3930 if (!noninteractive
&& !inhibit_window_system
)
3932 extern Lisp_Object Vwindow_system
, Vload_path
, Qfile_exists_p
;
3933 Lisp_Object objs
[2];
3934 Lisp_Object full_load_path
;
3935 Lisp_Object init_file
;
3938 objs
[0] = Vload_path
;
3939 objs
[1] = decode_env_path (0, (getenv ("EMACSLOADPATH")));
3940 full_load_path
= Fappend (2, objs
);
3941 init_file
= build_string ("term/w32-win");
3942 fd
= openp (full_load_path
, init_file
, Fget_load_suffixes (), NULL
, Qnil
);
3945 Lisp_Object load_path_print
= Fprin1_to_string (full_load_path
, Qnil
);
3946 char *init_file_name
= SDATA (init_file
);
3947 char *load_path
= SDATA (load_path_print
);
3948 char *buffer
= alloca (1024
3949 + strlen (init_file_name
)
3950 + strlen (load_path
));
3953 "The Emacs Windows initialization file \"%s.el\" "
3954 "could not be found in your Emacs installation. "
3955 "Emacs checked the following directories for this file:\n"
3957 "When Emacs cannot find this file, it usually means that it "
3958 "was not installed properly, or its distribution file was "
3959 "not unpacked properly.\nSee the README.W32 file in the "
3960 "top-level Emacs directory for more information.",
3961 init_file_name
, load_path
);
3964 "Emacs Abort Dialog",
3965 MB_OK
| MB_ICONEXCLAMATION
| MB_TASKMODAL
);
3966 /* Use the low-level Emacs abort. */
3981 /* shutdown the socket interface if necessary */
3992 /* Initialise the socket interface now if available and requested by
3993 the user by defining PRELOAD_WINSOCK; otherwise loading will be
3994 delayed until open-network-stream is called (w32-has-winsock can
3995 also be used to dynamically load or reload winsock).
3997 Conveniently, init_environment is called before us, so
3998 PRELOAD_WINSOCK can be set in the registry. */
4000 /* Always initialize this correctly. */
4003 if (getenv ("PRELOAD_WINSOCK") != NULL
)
4004 init_winsock (TRUE
);
4007 /* Initial preparation for subprocess support: replace our standard
4008 handles with non-inheritable versions. */
4011 HANDLE stdin_save
= INVALID_HANDLE_VALUE
;
4012 HANDLE stdout_save
= INVALID_HANDLE_VALUE
;
4013 HANDLE stderr_save
= INVALID_HANDLE_VALUE
;
4015 parent
= GetCurrentProcess ();
4017 /* ignore errors when duplicating and closing; typically the
4018 handles will be invalid when running as a gui program. */
4019 DuplicateHandle (parent
,
4020 GetStdHandle (STD_INPUT_HANDLE
),
4025 DUPLICATE_SAME_ACCESS
);
4027 DuplicateHandle (parent
,
4028 GetStdHandle (STD_OUTPUT_HANDLE
),
4033 DUPLICATE_SAME_ACCESS
);
4035 DuplicateHandle (parent
,
4036 GetStdHandle (STD_ERROR_HANDLE
),
4041 DUPLICATE_SAME_ACCESS
);
4047 if (stdin_save
!= INVALID_HANDLE_VALUE
)
4048 _open_osfhandle ((long) stdin_save
, O_TEXT
);
4050 _open ("nul", O_TEXT
| O_NOINHERIT
| O_RDONLY
);
4053 if (stdout_save
!= INVALID_HANDLE_VALUE
)
4054 _open_osfhandle ((long) stdout_save
, O_TEXT
);
4056 _open ("nul", O_TEXT
| O_NOINHERIT
| O_WRONLY
);
4059 if (stderr_save
!= INVALID_HANDLE_VALUE
)
4060 _open_osfhandle ((long) stderr_save
, O_TEXT
);
4062 _open ("nul", O_TEXT
| O_NOINHERIT
| O_WRONLY
);
4066 /* unfortunately, atexit depends on implementation of malloc */
4067 /* atexit (term_ntproc); */
4068 signal (SIGABRT
, term_ntproc
);
4070 /* determine which drives are fixed, for GetCachedVolumeInformation */
4072 /* GetDriveType must have trailing backslash. */
4073 char drive
[] = "A:\\";
4075 /* Loop over all possible drive letters */
4076 while (*drive
<= 'Z')
4078 /* Record if this drive letter refers to a fixed drive. */
4079 fixed_drives
[DRIVE_INDEX (*drive
)] =
4080 (GetDriveType (drive
) == DRIVE_FIXED
);
4085 /* Reset the volume info cache. */
4086 volume_cache
= NULL
;
4089 /* Check to see if Emacs has been installed correctly. */
4090 check_windows_init_file ();
4094 globals_of_w32 is used to initialize those global variables that
4095 must always be initialized on startup even when the global variable
4096 initialized is non zero (see the function main in emacs.c).
4098 void globals_of_w32 ()
4100 g_b_init_is_windows_9x
= 0;
4101 g_b_init_open_process_token
= 0;
4102 g_b_init_get_token_information
= 0;
4103 g_b_init_lookup_account_sid
= 0;
4104 g_b_init_get_sid_identifier_authority
= 0;
4109 /* arch-tag: 90442dd3-37be-482b-b272-ac752e3049f1
4110 (do not change this comment) */