]> code.delx.au - gnu-emacs/blob - src/w32.c
(pfn_WSACreateEvent, pfn_WSACloseEvent): New func ptrs.
[gnu-emacs] / src / w32.c
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.
4
5 This file is part of GNU Emacs.
6
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
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.
16
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.
21
22 Geoff Voelker (voelker@cs.washington.edu) 7-29-94
23 */
24 #include <stddef.h> /* for offsetof */
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <io.h>
28 #include <errno.h>
29 #include <fcntl.h>
30 #include <ctype.h>
31 #include <signal.h>
32 #include <sys/file.h>
33 #include <sys/time.h>
34 #include <sys/utime.h>
35
36 /* must include CRT headers *before* config.h */
37
38 #ifdef HAVE_CONFIG_H
39 #include <config.h>
40 #endif
41
42 #undef access
43 #undef chdir
44 #undef chmod
45 #undef creat
46 #undef ctime
47 #undef fopen
48 #undef link
49 #undef mkdir
50 #undef mktemp
51 #undef open
52 #undef rename
53 #undef rmdir
54 #undef unlink
55
56 #undef close
57 #undef dup
58 #undef dup2
59 #undef pipe
60 #undef read
61 #undef write
62
63 #undef strerror
64
65 #include "lisp.h"
66
67 #include <pwd.h>
68 #include <grp.h>
69
70 #ifdef __GNUC__
71 #define _ANONYMOUS_UNION
72 #define _ANONYMOUS_STRUCT
73 #endif
74 #include <windows.h>
75 #include <shlobj.h>
76
77 #ifdef HAVE_SOCKETS /* TCP connection support, if kernel can do it */
78 #include <sys/socket.h>
79 #undef socket
80 #undef bind
81 #undef connect
82 #undef htons
83 #undef ntohs
84 #undef inet_addr
85 #undef gethostname
86 #undef gethostbyname
87 #undef getservbyname
88 #undef getpeername
89 #undef shutdown
90 #undef setsockopt
91 #undef listen
92 #undef getsockname
93 #undef accept
94 #undef recvfrom
95 #undef sendto
96 #endif
97
98 #include "w32.h"
99 #include "ndir.h"
100 #include "w32heap.h"
101 #include "systime.h"
102
103 typedef HRESULT (WINAPI * ShGetFolderPath_fn)
104 (IN HWND, IN int, IN HANDLE, IN DWORD, OUT char *);
105
106 void globals_of_w32 ();
107
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;
112
113 \f
114 /*
115 Initialization states
116 */
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;
122
123 /*
124 BEGIN: Wrapper functions around OpenProcessToken
125 and other functions in advapi32.dll that are only
126 supported in Windows NT / 2k / XP
127 */
128 /* ** Function pointer typedefs ** */
129 typedef BOOL (WINAPI * OpenProcessToken_Proc) (
130 HANDLE ProcessHandle,
131 DWORD DesiredAccess,
132 PHANDLE TokenHandle);
133 typedef BOOL (WINAPI * GetTokenInformation_Proc) (
134 HANDLE TokenHandle,
135 TOKEN_INFORMATION_CLASS TokenInformationClass,
136 LPVOID TokenInformation,
137 DWORD TokenInformationLength,
138 PDWORD ReturnLength);
139 #ifdef _UNICODE
140 const char * const LookupAccountSid_Name = "LookupAccountSidW";
141 #else
142 const char * const LookupAccountSid_Name = "LookupAccountSidA";
143 #endif
144 typedef BOOL (WINAPI * LookupAccountSid_Proc) (
145 LPCTSTR lpSystemName,
146 PSID Sid,
147 LPTSTR Name,
148 LPDWORD cbName,
149 LPTSTR DomainName,
150 LPDWORD cbDomainName,
151 PSID_NAME_USE peUse);
152 typedef PSID_IDENTIFIER_AUTHORITY (WINAPI * GetSidIdentifierAuthority_Proc) (
153 PSID pSid);
154
155 /* ** A utility function ** */
156 static BOOL is_windows_9x ()
157 {
158 static BOOL s_b_ret=0;
159 OSVERSIONINFO os_ver;
160 if (g_b_init_is_windows_9x == 0)
161 {
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))
166 {
167 s_b_ret = (os_ver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS);
168 }
169 }
170 return s_b_ret;
171 }
172
173 /* ** The wrapper functions ** */
174
175 BOOL WINAPI open_process_token (
176 HANDLE ProcessHandle,
177 DWORD DesiredAccess,
178 PHANDLE TokenHandle)
179 {
180 static OpenProcessToken_Proc s_pfn_Open_Process_Token = NULL;
181 HMODULE hm_advapi32 = NULL;
182 if (is_windows_9x () == TRUE)
183 {
184 return FALSE;
185 }
186 if (g_b_init_open_process_token == 0)
187 {
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");
192 }
193 if (s_pfn_Open_Process_Token == NULL)
194 {
195 return FALSE;
196 }
197 return (
198 s_pfn_Open_Process_Token (
199 ProcessHandle,
200 DesiredAccess,
201 TokenHandle)
202 );
203 }
204
205 BOOL WINAPI get_token_information (
206 HANDLE TokenHandle,
207 TOKEN_INFORMATION_CLASS TokenInformationClass,
208 LPVOID TokenInformation,
209 DWORD TokenInformationLength,
210 PDWORD ReturnLength)
211 {
212 static GetTokenInformation_Proc s_pfn_Get_Token_Information = NULL;
213 HMODULE hm_advapi32 = NULL;
214 if (is_windows_9x () == TRUE)
215 {
216 return FALSE;
217 }
218 if (g_b_init_get_token_information == 0)
219 {
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");
224 }
225 if (s_pfn_Get_Token_Information == NULL)
226 {
227 return FALSE;
228 }
229 return (
230 s_pfn_Get_Token_Information (
231 TokenHandle,
232 TokenInformationClass,
233 TokenInformation,
234 TokenInformationLength,
235 ReturnLength)
236 );
237 }
238
239 BOOL WINAPI lookup_account_sid (
240 LPCTSTR lpSystemName,
241 PSID Sid,
242 LPTSTR Name,
243 LPDWORD cbName,
244 LPTSTR DomainName,
245 LPDWORD cbDomainName,
246 PSID_NAME_USE peUse)
247 {
248 static LookupAccountSid_Proc s_pfn_Lookup_Account_Sid = NULL;
249 HMODULE hm_advapi32 = NULL;
250 if (is_windows_9x () == TRUE)
251 {
252 return FALSE;
253 }
254 if (g_b_init_lookup_account_sid == 0)
255 {
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);
260 }
261 if (s_pfn_Lookup_Account_Sid == NULL)
262 {
263 return FALSE;
264 }
265 return (
266 s_pfn_Lookup_Account_Sid (
267 lpSystemName,
268 Sid,
269 Name,
270 cbName,
271 DomainName,
272 cbDomainName,
273 peUse)
274 );
275 }
276
277 PSID_IDENTIFIER_AUTHORITY WINAPI get_sid_identifier_authority (
278 PSID pSid)
279 {
280 static GetSidIdentifierAuthority_Proc s_pfn_Get_Sid_Identifier_Authority = NULL;
281 HMODULE hm_advapi32 = NULL;
282 if (is_windows_9x () == TRUE)
283 {
284 return NULL;
285 }
286 if (g_b_init_get_sid_identifier_authority == 0)
287 {
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");
293 }
294 if (s_pfn_Get_Sid_Identifier_Authority == NULL)
295 {
296 return NULL;
297 }
298 return (s_pfn_Get_Sid_Identifier_Authority (pSid));
299 }
300
301 /*
302 END: Wrapper functions around OpenProcessToken
303 and other functions in advapi32.dll that are only
304 supported in Windows NT / 2k / XP
305 */
306
307 \f
308 /* Equivalent of strerror for W32 error codes. */
309 char *
310 w32_strerror (int error_no)
311 {
312 static char buf[500];
313
314 if (error_no == 0)
315 error_no = GetLastError ();
316
317 buf[0] = '\0';
318 if (!FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL,
319 error_no,
320 0, /* choose most suitable language */
321 buf, sizeof (buf), NULL))
322 sprintf (buf, "w32 error %u", error_no);
323 return buf;
324 }
325
326 static char startup_dir[MAXPATHLEN];
327
328 /* Get the current working directory. */
329 char *
330 getwd (char *dir)
331 {
332 #if 0
333 if (GetCurrentDirectory (MAXPATHLEN, dir) > 0)
334 return dir;
335 return NULL;
336 #else
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);
341 return dir;
342 #endif
343 }
344
345 #ifndef HAVE_SOCKETS
346 /* Emulate gethostname. */
347 int
348 gethostname (char *buffer, int size)
349 {
350 /* NT only allows small host names, so the buffer is
351 certainly large enough. */
352 return !GetComputerName (buffer, &size);
353 }
354 #endif /* HAVE_SOCKETS */
355
356 /* Emulate getloadavg. */
357 int
358 getloadavg (double loadavg[], int nelem)
359 {
360 int i;
361
362 /* A faithful emulation is going to have to be saved for a rainy day. */
363 for (i = 0; i < nelem; i++)
364 {
365 loadavg[i] = 0.0;
366 }
367 return i;
368 }
369
370 /* Emulate getpwuid, getpwnam and others. */
371
372 #define PASSWD_FIELD_SIZE 256
373
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];
379
380 static struct passwd the_passwd =
381 {
382 the_passwd_name,
383 the_passwd_passwd,
384 0,
385 0,
386 0,
387 the_passwd_gecos,
388 the_passwd_dir,
389 the_passwd_shell,
390 };
391
392 static struct group the_group =
393 {
394 /* There are no groups on NT, so we just return "root" as the
395 group name. */
396 "root",
397 };
398
399 int
400 getuid ()
401 {
402 return the_passwd.pw_uid;
403 }
404
405 int
406 geteuid ()
407 {
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. */
411 return getuid ();
412 }
413
414 int
415 getgid ()
416 {
417 return the_passwd.pw_gid;
418 }
419
420 int
421 getegid ()
422 {
423 return getgid ();
424 }
425
426 struct passwd *
427 getpwuid (int uid)
428 {
429 if (uid == the_passwd.pw_uid)
430 return &the_passwd;
431 return NULL;
432 }
433
434 struct group *
435 getgrgid (gid_t gid)
436 {
437 return &the_group;
438 }
439
440 struct passwd *
441 getpwnam (char *name)
442 {
443 struct passwd *pw;
444
445 pw = getpwuid (getuid ());
446 if (!pw)
447 return pw;
448
449 if (stricmp (name, pw->pw_name))
450 return NULL;
451
452 return pw;
453 }
454
455 void
456 init_user_info ()
457 {
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.
460
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). */
464
465 char user_sid[256], name[256], domain[256];
466 DWORD length = sizeof (name), dlength = sizeof (domain), trash;
467 HANDLE token = NULL;
468 SID_NAME_USE user_type;
469
470 if (
471 open_process_token (GetCurrentProcess (), TOKEN_QUERY, &token)
472 && get_token_information (
473 token, TokenUser,
474 (PVOID) user_sid, sizeof (user_sid), &trash)
475 && lookup_account_sid (
476 NULL, *((PSID *) user_sid), name, &length,
477 domain, &dlength, &user_type)
478 )
479 {
480 strcpy (the_passwd.pw_name, name);
481 /* Determine a reasonable uid value. */
482 if (stricmp ("administrator", name) == 0)
483 {
484 the_passwd.pw_uid = 0;
485 the_passwd.pw_gid = 0;
486 }
487 else
488 {
489 SID_IDENTIFIER_AUTHORITY * pSIA;
490
491 pSIA = get_sid_identifier_authority (*((PSID *) user_sid));
492 /* I believe the relative portion is the last 4 bytes (of 6)
493 with msb first. */
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;
500
501 /* Get group id */
502 if (get_token_information (token, TokenPrimaryGroup,
503 (PVOID) user_sid, sizeof (user_sid), &trash))
504 {
505 SID_IDENTIFIER_AUTHORITY * pSIA;
506
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;
514 }
515 else
516 the_passwd.pw_gid = the_passwd.pw_uid;
517 }
518 }
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))
522 {
523 strcpy (the_passwd.pw_name, name);
524 if (stricmp ("administrator", name) == 0)
525 the_passwd.pw_uid = 0;
526 else
527 the_passwd.pw_uid = 123;
528 the_passwd.pw_gid = the_passwd.pw_uid;
529 }
530 else
531 {
532 strcpy (the_passwd.pw_name, "unknown");
533 the_passwd.pw_uid = 123;
534 the_passwd.pw_gid = 123;
535 }
536
537 /* Ensure HOME and SHELL are defined. */
538 if (getenv ("HOME") == NULL)
539 abort ();
540 if (getenv ("SHELL") == NULL)
541 abort ();
542
543 /* Set dir and shell from environment variables. */
544 strcpy (the_passwd.pw_dir, getenv ("HOME"));
545 strcpy (the_passwd.pw_shell, getenv ("SHELL"));
546
547 if (token)
548 CloseHandle (token);
549 }
550
551 int
552 random ()
553 {
554 /* rand () on NT gives us 15 random bits...hack together 30 bits. */
555 return ((rand () << 15) | rand ());
556 }
557
558 void
559 srandom (int seed)
560 {
561 srand (seed);
562 }
563
564
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. */
568
569 static void
570 normalize_filename (fp, path_sep)
571 register char *fp;
572 char path_sep;
573 {
574 char sep;
575 char *elem;
576
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')
583 {
584 *fp += 'a' - 'A';
585 fp += 2;
586 }
587
588 if (NILP (Vw32_downcase_file_names))
589 {
590 while (*fp)
591 {
592 if (*fp == '/' || *fp == '\\')
593 *fp = path_sep;
594 fp++;
595 }
596 return;
597 }
598
599 sep = path_sep; /* convert to this path separator */
600 elem = fp; /* start of current path element */
601
602 do {
603 if (*fp >= 'a' && *fp <= 'z')
604 elem = 0; /* don't convert this element */
605
606 if (*fp == 0 || *fp == ':')
607 {
608 sep = *fp; /* restore current separator (or 0) */
609 *fp = '/'; /* after conversion of this element */
610 }
611
612 if (*fp == '/' || *fp == '\\')
613 {
614 if (elem && elem != fp)
615 {
616 *fp = 0; /* temporary end of string */
617 _strlwr (elem); /* while we convert to lower case */
618 }
619 *fp = sep; /* convert (or restore) path separator */
620 elem = fp + 1; /* next element starts after separator */
621 sep = path_sep;
622 }
623 } while (*fp++);
624 }
625
626 /* Destructively turn backslashes into slashes. */
627 void
628 dostounix_filename (p)
629 register char *p;
630 {
631 normalize_filename (p, '/');
632 }
633
634 /* Destructively turn slashes into backslashes. */
635 void
636 unixtodos_filename (p)
637 register char *p;
638 {
639 normalize_filename (p, '\\');
640 }
641
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.) */
645 int
646 crlf_to_lf (n, buf)
647 register int n;
648 register unsigned char *buf;
649 {
650 unsigned char *np = buf;
651 unsigned char *startp = buf;
652 unsigned char *endp = buf + n;
653
654 if (n == 0)
655 return n;
656 while (buf < endp - 1)
657 {
658 if (*buf == 0x0d)
659 {
660 if (*(++buf) != 0x0a)
661 *np++ = 0x0d;
662 }
663 else
664 *np++ = *buf++;
665 }
666 if (buf < endp)
667 *np++ = *buf++;
668 return np - startp;
669 }
670
671 /* Parse the root part of file name, if present. Return length and
672 optionally store pointer to char after root. */
673 static int
674 parse_root (char * name, char ** pPath)
675 {
676 char * start = name;
677
678 if (name == NULL)
679 return 0;
680
681 /* find the root name of the volume if given */
682 if (isalpha (name[0]) && name[1] == ':')
683 {
684 /* skip past drive specifier */
685 name += 2;
686 if (IS_DIRECTORY_SEP (name[0]))
687 name++;
688 }
689 else if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1]))
690 {
691 int slashes = 2;
692 name += 2;
693 do
694 {
695 if (IS_DIRECTORY_SEP (*name) && --slashes == 0)
696 break;
697 name++;
698 }
699 while ( *name );
700 if (IS_DIRECTORY_SEP (name[0]))
701 name++;
702 }
703
704 if (pPath)
705 *pPath = name;
706
707 return name - start;
708 }
709
710 /* Get long base name for name; name is assumed to be absolute. */
711 static int
712 get_long_basename (char * name, char * buf, int size)
713 {
714 WIN32_FIND_DATA find_data;
715 HANDLE dir_handle;
716 int len = 0;
717
718 /* must be valid filename, no wild cards or other invalid characters */
719 if (strpbrk (name, "*?|<>\""))
720 return 0;
721
722 dir_handle = FindFirstFile (name, &find_data);
723 if (dir_handle != INVALID_HANDLE_VALUE)
724 {
725 if ((len = strlen (find_data.cFileName)) < size)
726 memcpy (buf, find_data.cFileName, len + 1);
727 else
728 len = 0;
729 FindClose (dir_handle);
730 }
731 return len;
732 }
733
734 /* Get long name for file, if possible (assumed to be absolute). */
735 BOOL
736 w32_get_long_filename (char * name, char * buf, int size)
737 {
738 char * o = buf;
739 char * p;
740 char * q;
741 char full[ MAX_PATH ];
742 int len;
743
744 len = strlen (name);
745 if (len >= MAX_PATH)
746 return FALSE;
747
748 /* Use local copy for destructive modification. */
749 memcpy (full, name, len+1);
750 unixtodos_filename (full);
751
752 /* Copy root part verbatim. */
753 len = parse_root (full, &p);
754 memcpy (o, full, len);
755 o += len;
756 *o = '\0';
757 size -= len;
758
759 while (p != NULL && *p)
760 {
761 q = p;
762 p = strchr (q, '\\');
763 if (p) *p = '\0';
764 len = get_long_basename (full, o, size);
765 if (len > 0)
766 {
767 o += len;
768 size -= len;
769 if (p != NULL)
770 {
771 *p++ = '\\';
772 if (size < 2)
773 return FALSE;
774 *o++ = '\\';
775 size--;
776 *o = '\0';
777 }
778 }
779 else
780 return FALSE;
781 }
782
783 return TRUE;
784 }
785
786 int
787 is_unc_volume (const char *filename)
788 {
789 const char *ptr = filename;
790
791 if (!IS_DIRECTORY_SEP (ptr[0]) || !IS_DIRECTORY_SEP (ptr[1]) || !ptr[2])
792 return 0;
793
794 if (strpbrk (ptr + 2, "*?|<>\"\\/"))
795 return 0;
796
797 return 1;
798 }
799
800 /* Routines that are no-ops on NT but are defined to get Emacs to compile. */
801
802 int
803 sigsetmask (int signal_mask)
804 {
805 return 0;
806 }
807
808 int
809 sigmask (int sig)
810 {
811 return 0;
812 }
813
814 int
815 sigblock (int sig)
816 {
817 return 0;
818 }
819
820 int
821 sigunblock (int sig)
822 {
823 return 0;
824 }
825
826 int
827 setpgrp (int pid, int gid)
828 {
829 return 0;
830 }
831
832 int
833 alarm (int seconds)
834 {
835 return 0;
836 }
837
838 void
839 unrequest_sigio (void)
840 {
841 return;
842 }
843
844 void
845 request_sigio (void)
846 {
847 return;
848 }
849
850 #define REG_ROOT "SOFTWARE\\GNU\\Emacs"
851
852 LPBYTE
853 w32_get_resource (key, lpdwtype)
854 char *key;
855 LPDWORD lpdwtype;
856 {
857 LPBYTE lpvalue;
858 HKEY hrootkey = NULL;
859 DWORD cbData;
860 BOOL ok = FALSE;
861
862 /* Check both the current user and the local machine to see if
863 we have any resources. */
864
865 if (RegOpenKeyEx (HKEY_CURRENT_USER, REG_ROOT, 0, KEY_READ, &hrootkey) == ERROR_SUCCESS)
866 {
867 lpvalue = NULL;
868
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)
872 {
873 return (lpvalue);
874 }
875
876 if (lpvalue) xfree (lpvalue);
877
878 RegCloseKey (hrootkey);
879 }
880
881 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, REG_ROOT, 0, KEY_READ, &hrootkey) == ERROR_SUCCESS)
882 {
883 lpvalue = NULL;
884
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)
888 {
889 return (lpvalue);
890 }
891
892 if (lpvalue) xfree (lpvalue);
893
894 RegCloseKey (hrootkey);
895 }
896
897 return (NULL);
898 }
899
900 char *get_emacs_configuration (void);
901 extern Lisp_Object Vsystem_configuration;
902
903 void
904 init_environment (char ** argv)
905 {
906 static const char * const tempdirs[] = {
907 "$TMPDIR", "$TEMP", "$TMP", "c:/"
908 };
909
910 int i;
911
912 const int imax = sizeof (tempdirs) / sizeof (tempdirs[0]);
913
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++)
919 {
920 const char *tmp = tempdirs[i];
921
922 if (*tmp == '$')
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)
929 {
930 char * var = alloca (strlen (tmp) + 8);
931 sprintf (var, "TMPDIR=%s", tmp);
932 _putenv (strdup (var));
933 break;
934 }
935 }
936 if (i >= imax)
937 cmd_error_internal
938 (Fcons (Qerror,
939 Fcons (build_string ("no usable temporary directories found!!"),
940 Qnil)),
941 "While setting TMPDIR: ");
942
943 /* Check for environment variables and use registry settings if they
944 don't exist. Fallback on default values where applicable. */
945 {
946 int i;
947 LPBYTE lpval;
948 DWORD dwType;
949 char locale_name[32];
950 struct stat ignored;
951 char default_home[MAX_PATH];
952
953 static const struct env_entry
954 {
955 char * name;
956 char * def_value;
957 } dflt_envvars[] =
958 {
959 {"HOME", "C:/"},
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
967 is then ignored. */
968 /* {"INFOPATH", "%emacs_dir%/info"}, */
969 {"EMACSDOC", "%emacs_dir%/etc"},
970 {"TERM", "cmd"},
971 {"LANG", NULL},
972 };
973
974 #define N_ENV_VARS sizeof(dflt_envvars)/sizeof(dflt_envvars[0])
975
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];
981
982 for (i = 0; i < N_ENV_VARS; i++)
983 env_vars[i] = dflt_envvars[i];
984
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)
989 {
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. */
994 HMODULE shell32_dll;
995 ShGetFolderPath_fn get_folder_path;
996 shell32_dll = GetModuleHandle ("shell32.dll");
997 get_folder_path = (ShGetFolderPath_fn)
998 GetProcAddress (shell32_dll, "SHGetFolderPathA");
999
1000 if (get_folder_path != NULL)
1001 {
1002 profile_result = get_folder_path (NULL, CSIDL_APPDATA, NULL,
1003 0, default_home);
1004
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;
1008 }
1009
1010 /* Unload shell32.dll, it is not needed anymore. */
1011 FreeLibrary (shell32_dll);
1012 }
1013
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)))
1018 {
1019 for (i = 0; i < N_ENV_VARS; i++)
1020 {
1021 if (strcmp (env_vars[i].name, "LANG") == 0)
1022 {
1023 env_vars[i].def_value = locale_name;
1024 break;
1025 }
1026 }
1027 }
1028
1029 #define SET_ENV_BUF_SIZE (4 * MAX_PATH) /* to cover EMACSLOADPATH */
1030
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. */
1034 {
1035 char *p;
1036 char modname[MAX_PATH];
1037
1038 if (!GetModuleFileName (NULL, modname, MAX_PATH))
1039 abort ();
1040 if ((p = strrchr (modname, '\\')) == NULL)
1041 abort ();
1042 *p = 0;
1043
1044 if ((p = strrchr (modname, '\\')) && stricmp (p, "\\bin") == 0)
1045 {
1046 char buf[SET_ENV_BUF_SIZE];
1047
1048 *p = 0;
1049 for (p = modname; *p; p++)
1050 if (*p == '\\') *p = '/';
1051
1052 _snprintf (buf, sizeof(buf)-1, "emacs_dir=%s", modname);
1053 _putenv (strdup (buf));
1054 }
1055 /* Handle running emacs from the build directory: src/oo-spd/i386/ */
1056
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)
1061 {
1062 *p = 0;
1063 p = strrchr (modname, '\\');
1064 if (p != NULL)
1065 {
1066 *p = 0;
1067 p = strrchr (modname, '\\');
1068 if (p && stricmp (p, "\\src") == 0)
1069 {
1070 char buf[SET_ENV_BUF_SIZE];
1071
1072 *p = 0;
1073 for (p = modname; *p; p++)
1074 if (*p == '\\') *p = '/';
1075
1076 _snprintf (buf, sizeof(buf)-1, "emacs_dir=%s", modname);
1077 _putenv (strdup (buf));
1078 }
1079 }
1080 }
1081 }
1082
1083 for (i = 0; i < N_ENV_VARS; i++)
1084 {
1085 if (!getenv (env_vars[i].name))
1086 {
1087 int dont_free = 0;
1088
1089 if ((lpval = w32_get_resource (env_vars[i].name, &dwType)) == NULL)
1090 {
1091 lpval = env_vars[i].def_value;
1092 dwType = REG_EXPAND_SZ;
1093 dont_free = 1;
1094 }
1095
1096 if (lpval)
1097 {
1098 char buf1[SET_ENV_BUF_SIZE], buf2[SET_ENV_BUF_SIZE];
1099
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)
1105 {
1106 _snprintf (buf2, sizeof(buf2)-1, "%s=%s", env_vars[i].name,
1107 buf1);
1108 _putenv (strdup (buf2));
1109 }
1110
1111 if (!dont_free)
1112 xfree (lpval);
1113 }
1114 }
1115 }
1116 }
1117
1118 /* Rebuild system configuration to reflect invoking system. */
1119 Vsystem_configuration = build_string (EMACS_CONFIGURATION);
1120
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.
1128
1129 The same applies to COMSPEC. */
1130 {
1131 char ** envp;
1132
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);
1138 }
1139
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))
1145 abort ();
1146
1147 {
1148 char *p;
1149 static char modname[MAX_PATH];
1150
1151 if (!GetModuleFileName (NULL, modname, MAX_PATH))
1152 abort ();
1153 if ((p = strrchr (modname, '\\')) == NULL)
1154 abort ();
1155 *p = 0;
1156
1157 SetCurrentDirectory (modname);
1158
1159 /* Ensure argv[0] has the full path to Emacs. */
1160 *p = '\\';
1161 argv[0] = modname;
1162 }
1163
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
1166 mouse-3. */
1167 w32_num_mouse_buttons = GetSystemMetrics (SM_CMOUSEBUTTONS);
1168
1169 init_user_info ();
1170 }
1171
1172 char *
1173 emacs_root_dir (void)
1174 {
1175 static char root_dir[FILENAME_MAX];
1176 const char *p;
1177
1178 p = getenv ("emacs_dir");
1179 if (p == NULL)
1180 abort ();
1181 strcpy (root_dir, p);
1182 root_dir[parse_root (root_dir, NULL)] = '\0';
1183 dostounix_filename (root_dir);
1184 return root_dir;
1185 }
1186
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
1190 routine. */
1191
1192 char *
1193 get_emacs_configuration (void)
1194 {
1195 char *arch, *oem, *os;
1196 int build_num;
1197 static char configuration_buffer[32];
1198
1199 /* Determine the processor type. */
1200 switch (get_processor_type ())
1201 {
1202
1203 #ifdef PROCESSOR_INTEL_386
1204 case PROCESSOR_INTEL_386:
1205 case PROCESSOR_INTEL_486:
1206 case PROCESSOR_INTEL_PENTIUM:
1207 arch = "i386";
1208 break;
1209 #endif
1210
1211 #ifdef PROCESSOR_INTEL_860
1212 case PROCESSOR_INTEL_860:
1213 arch = "i860";
1214 break;
1215 #endif
1216
1217 #ifdef PROCESSOR_MIPS_R2000
1218 case PROCESSOR_MIPS_R2000:
1219 case PROCESSOR_MIPS_R3000:
1220 case PROCESSOR_MIPS_R4000:
1221 arch = "mips";
1222 break;
1223 #endif
1224
1225 #ifdef PROCESSOR_ALPHA_21064
1226 case PROCESSOR_ALPHA_21064:
1227 arch = "alpha";
1228 break;
1229 #endif
1230
1231 default:
1232 arch = "unknown";
1233 break;
1234 }
1235
1236 /* Use the OEM field to reflect the compiler/library combination. */
1237 #ifdef _MSC_VER
1238 #define COMPILER_NAME "msvc"
1239 #else
1240 #ifdef __GNUC__
1241 #define COMPILER_NAME "mingw"
1242 #else
1243 #define COMPILER_NAME "unknown"
1244 #endif
1245 #endif
1246 oem = COMPILER_NAME;
1247
1248 switch (osinfo_cache.dwPlatformId) {
1249 case VER_PLATFORM_WIN32_NT:
1250 os = "nt";
1251 build_num = osinfo_cache.dwBuildNumber;
1252 break;
1253 case VER_PLATFORM_WIN32_WINDOWS:
1254 if (osinfo_cache.dwMinorVersion == 0) {
1255 os = "windows95";
1256 } else {
1257 os = "windows98";
1258 }
1259 build_num = LOWORD (osinfo_cache.dwBuildNumber);
1260 break;
1261 case VER_PLATFORM_WIN32s:
1262 /* Not supported, should not happen. */
1263 os = "windows32s";
1264 build_num = LOWORD (osinfo_cache.dwBuildNumber);
1265 break;
1266 default:
1267 os = "unknown";
1268 build_num = 0;
1269 break;
1270 }
1271
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);
1275 } else {
1276 sprintf (configuration_buffer, "%s-%s-%s.%d", arch, oem, os, build_num);
1277 }
1278
1279 return configuration_buffer;
1280 }
1281
1282 char *
1283 get_emacs_configuration_options (void)
1284 {
1285 static char options_buffer[256];
1286
1287 /* Work out the effective configure options for this build. */
1288 #ifdef _MSC_VER
1289 #define COMPILER_VERSION "--with-msvc (%d.%02d)", _MSC_VER / 100, _MSC_VER % 100
1290 #else
1291 #ifdef __GNUC__
1292 #define COMPILER_VERSION "--with-gcc (%d.%d)", __GNUC__, __GNUC_MINOR__
1293 #else
1294 #define COMPILER_VERSION ""
1295 #endif
1296 #endif
1297
1298 sprintf (options_buffer, COMPILER_VERSION);
1299 #ifdef EMACSDEBUG
1300 strcat (options_buffer, " --no-opt");
1301 #endif
1302 #ifdef USER_CFLAGS
1303 strcat (options_buffer, " --cflags");
1304 strcat (options_buffer, USER_CFLAGS);
1305 #endif
1306 #ifdef USER_LDFLAGS
1307 strcat (options_buffer, " --ldflags");
1308 strcat (options_buffer, USER_LDFLAGS);
1309 #endif
1310 return options_buffer;
1311 }
1312
1313
1314 #include <sys/timeb.h>
1315
1316 /* Emulate gettimeofday (Ulrich Leodolter, 1/11/95). */
1317 void
1318 gettimeofday (struct timeval *tv, struct timezone *tz)
1319 {
1320 struct _timeb tb;
1321 _ftime (&tb);
1322
1323 tv->tv_sec = tb.time;
1324 tv->tv_usec = tb.millitm * 1000L;
1325 if (tz)
1326 {
1327 tz->tz_minuteswest = tb.timezone; /* minutes west of Greenwich */
1328 tz->tz_dsttime = tb.dstflag; /* type of dst correction */
1329 }
1330 }
1331
1332 /* ------------------------------------------------------------------------- */
1333 /* IO support and wrapper functions for W32 API. */
1334 /* ------------------------------------------------------------------------- */
1335
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). */
1339 char *
1340 sys_ctime (const time_t *t)
1341 {
1342 char *str = (char *) ctime (t);
1343 return (str ? str : "Sun Jan 01 00:00:00 1970");
1344 }
1345
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. */
1349 void
1350 sys_sleep (int seconds)
1351 {
1352 Sleep (seconds * 1000);
1353 }
1354
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);
1358
1359 /* parallel array of private info on file handles */
1360 filedesc fd_info [ MAXDESC ];
1361
1362 typedef struct volume_info_data {
1363 struct volume_info_data * next;
1364
1365 /* time when info was obtained */
1366 DWORD timestamp;
1367
1368 /* actual volume info */
1369 char * root_dir;
1370 DWORD serialnum;
1371 DWORD maxcomp;
1372 DWORD flags;
1373 char * name;
1374 char * type;
1375 } volume_info_data;
1376
1377 /* Global referenced by various functions. */
1378 static volume_info_data volume_info;
1379
1380 /* Vector to indicate which drives are local and fixed (for which cached
1381 data never expires). */
1382 static BOOL fixed_drives[26];
1383
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 )
1391
1392 /* Cache support functions. */
1393
1394 /* Simple linked list with linear search is sufficient. */
1395 static volume_info_data *volume_cache = NULL;
1396
1397 static volume_info_data *
1398 lookup_volume_info (char * root_dir)
1399 {
1400 volume_info_data * info;
1401
1402 for (info = volume_cache; info; info = info->next)
1403 if (stricmp (info->root_dir, root_dir) == 0)
1404 break;
1405 return info;
1406 }
1407
1408 static void
1409 add_volume_info (char * root_dir, volume_info_data * info)
1410 {
1411 info->root_dir = xstrdup (root_dir);
1412 info->next = volume_cache;
1413 volume_cache = info;
1414 }
1415
1416
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). */
1420 volume_info_data *
1421 GetCachedVolumeInformation (char * root_dir)
1422 {
1423 volume_info_data * info;
1424 char default_root[ MAX_PATH ];
1425
1426 /* NULL for root_dir means use root from current directory. */
1427 if (root_dir == NULL)
1428 {
1429 if (GetCurrentDirectory (MAX_PATH, default_root) == 0)
1430 return NULL;
1431 parse_root (default_root, &root_dir);
1432 *root_dir = 0;
1433 root_dir = default_root;
1434 }
1435
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.
1443
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. */
1447
1448 #if 0
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). */
1453
1454 /* Map drive letter to UNC if remote. */
1455 if ( isalpha( root_dir[0] ) && !fixed[ DRIVE_INDEX( root_dir[0] ) ] )
1456 {
1457 char remote_name[ 256 ];
1458 char drive[3] = { root_dir[0], ':' };
1459
1460 if (WNetGetConnection (drive, remote_name, sizeof (remote_name))
1461 == NO_ERROR)
1462 /* do something */ ;
1463 }
1464 #endif
1465
1466 info = lookup_volume_info (root_dir);
1467
1468 if (info == NULL || ! VOLINFO_STILL_VALID (root_dir, info))
1469 {
1470 char name[ 256 ];
1471 DWORD serialnum;
1472 DWORD maxcomp;
1473 DWORD flags;
1474 char type[ 256 ];
1475
1476 /* Info is not cached, or is stale. */
1477 if (!GetVolumeInformation (root_dir,
1478 name, sizeof (name),
1479 &serialnum,
1480 &maxcomp,
1481 &flags,
1482 type, sizeof (type)))
1483 return NULL;
1484
1485 /* Cache the volume information for future use, overwriting existing
1486 entry if present. */
1487 if (info == NULL)
1488 {
1489 info = (volume_info_data *) xmalloc (sizeof (volume_info_data));
1490 add_volume_info (root_dir, info);
1491 }
1492 else
1493 {
1494 xfree (info->name);
1495 xfree (info->type);
1496 }
1497
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 ();
1504 }
1505
1506 return info;
1507 }
1508
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). */
1511 int
1512 get_volume_info (const char * name, const char ** pPath)
1513 {
1514 char temp[MAX_PATH];
1515 char *rootname = NULL; /* default to current volume */
1516 volume_info_data * info;
1517
1518 if (name == NULL)
1519 return FALSE;
1520
1521 /* find the root name of the volume if given */
1522 if (isalpha (name[0]) && name[1] == ':')
1523 {
1524 rootname = temp;
1525 temp[0] = *name++;
1526 temp[1] = *name++;
1527 temp[2] = '\\';
1528 temp[3] = 0;
1529 }
1530 else if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1]))
1531 {
1532 char *str = temp;
1533 int slashes = 4;
1534 rootname = temp;
1535 do
1536 {
1537 if (IS_DIRECTORY_SEP (*name) && --slashes == 0)
1538 break;
1539 *str++ = *name++;
1540 }
1541 while ( *name );
1542
1543 *str++ = '\\';
1544 *str = 0;
1545 }
1546
1547 if (pPath)
1548 *pPath = name;
1549
1550 info = GetCachedVolumeInformation (rootname);
1551 if (info != NULL)
1552 {
1553 /* Set global referenced by other functions. */
1554 volume_info = *info;
1555 return TRUE;
1556 }
1557 return FALSE;
1558 }
1559
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. */
1562 int
1563 is_fat_volume (const char * name, const char ** pPath)
1564 {
1565 if (get_volume_info (name, pPath))
1566 return (volume_info.maxcomp == 12);
1567 return FALSE;
1568 }
1569
1570 /* Map filename to a legal 8.3 name if necessary. */
1571 const char *
1572 map_w32_filename (const char * name, const char ** pPath)
1573 {
1574 static char shortname[MAX_PATH];
1575 char * str = shortname;
1576 char c;
1577 char * path;
1578 const char * save_name = name;
1579
1580 if (strlen (name) >= MAX_PATH)
1581 {
1582 /* Return a filename which will cause callers to fail. */
1583 strcpy (shortname, "?");
1584 return shortname;
1585 }
1586
1587 if (is_fat_volume (name, (const char **)&path)) /* truncate to 8.3 */
1588 {
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 */
1592
1593 while (name < path)
1594 *str++ = *name++; /* skip past UNC header */
1595
1596 while ((c = *name++))
1597 {
1598 switch ( c )
1599 {
1600 case '\\':
1601 case '/':
1602 *str++ = '\\';
1603 extn = 0; /* reset extension flags */
1604 dots = 2; /* max 2 dots */
1605 left = 8; /* max length 8 for main part */
1606 break;
1607 case ':':
1608 *str++ = ':';
1609 extn = 0; /* reset extension flags */
1610 dots = 2; /* max 2 dots */
1611 left = 8; /* max length 8 for main part */
1612 break;
1613 case '.':
1614 if ( dots )
1615 {
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. */
1619
1620 if (! *name ||
1621 *name == '.' ||
1622 IS_DIRECTORY_SEP (*name))
1623 {
1624 *str++ = '.';
1625 dots--;
1626 }
1627 else
1628 {
1629 *str++ = '_';
1630 left--;
1631 dots = 0;
1632 }
1633 }
1634 else if ( !extn )
1635 {
1636 *str++ = '.';
1637 extn = 1; /* we've got an extension */
1638 left = 3; /* 3 chars in extension */
1639 }
1640 else
1641 {
1642 /* any embedded dots after the first are converted to _ */
1643 *str++ = '_';
1644 }
1645 break;
1646 case '~':
1647 case '#': /* don't lose these, they're important */
1648 if ( ! left )
1649 str[-1] = c; /* replace last character of part */
1650 /* FALLTHRU */
1651 default:
1652 if ( left )
1653 {
1654 *str++ = tolower (c); /* map to lower case (looks nicer) */
1655 left--;
1656 dots = 0; /* started a path component */
1657 }
1658 break;
1659 }
1660 }
1661 *str = '\0';
1662 }
1663 else
1664 {
1665 strcpy (shortname, name);
1666 unixtodos_filename (shortname);
1667 }
1668
1669 if (pPath)
1670 *pPath = shortname + (path - save_name);
1671
1672 return shortname;
1673 }
1674
1675 static int
1676 is_exec (const char * name)
1677 {
1678 char * p = strrchr (name, '.');
1679 return
1680 (p != NULL
1681 && (stricmp (p, ".exe") == 0 ||
1682 stricmp (p, ".com") == 0 ||
1683 stricmp (p, ".bat") == 0 ||
1684 stricmp (p, ".cmd") == 0));
1685 }
1686
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. */
1690
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;
1696
1697 /* Support shares on a network resource as subdirectories of a read-only
1698 root directory. */
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);
1703
1704 DIR *
1705 opendir (char *filename)
1706 {
1707 DIR *dirp;
1708
1709 /* Opening is done by FindFirstFile. However, a read is inherent to
1710 this operation, so we defer the open until read time. */
1711
1712 if (dir_find_handle != INVALID_HANDLE_VALUE)
1713 return NULL;
1714 if (wnet_enum_handle != INVALID_HANDLE_VALUE)
1715 return NULL;
1716
1717 if (is_unc_volume (filename))
1718 {
1719 wnet_enum_handle = open_unc_volume (filename);
1720 if (wnet_enum_handle == INVALID_HANDLE_VALUE)
1721 return NULL;
1722 }
1723
1724 if (!(dirp = (DIR *) malloc (sizeof (DIR))))
1725 return NULL;
1726
1727 dirp->dd_fd = 0;
1728 dirp->dd_loc = 0;
1729 dirp->dd_size = 0;
1730
1731 strncpy (dir_pathname, map_w32_filename (filename, NULL), MAXPATHLEN);
1732 dir_pathname[MAXPATHLEN] = '\0';
1733 dir_is_fat = is_fat_volume (filename, NULL);
1734
1735 return dirp;
1736 }
1737
1738 void
1739 closedir (DIR *dirp)
1740 {
1741 /* If we have a find-handle open, close it. */
1742 if (dir_find_handle != INVALID_HANDLE_VALUE)
1743 {
1744 FindClose (dir_find_handle);
1745 dir_find_handle = INVALID_HANDLE_VALUE;
1746 }
1747 else if (wnet_enum_handle != INVALID_HANDLE_VALUE)
1748 {
1749 close_unc_volume (wnet_enum_handle);
1750 wnet_enum_handle = INVALID_HANDLE_VALUE;
1751 }
1752 xfree ((char *) dirp);
1753 }
1754
1755 struct direct *
1756 readdir (DIR *dirp)
1757 {
1758 if (wnet_enum_handle != INVALID_HANDLE_VALUE)
1759 {
1760 if (!read_unc_volume (wnet_enum_handle,
1761 dir_find_data.cFileName,
1762 MAX_PATH))
1763 return NULL;
1764 }
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)
1767 {
1768 char filename[MAXNAMLEN + 3];
1769 int ln;
1770
1771 strcpy (filename, dir_pathname);
1772 ln = strlen (filename) - 1;
1773 if (!IS_DIRECTORY_SEP (filename[ln]))
1774 strcat (filename, "\\");
1775 strcat (filename, "*");
1776
1777 dir_find_handle = FindFirstFile (filename, &dir_find_data);
1778
1779 if (dir_find_handle == INVALID_HANDLE_VALUE)
1780 return NULL;
1781 }
1782 else
1783 {
1784 if (!FindNextFile (dir_find_handle, &dir_find_data))
1785 return NULL;
1786 }
1787
1788 /* Emacs never uses this value, so don't bother making it match
1789 value returned by stat(). */
1790 dir_static.d_ino = 1;
1791
1792 dir_static.d_reclen = sizeof (struct direct) - MAXNAMLEN + 3 +
1793 dir_static.d_namlen - dir_static.d_namlen % 4;
1794
1795 dir_static.d_namlen = strlen (dir_find_data.cFileName);
1796 strcpy (dir_static.d_name, dir_find_data.cFileName);
1797 if (dir_is_fat)
1798 _strlwr (dir_static.d_name);
1799 else if (!NILP (Vw32_downcase_file_names))
1800 {
1801 register char *p;
1802 for (p = dir_static.d_name; *p; p++)
1803 if (*p >= 'a' && *p <= 'z')
1804 break;
1805 if (!*p)
1806 _strlwr (dir_static.d_name);
1807 }
1808
1809 return &dir_static;
1810 }
1811
1812 HANDLE
1813 open_unc_volume (const char *path)
1814 {
1815 NETRESOURCE nr;
1816 HANDLE henum;
1817 int result;
1818
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;
1827
1828 result = WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_DISK,
1829 RESOURCEUSAGE_CONNECTABLE, &nr, &henum);
1830
1831 if (result == NO_ERROR)
1832 return henum;
1833 else
1834 return INVALID_HANDLE_VALUE;
1835 }
1836
1837 char *
1838 read_unc_volume (HANDLE henum, char *readbuf, int size)
1839 {
1840 DWORD count;
1841 int result;
1842 DWORD bufsize = 512;
1843 char *buffer;
1844 char *ptr;
1845
1846 count = 1;
1847 buffer = alloca (bufsize);
1848 result = WNetEnumResource (wnet_enum_handle, &count, buffer, &bufsize);
1849 if (result != NO_ERROR)
1850 return NULL;
1851
1852 /* WNetEnumResource returns \\resource\share...skip forward to "share". */
1853 ptr = ((LPNETRESOURCE) buffer)->lpRemoteName;
1854 ptr += 2;
1855 while (*ptr && !IS_DIRECTORY_SEP (*ptr)) ptr++;
1856 ptr++;
1857
1858 strncpy (readbuf, ptr, size);
1859 return readbuf;
1860 }
1861
1862 void
1863 close_unc_volume (HANDLE henum)
1864 {
1865 if (henum != INVALID_HANDLE_VALUE)
1866 WNetCloseEnum (henum);
1867 }
1868
1869 DWORD
1870 unc_volume_file_attributes (const char *path)
1871 {
1872 HANDLE henum;
1873 DWORD attrs;
1874
1875 henum = open_unc_volume (path);
1876 if (henum == INVALID_HANDLE_VALUE)
1877 return -1;
1878
1879 attrs = FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_DIRECTORY;
1880
1881 close_unc_volume (henum);
1882
1883 return attrs;
1884 }
1885
1886
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
1890 long file names. */
1891
1892 int
1893 sys_access (const char * path, int mode)
1894 {
1895 DWORD attributes;
1896
1897 /* MSVC implementation doesn't recognize D_OK. */
1898 path = map_w32_filename (path, NULL);
1899 if (is_unc_volume (path))
1900 {
1901 attributes = unc_volume_file_attributes (path);
1902 if (attributes == -1) {
1903 errno = EACCES;
1904 return -1;
1905 }
1906 }
1907 else if ((attributes = GetFileAttributes (path)) == -1)
1908 {
1909 /* Should try mapping GetLastError to errno; for now just indicate
1910 that path doesn't exist. */
1911 errno = EACCES;
1912 return -1;
1913 }
1914 if ((mode & X_OK) != 0 && !is_exec (path))
1915 {
1916 errno = EACCES;
1917 return -1;
1918 }
1919 if ((mode & W_OK) != 0 && (attributes & FILE_ATTRIBUTE_READONLY) != 0)
1920 {
1921 errno = EACCES;
1922 return -1;
1923 }
1924 if ((mode & D_OK) != 0 && (attributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
1925 {
1926 errno = EACCES;
1927 return -1;
1928 }
1929 return 0;
1930 }
1931
1932 int
1933 sys_chdir (const char * path)
1934 {
1935 return _chdir (map_w32_filename (path, NULL));
1936 }
1937
1938 int
1939 sys_chmod (const char * path, int mode)
1940 {
1941 return _chmod (map_w32_filename (path, NULL), mode);
1942 }
1943
1944 int
1945 sys_chown (const char *path, uid_t owner, gid_t group)
1946 {
1947 if (sys_chmod (path, _S_IREAD) == -1) /* check if file exists */
1948 return -1;
1949 return 0;
1950 }
1951
1952 int
1953 sys_creat (const char * path, int mode)
1954 {
1955 return _creat (map_w32_filename (path, NULL), mode);
1956 }
1957
1958 FILE *
1959 sys_fopen(const char * path, const char * mode)
1960 {
1961 int fd;
1962 int oflag;
1963 const char * mode_save = mode;
1964
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. */
1968
1969 if (mode[0] == 'r')
1970 oflag = O_RDONLY;
1971 else if (mode[0] == 'w' || mode[0] == 'a')
1972 oflag = O_WRONLY | O_CREAT | O_TRUNC;
1973 else
1974 return NULL;
1975
1976 /* Only do simplistic option parsing. */
1977 while (*++mode)
1978 if (mode[0] == '+')
1979 {
1980 oflag &= ~(O_RDONLY | O_WRONLY);
1981 oflag |= O_RDWR;
1982 }
1983 else if (mode[0] == 'b')
1984 {
1985 oflag &= ~O_TEXT;
1986 oflag |= O_BINARY;
1987 }
1988 else if (mode[0] == 't')
1989 {
1990 oflag &= ~O_BINARY;
1991 oflag |= O_TEXT;
1992 }
1993 else break;
1994
1995 fd = _open (map_w32_filename (path, NULL), oflag | _O_NOINHERIT, 0644);
1996 if (fd < 0)
1997 return NULL;
1998
1999 return _fdopen (fd, mode_save);
2000 }
2001
2002 /* This only works on NTFS volumes, but is useful to have. */
2003 int
2004 sys_link (const char * old, const char * new)
2005 {
2006 HANDLE fileh;
2007 int result = -1;
2008 char oldname[MAX_PATH], newname[MAX_PATH];
2009
2010 if (old == NULL || new == NULL)
2011 {
2012 errno = ENOENT;
2013 return -1;
2014 }
2015
2016 strcpy (oldname, map_w32_filename (old, NULL));
2017 strcpy (newname, map_w32_filename (new, NULL));
2018
2019 fileh = CreateFile (oldname, 0, 0, NULL, OPEN_EXISTING,
2020 FILE_FLAG_BACKUP_SEMANTICS, NULL);
2021 if (fileh != INVALID_HANDLE_VALUE)
2022 {
2023 int wlen;
2024
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
2030 stream data. */
2031
2032 struct {
2033 WIN32_STREAM_ID wid;
2034 WCHAR wbuffer[MAX_PATH]; /* extra space for link name */
2035 } data;
2036
2037 wlen = MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, newname, -1,
2038 data.wid.cStreamName, MAX_PATH);
2039 if (wlen > 0)
2040 {
2041 LPVOID context = NULL;
2042 DWORD wbytes = 0;
2043
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;
2049
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))
2055 {
2056 /* succeeded */
2057 result = 0;
2058 }
2059 else
2060 {
2061 /* Should try mapping GetLastError to errno; for now just
2062 indicate a general error (eg. links not supported). */
2063 errno = EINVAL; // perhaps EMLINK?
2064 }
2065 }
2066
2067 CloseHandle (fileh);
2068 }
2069 else
2070 errno = ENOENT;
2071
2072 return result;
2073 }
2074
2075 int
2076 sys_mkdir (const char * path)
2077 {
2078 return _mkdir (map_w32_filename (path, NULL));
2079 }
2080
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
2084 string.
2085
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. */
2090 char *
2091 sys_mktemp (char * template)
2092 {
2093 char * p;
2094 int i;
2095 unsigned uid = GetCurrentThreadId ();
2096 static char first_char[] = "abcdefghijklmnopqrstuvwyz0123456789!%-_@#";
2097
2098 if (template == NULL)
2099 return NULL;
2100 p = template + strlen (template);
2101 i = 5;
2102 /* replace up to the last 5 X's with uid in decimal */
2103 while (--p >= template && p[0] == 'X' && --i >= 0)
2104 {
2105 p[0] = '0' + uid % 10;
2106 uid /= 10;
2107 }
2108
2109 if (i < 0 && p[0] == 'X')
2110 {
2111 i = 0;
2112 do
2113 {
2114 int save_errno = errno;
2115 p[0] = first_char[i];
2116 if (sys_access (template, 0) < 0)
2117 {
2118 errno = save_errno;
2119 return template;
2120 }
2121 }
2122 while (++i < sizeof (first_char));
2123 }
2124
2125 /* Template is badly formed or else we can't generate a unique name,
2126 so return empty string */
2127 template[0] = 0;
2128 return template;
2129 }
2130
2131 int
2132 sys_open (const char * path, int oflag, int mode)
2133 {
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
2137 non-inheritable. */
2138 int res = _open (mpath, (oflag & ~_O_CREAT) | _O_NOINHERIT, mode);
2139 if (res >= 0)
2140 return res;
2141 return _open (mpath, oflag | _O_NOINHERIT, mode);
2142 }
2143
2144 int
2145 sys_rename (const char * oldname, const char * newname)
2146 {
2147 BOOL result;
2148 char temp[MAX_PATH];
2149
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.
2154
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.
2159
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. */
2162
2163 strcpy (temp, map_w32_filename (oldname, NULL));
2164
2165 if (os_subtype == OS_WIN95)
2166 {
2167 char * o;
2168 char * p;
2169 int i = 0;
2170
2171 oldname = map_w32_filename (oldname, NULL);
2172 if (o = strrchr (oldname, '\\'))
2173 o++;
2174 else
2175 o = (char *) oldname;
2176
2177 if (p = strrchr (temp, '\\'))
2178 p++;
2179 else
2180 p = temp;
2181
2182 do
2183 {
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);
2187 i++;
2188 result = rename (oldname, temp);
2189 }
2190 /* This loop must surely terminate! */
2191 while (result < 0 && errno == EEXIST);
2192 if (result < 0)
2193 return -1;
2194 }
2195
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).
2198
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.) */
2206
2207 newname = map_w32_filename (newname, NULL);
2208 result = rename (temp, newname);
2209
2210 if (result < 0
2211 && errno == EEXIST
2212 && _chmod (newname, 0666) == 0
2213 && _unlink (newname) == 0)
2214 result = rename (temp, newname);
2215
2216 return result;
2217 }
2218
2219 int
2220 sys_rmdir (const char * path)
2221 {
2222 return _rmdir (map_w32_filename (path, NULL));
2223 }
2224
2225 int
2226 sys_unlink (const char * path)
2227 {
2228 path = map_w32_filename (path, NULL);
2229
2230 /* On Unix, unlink works without write permission. */
2231 _chmod (path, 0666);
2232 return _unlink (path);
2233 }
2234
2235 static FILETIME utc_base_ft;
2236 static long double utc_base;
2237 static int init = 0;
2238
2239 static time_t
2240 convert_time (FILETIME ft)
2241 {
2242 long double ret;
2243
2244 if (!init)
2245 {
2246 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
2247 SYSTEMTIME st;
2248
2249 st.wYear = 1970;
2250 st.wMonth = 1;
2251 st.wDay = 1;
2252 st.wHour = 0;
2253 st.wMinute = 0;
2254 st.wSecond = 0;
2255 st.wMilliseconds = 0;
2256
2257 SystemTimeToFileTime (&st, &utc_base_ft);
2258 utc_base = (long double) utc_base_ft.dwHighDateTime
2259 * 4096 * 1024 * 1024 + utc_base_ft.dwLowDateTime;
2260 init = 1;
2261 }
2262
2263 if (CompareFileTime (&ft, &utc_base_ft) < 0)
2264 return 0;
2265
2266 ret = (long double) ft.dwHighDateTime * 4096 * 1024 * 1024 + ft.dwLowDateTime;
2267 ret -= utc_base;
2268 return (time_t) (ret * 1e-7);
2269 }
2270
2271 void
2272 convert_from_time_t (time_t time, FILETIME * pft)
2273 {
2274 long double tmp;
2275
2276 if (!init)
2277 {
2278 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
2279 SYSTEMTIME st;
2280
2281 st.wYear = 1970;
2282 st.wMonth = 1;
2283 st.wDay = 1;
2284 st.wHour = 0;
2285 st.wMinute = 0;
2286 st.wSecond = 0;
2287 st.wMilliseconds = 0;
2288
2289 SystemTimeToFileTime (&st, &utc_base_ft);
2290 utc_base = (long double) utc_base_ft.dwHighDateTime
2291 * 4096 * 1024 * 1024 + utc_base_ft.dwLowDateTime;
2292 init = 1;
2293 }
2294
2295 /* time in 100ns units since 1-Jan-1601 */
2296 tmp = (long double) time * 1e7 + utc_base;
2297 pft->dwHighDateTime = (DWORD) (tmp / (4096.0 * 1024 * 1024));
2298 pft->dwLowDateTime = (DWORD) (tmp - (4096.0 * 1024 * 1024) * pft->dwHighDateTime);
2299 }
2300
2301 #if 0
2302 /* No reason to keep this; faking inode values either by hashing or even
2303 using the file index from GetInformationByHandle, is not perfect and
2304 so by default Emacs doesn't use the inode values on Windows.
2305 Instead, we now determine file-truename correctly (except for
2306 possible drive aliasing etc). */
2307
2308 /* Modified version of "PJW" algorithm (see the "Dragon" compiler book). */
2309 static unsigned
2310 hashval (const unsigned char * str)
2311 {
2312 unsigned h = 0;
2313 while (*str)
2314 {
2315 h = (h << 4) + *str++;
2316 h ^= (h >> 28);
2317 }
2318 return h;
2319 }
2320
2321 /* Return the hash value of the canonical pathname, excluding the
2322 drive/UNC header, to get a hopefully unique inode number. */
2323 static DWORD
2324 generate_inode_val (const char * name)
2325 {
2326 char fullname[ MAX_PATH ];
2327 char * p;
2328 unsigned hash;
2329
2330 /* Get the truly canonical filename, if it exists. (Note: this
2331 doesn't resolve aliasing due to subst commands, or recognise hard
2332 links. */
2333 if (!w32_get_long_filename ((char *)name, fullname, MAX_PATH))
2334 abort ();
2335
2336 parse_root (fullname, &p);
2337 /* Normal W32 filesystems are still case insensitive. */
2338 _strlwr (p);
2339 return hashval (p);
2340 }
2341
2342 #endif
2343
2344 /* MSVC stat function can't cope with UNC names and has other bugs, so
2345 replace it with our own. This also allows us to calculate consistent
2346 inode values without hacks in the main Emacs code. */
2347 int
2348 stat (const char * path, struct stat * buf)
2349 {
2350 char *name, *r;
2351 WIN32_FIND_DATA wfd;
2352 HANDLE fh;
2353 DWORD fake_inode;
2354 int permission;
2355 int len;
2356 int rootdir = FALSE;
2357
2358 if (path == NULL || buf == NULL)
2359 {
2360 errno = EFAULT;
2361 return -1;
2362 }
2363
2364 name = (char *) map_w32_filename (path, &path);
2365 /* must be valid filename, no wild cards or other invalid characters */
2366 if (strpbrk (name, "*?|<>\""))
2367 {
2368 errno = ENOENT;
2369 return -1;
2370 }
2371
2372 /* If name is "c:/.." or "/.." then stat "c:/" or "/". */
2373 r = IS_DEVICE_SEP (name[1]) ? &name[2] : name;
2374 if (IS_DIRECTORY_SEP (r[0]) && r[1] == '.' && r[2] == '.' && r[3] == '\0')
2375 {
2376 r[1] = r[2] = '\0';
2377 }
2378
2379 /* Remove trailing directory separator, unless name is the root
2380 directory of a drive or UNC volume in which case ensure there
2381 is a trailing separator. */
2382 len = strlen (name);
2383 rootdir = (path >= name + len - 1
2384 && (IS_DIRECTORY_SEP (*path) || *path == 0));
2385 name = strcpy (alloca (len + 2), name);
2386
2387 if (is_unc_volume (name))
2388 {
2389 DWORD attrs = unc_volume_file_attributes (name);
2390
2391 if (attrs == -1)
2392 return -1;
2393
2394 memset (&wfd, 0, sizeof (wfd));
2395 wfd.dwFileAttributes = attrs;
2396 wfd.ftCreationTime = utc_base_ft;
2397 wfd.ftLastAccessTime = utc_base_ft;
2398 wfd.ftLastWriteTime = utc_base_ft;
2399 strcpy (wfd.cFileName, name);
2400 }
2401 else if (rootdir)
2402 {
2403 if (!IS_DIRECTORY_SEP (name[len-1]))
2404 strcat (name, "\\");
2405 if (GetDriveType (name) < 2)
2406 {
2407 errno = ENOENT;
2408 return -1;
2409 }
2410 memset (&wfd, 0, sizeof (wfd));
2411 wfd.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY;
2412 wfd.ftCreationTime = utc_base_ft;
2413 wfd.ftLastAccessTime = utc_base_ft;
2414 wfd.ftLastWriteTime = utc_base_ft;
2415 strcpy (wfd.cFileName, name);
2416 }
2417 else
2418 {
2419 if (IS_DIRECTORY_SEP (name[len-1]))
2420 name[len - 1] = 0;
2421
2422 /* (This is hacky, but helps when doing file completions on
2423 network drives.) Optimize by using information available from
2424 active readdir if possible. */
2425 len = strlen (dir_pathname);
2426 if (IS_DIRECTORY_SEP (dir_pathname[len-1]))
2427 len--;
2428 if (dir_find_handle != INVALID_HANDLE_VALUE
2429 && strnicmp (name, dir_pathname, len) == 0
2430 && IS_DIRECTORY_SEP (name[len])
2431 && stricmp (name + len + 1, dir_static.d_name) == 0)
2432 {
2433 /* This was the last entry returned by readdir. */
2434 wfd = dir_find_data;
2435 }
2436 else
2437 {
2438 fh = FindFirstFile (name, &wfd);
2439 if (fh == INVALID_HANDLE_VALUE)
2440 {
2441 errno = ENOENT;
2442 return -1;
2443 }
2444 FindClose (fh);
2445 }
2446 }
2447
2448 if (!NILP (Vw32_get_true_file_attributes)
2449 /* No access rights required to get info. */
2450 && (fh = CreateFile (name, 0, 0, NULL, OPEN_EXISTING,
2451 FILE_FLAG_BACKUP_SEMANTICS, NULL))
2452 != INVALID_HANDLE_VALUE)
2453 {
2454 /* This is more accurate in terms of gettting the correct number
2455 of links, but is quite slow (it is noticable when Emacs is
2456 making a list of file name completions). */
2457 BY_HANDLE_FILE_INFORMATION info;
2458
2459 if (GetFileInformationByHandle (fh, &info))
2460 {
2461 buf->st_nlink = info.nNumberOfLinks;
2462 /* Might as well use file index to fake inode values, but this
2463 is not guaranteed to be unique unless we keep a handle open
2464 all the time (even then there are situations where it is
2465 not unique). Reputedly, there are at most 48 bits of info
2466 (on NTFS, presumably less on FAT). */
2467 fake_inode = info.nFileIndexLow ^ info.nFileIndexHigh;
2468 }
2469 else
2470 {
2471 buf->st_nlink = 1;
2472 fake_inode = 0;
2473 }
2474
2475 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
2476 {
2477 buf->st_mode = _S_IFDIR;
2478 }
2479 else
2480 {
2481 switch (GetFileType (fh))
2482 {
2483 case FILE_TYPE_DISK:
2484 buf->st_mode = _S_IFREG;
2485 break;
2486 case FILE_TYPE_PIPE:
2487 buf->st_mode = _S_IFIFO;
2488 break;
2489 case FILE_TYPE_CHAR:
2490 case FILE_TYPE_UNKNOWN:
2491 default:
2492 buf->st_mode = _S_IFCHR;
2493 }
2494 }
2495 CloseHandle (fh);
2496 }
2497 else
2498 {
2499 /* Don't bother to make this information more accurate. */
2500 buf->st_mode = (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ?
2501 _S_IFDIR : _S_IFREG;
2502 buf->st_nlink = 1;
2503 fake_inode = 0;
2504 }
2505
2506 #if 0
2507 /* Not sure if there is any point in this. */
2508 if (!NILP (Vw32_generate_fake_inodes))
2509 fake_inode = generate_inode_val (name);
2510 else if (fake_inode == 0)
2511 {
2512 /* For want of something better, try to make everything unique. */
2513 static DWORD gen_num = 0;
2514 fake_inode = ++gen_num;
2515 }
2516 #endif
2517
2518 /* MSVC defines _ino_t to be short; other libc's might not. */
2519 if (sizeof (buf->st_ino) == 2)
2520 buf->st_ino = fake_inode ^ (fake_inode >> 16);
2521 else
2522 buf->st_ino = fake_inode;
2523
2524 /* consider files to belong to current user */
2525 buf->st_uid = the_passwd.pw_uid;
2526 buf->st_gid = the_passwd.pw_gid;
2527
2528 /* volume_info is set indirectly by map_w32_filename */
2529 buf->st_dev = volume_info.serialnum;
2530 buf->st_rdev = volume_info.serialnum;
2531
2532
2533 buf->st_size = wfd.nFileSizeLow;
2534
2535 /* Convert timestamps to Unix format. */
2536 buf->st_mtime = convert_time (wfd.ftLastWriteTime);
2537 buf->st_atime = convert_time (wfd.ftLastAccessTime);
2538 if (buf->st_atime == 0) buf->st_atime = buf->st_mtime;
2539 buf->st_ctime = convert_time (wfd.ftCreationTime);
2540 if (buf->st_ctime == 0) buf->st_ctime = buf->st_mtime;
2541
2542 /* determine rwx permissions */
2543 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
2544 permission = _S_IREAD;
2545 else
2546 permission = _S_IREAD | _S_IWRITE;
2547
2548 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
2549 permission |= _S_IEXEC;
2550 else if (is_exec (name))
2551 permission |= _S_IEXEC;
2552
2553 buf->st_mode |= permission | (permission >> 3) | (permission >> 6);
2554
2555 return 0;
2556 }
2557
2558 /* Provide fstat and utime as well as stat for consistent handling of
2559 file timestamps. */
2560 int
2561 fstat (int desc, struct stat * buf)
2562 {
2563 HANDLE fh = (HANDLE) _get_osfhandle (desc);
2564 BY_HANDLE_FILE_INFORMATION info;
2565 DWORD fake_inode;
2566 int permission;
2567
2568 switch (GetFileType (fh) & ~FILE_TYPE_REMOTE)
2569 {
2570 case FILE_TYPE_DISK:
2571 buf->st_mode = _S_IFREG;
2572 if (!GetFileInformationByHandle (fh, &info))
2573 {
2574 errno = EACCES;
2575 return -1;
2576 }
2577 break;
2578 case FILE_TYPE_PIPE:
2579 buf->st_mode = _S_IFIFO;
2580 goto non_disk;
2581 case FILE_TYPE_CHAR:
2582 case FILE_TYPE_UNKNOWN:
2583 default:
2584 buf->st_mode = _S_IFCHR;
2585 non_disk:
2586 memset (&info, 0, sizeof (info));
2587 info.dwFileAttributes = 0;
2588 info.ftCreationTime = utc_base_ft;
2589 info.ftLastAccessTime = utc_base_ft;
2590 info.ftLastWriteTime = utc_base_ft;
2591 }
2592
2593 if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
2594 buf->st_mode = _S_IFDIR;
2595
2596 buf->st_nlink = info.nNumberOfLinks;
2597 /* Might as well use file index to fake inode values, but this
2598 is not guaranteed to be unique unless we keep a handle open
2599 all the time (even then there are situations where it is
2600 not unique). Reputedly, there are at most 48 bits of info
2601 (on NTFS, presumably less on FAT). */
2602 fake_inode = info.nFileIndexLow ^ info.nFileIndexHigh;
2603
2604 /* MSVC defines _ino_t to be short; other libc's might not. */
2605 if (sizeof (buf->st_ino) == 2)
2606 buf->st_ino = fake_inode ^ (fake_inode >> 16);
2607 else
2608 buf->st_ino = fake_inode;
2609
2610 /* consider files to belong to current user */
2611 buf->st_uid = 0;
2612 buf->st_gid = 0;
2613
2614 buf->st_dev = info.dwVolumeSerialNumber;
2615 buf->st_rdev = info.dwVolumeSerialNumber;
2616
2617 buf->st_size = info.nFileSizeLow;
2618
2619 /* Convert timestamps to Unix format. */
2620 buf->st_mtime = convert_time (info.ftLastWriteTime);
2621 buf->st_atime = convert_time (info.ftLastAccessTime);
2622 if (buf->st_atime == 0) buf->st_atime = buf->st_mtime;
2623 buf->st_ctime = convert_time (info.ftCreationTime);
2624 if (buf->st_ctime == 0) buf->st_ctime = buf->st_mtime;
2625
2626 /* determine rwx permissions */
2627 if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
2628 permission = _S_IREAD;
2629 else
2630 permission = _S_IREAD | _S_IWRITE;
2631
2632 if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
2633 permission |= _S_IEXEC;
2634 else
2635 {
2636 #if 0 /* no way of knowing the filename */
2637 char * p = strrchr (name, '.');
2638 if (p != NULL &&
2639 (stricmp (p, ".exe") == 0 ||
2640 stricmp (p, ".com") == 0 ||
2641 stricmp (p, ".bat") == 0 ||
2642 stricmp (p, ".cmd") == 0))
2643 permission |= _S_IEXEC;
2644 #endif
2645 }
2646
2647 buf->st_mode |= permission | (permission >> 3) | (permission >> 6);
2648
2649 return 0;
2650 }
2651
2652 int
2653 utime (const char *name, struct utimbuf *times)
2654 {
2655 struct utimbuf deftime;
2656 HANDLE fh;
2657 FILETIME mtime;
2658 FILETIME atime;
2659
2660 if (times == NULL)
2661 {
2662 deftime.modtime = deftime.actime = time (NULL);
2663 times = &deftime;
2664 }
2665
2666 /* Need write access to set times. */
2667 fh = CreateFile (name, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
2668 0, OPEN_EXISTING, 0, NULL);
2669 if (fh)
2670 {
2671 convert_from_time_t (times->actime, &atime);
2672 convert_from_time_t (times->modtime, &mtime);
2673 if (!SetFileTime (fh, NULL, &atime, &mtime))
2674 {
2675 CloseHandle (fh);
2676 errno = EACCES;
2677 return -1;
2678 }
2679 CloseHandle (fh);
2680 }
2681 else
2682 {
2683 errno = EINVAL;
2684 return -1;
2685 }
2686 return 0;
2687 }
2688
2689 #ifdef HAVE_SOCKETS
2690
2691 /* Wrappers for winsock functions to map between our file descriptors
2692 and winsock's handles; also set h_errno for convenience.
2693
2694 To allow Emacs to run on systems which don't have winsock support
2695 installed, we dynamically link to winsock on startup if present, and
2696 otherwise provide the minimum necessary functionality
2697 (eg. gethostname). */
2698
2699 /* function pointers for relevant socket functions */
2700 int (PASCAL *pfn_WSAStartup) (WORD wVersionRequired, LPWSADATA lpWSAData);
2701 void (PASCAL *pfn_WSASetLastError) (int iError);
2702 int (PASCAL *pfn_WSAGetLastError) (void);
2703 int (PASCAL *pfn_WSAEventSelect) (SOCKET s, HANDLE hEventObject, long lNetworkEvents);
2704 HANDLE (PASCAL *pfn_WSACreateEvent) (void);
2705 int (PASCAL *pfn_WSACloseEvent) (HANDLE hEvent);
2706 int (PASCAL *pfn_socket) (int af, int type, int protocol);
2707 int (PASCAL *pfn_bind) (SOCKET s, const struct sockaddr *addr, int namelen);
2708 int (PASCAL *pfn_connect) (SOCKET s, const struct sockaddr *addr, int namelen);
2709 int (PASCAL *pfn_ioctlsocket) (SOCKET s, long cmd, u_long *argp);
2710 int (PASCAL *pfn_recv) (SOCKET s, char * buf, int len, int flags);
2711 int (PASCAL *pfn_send) (SOCKET s, const char * buf, int len, int flags);
2712 int (PASCAL *pfn_closesocket) (SOCKET s);
2713 int (PASCAL *pfn_shutdown) (SOCKET s, int how);
2714 int (PASCAL *pfn_WSACleanup) (void);
2715
2716 u_short (PASCAL *pfn_htons) (u_short hostshort);
2717 u_short (PASCAL *pfn_ntohs) (u_short netshort);
2718 unsigned long (PASCAL *pfn_inet_addr) (const char * cp);
2719 int (PASCAL *pfn_gethostname) (char * name, int namelen);
2720 struct hostent * (PASCAL *pfn_gethostbyname) (const char * name);
2721 struct servent * (PASCAL *pfn_getservbyname) (const char * name, const char * proto);
2722 int (PASCAL *pfn_getpeername) (SOCKET s, struct sockaddr *addr, int * namelen);
2723 int (PASCAL *pfn_setsockopt) (SOCKET s, int level, int optname,
2724 const char * optval, int optlen);
2725 int (PASCAL *pfn_listen) (SOCKET s, int backlog);
2726 int (PASCAL *pfn_getsockname) (SOCKET s, struct sockaddr * name,
2727 int * namelen);
2728 SOCKET (PASCAL *pfn_accept) (SOCKET s, struct sockaddr * addr, int * addrlen);
2729 int (PASCAL *pfn_recvfrom) (SOCKET s, char * buf, int len, int flags,
2730 struct sockaddr * from, int * fromlen);
2731 int (PASCAL *pfn_sendto) (SOCKET s, const char * buf, int len, int flags,
2732 const struct sockaddr * to, int tolen);
2733
2734 /* SetHandleInformation is only needed to make sockets non-inheritable. */
2735 BOOL (WINAPI *pfn_SetHandleInformation) (HANDLE object, DWORD mask, DWORD flags);
2736 #ifndef HANDLE_FLAG_INHERIT
2737 #define HANDLE_FLAG_INHERIT 1
2738 #endif
2739
2740 HANDLE winsock_lib;
2741 static int winsock_inuse;
2742
2743 BOOL
2744 term_winsock (void)
2745 {
2746 if (winsock_lib != NULL && winsock_inuse == 0)
2747 {
2748 /* Not sure what would cause WSAENETDOWN, or even if it can happen
2749 after WSAStartup returns successfully, but it seems reasonable
2750 to allow unloading winsock anyway in that case. */
2751 if (pfn_WSACleanup () == 0 ||
2752 pfn_WSAGetLastError () == WSAENETDOWN)
2753 {
2754 if (FreeLibrary (winsock_lib))
2755 winsock_lib = NULL;
2756 return TRUE;
2757 }
2758 }
2759 return FALSE;
2760 }
2761
2762 BOOL
2763 init_winsock (int load_now)
2764 {
2765 WSADATA winsockData;
2766
2767 if (winsock_lib != NULL)
2768 return TRUE;
2769
2770 pfn_SetHandleInformation = NULL;
2771 pfn_SetHandleInformation
2772 = (void *) GetProcAddress (GetModuleHandle ("kernel32.dll"),
2773 "SetHandleInformation");
2774
2775 winsock_lib = LoadLibrary ("Ws2_32.dll");
2776
2777 if (winsock_lib != NULL)
2778 {
2779 /* dynamically link to socket functions */
2780
2781 #define LOAD_PROC(fn) \
2782 if ((pfn_##fn = (void *) GetProcAddress (winsock_lib, #fn)) == NULL) \
2783 goto fail;
2784
2785 LOAD_PROC( WSAStartup );
2786 LOAD_PROC( WSASetLastError );
2787 LOAD_PROC( WSAGetLastError );
2788 LOAD_PROC( WSAEventSelect );
2789 LOAD_PROC( WSACreateEvent );
2790 LOAD_PROC( WSACloseEvent );
2791 LOAD_PROC( socket );
2792 LOAD_PROC( bind );
2793 LOAD_PROC( connect );
2794 LOAD_PROC( ioctlsocket );
2795 LOAD_PROC( recv );
2796 LOAD_PROC( send );
2797 LOAD_PROC( closesocket );
2798 LOAD_PROC( shutdown );
2799 LOAD_PROC( htons );
2800 LOAD_PROC( ntohs );
2801 LOAD_PROC( inet_addr );
2802 LOAD_PROC( gethostname );
2803 LOAD_PROC( gethostbyname );
2804 LOAD_PROC( getservbyname );
2805 LOAD_PROC( getpeername );
2806 LOAD_PROC( WSACleanup );
2807 LOAD_PROC( setsockopt );
2808 LOAD_PROC( listen );
2809 LOAD_PROC( getsockname );
2810 LOAD_PROC( accept );
2811 LOAD_PROC( recvfrom );
2812 LOAD_PROC( sendto );
2813 #undef LOAD_PROC
2814
2815 /* specify version 1.1 of winsock */
2816 if (pfn_WSAStartup (0x101, &winsockData) == 0)
2817 {
2818 if (winsockData.wVersion != 0x101)
2819 goto fail;
2820
2821 if (!load_now)
2822 {
2823 /* Report that winsock exists and is usable, but leave
2824 socket functions disabled. I am assuming that calling
2825 WSAStartup does not require any network interaction,
2826 and in particular does not cause or require a dial-up
2827 connection to be established. */
2828
2829 pfn_WSACleanup ();
2830 FreeLibrary (winsock_lib);
2831 winsock_lib = NULL;
2832 }
2833 winsock_inuse = 0;
2834 return TRUE;
2835 }
2836
2837 fail:
2838 FreeLibrary (winsock_lib);
2839 winsock_lib = NULL;
2840 }
2841
2842 return FALSE;
2843 }
2844
2845
2846 int h_errno = 0;
2847
2848 /* function to set h_errno for compatability; map winsock error codes to
2849 normal system codes where they overlap (non-overlapping definitions
2850 are already in <sys/socket.h> */
2851 static void set_errno ()
2852 {
2853 if (winsock_lib == NULL)
2854 h_errno = EINVAL;
2855 else
2856 h_errno = pfn_WSAGetLastError ();
2857
2858 switch (h_errno)
2859 {
2860 case WSAEACCES: h_errno = EACCES; break;
2861 case WSAEBADF: h_errno = EBADF; break;
2862 case WSAEFAULT: h_errno = EFAULT; break;
2863 case WSAEINTR: h_errno = EINTR; break;
2864 case WSAEINVAL: h_errno = EINVAL; break;
2865 case WSAEMFILE: h_errno = EMFILE; break;
2866 case WSAENAMETOOLONG: h_errno = ENAMETOOLONG; break;
2867 case WSAENOTEMPTY: h_errno = ENOTEMPTY; break;
2868 }
2869 errno = h_errno;
2870 }
2871
2872 static void check_errno ()
2873 {
2874 if (h_errno == 0 && winsock_lib != NULL)
2875 pfn_WSASetLastError (0);
2876 }
2877
2878 /* Extend strerror to handle the winsock-specific error codes. */
2879 struct {
2880 int errnum;
2881 char * msg;
2882 } _wsa_errlist[] = {
2883 WSAEINTR , "Interrupted function call",
2884 WSAEBADF , "Bad file descriptor",
2885 WSAEACCES , "Permission denied",
2886 WSAEFAULT , "Bad address",
2887 WSAEINVAL , "Invalid argument",
2888 WSAEMFILE , "Too many open files",
2889
2890 WSAEWOULDBLOCK , "Resource temporarily unavailable",
2891 WSAEINPROGRESS , "Operation now in progress",
2892 WSAEALREADY , "Operation already in progress",
2893 WSAENOTSOCK , "Socket operation on non-socket",
2894 WSAEDESTADDRREQ , "Destination address required",
2895 WSAEMSGSIZE , "Message too long",
2896 WSAEPROTOTYPE , "Protocol wrong type for socket",
2897 WSAENOPROTOOPT , "Bad protocol option",
2898 WSAEPROTONOSUPPORT , "Protocol not supported",
2899 WSAESOCKTNOSUPPORT , "Socket type not supported",
2900 WSAEOPNOTSUPP , "Operation not supported",
2901 WSAEPFNOSUPPORT , "Protocol family not supported",
2902 WSAEAFNOSUPPORT , "Address family not supported by protocol family",
2903 WSAEADDRINUSE , "Address already in use",
2904 WSAEADDRNOTAVAIL , "Cannot assign requested address",
2905 WSAENETDOWN , "Network is down",
2906 WSAENETUNREACH , "Network is unreachable",
2907 WSAENETRESET , "Network dropped connection on reset",
2908 WSAECONNABORTED , "Software caused connection abort",
2909 WSAECONNRESET , "Connection reset by peer",
2910 WSAENOBUFS , "No buffer space available",
2911 WSAEISCONN , "Socket is already connected",
2912 WSAENOTCONN , "Socket is not connected",
2913 WSAESHUTDOWN , "Cannot send after socket shutdown",
2914 WSAETOOMANYREFS , "Too many references", /* not sure */
2915 WSAETIMEDOUT , "Connection timed out",
2916 WSAECONNREFUSED , "Connection refused",
2917 WSAELOOP , "Network loop", /* not sure */
2918 WSAENAMETOOLONG , "Name is too long",
2919 WSAEHOSTDOWN , "Host is down",
2920 WSAEHOSTUNREACH , "No route to host",
2921 WSAENOTEMPTY , "Buffer not empty", /* not sure */
2922 WSAEPROCLIM , "Too many processes",
2923 WSAEUSERS , "Too many users", /* not sure */
2924 WSAEDQUOT , "Double quote in host name", /* really not sure */
2925 WSAESTALE , "Data is stale", /* not sure */
2926 WSAEREMOTE , "Remote error", /* not sure */
2927
2928 WSASYSNOTREADY , "Network subsystem is unavailable",
2929 WSAVERNOTSUPPORTED , "WINSOCK.DLL version out of range",
2930 WSANOTINITIALISED , "Winsock not initialized successfully",
2931 WSAEDISCON , "Graceful shutdown in progress",
2932 #ifdef WSAENOMORE
2933 WSAENOMORE , "No more operations allowed", /* not sure */
2934 WSAECANCELLED , "Operation cancelled", /* not sure */
2935 WSAEINVALIDPROCTABLE , "Invalid procedure table from service provider",
2936 WSAEINVALIDPROVIDER , "Invalid service provider version number",
2937 WSAEPROVIDERFAILEDINIT , "Unable to initialize a service provider",
2938 WSASYSCALLFAILURE , "System call failured",
2939 WSASERVICE_NOT_FOUND , "Service not found", /* not sure */
2940 WSATYPE_NOT_FOUND , "Class type not found",
2941 WSA_E_NO_MORE , "No more resources available", /* really not sure */
2942 WSA_E_CANCELLED , "Operation already cancelled", /* really not sure */
2943 WSAEREFUSED , "Operation refused", /* not sure */
2944 #endif
2945
2946 WSAHOST_NOT_FOUND , "Host not found",
2947 WSATRY_AGAIN , "Authoritative host not found during name lookup",
2948 WSANO_RECOVERY , "Non-recoverable error during name lookup",
2949 WSANO_DATA , "Valid name, no data record of requested type",
2950
2951 -1, NULL
2952 };
2953
2954 char *
2955 sys_strerror(int error_no)
2956 {
2957 int i;
2958 static char unknown_msg[40];
2959
2960 if (error_no >= 0 && error_no < sys_nerr)
2961 return sys_errlist[error_no];
2962
2963 for (i = 0; _wsa_errlist[i].errnum >= 0; i++)
2964 if (_wsa_errlist[i].errnum == error_no)
2965 return _wsa_errlist[i].msg;
2966
2967 sprintf(unknown_msg, "Unidentified error: %d", error_no);
2968 return unknown_msg;
2969 }
2970
2971 /* [andrewi 3-May-96] I've had conflicting results using both methods,
2972 but I believe the method of keeping the socket handle separate (and
2973 insuring it is not inheritable) is the correct one. */
2974
2975 //#define SOCK_REPLACE_HANDLE
2976
2977 #ifdef SOCK_REPLACE_HANDLE
2978 #define SOCK_HANDLE(fd) ((SOCKET) _get_osfhandle (fd))
2979 #else
2980 #define SOCK_HANDLE(fd) ((SOCKET) fd_info[fd].hnd)
2981 #endif
2982
2983 int socket_to_fd (SOCKET s);
2984
2985 int
2986 sys_socket(int af, int type, int protocol)
2987 {
2988 SOCKET s;
2989
2990 if (winsock_lib == NULL)
2991 {
2992 h_errno = ENETDOWN;
2993 return INVALID_SOCKET;
2994 }
2995
2996 check_errno ();
2997
2998 /* call the real socket function */
2999 s = pfn_socket (af, type, protocol);
3000
3001 if (s != INVALID_SOCKET)
3002 return socket_to_fd (s);
3003
3004 set_errno ();
3005 return -1;
3006 }
3007
3008 /* Convert a SOCKET to a file descriptor. */
3009 int
3010 socket_to_fd (SOCKET s)
3011 {
3012 int fd;
3013 child_process * cp;
3014
3015 /* Although under NT 3.5 _open_osfhandle will accept a socket
3016 handle, if opened with SO_OPENTYPE == SO_SYNCHRONOUS_NONALERT,
3017 that does not work under NT 3.1. However, we can get the same
3018 effect by using a backdoor function to replace an existing
3019 descriptor handle with the one we want. */
3020
3021 /* allocate a file descriptor (with appropriate flags) */
3022 fd = _open ("NUL:", _O_RDWR);
3023 if (fd >= 0)
3024 {
3025 #ifdef SOCK_REPLACE_HANDLE
3026 /* now replace handle to NUL with our socket handle */
3027 CloseHandle ((HANDLE) _get_osfhandle (fd));
3028 _free_osfhnd (fd);
3029 _set_osfhnd (fd, s);
3030 /* setmode (fd, _O_BINARY); */
3031 #else
3032 /* Make a non-inheritable copy of the socket handle. Note
3033 that it is possible that sockets aren't actually kernel
3034 handles, which appears to be the case on Windows 9x when
3035 the MS Proxy winsock client is installed. */
3036 {
3037 /* Apparently there is a bug in NT 3.51 with some service
3038 packs, which prevents using DuplicateHandle to make a
3039 socket handle non-inheritable (causes WSACleanup to
3040 hang). The work-around is to use SetHandleInformation
3041 instead if it is available and implemented. */
3042 if (pfn_SetHandleInformation)
3043 {
3044 pfn_SetHandleInformation ((HANDLE) s, HANDLE_FLAG_INHERIT, 0);
3045 }
3046 else
3047 {
3048 HANDLE parent = GetCurrentProcess ();
3049 HANDLE new_s = INVALID_HANDLE_VALUE;
3050
3051 if (DuplicateHandle (parent,
3052 (HANDLE) s,
3053 parent,
3054 &new_s,
3055 0,
3056 FALSE,
3057 DUPLICATE_SAME_ACCESS))
3058 {
3059 /* It is possible that DuplicateHandle succeeds even
3060 though the socket wasn't really a kernel handle,
3061 because a real handle has the same value. So
3062 test whether the new handle really is a socket. */
3063 long nonblocking = 0;
3064 if (pfn_ioctlsocket ((SOCKET) new_s, FIONBIO, &nonblocking) == 0)
3065 {
3066 pfn_closesocket (s);
3067 s = (SOCKET) new_s;
3068 }
3069 else
3070 {
3071 CloseHandle (new_s);
3072 }
3073 }
3074 }
3075 }
3076 fd_info[fd].hnd = (HANDLE) s;
3077 #endif
3078
3079 /* set our own internal flags */
3080 fd_info[fd].flags = FILE_SOCKET | FILE_BINARY | FILE_READ | FILE_WRITE;
3081
3082 cp = new_child ();
3083 if (cp)
3084 {
3085 cp->fd = fd;
3086 cp->status = STATUS_READ_ACKNOWLEDGED;
3087
3088 /* attach child_process to fd_info */
3089 if (fd_info[ fd ].cp != NULL)
3090 {
3091 DebPrint (("sys_socket: fd_info[%d] apparently in use!\n", fd));
3092 abort ();
3093 }
3094
3095 fd_info[ fd ].cp = cp;
3096
3097 /* success! */
3098 winsock_inuse++; /* count open sockets */
3099 return fd;
3100 }
3101
3102 /* clean up */
3103 _close (fd);
3104 }
3105 pfn_closesocket (s);
3106 h_errno = EMFILE;
3107 return -1;
3108 }
3109
3110
3111 int
3112 sys_bind (int s, const struct sockaddr * addr, int namelen)
3113 {
3114 if (winsock_lib == NULL)
3115 {
3116 h_errno = ENOTSOCK;
3117 return SOCKET_ERROR;
3118 }
3119
3120 check_errno ();
3121 if (fd_info[s].flags & FILE_SOCKET)
3122 {
3123 int rc = pfn_bind (SOCK_HANDLE (s), addr, namelen);
3124 if (rc == SOCKET_ERROR)
3125 set_errno ();
3126 return rc;
3127 }
3128 h_errno = ENOTSOCK;
3129 return SOCKET_ERROR;
3130 }
3131
3132
3133 int
3134 sys_connect (int s, const struct sockaddr * name, int namelen)
3135 {
3136 if (winsock_lib == NULL)
3137 {
3138 h_errno = ENOTSOCK;
3139 return SOCKET_ERROR;
3140 }
3141
3142 check_errno ();
3143 if (fd_info[s].flags & FILE_SOCKET)
3144 {
3145 int rc = pfn_connect (SOCK_HANDLE (s), name, namelen);
3146 if (rc == SOCKET_ERROR)
3147 set_errno ();
3148 return rc;
3149 }
3150 h_errno = ENOTSOCK;
3151 return SOCKET_ERROR;
3152 }
3153
3154 u_short
3155 sys_htons (u_short hostshort)
3156 {
3157 return (winsock_lib != NULL) ?
3158 pfn_htons (hostshort) : hostshort;
3159 }
3160
3161 u_short
3162 sys_ntohs (u_short netshort)
3163 {
3164 return (winsock_lib != NULL) ?
3165 pfn_ntohs (netshort) : netshort;
3166 }
3167
3168 unsigned long
3169 sys_inet_addr (const char * cp)
3170 {
3171 return (winsock_lib != NULL) ?
3172 pfn_inet_addr (cp) : INADDR_NONE;
3173 }
3174
3175 int
3176 sys_gethostname (char * name, int namelen)
3177 {
3178 if (winsock_lib != NULL)
3179 return pfn_gethostname (name, namelen);
3180
3181 if (namelen > MAX_COMPUTERNAME_LENGTH)
3182 return !GetComputerName (name, (DWORD *)&namelen);
3183
3184 h_errno = EFAULT;
3185 return SOCKET_ERROR;
3186 }
3187
3188 struct hostent *
3189 sys_gethostbyname(const char * name)
3190 {
3191 struct hostent * host;
3192
3193 if (winsock_lib == NULL)
3194 {
3195 h_errno = ENETDOWN;
3196 return NULL;
3197 }
3198
3199 check_errno ();
3200 host = pfn_gethostbyname (name);
3201 if (!host)
3202 set_errno ();
3203 return host;
3204 }
3205
3206 struct servent *
3207 sys_getservbyname(const char * name, const char * proto)
3208 {
3209 struct servent * serv;
3210
3211 if (winsock_lib == NULL)
3212 {
3213 h_errno = ENETDOWN;
3214 return NULL;
3215 }
3216
3217 check_errno ();
3218 serv = pfn_getservbyname (name, proto);
3219 if (!serv)
3220 set_errno ();
3221 return serv;
3222 }
3223
3224 int
3225 sys_getpeername (int s, struct sockaddr *addr, int * namelen)
3226 {
3227 if (winsock_lib == NULL)
3228 {
3229 h_errno = ENETDOWN;
3230 return SOCKET_ERROR;
3231 }
3232
3233 check_errno ();
3234 if (fd_info[s].flags & FILE_SOCKET)
3235 {
3236 int rc = pfn_getpeername (SOCK_HANDLE (s), addr, namelen);
3237 if (rc == SOCKET_ERROR)
3238 set_errno ();
3239 return rc;
3240 }
3241 h_errno = ENOTSOCK;
3242 return SOCKET_ERROR;
3243 }
3244
3245
3246 int
3247 sys_shutdown (int s, int how)
3248 {
3249 if (winsock_lib == NULL)
3250 {
3251 h_errno = ENETDOWN;
3252 return SOCKET_ERROR;
3253 }
3254
3255 check_errno ();
3256 if (fd_info[s].flags & FILE_SOCKET)
3257 {
3258 int rc = pfn_shutdown (SOCK_HANDLE (s), how);
3259 if (rc == SOCKET_ERROR)
3260 set_errno ();
3261 return rc;
3262 }
3263 h_errno = ENOTSOCK;
3264 return SOCKET_ERROR;
3265 }
3266
3267 int
3268 sys_setsockopt (int s, int level, int optname, const void * optval, int optlen)
3269 {
3270 if (winsock_lib == NULL)
3271 {
3272 h_errno = ENETDOWN;
3273 return SOCKET_ERROR;
3274 }
3275
3276 check_errno ();
3277 if (fd_info[s].flags & FILE_SOCKET)
3278 {
3279 int rc = pfn_setsockopt (SOCK_HANDLE (s), level, optname,
3280 (const char *)optval, optlen);
3281 if (rc == SOCKET_ERROR)
3282 set_errno ();
3283 return rc;
3284 }
3285 h_errno = ENOTSOCK;
3286 return SOCKET_ERROR;
3287 }
3288
3289 int
3290 sys_listen (int s, int backlog)
3291 {
3292 if (winsock_lib == NULL)
3293 {
3294 h_errno = ENETDOWN;
3295 return SOCKET_ERROR;
3296 }
3297
3298 check_errno ();
3299 if (fd_info[s].flags & FILE_SOCKET)
3300 {
3301 int rc = pfn_listen (SOCK_HANDLE (s), backlog);
3302 if (rc == SOCKET_ERROR)
3303 set_errno ();
3304 else
3305 fd_info[s].flags |= FILE_LISTEN;
3306 return rc;
3307 }
3308 h_errno = ENOTSOCK;
3309 return SOCKET_ERROR;
3310 }
3311
3312 int
3313 sys_getsockname (int s, struct sockaddr * name, int * namelen)
3314 {
3315 if (winsock_lib == NULL)
3316 {
3317 h_errno = ENETDOWN;
3318 return SOCKET_ERROR;
3319 }
3320
3321 check_errno ();
3322 if (fd_info[s].flags & FILE_SOCKET)
3323 {
3324 int rc = pfn_getsockname (SOCK_HANDLE (s), name, namelen);
3325 if (rc == SOCKET_ERROR)
3326 set_errno ();
3327 return rc;
3328 }
3329 h_errno = ENOTSOCK;
3330 return SOCKET_ERROR;
3331 }
3332
3333 int
3334 sys_accept (int s, struct sockaddr * addr, int * addrlen)
3335 {
3336 if (winsock_lib == NULL)
3337 {
3338 h_errno = ENETDOWN;
3339 return -1;
3340 }
3341
3342 check_errno ();
3343 if (fd_info[s].flags & FILE_LISTEN)
3344 {
3345 SOCKET t = pfn_accept (SOCK_HANDLE (s), addr, addrlen);
3346 int fd = -1;
3347 if (t == INVALID_SOCKET)
3348 set_errno ();
3349 else
3350 fd = socket_to_fd (t);
3351
3352 fd_info[s].cp->status = STATUS_READ_ACKNOWLEDGED;
3353 ResetEvent (fd_info[s].cp->char_avail);
3354 return fd;
3355 }
3356 h_errno = ENOTSOCK;
3357 return -1;
3358 }
3359
3360 int
3361 sys_recvfrom (int s, char * buf, int len, int flags,
3362 struct sockaddr * from, int * fromlen)
3363 {
3364 if (winsock_lib == NULL)
3365 {
3366 h_errno = ENETDOWN;
3367 return SOCKET_ERROR;
3368 }
3369
3370 check_errno ();
3371 if (fd_info[s].flags & FILE_SOCKET)
3372 {
3373 int rc = pfn_recvfrom (SOCK_HANDLE (s), buf, len, flags, from, fromlen);
3374 if (rc == SOCKET_ERROR)
3375 set_errno ();
3376 return rc;
3377 }
3378 h_errno = ENOTSOCK;
3379 return SOCKET_ERROR;
3380 }
3381
3382 int
3383 sys_sendto (int s, const char * buf, int len, int flags,
3384 const struct sockaddr * to, int tolen)
3385 {
3386 if (winsock_lib == NULL)
3387 {
3388 h_errno = ENETDOWN;
3389 return SOCKET_ERROR;
3390 }
3391
3392 check_errno ();
3393 if (fd_info[s].flags & FILE_SOCKET)
3394 {
3395 int rc = pfn_sendto (SOCK_HANDLE (s), buf, len, flags, to, tolen);
3396 if (rc == SOCKET_ERROR)
3397 set_errno ();
3398 return rc;
3399 }
3400 h_errno = ENOTSOCK;
3401 return SOCKET_ERROR;
3402 }
3403
3404 /* Windows does not have an fcntl function. Provide an implementation
3405 solely for making sockets non-blocking. */
3406 int
3407 fcntl (int s, int cmd, int options)
3408 {
3409 if (winsock_lib == NULL)
3410 {
3411 h_errno = ENETDOWN;
3412 return -1;
3413 }
3414
3415 check_errno ();
3416 if (fd_info[s].flags & FILE_SOCKET)
3417 {
3418 if (cmd == F_SETFL && options == O_NDELAY)
3419 {
3420 unsigned long nblock = 1;
3421 int rc = pfn_ioctlsocket (SOCK_HANDLE (s), FIONBIO, &nblock);
3422 if (rc == SOCKET_ERROR)
3423 set_errno();
3424 /* Keep track of the fact that we set this to non-blocking. */
3425 fd_info[s].flags |= FILE_NDELAY;
3426 return rc;
3427 }
3428 else
3429 {
3430 h_errno = EINVAL;
3431 return SOCKET_ERROR;
3432 }
3433 }
3434 h_errno = ENOTSOCK;
3435 return SOCKET_ERROR;
3436 }
3437
3438 #endif /* HAVE_SOCKETS */
3439
3440
3441 /* Shadow main io functions: we need to handle pipes and sockets more
3442 intelligently, and implement non-blocking mode as well. */
3443
3444 int
3445 sys_close (int fd)
3446 {
3447 int rc;
3448
3449 if (fd < 0)
3450 {
3451 errno = EBADF;
3452 return -1;
3453 }
3454
3455 if (fd < MAXDESC && fd_info[fd].cp)
3456 {
3457 child_process * cp = fd_info[fd].cp;
3458
3459 fd_info[fd].cp = NULL;
3460
3461 if (CHILD_ACTIVE (cp))
3462 {
3463 /* if last descriptor to active child_process then cleanup */
3464 int i;
3465 for (i = 0; i < MAXDESC; i++)
3466 {
3467 if (i == fd)
3468 continue;
3469 if (fd_info[i].cp == cp)
3470 break;
3471 }
3472 if (i == MAXDESC)
3473 {
3474 #ifdef HAVE_SOCKETS
3475 if (fd_info[fd].flags & FILE_SOCKET)
3476 {
3477 #ifndef SOCK_REPLACE_HANDLE
3478 if (winsock_lib == NULL) abort ();
3479
3480 pfn_shutdown (SOCK_HANDLE (fd), 2);
3481 rc = pfn_closesocket (SOCK_HANDLE (fd));
3482 #endif
3483 winsock_inuse--; /* count open sockets */
3484 }
3485 #endif
3486 delete_child (cp);
3487 }
3488 }
3489 }
3490
3491 /* Note that sockets do not need special treatment here (at least on
3492 NT and Windows 95 using the standard tcp/ip stacks) - it appears that
3493 closesocket is equivalent to CloseHandle, which is to be expected
3494 because socket handles are fully fledged kernel handles. */
3495 rc = _close (fd);
3496
3497 if (rc == 0 && fd < MAXDESC)
3498 fd_info[fd].flags = 0;
3499
3500 return rc;
3501 }
3502
3503 int
3504 sys_dup (int fd)
3505 {
3506 int new_fd;
3507
3508 new_fd = _dup (fd);
3509 if (new_fd >= 0 && new_fd < MAXDESC)
3510 {
3511 /* duplicate our internal info as well */
3512 fd_info[new_fd] = fd_info[fd];
3513 }
3514 return new_fd;
3515 }
3516
3517
3518 int
3519 sys_dup2 (int src, int dst)
3520 {
3521 int rc;
3522
3523 if (dst < 0 || dst >= MAXDESC)
3524 {
3525 errno = EBADF;
3526 return -1;
3527 }
3528
3529 /* make sure we close the destination first if it's a pipe or socket */
3530 if (src != dst && fd_info[dst].flags != 0)
3531 sys_close (dst);
3532
3533 rc = _dup2 (src, dst);
3534 if (rc == 0)
3535 {
3536 /* duplicate our internal info as well */
3537 fd_info[dst] = fd_info[src];
3538 }
3539 return rc;
3540 }
3541
3542 /* Unix pipe() has only one arg */
3543 int
3544 sys_pipe (int * phandles)
3545 {
3546 int rc;
3547 unsigned flags;
3548
3549 /* make pipe handles non-inheritable; when we spawn a child, we
3550 replace the relevant handle with an inheritable one. Also put
3551 pipes into binary mode; we will do text mode translation ourselves
3552 if required. */
3553 rc = _pipe (phandles, 0, _O_NOINHERIT | _O_BINARY);
3554
3555 if (rc == 0)
3556 {
3557 /* Protect against overflow, since Windows can open more handles than
3558 our fd_info array has room for. */
3559 if (phandles[0] >= MAXDESC || phandles[1] >= MAXDESC)
3560 {
3561 _close (phandles[0]);
3562 _close (phandles[1]);
3563 rc = -1;
3564 }
3565 else
3566 {
3567 flags = FILE_PIPE | FILE_READ | FILE_BINARY;
3568 fd_info[phandles[0]].flags = flags;
3569
3570 flags = FILE_PIPE | FILE_WRITE | FILE_BINARY;
3571 fd_info[phandles[1]].flags = flags;
3572 }
3573 }
3574
3575 return rc;
3576 }
3577
3578 /* From ntproc.c */
3579 extern int w32_pipe_read_delay;
3580
3581 /* Function to do blocking read of one byte, needed to implement
3582 select. It is only allowed on sockets and pipes. */
3583 int
3584 _sys_read_ahead (int fd)
3585 {
3586 child_process * cp;
3587 int rc;
3588
3589 if (fd < 0 || fd >= MAXDESC)
3590 return STATUS_READ_ERROR;
3591
3592 cp = fd_info[fd].cp;
3593
3594 if (cp == NULL || cp->fd != fd || cp->status != STATUS_READ_READY)
3595 return STATUS_READ_ERROR;
3596
3597 if ((fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET)) == 0
3598 || (fd_info[fd].flags & FILE_READ) == 0)
3599 {
3600 DebPrint (("_sys_read_ahead: internal error: fd %d is not a pipe or socket!\n", fd));
3601 abort ();
3602 }
3603
3604 cp->status = STATUS_READ_IN_PROGRESS;
3605
3606 if (fd_info[fd].flags & FILE_PIPE)
3607 {
3608 rc = _read (fd, &cp->chr, sizeof (char));
3609
3610 /* Give subprocess time to buffer some more output for us before
3611 reporting that input is available; we need this because Windows 95
3612 connects DOS programs to pipes by making the pipe appear to be
3613 the normal console stdout - as a result most DOS programs will
3614 write to stdout without buffering, ie. one character at a
3615 time. Even some W32 programs do this - "dir" in a command
3616 shell on NT is very slow if we don't do this. */
3617 if (rc > 0)
3618 {
3619 int wait = w32_pipe_read_delay;
3620
3621 if (wait > 0)
3622 Sleep (wait);
3623 else if (wait < 0)
3624 while (++wait <= 0)
3625 /* Yield remainder of our time slice, effectively giving a
3626 temporary priority boost to the child process. */
3627 Sleep (0);
3628 }
3629 }
3630 #ifdef HAVE_SOCKETS
3631 else if (fd_info[fd].flags & FILE_SOCKET)
3632 {
3633 unsigned long nblock = 0;
3634 /* We always want this to block, so temporarily disable NDELAY. */
3635 if (fd_info[fd].flags & FILE_NDELAY)
3636 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONBIO, &nblock);
3637
3638 rc = pfn_recv (SOCK_HANDLE (fd), &cp->chr, sizeof (char), 0);
3639
3640 if (fd_info[fd].flags & FILE_NDELAY)
3641 {
3642 nblock = 1;
3643 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONBIO, &nblock);
3644 }
3645 }
3646 #endif
3647
3648 if (rc == sizeof (char))
3649 cp->status = STATUS_READ_SUCCEEDED;
3650 else
3651 cp->status = STATUS_READ_FAILED;
3652
3653 return cp->status;
3654 }
3655
3656 int _sys_wait_accept (int fd)
3657 {
3658 HANDLE hEv;
3659 child_process * cp;
3660 int rc;
3661
3662 if (fd < 0 || fd >= MAXDESC)
3663 return STATUS_READ_ERROR;
3664
3665 cp = fd_info[fd].cp;
3666
3667 if (cp == NULL || cp->fd != fd || cp->status != STATUS_READ_READY)
3668 return STATUS_READ_ERROR;
3669
3670 cp->status = STATUS_READ_FAILED;
3671
3672 hEv = pfn_WSACreateEvent ();
3673 rc = pfn_WSAEventSelect (SOCK_HANDLE (fd), hEv, FD_ACCEPT);
3674 if (rc != SOCKET_ERROR)
3675 {
3676 rc = WaitForSingleObject (hEv, INFINITE);
3677 pfn_WSAEventSelect (SOCK_HANDLE (fd), NULL, 0);
3678 pfn_WSACloseEvent (hEv);
3679 if (rc == WAIT_OBJECT_0)
3680 cp->status = STATUS_READ_SUCCEEDED;
3681 }
3682
3683 return cp->status;
3684 }
3685
3686 int
3687 sys_read (int fd, char * buffer, unsigned int count)
3688 {
3689 int nchars;
3690 int to_read;
3691 DWORD waiting;
3692 char * orig_buffer = buffer;
3693
3694 if (fd < 0)
3695 {
3696 errno = EBADF;
3697 return -1;
3698 }
3699
3700 if (fd < MAXDESC && fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET))
3701 {
3702 child_process *cp = fd_info[fd].cp;
3703
3704 if ((fd_info[fd].flags & FILE_READ) == 0)
3705 {
3706 errno = EBADF;
3707 return -1;
3708 }
3709
3710 nchars = 0;
3711
3712 /* re-read CR carried over from last read */
3713 if (fd_info[fd].flags & FILE_LAST_CR)
3714 {
3715 if (fd_info[fd].flags & FILE_BINARY) abort ();
3716 *buffer++ = 0x0d;
3717 count--;
3718 nchars++;
3719 fd_info[fd].flags &= ~FILE_LAST_CR;
3720 }
3721
3722 /* presence of a child_process structure means we are operating in
3723 non-blocking mode - otherwise we just call _read directly.
3724 Note that the child_process structure might be missing because
3725 reap_subprocess has been called; in this case the pipe is
3726 already broken, so calling _read on it is okay. */
3727 if (cp)
3728 {
3729 int current_status = cp->status;
3730
3731 switch (current_status)
3732 {
3733 case STATUS_READ_FAILED:
3734 case STATUS_READ_ERROR:
3735 /* report normal EOF if nothing in buffer */
3736 if (nchars <= 0)
3737 fd_info[fd].flags |= FILE_AT_EOF;
3738 return nchars;
3739
3740 case STATUS_READ_READY:
3741 case STATUS_READ_IN_PROGRESS:
3742 DebPrint (("sys_read called when read is in progress\n"));
3743 errno = EWOULDBLOCK;
3744 return -1;
3745
3746 case STATUS_READ_SUCCEEDED:
3747 /* consume read-ahead char */
3748 *buffer++ = cp->chr;
3749 count--;
3750 nchars++;
3751 cp->status = STATUS_READ_ACKNOWLEDGED;
3752 ResetEvent (cp->char_avail);
3753
3754 case STATUS_READ_ACKNOWLEDGED:
3755 break;
3756
3757 default:
3758 DebPrint (("sys_read: bad status %d\n", current_status));
3759 errno = EBADF;
3760 return -1;
3761 }
3762
3763 if (fd_info[fd].flags & FILE_PIPE)
3764 {
3765 PeekNamedPipe ((HANDLE) _get_osfhandle (fd), NULL, 0, NULL, &waiting, NULL);
3766 to_read = min (waiting, (DWORD) count);
3767
3768 if (to_read > 0)
3769 nchars += _read (fd, buffer, to_read);
3770 }
3771 #ifdef HAVE_SOCKETS
3772 else /* FILE_SOCKET */
3773 {
3774 if (winsock_lib == NULL) abort ();
3775
3776 /* do the equivalent of a non-blocking read */
3777 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONREAD, &waiting);
3778 if (waiting == 0 && nchars == 0)
3779 {
3780 h_errno = errno = EWOULDBLOCK;
3781 return -1;
3782 }
3783
3784 if (waiting)
3785 {
3786 /* always use binary mode for sockets */
3787 int res = pfn_recv (SOCK_HANDLE (fd), buffer, count, 0);
3788 if (res == SOCKET_ERROR)
3789 {
3790 DebPrint(("sys_read.recv failed with error %d on socket %ld\n",
3791 pfn_WSAGetLastError (), SOCK_HANDLE (fd)));
3792 set_errno ();
3793 return -1;
3794 }
3795 nchars += res;
3796 }
3797 }
3798 #endif
3799 }
3800 else
3801 {
3802 int nread = _read (fd, buffer, count);
3803 if (nread >= 0)
3804 nchars += nread;
3805 else if (nchars == 0)
3806 nchars = nread;
3807 }
3808
3809 if (nchars <= 0)
3810 fd_info[fd].flags |= FILE_AT_EOF;
3811 /* Perform text mode translation if required. */
3812 else if ((fd_info[fd].flags & FILE_BINARY) == 0)
3813 {
3814 nchars = crlf_to_lf (nchars, orig_buffer);
3815 /* If buffer contains only CR, return that. To be absolutely
3816 sure we should attempt to read the next char, but in
3817 practice a CR to be followed by LF would not appear by
3818 itself in the buffer. */
3819 if (nchars > 1 && orig_buffer[nchars - 1] == 0x0d)
3820 {
3821 fd_info[fd].flags |= FILE_LAST_CR;
3822 nchars--;
3823 }
3824 }
3825 }
3826 else
3827 nchars = _read (fd, buffer, count);
3828
3829 return nchars;
3830 }
3831
3832 /* For now, don't bother with a non-blocking mode */
3833 int
3834 sys_write (int fd, const void * buffer, unsigned int count)
3835 {
3836 int nchars;
3837
3838 if (fd < 0)
3839 {
3840 errno = EBADF;
3841 return -1;
3842 }
3843
3844 if (fd < MAXDESC && fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET))
3845 {
3846 if ((fd_info[fd].flags & FILE_WRITE) == 0)
3847 {
3848 errno = EBADF;
3849 return -1;
3850 }
3851
3852 /* Perform text mode translation if required. */
3853 if ((fd_info[fd].flags & FILE_BINARY) == 0)
3854 {
3855 char * tmpbuf = alloca (count * 2);
3856 unsigned char * src = (void *)buffer;
3857 unsigned char * dst = tmpbuf;
3858 int nbytes = count;
3859
3860 while (1)
3861 {
3862 unsigned char *next;
3863 /* copy next line or remaining bytes */
3864 next = _memccpy (dst, src, '\n', nbytes);
3865 if (next)
3866 {
3867 /* copied one line ending with '\n' */
3868 int copied = next - dst;
3869 nbytes -= copied;
3870 src += copied;
3871 /* insert '\r' before '\n' */
3872 next[-1] = '\r';
3873 next[0] = '\n';
3874 dst = next + 1;
3875 count++;
3876 }
3877 else
3878 /* copied remaining partial line -> now finished */
3879 break;
3880 }
3881 buffer = tmpbuf;
3882 }
3883 }
3884
3885 #ifdef HAVE_SOCKETS
3886 if (fd < MAXDESC && fd_info[fd].flags & FILE_SOCKET)
3887 {
3888 unsigned long nblock = 0;
3889 if (winsock_lib == NULL) abort ();
3890
3891 /* TODO: implement select() properly so non-blocking I/O works. */
3892 /* For now, make sure the write blocks. */
3893 if (fd_info[fd].flags & FILE_NDELAY)
3894 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONBIO, &nblock);
3895
3896 nchars = pfn_send (SOCK_HANDLE (fd), buffer, count, 0);
3897
3898 /* Set the socket back to non-blocking if it was before,
3899 for other operations that support it. */
3900 if (fd_info[fd].flags & FILE_NDELAY)
3901 {
3902 nblock = 1;
3903 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONBIO, &nblock);
3904 }
3905
3906 if (nchars == SOCKET_ERROR)
3907 {
3908 DebPrint(("sys_write.send failed with error %d on socket %ld\n",
3909 pfn_WSAGetLastError (), SOCK_HANDLE (fd)));
3910 set_errno ();
3911 }
3912 }
3913 else
3914 #endif
3915 nchars = _write (fd, buffer, count);
3916
3917 return nchars;
3918 }
3919
3920 static void
3921 check_windows_init_file ()
3922 {
3923 extern int noninteractive, inhibit_window_system;
3924
3925 /* A common indication that Emacs is not installed properly is when
3926 it cannot find the Windows installation file. If this file does
3927 not exist in the expected place, tell the user. */
3928
3929 if (!noninteractive && !inhibit_window_system)
3930 {
3931 extern Lisp_Object Vwindow_system, Vload_path, Qfile_exists_p;
3932 Lisp_Object objs[2];
3933 Lisp_Object full_load_path;
3934 Lisp_Object init_file;
3935 int fd;
3936
3937 objs[0] = Vload_path;
3938 objs[1] = decode_env_path (0, (getenv ("EMACSLOADPATH")));
3939 full_load_path = Fappend (2, objs);
3940 init_file = build_string ("term/w32-win");
3941 fd = openp (full_load_path, init_file, Fget_load_suffixes (), NULL, Qnil);
3942 if (fd < 0)
3943 {
3944 Lisp_Object load_path_print = Fprin1_to_string (full_load_path, Qnil);
3945 char *init_file_name = SDATA (init_file);
3946 char *load_path = SDATA (load_path_print);
3947 char *buffer = alloca (1024
3948 + strlen (init_file_name)
3949 + strlen (load_path));
3950
3951 sprintf (buffer,
3952 "The Emacs Windows initialization file \"%s.el\" "
3953 "could not be found in your Emacs installation. "
3954 "Emacs checked the following directories for this file:\n"
3955 "\n%s\n\n"
3956 "When Emacs cannot find this file, it usually means that it "
3957 "was not installed properly, or its distribution file was "
3958 "not unpacked properly.\nSee the README.W32 file in the "
3959 "top-level Emacs directory for more information.",
3960 init_file_name, load_path);
3961 MessageBox (NULL,
3962 buffer,
3963 "Emacs Abort Dialog",
3964 MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL);
3965 /* Use the low-level Emacs abort. */
3966 #undef abort
3967 abort ();
3968 }
3969 else
3970 {
3971 _close (fd);
3972 }
3973 }
3974 }
3975
3976 void
3977 term_ntproc ()
3978 {
3979 #ifdef HAVE_SOCKETS
3980 /* shutdown the socket interface if necessary */
3981 term_winsock ();
3982 #endif
3983
3984 term_w32select ();
3985 }
3986
3987 void
3988 init_ntproc ()
3989 {
3990 #ifdef HAVE_SOCKETS
3991 /* Initialise the socket interface now if available and requested by
3992 the user by defining PRELOAD_WINSOCK; otherwise loading will be
3993 delayed until open-network-stream is called (w32-has-winsock can
3994 also be used to dynamically load or reload winsock).
3995
3996 Conveniently, init_environment is called before us, so
3997 PRELOAD_WINSOCK can be set in the registry. */
3998
3999 /* Always initialize this correctly. */
4000 winsock_lib = NULL;
4001
4002 if (getenv ("PRELOAD_WINSOCK") != NULL)
4003 init_winsock (TRUE);
4004 #endif
4005
4006 /* Initial preparation for subprocess support: replace our standard
4007 handles with non-inheritable versions. */
4008 {
4009 HANDLE parent;
4010 HANDLE stdin_save = INVALID_HANDLE_VALUE;
4011 HANDLE stdout_save = INVALID_HANDLE_VALUE;
4012 HANDLE stderr_save = INVALID_HANDLE_VALUE;
4013
4014 parent = GetCurrentProcess ();
4015
4016 /* ignore errors when duplicating and closing; typically the
4017 handles will be invalid when running as a gui program. */
4018 DuplicateHandle (parent,
4019 GetStdHandle (STD_INPUT_HANDLE),
4020 parent,
4021 &stdin_save,
4022 0,
4023 FALSE,
4024 DUPLICATE_SAME_ACCESS);
4025
4026 DuplicateHandle (parent,
4027 GetStdHandle (STD_OUTPUT_HANDLE),
4028 parent,
4029 &stdout_save,
4030 0,
4031 FALSE,
4032 DUPLICATE_SAME_ACCESS);
4033
4034 DuplicateHandle (parent,
4035 GetStdHandle (STD_ERROR_HANDLE),
4036 parent,
4037 &stderr_save,
4038 0,
4039 FALSE,
4040 DUPLICATE_SAME_ACCESS);
4041
4042 fclose (stdin);
4043 fclose (stdout);
4044 fclose (stderr);
4045
4046 if (stdin_save != INVALID_HANDLE_VALUE)
4047 _open_osfhandle ((long) stdin_save, O_TEXT);
4048 else
4049 _open ("nul", O_TEXT | O_NOINHERIT | O_RDONLY);
4050 _fdopen (0, "r");
4051
4052 if (stdout_save != INVALID_HANDLE_VALUE)
4053 _open_osfhandle ((long) stdout_save, O_TEXT);
4054 else
4055 _open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY);
4056 _fdopen (1, "w");
4057
4058 if (stderr_save != INVALID_HANDLE_VALUE)
4059 _open_osfhandle ((long) stderr_save, O_TEXT);
4060 else
4061 _open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY);
4062 _fdopen (2, "w");
4063 }
4064
4065 /* unfortunately, atexit depends on implementation of malloc */
4066 /* atexit (term_ntproc); */
4067 signal (SIGABRT, term_ntproc);
4068
4069 /* determine which drives are fixed, for GetCachedVolumeInformation */
4070 {
4071 /* GetDriveType must have trailing backslash. */
4072 char drive[] = "A:\\";
4073
4074 /* Loop over all possible drive letters */
4075 while (*drive <= 'Z')
4076 {
4077 /* Record if this drive letter refers to a fixed drive. */
4078 fixed_drives[DRIVE_INDEX (*drive)] =
4079 (GetDriveType (drive) == DRIVE_FIXED);
4080
4081 (*drive)++;
4082 }
4083
4084 /* Reset the volume info cache. */
4085 volume_cache = NULL;
4086 }
4087
4088 /* Check to see if Emacs has been installed correctly. */
4089 check_windows_init_file ();
4090 }
4091
4092 /*
4093 globals_of_w32 is used to initialize those global variables that
4094 must always be initialized on startup even when the global variable
4095 initialized is non zero (see the function main in emacs.c).
4096 */
4097 void globals_of_w32 ()
4098 {
4099 g_b_init_is_windows_9x = 0;
4100 g_b_init_open_process_token = 0;
4101 g_b_init_get_token_information = 0;
4102 g_b_init_lookup_account_sid = 0;
4103 g_b_init_get_sid_identifier_authority = 0;
4104 }
4105
4106 /* end of nt.c */
4107
4108 /* arch-tag: 90442dd3-37be-482b-b272-ac752e3049f1
4109 (do not change this comment) */