Fix network streams.
[emacs.git] / src / w32.c
blob7a80275a7c8514916c387cc065320c5bbe95302f
1 /* Utility and Unix shadow routines for GNU Emacs on the Microsoft Windows API.
3 Copyright (C) 1994-1995, 2000-2016 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or (at
10 your option) any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
21 Geoff Voelker (voelker@cs.washington.edu) 7-29-94
24 #define DEFER_MS_W32_H
25 #include <config.h>
27 #include <mingw_time.h>
28 #include <stddef.h> /* for offsetof */
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <float.h> /* for DBL_EPSILON */
32 #include <io.h>
33 #include <errno.h>
34 #include <fcntl.h>
35 #include <ctype.h>
36 #include <signal.h>
37 #include <sys/file.h>
38 #include <time.h> /* must be before nt/inc/sys/time.h, for MinGW64 */
39 #include <sys/time.h>
40 #include <sys/utime.h>
41 #include <math.h>
43 /* Include (most) CRT headers *before* ms-w32.h. */
44 #include <ms-w32.h>
46 #include <string.h> /* for strerror, needed by sys_strerror */
47 #include <mbstring.h> /* for _mbspbrk, _mbslwr, _mbsrchr, ... */
49 #undef access
50 #undef chdir
51 #undef chmod
52 #undef creat
53 #undef ctime
54 #undef fopen
55 #undef link
56 #undef mkdir
57 #undef open
58 #undef rename
59 #undef rmdir
60 #undef unlink
62 #undef close
63 #undef dup
64 #undef dup2
65 #undef pipe
66 #undef read
67 #undef write
69 #undef strerror
71 #undef localtime
73 char *sys_ctime (const time_t *);
74 int sys_chdir (const char *);
75 int sys_creat (const char *, int);
76 FILE *sys_fopen (const char *, const char *);
77 int sys_mkdir (const char *);
78 int sys_open (const char *, int, int);
79 int sys_rename (char const *, char const *);
80 int sys_rmdir (const char *);
81 int sys_close (int);
82 int sys_dup2 (int, int);
83 int sys_read (int, char *, unsigned int);
84 int sys_write (int, const void *, unsigned int);
85 struct tm *sys_localtime (const time_t *);
87 #ifdef HAVE_MODULES
88 extern void dynlib_reset_last_error (void);
89 #endif
91 #include "lisp.h"
92 #include "epaths.h" /* for PATH_EXEC */
94 #include <pwd.h>
95 #include <grp.h>
97 #include <windows.h>
98 /* Some versions of compiler define MEMORYSTATUSEX, some don't, so we
99 use a different name to avoid compilation problems. */
100 typedef struct _MEMORY_STATUS_EX {
101 DWORD dwLength;
102 DWORD dwMemoryLoad;
103 DWORDLONG ullTotalPhys;
104 DWORDLONG ullAvailPhys;
105 DWORDLONG ullTotalPageFile;
106 DWORDLONG ullAvailPageFile;
107 DWORDLONG ullTotalVirtual;
108 DWORDLONG ullAvailVirtual;
109 DWORDLONG ullAvailExtendedVirtual;
110 } MEMORY_STATUS_EX,*LPMEMORY_STATUS_EX;
112 /* These are here so that GDB would know about these data types. This
113 allows attaching GDB to Emacs when a fatal exception is triggered
114 and Windows pops up the "application needs to be closed" dialog.
115 At that point, _gnu_exception_handler, the top-level exception
116 handler installed by the MinGW startup code, is somewhere on the
117 call-stack of the main thread, so going to that call frame and
118 looking at the argument to _gnu_exception_handler, which is a
119 PEXCEPTION_POINTERS pointer, can reveal the exception code
120 (excptr->ExceptionRecord->ExceptionCode) and the address where the
121 exception happened (excptr->ExceptionRecord->ExceptionAddress), as
122 well as some additional information specific to the exception. */
123 PEXCEPTION_POINTERS excptr;
124 PEXCEPTION_RECORD excprec;
125 PCONTEXT ctxrec;
127 #include <lmcons.h>
128 #include <shlobj.h>
130 #include <tlhelp32.h>
131 #include <psapi.h>
132 #ifndef _MSC_VER
133 #include <w32api.h>
134 #endif
135 #if _WIN32_WINNT < 0x0500
136 #if !defined (__MINGW32__) || __W32API_MAJOR_VERSION < 3 || (__W32API_MAJOR_VERSION == 3 && __W32API_MINOR_VERSION < 15)
137 /* This either is not in psapi.h or guarded by higher value of
138 _WIN32_WINNT than what we use. w32api supplied with MinGW 3.15
139 defines it in psapi.h */
140 typedef struct _PROCESS_MEMORY_COUNTERS_EX {
141 DWORD cb;
142 DWORD PageFaultCount;
143 SIZE_T PeakWorkingSetSize;
144 SIZE_T WorkingSetSize;
145 SIZE_T QuotaPeakPagedPoolUsage;
146 SIZE_T QuotaPagedPoolUsage;
147 SIZE_T QuotaPeakNonPagedPoolUsage;
148 SIZE_T QuotaNonPagedPoolUsage;
149 SIZE_T PagefileUsage;
150 SIZE_T PeakPagefileUsage;
151 SIZE_T PrivateUsage;
152 } PROCESS_MEMORY_COUNTERS_EX,*PPROCESS_MEMORY_COUNTERS_EX;
153 #endif
154 #endif
156 #include <winioctl.h>
157 #include <aclapi.h>
158 #include <sddl.h>
160 #include <sys/acl.h>
161 #include <acl.h>
163 /* This is not in MinGW's sddl.h (but they are in MSVC headers), so we
164 define them by hand if not already defined. */
165 #ifndef SDDL_REVISION_1
166 #define SDDL_REVISION_1 1
167 #endif /* SDDL_REVISION_1 */
169 #if defined(_MSC_VER) || defined(MINGW_W64)
170 /* MSVC and MinGW64 don't provide the definition of
171 REPARSE_DATA_BUFFER and the associated macros, except on ntifs.h,
172 which cannot be included because it triggers conflicts with other
173 Windows API headers. So we define it here by hand. */
175 typedef struct _REPARSE_DATA_BUFFER {
176 ULONG ReparseTag;
177 USHORT ReparseDataLength;
178 USHORT Reserved;
179 union {
180 struct {
181 USHORT SubstituteNameOffset;
182 USHORT SubstituteNameLength;
183 USHORT PrintNameOffset;
184 USHORT PrintNameLength;
185 ULONG Flags;
186 WCHAR PathBuffer[1];
187 } SymbolicLinkReparseBuffer;
188 struct {
189 USHORT SubstituteNameOffset;
190 USHORT SubstituteNameLength;
191 USHORT PrintNameOffset;
192 USHORT PrintNameLength;
193 WCHAR PathBuffer[1];
194 } MountPointReparseBuffer;
195 struct {
196 UCHAR DataBuffer[1];
197 } GenericReparseBuffer;
198 } DUMMYUNIONNAME;
199 } REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
201 #ifndef FILE_DEVICE_FILE_SYSTEM
202 #define FILE_DEVICE_FILE_SYSTEM 9
203 #endif
204 #ifndef METHOD_BUFFERED
205 #define METHOD_BUFFERED 0
206 #endif
207 #ifndef FILE_ANY_ACCESS
208 #define FILE_ANY_ACCESS 0x00000000
209 #endif
210 #ifndef CTL_CODE
211 #define CTL_CODE(t,f,m,a) (((t)<<16)|((a)<<14)|((f)<<2)|(m))
212 #endif
213 /* MinGW64 defines FSCTL_GET_REPARSE_POINT on winioctl.h. */
214 #ifndef FSCTL_GET_REPARSE_POINT
215 #define FSCTL_GET_REPARSE_POINT \
216 CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS)
217 #endif
218 #endif
220 /* TCP connection support. */
221 #include <sys/socket.h>
222 #undef socket
223 #undef bind
224 #undef connect
225 #undef htons
226 #undef ntohs
227 #undef inet_addr
228 #undef gethostname
229 #undef gethostbyname
230 #undef getservbyname
231 #undef getpeername
232 #undef shutdown
233 #undef setsockopt
234 #undef listen
235 #undef getsockname
236 #undef accept
237 #undef recvfrom
238 #undef sendto
240 #include <iphlpapi.h> /* should be after winsock2.h */
242 #include <wincrypt.h>
244 #include <c-strcase.h>
245 #include <utimens.h> /* for fdutimens */
247 #include "w32.h"
248 #include <dirent.h>
249 #include "w32common.h"
250 #include "w32select.h"
251 #include "systime.h" /* for current_timespec, struct timespec */
252 #include "dispextern.h" /* for xstrcasecmp */
253 #include "coding.h" /* for Vlocale_coding_system */
255 #include "careadlinkat.h"
256 #include "allocator.h"
258 /* For Lisp_Process, serial_configure and serial_open. */
259 #include "process.h"
260 #include "systty.h"
262 typedef HRESULT (WINAPI * ShGetFolderPath_fn)
263 (IN HWND, IN int, IN HANDLE, IN DWORD, OUT char *);
265 static DWORD get_rid (PSID);
266 static int is_symlink (const char *);
267 static char * chase_symlinks (const char *);
268 static int enable_privilege (LPCTSTR, BOOL, TOKEN_PRIVILEGES *);
269 static int restore_privilege (TOKEN_PRIVILEGES *);
270 static BOOL WINAPI revert_to_self (void);
272 static int sys_access (const char *, int);
273 extern void *e_malloc (size_t);
274 extern int sys_select (int, SELECT_TYPE *, SELECT_TYPE *, SELECT_TYPE *,
275 struct timespec *, sigset_t *);
276 extern int sys_dup (int);
279 /* Initialization states.
281 WARNING: If you add any more such variables for additional APIs,
282 you MUST add initialization for them to globals_of_w32
283 below. This is because these variables might get set
284 to non-NULL values during dumping, but the dumped Emacs
285 cannot reuse those values, because it could be run on a
286 different version of the OS, where API addresses are
287 different. */
288 static BOOL g_b_init_is_windows_9x;
289 static BOOL g_b_init_open_process_token;
290 static BOOL g_b_init_get_token_information;
291 static BOOL g_b_init_lookup_account_sid;
292 static BOOL g_b_init_get_sid_sub_authority;
293 static BOOL g_b_init_get_sid_sub_authority_count;
294 static BOOL g_b_init_get_security_info;
295 static BOOL g_b_init_get_file_security_w;
296 static BOOL g_b_init_get_file_security_a;
297 static BOOL g_b_init_get_security_descriptor_owner;
298 static BOOL g_b_init_get_security_descriptor_group;
299 static BOOL g_b_init_is_valid_sid;
300 static BOOL g_b_init_create_toolhelp32_snapshot;
301 static BOOL g_b_init_process32_first;
302 static BOOL g_b_init_process32_next;
303 static BOOL g_b_init_open_thread_token;
304 static BOOL g_b_init_impersonate_self;
305 static BOOL g_b_init_revert_to_self;
306 static BOOL g_b_init_get_process_memory_info;
307 static BOOL g_b_init_get_process_working_set_size;
308 static BOOL g_b_init_global_memory_status;
309 static BOOL g_b_init_global_memory_status_ex;
310 static BOOL g_b_init_get_length_sid;
311 static BOOL g_b_init_equal_sid;
312 static BOOL g_b_init_copy_sid;
313 static BOOL g_b_init_get_native_system_info;
314 static BOOL g_b_init_get_system_times;
315 static BOOL g_b_init_create_symbolic_link_w;
316 static BOOL g_b_init_create_symbolic_link_a;
317 static BOOL g_b_init_get_security_descriptor_dacl;
318 static BOOL g_b_init_convert_sd_to_sddl;
319 static BOOL g_b_init_convert_sddl_to_sd;
320 static BOOL g_b_init_is_valid_security_descriptor;
321 static BOOL g_b_init_set_file_security_w;
322 static BOOL g_b_init_set_file_security_a;
323 static BOOL g_b_init_set_named_security_info_w;
324 static BOOL g_b_init_set_named_security_info_a;
325 static BOOL g_b_init_get_adapters_info;
327 BOOL g_b_init_compare_string_w;
328 BOOL g_b_init_debug_break_process;
331 BEGIN: Wrapper functions around OpenProcessToken
332 and other functions in advapi32.dll that are only
333 supported in Windows NT / 2k / XP
335 /* ** Function pointer typedefs ** */
336 typedef BOOL (WINAPI * OpenProcessToken_Proc) (
337 HANDLE ProcessHandle,
338 DWORD DesiredAccess,
339 PHANDLE TokenHandle);
340 typedef BOOL (WINAPI * GetTokenInformation_Proc) (
341 HANDLE TokenHandle,
342 TOKEN_INFORMATION_CLASS TokenInformationClass,
343 LPVOID TokenInformation,
344 DWORD TokenInformationLength,
345 PDWORD ReturnLength);
346 typedef BOOL (WINAPI * GetProcessTimes_Proc) (
347 HANDLE process_handle,
348 LPFILETIME creation_time,
349 LPFILETIME exit_time,
350 LPFILETIME kernel_time,
351 LPFILETIME user_time);
353 GetProcessTimes_Proc get_process_times_fn = NULL;
355 #ifdef _UNICODE
356 const char * const LookupAccountSid_Name = "LookupAccountSidW";
357 #else
358 const char * const LookupAccountSid_Name = "LookupAccountSidA";
359 #endif
360 typedef BOOL (WINAPI * LookupAccountSid_Proc) (
361 LPCTSTR lpSystemName,
362 PSID Sid,
363 LPTSTR Name,
364 LPDWORD cbName,
365 LPTSTR DomainName,
366 LPDWORD cbDomainName,
367 PSID_NAME_USE peUse);
368 typedef PDWORD (WINAPI * GetSidSubAuthority_Proc) (
369 PSID pSid,
370 DWORD n);
371 typedef PUCHAR (WINAPI * GetSidSubAuthorityCount_Proc) (
372 PSID pSid);
373 typedef DWORD (WINAPI * GetSecurityInfo_Proc) (
374 HANDLE handle,
375 SE_OBJECT_TYPE ObjectType,
376 SECURITY_INFORMATION SecurityInfo,
377 PSID *ppsidOwner,
378 PSID *ppsidGroup,
379 PACL *ppDacl,
380 PACL *ppSacl,
381 PSECURITY_DESCRIPTOR *ppSecurityDescriptor);
382 typedef BOOL (WINAPI * GetFileSecurityW_Proc) (
383 LPCWSTR lpFileName,
384 SECURITY_INFORMATION RequestedInformation,
385 PSECURITY_DESCRIPTOR pSecurityDescriptor,
386 DWORD nLength,
387 LPDWORD lpnLengthNeeded);
388 typedef BOOL (WINAPI * GetFileSecurityA_Proc) (
389 LPCSTR lpFileName,
390 SECURITY_INFORMATION RequestedInformation,
391 PSECURITY_DESCRIPTOR pSecurityDescriptor,
392 DWORD nLength,
393 LPDWORD lpnLengthNeeded);
394 typedef BOOL (WINAPI *SetFileSecurityW_Proc) (
395 LPCWSTR lpFileName,
396 SECURITY_INFORMATION SecurityInformation,
397 PSECURITY_DESCRIPTOR pSecurityDescriptor);
398 typedef BOOL (WINAPI *SetFileSecurityA_Proc) (
399 LPCSTR lpFileName,
400 SECURITY_INFORMATION SecurityInformation,
401 PSECURITY_DESCRIPTOR pSecurityDescriptor);
402 typedef DWORD (WINAPI *SetNamedSecurityInfoW_Proc) (
403 LPCWSTR lpObjectName,
404 SE_OBJECT_TYPE ObjectType,
405 SECURITY_INFORMATION SecurityInformation,
406 PSID psidOwner,
407 PSID psidGroup,
408 PACL pDacl,
409 PACL pSacl);
410 typedef DWORD (WINAPI *SetNamedSecurityInfoA_Proc) (
411 LPCSTR lpObjectName,
412 SE_OBJECT_TYPE ObjectType,
413 SECURITY_INFORMATION SecurityInformation,
414 PSID psidOwner,
415 PSID psidGroup,
416 PACL pDacl,
417 PACL pSacl);
418 typedef BOOL (WINAPI * GetSecurityDescriptorOwner_Proc) (
419 PSECURITY_DESCRIPTOR pSecurityDescriptor,
420 PSID *pOwner,
421 LPBOOL lpbOwnerDefaulted);
422 typedef BOOL (WINAPI * GetSecurityDescriptorGroup_Proc) (
423 PSECURITY_DESCRIPTOR pSecurityDescriptor,
424 PSID *pGroup,
425 LPBOOL lpbGroupDefaulted);
426 typedef BOOL (WINAPI *GetSecurityDescriptorDacl_Proc) (
427 PSECURITY_DESCRIPTOR pSecurityDescriptor,
428 LPBOOL lpbDaclPresent,
429 PACL *pDacl,
430 LPBOOL lpbDaclDefaulted);
431 typedef BOOL (WINAPI * IsValidSid_Proc) (
432 PSID sid);
433 typedef HANDLE (WINAPI * CreateToolhelp32Snapshot_Proc) (
434 DWORD dwFlags,
435 DWORD th32ProcessID);
436 typedef BOOL (WINAPI * Process32First_Proc) (
437 HANDLE hSnapshot,
438 LPPROCESSENTRY32 lppe);
439 typedef BOOL (WINAPI * Process32Next_Proc) (
440 HANDLE hSnapshot,
441 LPPROCESSENTRY32 lppe);
442 typedef BOOL (WINAPI * OpenThreadToken_Proc) (
443 HANDLE ThreadHandle,
444 DWORD DesiredAccess,
445 BOOL OpenAsSelf,
446 PHANDLE TokenHandle);
447 typedef BOOL (WINAPI * ImpersonateSelf_Proc) (
448 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel);
449 typedef BOOL (WINAPI * RevertToSelf_Proc) (void);
450 typedef BOOL (WINAPI * GetProcessMemoryInfo_Proc) (
451 HANDLE Process,
452 PPROCESS_MEMORY_COUNTERS ppsmemCounters,
453 DWORD cb);
454 typedef BOOL (WINAPI * GetProcessWorkingSetSize_Proc) (
455 HANDLE hProcess,
456 PSIZE_T lpMinimumWorkingSetSize,
457 PSIZE_T lpMaximumWorkingSetSize);
458 typedef BOOL (WINAPI * GlobalMemoryStatus_Proc) (
459 LPMEMORYSTATUS lpBuffer);
460 typedef BOOL (WINAPI * GlobalMemoryStatusEx_Proc) (
461 LPMEMORY_STATUS_EX lpBuffer);
462 typedef BOOL (WINAPI * CopySid_Proc) (
463 DWORD nDestinationSidLength,
464 PSID pDestinationSid,
465 PSID pSourceSid);
466 typedef BOOL (WINAPI * EqualSid_Proc) (
467 PSID pSid1,
468 PSID pSid2);
469 typedef DWORD (WINAPI * GetLengthSid_Proc) (
470 PSID pSid);
471 typedef void (WINAPI * GetNativeSystemInfo_Proc) (
472 LPSYSTEM_INFO lpSystemInfo);
473 typedef BOOL (WINAPI * GetSystemTimes_Proc) (
474 LPFILETIME lpIdleTime,
475 LPFILETIME lpKernelTime,
476 LPFILETIME lpUserTime);
477 typedef BOOLEAN (WINAPI *CreateSymbolicLinkW_Proc) (
478 LPCWSTR lpSymlinkFileName,
479 LPCWSTR lpTargetFileName,
480 DWORD dwFlags);
481 typedef BOOLEAN (WINAPI *CreateSymbolicLinkA_Proc) (
482 LPCSTR lpSymlinkFileName,
483 LPCSTR lpTargetFileName,
484 DWORD dwFlags);
485 typedef BOOL (WINAPI *ConvertStringSecurityDescriptorToSecurityDescriptor_Proc) (
486 LPCTSTR StringSecurityDescriptor,
487 DWORD StringSDRevision,
488 PSECURITY_DESCRIPTOR *SecurityDescriptor,
489 PULONG SecurityDescriptorSize);
490 typedef BOOL (WINAPI *ConvertSecurityDescriptorToStringSecurityDescriptor_Proc) (
491 PSECURITY_DESCRIPTOR SecurityDescriptor,
492 DWORD RequestedStringSDRevision,
493 SECURITY_INFORMATION SecurityInformation,
494 LPTSTR *StringSecurityDescriptor,
495 PULONG StringSecurityDescriptorLen);
496 typedef BOOL (WINAPI *IsValidSecurityDescriptor_Proc) (PSECURITY_DESCRIPTOR);
497 typedef DWORD (WINAPI *GetAdaptersInfo_Proc) (
498 PIP_ADAPTER_INFO pAdapterInfo,
499 PULONG pOutBufLen);
501 int (WINAPI *pMultiByteToWideChar)(UINT,DWORD,LPCSTR,int,LPWSTR,int);
502 int (WINAPI *pWideCharToMultiByte)(UINT,DWORD,LPCWSTR,int,LPSTR,int,LPCSTR,LPBOOL);
503 DWORD multiByteToWideCharFlags;
505 /* ** A utility function ** */
506 static BOOL
507 is_windows_9x (void)
509 static BOOL s_b_ret = 0;
510 OSVERSIONINFO os_ver;
511 if (g_b_init_is_windows_9x == 0)
513 g_b_init_is_windows_9x = 1;
514 ZeroMemory (&os_ver, sizeof (OSVERSIONINFO));
515 os_ver.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
516 if (GetVersionEx (&os_ver))
518 s_b_ret = (os_ver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS);
521 return s_b_ret;
524 static Lisp_Object ltime (ULONGLONG);
526 /* Get total user and system times for get-internal-run-time.
527 Returns a list of integers if the times are provided by the OS
528 (NT derivatives), otherwise it returns the result of current-time. */
529 Lisp_Object w32_get_internal_run_time (void);
531 Lisp_Object
532 w32_get_internal_run_time (void)
534 if (get_process_times_fn)
536 FILETIME create, exit, kernel, user;
537 HANDLE proc = GetCurrentProcess ();
538 if ((*get_process_times_fn) (proc, &create, &exit, &kernel, &user))
540 LARGE_INTEGER user_int, kernel_int, total;
541 user_int.LowPart = user.dwLowDateTime;
542 user_int.HighPart = user.dwHighDateTime;
543 kernel_int.LowPart = kernel.dwLowDateTime;
544 kernel_int.HighPart = kernel.dwHighDateTime;
545 total.QuadPart = user_int.QuadPart + kernel_int.QuadPart;
546 return ltime (total.QuadPart);
550 return Fcurrent_time ();
553 /* ** The wrapper functions ** */
555 static BOOL WINAPI
556 open_process_token (HANDLE ProcessHandle,
557 DWORD DesiredAccess,
558 PHANDLE TokenHandle)
560 static OpenProcessToken_Proc s_pfn_Open_Process_Token = NULL;
561 HMODULE hm_advapi32 = NULL;
562 if (is_windows_9x () == TRUE)
564 return FALSE;
566 if (g_b_init_open_process_token == 0)
568 g_b_init_open_process_token = 1;
569 hm_advapi32 = LoadLibrary ("Advapi32.dll");
570 s_pfn_Open_Process_Token =
571 (OpenProcessToken_Proc) GetProcAddress (hm_advapi32, "OpenProcessToken");
573 if (s_pfn_Open_Process_Token == NULL)
575 return FALSE;
577 return (
578 s_pfn_Open_Process_Token (
579 ProcessHandle,
580 DesiredAccess,
581 TokenHandle)
585 static BOOL WINAPI
586 get_token_information (HANDLE TokenHandle,
587 TOKEN_INFORMATION_CLASS TokenInformationClass,
588 LPVOID TokenInformation,
589 DWORD TokenInformationLength,
590 PDWORD ReturnLength)
592 static GetTokenInformation_Proc s_pfn_Get_Token_Information = NULL;
593 HMODULE hm_advapi32 = NULL;
594 if (is_windows_9x () == TRUE)
596 return FALSE;
598 if (g_b_init_get_token_information == 0)
600 g_b_init_get_token_information = 1;
601 hm_advapi32 = LoadLibrary ("Advapi32.dll");
602 s_pfn_Get_Token_Information =
603 (GetTokenInformation_Proc) GetProcAddress (hm_advapi32, "GetTokenInformation");
605 if (s_pfn_Get_Token_Information == NULL)
607 return FALSE;
609 return (
610 s_pfn_Get_Token_Information (
611 TokenHandle,
612 TokenInformationClass,
613 TokenInformation,
614 TokenInformationLength,
615 ReturnLength)
619 static BOOL WINAPI
620 lookup_account_sid (LPCTSTR lpSystemName,
621 PSID Sid,
622 LPTSTR Name,
623 LPDWORD cbName,
624 LPTSTR DomainName,
625 LPDWORD cbDomainName,
626 PSID_NAME_USE peUse)
628 static LookupAccountSid_Proc s_pfn_Lookup_Account_Sid = NULL;
629 HMODULE hm_advapi32 = NULL;
630 if (is_windows_9x () == TRUE)
632 return FALSE;
634 if (g_b_init_lookup_account_sid == 0)
636 g_b_init_lookup_account_sid = 1;
637 hm_advapi32 = LoadLibrary ("Advapi32.dll");
638 s_pfn_Lookup_Account_Sid =
639 (LookupAccountSid_Proc) GetProcAddress (hm_advapi32, LookupAccountSid_Name);
641 if (s_pfn_Lookup_Account_Sid == NULL)
643 return FALSE;
645 return (
646 s_pfn_Lookup_Account_Sid (
647 lpSystemName,
648 Sid,
649 Name,
650 cbName,
651 DomainName,
652 cbDomainName,
653 peUse)
657 static PDWORD WINAPI
658 get_sid_sub_authority (PSID pSid, DWORD n)
660 static GetSidSubAuthority_Proc s_pfn_Get_Sid_Sub_Authority = NULL;
661 static DWORD zero = 0U;
662 HMODULE hm_advapi32 = NULL;
663 if (is_windows_9x () == TRUE)
665 return &zero;
667 if (g_b_init_get_sid_sub_authority == 0)
669 g_b_init_get_sid_sub_authority = 1;
670 hm_advapi32 = LoadLibrary ("Advapi32.dll");
671 s_pfn_Get_Sid_Sub_Authority =
672 (GetSidSubAuthority_Proc) GetProcAddress (
673 hm_advapi32, "GetSidSubAuthority");
675 if (s_pfn_Get_Sid_Sub_Authority == NULL)
677 return &zero;
679 return (s_pfn_Get_Sid_Sub_Authority (pSid, n));
682 static PUCHAR WINAPI
683 get_sid_sub_authority_count (PSID pSid)
685 static GetSidSubAuthorityCount_Proc s_pfn_Get_Sid_Sub_Authority_Count = NULL;
686 static UCHAR zero = 0U;
687 HMODULE hm_advapi32 = NULL;
688 if (is_windows_9x () == TRUE)
690 return &zero;
692 if (g_b_init_get_sid_sub_authority_count == 0)
694 g_b_init_get_sid_sub_authority_count = 1;
695 hm_advapi32 = LoadLibrary ("Advapi32.dll");
696 s_pfn_Get_Sid_Sub_Authority_Count =
697 (GetSidSubAuthorityCount_Proc) GetProcAddress (
698 hm_advapi32, "GetSidSubAuthorityCount");
700 if (s_pfn_Get_Sid_Sub_Authority_Count == NULL)
702 return &zero;
704 return (s_pfn_Get_Sid_Sub_Authority_Count (pSid));
707 static DWORD WINAPI
708 get_security_info (HANDLE handle,
709 SE_OBJECT_TYPE ObjectType,
710 SECURITY_INFORMATION SecurityInfo,
711 PSID *ppsidOwner,
712 PSID *ppsidGroup,
713 PACL *ppDacl,
714 PACL *ppSacl,
715 PSECURITY_DESCRIPTOR *ppSecurityDescriptor)
717 static GetSecurityInfo_Proc s_pfn_Get_Security_Info = NULL;
718 HMODULE hm_advapi32 = NULL;
719 if (is_windows_9x () == TRUE)
721 return FALSE;
723 if (g_b_init_get_security_info == 0)
725 g_b_init_get_security_info = 1;
726 hm_advapi32 = LoadLibrary ("Advapi32.dll");
727 s_pfn_Get_Security_Info =
728 (GetSecurityInfo_Proc) GetProcAddress (
729 hm_advapi32, "GetSecurityInfo");
731 if (s_pfn_Get_Security_Info == NULL)
733 return FALSE;
735 return (s_pfn_Get_Security_Info (handle, ObjectType, SecurityInfo,
736 ppsidOwner, ppsidGroup, ppDacl, ppSacl,
737 ppSecurityDescriptor));
740 static BOOL WINAPI
741 get_file_security (const char *lpFileName,
742 SECURITY_INFORMATION RequestedInformation,
743 PSECURITY_DESCRIPTOR pSecurityDescriptor,
744 DWORD nLength,
745 LPDWORD lpnLengthNeeded)
747 static GetFileSecurityA_Proc s_pfn_Get_File_SecurityA = NULL;
748 static GetFileSecurityW_Proc s_pfn_Get_File_SecurityW = NULL;
749 HMODULE hm_advapi32 = NULL;
750 if (is_windows_9x () == TRUE)
752 errno = ENOTSUP;
753 return FALSE;
755 if (w32_unicode_filenames)
757 wchar_t filename_w[MAX_PATH];
759 if (g_b_init_get_file_security_w == 0)
761 g_b_init_get_file_security_w = 1;
762 hm_advapi32 = LoadLibrary ("Advapi32.dll");
763 s_pfn_Get_File_SecurityW =
764 (GetFileSecurityW_Proc) GetProcAddress (hm_advapi32,
765 "GetFileSecurityW");
767 if (s_pfn_Get_File_SecurityW == NULL)
769 errno = ENOTSUP;
770 return FALSE;
772 filename_to_utf16 (lpFileName, filename_w);
773 return (s_pfn_Get_File_SecurityW (filename_w, RequestedInformation,
774 pSecurityDescriptor, nLength,
775 lpnLengthNeeded));
777 else
779 char filename_a[MAX_PATH];
781 if (g_b_init_get_file_security_a == 0)
783 g_b_init_get_file_security_a = 1;
784 hm_advapi32 = LoadLibrary ("Advapi32.dll");
785 s_pfn_Get_File_SecurityA =
786 (GetFileSecurityA_Proc) GetProcAddress (hm_advapi32,
787 "GetFileSecurityA");
789 if (s_pfn_Get_File_SecurityA == NULL)
791 errno = ENOTSUP;
792 return FALSE;
794 filename_to_ansi (lpFileName, filename_a);
795 return (s_pfn_Get_File_SecurityA (filename_a, RequestedInformation,
796 pSecurityDescriptor, nLength,
797 lpnLengthNeeded));
801 static BOOL WINAPI
802 set_file_security (const char *lpFileName,
803 SECURITY_INFORMATION SecurityInformation,
804 PSECURITY_DESCRIPTOR pSecurityDescriptor)
806 static SetFileSecurityW_Proc s_pfn_Set_File_SecurityW = NULL;
807 static SetFileSecurityA_Proc s_pfn_Set_File_SecurityA = NULL;
808 HMODULE hm_advapi32 = NULL;
809 if (is_windows_9x () == TRUE)
811 errno = ENOTSUP;
812 return FALSE;
814 if (w32_unicode_filenames)
816 wchar_t filename_w[MAX_PATH];
818 if (g_b_init_set_file_security_w == 0)
820 g_b_init_set_file_security_w = 1;
821 hm_advapi32 = LoadLibrary ("Advapi32.dll");
822 s_pfn_Set_File_SecurityW =
823 (SetFileSecurityW_Proc) GetProcAddress (hm_advapi32,
824 "SetFileSecurityW");
826 if (s_pfn_Set_File_SecurityW == NULL)
828 errno = ENOTSUP;
829 return FALSE;
831 filename_to_utf16 (lpFileName, filename_w);
832 return (s_pfn_Set_File_SecurityW (filename_w, SecurityInformation,
833 pSecurityDescriptor));
835 else
837 char filename_a[MAX_PATH];
839 if (g_b_init_set_file_security_a == 0)
841 g_b_init_set_file_security_a = 1;
842 hm_advapi32 = LoadLibrary ("Advapi32.dll");
843 s_pfn_Set_File_SecurityA =
844 (SetFileSecurityA_Proc) GetProcAddress (hm_advapi32,
845 "SetFileSecurityA");
847 if (s_pfn_Set_File_SecurityA == NULL)
849 errno = ENOTSUP;
850 return FALSE;
852 filename_to_ansi (lpFileName, filename_a);
853 return (s_pfn_Set_File_SecurityA (filename_a, SecurityInformation,
854 pSecurityDescriptor));
858 static DWORD WINAPI
859 set_named_security_info (LPCTSTR lpObjectName,
860 SE_OBJECT_TYPE ObjectType,
861 SECURITY_INFORMATION SecurityInformation,
862 PSID psidOwner,
863 PSID psidGroup,
864 PACL pDacl,
865 PACL pSacl)
867 static SetNamedSecurityInfoW_Proc s_pfn_Set_Named_Security_InfoW = NULL;
868 static SetNamedSecurityInfoA_Proc s_pfn_Set_Named_Security_InfoA = NULL;
869 HMODULE hm_advapi32 = NULL;
870 if (is_windows_9x () == TRUE)
872 errno = ENOTSUP;
873 return ENOTSUP;
875 if (w32_unicode_filenames)
877 wchar_t filename_w[MAX_PATH];
879 if (g_b_init_set_named_security_info_w == 0)
881 g_b_init_set_named_security_info_w = 1;
882 hm_advapi32 = LoadLibrary ("Advapi32.dll");
883 s_pfn_Set_Named_Security_InfoW =
884 (SetNamedSecurityInfoW_Proc) GetProcAddress (hm_advapi32,
885 "SetNamedSecurityInfoW");
887 if (s_pfn_Set_Named_Security_InfoW == NULL)
889 errno = ENOTSUP;
890 return ENOTSUP;
892 filename_to_utf16 (lpObjectName, filename_w);
893 return (s_pfn_Set_Named_Security_InfoW (filename_w, ObjectType,
894 SecurityInformation, psidOwner,
895 psidGroup, pDacl, pSacl));
897 else
899 char filename_a[MAX_PATH];
901 if (g_b_init_set_named_security_info_a == 0)
903 g_b_init_set_named_security_info_a = 1;
904 hm_advapi32 = LoadLibrary ("Advapi32.dll");
905 s_pfn_Set_Named_Security_InfoA =
906 (SetNamedSecurityInfoA_Proc) GetProcAddress (hm_advapi32,
907 "SetNamedSecurityInfoA");
909 if (s_pfn_Set_Named_Security_InfoA == NULL)
911 errno = ENOTSUP;
912 return ENOTSUP;
914 filename_to_ansi (lpObjectName, filename_a);
915 return (s_pfn_Set_Named_Security_InfoA (filename_a, ObjectType,
916 SecurityInformation, psidOwner,
917 psidGroup, pDacl, pSacl));
921 static BOOL WINAPI
922 get_security_descriptor_owner (PSECURITY_DESCRIPTOR pSecurityDescriptor,
923 PSID *pOwner,
924 LPBOOL lpbOwnerDefaulted)
926 static GetSecurityDescriptorOwner_Proc s_pfn_Get_Security_Descriptor_Owner = NULL;
927 HMODULE hm_advapi32 = NULL;
928 if (is_windows_9x () == TRUE)
930 errno = ENOTSUP;
931 return FALSE;
933 if (g_b_init_get_security_descriptor_owner == 0)
935 g_b_init_get_security_descriptor_owner = 1;
936 hm_advapi32 = LoadLibrary ("Advapi32.dll");
937 s_pfn_Get_Security_Descriptor_Owner =
938 (GetSecurityDescriptorOwner_Proc) GetProcAddress (
939 hm_advapi32, "GetSecurityDescriptorOwner");
941 if (s_pfn_Get_Security_Descriptor_Owner == NULL)
943 errno = ENOTSUP;
944 return FALSE;
946 return (s_pfn_Get_Security_Descriptor_Owner (pSecurityDescriptor, pOwner,
947 lpbOwnerDefaulted));
950 static BOOL WINAPI
951 get_security_descriptor_group (PSECURITY_DESCRIPTOR pSecurityDescriptor,
952 PSID *pGroup,
953 LPBOOL lpbGroupDefaulted)
955 static GetSecurityDescriptorGroup_Proc s_pfn_Get_Security_Descriptor_Group = NULL;
956 HMODULE hm_advapi32 = NULL;
957 if (is_windows_9x () == TRUE)
959 errno = ENOTSUP;
960 return FALSE;
962 if (g_b_init_get_security_descriptor_group == 0)
964 g_b_init_get_security_descriptor_group = 1;
965 hm_advapi32 = LoadLibrary ("Advapi32.dll");
966 s_pfn_Get_Security_Descriptor_Group =
967 (GetSecurityDescriptorGroup_Proc) GetProcAddress (
968 hm_advapi32, "GetSecurityDescriptorGroup");
970 if (s_pfn_Get_Security_Descriptor_Group == NULL)
972 errno = ENOTSUP;
973 return FALSE;
975 return (s_pfn_Get_Security_Descriptor_Group (pSecurityDescriptor, pGroup,
976 lpbGroupDefaulted));
979 static BOOL WINAPI
980 get_security_descriptor_dacl (PSECURITY_DESCRIPTOR pSecurityDescriptor,
981 LPBOOL lpbDaclPresent,
982 PACL *pDacl,
983 LPBOOL lpbDaclDefaulted)
985 static GetSecurityDescriptorDacl_Proc s_pfn_Get_Security_Descriptor_Dacl = NULL;
986 HMODULE hm_advapi32 = NULL;
987 if (is_windows_9x () == TRUE)
989 errno = ENOTSUP;
990 return FALSE;
992 if (g_b_init_get_security_descriptor_dacl == 0)
994 g_b_init_get_security_descriptor_dacl = 1;
995 hm_advapi32 = LoadLibrary ("Advapi32.dll");
996 s_pfn_Get_Security_Descriptor_Dacl =
997 (GetSecurityDescriptorDacl_Proc) GetProcAddress (
998 hm_advapi32, "GetSecurityDescriptorDacl");
1000 if (s_pfn_Get_Security_Descriptor_Dacl == NULL)
1002 errno = ENOTSUP;
1003 return FALSE;
1005 return (s_pfn_Get_Security_Descriptor_Dacl (pSecurityDescriptor,
1006 lpbDaclPresent, pDacl,
1007 lpbDaclDefaulted));
1010 static BOOL WINAPI
1011 is_valid_sid (PSID sid)
1013 static IsValidSid_Proc s_pfn_Is_Valid_Sid = NULL;
1014 HMODULE hm_advapi32 = NULL;
1015 if (is_windows_9x () == TRUE)
1017 return FALSE;
1019 if (g_b_init_is_valid_sid == 0)
1021 g_b_init_is_valid_sid = 1;
1022 hm_advapi32 = LoadLibrary ("Advapi32.dll");
1023 s_pfn_Is_Valid_Sid =
1024 (IsValidSid_Proc) GetProcAddress (
1025 hm_advapi32, "IsValidSid");
1027 if (s_pfn_Is_Valid_Sid == NULL)
1029 return FALSE;
1031 return (s_pfn_Is_Valid_Sid (sid));
1034 static BOOL WINAPI
1035 equal_sid (PSID sid1, PSID sid2)
1037 static EqualSid_Proc s_pfn_Equal_Sid = NULL;
1038 HMODULE hm_advapi32 = NULL;
1039 if (is_windows_9x () == TRUE)
1041 return FALSE;
1043 if (g_b_init_equal_sid == 0)
1045 g_b_init_equal_sid = 1;
1046 hm_advapi32 = LoadLibrary ("Advapi32.dll");
1047 s_pfn_Equal_Sid =
1048 (EqualSid_Proc) GetProcAddress (
1049 hm_advapi32, "EqualSid");
1051 if (s_pfn_Equal_Sid == NULL)
1053 return FALSE;
1055 return (s_pfn_Equal_Sid (sid1, sid2));
1058 static DWORD WINAPI
1059 get_length_sid (PSID sid)
1061 static GetLengthSid_Proc s_pfn_Get_Length_Sid = NULL;
1062 HMODULE hm_advapi32 = NULL;
1063 if (is_windows_9x () == TRUE)
1065 return 0;
1067 if (g_b_init_get_length_sid == 0)
1069 g_b_init_get_length_sid = 1;
1070 hm_advapi32 = LoadLibrary ("Advapi32.dll");
1071 s_pfn_Get_Length_Sid =
1072 (GetLengthSid_Proc) GetProcAddress (
1073 hm_advapi32, "GetLengthSid");
1075 if (s_pfn_Get_Length_Sid == NULL)
1077 return 0;
1079 return (s_pfn_Get_Length_Sid (sid));
1082 static BOOL WINAPI
1083 copy_sid (DWORD destlen, PSID dest, PSID src)
1085 static CopySid_Proc s_pfn_Copy_Sid = NULL;
1086 HMODULE hm_advapi32 = NULL;
1087 if (is_windows_9x () == TRUE)
1089 return FALSE;
1091 if (g_b_init_copy_sid == 0)
1093 g_b_init_copy_sid = 1;
1094 hm_advapi32 = LoadLibrary ("Advapi32.dll");
1095 s_pfn_Copy_Sid =
1096 (CopySid_Proc) GetProcAddress (
1097 hm_advapi32, "CopySid");
1099 if (s_pfn_Copy_Sid == NULL)
1101 return FALSE;
1103 return (s_pfn_Copy_Sid (destlen, dest, src));
1107 END: Wrapper functions around OpenProcessToken
1108 and other functions in advapi32.dll that are only
1109 supported in Windows NT / 2k / XP
1112 static void WINAPI
1113 get_native_system_info (LPSYSTEM_INFO lpSystemInfo)
1115 static GetNativeSystemInfo_Proc s_pfn_Get_Native_System_Info = NULL;
1116 if (is_windows_9x () != TRUE)
1118 if (g_b_init_get_native_system_info == 0)
1120 g_b_init_get_native_system_info = 1;
1121 s_pfn_Get_Native_System_Info =
1122 (GetNativeSystemInfo_Proc)GetProcAddress (GetModuleHandle ("kernel32.dll"),
1123 "GetNativeSystemInfo");
1125 if (s_pfn_Get_Native_System_Info != NULL)
1126 s_pfn_Get_Native_System_Info (lpSystemInfo);
1128 else
1129 lpSystemInfo->dwNumberOfProcessors = -1;
1132 static BOOL WINAPI
1133 get_system_times (LPFILETIME lpIdleTime,
1134 LPFILETIME lpKernelTime,
1135 LPFILETIME lpUserTime)
1137 static GetSystemTimes_Proc s_pfn_Get_System_times = NULL;
1138 if (is_windows_9x () == TRUE)
1140 return FALSE;
1142 if (g_b_init_get_system_times == 0)
1144 g_b_init_get_system_times = 1;
1145 s_pfn_Get_System_times =
1146 (GetSystemTimes_Proc)GetProcAddress (GetModuleHandle ("kernel32.dll"),
1147 "GetSystemTimes");
1149 if (s_pfn_Get_System_times == NULL)
1150 return FALSE;
1151 return (s_pfn_Get_System_times (lpIdleTime, lpKernelTime, lpUserTime));
1154 static BOOLEAN WINAPI
1155 create_symbolic_link (LPCSTR lpSymlinkFilename,
1156 LPCSTR lpTargetFileName,
1157 DWORD dwFlags)
1159 static CreateSymbolicLinkW_Proc s_pfn_Create_Symbolic_LinkW = NULL;
1160 static CreateSymbolicLinkA_Proc s_pfn_Create_Symbolic_LinkA = NULL;
1161 BOOLEAN retval;
1163 if (is_windows_9x () == TRUE)
1165 errno = ENOSYS;
1166 return 0;
1168 if (w32_unicode_filenames)
1170 wchar_t symfn_w[MAX_PATH], tgtfn_w[MAX_PATH];
1172 if (g_b_init_create_symbolic_link_w == 0)
1174 g_b_init_create_symbolic_link_w = 1;
1175 s_pfn_Create_Symbolic_LinkW =
1176 (CreateSymbolicLinkW_Proc)GetProcAddress (GetModuleHandle ("kernel32.dll"),
1177 "CreateSymbolicLinkW");
1179 if (s_pfn_Create_Symbolic_LinkW == NULL)
1181 errno = ENOSYS;
1182 return 0;
1185 filename_to_utf16 (lpSymlinkFilename, symfn_w);
1186 filename_to_utf16 (lpTargetFileName, tgtfn_w);
1187 retval = s_pfn_Create_Symbolic_LinkW (symfn_w, tgtfn_w, dwFlags);
1188 /* If we were denied creation of the symlink, try again after
1189 enabling the SeCreateSymbolicLinkPrivilege for our process. */
1190 if (!retval)
1192 TOKEN_PRIVILEGES priv_current;
1194 if (enable_privilege (SE_CREATE_SYMBOLIC_LINK_NAME, TRUE,
1195 &priv_current))
1197 retval = s_pfn_Create_Symbolic_LinkW (symfn_w, tgtfn_w, dwFlags);
1198 restore_privilege (&priv_current);
1199 revert_to_self ();
1203 else
1205 char symfn_a[MAX_PATH], tgtfn_a[MAX_PATH];
1207 if (g_b_init_create_symbolic_link_a == 0)
1209 g_b_init_create_symbolic_link_a = 1;
1210 s_pfn_Create_Symbolic_LinkA =
1211 (CreateSymbolicLinkA_Proc)GetProcAddress (GetModuleHandle ("kernel32.dll"),
1212 "CreateSymbolicLinkA");
1214 if (s_pfn_Create_Symbolic_LinkA == NULL)
1216 errno = ENOSYS;
1217 return 0;
1220 filename_to_ansi (lpSymlinkFilename, symfn_a);
1221 filename_to_ansi (lpTargetFileName, tgtfn_a);
1222 retval = s_pfn_Create_Symbolic_LinkA (symfn_a, tgtfn_a, dwFlags);
1223 /* If we were denied creation of the symlink, try again after
1224 enabling the SeCreateSymbolicLinkPrivilege for our process. */
1225 if (!retval)
1227 TOKEN_PRIVILEGES priv_current;
1229 if (enable_privilege (SE_CREATE_SYMBOLIC_LINK_NAME, TRUE,
1230 &priv_current))
1232 retval = s_pfn_Create_Symbolic_LinkA (symfn_a, tgtfn_a, dwFlags);
1233 restore_privilege (&priv_current);
1234 revert_to_self ();
1238 return retval;
1241 static BOOL WINAPI
1242 is_valid_security_descriptor (PSECURITY_DESCRIPTOR pSecurityDescriptor)
1244 static IsValidSecurityDescriptor_Proc s_pfn_Is_Valid_Security_Descriptor_Proc = NULL;
1246 if (is_windows_9x () == TRUE)
1248 errno = ENOTSUP;
1249 return FALSE;
1252 if (g_b_init_is_valid_security_descriptor == 0)
1254 g_b_init_is_valid_security_descriptor = 1;
1255 s_pfn_Is_Valid_Security_Descriptor_Proc =
1256 (IsValidSecurityDescriptor_Proc)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1257 "IsValidSecurityDescriptor");
1259 if (s_pfn_Is_Valid_Security_Descriptor_Proc == NULL)
1261 errno = ENOTSUP;
1262 return FALSE;
1265 return s_pfn_Is_Valid_Security_Descriptor_Proc (pSecurityDescriptor);
1268 static BOOL WINAPI
1269 convert_sd_to_sddl (PSECURITY_DESCRIPTOR SecurityDescriptor,
1270 DWORD RequestedStringSDRevision,
1271 SECURITY_INFORMATION SecurityInformation,
1272 LPTSTR *StringSecurityDescriptor,
1273 PULONG StringSecurityDescriptorLen)
1275 static ConvertSecurityDescriptorToStringSecurityDescriptor_Proc s_pfn_Convert_SD_To_SDDL = NULL;
1276 BOOL retval;
1278 if (is_windows_9x () == TRUE)
1280 errno = ENOTSUP;
1281 return FALSE;
1284 if (g_b_init_convert_sd_to_sddl == 0)
1286 g_b_init_convert_sd_to_sddl = 1;
1287 #ifdef _UNICODE
1288 s_pfn_Convert_SD_To_SDDL =
1289 (ConvertSecurityDescriptorToStringSecurityDescriptor_Proc)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1290 "ConvertSecurityDescriptorToStringSecurityDescriptorW");
1291 #else
1292 s_pfn_Convert_SD_To_SDDL =
1293 (ConvertSecurityDescriptorToStringSecurityDescriptor_Proc)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1294 "ConvertSecurityDescriptorToStringSecurityDescriptorA");
1295 #endif
1297 if (s_pfn_Convert_SD_To_SDDL == NULL)
1299 errno = ENOTSUP;
1300 return FALSE;
1303 retval = s_pfn_Convert_SD_To_SDDL (SecurityDescriptor,
1304 RequestedStringSDRevision,
1305 SecurityInformation,
1306 StringSecurityDescriptor,
1307 StringSecurityDescriptorLen);
1309 return retval;
1312 static BOOL WINAPI
1313 convert_sddl_to_sd (LPCTSTR StringSecurityDescriptor,
1314 DWORD StringSDRevision,
1315 PSECURITY_DESCRIPTOR *SecurityDescriptor,
1316 PULONG SecurityDescriptorSize)
1318 static ConvertStringSecurityDescriptorToSecurityDescriptor_Proc s_pfn_Convert_SDDL_To_SD = NULL;
1319 BOOL retval;
1321 if (is_windows_9x () == TRUE)
1323 errno = ENOTSUP;
1324 return FALSE;
1327 if (g_b_init_convert_sddl_to_sd == 0)
1329 g_b_init_convert_sddl_to_sd = 1;
1330 #ifdef _UNICODE
1331 s_pfn_Convert_SDDL_To_SD =
1332 (ConvertStringSecurityDescriptorToSecurityDescriptor_Proc)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1333 "ConvertStringSecurityDescriptorToSecurityDescriptorW");
1334 #else
1335 s_pfn_Convert_SDDL_To_SD =
1336 (ConvertStringSecurityDescriptorToSecurityDescriptor_Proc)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1337 "ConvertStringSecurityDescriptorToSecurityDescriptorA");
1338 #endif
1340 if (s_pfn_Convert_SDDL_To_SD == NULL)
1342 errno = ENOTSUP;
1343 return FALSE;
1346 retval = s_pfn_Convert_SDDL_To_SD (StringSecurityDescriptor,
1347 StringSDRevision,
1348 SecurityDescriptor,
1349 SecurityDescriptorSize);
1351 return retval;
1354 static DWORD WINAPI
1355 get_adapters_info (PIP_ADAPTER_INFO pAdapterInfo, PULONG pOutBufLen)
1357 static GetAdaptersInfo_Proc s_pfn_Get_Adapters_Info = NULL;
1358 HMODULE hm_iphlpapi = NULL;
1360 if (is_windows_9x () == TRUE)
1361 return ERROR_NOT_SUPPORTED;
1363 if (g_b_init_get_adapters_info == 0)
1365 g_b_init_get_adapters_info = 1;
1366 hm_iphlpapi = LoadLibrary ("Iphlpapi.dll");
1367 if (hm_iphlpapi)
1368 s_pfn_Get_Adapters_Info = (GetAdaptersInfo_Proc)
1369 GetProcAddress (hm_iphlpapi, "GetAdaptersInfo");
1371 if (s_pfn_Get_Adapters_Info == NULL)
1372 return ERROR_NOT_SUPPORTED;
1373 return s_pfn_Get_Adapters_Info (pAdapterInfo, pOutBufLen);
1378 /* Return 1 if P is a valid pointer to an object of size SIZE. Return
1379 0 if P is NOT a valid pointer. Return -1 if we cannot validate P.
1381 This is called from alloc.c:valid_pointer_p. */
1383 w32_valid_pointer_p (void *p, int size)
1385 SIZE_T done;
1386 HANDLE h = OpenProcess (PROCESS_VM_READ, FALSE, GetCurrentProcessId ());
1388 if (h)
1390 unsigned char *buf = alloca (size);
1391 int retval = ReadProcessMemory (h, p, buf, size, &done);
1393 CloseHandle (h);
1394 return retval;
1396 else
1397 return -1;
1402 /* Here's an overview of how the Windows build supports file names
1403 that cannot be encoded by the current system codepage.
1405 From the POV of Lisp and layers of C code above the functions here,
1406 Emacs on Windows pretends that its file names are encoded in UTF-8;
1407 see encode_file and decode_file on coding.c. Any file name that is
1408 passed as a unibyte string to C functions defined here is assumed
1409 to be in UTF-8 encoding. Any file name returned by functions
1410 defined here must be in UTF-8 encoding, with only a few exceptions
1411 reserved for a couple of special cases. (Be sure to use
1412 MAX_UTF8_PATH for char arrays that store UTF-8 encoded file names,
1413 as they can be much longer than MAX_PATH!)
1415 The UTF-8 encoded file names cannot be passed to system APIs, as
1416 Windows does not support that. Therefore, they are converted
1417 either to UTF-16 or to the ANSI codepage, depending on the value of
1418 w32-unicode-filenames, before calling any system APIs or CRT library
1419 functions. The default value of that variable is determined by the
1420 OS on which Emacs runs: nil on Windows 9X and t otherwise, but the
1421 user can change that default (although I don't see why would she
1422 want to).
1424 The 4 functions defined below, filename_to_utf16, filename_to_ansi,
1425 filename_from_utf16, and filename_from_ansi, are the workhorses of
1426 these conversions. They rely on Windows native APIs
1427 MultiByteToWideChar and WideCharToMultiByte; we cannot use
1428 functions from coding.c here, because they allocate memory, which
1429 is a bad idea on the level of libc, which is what the functions
1430 here emulate. (If you worry about performance due to constant
1431 conversion back and forth from UTF-8 to UTF-16, then don't: first,
1432 it was measured to take only a few microseconds on a not-so-fast
1433 machine, and second, that's exactly what the ANSI APIs we used
1434 before did anyway, because they are just thin wrappers around the
1435 Unicode APIs.)
1437 The variables file-name-coding-system and default-file-name-coding-system
1438 still exist, but are actually used only when a file name needs to
1439 be converted to the ANSI codepage. This happens all the time when
1440 w32-unicode-filenames is nil, but can also happen from time to time
1441 when it is t. Otherwise, these variables have no effect on file-name
1442 encoding when w32-unicode-filenames is t; this is similar to
1443 selection-coding-system.
1445 This arrangement works very well, but it has a few gotchas and
1446 limitations:
1448 . Lisp code that encodes or decodes file names manually should
1449 normally use 'utf-8' as the coding-system on Windows,
1450 disregarding file-name-coding-system. This is a somewhat
1451 unpleasant consequence, but it cannot be avoided. Fortunately,
1452 very few Lisp packages need to do that.
1454 More generally, passing to library functions (e.g., fopen or
1455 opendir) file names already encoded in the ANSI codepage is
1456 explicitly *verboten*, as all those functions, as shadowed and
1457 emulated here, assume they will receive UTF-8 encoded file names.
1459 For the same reasons, no CRT function or Win32 API can be called
1460 directly in Emacs sources, without either converting the file
1461 names from UTF-8 to UTF-16 or ANSI codepage, or going through
1462 some shadowing function defined here.
1464 . Environment variables stored in Vprocess_environment are encoded
1465 in the ANSI codepage, so if getenv/egetenv is used for a variable
1466 whose value is a file name or a list of directories, it needs to
1467 be converted to UTF-8, before it is used as argument to functions
1468 or decoded into a Lisp string.
1470 . File names passed to external libraries, like the image libraries
1471 and GnuTLS, need special handling. These libraries generally
1472 don't support UTF-16 or UTF-8 file names, so they must get file
1473 names encoded in the ANSI codepage. To facilitate using these
1474 libraries with file names that are not encodable in the ANSI
1475 codepage, use the function ansi_encode_filename, which will try
1476 to use the short 8+3 alias of a file name if that file name is
1477 not encodable in the ANSI codepage. See image.c and gnutls.c for
1478 examples of how this should be done.
1480 . Running subprocesses in non-ASCII directories and with non-ASCII
1481 file arguments is limited to the current codepage (even though
1482 Emacs is perfectly capable of finding an executable program file
1483 in a directory whose name cannot be encoded in the current
1484 codepage). This is because the command-line arguments are
1485 encoded _before_ they get to the w32-specific level, and the
1486 encoding is not known in advance (it doesn't have to be the
1487 current ANSI codepage), so w32proc.c functions cannot re-encode
1488 them in UTF-16. This should be fixed, but will also require
1489 changes in cmdproxy. The current limitation is not terribly bad
1490 anyway, since very few, if any, Windows console programs that are
1491 likely to be invoked by Emacs support UTF-16 encoded command
1492 lines.
1494 . For similar reasons, server.el and emacsclient are also limited
1495 to the current ANSI codepage for now.
1497 . Emacs itself can only handle command-line arguments encoded in
1498 the current codepage.
1500 . Turning on w32-unicode-filename on Windows 9X (if it at all
1501 works) requires UNICOWS.DLL, which is thus a requirement even in
1502 non-GUI sessions, something the we previously avoided. */
1506 /* Converting file names from UTF-8 to either UTF-16 or the ANSI
1507 codepage defined by file-name-coding-system. */
1509 /* Current codepage for encoding file names. */
1510 static int file_name_codepage;
1512 /* Produce a Windows ANSI codepage suitable for encoding file names.
1513 Return the information about that codepage in CP_INFO. */
1515 codepage_for_filenames (CPINFO *cp_info)
1517 /* A simple cache to avoid calling GetCPInfo every time we need to
1518 encode/decode a file name. The file-name encoding is not
1519 supposed to be changed too frequently, if ever. */
1520 static Lisp_Object last_file_name_encoding;
1521 static CPINFO cp;
1522 Lisp_Object current_encoding;
1524 current_encoding = Vfile_name_coding_system;
1525 if (NILP (current_encoding))
1526 current_encoding = Vdefault_file_name_coding_system;
1528 if (!EQ (last_file_name_encoding, current_encoding))
1530 /* Default to the current ANSI codepage. */
1531 file_name_codepage = w32_ansi_code_page;
1533 if (NILP (current_encoding))
1535 char *cpname = SSDATA (SYMBOL_NAME (current_encoding));
1536 char *cp = NULL, *end;
1537 int cpnum;
1539 if (strncmp (cpname, "cp", 2) == 0)
1540 cp = cpname + 2;
1541 else if (strncmp (cpname, "windows-", 8) == 0)
1542 cp = cpname + 8;
1544 if (cp)
1546 end = cp;
1547 cpnum = strtol (cp, &end, 10);
1548 if (cpnum && *end == '\0' && end - cp >= 2)
1549 file_name_codepage = cpnum;
1553 if (!file_name_codepage)
1554 file_name_codepage = CP_ACP; /* CP_ACP = 0, but let's not assume that */
1556 if (!GetCPInfo (file_name_codepage, &cp))
1558 file_name_codepage = CP_ACP;
1559 if (!GetCPInfo (file_name_codepage, &cp))
1560 emacs_abort ();
1563 if (cp_info)
1564 *cp_info = cp;
1566 return file_name_codepage;
1570 filename_to_utf16 (const char *fn_in, wchar_t *fn_out)
1572 int result = pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags, fn_in,
1573 -1, fn_out, MAX_PATH);
1575 if (!result)
1577 DWORD err = GetLastError ();
1579 switch (err)
1581 case ERROR_INVALID_FLAGS:
1582 case ERROR_INVALID_PARAMETER:
1583 errno = EINVAL;
1584 break;
1585 case ERROR_INSUFFICIENT_BUFFER:
1586 case ERROR_NO_UNICODE_TRANSLATION:
1587 default:
1588 errno = ENOENT;
1589 break;
1591 return -1;
1593 return 0;
1597 filename_from_utf16 (const wchar_t *fn_in, char *fn_out)
1599 int result = pWideCharToMultiByte (CP_UTF8, 0, fn_in, -1,
1600 fn_out, MAX_UTF8_PATH, NULL, NULL);
1602 if (!result)
1604 DWORD err = GetLastError ();
1606 switch (err)
1608 case ERROR_INVALID_FLAGS:
1609 case ERROR_INVALID_PARAMETER:
1610 errno = EINVAL;
1611 break;
1612 case ERROR_INSUFFICIENT_BUFFER:
1613 case ERROR_NO_UNICODE_TRANSLATION:
1614 default:
1615 errno = ENOENT;
1616 break;
1618 return -1;
1620 return 0;
1624 filename_to_ansi (const char *fn_in, char *fn_out)
1626 wchar_t fn_utf16[MAX_PATH];
1628 if (filename_to_utf16 (fn_in, fn_utf16) == 0)
1630 int result;
1631 int codepage = codepage_for_filenames (NULL);
1633 result = pWideCharToMultiByte (codepage, 0, fn_utf16, -1,
1634 fn_out, MAX_PATH, NULL, NULL);
1635 if (!result)
1637 DWORD err = GetLastError ();
1639 switch (err)
1641 case ERROR_INVALID_FLAGS:
1642 case ERROR_INVALID_PARAMETER:
1643 errno = EINVAL;
1644 break;
1645 case ERROR_INSUFFICIENT_BUFFER:
1646 case ERROR_NO_UNICODE_TRANSLATION:
1647 default:
1648 errno = ENOENT;
1649 break;
1651 return -1;
1653 return 0;
1655 return -1;
1659 filename_from_ansi (const char *fn_in, char *fn_out)
1661 wchar_t fn_utf16[MAX_PATH];
1662 int codepage = codepage_for_filenames (NULL);
1663 int result = pMultiByteToWideChar (codepage, multiByteToWideCharFlags, fn_in,
1664 -1, fn_utf16, MAX_PATH);
1666 if (!result)
1668 DWORD err = GetLastError ();
1670 switch (err)
1672 case ERROR_INVALID_FLAGS:
1673 case ERROR_INVALID_PARAMETER:
1674 errno = EINVAL;
1675 break;
1676 case ERROR_INSUFFICIENT_BUFFER:
1677 case ERROR_NO_UNICODE_TRANSLATION:
1678 default:
1679 errno = ENOENT;
1680 break;
1682 return -1;
1684 return filename_from_utf16 (fn_utf16, fn_out);
1689 /* The directory where we started, in UTF-8. */
1690 static char startup_dir[MAX_UTF8_PATH];
1692 /* Get the current working directory. */
1693 char *
1694 getcwd (char *dir, int dirsize)
1696 if (!dirsize)
1698 errno = EINVAL;
1699 return NULL;
1701 if (dirsize <= strlen (startup_dir))
1703 errno = ERANGE;
1704 return NULL;
1706 #if 0
1707 if (GetCurrentDirectory (MAXPATHLEN, dir) > 0)
1708 return dir;
1709 return NULL;
1710 #else
1711 /* Emacs doesn't actually change directory itself, it stays in the
1712 same directory where it was started. */
1713 strcpy (dir, startup_dir);
1714 return dir;
1715 #endif
1718 /* Emulate getloadavg. */
1720 struct load_sample {
1721 time_t sample_time;
1722 ULONGLONG idle;
1723 ULONGLONG kernel;
1724 ULONGLONG user;
1727 /* Number of processors on this machine. */
1728 static unsigned num_of_processors;
1730 /* We maintain 1-sec samples for the last 16 minutes in a circular buffer. */
1731 static struct load_sample samples[16*60];
1732 static int first_idx = -1, last_idx = -1;
1733 static int max_idx = ARRAYELTS (samples);
1735 static int
1736 buf_next (int from)
1738 int next_idx = from + 1;
1740 if (next_idx >= max_idx)
1741 next_idx = 0;
1743 return next_idx;
1746 static int
1747 buf_prev (int from)
1749 int prev_idx = from - 1;
1751 if (prev_idx < 0)
1752 prev_idx = max_idx - 1;
1754 return prev_idx;
1757 static void
1758 sample_system_load (ULONGLONG *idle, ULONGLONG *kernel, ULONGLONG *user)
1760 SYSTEM_INFO sysinfo;
1761 FILETIME ft_idle, ft_user, ft_kernel;
1763 /* Initialize the number of processors on this machine. */
1764 if (num_of_processors <= 0)
1766 get_native_system_info (&sysinfo);
1767 num_of_processors = sysinfo.dwNumberOfProcessors;
1768 if (num_of_processors <= 0)
1770 GetSystemInfo (&sysinfo);
1771 num_of_processors = sysinfo.dwNumberOfProcessors;
1773 if (num_of_processors <= 0)
1774 num_of_processors = 1;
1777 /* TODO: Take into account threads that are ready to run, by
1778 sampling the "\System\Processor Queue Length" performance
1779 counter. The code below accounts only for threads that are
1780 actually running. */
1782 if (get_system_times (&ft_idle, &ft_kernel, &ft_user))
1784 ULARGE_INTEGER uidle, ukernel, uuser;
1786 memcpy (&uidle, &ft_idle, sizeof (ft_idle));
1787 memcpy (&ukernel, &ft_kernel, sizeof (ft_kernel));
1788 memcpy (&uuser, &ft_user, sizeof (ft_user));
1789 *idle = uidle.QuadPart;
1790 *kernel = ukernel.QuadPart;
1791 *user = uuser.QuadPart;
1793 else
1795 *idle = 0;
1796 *kernel = 0;
1797 *user = 0;
1801 /* Produce the load average for a given time interval, using the
1802 samples in the samples[] array. WHICH can be 0, 1, or 2, meaning
1803 1-minute, 5-minute, or 15-minute average, respectively. */
1804 static double
1805 getavg (int which)
1807 double retval = -1.0;
1808 double tdiff;
1809 int idx;
1810 double span = (which == 0 ? 1.0 : (which == 1 ? 5.0 : 15.0)) * 60;
1811 time_t now = samples[last_idx].sample_time;
1813 if (first_idx != last_idx)
1815 for (idx = buf_prev (last_idx); ; idx = buf_prev (idx))
1817 tdiff = difftime (now, samples[idx].sample_time);
1818 if (tdiff >= span - 2*DBL_EPSILON*now)
1820 long double sys =
1821 samples[last_idx].kernel + samples[last_idx].user
1822 - (samples[idx].kernel + samples[idx].user);
1823 long double idl = samples[last_idx].idle - samples[idx].idle;
1825 retval = (1.0 - idl / sys) * num_of_processors;
1826 break;
1828 if (idx == first_idx)
1829 break;
1833 return retval;
1837 getloadavg (double loadavg[], int nelem)
1839 int elem;
1840 ULONGLONG idle, kernel, user;
1841 time_t now = time (NULL);
1843 /* If system time jumped back for some reason, delete all samples
1844 whose time is later than the current wall-clock time. This
1845 prevents load average figures from becoming frozen for prolonged
1846 periods of time, when system time is reset backwards. */
1847 if (last_idx >= 0)
1849 while (difftime (now, samples[last_idx].sample_time) < -1.0)
1851 if (last_idx == first_idx)
1853 first_idx = last_idx = -1;
1854 break;
1856 last_idx = buf_prev (last_idx);
1860 /* Store another sample. We ignore samples that are less than 1 sec
1861 apart. */
1862 if (last_idx < 0
1863 || (difftime (now, samples[last_idx].sample_time)
1864 >= 1.0 - 2*DBL_EPSILON*now))
1866 sample_system_load (&idle, &kernel, &user);
1867 last_idx = buf_next (last_idx);
1868 samples[last_idx].sample_time = now;
1869 samples[last_idx].idle = idle;
1870 samples[last_idx].kernel = kernel;
1871 samples[last_idx].user = user;
1872 /* If the buffer has more that 15 min worth of samples, discard
1873 the old ones. */
1874 if (first_idx == -1)
1875 first_idx = last_idx;
1876 while (first_idx != last_idx
1877 && (difftime (now, samples[first_idx].sample_time)
1878 >= 15.0*60 + 2*DBL_EPSILON*now))
1879 first_idx = buf_next (first_idx);
1882 for (elem = 0; elem < nelem; elem++)
1884 double avg = getavg (elem);
1886 if (avg < 0)
1887 break;
1888 loadavg[elem] = avg;
1891 return elem;
1894 /* Emulate getpwuid, getpwnam and others. */
1896 #define PASSWD_FIELD_SIZE 256
1898 static char dflt_passwd_name[PASSWD_FIELD_SIZE];
1899 static char dflt_passwd_passwd[PASSWD_FIELD_SIZE];
1900 static char dflt_passwd_gecos[PASSWD_FIELD_SIZE];
1901 static char dflt_passwd_dir[MAX_UTF8_PATH];
1902 static char dflt_passwd_shell[MAX_UTF8_PATH];
1904 static struct passwd dflt_passwd =
1906 dflt_passwd_name,
1907 dflt_passwd_passwd,
1911 dflt_passwd_gecos,
1912 dflt_passwd_dir,
1913 dflt_passwd_shell,
1916 static char dflt_group_name[GNLEN+1];
1918 static struct group dflt_group =
1920 /* When group information is not available, we return this as the
1921 group for all files. */
1922 dflt_group_name,
1926 unsigned
1927 getuid (void)
1929 return dflt_passwd.pw_uid;
1932 unsigned
1933 geteuid (void)
1935 /* I could imagine arguing for checking to see whether the user is
1936 in the Administrators group and returning a UID of 0 for that
1937 case, but I don't know how wise that would be in the long run. */
1938 return getuid ();
1941 unsigned
1942 getgid (void)
1944 return dflt_passwd.pw_gid;
1947 unsigned
1948 getegid (void)
1950 return getgid ();
1953 struct passwd *
1954 getpwuid (unsigned uid)
1956 if (uid == dflt_passwd.pw_uid)
1957 return &dflt_passwd;
1958 return NULL;
1961 struct group *
1962 getgrgid (gid_t gid)
1964 return &dflt_group;
1967 struct passwd *
1968 getpwnam (char *name)
1970 struct passwd *pw;
1972 pw = getpwuid (getuid ());
1973 if (!pw)
1974 return pw;
1976 if (xstrcasecmp (name, pw->pw_name))
1977 return NULL;
1979 return pw;
1982 static void
1983 init_user_info (void)
1985 /* Find the user's real name by opening the process token and
1986 looking up the name associated with the user-sid in that token.
1988 Use the relative portion of the identifier authority value from
1989 the user-sid as the user id value (same for group id using the
1990 primary group sid from the process token). */
1992 char uname[UNLEN+1], gname[GNLEN+1], domain[1025];
1993 DWORD ulength = sizeof (uname), dlength = sizeof (domain), needed;
1994 DWORD glength = sizeof (gname);
1995 HANDLE token = NULL;
1996 SID_NAME_USE user_type;
1997 unsigned char *buf = NULL;
1998 DWORD blen = 0;
1999 TOKEN_USER user_token;
2000 TOKEN_PRIMARY_GROUP group_token;
2001 BOOL result;
2003 result = open_process_token (GetCurrentProcess (), TOKEN_QUERY, &token);
2004 if (result)
2006 result = get_token_information (token, TokenUser, NULL, 0, &blen);
2007 if (!result && GetLastError () == ERROR_INSUFFICIENT_BUFFER)
2009 buf = xmalloc (blen);
2010 result = get_token_information (token, TokenUser,
2011 (LPVOID)buf, blen, &needed);
2012 if (result)
2014 memcpy (&user_token, buf, sizeof (user_token));
2015 result = lookup_account_sid (NULL, user_token.User.Sid,
2016 uname, &ulength,
2017 domain, &dlength, &user_type);
2020 else
2021 result = FALSE;
2023 if (result)
2025 strcpy (dflt_passwd.pw_name, uname);
2026 /* Determine a reasonable uid value. */
2027 if (xstrcasecmp ("administrator", uname) == 0)
2029 dflt_passwd.pw_uid = 500; /* well-known Administrator uid */
2030 dflt_passwd.pw_gid = 513; /* well-known None gid */
2032 else
2034 /* Use the last sub-authority value of the RID, the relative
2035 portion of the SID, as user/group ID. */
2036 dflt_passwd.pw_uid = get_rid (user_token.User.Sid);
2038 /* Get group id and name. */
2039 result = get_token_information (token, TokenPrimaryGroup,
2040 (LPVOID)buf, blen, &needed);
2041 if (!result && GetLastError () == ERROR_INSUFFICIENT_BUFFER)
2043 buf = xrealloc (buf, blen = needed);
2044 result = get_token_information (token, TokenPrimaryGroup,
2045 (LPVOID)buf, blen, &needed);
2047 if (result)
2049 memcpy (&group_token, buf, sizeof (group_token));
2050 dflt_passwd.pw_gid = get_rid (group_token.PrimaryGroup);
2051 dlength = sizeof (domain);
2052 /* If we can get at the real Primary Group name, use that.
2053 Otherwise, the default group name was already set to
2054 "None" in globals_of_w32. */
2055 if (lookup_account_sid (NULL, group_token.PrimaryGroup,
2056 gname, &glength, NULL, &dlength,
2057 &user_type))
2058 strcpy (dflt_group_name, gname);
2060 else
2061 dflt_passwd.pw_gid = dflt_passwd.pw_uid;
2064 /* If security calls are not supported (presumably because we
2065 are running under Windows 9X), fallback to this: */
2066 else if (GetUserName (uname, &ulength))
2068 strcpy (dflt_passwd.pw_name, uname);
2069 if (xstrcasecmp ("administrator", uname) == 0)
2070 dflt_passwd.pw_uid = 0;
2071 else
2072 dflt_passwd.pw_uid = 123;
2073 dflt_passwd.pw_gid = dflt_passwd.pw_uid;
2075 else
2077 strcpy (dflt_passwd.pw_name, "unknown");
2078 dflt_passwd.pw_uid = 123;
2079 dflt_passwd.pw_gid = 123;
2081 dflt_group.gr_gid = dflt_passwd.pw_gid;
2083 /* Set dir and shell from environment variables. */
2084 if (w32_unicode_filenames)
2086 wchar_t *home = _wgetenv (L"HOME");
2087 wchar_t *shell = _wgetenv (L"SHELL");
2089 /* Ensure HOME and SHELL are defined. */
2090 if (home == NULL)
2091 emacs_abort ();
2092 if (shell == NULL)
2093 emacs_abort ();
2094 filename_from_utf16 (home, dflt_passwd.pw_dir);
2095 filename_from_utf16 (shell, dflt_passwd.pw_shell);
2097 else
2099 char *home = getenv ("HOME");
2100 char *shell = getenv ("SHELL");
2102 if (home == NULL)
2103 emacs_abort ();
2104 if (shell == NULL)
2105 emacs_abort ();
2106 filename_from_ansi (home, dflt_passwd.pw_dir);
2107 filename_from_ansi (shell, dflt_passwd.pw_shell);
2110 xfree (buf);
2111 if (token)
2112 CloseHandle (token);
2115 static HCRYPTPROV w32_crypto_hprov;
2116 static int
2117 w32_init_crypt_random (void)
2119 if (!CryptAcquireContext (&w32_crypto_hprov, NULL, NULL, PROV_RSA_FULL,
2120 CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
2122 DebPrint (("CryptAcquireContext failed with error %x\n",
2123 GetLastError ()));
2124 w32_crypto_hprov = 0;
2125 return -1;
2127 return 0;
2131 w32_init_random (void *buf, ptrdiff_t buflen)
2133 if (!w32_crypto_hprov)
2134 w32_init_crypt_random ();
2135 if (w32_crypto_hprov)
2137 if (CryptGenRandom (w32_crypto_hprov, buflen, (BYTE *)buf))
2138 return 0;
2140 return -1;
2144 random (void)
2146 /* rand () on NT gives us 15 random bits...hack together 30 bits. */
2147 return ((rand () << 15) | rand ());
2150 void
2151 srandom (int seed)
2153 srand (seed);
2156 /* Return the maximum length in bytes of a multibyte character
2157 sequence encoded in the current ANSI codepage. This is required to
2158 correctly walk the encoded file names one character at a time. */
2159 static int
2160 max_filename_mbslen (void)
2162 CPINFO cp_info;
2164 codepage_for_filenames (&cp_info);
2165 return cp_info.MaxCharSize;
2168 /* Normalize filename by converting in-place all of its path
2169 separators to the separator specified by PATH_SEP. */
2171 static void
2172 normalize_filename (register char *fp, char path_sep)
2174 char *p2;
2176 /* Always lower-case drive letters a-z, even if the filesystem
2177 preserves case in filenames.
2178 This is so filenames can be compared by string comparison
2179 functions that are case-sensitive. Even case-preserving filesystems
2180 do not distinguish case in drive letters. */
2181 p2 = fp + 1;
2183 if (*p2 == ':' && *fp >= 'A' && *fp <= 'Z')
2185 *fp += 'a' - 'A';
2186 fp += 2;
2189 while (*fp)
2191 if ((*fp == '/' || *fp == '\\') && *fp != path_sep)
2192 *fp = path_sep;
2193 fp++;
2197 /* Destructively turn backslashes into slashes. */
2198 void
2199 dostounix_filename (register char *p)
2201 normalize_filename (p, '/');
2204 /* Destructively turn slashes into backslashes. */
2205 void
2206 unixtodos_filename (register char *p)
2208 normalize_filename (p, '\\');
2211 /* Remove all CR's that are followed by a LF.
2212 (From msdos.c...probably should figure out a way to share it,
2213 although this code isn't going to ever change.) */
2214 static int
2215 crlf_to_lf (register int n, register char *buf)
2217 unsigned char *np = (unsigned char *)buf;
2218 unsigned char *startp = np;
2219 char *endp = buf + n;
2221 if (n == 0)
2222 return n;
2223 while (buf < endp - 1)
2225 if (*buf == 0x0d)
2227 if (*(++buf) != 0x0a)
2228 *np++ = 0x0d;
2230 else
2231 *np++ = *buf++;
2233 if (buf < endp)
2234 *np++ = *buf++;
2235 return np - startp;
2238 /* Parse the root part of file name, if present. Return length and
2239 optionally store pointer to char after root. */
2240 static int
2241 parse_root (const char * name, const char ** pPath)
2243 const char * start = name;
2245 if (name == NULL)
2246 return 0;
2248 /* find the root name of the volume if given */
2249 if (isalpha (name[0]) && name[1] == ':')
2251 /* skip past drive specifier */
2252 name += 2;
2253 if (IS_DIRECTORY_SEP (name[0]))
2254 name++;
2256 else if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1]))
2258 int slashes = 2;
2260 name += 2;
2263 if (IS_DIRECTORY_SEP (*name) && --slashes == 0)
2264 break;
2265 name++;
2267 while ( *name );
2268 if (IS_DIRECTORY_SEP (name[0]))
2269 name++;
2272 if (pPath)
2273 *pPath = name;
2275 return name - start;
2278 /* Get long base name for name; name is assumed to be absolute. */
2279 static int
2280 get_long_basename (char * name, char * buf, int size)
2282 HANDLE dir_handle = INVALID_HANDLE_VALUE;
2283 char fname_utf8[MAX_UTF8_PATH];
2284 int len = 0;
2285 int cstatus = -1;
2287 /* Must be valid filename, no wild cards or other invalid characters. */
2288 if (strpbrk (name, "*?|<>\""))
2289 return 0;
2291 if (w32_unicode_filenames)
2293 wchar_t fname_utf16[MAX_PATH];
2294 WIN32_FIND_DATAW find_data_wide;
2296 filename_to_utf16 (name, fname_utf16);
2297 dir_handle = FindFirstFileW (fname_utf16, &find_data_wide);
2298 if (dir_handle != INVALID_HANDLE_VALUE)
2299 cstatus = filename_from_utf16 (find_data_wide.cFileName, fname_utf8);
2301 else
2303 char fname_ansi[MAX_PATH];
2304 WIN32_FIND_DATAA find_data_ansi;
2306 filename_to_ansi (name, fname_ansi);
2307 /* If the ANSI name includes ? characters, it is not encodable
2308 in the ANSI codepage. In that case, we deliver the question
2309 marks to the caller; calling FindFirstFileA in this case
2310 could return some unrelated file name in the same
2311 directory. */
2312 if (_mbspbrk (fname_ansi, "?"))
2314 /* Find the basename of fname_ansi. */
2315 char *p = strrchr (fname_ansi, '\\');
2317 if (!p)
2318 p = fname_ansi;
2319 else
2320 p++;
2321 cstatus = filename_from_ansi (p, fname_utf8);
2323 else
2325 dir_handle = FindFirstFileA (fname_ansi, &find_data_ansi);
2326 if (dir_handle != INVALID_HANDLE_VALUE)
2327 cstatus = filename_from_ansi (find_data_ansi.cFileName, fname_utf8);
2331 if (cstatus == 0 && (len = strlen (fname_utf8)) < size)
2332 memcpy (buf, fname_utf8, len + 1);
2333 else
2334 len = 0;
2336 if (dir_handle != INVALID_HANDLE_VALUE)
2337 FindClose (dir_handle);
2339 return len;
2342 /* Get long name for file, if possible (assumed to be absolute). */
2343 BOOL
2344 w32_get_long_filename (const char * name, char * buf, int size)
2346 char * o = buf;
2347 char * p;
2348 const char * q;
2349 char full[ MAX_UTF8_PATH ];
2350 int len;
2352 len = strlen (name);
2353 if (len >= MAX_UTF8_PATH)
2354 return FALSE;
2356 /* Use local copy for destructive modification. */
2357 memcpy (full, name, len+1);
2358 unixtodos_filename (full);
2360 /* Copy root part verbatim. */
2361 len = parse_root (full, (const char **)&p);
2362 memcpy (o, full, len);
2363 o += len;
2364 *o = '\0';
2365 size -= len;
2367 while (p != NULL && *p)
2369 q = p;
2370 p = strchr (q, '\\');
2371 if (p) *p = '\0';
2372 len = get_long_basename (full, o, size);
2373 if (len > 0)
2375 o += len;
2376 size -= len;
2377 if (p != NULL)
2379 *p++ = '\\';
2380 if (size < 2)
2381 return FALSE;
2382 *o++ = '\\';
2383 size--;
2384 *o = '\0';
2387 else
2388 return FALSE;
2391 return TRUE;
2394 unsigned int
2395 w32_get_short_filename (const char * name, char * buf, int size)
2397 if (w32_unicode_filenames)
2399 wchar_t name_utf16[MAX_PATH], short_name[MAX_PATH];
2400 unsigned int retval;
2402 filename_to_utf16 (name, name_utf16);
2403 retval = GetShortPathNameW (name_utf16, short_name, size);
2404 if (retval && retval < size)
2405 filename_from_utf16 (short_name, buf);
2406 return retval;
2408 else
2410 char name_ansi[MAX_PATH];
2412 filename_to_ansi (name, name_ansi);
2413 return GetShortPathNameA (name_ansi, buf, size);
2417 /* Re-encode FILENAME, a UTF-8 encoded unibyte string, using the
2418 MS-Windows ANSI codepage. If FILENAME includes characters not
2419 supported by the ANSI codepage, return the 8+3 alias of FILENAME,
2420 if it exists. This is needed because the w32 build wants to
2421 support file names outside of the system locale, but image
2422 libraries typically don't support wide (a.k.a. "Unicode") APIs
2423 required for that. */
2425 Lisp_Object
2426 ansi_encode_filename (Lisp_Object filename)
2428 Lisp_Object encoded_filename;
2429 char fname[MAX_PATH];
2431 filename_to_ansi (SSDATA (filename), fname);
2432 if (_mbspbrk (fname, "?"))
2434 char shortname[MAX_PATH];
2436 if (w32_get_short_filename (SSDATA (filename), shortname, MAX_PATH))
2438 dostounix_filename (shortname);
2439 encoded_filename = build_string (shortname);
2441 else
2442 encoded_filename = build_unibyte_string (fname);
2444 else
2445 encoded_filename = build_unibyte_string (fname);
2446 return encoded_filename;
2449 static int
2450 is_unc_volume (const char *filename)
2452 const char *ptr = filename;
2454 if (!IS_DIRECTORY_SEP (ptr[0]) || !IS_DIRECTORY_SEP (ptr[1]) || !ptr[2])
2455 return 0;
2457 if (strpbrk (ptr + 2, "*?|<>\"\\/"))
2458 return 0;
2460 return 1;
2463 /* Emulate the Posix unsetenv. */
2465 unsetenv (const char *name)
2467 char *var;
2468 size_t name_len;
2470 if (name == NULL || *name == '\0' || strchr (name, '=') != NULL)
2472 errno = EINVAL;
2473 return -1;
2475 name_len = strlen (name);
2476 /* MS docs says an environment variable cannot be longer than 32K. */
2477 if (name_len > 32767)
2479 errno = ENOMEM;
2480 return 0;
2482 /* It is safe to use 'alloca' with 32K size, since the stack is at
2483 least 2MB, and we set it to 8MB in the link command line. */
2484 var = alloca (name_len + 2);
2485 strncpy (var, name, name_len);
2486 var[name_len++] = '=';
2487 var[name_len] = '\0';
2488 return _putenv (var);
2491 /* MS _putenv doesn't support removing a variable when the argument
2492 does not include the '=' character, so we fix that here. */
2494 sys_putenv (char *str)
2496 const char *const name_end = strchr (str, '=');
2498 if (name_end == NULL)
2500 /* Remove the variable from the environment. */
2501 return unsetenv (str);
2504 if (strncmp (str, "TZ=<", 4) == 0)
2506 /* MS-Windows does not support POSIX.1-2001 angle-bracket TZ
2507 abbreviation syntax. Convert to POSIX.1-1988 syntax if possible,
2508 and to the undocumented placeholder "ZZZ" otherwise. */
2509 bool supported_abbr = true;
2510 for (char *p = str + 4; *p; p++)
2512 if (('0' <= *p && *p <= '9') || *p == '-' || *p == '+')
2513 supported_abbr = false;
2514 else if (*p == '>')
2516 ptrdiff_t abbrlen;
2517 if (supported_abbr)
2519 abbrlen = p - (str + 4);
2520 memmove (str + 3, str + 4, abbrlen);
2522 else
2524 abbrlen = 3;
2525 memset (str + 3, 'Z', abbrlen);
2527 memmove (str + 3 + abbrlen, p + 1, strlen (p));
2528 break;
2533 return _putenv (str);
2536 #define REG_ROOT "SOFTWARE\\GNU\\Emacs"
2538 LPBYTE
2539 w32_get_resource (const char *key, LPDWORD lpdwtype)
2541 LPBYTE lpvalue;
2542 HKEY hrootkey = NULL;
2543 DWORD cbData;
2545 /* Check both the current user and the local machine to see if
2546 we have any resources. */
2548 if (RegOpenKeyEx (HKEY_CURRENT_USER, REG_ROOT, 0, KEY_READ, &hrootkey) == ERROR_SUCCESS)
2550 lpvalue = NULL;
2552 if (RegQueryValueEx (hrootkey, key, NULL, NULL, NULL, &cbData) == ERROR_SUCCESS
2553 && (lpvalue = xmalloc (cbData)) != NULL
2554 && RegQueryValueEx (hrootkey, key, NULL, lpdwtype, lpvalue, &cbData) == ERROR_SUCCESS)
2556 RegCloseKey (hrootkey);
2557 return (lpvalue);
2560 xfree (lpvalue);
2562 RegCloseKey (hrootkey);
2565 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, REG_ROOT, 0, KEY_READ, &hrootkey) == ERROR_SUCCESS)
2567 lpvalue = NULL;
2569 if (RegQueryValueEx (hrootkey, key, NULL, NULL, NULL, &cbData) == ERROR_SUCCESS
2570 && (lpvalue = xmalloc (cbData)) != NULL
2571 && RegQueryValueEx (hrootkey, key, NULL, lpdwtype, lpvalue, &cbData) == ERROR_SUCCESS)
2573 RegCloseKey (hrootkey);
2574 return (lpvalue);
2577 xfree (lpvalue);
2579 RegCloseKey (hrootkey);
2582 return (NULL);
2585 /* The argv[] array holds ANSI-encoded strings, and so this function
2586 works with ANS_encoded strings. */
2587 void
2588 init_environment (char ** argv)
2590 static const char * const tempdirs[] = {
2591 "$TMPDIR", "$TEMP", "$TMP", "c:/"
2594 int i;
2596 const int imax = ARRAYELTS (tempdirs);
2598 /* Implementation note: This function explicitly works with ANSI
2599 file names, not with UTF-8 encoded file names. This is because
2600 this function pushes variables into the Emacs's environment, and
2601 the environment variables are always assumed to be in the
2602 locale-specific encoding. Do NOT call any functions that accept
2603 UTF-8 file names from this function! */
2605 /* Make sure they have a usable $TMPDIR. Many Emacs functions use
2606 temporary files and assume "/tmp" if $TMPDIR is unset, which
2607 will break on DOS/Windows. Refuse to work if we cannot find
2608 a directory, not even "c:/", usable for that purpose. */
2609 for (i = 0; i < imax ; i++)
2611 const char *tmp = tempdirs[i];
2613 if (*tmp == '$')
2614 tmp = getenv (tmp + 1);
2615 /* Note that `access' can lie to us if the directory resides on a
2616 read-only filesystem, like CD-ROM or a write-protected floppy.
2617 The only way to be really sure is to actually create a file and
2618 see if it succeeds. But I think that's too much to ask. */
2620 /* MSVCRT's _access crashes with D_OK, so we use our replacement. */
2621 if (tmp && sys_access (tmp, D_OK) == 0)
2623 char * var = alloca (strlen (tmp) + 8);
2624 sprintf (var, "TMPDIR=%s", tmp);
2625 _putenv (strdup (var));
2626 break;
2629 if (i >= imax)
2630 cmd_error_internal
2631 (Fcons (Qerror,
2632 Fcons (build_string ("no usable temporary directories found!!"),
2633 Qnil)),
2634 "While setting TMPDIR: ");
2636 /* Check for environment variables and use registry settings if they
2637 don't exist. Fallback on default values where applicable. */
2639 int i;
2640 LPBYTE lpval;
2641 DWORD dwType;
2642 char locale_name[32];
2643 char default_home[MAX_PATH];
2644 int appdata = 0;
2646 static const struct env_entry
2648 const char * name;
2649 const char * def_value;
2650 } dflt_envvars[] =
2652 /* If the default value is NULL, we will use the value from the
2653 outside environment or the Registry, but will not push the
2654 variable into the Emacs environment if it is defined neither
2655 in the Registry nor in the outside environment. */
2656 {"HOME", "C:/"},
2657 {"PRELOAD_WINSOCK", NULL},
2658 {"emacs_dir", "C:/emacs"},
2659 {"EMACSLOADPATH", NULL},
2660 {"SHELL", "cmdproxy.exe"}, /* perhaps it is somewhere on PATH */
2661 {"EMACSDATA", NULL},
2662 {"EMACSPATH", NULL},
2663 {"INFOPATH", NULL},
2664 {"EMACSDOC", NULL},
2665 {"TERM", "cmd"},
2666 {"LANG", NULL},
2669 #define N_ENV_VARS ARRAYELTS (dflt_envvars)
2671 /* We need to copy dflt_envvars[] and work on the copy because we
2672 don't want the dumped Emacs to inherit the values of
2673 environment variables we saw during dumping (which could be on
2674 a different system). The defaults above must be left intact. */
2675 struct env_entry env_vars[N_ENV_VARS];
2677 for (i = 0; i < N_ENV_VARS; i++)
2678 env_vars[i] = dflt_envvars[i];
2680 /* For backwards compatibility, check if a .emacs file exists in C:/
2681 If not, then we can try to default to the appdata directory under the
2682 user's profile, which is more likely to be writable. */
2683 if (sys_access ("C:/.emacs", F_OK) != 0)
2685 HRESULT profile_result;
2686 /* Dynamically load ShGetFolderPath, as it won't exist on versions
2687 of Windows 95 and NT4 that have not been updated to include
2688 MSIE 5. */
2689 ShGetFolderPath_fn get_folder_path;
2690 get_folder_path = (ShGetFolderPath_fn)
2691 GetProcAddress (GetModuleHandle ("shell32.dll"), "SHGetFolderPathA");
2693 if (get_folder_path != NULL)
2695 profile_result = get_folder_path (NULL, CSIDL_APPDATA, NULL,
2696 0, default_home);
2698 /* If we can't get the appdata dir, revert to old behavior. */
2699 if (profile_result == S_OK)
2701 env_vars[0].def_value = default_home;
2702 appdata = 1;
2707 /* Get default locale info and use it for LANG. */
2708 if (GetLocaleInfo (LOCALE_USER_DEFAULT,
2709 LOCALE_SABBREVLANGNAME | LOCALE_USE_CP_ACP,
2710 locale_name, sizeof (locale_name)))
2712 for (i = 0; i < N_ENV_VARS; i++)
2714 if (strcmp (env_vars[i].name, "LANG") == 0)
2716 env_vars[i].def_value = locale_name;
2717 break;
2722 #define SET_ENV_BUF_SIZE (4 * MAX_PATH) /* to cover EMACSLOADPATH */
2724 /* Treat emacs_dir specially: set it unconditionally based on our
2725 location. */
2727 char *p;
2728 char modname[MAX_PATH];
2730 if (!GetModuleFileNameA (NULL, modname, MAX_PATH))
2731 emacs_abort ();
2732 if ((p = _mbsrchr (modname, '\\')) == NULL)
2733 emacs_abort ();
2734 *p = 0;
2736 if ((p = _mbsrchr (modname, '\\'))
2737 /* From bin means installed Emacs, from src means uninstalled. */
2738 && (xstrcasecmp (p, "\\bin") == 0 || xstrcasecmp (p, "\\src") == 0))
2740 char buf[SET_ENV_BUF_SIZE];
2741 int within_build_tree = xstrcasecmp (p, "\\src") == 0;
2743 *p = 0;
2744 for (p = modname; *p; p = CharNext (p))
2745 if (*p == '\\') *p = '/';
2747 _snprintf (buf, sizeof (buf)-1, "emacs_dir=%s", modname);
2748 _putenv (strdup (buf));
2749 /* If we are running from the Posix-like build tree, define
2750 SHELL to point to our own cmdproxy. The loop below will
2751 then disregard PATH_EXEC and the default value. */
2752 if (within_build_tree)
2754 _snprintf (buf, sizeof (buf) - 1,
2755 "SHELL=%s/nt/cmdproxy.exe", modname);
2756 _putenv (strdup (buf));
2761 for (i = 0; i < N_ENV_VARS; i++)
2763 if (!getenv (env_vars[i].name))
2765 int dont_free = 0;
2766 char bufc[SET_ENV_BUF_SIZE];
2768 if ((lpval = w32_get_resource (env_vars[i].name, &dwType)) == NULL
2769 /* Also ignore empty environment variables. */
2770 || *lpval == 0)
2772 xfree (lpval);
2773 dont_free = 1;
2774 if (strcmp (env_vars[i].name, "SHELL") == 0)
2776 /* Look for cmdproxy.exe in every directory in
2777 PATH_EXEC. FIXME: This does not find cmdproxy
2778 in nt/ when we run uninstalled. */
2779 char fname[MAX_PATH];
2780 const char *pstart = PATH_EXEC, *pend;
2782 do {
2783 pend = _mbschr (pstart, ';');
2784 if (!pend)
2785 pend = pstart + strlen (pstart);
2786 /* Be defensive against series of ;;; characters. */
2787 if (pend > pstart)
2789 strncpy (fname, pstart, pend - pstart);
2790 fname[pend - pstart] = '/';
2791 strcpy (&fname[pend - pstart + 1], "cmdproxy.exe");
2792 ExpandEnvironmentStrings ((LPSTR) fname, bufc,
2793 sizeof (bufc));
2794 if (sys_access (bufc, F_OK) == 0)
2796 lpval = bufc;
2797 dwType = REG_SZ;
2798 break;
2801 if (*pend)
2802 pstart = pend + 1;
2803 else
2804 pstart = pend;
2805 if (!*pstart)
2807 /* If not found in any directory, use the
2808 default as the last resort. */
2809 lpval = (char *)env_vars[i].def_value;
2810 dwType = REG_EXPAND_SZ;
2812 } while (*pstart);
2814 else
2816 lpval = (char *)env_vars[i].def_value;
2817 dwType = REG_EXPAND_SZ;
2819 if (strcmp (env_vars[i].name, "HOME") == 0 && !appdata)
2820 Vdelayed_warnings_list
2821 = Fcons
2822 (listn (CONSTYPE_HEAP, 2,
2823 intern ("initialization"), build_string
2824 ("Use of `C:\\.emacs' without defining `HOME'\n"
2825 "in the environment is deprecated, "
2826 "see `Windows HOME' in the Emacs manual.")),
2827 Vdelayed_warnings_list);
2830 if (lpval)
2832 char buf1[SET_ENV_BUF_SIZE], buf2[SET_ENV_BUF_SIZE];
2834 if (dwType == REG_EXPAND_SZ)
2835 ExpandEnvironmentStrings ((LPSTR) lpval, buf1, sizeof (buf1));
2836 else if (dwType == REG_SZ)
2837 strcpy (buf1, (char *)lpval);
2838 if (dwType == REG_EXPAND_SZ || dwType == REG_SZ)
2840 _snprintf (buf2, sizeof (buf2)-1, "%s=%s", env_vars[i].name,
2841 buf1);
2842 _putenv (strdup (buf2));
2845 if (!dont_free)
2846 xfree (lpval);
2852 /* Rebuild system configuration to reflect invoking system. */
2853 Vsystem_configuration = build_string (EMACS_CONFIGURATION);
2855 /* Another special case: on NT, the PATH variable is actually named
2856 "Path" although cmd.exe (perhaps NT itself) arranges for
2857 environment variable lookup and setting to be case insensitive.
2858 However, Emacs assumes a fully case sensitive environment, so we
2859 need to change "Path" to "PATH" to match the expectations of
2860 various elisp packages. We do this by the sneaky method of
2861 modifying the string in the C runtime environ entry.
2863 The same applies to COMSPEC. */
2865 char ** envp;
2866 const char *path = "PATH=";
2867 int path_len = strlen (path);
2868 const char *comspec = "COMSPEC=";
2869 int comspec_len = strlen (comspec);
2871 for (envp = environ; *envp; envp++)
2872 if (_strnicmp (*envp, path, path_len) == 0)
2873 memcpy (*envp, path, path_len);
2874 else if (_strnicmp (*envp, comspec, comspec_len) == 0)
2875 memcpy (*envp, comspec, comspec_len);
2877 /* Make the same modification to `process-environment' which has
2878 already been initialized in set_initial_environment. */
2879 for (Lisp_Object env = Vprocess_environment; CONSP (env); env = XCDR (env))
2881 Lisp_Object entry = XCAR (env);
2882 if (_strnicmp (SDATA (entry), path, path_len) == 0)
2883 for (int i = 0; i < path_len; i++)
2884 SSET (entry, i, path[i]);
2885 else if (_strnicmp (SDATA (entry), comspec, comspec_len) == 0)
2886 for (int i = 0; i < comspec_len; i++)
2887 SSET (entry, i, comspec[i]);
2891 /* Remember the initial working directory for getcwd. */
2892 /* FIXME: Do we need to resolve possible symlinks in startup_dir?
2893 Does it matter anywhere in Emacs? */
2894 if (w32_unicode_filenames)
2896 wchar_t wstartup_dir[MAX_PATH];
2898 if (!GetCurrentDirectoryW (MAX_PATH, wstartup_dir))
2899 emacs_abort ();
2900 filename_from_utf16 (wstartup_dir, startup_dir);
2902 else
2904 char astartup_dir[MAX_PATH];
2906 if (!GetCurrentDirectoryA (MAX_PATH, astartup_dir))
2907 emacs_abort ();
2908 filename_from_ansi (astartup_dir, startup_dir);
2912 static char modname[MAX_PATH];
2914 if (!GetModuleFileNameA (NULL, modname, MAX_PATH))
2915 emacs_abort ();
2916 argv[0] = modname;
2919 /* Determine if there is a middle mouse button, to allow parse_button
2920 to decide whether right mouse events should be mouse-2 or
2921 mouse-3. */
2922 w32_num_mouse_buttons = GetSystemMetrics (SM_CMOUSEBUTTONS);
2924 init_user_info ();
2927 /* Called from expand-file-name when default-directory is not a string. */
2929 char *
2930 emacs_root_dir (void)
2932 static char root_dir[MAX_UTF8_PATH];
2933 const char *p;
2935 p = getenv ("emacs_dir");
2936 if (p == NULL)
2937 emacs_abort ();
2938 filename_from_ansi (p, root_dir);
2939 root_dir[parse_root (root_dir, NULL)] = '\0';
2940 dostounix_filename (root_dir);
2941 return root_dir;
2944 #include <sys/timeb.h>
2946 /* Emulate gettimeofday (Ulrich Leodolter, 1/11/95). */
2948 gettimeofday (struct timeval *__restrict tv, struct timezone *__restrict tz)
2950 struct _timeb tb;
2951 _ftime (&tb);
2953 tv->tv_sec = tb.time;
2954 tv->tv_usec = tb.millitm * 1000L;
2955 /* Implementation note: _ftime sometimes doesn't update the dstflag
2956 according to the new timezone when the system timezone is
2957 changed. We could fix that by using GetSystemTime and
2958 GetTimeZoneInformation, but that doesn't seem necessary, since
2959 Emacs always calls gettimeofday with the 2nd argument NULL (see
2960 current_emacs_time). */
2961 if (tz)
2963 tz->tz_minuteswest = tb.timezone; /* minutes west of Greenwich */
2964 tz->tz_dsttime = tb.dstflag; /* type of dst correction */
2966 return 0;
2969 /* Emulate fdutimens. */
2971 /* Set the access and modification time stamps of FD (a.k.a. FILE) to be
2972 TIMESPEC[0] and TIMESPEC[1], respectively.
2973 FD must be either negative -- in which case it is ignored --
2974 or a file descriptor that is open on FILE.
2975 If FD is nonnegative, then FILE can be NULL, which means
2976 use just futimes instead of utimes.
2977 If TIMESPEC is null, FAIL.
2978 Return 0 on success, -1 (setting errno) on failure. */
2981 fdutimens (int fd, char const *file, struct timespec const timespec[2])
2983 if (!timespec)
2985 errno = ENOSYS;
2986 return -1;
2988 if (fd < 0 && !file)
2990 errno = EBADF;
2991 return -1;
2993 /* _futime's prototype defines 2nd arg as having the type 'struct
2994 _utimbuf', while utime needs to accept 'struct utimbuf' for
2995 compatibility with Posix. So we need to use 2 different (but
2996 equivalent) types to avoid compiler warnings, sigh. */
2997 if (fd >= 0)
2999 struct _utimbuf _ut;
3001 _ut.actime = timespec[0].tv_sec;
3002 _ut.modtime = timespec[1].tv_sec;
3003 return _futime (fd, &_ut);
3005 else
3007 struct utimbuf ut;
3009 ut.actime = timespec[0].tv_sec;
3010 ut.modtime = timespec[1].tv_sec;
3011 /* Call 'utime', which is implemented below, not the MS library
3012 function, which fails on directories. */
3013 return utime (file, &ut);
3018 /* ------------------------------------------------------------------------- */
3019 /* IO support and wrapper functions for the Windows API. */
3020 /* ------------------------------------------------------------------------- */
3022 /* Place a wrapper around the MSVC version of ctime. It returns NULL
3023 on network directories, so we handle that case here.
3024 (Ulrich Leodolter, 1/11/95). */
3025 char *
3026 sys_ctime (const time_t *t)
3028 char *str = (char *) ctime (t);
3029 return (str ? str : (char *)"Sun Jan 01 00:00:00 1970");
3032 /* Emulate sleep...we could have done this with a define, but that
3033 would necessitate including windows.h in the files that used it.
3034 This is much easier. */
3035 void
3036 sys_sleep (int seconds)
3038 Sleep (seconds * 1000);
3041 /* Internal MSVC functions for low-level descriptor munging */
3042 extern int __cdecl _set_osfhnd (int fd, long h);
3043 extern int __cdecl _free_osfhnd (int fd);
3045 /* parallel array of private info on file handles */
3046 filedesc fd_info [ MAXDESC ];
3048 typedef struct volume_info_data {
3049 struct volume_info_data * next;
3051 /* time when info was obtained */
3052 DWORD timestamp;
3054 /* actual volume info */
3055 char * root_dir;
3056 DWORD serialnum;
3057 DWORD maxcomp;
3058 DWORD flags;
3059 char * name;
3060 char * type;
3061 } volume_info_data;
3063 /* Global referenced by various functions. */
3064 static volume_info_data volume_info;
3066 /* Vector to indicate which drives are local and fixed (for which cached
3067 data never expires). */
3068 static BOOL fixed_drives[26];
3070 /* Consider cached volume information to be stale if older than 10s,
3071 at least for non-local drives. Info for fixed drives is never stale. */
3072 #define DRIVE_INDEX( c ) ( (c) <= 'Z' ? (c) - 'A' : (c) - 'a' )
3073 #define VOLINFO_STILL_VALID( root_dir, info ) \
3074 ( ( isalpha (root_dir[0]) && \
3075 fixed_drives[ DRIVE_INDEX (root_dir[0]) ] ) \
3076 || GetTickCount () - info->timestamp < 10000 )
3078 /* Cache support functions. */
3080 /* Simple linked list with linear search is sufficient. */
3081 static volume_info_data *volume_cache = NULL;
3083 static volume_info_data *
3084 lookup_volume_info (char * root_dir)
3086 volume_info_data * info;
3088 for (info = volume_cache; info; info = info->next)
3089 if (xstrcasecmp (info->root_dir, root_dir) == 0)
3090 break;
3091 return info;
3094 static void
3095 add_volume_info (char * root_dir, volume_info_data * info)
3097 info->root_dir = xstrdup (root_dir);
3098 unixtodos_filename (info->root_dir);
3099 info->next = volume_cache;
3100 volume_cache = info;
3104 /* Wrapper for GetVolumeInformation, which uses caching to avoid
3105 performance penalty (~2ms on 486 for local drives, 7.5ms for local
3106 cdrom drive, ~5-10ms or more for remote drives on LAN). */
3107 static volume_info_data *
3108 GetCachedVolumeInformation (char * root_dir)
3110 volume_info_data * info;
3111 char default_root[ MAX_UTF8_PATH ];
3112 char name[MAX_PATH+1];
3113 char type[MAX_PATH+1];
3115 /* NULL for root_dir means use root from current directory. */
3116 if (root_dir == NULL)
3118 if (w32_unicode_filenames)
3120 wchar_t curdirw[MAX_PATH];
3122 if (GetCurrentDirectoryW (MAX_PATH, curdirw) == 0)
3123 return NULL;
3124 filename_from_utf16 (curdirw, default_root);
3126 else
3128 char curdira[MAX_PATH];
3130 if (GetCurrentDirectoryA (MAX_PATH, curdira) == 0)
3131 return NULL;
3132 filename_from_ansi (curdira, default_root);
3134 parse_root (default_root, (const char **)&root_dir);
3135 *root_dir = 0;
3136 root_dir = default_root;
3139 /* Local fixed drives can be cached permanently. Removable drives
3140 cannot be cached permanently, since the volume name and serial
3141 number (if nothing else) can change. Remote drives should be
3142 treated as if they are removable, since there is no sure way to
3143 tell whether they are or not. Also, the UNC association of drive
3144 letters mapped to remote volumes can be changed at any time (even
3145 by other processes) without notice.
3147 As a compromise, so we can benefit from caching info for remote
3148 volumes, we use a simple expiry mechanism to invalidate cache
3149 entries that are more than ten seconds old. */
3151 #if 0
3152 /* No point doing this, because WNetGetConnection is even slower than
3153 GetVolumeInformation, consistently taking ~50ms on a 486 (FWIW,
3154 GetDriveType is about the only call of this type which does not
3155 involve network access, and so is extremely quick). */
3157 /* Map drive letter to UNC if remote. */
3158 if (isalpha (root_dir[0]) && !fixed[DRIVE_INDEX (root_dir[0])])
3160 char remote_name[ 256 ];
3161 char drive[3] = { root_dir[0], ':' };
3163 if (WNetGetConnection (drive, remote_name, sizeof (remote_name))
3164 == NO_ERROR)
3165 /* do something */ ;
3167 #endif
3169 info = lookup_volume_info (root_dir);
3171 if (info == NULL || ! VOLINFO_STILL_VALID (root_dir, info))
3173 DWORD serialnum;
3174 DWORD maxcomp;
3175 DWORD flags;
3177 /* Info is not cached, or is stale. */
3178 if (w32_unicode_filenames)
3180 wchar_t root_w[MAX_PATH];
3181 wchar_t name_w[MAX_PATH+1];
3182 wchar_t type_w[MAX_PATH+1];
3184 filename_to_utf16 (root_dir, root_w);
3185 if (!GetVolumeInformationW (root_w,
3186 name_w, sizeof (name_w),
3187 &serialnum,
3188 &maxcomp,
3189 &flags,
3190 type_w, sizeof (type_w)))
3191 return NULL;
3192 /* Hmm... not really 100% correct, as these 2 are not file
3193 names... */
3194 filename_from_utf16 (name_w, name);
3195 filename_from_utf16 (type_w, type);
3197 else
3199 char root_a[MAX_PATH];
3200 char name_a[MAX_PATH+1];
3201 char type_a[MAX_PATH+1];
3203 filename_to_ansi (root_dir, root_a);
3204 if (!GetVolumeInformationA (root_a,
3205 name_a, sizeof (name_a),
3206 &serialnum,
3207 &maxcomp,
3208 &flags,
3209 type_a, sizeof (type_a)))
3210 return NULL;
3211 filename_from_ansi (name_a, name);
3212 filename_from_ansi (type_a, type);
3215 /* Cache the volume information for future use, overwriting existing
3216 entry if present. */
3217 if (info == NULL)
3219 info = xmalloc (sizeof (volume_info_data));
3220 add_volume_info (root_dir, info);
3222 else
3224 xfree (info->name);
3225 xfree (info->type);
3228 info->name = xstrdup (name);
3229 unixtodos_filename (info->name);
3230 info->serialnum = serialnum;
3231 info->maxcomp = maxcomp;
3232 info->flags = flags;
3233 info->type = xstrdup (type);
3234 info->timestamp = GetTickCount ();
3237 return info;
3240 /* Get information on the volume where NAME is held; set path pointer to
3241 start of pathname in NAME (past UNC header\volume header if present),
3242 if pPath is non-NULL.
3244 Note: if NAME includes symlinks, the information is for the volume
3245 of the symlink, not of its target. That's because, even though
3246 GetVolumeInformation returns information about the symlink target
3247 of its argument, we only pass the root directory to
3248 GetVolumeInformation, not the full NAME. */
3249 static int
3250 get_volume_info (const char * name, const char ** pPath)
3252 char temp[MAX_UTF8_PATH];
3253 char *rootname = NULL; /* default to current volume */
3254 volume_info_data * info;
3255 int root_len = parse_root (name, pPath);
3257 if (name == NULL)
3258 return FALSE;
3260 /* Copy the root name of the volume, if given. */
3261 if (root_len)
3263 strncpy (temp, name, root_len);
3264 temp[root_len] = '\0';
3265 unixtodos_filename (temp);
3266 rootname = temp;
3269 info = GetCachedVolumeInformation (rootname);
3270 if (info != NULL)
3272 /* Set global referenced by other functions. */
3273 volume_info = *info;
3274 return TRUE;
3276 return FALSE;
3279 /* Determine if volume is FAT format (ie. only supports short 8.3
3280 names); also set path pointer to start of pathname in name, if
3281 pPath is non-NULL. */
3282 static int
3283 is_fat_volume (const char * name, const char ** pPath)
3285 if (get_volume_info (name, pPath))
3286 return (volume_info.maxcomp == 12);
3287 return FALSE;
3290 /* Convert all slashes in a filename to backslashes, and map filename
3291 to a valid 8.3 name if necessary. The result is a pointer to a
3292 static buffer, so CAVEAT EMPTOR! */
3293 const char *map_w32_filename (const char *, const char **);
3295 const char *
3296 map_w32_filename (const char * name, const char ** pPath)
3298 static char shortname[MAX_UTF8_PATH];
3299 char * str = shortname;
3300 char c;
3301 char * path;
3302 const char * save_name = name;
3304 if (strlen (name) >= sizeof (shortname))
3306 /* Return a filename which will cause callers to fail. */
3307 strcpy (shortname, "?");
3308 return shortname;
3311 if (!fatal_error_in_progress /* disable fancy processing during crash */
3312 && is_fat_volume (name, (const char **)&path)) /* truncate to 8.3 */
3314 register int left = 8; /* maximum number of chars in part */
3315 register int extn = 0; /* extension added? */
3316 register int dots = 2; /* maximum number of dots allowed */
3318 while (name < path)
3319 *str++ = *name++; /* skip past UNC header */
3321 while ((c = *name++))
3323 switch ( c )
3325 case ':':
3326 case '\\':
3327 case '/':
3328 *str++ = (c == ':' ? ':' : '\\');
3329 extn = 0; /* reset extension flags */
3330 dots = 2; /* max 2 dots */
3331 left = 8; /* max length 8 for main part */
3332 break;
3333 case '.':
3334 if ( dots )
3336 /* Convert path components of the form .xxx to _xxx,
3337 but leave . and .. as they are. This allows .emacs
3338 to be read as _emacs, for example. */
3340 if (! *name ||
3341 *name == '.' ||
3342 IS_DIRECTORY_SEP (*name))
3344 *str++ = '.';
3345 dots--;
3347 else
3349 *str++ = '_';
3350 left--;
3351 dots = 0;
3354 else if ( !extn )
3356 *str++ = '.';
3357 extn = 1; /* we've got an extension */
3358 left = 3; /* 3 chars in extension */
3360 else
3362 /* any embedded dots after the first are converted to _ */
3363 *str++ = '_';
3365 break;
3366 case '~':
3367 case '#': /* don't lose these, they're important */
3368 if ( ! left )
3369 str[-1] = c; /* replace last character of part */
3370 /* FALLTHRU */
3371 default:
3372 if ( left && 'A' <= c && c <= 'Z' )
3374 *str++ = tolower (c); /* map to lower case (looks nicer) */
3375 left--;
3376 dots = 0; /* started a path component */
3378 break;
3381 *str = '\0';
3383 else
3385 strcpy (shortname, name);
3386 unixtodos_filename (shortname);
3389 if (pPath)
3390 *pPath = shortname + (path - save_name);
3392 return shortname;
3395 static int
3396 is_exec (const char * name)
3398 char * p = strrchr (name, '.');
3399 return
3400 (p != NULL
3401 && (xstrcasecmp (p, ".exe") == 0 ||
3402 xstrcasecmp (p, ".com") == 0 ||
3403 xstrcasecmp (p, ".bat") == 0 ||
3404 xstrcasecmp (p, ".cmd") == 0));
3407 /* Emulate the Unix directory procedures opendir, closedir, and
3408 readdir. We rename them to sys_* names because some versions of
3409 MinGW startup code call opendir and readdir to glob wildcards, and
3410 the code that calls them doesn't grok UTF-8 encoded file names we
3411 produce in dirent->d_name[]. */
3413 struct dirent dir_static; /* simulated directory contents */
3414 static HANDLE dir_find_handle = INVALID_HANDLE_VALUE;
3415 static int dir_is_fat;
3416 static char dir_pathname[MAX_UTF8_PATH];
3417 static WIN32_FIND_DATAW dir_find_data_w;
3418 static WIN32_FIND_DATAA dir_find_data_a;
3419 #define DIR_FIND_DATA_W 1
3420 #define DIR_FIND_DATA_A 2
3421 static int last_dir_find_data = -1;
3423 /* Support shares on a network resource as subdirectories of a read-only
3424 root directory. */
3425 static HANDLE wnet_enum_handle = INVALID_HANDLE_VALUE;
3426 static HANDLE open_unc_volume (const char *);
3427 static void *read_unc_volume (HANDLE, wchar_t *, char *, int);
3428 static void close_unc_volume (HANDLE);
3430 DIR *
3431 sys_opendir (const char *filename)
3433 DIR *dirp;
3435 /* Opening is done by FindFirstFile. However, a read is inherent to
3436 this operation, so we defer the open until read time. */
3438 if (dir_find_handle != INVALID_HANDLE_VALUE)
3439 return NULL;
3440 if (wnet_enum_handle != INVALID_HANDLE_VALUE)
3441 return NULL;
3443 /* Note: We don't support traversal of UNC volumes via symlinks.
3444 Doing so would mean punishing 99.99% of use cases by resolving
3445 all the possible symlinks in FILENAME, recursively. */
3446 if (is_unc_volume (filename))
3448 wnet_enum_handle = open_unc_volume (filename);
3449 if (wnet_enum_handle == INVALID_HANDLE_VALUE)
3450 return NULL;
3453 if (!(dirp = (DIR *) malloc (sizeof (DIR))))
3454 return NULL;
3456 dirp->dd_fd = 0;
3457 dirp->dd_loc = 0;
3458 dirp->dd_size = 0;
3460 strncpy (dir_pathname, map_w32_filename (filename, NULL), MAX_UTF8_PATH - 1);
3461 dir_pathname[MAX_UTF8_PATH - 1] = '\0';
3462 /* Note: We don't support symlinks to file names on FAT volumes.
3463 Doing so would mean punishing 99.99% of use cases by resolving
3464 all the possible symlinks in FILENAME, recursively. */
3465 dir_is_fat = is_fat_volume (filename, NULL);
3467 return dirp;
3470 void
3471 sys_closedir (DIR *dirp)
3473 /* If we have a find-handle open, close it. */
3474 if (dir_find_handle != INVALID_HANDLE_VALUE)
3476 FindClose (dir_find_handle);
3477 dir_find_handle = INVALID_HANDLE_VALUE;
3479 else if (wnet_enum_handle != INVALID_HANDLE_VALUE)
3481 close_unc_volume (wnet_enum_handle);
3482 wnet_enum_handle = INVALID_HANDLE_VALUE;
3484 xfree ((char *) dirp);
3487 struct dirent *
3488 sys_readdir (DIR *dirp)
3490 int downcase = !NILP (Vw32_downcase_file_names);
3492 if (wnet_enum_handle != INVALID_HANDLE_VALUE)
3494 if (!read_unc_volume (wnet_enum_handle,
3495 dir_find_data_w.cFileName,
3496 dir_find_data_a.cFileName,
3497 MAX_PATH))
3498 return NULL;
3500 /* If we aren't dir_finding, do a find-first, otherwise do a find-next. */
3501 else if (dir_find_handle == INVALID_HANDLE_VALUE)
3503 char filename[MAX_UTF8_PATH];
3504 int ln;
3505 bool last_slash = true;
3507 /* Note: We don't need to worry about dir_pathname being longer
3508 than MAX_UTF8_PATH, as sys_opendir already took care of that
3509 when it called map_w32_filename: that function will put a "?"
3510 in its return value in that case, thus failing all the calls
3511 below. */
3512 strcpy (filename, dir_pathname);
3513 ln = strlen (filename);
3514 if (!IS_DIRECTORY_SEP (filename[ln - 1]))
3515 last_slash = false;
3517 /* Note: No need to resolve symlinks in FILENAME, because
3518 FindFirst opens the directory that is the target of a
3519 symlink. */
3520 if (w32_unicode_filenames)
3522 wchar_t fnw[MAX_PATH + 2];
3524 filename_to_utf16 (filename, fnw);
3525 if (!last_slash)
3526 wcscat (fnw, L"\\");
3527 wcscat (fnw, L"*");
3528 dir_find_handle = FindFirstFileW (fnw, &dir_find_data_w);
3530 else
3532 char fna[MAX_PATH + 2];
3534 filename_to_ansi (filename, fna);
3535 if (!last_slash)
3536 strcat (fna, "\\");
3537 strcat (fna, "*");
3538 /* If FILENAME is not representable by the current ANSI
3539 codepage, we don't want FindFirstFileA to interpret the
3540 '?' characters as a wildcard. */
3541 if (_mbspbrk (fna, "?"))
3542 dir_find_handle = INVALID_HANDLE_VALUE;
3543 else
3544 dir_find_handle = FindFirstFileA (fna, &dir_find_data_a);
3547 if (dir_find_handle == INVALID_HANDLE_VALUE)
3549 /* Any changes in the value of errno here should be in sync
3550 with what directory_files_internal does when it calls
3551 readdir. */
3552 switch (GetLastError ())
3554 /* Windows uses this value when FindFirstFile finds no
3555 files that match the wildcard. This is not supposed
3556 to happen, since our wildcard is "*", but just in
3557 case, if there's some weird empty directory with not
3558 even "." and ".." entries... */
3559 case ERROR_FILE_NOT_FOUND:
3560 errno = 0;
3561 /* FALLTHRU */
3562 default:
3563 break;
3564 case ERROR_ACCESS_DENIED:
3565 case ERROR_NETWORK_ACCESS_DENIED:
3566 errno = EACCES;
3567 break;
3568 case ERROR_PATH_NOT_FOUND:
3569 case ERROR_INVALID_DRIVE:
3570 case ERROR_NOT_READY:
3571 case ERROR_BAD_NETPATH:
3572 case ERROR_BAD_NET_NAME:
3573 errno = ENOENT;
3574 break;
3576 return NULL;
3579 else if (w32_unicode_filenames)
3581 if (!FindNextFileW (dir_find_handle, &dir_find_data_w))
3583 errno = 0;
3584 return NULL;
3587 else
3589 if (!FindNextFileA (dir_find_handle, &dir_find_data_a))
3591 errno = 0;
3592 return NULL;
3596 /* Emacs never uses this value, so don't bother making it match
3597 value returned by stat(). */
3598 dir_static.d_ino = 1;
3600 if (w32_unicode_filenames)
3602 if (downcase || dir_is_fat)
3604 wchar_t tem[MAX_PATH];
3606 wcscpy (tem, dir_find_data_w.cFileName);
3607 CharLowerW (tem);
3608 filename_from_utf16 (tem, dir_static.d_name);
3610 else
3611 filename_from_utf16 (dir_find_data_w.cFileName, dir_static.d_name);
3612 last_dir_find_data = DIR_FIND_DATA_W;
3614 else
3616 char tem[MAX_PATH];
3618 /* If the file name in cFileName[] includes `?' characters, it
3619 means the original file name used characters that cannot be
3620 represented by the current ANSI codepage. To avoid total
3621 lossage, retrieve the short 8+3 alias of the long file
3622 name. */
3623 if (_mbspbrk (dir_find_data_a.cFileName, "?"))
3625 strcpy (tem, dir_find_data_a.cAlternateFileName);
3626 /* 8+3 aliases are returned in all caps, which could break
3627 various alists that look at filenames' extensions. */
3628 downcase = 1;
3630 else if (downcase || dir_is_fat)
3631 strcpy (tem, dir_find_data_a.cFileName);
3632 else
3633 filename_from_ansi (dir_find_data_a.cFileName, dir_static.d_name);
3634 if (downcase || dir_is_fat)
3636 _mbslwr (tem);
3637 filename_from_ansi (tem, dir_static.d_name);
3639 last_dir_find_data = DIR_FIND_DATA_A;
3642 dir_static.d_namlen = strlen (dir_static.d_name);
3643 dir_static.d_reclen = sizeof (struct dirent) - MAX_UTF8_PATH + 3 +
3644 dir_static.d_namlen - dir_static.d_namlen % 4;
3646 return &dir_static;
3649 static HANDLE
3650 open_unc_volume (const char *path)
3652 const char *fn = map_w32_filename (path, NULL);
3653 DWORD result;
3654 HANDLE henum;
3656 if (w32_unicode_filenames)
3658 NETRESOURCEW nrw;
3659 wchar_t fnw[MAX_PATH];
3661 nrw.dwScope = RESOURCE_GLOBALNET;
3662 nrw.dwType = RESOURCETYPE_DISK;
3663 nrw.dwDisplayType = RESOURCEDISPLAYTYPE_SERVER;
3664 nrw.dwUsage = RESOURCEUSAGE_CONTAINER;
3665 nrw.lpLocalName = NULL;
3666 filename_to_utf16 (fn, fnw);
3667 nrw.lpRemoteName = fnw;
3668 nrw.lpComment = NULL;
3669 nrw.lpProvider = NULL;
3671 result = WNetOpenEnumW (RESOURCE_GLOBALNET, RESOURCETYPE_DISK,
3672 RESOURCEUSAGE_CONNECTABLE, &nrw, &henum);
3674 else
3676 NETRESOURCEA nra;
3677 char fna[MAX_PATH];
3679 nra.dwScope = RESOURCE_GLOBALNET;
3680 nra.dwType = RESOURCETYPE_DISK;
3681 nra.dwDisplayType = RESOURCEDISPLAYTYPE_SERVER;
3682 nra.dwUsage = RESOURCEUSAGE_CONTAINER;
3683 nra.lpLocalName = NULL;
3684 filename_to_ansi (fn, fna);
3685 nra.lpRemoteName = fna;
3686 nra.lpComment = NULL;
3687 nra.lpProvider = NULL;
3689 result = WNetOpenEnumA (RESOURCE_GLOBALNET, RESOURCETYPE_DISK,
3690 RESOURCEUSAGE_CONNECTABLE, &nra, &henum);
3692 if (result == NO_ERROR)
3693 return henum;
3694 else
3696 /* Make sure directory_files_internal reports a sensible error. */
3697 errno = ENOENT;
3698 return INVALID_HANDLE_VALUE;
3702 static void *
3703 read_unc_volume (HANDLE henum, wchar_t *fname_w, char *fname_a, int size)
3705 DWORD count;
3706 int result;
3707 char *buffer;
3708 DWORD bufsize = 512;
3709 void *retval;
3711 count = 1;
3712 if (w32_unicode_filenames)
3714 wchar_t *ptrw;
3716 bufsize *= 2;
3717 buffer = alloca (bufsize);
3718 result = WNetEnumResourceW (henum, &count, buffer, &bufsize);
3719 if (result != NO_ERROR)
3720 return NULL;
3721 /* WNetEnumResource returns \\resource\share...skip forward to "share". */
3722 ptrw = ((LPNETRESOURCEW) buffer)->lpRemoteName;
3723 ptrw += 2;
3724 while (*ptrw && *ptrw != L'/' && *ptrw != L'\\') ptrw++;
3725 ptrw++;
3726 wcsncpy (fname_w, ptrw, size);
3727 retval = fname_w;
3729 else
3731 int dbcs_p = max_filename_mbslen () > 1;
3732 char *ptra;
3734 buffer = alloca (bufsize);
3735 result = WNetEnumResourceA (henum, &count, buffer, &bufsize);
3736 if (result != NO_ERROR)
3737 return NULL;
3738 ptra = ((LPNETRESOURCEA) buffer)->lpRemoteName;
3739 ptra += 2;
3740 if (!dbcs_p)
3741 while (*ptra && !IS_DIRECTORY_SEP (*ptra)) ptra++;
3742 else
3744 while (*ptra && !IS_DIRECTORY_SEP (*ptra))
3745 ptra = CharNextExA (file_name_codepage, ptra, 0);
3747 ptra++;
3748 strncpy (fname_a, ptra, size);
3749 retval = fname_a;
3752 return retval;
3755 static void
3756 close_unc_volume (HANDLE henum)
3758 if (henum != INVALID_HANDLE_VALUE)
3759 WNetCloseEnum (henum);
3762 static DWORD
3763 unc_volume_file_attributes (const char *path)
3765 HANDLE henum;
3766 DWORD attrs;
3768 henum = open_unc_volume (path);
3769 if (henum == INVALID_HANDLE_VALUE)
3770 return -1;
3772 attrs = FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_DIRECTORY;
3774 close_unc_volume (henum);
3776 return attrs;
3779 /* Ensure a network connection is authenticated. */
3780 static void
3781 logon_network_drive (const char *path)
3783 char share[MAX_UTF8_PATH];
3784 int n_slashes;
3785 char drive[4];
3786 UINT drvtype;
3787 char *p;
3788 DWORD val;
3790 if (IS_DIRECTORY_SEP (path[0]) && IS_DIRECTORY_SEP (path[1]))
3791 drvtype = DRIVE_REMOTE;
3792 else if (path[0] == '\0' || path[1] != ':')
3793 drvtype = GetDriveType (NULL);
3794 else
3796 drive[0] = path[0];
3797 drive[1] = ':';
3798 drive[2] = '\\';
3799 drive[3] = '\0';
3800 drvtype = GetDriveType (drive);
3803 /* Only logon to networked drives. */
3804 if (drvtype != DRIVE_REMOTE)
3805 return;
3807 n_slashes = 2;
3808 strncpy (share, path, MAX_UTF8_PATH);
3809 /* Truncate to just server and share name. */
3810 for (p = share + 2; *p && p < share + MAX_UTF8_PATH; p++)
3812 if (IS_DIRECTORY_SEP (*p) && ++n_slashes > 3)
3814 *p = '\0';
3815 break;
3819 if (w32_unicode_filenames)
3821 NETRESOURCEW resourcew;
3822 wchar_t share_w[MAX_PATH];
3824 resourcew.dwScope = RESOURCE_GLOBALNET;
3825 resourcew.dwType = RESOURCETYPE_DISK;
3826 resourcew.dwDisplayType = RESOURCEDISPLAYTYPE_SHARE;
3827 resourcew.dwUsage = RESOURCEUSAGE_CONTAINER;
3828 resourcew.lpLocalName = NULL;
3829 filename_to_utf16 (share, share_w);
3830 resourcew.lpRemoteName = share_w;
3831 resourcew.lpProvider = NULL;
3833 val = WNetAddConnection2W (&resourcew, NULL, NULL, CONNECT_INTERACTIVE);
3835 else
3837 NETRESOURCEA resourcea;
3838 char share_a[MAX_PATH];
3840 resourcea.dwScope = RESOURCE_GLOBALNET;
3841 resourcea.dwType = RESOURCETYPE_DISK;
3842 resourcea.dwDisplayType = RESOURCEDISPLAYTYPE_SHARE;
3843 resourcea.dwUsage = RESOURCEUSAGE_CONTAINER;
3844 resourcea.lpLocalName = NULL;
3845 filename_to_ansi (share, share_a);
3846 resourcea.lpRemoteName = share_a;
3847 resourcea.lpProvider = NULL;
3849 val = WNetAddConnection2A (&resourcea, NULL, NULL, CONNECT_INTERACTIVE);
3852 switch (val)
3854 case NO_ERROR:
3855 case ERROR_ALREADY_ASSIGNED:
3856 break;
3857 case ERROR_ACCESS_DENIED:
3858 case ERROR_LOGON_FAILURE:
3859 errno = EACCES;
3860 break;
3861 case ERROR_BUSY:
3862 errno = EAGAIN;
3863 break;
3864 case ERROR_BAD_NET_NAME:
3865 case ERROR_NO_NET_OR_BAD_PATH:
3866 case ERROR_NO_NETWORK:
3867 case ERROR_CANCELLED:
3868 default:
3869 errno = ENOENT;
3870 break;
3874 /* Emulate faccessat(2). */
3876 faccessat (int dirfd, const char * path, int mode, int flags)
3878 DWORD attributes;
3880 if (dirfd != AT_FDCWD
3881 && !(IS_DIRECTORY_SEP (path[0])
3882 || IS_DEVICE_SEP (path[1])))
3884 errno = EBADF;
3885 return -1;
3888 /* MSVCRT implementation of 'access' doesn't recognize D_OK, and its
3889 newer versions blow up when passed D_OK. */
3890 path = map_w32_filename (path, NULL);
3891 /* If the last element of PATH is a symlink, we need to resolve it
3892 to get the attributes of its target file. Note: any symlinks in
3893 PATH elements other than the last one are transparently resolved
3894 by GetFileAttributes below. */
3895 if ((volume_info.flags & FILE_SUPPORTS_REPARSE_POINTS) != 0
3896 && (flags & AT_SYMLINK_NOFOLLOW) == 0)
3897 path = chase_symlinks (path);
3899 if (w32_unicode_filenames)
3901 wchar_t path_w[MAX_PATH];
3903 filename_to_utf16 (path, path_w);
3904 attributes = GetFileAttributesW (path_w);
3906 else
3908 char path_a[MAX_PATH];
3910 filename_to_ansi (path, path_a);
3911 attributes = GetFileAttributesA (path_a);
3914 if (attributes == -1)
3916 DWORD w32err = GetLastError ();
3918 switch (w32err)
3920 case ERROR_INVALID_NAME:
3921 case ERROR_BAD_PATHNAME:
3922 if (is_unc_volume (path))
3924 attributes = unc_volume_file_attributes (path);
3925 if (attributes == -1)
3927 errno = EACCES;
3928 return -1;
3930 goto check_attrs;
3932 /* FALLTHROUGH */
3933 case ERROR_FILE_NOT_FOUND:
3934 case ERROR_BAD_NETPATH:
3935 errno = ENOENT;
3936 break;
3937 default:
3938 errno = EACCES;
3939 break;
3941 return -1;
3944 check_attrs:
3945 if ((mode & X_OK) != 0
3946 && !(is_exec (path) || (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0))
3948 errno = EACCES;
3949 return -1;
3951 if ((mode & W_OK) != 0 && (attributes & FILE_ATTRIBUTE_READONLY) != 0)
3953 errno = EACCES;
3954 return -1;
3956 if ((mode & D_OK) != 0 && (attributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
3958 errno = EACCES;
3959 return -1;
3961 return 0;
3964 /* A special test for DIRNAME being a directory accessible by the
3965 current user. This is needed because the security permissions in
3966 directory's ACLs are not visible in the Posix-style mode bits
3967 returned by 'stat' and in attributes returned by GetFileAttributes.
3968 So a directory would seem like it's readable by the current user,
3969 but will in fact error out with EACCES when they actually try. */
3971 w32_accessible_directory_p (const char *dirname, ptrdiff_t dirlen)
3973 char pattern[MAX_UTF8_PATH];
3974 bool last_slash = dirlen > 0 && IS_DIRECTORY_SEP (dirname[dirlen - 1]);
3975 HANDLE dh;
3977 /* Network volumes need a different reading method. */
3978 if (is_unc_volume (dirname))
3980 void *read_result = NULL;
3981 wchar_t fnw[MAX_PATH];
3982 char fna[MAX_PATH];
3984 dh = open_unc_volume (dirname);
3985 if (dh != INVALID_HANDLE_VALUE)
3987 read_result = read_unc_volume (dh, fnw, fna, MAX_PATH);
3988 close_unc_volume (dh);
3990 /* Treat empty volumes as accessible. */
3991 return read_result != NULL || GetLastError () == ERROR_NO_MORE_ITEMS;
3994 /* Note: map_w32_filename makes sure DIRNAME is not longer than
3995 MAX_UTF8_PATH. */
3996 strcpy (pattern, map_w32_filename (dirname, NULL));
3998 /* Note: No need to resolve symlinks in FILENAME, because FindFirst
3999 opens the directory that is the target of a symlink. */
4000 if (w32_unicode_filenames)
4002 wchar_t pat_w[MAX_PATH + 2];
4003 WIN32_FIND_DATAW dfd_w;
4005 filename_to_utf16 (pattern, pat_w);
4006 if (!last_slash)
4007 wcscat (pat_w, L"\\");
4008 wcscat (pat_w, L"*");
4009 dh = FindFirstFileW (pat_w, &dfd_w);
4011 else
4013 char pat_a[MAX_PATH + 2];
4014 WIN32_FIND_DATAA dfd_a;
4016 filename_to_ansi (pattern, pat_a);
4017 if (!last_slash)
4018 strcpy (pat_a, "\\");
4019 strcat (pat_a, "*");
4020 /* In case DIRNAME cannot be expressed in characters from the
4021 current ANSI codepage. */
4022 if (_mbspbrk (pat_a, "?"))
4023 dh = INVALID_HANDLE_VALUE;
4024 else
4025 dh = FindFirstFileA (pat_a, &dfd_a);
4028 if (dh == INVALID_HANDLE_VALUE)
4029 return 0;
4030 FindClose (dh);
4031 return 1;
4034 /* A version of 'access' to be used locally with file names in
4035 locale-specific encoding. Does not resolve symlinks and does not
4036 support file names on FAT12 and FAT16 volumes, but that's OK, since
4037 we only invoke this function for files inside the Emacs source or
4038 installation tree, on directories (so any symlinks should have the
4039 directory bit set), and on short file names such as "C:/.emacs". */
4040 static int
4041 sys_access (const char *fname, int mode)
4043 char fname_copy[MAX_PATH], *p;
4044 DWORD attributes;
4046 strcpy (fname_copy, fname);
4047 /* Do the equivalent of unixtodos_filename. */
4048 for (p = fname_copy; *p; p = CharNext (p))
4049 if (*p == '/')
4050 *p = '\\';
4052 if ((attributes = GetFileAttributesA (fname_copy)) == -1)
4054 DWORD w32err = GetLastError ();
4056 switch (w32err)
4058 case ERROR_INVALID_NAME:
4059 case ERROR_BAD_PATHNAME:
4060 case ERROR_FILE_NOT_FOUND:
4061 case ERROR_BAD_NETPATH:
4062 errno = ENOENT;
4063 break;
4064 default:
4065 errno = EACCES;
4066 break;
4068 return -1;
4070 if ((mode & X_OK) != 0
4071 && !(is_exec (fname_copy)
4072 || (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0))
4074 errno = EACCES;
4075 return -1;
4077 if ((mode & W_OK) != 0 && (attributes & FILE_ATTRIBUTE_READONLY) != 0)
4079 errno = EACCES;
4080 return -1;
4082 if ((mode & D_OK) != 0 && (attributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
4084 errno = EACCES;
4085 return -1;
4087 return 0;
4090 /* Shadow some MSVC runtime functions to map requests for long filenames
4091 to reasonable short names if necessary. This was originally added to
4092 permit running Emacs on NT 3.1 on a FAT partition, which doesn't support
4093 long file names. */
4096 sys_chdir (const char * path)
4098 path = map_w32_filename (path, NULL);
4099 if (w32_unicode_filenames)
4101 wchar_t newdir_w[MAX_PATH];
4103 if (filename_to_utf16 (path, newdir_w) == 0)
4104 return _wchdir (newdir_w);
4105 return -1;
4107 else
4109 char newdir_a[MAX_PATH];
4111 if (filename_to_ansi (path, newdir_a) == 0)
4112 return _chdir (newdir_a);
4113 return -1;
4118 sys_chmod (const char * path, int mode)
4120 path = chase_symlinks (map_w32_filename (path, NULL));
4121 if (w32_unicode_filenames)
4123 wchar_t path_w[MAX_PATH];
4125 filename_to_utf16 (path, path_w);
4126 return _wchmod (path_w, mode);
4128 else
4130 char path_a[MAX_PATH];
4132 filename_to_ansi (path, path_a);
4133 return _chmod (path_a, mode);
4138 sys_creat (const char * path, int mode)
4140 path = map_w32_filename (path, NULL);
4141 if (w32_unicode_filenames)
4143 wchar_t path_w[MAX_PATH];
4145 filename_to_utf16 (path, path_w);
4146 return _wcreat (path_w, mode);
4148 else
4150 char path_a[MAX_PATH];
4152 filename_to_ansi (path, path_a);
4153 return _creat (path_a, mode);
4157 FILE *
4158 sys_fopen (const char * path, const char * mode)
4160 int fd;
4161 int oflag;
4162 const char * mode_save = mode;
4164 /* Force all file handles to be non-inheritable. This is necessary to
4165 ensure child processes don't unwittingly inherit handles that might
4166 prevent future file access. */
4168 if (mode[0] == 'r')
4169 oflag = O_RDONLY;
4170 else if (mode[0] == 'w' || mode[0] == 'a')
4171 oflag = O_WRONLY | O_CREAT | O_TRUNC;
4172 else
4173 return NULL;
4175 /* Only do simplistic option parsing. */
4176 while (*++mode)
4177 if (mode[0] == '+')
4179 oflag &= ~(O_RDONLY | O_WRONLY);
4180 oflag |= O_RDWR;
4182 else if (mode[0] == 'b')
4184 oflag &= ~O_TEXT;
4185 oflag |= O_BINARY;
4187 else if (mode[0] == 't')
4189 oflag &= ~O_BINARY;
4190 oflag |= O_TEXT;
4192 else break;
4194 path = map_w32_filename (path, NULL);
4195 if (w32_unicode_filenames)
4197 wchar_t path_w[MAX_PATH];
4199 filename_to_utf16 (path, path_w);
4200 fd = _wopen (path_w, oflag | _O_NOINHERIT, 0644);
4202 else
4204 char path_a[MAX_PATH];
4206 filename_to_ansi (path, path_a);
4207 fd = _open (path_a, oflag | _O_NOINHERIT, 0644);
4209 if (fd < 0)
4210 return NULL;
4212 return _fdopen (fd, mode_save);
4215 /* This only works on NTFS volumes, but is useful to have. */
4217 sys_link (const char * old, const char * new)
4219 HANDLE fileh;
4220 int result = -1;
4221 char oldname[MAX_UTF8_PATH], newname[MAX_UTF8_PATH];
4222 wchar_t oldname_w[MAX_PATH];
4223 char oldname_a[MAX_PATH];
4225 if (old == NULL || new == NULL)
4227 errno = ENOENT;
4228 return -1;
4231 strcpy (oldname, map_w32_filename (old, NULL));
4232 strcpy (newname, map_w32_filename (new, NULL));
4234 if (w32_unicode_filenames)
4236 filename_to_utf16 (oldname, oldname_w);
4237 fileh = CreateFileW (oldname_w, 0, 0, NULL, OPEN_EXISTING,
4238 FILE_FLAG_BACKUP_SEMANTICS, NULL);
4240 else
4242 filename_to_ansi (oldname, oldname_a);
4243 fileh = CreateFileA (oldname_a, 0, 0, NULL, OPEN_EXISTING,
4244 FILE_FLAG_BACKUP_SEMANTICS, NULL);
4246 if (fileh != INVALID_HANDLE_VALUE)
4248 int wlen;
4250 /* Confusingly, the "alternate" stream name field does not apply
4251 when restoring a hard link, and instead contains the actual
4252 stream data for the link (ie. the name of the link to create).
4253 The WIN32_STREAM_ID structure before the cStreamName field is
4254 the stream header, which is then immediately followed by the
4255 stream data. */
4257 struct {
4258 WIN32_STREAM_ID wid;
4259 WCHAR wbuffer[MAX_PATH]; /* extra space for link name */
4260 } data;
4262 /* We used to pass MB_PRECOMPOSED as the 2nd arg here, but MSDN
4263 indicates that flag is unsupported for CP_UTF8, and OTOH says
4264 it is the default anyway. */
4265 wlen = pMultiByteToWideChar (CP_UTF8, 0, newname, -1,
4266 data.wid.cStreamName, MAX_PATH);
4267 if (wlen > 0)
4269 LPVOID context = NULL;
4270 DWORD wbytes = 0;
4272 data.wid.dwStreamId = BACKUP_LINK;
4273 data.wid.dwStreamAttributes = 0;
4274 data.wid.Size.LowPart = wlen * sizeof (WCHAR);
4275 data.wid.Size.HighPart = 0;
4276 data.wid.dwStreamNameSize = 0;
4278 if (BackupWrite (fileh, (LPBYTE)&data,
4279 offsetof (WIN32_STREAM_ID, cStreamName)
4280 + data.wid.Size.LowPart,
4281 &wbytes, FALSE, FALSE, &context)
4282 && BackupWrite (fileh, NULL, 0, &wbytes, TRUE, FALSE, &context))
4284 /* succeeded */
4285 result = 0;
4287 else
4289 DWORD err = GetLastError ();
4290 DWORD attributes;
4292 switch (err)
4294 case ERROR_ACCESS_DENIED:
4295 /* This is what happens when OLDNAME is a directory,
4296 since Windows doesn't support hard links to
4297 directories. Posix says to set errno to EPERM in
4298 that case. */
4299 if (w32_unicode_filenames)
4300 attributes = GetFileAttributesW (oldname_w);
4301 else
4302 attributes = GetFileAttributesA (oldname_a);
4303 if (attributes != -1
4304 && (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
4305 errno = EPERM;
4306 else if (attributes == -1
4307 && is_unc_volume (oldname)
4308 && unc_volume_file_attributes (oldname) != -1)
4309 errno = EPERM;
4310 else
4311 errno = EACCES;
4312 break;
4313 case ERROR_TOO_MANY_LINKS:
4314 errno = EMLINK;
4315 break;
4316 case ERROR_NOT_SAME_DEVICE:
4317 errno = EXDEV;
4318 break;
4319 default:
4320 errno = EINVAL;
4321 break;
4326 CloseHandle (fileh);
4328 else
4329 errno = ENOENT;
4331 return result;
4335 sys_mkdir (const char * path)
4337 path = map_w32_filename (path, NULL);
4339 if (w32_unicode_filenames)
4341 wchar_t path_w[MAX_PATH];
4343 filename_to_utf16 (path, path_w);
4344 return _wmkdir (path_w);
4346 else
4348 char path_a[MAX_PATH];
4350 filename_to_ansi (path, path_a);
4351 return _mkdir (path_a);
4356 sys_open (const char * path, int oflag, int mode)
4358 const char* mpath = map_w32_filename (path, NULL);
4359 int res = -1;
4361 if (w32_unicode_filenames)
4363 wchar_t mpath_w[MAX_PATH];
4365 filename_to_utf16 (mpath, mpath_w);
4366 /* If possible, try to open file without _O_CREAT, to be able to
4367 write to existing hidden and system files. Force all file
4368 handles to be non-inheritable. */
4369 if ((oflag & (_O_CREAT | _O_EXCL)) != (_O_CREAT | _O_EXCL))
4370 res = _wopen (mpath_w, (oflag & ~_O_CREAT) | _O_NOINHERIT, mode);
4371 if (res < 0)
4372 res = _wopen (mpath_w, oflag | _O_NOINHERIT, mode);
4374 else
4376 char mpath_a[MAX_PATH];
4378 filename_to_ansi (mpath, mpath_a);
4379 if ((oflag & (_O_CREAT | _O_EXCL)) != (_O_CREAT | _O_EXCL))
4380 res = _open (mpath_a, (oflag & ~_O_CREAT) | _O_NOINHERIT, mode);
4381 if (res < 0)
4382 res = _open (mpath_a, oflag | _O_NOINHERIT, mode);
4385 return res;
4388 /* Implementation of mkostemp for MS-Windows, to avoid race conditions
4389 when using mktemp.
4391 Standard algorithm for generating a temporary file name seems to be
4392 use pid or tid with a letter on the front (in place of the 6 X's)
4393 and cycle through the letters to find a unique name. We extend
4394 that to allow any reasonable character as the first of the 6 X's,
4395 so that the number of simultaneously used temporary files will be
4396 greater. */
4399 mkostemp (char * template, int flags)
4401 char * p;
4402 int i, fd = -1;
4403 unsigned uid = GetCurrentThreadId ();
4404 int save_errno = errno;
4405 static char first_char[] = "abcdefghijklmnopqrstuvwyz0123456789!%-_@#";
4407 errno = EINVAL;
4408 if (template == NULL)
4409 return -1;
4411 p = template + strlen (template);
4412 i = 5;
4413 /* replace up to the last 5 X's with uid in decimal */
4414 while (--p >= template && p[0] == 'X' && --i >= 0)
4416 p[0] = '0' + uid % 10;
4417 uid /= 10;
4420 if (i < 0 && p[0] == 'X')
4422 i = 0;
4425 p[0] = first_char[i];
4426 if ((fd = sys_open (template,
4427 flags | _O_CREAT | _O_EXCL | _O_RDWR,
4428 S_IRUSR | S_IWUSR)) >= 0
4429 || errno != EEXIST)
4431 if (fd >= 0)
4432 errno = save_errno;
4433 return fd;
4436 while (++i < sizeof (first_char));
4439 /* Template is badly formed or else we can't generate a unique name. */
4440 return -1;
4444 fchmod (int fd, mode_t mode)
4446 return 0;
4450 sys_rename_replace (const char *oldname, const char *newname, BOOL force)
4452 BOOL result;
4453 char temp[MAX_UTF8_PATH], temp_a[MAX_PATH];;
4454 int newname_dev;
4455 int oldname_dev;
4456 bool have_temp_a = false;
4458 /* MoveFile on Windows 95 doesn't correctly change the short file name
4459 alias in a number of circumstances (it is not easy to predict when
4460 just by looking at oldname and newname, unfortunately). In these
4461 cases, renaming through a temporary name avoids the problem.
4463 A second problem on Windows 95 is that renaming through a temp name when
4464 newname is uppercase fails (the final long name ends up in
4465 lowercase, although the short alias might be uppercase) UNLESS the
4466 long temp name is not 8.3.
4468 So, on Windows 95 we always rename through a temp name, and we make sure
4469 the temp name has a long extension to ensure correct renaming. */
4471 strcpy (temp, map_w32_filename (oldname, NULL));
4473 /* volume_info is set indirectly by map_w32_filename. */
4474 oldname_dev = volume_info.serialnum;
4476 if (os_subtype == OS_9X)
4478 char * o;
4479 char * p;
4480 int i = 0;
4481 char oldname_a[MAX_PATH];
4483 oldname = map_w32_filename (oldname, NULL);
4484 filename_to_ansi (oldname, oldname_a);
4485 filename_to_ansi (temp, temp_a);
4486 if ((o = strrchr (oldname_a, '\\')))
4487 o++;
4488 else
4489 o = (char *) oldname_a;
4491 if ((p = strrchr (temp_a, '\\')))
4492 p++;
4493 else
4494 p = temp_a;
4498 /* Force temp name to require a manufactured 8.3 alias - this
4499 seems to make the second rename work properly. */
4500 sprintf (p, "_.%s.%d", o, i);
4501 i++;
4502 result = rename (oldname_a, temp_a);
4504 /* This loop must surely terminate! */
4505 while (result < 0 && errno == EEXIST);
4506 if (result < 0)
4507 return -1;
4508 have_temp_a = true;
4511 /* If FORCE, emulate Unix behavior - newname is deleted if it already exists
4512 (at least if it is a file; don't do this for directories).
4514 Since we mustn't do this if we are just changing the case of the
4515 file name (we would end up deleting the file we are trying to
4516 rename!), we let rename detect if the destination file already
4517 exists - that way we avoid the possible pitfalls of trying to
4518 determine ourselves whether two names really refer to the same
4519 file, which is not always possible in the general case. (Consider
4520 all the permutations of shared or subst'd drives, etc.) */
4522 newname = map_w32_filename (newname, NULL);
4524 /* volume_info is set indirectly by map_w32_filename. */
4525 newname_dev = volume_info.serialnum;
4527 if (w32_unicode_filenames)
4529 wchar_t temp_w[MAX_PATH], newname_w[MAX_PATH];
4531 filename_to_utf16 (temp, temp_w);
4532 filename_to_utf16 (newname, newname_w);
4533 result = _wrename (temp_w, newname_w);
4534 if (result < 0 && force)
4536 DWORD w32err = GetLastError ();
4538 if (errno == EACCES
4539 && newname_dev != oldname_dev)
4541 /* The implementation of `rename' on Windows does not return
4542 errno = EXDEV when you are moving a directory to a
4543 different storage device (ex. logical disk). It returns
4544 EACCES instead. So here we handle such situations and
4545 return EXDEV. */
4546 DWORD attributes;
4548 if ((attributes = GetFileAttributesW (temp_w)) != -1
4549 && (attributes & FILE_ATTRIBUTE_DIRECTORY))
4550 errno = EXDEV;
4552 else if (errno == EEXIST)
4554 if (_wchmod (newname_w, 0666) != 0)
4555 return result;
4556 if (_wunlink (newname_w) != 0)
4557 return result;
4558 result = _wrename (temp_w, newname_w);
4560 else if (w32err == ERROR_PRIVILEGE_NOT_HELD
4561 && is_symlink (temp))
4563 /* This is Windows prohibiting the user from creating a
4564 symlink in another place, since that requires
4565 privileges. */
4566 errno = EPERM;
4570 else
4572 char newname_a[MAX_PATH];
4574 if (!have_temp_a)
4575 filename_to_ansi (temp, temp_a);
4576 filename_to_ansi (newname, newname_a);
4577 result = rename (temp_a, newname_a);
4578 if (result < 0 && force)
4580 DWORD w32err = GetLastError ();
4582 if (errno == EACCES
4583 && newname_dev != oldname_dev)
4585 DWORD attributes;
4587 if ((attributes = GetFileAttributesA (temp_a)) != -1
4588 && (attributes & FILE_ATTRIBUTE_DIRECTORY))
4589 errno = EXDEV;
4591 else if (errno == EEXIST)
4593 if (_chmod (newname_a, 0666) != 0)
4594 return result;
4595 if (_unlink (newname_a) != 0)
4596 return result;
4597 result = rename (temp_a, newname_a);
4599 else if (w32err == ERROR_PRIVILEGE_NOT_HELD
4600 && is_symlink (temp))
4601 errno = EPERM;
4605 return result;
4609 sys_rename (char const *old, char const *new)
4611 return sys_rename_replace (old, new, TRUE);
4615 sys_rmdir (const char * path)
4617 path = map_w32_filename (path, NULL);
4619 if (w32_unicode_filenames)
4621 wchar_t path_w[MAX_PATH];
4623 filename_to_utf16 (path, path_w);
4624 return _wrmdir (path_w);
4626 else
4628 char path_a[MAX_PATH];
4630 filename_to_ansi (path, path_a);
4631 return _rmdir (path_a);
4636 sys_unlink (const char * path)
4638 int rmstatus, e;
4640 path = map_w32_filename (path, NULL);
4642 if (w32_unicode_filenames)
4644 wchar_t path_w[MAX_PATH];
4646 filename_to_utf16 (path, path_w);
4647 /* On Unix, unlink works without write permission. */
4648 _wchmod (path_w, 0666);
4649 rmstatus = _wunlink (path_w);
4650 e = errno;
4651 /* Symlinks to directories can only be deleted by _rmdir;
4652 _unlink returns EACCES. */
4653 if (rmstatus != 0
4654 && errno == EACCES
4655 && (is_symlink (path) & FILE_ATTRIBUTE_DIRECTORY) != 0)
4656 rmstatus = _wrmdir (path_w);
4657 else
4658 errno = e;
4660 else
4662 char path_a[MAX_PATH];
4664 filename_to_ansi (path, path_a);
4665 _chmod (path_a, 0666);
4666 rmstatus = _unlink (path_a);
4667 e = errno;
4668 if (rmstatus != 0
4669 && errno == EACCES
4670 && (is_symlink (path) & FILE_ATTRIBUTE_DIRECTORY) != 0)
4671 rmstatus = _rmdir (path_a);
4672 else
4673 errno = e;
4676 return rmstatus;
4679 static FILETIME utc_base_ft;
4680 static ULONGLONG utc_base; /* In 100ns units */
4681 static int init = 0;
4683 #define FILETIME_TO_U64(result, ft) \
4684 do { \
4685 ULARGE_INTEGER uiTemp; \
4686 uiTemp.LowPart = (ft).dwLowDateTime; \
4687 uiTemp.HighPart = (ft).dwHighDateTime; \
4688 result = uiTemp.QuadPart; \
4689 } while (0)
4691 static void
4692 initialize_utc_base (void)
4694 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
4695 SYSTEMTIME st;
4697 st.wYear = 1970;
4698 st.wMonth = 1;
4699 st.wDay = 1;
4700 st.wHour = 0;
4701 st.wMinute = 0;
4702 st.wSecond = 0;
4703 st.wMilliseconds = 0;
4705 SystemTimeToFileTime (&st, &utc_base_ft);
4706 FILETIME_TO_U64 (utc_base, utc_base_ft);
4709 static time_t
4710 convert_time (FILETIME ft)
4712 ULONGLONG tmp;
4714 if (!init)
4716 initialize_utc_base ();
4717 init = 1;
4720 if (CompareFileTime (&ft, &utc_base_ft) < 0)
4721 return 0;
4723 FILETIME_TO_U64 (tmp, ft);
4724 return (time_t) ((tmp - utc_base) / 10000000L);
4727 static void
4728 convert_from_time_t (time_t time, FILETIME * pft)
4730 ULARGE_INTEGER tmp;
4732 if (!init)
4734 initialize_utc_base ();
4735 init = 1;
4738 /* time in 100ns units since 1-Jan-1601 */
4739 tmp.QuadPart = (ULONGLONG) time * 10000000L + utc_base;
4740 pft->dwHighDateTime = tmp.HighPart;
4741 pft->dwLowDateTime = tmp.LowPart;
4744 static PSECURITY_DESCRIPTOR
4745 get_file_security_desc_by_handle (HANDLE h)
4747 PSECURITY_DESCRIPTOR psd = NULL;
4748 DWORD err;
4749 SECURITY_INFORMATION si = OWNER_SECURITY_INFORMATION
4750 | GROUP_SECURITY_INFORMATION /* | DACL_SECURITY_INFORMATION */ ;
4752 err = get_security_info (h, SE_FILE_OBJECT, si,
4753 NULL, NULL, NULL, NULL, &psd);
4754 if (err != ERROR_SUCCESS)
4755 return NULL;
4757 return psd;
4760 static PSECURITY_DESCRIPTOR
4761 get_file_security_desc_by_name (const char *fname)
4763 PSECURITY_DESCRIPTOR psd = NULL;
4764 DWORD sd_len, err;
4765 SECURITY_INFORMATION si = OWNER_SECURITY_INFORMATION
4766 | GROUP_SECURITY_INFORMATION /* | DACL_SECURITY_INFORMATION */ ;
4768 if (!get_file_security (fname, si, psd, 0, &sd_len))
4770 err = GetLastError ();
4771 if (err != ERROR_INSUFFICIENT_BUFFER)
4772 return NULL;
4775 psd = xmalloc (sd_len);
4776 if (!get_file_security (fname, si, psd, sd_len, &sd_len))
4778 xfree (psd);
4779 return NULL;
4782 return psd;
4785 static DWORD
4786 get_rid (PSID sid)
4788 unsigned n_subauthorities;
4790 /* Use the last sub-authority value of the RID, the relative
4791 portion of the SID, as user/group ID. */
4792 n_subauthorities = *get_sid_sub_authority_count (sid);
4793 if (n_subauthorities < 1)
4794 return 0; /* the "World" RID */
4795 return *get_sid_sub_authority (sid, n_subauthorities - 1);
4798 /* Caching SID and account values for faster lokup. */
4800 struct w32_id {
4801 unsigned rid;
4802 struct w32_id *next;
4803 char name[GNLEN+1];
4804 unsigned char sid[FLEXIBLE_ARRAY_MEMBER];
4807 static struct w32_id *w32_idlist;
4809 static int
4810 w32_cached_id (PSID sid, unsigned *id, char *name)
4812 struct w32_id *tail, *found;
4814 for (found = NULL, tail = w32_idlist; tail; tail = tail->next)
4816 if (equal_sid ((PSID)tail->sid, sid))
4818 found = tail;
4819 break;
4822 if (found)
4824 *id = found->rid;
4825 strcpy (name, found->name);
4826 return 1;
4828 else
4829 return 0;
4832 static void
4833 w32_add_to_cache (PSID sid, unsigned id, char *name)
4835 DWORD sid_len;
4836 struct w32_id *new_entry;
4838 /* We don't want to leave behind stale cache from when Emacs was
4839 dumped. */
4840 if (initialized)
4842 sid_len = get_length_sid (sid);
4843 new_entry = xmalloc (offsetof (struct w32_id, sid) + sid_len);
4844 if (new_entry)
4846 new_entry->rid = id;
4847 strcpy (new_entry->name, name);
4848 copy_sid (sid_len, (PSID)new_entry->sid, sid);
4849 new_entry->next = w32_idlist;
4850 w32_idlist = new_entry;
4855 #define UID 1
4856 #define GID 2
4858 static int
4859 get_name_and_id (PSECURITY_DESCRIPTOR psd, unsigned *id, char *nm, int what)
4861 PSID sid = NULL;
4862 BOOL dflt;
4863 SID_NAME_USE ignore;
4864 char name[UNLEN+1];
4865 DWORD name_len = sizeof (name);
4866 char domain[1024];
4867 DWORD domain_len = sizeof (domain);
4868 int use_dflt = 0;
4869 int result;
4871 if (what == UID)
4872 result = get_security_descriptor_owner (psd, &sid, &dflt);
4873 else if (what == GID)
4874 result = get_security_descriptor_group (psd, &sid, &dflt);
4875 else
4876 result = 0;
4878 if (!result || !is_valid_sid (sid))
4879 use_dflt = 1;
4880 else if (!w32_cached_id (sid, id, nm))
4882 if (!lookup_account_sid (NULL, sid, name, &name_len,
4883 domain, &domain_len, &ignore)
4884 || name_len > UNLEN+1)
4885 use_dflt = 1;
4886 else
4888 *id = get_rid (sid);
4889 strcpy (nm, name);
4890 w32_add_to_cache (sid, *id, name);
4893 return use_dflt;
4896 static void
4897 get_file_owner_and_group (PSECURITY_DESCRIPTOR psd, struct stat *st)
4899 int dflt_usr = 0, dflt_grp = 0;
4901 if (!psd)
4903 dflt_usr = 1;
4904 dflt_grp = 1;
4906 else
4908 if (get_name_and_id (psd, &st->st_uid, st->st_uname, UID))
4909 dflt_usr = 1;
4910 if (get_name_and_id (psd, &st->st_gid, st->st_gname, GID))
4911 dflt_grp = 1;
4913 /* Consider files to belong to current user/group, if we cannot get
4914 more accurate information. */
4915 if (dflt_usr)
4917 st->st_uid = dflt_passwd.pw_uid;
4918 strcpy (st->st_uname, dflt_passwd.pw_name);
4920 if (dflt_grp)
4922 st->st_gid = dflt_passwd.pw_gid;
4923 strcpy (st->st_gname, dflt_group.gr_name);
4927 /* Return non-zero if NAME is a potentially slow filesystem. */
4928 int is_slow_fs (const char *);
4931 is_slow_fs (const char *name)
4933 char drive_root[4];
4934 UINT devtype;
4936 if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1]))
4937 devtype = DRIVE_REMOTE; /* assume UNC name is remote */
4938 else if (!(strlen (name) >= 2 && IS_DEVICE_SEP (name[1])))
4939 devtype = GetDriveType (NULL); /* use root of current drive */
4940 else
4942 /* GetDriveType needs the root directory of the drive. */
4943 strncpy (drive_root, name, 2);
4944 drive_root[2] = '\\';
4945 drive_root[3] = '\0';
4946 devtype = GetDriveType (drive_root);
4948 return !(devtype == DRIVE_FIXED || devtype == DRIVE_RAMDISK);
4951 /* If this is non-zero, the caller wants accurate information about
4952 file's owner and group, which could be expensive to get. dired.c
4953 uses this flag when needed for the job at hand. */
4954 int w32_stat_get_owner_group;
4956 /* MSVC stat function can't cope with UNC names and has other bugs, so
4957 replace it with our own. This also allows us to calculate consistent
4958 inode values and owner/group without hacks in the main Emacs code,
4959 and support file names encoded in UTF-8. */
4961 static int
4962 stat_worker (const char * path, struct stat * buf, int follow_symlinks)
4964 char *name, *save_name, *r;
4965 WIN32_FIND_DATAW wfd_w;
4966 WIN32_FIND_DATAA wfd_a;
4967 HANDLE fh;
4968 unsigned __int64 fake_inode = 0;
4969 int permission;
4970 int len;
4971 int rootdir = FALSE;
4972 PSECURITY_DESCRIPTOR psd = NULL;
4973 int is_a_symlink = 0;
4974 DWORD file_flags = FILE_FLAG_BACKUP_SEMANTICS;
4975 DWORD access_rights = 0;
4976 DWORD fattrs = 0, serialnum = 0, fs_high = 0, fs_low = 0, nlinks = 1;
4977 FILETIME ctime, atime, wtime;
4978 wchar_t name_w[MAX_PATH];
4979 char name_a[MAX_PATH];
4981 if (path == NULL || buf == NULL)
4983 errno = EFAULT;
4984 return -1;
4987 save_name = name = (char *) map_w32_filename (path, &path);
4988 /* Must be valid filename, no wild cards or other invalid
4989 characters. */
4990 if (strpbrk (name, "*?|<>\""))
4992 errno = ENOENT;
4993 return -1;
4996 len = strlen (name);
4997 /* Allocate 1 extra byte so that we could append a slash to a root
4998 directory, down below. */
4999 name = strcpy (alloca (len + 2), name);
5001 /* Avoid a somewhat costly call to is_symlink if the filesystem
5002 doesn't support symlinks. */
5003 if ((volume_info.flags & FILE_SUPPORTS_REPARSE_POINTS) != 0)
5004 is_a_symlink = is_symlink (name);
5006 /* Plan A: Open the file and get all the necessary information via
5007 the resulting handle. This solves several issues in one blow:
5009 . retrieves attributes for the target of a symlink, if needed
5010 . gets attributes of root directories and symlinks pointing to
5011 root directories, thus avoiding the need for special-casing
5012 these and detecting them by examining the file-name format
5013 . retrieves more accurate attributes (e.g., non-zero size for
5014 some directories, esp. directories that are junction points)
5015 . correctly resolves "c:/..", "/.." and similar file names
5016 . avoids run-time penalties for 99% of use cases
5018 Plan A is always tried first, unless the user asked not to (but
5019 if the file is a symlink and we need to follow links, we try Plan
5020 A even if the user asked not to).
5022 If Plan A fails, we go to Plan B (below), where various
5023 potentially expensive techniques must be used to handle "special"
5024 files such as UNC volumes etc. */
5025 if (!(NILP (Vw32_get_true_file_attributes)
5026 || (EQ (Vw32_get_true_file_attributes, Qlocal) && is_slow_fs (name)))
5027 /* Following symlinks requires getting the info by handle. */
5028 || (is_a_symlink && follow_symlinks))
5030 BY_HANDLE_FILE_INFORMATION info;
5032 if (is_a_symlink && !follow_symlinks)
5033 file_flags |= FILE_FLAG_OPEN_REPARSE_POINT;
5034 /* READ_CONTROL access rights are required to get security info
5035 by handle. But if the OS doesn't support security in the
5036 first place, we don't need to try. */
5037 if (is_windows_9x () != TRUE)
5038 access_rights |= READ_CONTROL;
5040 if (w32_unicode_filenames)
5042 filename_to_utf16 (name, name_w);
5043 fh = CreateFileW (name_w, access_rights, 0, NULL, OPEN_EXISTING,
5044 file_flags, NULL);
5045 /* If CreateFile fails with READ_CONTROL, try again with
5046 zero as access rights. */
5047 if (fh == INVALID_HANDLE_VALUE && access_rights)
5048 fh = CreateFileW (name_w, 0, 0, NULL, OPEN_EXISTING,
5049 file_flags, NULL);
5051 else
5053 filename_to_ansi (name, name_a);
5054 fh = CreateFileA (name_a, access_rights, 0, NULL, OPEN_EXISTING,
5055 file_flags, NULL);
5056 if (fh == INVALID_HANDLE_VALUE && access_rights)
5057 fh = CreateFileA (name_a, 0, 0, NULL, OPEN_EXISTING,
5058 file_flags, NULL);
5060 if (fh == INVALID_HANDLE_VALUE)
5061 goto no_true_file_attributes;
5063 /* This is more accurate in terms of getting the correct number
5064 of links, but is quite slow (it is noticeable when Emacs is
5065 making a list of file name completions). */
5066 if (GetFileInformationByHandle (fh, &info))
5068 nlinks = info.nNumberOfLinks;
5069 /* Might as well use file index to fake inode values, but this
5070 is not guaranteed to be unique unless we keep a handle open
5071 all the time (even then there are situations where it is
5072 not unique). Reputedly, there are at most 48 bits of info
5073 (on NTFS, presumably less on FAT). */
5074 fake_inode = info.nFileIndexHigh;
5075 fake_inode <<= 32;
5076 fake_inode += info.nFileIndexLow;
5077 serialnum = info.dwVolumeSerialNumber;
5078 fs_high = info.nFileSizeHigh;
5079 fs_low = info.nFileSizeLow;
5080 ctime = info.ftCreationTime;
5081 atime = info.ftLastAccessTime;
5082 wtime = info.ftLastWriteTime;
5083 fattrs = info.dwFileAttributes;
5085 else
5087 /* We don't go to Plan B here, because it's not clear that
5088 it's a good idea. The only known use case where
5089 CreateFile succeeds, but GetFileInformationByHandle fails
5090 (with ERROR_INVALID_FUNCTION) is for character devices
5091 such as NUL, PRN, etc. For these, switching to Plan B is
5092 a net loss, because we lose the character device
5093 attribute returned by GetFileType below (FindFirstFile
5094 doesn't set that bit in the attributes), and the other
5095 fields don't make sense for character devices anyway.
5096 Emacs doesn't really care for non-file entities in the
5097 context of l?stat, so neither do we. */
5099 /* w32err is assigned so one could put a breakpoint here and
5100 examine its value, when GetFileInformationByHandle
5101 fails. */
5102 DWORD w32err = GetLastError ();
5104 switch (w32err)
5106 case ERROR_FILE_NOT_FOUND: /* can this ever happen? */
5107 errno = ENOENT;
5108 return -1;
5112 /* Test for a symlink before testing for a directory, since
5113 symlinks to directories have the directory bit set, but we
5114 don't want them to appear as directories. */
5115 if (is_a_symlink && !follow_symlinks)
5116 buf->st_mode = S_IFLNK;
5117 else if (fattrs & FILE_ATTRIBUTE_DIRECTORY)
5118 buf->st_mode = S_IFDIR;
5119 else
5121 DWORD ftype = GetFileType (fh);
5123 switch (ftype)
5125 case FILE_TYPE_DISK:
5126 buf->st_mode = S_IFREG;
5127 break;
5128 case FILE_TYPE_PIPE:
5129 buf->st_mode = S_IFIFO;
5130 break;
5131 case FILE_TYPE_CHAR:
5132 case FILE_TYPE_UNKNOWN:
5133 default:
5134 buf->st_mode = S_IFCHR;
5137 /* We produce the fallback owner and group data, based on the
5138 current user that runs Emacs, in the following cases:
5140 . caller didn't request owner and group info
5141 . this is Windows 9X
5142 . getting security by handle failed, and we need to produce
5143 information for the target of a symlink (this is better
5144 than producing a potentially misleading info about the
5145 symlink itself)
5147 If getting security by handle fails, and we don't need to
5148 resolve symlinks, we try getting security by name. */
5149 if (!w32_stat_get_owner_group || is_windows_9x () == TRUE)
5150 get_file_owner_and_group (NULL, buf);
5151 else
5153 psd = get_file_security_desc_by_handle (fh);
5154 if (psd)
5156 get_file_owner_and_group (psd, buf);
5157 LocalFree (psd);
5159 else if (!(is_a_symlink && follow_symlinks))
5161 psd = get_file_security_desc_by_name (name);
5162 get_file_owner_and_group (psd, buf);
5163 xfree (psd);
5165 else
5166 get_file_owner_and_group (NULL, buf);
5168 CloseHandle (fh);
5170 else
5172 no_true_file_attributes:
5173 /* Plan B: Either getting a handle on the file failed, or the
5174 caller explicitly asked us to not bother making this
5175 information more accurate.
5177 Implementation note: In Plan B, we never bother to resolve
5178 symlinks, even if we got here because we tried Plan A and
5179 failed. That's because, even if the caller asked for extra
5180 precision by setting Vw32_get_true_file_attributes to t,
5181 resolving symlinks requires acquiring a file handle to the
5182 symlink, which we already know will fail. And if the user
5183 did not ask for extra precision, resolving symlinks will fly
5184 in the face of that request, since the user then wants the
5185 lightweight version of the code. */
5186 rootdir = (path >= save_name + len - 1
5187 && (IS_DIRECTORY_SEP (*path) || *path == 0));
5189 /* If name is "c:/.." or "/.." then stat "c:/" or "/". */
5190 r = IS_DEVICE_SEP (name[1]) ? &name[2] : name;
5191 if (IS_DIRECTORY_SEP (r[0])
5192 && r[1] == '.' && r[2] == '.' && r[3] == '\0')
5193 r[1] = r[2] = '\0';
5195 /* Note: If NAME is a symlink to the root of a UNC volume
5196 (i.e. "\\SERVER"), we will not detect that here, and we will
5197 return data about the symlink as result of FindFirst below.
5198 This is unfortunate, but that marginal use case does not
5199 justify a call to chase_symlinks which would impose a penalty
5200 on all the other use cases. (We get here for symlinks to
5201 roots of UNC volumes because CreateFile above fails for them,
5202 unlike with symlinks to root directories X:\ of drives.) */
5203 if (is_unc_volume (name))
5205 fattrs = unc_volume_file_attributes (name);
5206 if (fattrs == -1)
5207 return -1;
5209 ctime = atime = wtime = utc_base_ft;
5211 else if (rootdir)
5213 /* Make sure root directories end in a slash. */
5214 if (!IS_DIRECTORY_SEP (name[len-1]))
5215 strcpy (name + len, "\\");
5216 if (GetDriveType (name) < 2)
5218 errno = ENOENT;
5219 return -1;
5222 fattrs = FILE_ATTRIBUTE_DIRECTORY;
5223 ctime = atime = wtime = utc_base_ft;
5225 else
5227 int have_wfd = -1;
5229 /* Make sure non-root directories do NOT end in a slash,
5230 otherwise FindFirstFile might fail. */
5231 if (IS_DIRECTORY_SEP (name[len-1]))
5232 name[len - 1] = 0;
5234 /* (This is hacky, but helps when doing file completions on
5235 network drives.) Optimize by using information available from
5236 active readdir if possible. */
5237 len = strlen (dir_pathname);
5238 if (IS_DIRECTORY_SEP (dir_pathname[len-1]))
5239 len--;
5240 if (dir_find_handle != INVALID_HANDLE_VALUE
5241 && last_dir_find_data != -1
5242 && !(is_a_symlink && follow_symlinks)
5243 /* The 2 file-name comparisons below support only ASCII
5244 characters, and will lose (compare not equal) when
5245 the file names include non-ASCII characters that are
5246 the same but for the case. However, doing this
5247 properly involves: (a) converting both file names to
5248 UTF-16, (b) lower-casing both names using CharLowerW,
5249 and (c) comparing the results; this would be quite a
5250 bit slower, whereas Plan B is for users who want
5251 lightweight albeit inaccurate version of 'stat'. */
5252 && c_strncasecmp (save_name, dir_pathname, len) == 0
5253 && IS_DIRECTORY_SEP (name[len])
5254 && xstrcasecmp (name + len + 1, dir_static.d_name) == 0)
5256 have_wfd = last_dir_find_data;
5257 /* This was the last entry returned by readdir. */
5258 if (last_dir_find_data == DIR_FIND_DATA_W)
5259 wfd_w = dir_find_data_w;
5260 else
5261 wfd_a = dir_find_data_a;
5263 else
5265 logon_network_drive (name);
5267 if (w32_unicode_filenames)
5269 filename_to_utf16 (name, name_w);
5270 fh = FindFirstFileW (name_w, &wfd_w);
5271 have_wfd = DIR_FIND_DATA_W;
5273 else
5275 filename_to_ansi (name, name_a);
5276 /* If NAME includes characters not representable by
5277 the current ANSI codepage, filename_to_ansi
5278 usually replaces them with a '?'. We don't want
5279 to let FindFirstFileA interpret those as wildcards,
5280 and "succeed", returning us data from some random
5281 file in the same directory. */
5282 if (_mbspbrk (name_a, "?"))
5283 fh = INVALID_HANDLE_VALUE;
5284 else
5285 fh = FindFirstFileA (name_a, &wfd_a);
5286 have_wfd = DIR_FIND_DATA_A;
5288 if (fh == INVALID_HANDLE_VALUE)
5290 errno = ENOENT;
5291 return -1;
5293 FindClose (fh);
5295 /* Note: if NAME is a symlink, the information we get from
5296 FindFirstFile is for the symlink, not its target. */
5297 if (have_wfd == DIR_FIND_DATA_W)
5299 fattrs = wfd_w.dwFileAttributes;
5300 ctime = wfd_w.ftCreationTime;
5301 atime = wfd_w.ftLastAccessTime;
5302 wtime = wfd_w.ftLastWriteTime;
5303 fs_high = wfd_w.nFileSizeHigh;
5304 fs_low = wfd_w.nFileSizeLow;
5306 else
5308 fattrs = wfd_a.dwFileAttributes;
5309 ctime = wfd_a.ftCreationTime;
5310 atime = wfd_a.ftLastAccessTime;
5311 wtime = wfd_a.ftLastWriteTime;
5312 fs_high = wfd_a.nFileSizeHigh;
5313 fs_low = wfd_a.nFileSizeLow;
5315 fake_inode = 0;
5316 nlinks = 1;
5317 serialnum = volume_info.serialnum;
5319 if (is_a_symlink && !follow_symlinks)
5320 buf->st_mode = S_IFLNK;
5321 else if (fattrs & FILE_ATTRIBUTE_DIRECTORY)
5322 buf->st_mode = S_IFDIR;
5323 else
5324 buf->st_mode = S_IFREG;
5326 get_file_owner_and_group (NULL, buf);
5329 buf->st_ino = fake_inode;
5331 buf->st_dev = serialnum;
5332 buf->st_rdev = serialnum;
5334 buf->st_size = fs_high;
5335 buf->st_size <<= 32;
5336 buf->st_size += fs_low;
5337 buf->st_nlink = nlinks;
5339 /* Convert timestamps to Unix format. */
5340 buf->st_mtime = convert_time (wtime);
5341 buf->st_atime = convert_time (atime);
5342 if (buf->st_atime == 0) buf->st_atime = buf->st_mtime;
5343 buf->st_ctime = convert_time (ctime);
5344 if (buf->st_ctime == 0) buf->st_ctime = buf->st_mtime;
5346 /* determine rwx permissions */
5347 if (is_a_symlink && !follow_symlinks)
5348 permission = S_IREAD | S_IWRITE | S_IEXEC; /* Posix expectations */
5349 else
5351 if (fattrs & FILE_ATTRIBUTE_READONLY)
5352 permission = S_IREAD;
5353 else
5354 permission = S_IREAD | S_IWRITE;
5356 if (fattrs & FILE_ATTRIBUTE_DIRECTORY)
5357 permission |= S_IEXEC;
5358 else if (is_exec (name))
5359 permission |= S_IEXEC;
5362 buf->st_mode |= permission | (permission >> 3) | (permission >> 6);
5364 return 0;
5368 stat (const char * path, struct stat * buf)
5370 return stat_worker (path, buf, 1);
5374 lstat (const char * path, struct stat * buf)
5376 return stat_worker (path, buf, 0);
5380 fstatat (int fd, char const *name, struct stat *st, int flags)
5382 /* Rely on a hack: an open directory is modeled as file descriptor 0.
5383 This is good enough for the current usage in Emacs, but is fragile.
5385 FIXME: Add proper support for fdopendir, fstatat, readlinkat.
5386 Gnulib does this and can serve as a model. */
5387 char fullname[MAX_UTF8_PATH];
5389 if (fd != AT_FDCWD)
5391 char lastc = dir_pathname[strlen (dir_pathname) - 1];
5393 if (_snprintf (fullname, sizeof fullname, "%s%s%s",
5394 dir_pathname, IS_DIRECTORY_SEP (lastc) ? "" : "/", name)
5395 < 0)
5397 errno = ENAMETOOLONG;
5398 return -1;
5400 name = fullname;
5403 return stat_worker (name, st, ! (flags & AT_SYMLINK_NOFOLLOW));
5406 /* Provide fstat and utime as well as stat for consistent handling of
5407 file timestamps. */
5409 fstat (int desc, struct stat * buf)
5411 HANDLE fh = (HANDLE) _get_osfhandle (desc);
5412 BY_HANDLE_FILE_INFORMATION info;
5413 unsigned __int64 fake_inode;
5414 int permission;
5416 switch (GetFileType (fh) & ~FILE_TYPE_REMOTE)
5418 case FILE_TYPE_DISK:
5419 buf->st_mode = S_IFREG;
5420 if (!GetFileInformationByHandle (fh, &info))
5422 errno = EACCES;
5423 return -1;
5425 break;
5426 case FILE_TYPE_PIPE:
5427 buf->st_mode = S_IFIFO;
5428 goto non_disk;
5429 case FILE_TYPE_CHAR:
5430 case FILE_TYPE_UNKNOWN:
5431 default:
5432 buf->st_mode = S_IFCHR;
5433 non_disk:
5434 memset (&info, 0, sizeof (info));
5435 info.dwFileAttributes = 0;
5436 info.ftCreationTime = utc_base_ft;
5437 info.ftLastAccessTime = utc_base_ft;
5438 info.ftLastWriteTime = utc_base_ft;
5441 if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
5442 buf->st_mode = S_IFDIR;
5444 buf->st_nlink = info.nNumberOfLinks;
5445 /* Might as well use file index to fake inode values, but this
5446 is not guaranteed to be unique unless we keep a handle open
5447 all the time (even then there are situations where it is
5448 not unique). Reputedly, there are at most 48 bits of info
5449 (on NTFS, presumably less on FAT). */
5450 fake_inode = info.nFileIndexHigh;
5451 fake_inode <<= 32;
5452 fake_inode += info.nFileIndexLow;
5454 /* MSVC defines _ino_t to be short; other libc's might not. */
5455 if (sizeof (buf->st_ino) == 2)
5456 buf->st_ino = fake_inode ^ (fake_inode >> 16);
5457 else
5458 buf->st_ino = fake_inode;
5460 /* If the caller so requested, get the true file owner and group.
5461 Otherwise, consider the file to belong to the current user. */
5462 if (!w32_stat_get_owner_group || is_windows_9x () == TRUE)
5463 get_file_owner_and_group (NULL, buf);
5464 else
5466 PSECURITY_DESCRIPTOR psd = NULL;
5468 psd = get_file_security_desc_by_handle (fh);
5469 if (psd)
5471 get_file_owner_and_group (psd, buf);
5472 LocalFree (psd);
5474 else
5475 get_file_owner_and_group (NULL, buf);
5478 buf->st_dev = info.dwVolumeSerialNumber;
5479 buf->st_rdev = info.dwVolumeSerialNumber;
5481 buf->st_size = info.nFileSizeHigh;
5482 buf->st_size <<= 32;
5483 buf->st_size += info.nFileSizeLow;
5485 /* Convert timestamps to Unix format. */
5486 buf->st_mtime = convert_time (info.ftLastWriteTime);
5487 buf->st_atime = convert_time (info.ftLastAccessTime);
5488 if (buf->st_atime == 0) buf->st_atime = buf->st_mtime;
5489 buf->st_ctime = convert_time (info.ftCreationTime);
5490 if (buf->st_ctime == 0) buf->st_ctime = buf->st_mtime;
5492 /* determine rwx permissions */
5493 if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
5494 permission = S_IREAD;
5495 else
5496 permission = S_IREAD | S_IWRITE;
5498 if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
5499 permission |= S_IEXEC;
5500 else
5502 #if 0 /* no way of knowing the filename */
5503 char * p = strrchr (name, '.');
5504 if (p != NULL &&
5505 (xstrcasecmp (p, ".exe") == 0 ||
5506 xstrcasecmp (p, ".com") == 0 ||
5507 xstrcasecmp (p, ".bat") == 0 ||
5508 xstrcasecmp (p, ".cmd") == 0))
5509 permission |= S_IEXEC;
5510 #endif
5513 buf->st_mode |= permission | (permission >> 3) | (permission >> 6);
5515 return 0;
5518 /* A version of 'utime' which handles directories as well as
5519 files. */
5522 utime (const char *name, struct utimbuf *times)
5524 struct utimbuf deftime;
5525 HANDLE fh;
5526 FILETIME mtime;
5527 FILETIME atime;
5529 if (times == NULL)
5531 deftime.modtime = deftime.actime = time (NULL);
5532 times = &deftime;
5535 if (w32_unicode_filenames)
5537 wchar_t name_utf16[MAX_PATH];
5539 if (filename_to_utf16 (name, name_utf16) != 0)
5540 return -1; /* errno set by filename_to_utf16 */
5542 /* Need write access to set times. */
5543 fh = CreateFileW (name_utf16, FILE_WRITE_ATTRIBUTES,
5544 /* If NAME specifies a directory, FILE_SHARE_DELETE
5545 allows other processes to delete files inside it,
5546 while we have the directory open. */
5547 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
5548 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
5550 else
5552 char name_ansi[MAX_PATH];
5554 if (filename_to_ansi (name, name_ansi) != 0)
5555 return -1; /* errno set by filename_to_ansi */
5557 fh = CreateFileA (name_ansi, FILE_WRITE_ATTRIBUTES,
5558 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
5559 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
5561 if (fh != INVALID_HANDLE_VALUE)
5563 convert_from_time_t (times->actime, &atime);
5564 convert_from_time_t (times->modtime, &mtime);
5565 if (!SetFileTime (fh, NULL, &atime, &mtime))
5567 CloseHandle (fh);
5568 errno = EACCES;
5569 return -1;
5571 CloseHandle (fh);
5573 else
5575 DWORD err = GetLastError ();
5577 switch (err)
5579 case ERROR_FILE_NOT_FOUND:
5580 case ERROR_PATH_NOT_FOUND:
5581 case ERROR_INVALID_DRIVE:
5582 case ERROR_BAD_NETPATH:
5583 case ERROR_DEV_NOT_EXIST:
5584 /* ERROR_INVALID_NAME is the error CreateFile sets when the
5585 file name includes ?s, i.e. translation to ANSI failed. */
5586 case ERROR_INVALID_NAME:
5587 errno = ENOENT;
5588 break;
5589 case ERROR_TOO_MANY_OPEN_FILES:
5590 errno = ENFILE;
5591 break;
5592 case ERROR_ACCESS_DENIED:
5593 case ERROR_SHARING_VIOLATION:
5594 errno = EACCES;
5595 break;
5596 default:
5597 errno = EINVAL;
5598 break;
5600 return -1;
5602 return 0;
5606 sys_umask (int mode)
5608 static int current_mask;
5609 int retval, arg = 0;
5611 /* The only bit we really support is the write bit. Files are
5612 always readable on MS-Windows, and the execute bit does not exist
5613 at all. */
5614 /* FIXME: if the GROUP and OTHER bits are reset, we should use ACLs
5615 to prevent access by other users on NTFS. */
5616 if ((mode & S_IWRITE) != 0)
5617 arg |= S_IWRITE;
5619 retval = _umask (arg);
5620 /* Merge into the return value the bits they've set the last time,
5621 which msvcrt.dll ignores and never returns. Emacs insists on its
5622 notion of mask being identical to what we return. */
5623 retval |= (current_mask & ~S_IWRITE);
5624 current_mask = mode;
5626 return retval;
5630 /* Symlink-related functions. */
5631 #ifndef SYMBOLIC_LINK_FLAG_DIRECTORY
5632 #define SYMBOLIC_LINK_FLAG_DIRECTORY 0x1
5633 #endif
5636 symlink (char const *filename, char const *linkname)
5638 char linkfn[MAX_UTF8_PATH], *tgtfn;
5639 DWORD flags = 0;
5640 int dir_access, filename_ends_in_slash;
5642 /* Diagnostics follows Posix as much as possible. */
5643 if (filename == NULL || linkname == NULL)
5645 errno = EFAULT;
5646 return -1;
5648 if (!*filename)
5650 errno = ENOENT;
5651 return -1;
5653 if (strlen (filename) > MAX_UTF8_PATH || strlen (linkname) > MAX_UTF8_PATH)
5655 errno = ENAMETOOLONG;
5656 return -1;
5659 strcpy (linkfn, map_w32_filename (linkname, NULL));
5660 if ((volume_info.flags & FILE_SUPPORTS_REPARSE_POINTS) == 0)
5662 errno = EPERM;
5663 return -1;
5666 /* Note: since empty FILENAME was already rejected, we can safely
5667 refer to FILENAME[1]. */
5668 if (!(IS_DIRECTORY_SEP (filename[0]) || IS_DEVICE_SEP (filename[1])))
5670 /* Non-absolute FILENAME is understood as being relative to
5671 LINKNAME's directory. We need to prepend that directory to
5672 FILENAME to get correct results from faccessat below, since
5673 otherwise it will interpret FILENAME relative to the
5674 directory where the Emacs process runs. Note that
5675 make-symbolic-link always makes sure LINKNAME is a fully
5676 expanded file name. */
5677 char tem[MAX_UTF8_PATH];
5678 char *p = linkfn + strlen (linkfn);
5680 while (p > linkfn && !IS_ANY_SEP (p[-1]))
5681 p--;
5682 if (p > linkfn)
5683 strncpy (tem, linkfn, p - linkfn);
5684 strcpy (tem + (p - linkfn), filename);
5685 dir_access = faccessat (AT_FDCWD, tem, D_OK, AT_EACCESS);
5687 else
5688 dir_access = faccessat (AT_FDCWD, filename, D_OK, AT_EACCESS);
5690 /* Since Windows distinguishes between symlinks to directories and
5691 to files, we provide a kludgy feature: if FILENAME doesn't
5692 exist, but ends in a slash, we create a symlink to directory. If
5693 FILENAME exists and is a directory, we always create a symlink to
5694 directory. */
5695 filename_ends_in_slash = IS_DIRECTORY_SEP (filename[strlen (filename) - 1]);
5696 if (dir_access == 0 || filename_ends_in_slash)
5697 flags = SYMBOLIC_LINK_FLAG_DIRECTORY;
5699 tgtfn = (char *)map_w32_filename (filename, NULL);
5700 if (filename_ends_in_slash)
5701 tgtfn[strlen (tgtfn) - 1] = '\0';
5703 errno = 0;
5704 if (!create_symbolic_link (linkfn, tgtfn, flags))
5706 /* ENOSYS is set by create_symbolic_link, when it detects that
5707 the OS doesn't support the CreateSymbolicLink API. */
5708 if (errno != ENOSYS)
5710 DWORD w32err = GetLastError ();
5712 switch (w32err)
5714 /* ERROR_SUCCESS is sometimes returned when LINKFN and
5715 TGTFN point to the same file name, go figure. */
5716 case ERROR_SUCCESS:
5717 case ERROR_FILE_EXISTS:
5718 errno = EEXIST;
5719 break;
5720 case ERROR_ACCESS_DENIED:
5721 errno = EACCES;
5722 break;
5723 case ERROR_FILE_NOT_FOUND:
5724 case ERROR_PATH_NOT_FOUND:
5725 case ERROR_BAD_NETPATH:
5726 case ERROR_INVALID_REPARSE_DATA:
5727 errno = ENOENT;
5728 break;
5729 case ERROR_DIRECTORY:
5730 errno = EISDIR;
5731 break;
5732 case ERROR_PRIVILEGE_NOT_HELD:
5733 case ERROR_NOT_ALL_ASSIGNED:
5734 errno = EPERM;
5735 break;
5736 case ERROR_DISK_FULL:
5737 errno = ENOSPC;
5738 break;
5739 default:
5740 errno = EINVAL;
5741 break;
5744 return -1;
5746 return 0;
5749 /* A quick inexpensive test of whether FILENAME identifies a file that
5750 is a symlink. Returns non-zero if it is, zero otherwise. FILENAME
5751 must already be in the normalized form returned by
5752 map_w32_filename. If the symlink is to a directory, the
5753 FILE_ATTRIBUTE_DIRECTORY bit will be set in the return value.
5755 Note: for repeated operations on many files, it is best to test
5756 whether the underlying volume actually supports symlinks, by
5757 testing the FILE_SUPPORTS_REPARSE_POINTS bit in volume's flags, and
5758 avoid the call to this function if it doesn't. That's because the
5759 call to GetFileAttributes takes a non-negligible time, especially
5760 on non-local or removable filesystems. See stat_worker for an
5761 example of how to do that. */
5762 static int
5763 is_symlink (const char *filename)
5765 DWORD attrs;
5766 wchar_t filename_w[MAX_PATH];
5767 char filename_a[MAX_PATH];
5768 WIN32_FIND_DATAW wfdw;
5769 WIN32_FIND_DATAA wfda;
5770 HANDLE fh;
5771 int attrs_mean_symlink;
5773 if (w32_unicode_filenames)
5775 filename_to_utf16 (filename, filename_w);
5776 attrs = GetFileAttributesW (filename_w);
5778 else
5780 filename_to_ansi (filename, filename_a);
5781 attrs = GetFileAttributesA (filename_a);
5783 if (attrs == -1)
5785 DWORD w32err = GetLastError ();
5787 switch (w32err)
5789 case ERROR_BAD_NETPATH: /* network share, can't be a symlink */
5790 break;
5791 case ERROR_ACCESS_DENIED:
5792 errno = EACCES;
5793 break;
5794 case ERROR_FILE_NOT_FOUND:
5795 case ERROR_PATH_NOT_FOUND:
5796 default:
5797 errno = ENOENT;
5798 break;
5800 return 0;
5802 if ((attrs & FILE_ATTRIBUTE_REPARSE_POINT) == 0)
5803 return 0;
5804 logon_network_drive (filename);
5805 if (w32_unicode_filenames)
5807 fh = FindFirstFileW (filename_w, &wfdw);
5808 attrs_mean_symlink =
5809 (wfdw.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0
5810 && (wfdw.dwReserved0 & IO_REPARSE_TAG_SYMLINK) == IO_REPARSE_TAG_SYMLINK;
5811 if (attrs_mean_symlink)
5812 attrs_mean_symlink |= (wfdw.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
5814 else if (_mbspbrk (filename_a, "?"))
5816 /* filename_to_ansi failed to convert the file name. */
5817 errno = ENOENT;
5818 return 0;
5820 else
5822 fh = FindFirstFileA (filename_a, &wfda);
5823 attrs_mean_symlink =
5824 (wfda.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0
5825 && (wfda.dwReserved0 & IO_REPARSE_TAG_SYMLINK) == IO_REPARSE_TAG_SYMLINK;
5826 if (attrs_mean_symlink)
5827 attrs_mean_symlink |= (wfda.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
5829 if (fh == INVALID_HANDLE_VALUE)
5830 return 0;
5831 FindClose (fh);
5832 return attrs_mean_symlink;
5835 /* If NAME identifies a symbolic link, copy into BUF the file name of
5836 the symlink's target. Copy at most BUF_SIZE bytes, and do NOT
5837 null-terminate the target name, even if it fits. Return the number
5838 of bytes copied, or -1 if NAME is not a symlink or any error was
5839 encountered while resolving it. The file name copied into BUF is
5840 encoded in the current ANSI codepage. */
5841 ssize_t
5842 readlink (const char *name, char *buf, size_t buf_size)
5844 const char *path;
5845 TOKEN_PRIVILEGES privs;
5846 int restore_privs = 0;
5847 HANDLE sh;
5848 ssize_t retval;
5849 char resolved[MAX_UTF8_PATH];
5851 if (name == NULL)
5853 errno = EFAULT;
5854 return -1;
5856 if (!*name)
5858 errno = ENOENT;
5859 return -1;
5862 path = map_w32_filename (name, NULL);
5864 if (strlen (path) > MAX_UTF8_PATH)
5866 errno = ENAMETOOLONG;
5867 return -1;
5870 errno = 0;
5871 if (is_windows_9x () == TRUE
5872 || (volume_info.flags & FILE_SUPPORTS_REPARSE_POINTS) == 0
5873 || !is_symlink (path))
5875 if (!errno)
5876 errno = EINVAL; /* not a symlink */
5877 return -1;
5880 /* Done with simple tests, now we're in for some _real_ work. */
5881 if (enable_privilege (SE_BACKUP_NAME, TRUE, &privs))
5882 restore_privs = 1;
5883 /* Implementation note: From here and onward, don't return early,
5884 since that will fail to restore the original set of privileges of
5885 the calling thread. */
5887 retval = -1; /* not too optimistic, are we? */
5889 /* Note: In the next call to CreateFile, we use zero as the 2nd
5890 argument because, when the symlink is a hidden/system file,
5891 e.g. 'C:\Users\All Users', GENERIC_READ fails with
5892 ERROR_ACCESS_DENIED. Zero seems to work just fine, both for file
5893 and directory symlinks. */
5894 if (w32_unicode_filenames)
5896 wchar_t path_w[MAX_PATH];
5898 filename_to_utf16 (path, path_w);
5899 sh = CreateFileW (path_w, 0, 0, NULL, OPEN_EXISTING,
5900 FILE_FLAG_OPEN_REPARSE_POINT
5901 | FILE_FLAG_BACKUP_SEMANTICS,
5902 NULL);
5904 else
5906 char path_a[MAX_PATH];
5908 filename_to_ansi (path, path_a);
5909 sh = CreateFileA (path_a, 0, 0, NULL, OPEN_EXISTING,
5910 FILE_FLAG_OPEN_REPARSE_POINT
5911 | FILE_FLAG_BACKUP_SEMANTICS,
5912 NULL);
5914 if (sh != INVALID_HANDLE_VALUE)
5916 BYTE reparse_buf[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
5917 REPARSE_DATA_BUFFER *reparse_data = (REPARSE_DATA_BUFFER *)&reparse_buf[0];
5918 DWORD retbytes;
5920 if (!DeviceIoControl (sh, FSCTL_GET_REPARSE_POINT, NULL, 0,
5921 reparse_buf, MAXIMUM_REPARSE_DATA_BUFFER_SIZE,
5922 &retbytes, NULL))
5923 errno = EIO;
5924 else if (reparse_data->ReparseTag != IO_REPARSE_TAG_SYMLINK)
5925 errno = EINVAL;
5926 else
5928 /* Copy the link target name, in wide characters, from
5929 reparse_data, then convert it to multibyte encoding in
5930 the current locale's codepage. */
5931 WCHAR *lwname;
5932 size_t lname_size;
5933 USHORT lwname_len =
5934 reparse_data->SymbolicLinkReparseBuffer.PrintNameLength;
5935 WCHAR *lwname_src =
5936 reparse_data->SymbolicLinkReparseBuffer.PathBuffer
5937 + reparse_data->SymbolicLinkReparseBuffer.PrintNameOffset/sizeof(WCHAR);
5938 size_t size_to_copy = buf_size;
5940 /* According to MSDN, PrintNameLength does not include the
5941 terminating null character. */
5942 lwname = alloca ((lwname_len + 1) * sizeof(WCHAR));
5943 memcpy (lwname, lwname_src, lwname_len);
5944 lwname[lwname_len/sizeof(WCHAR)] = 0; /* null-terminate */
5945 filename_from_utf16 (lwname, resolved);
5946 dostounix_filename (resolved);
5947 lname_size = strlen (resolved) + 1;
5948 if (lname_size <= buf_size)
5949 size_to_copy = lname_size;
5950 strncpy (buf, resolved, size_to_copy);
5951 /* Success! */
5952 retval = size_to_copy;
5954 CloseHandle (sh);
5956 else
5958 /* CreateFile failed. */
5959 DWORD w32err2 = GetLastError ();
5961 switch (w32err2)
5963 case ERROR_FILE_NOT_FOUND:
5964 case ERROR_PATH_NOT_FOUND:
5965 errno = ENOENT;
5966 break;
5967 case ERROR_ACCESS_DENIED:
5968 case ERROR_TOO_MANY_OPEN_FILES:
5969 errno = EACCES;
5970 break;
5971 default:
5972 errno = EPERM;
5973 break;
5976 if (restore_privs)
5978 restore_privilege (&privs);
5979 revert_to_self ();
5982 return retval;
5985 ssize_t
5986 readlinkat (int fd, char const *name, char *buffer,
5987 size_t buffer_size)
5989 /* Rely on a hack: an open directory is modeled as file descriptor 0,
5990 as in fstatat. FIXME: Add proper support for readlinkat. */
5991 char fullname[MAX_UTF8_PATH];
5993 if (fd != AT_FDCWD)
5995 if (_snprintf (fullname, sizeof fullname, "%s/%s", dir_pathname, name)
5996 < 0)
5998 errno = ENAMETOOLONG;
5999 return -1;
6001 name = fullname;
6004 return readlink (name, buffer, buffer_size);
6007 /* If FILE is a symlink, return its target (stored in a static
6008 buffer); otherwise return FILE.
6010 This function repeatedly resolves symlinks in the last component of
6011 a chain of symlink file names, as in foo -> bar -> baz -> ...,
6012 until it arrives at a file whose last component is not a symlink,
6013 or some error occurs. It returns the target of the last
6014 successfully resolved symlink in the chain. If it succeeds to
6015 resolve even a single symlink, the value returned is an absolute
6016 file name with backslashes (result of GetFullPathName). By
6017 contrast, if the original FILE is returned, it is unaltered.
6019 Note: This function can set errno even if it succeeds.
6021 Implementation note: we only resolve the last portion ("basename")
6022 of the argument FILE and of each following file in the chain,
6023 disregarding any possible symlinks in its leading directories.
6024 This is because Windows system calls and library functions
6025 transparently resolve symlinks in leading directories and return
6026 correct information, as long as the basename is not a symlink. */
6027 static char *
6028 chase_symlinks (const char *file)
6030 static char target[MAX_UTF8_PATH];
6031 char link[MAX_UTF8_PATH];
6032 wchar_t target_w[MAX_PATH], link_w[MAX_PATH];
6033 char target_a[MAX_PATH], link_a[MAX_PATH];
6034 ssize_t res, link_len;
6035 int loop_count = 0;
6037 if (is_windows_9x () == TRUE || !is_symlink (file))
6038 return (char *)file;
6040 if (w32_unicode_filenames)
6042 wchar_t file_w[MAX_PATH];
6044 filename_to_utf16 (file, file_w);
6045 if (GetFullPathNameW (file_w, MAX_PATH, link_w, NULL) == 0)
6046 return (char *)file;
6047 filename_from_utf16 (link_w, link);
6049 else
6051 char file_a[MAX_PATH];
6053 filename_to_ansi (file, file_a);
6054 if (GetFullPathNameA (file_a, MAX_PATH, link_a, NULL) == 0)
6055 return (char *)file;
6056 filename_from_ansi (link_a, link);
6058 link_len = strlen (link);
6060 target[0] = '\0';
6061 do {
6063 /* Remove trailing slashes, as we want to resolve the last
6064 non-trivial part of the link name. */
6065 while (link_len > 3 && IS_DIRECTORY_SEP (link[link_len-1]))
6066 link[link_len--] = '\0';
6068 res = readlink (link, target, MAX_UTF8_PATH);
6069 if (res > 0)
6071 target[res] = '\0';
6072 if (!(IS_DEVICE_SEP (target[1])
6073 || (IS_DIRECTORY_SEP (target[0]) && IS_DIRECTORY_SEP (target[1]))))
6075 /* Target is relative. Append it to the directory part of
6076 the symlink, then copy the result back to target. */
6077 char *p = link + link_len;
6079 while (p > link && !IS_ANY_SEP (p[-1]))
6080 p--;
6081 strcpy (p, target);
6082 strcpy (target, link);
6084 /* Resolve any "." and ".." to get a fully-qualified file name
6085 in link[] again. */
6086 if (w32_unicode_filenames)
6088 filename_to_utf16 (target, target_w);
6089 link_len = GetFullPathNameW (target_w, MAX_PATH, link_w, NULL);
6090 if (link_len > 0)
6091 filename_from_utf16 (link_w, link);
6093 else
6095 filename_to_ansi (target, target_a);
6096 link_len = GetFullPathNameA (target_a, MAX_PATH, link_a, NULL);
6097 if (link_len > 0)
6098 filename_from_ansi (link_a, link);
6100 link_len = strlen (link);
6102 } while (res > 0 && link_len > 0 && ++loop_count <= 100);
6104 if (loop_count > 100)
6105 errno = ELOOP;
6107 if (target[0] == '\0') /* not a single call to readlink succeeded */
6108 return (char *)file;
6109 return target;
6113 /* Posix ACL emulation. */
6116 acl_valid (acl_t acl)
6118 return is_valid_security_descriptor ((PSECURITY_DESCRIPTOR)acl) ? 0 : -1;
6121 char *
6122 acl_to_text (acl_t acl, ssize_t *size)
6124 LPTSTR str_acl;
6125 SECURITY_INFORMATION flags =
6126 OWNER_SECURITY_INFORMATION |
6127 GROUP_SECURITY_INFORMATION |
6128 DACL_SECURITY_INFORMATION;
6129 char *retval = NULL;
6130 ULONG local_size;
6131 int e = errno;
6133 errno = 0;
6135 if (convert_sd_to_sddl ((PSECURITY_DESCRIPTOR)acl, SDDL_REVISION_1, flags, &str_acl, &local_size))
6137 errno = e;
6138 /* We don't want to mix heaps, so we duplicate the string in our
6139 heap and free the one allocated by the API. */
6140 retval = xstrdup (str_acl);
6141 if (size)
6142 *size = local_size;
6143 LocalFree (str_acl);
6145 else if (errno != ENOTSUP)
6146 errno = EINVAL;
6148 return retval;
6151 acl_t
6152 acl_from_text (const char *acl_str)
6154 PSECURITY_DESCRIPTOR psd, retval = NULL;
6155 ULONG sd_size;
6156 int e = errno;
6158 errno = 0;
6160 if (convert_sddl_to_sd (acl_str, SDDL_REVISION_1, &psd, &sd_size))
6162 errno = e;
6163 retval = xmalloc (sd_size);
6164 memcpy (retval, psd, sd_size);
6165 LocalFree (psd);
6167 else if (errno != ENOTSUP)
6168 errno = EINVAL;
6170 return retval;
6174 acl_free (void *ptr)
6176 xfree (ptr);
6177 return 0;
6180 acl_t
6181 acl_get_file (const char *fname, acl_type_t type)
6183 PSECURITY_DESCRIPTOR psd = NULL;
6184 const char *filename;
6186 if (type == ACL_TYPE_ACCESS)
6188 DWORD sd_len, err;
6189 SECURITY_INFORMATION si =
6190 OWNER_SECURITY_INFORMATION |
6191 GROUP_SECURITY_INFORMATION |
6192 DACL_SECURITY_INFORMATION ;
6193 int e = errno;
6195 filename = map_w32_filename (fname, NULL);
6196 if ((volume_info.flags & FILE_SUPPORTS_REPARSE_POINTS) != 0)
6197 fname = chase_symlinks (filename);
6198 else
6199 fname = filename;
6201 errno = 0;
6202 if (!get_file_security (fname, si, psd, 0, &sd_len)
6203 && errno != ENOTSUP)
6205 err = GetLastError ();
6206 if (err == ERROR_INSUFFICIENT_BUFFER)
6208 psd = xmalloc (sd_len);
6209 if (!get_file_security (fname, si, psd, sd_len, &sd_len))
6211 xfree (psd);
6212 errno = EIO;
6213 psd = NULL;
6216 else if (err == ERROR_FILE_NOT_FOUND
6217 || err == ERROR_PATH_NOT_FOUND
6218 /* ERROR_INVALID_NAME is what we get if
6219 w32-unicode-filenames is nil and the file cannot
6220 be encoded in the current ANSI codepage. */
6221 || err == ERROR_INVALID_NAME)
6222 errno = ENOENT;
6223 else
6224 errno = EIO;
6226 else if (!errno)
6227 errno = e;
6229 else if (type != ACL_TYPE_DEFAULT)
6230 errno = EINVAL;
6232 return psd;
6236 acl_set_file (const char *fname, acl_type_t type, acl_t acl)
6238 TOKEN_PRIVILEGES old1, old2;
6239 DWORD err;
6240 int st = 0, retval = -1;
6241 SECURITY_INFORMATION flags = 0;
6242 PSID psidOwner, psidGroup;
6243 PACL pacl;
6244 BOOL dflt;
6245 BOOL dacl_present;
6246 int e;
6247 const char *filename;
6249 if (acl_valid (acl) != 0
6250 || (type != ACL_TYPE_DEFAULT && type != ACL_TYPE_ACCESS))
6252 errno = EINVAL;
6253 return -1;
6256 if (type == ACL_TYPE_DEFAULT)
6258 errno = ENOSYS;
6259 return -1;
6262 filename = map_w32_filename (fname, NULL);
6263 if ((volume_info.flags & FILE_SUPPORTS_REPARSE_POINTS) != 0)
6264 fname = chase_symlinks (filename);
6265 else
6266 fname = filename;
6268 if (get_security_descriptor_owner ((PSECURITY_DESCRIPTOR)acl, &psidOwner,
6269 &dflt)
6270 && psidOwner)
6271 flags |= OWNER_SECURITY_INFORMATION;
6272 if (get_security_descriptor_group ((PSECURITY_DESCRIPTOR)acl, &psidGroup,
6273 &dflt)
6274 && psidGroup)
6275 flags |= GROUP_SECURITY_INFORMATION;
6276 if (get_security_descriptor_dacl ((PSECURITY_DESCRIPTOR)acl, &dacl_present,
6277 &pacl, &dflt)
6278 && dacl_present)
6279 flags |= DACL_SECURITY_INFORMATION;
6280 if (!flags)
6281 return 0;
6283 /* According to KB-245153, setting the owner will succeed if either:
6284 (1) the caller is the user who will be the new owner, and has the
6285 SE_TAKE_OWNERSHIP privilege, or
6286 (2) the caller has the SE_RESTORE privilege, in which case she can
6287 set any valid user or group as the owner
6289 We request below both SE_TAKE_OWNERSHIP and SE_RESTORE
6290 privileges, and disregard any failures in obtaining them. If
6291 these privileges cannot be obtained, and do not already exist in
6292 the calling thread's security token, this function could fail
6293 with EPERM. */
6294 if (enable_privilege (SE_TAKE_OWNERSHIP_NAME, TRUE, &old1))
6295 st++;
6296 if (enable_privilege (SE_RESTORE_NAME, TRUE, &old2))
6297 st++;
6299 e = errno;
6300 errno = 0;
6301 /* SetFileSecurity is deprecated by MS, and sometimes fails when
6302 DACL inheritance is involved, but it seems to preserve ownership
6303 better than SetNamedSecurityInfo, which is important e.g., in
6304 copy-file. */
6305 if (!set_file_security (fname, flags, (PSECURITY_DESCRIPTOR)acl))
6307 err = GetLastError ();
6309 if (errno != ENOTSUP)
6310 err = set_named_security_info (fname, SE_FILE_OBJECT, flags,
6311 psidOwner, psidGroup, pacl, NULL);
6313 else
6314 err = ERROR_SUCCESS;
6315 if (err != ERROR_SUCCESS)
6317 if (errno == ENOTSUP)
6319 else if (err == ERROR_INVALID_OWNER
6320 || err == ERROR_NOT_ALL_ASSIGNED
6321 || err == ERROR_ACCESS_DENIED)
6323 /* Maybe the requested ACL and the one the file already has
6324 are identical, in which case we can silently ignore the
6325 failure. (And no, Windows doesn't.) */
6326 acl_t current_acl = acl_get_file (fname, ACL_TYPE_ACCESS);
6328 errno = EPERM;
6329 if (current_acl)
6331 char *acl_from = acl_to_text (current_acl, NULL);
6332 char *acl_to = acl_to_text (acl, NULL);
6334 if (acl_from && acl_to && xstrcasecmp (acl_from, acl_to) == 0)
6336 retval = 0;
6337 errno = e;
6339 if (acl_from)
6340 acl_free (acl_from);
6341 if (acl_to)
6342 acl_free (acl_to);
6343 acl_free (current_acl);
6346 else if (err == ERROR_FILE_NOT_FOUND
6347 || err == ERROR_PATH_NOT_FOUND
6348 /* ERROR_INVALID_NAME is what we get if
6349 w32-unicode-filenames is nil and the file cannot be
6350 encoded in the current ANSI codepage. */
6351 || err == ERROR_INVALID_NAME)
6352 errno = ENOENT;
6353 else
6354 errno = EACCES;
6356 else
6358 retval = 0;
6359 errno = e;
6362 if (st)
6364 if (st >= 2)
6365 restore_privilege (&old2);
6366 restore_privilege (&old1);
6367 revert_to_self ();
6370 return retval;
6374 /* MS-Windows version of careadlinkat (cf. ../lib/careadlinkat.c). We
6375 have a fixed max size for file names, so we don't need the kind of
6376 alloc/malloc/realloc dance the gnulib version does. We also don't
6377 support FD-relative symlinks. */
6378 char *
6379 careadlinkat (int fd, char const *filename,
6380 char *buffer, size_t buffer_size,
6381 struct allocator const *alloc,
6382 ssize_t (*preadlinkat) (int, char const *, char *, size_t))
6384 char linkname[MAX_UTF8_PATH];
6385 ssize_t link_size;
6387 link_size = preadlinkat (fd, filename, linkname, sizeof(linkname));
6389 if (link_size > 0)
6391 char *retval = buffer;
6393 linkname[link_size++] = '\0';
6394 if (link_size > buffer_size)
6395 retval = (char *)(alloc ? alloc->allocate : xmalloc) (link_size);
6396 if (retval)
6397 memcpy (retval, linkname, link_size);
6399 return retval;
6401 return NULL;
6405 w32_copy_file (const char *from, const char *to,
6406 int keep_time, int preserve_ownership, int copy_acls)
6408 acl_t acl = NULL;
6409 BOOL copy_result;
6410 wchar_t from_w[MAX_PATH], to_w[MAX_PATH];
6411 char from_a[MAX_PATH], to_a[MAX_PATH];
6413 /* We ignore preserve_ownership for now. */
6414 preserve_ownership = preserve_ownership;
6416 if (copy_acls)
6418 acl = acl_get_file (from, ACL_TYPE_ACCESS);
6419 if (acl == NULL && acl_errno_valid (errno))
6420 return -2;
6422 if (w32_unicode_filenames)
6424 filename_to_utf16 (from, from_w);
6425 filename_to_utf16 (to, to_w);
6426 copy_result = CopyFileW (from_w, to_w, FALSE);
6428 else
6430 filename_to_ansi (from, from_a);
6431 filename_to_ansi (to, to_a);
6432 copy_result = CopyFileA (from_a, to_a, FALSE);
6434 if (!copy_result)
6436 /* CopyFile doesn't set errno when it fails. By far the most
6437 "popular" reason is that the target is read-only. */
6438 DWORD err = GetLastError ();
6440 switch (err)
6442 case ERROR_FILE_NOT_FOUND:
6443 errno = ENOENT;
6444 break;
6445 case ERROR_ACCESS_DENIED:
6446 errno = EACCES;
6447 break;
6448 case ERROR_ENCRYPTION_FAILED:
6449 errno = EIO;
6450 break;
6451 default:
6452 errno = EPERM;
6453 break;
6456 if (acl)
6457 acl_free (acl);
6458 return -1;
6460 /* CopyFile retains the timestamp by default. However, see
6461 "Community Additions" for CopyFile: it sounds like that is not
6462 entirely true. Testing on Windows XP confirms that modified time
6463 is copied, but creation and last-access times are not.
6464 FIXME? */
6465 else if (!keep_time)
6467 struct timespec now;
6468 DWORD attributes;
6470 if (w32_unicode_filenames)
6472 /* Ensure file is writable while its times are set. */
6473 attributes = GetFileAttributesW (to_w);
6474 SetFileAttributesW (to_w, attributes & ~FILE_ATTRIBUTE_READONLY);
6475 now = current_timespec ();
6476 if (set_file_times (-1, to, now, now))
6478 /* Restore original attributes. */
6479 SetFileAttributesW (to_w, attributes);
6480 if (acl)
6481 acl_free (acl);
6482 return -3;
6484 /* Restore original attributes. */
6485 SetFileAttributesW (to_w, attributes);
6487 else
6489 attributes = GetFileAttributesA (to_a);
6490 SetFileAttributesA (to_a, attributes & ~FILE_ATTRIBUTE_READONLY);
6491 now = current_timespec ();
6492 if (set_file_times (-1, to, now, now))
6494 SetFileAttributesA (to_a, attributes);
6495 if (acl)
6496 acl_free (acl);
6497 return -3;
6499 SetFileAttributesA (to_a, attributes);
6502 if (acl != NULL)
6504 bool fail =
6505 acl_set_file (to, ACL_TYPE_ACCESS, acl) != 0;
6506 acl_free (acl);
6507 if (fail && acl_errno_valid (errno))
6508 return -4;
6511 return 0;
6515 /* Support for browsing other processes and their attributes. See
6516 process.c for the Lisp bindings. */
6518 /* Helper wrapper functions. */
6520 static HANDLE WINAPI
6521 create_toolhelp32_snapshot (DWORD Flags, DWORD Ignored)
6523 static CreateToolhelp32Snapshot_Proc s_pfn_Create_Toolhelp32_Snapshot = NULL;
6525 if (g_b_init_create_toolhelp32_snapshot == 0)
6527 g_b_init_create_toolhelp32_snapshot = 1;
6528 s_pfn_Create_Toolhelp32_Snapshot = (CreateToolhelp32Snapshot_Proc)
6529 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6530 "CreateToolhelp32Snapshot");
6532 if (s_pfn_Create_Toolhelp32_Snapshot == NULL)
6534 return INVALID_HANDLE_VALUE;
6536 return (s_pfn_Create_Toolhelp32_Snapshot (Flags, Ignored));
6539 static BOOL WINAPI
6540 process32_first (HANDLE hSnapshot, LPPROCESSENTRY32 lppe)
6542 static Process32First_Proc s_pfn_Process32_First = NULL;
6544 if (g_b_init_process32_first == 0)
6546 g_b_init_process32_first = 1;
6547 s_pfn_Process32_First = (Process32First_Proc)
6548 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6549 "Process32First");
6551 if (s_pfn_Process32_First == NULL)
6553 return FALSE;
6555 return (s_pfn_Process32_First (hSnapshot, lppe));
6558 static BOOL WINAPI
6559 process32_next (HANDLE hSnapshot, LPPROCESSENTRY32 lppe)
6561 static Process32Next_Proc s_pfn_Process32_Next = NULL;
6563 if (g_b_init_process32_next == 0)
6565 g_b_init_process32_next = 1;
6566 s_pfn_Process32_Next = (Process32Next_Proc)
6567 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6568 "Process32Next");
6570 if (s_pfn_Process32_Next == NULL)
6572 return FALSE;
6574 return (s_pfn_Process32_Next (hSnapshot, lppe));
6577 static BOOL WINAPI
6578 open_thread_token (HANDLE ThreadHandle,
6579 DWORD DesiredAccess,
6580 BOOL OpenAsSelf,
6581 PHANDLE TokenHandle)
6583 static OpenThreadToken_Proc s_pfn_Open_Thread_Token = NULL;
6584 HMODULE hm_advapi32 = NULL;
6585 if (is_windows_9x () == TRUE)
6587 SetLastError (ERROR_NOT_SUPPORTED);
6588 return FALSE;
6590 if (g_b_init_open_thread_token == 0)
6592 g_b_init_open_thread_token = 1;
6593 hm_advapi32 = LoadLibrary ("Advapi32.dll");
6594 s_pfn_Open_Thread_Token =
6595 (OpenThreadToken_Proc) GetProcAddress (hm_advapi32, "OpenThreadToken");
6597 if (s_pfn_Open_Thread_Token == NULL)
6599 SetLastError (ERROR_NOT_SUPPORTED);
6600 return FALSE;
6602 return (
6603 s_pfn_Open_Thread_Token (
6604 ThreadHandle,
6605 DesiredAccess,
6606 OpenAsSelf,
6607 TokenHandle)
6611 static BOOL WINAPI
6612 impersonate_self (SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
6614 static ImpersonateSelf_Proc s_pfn_Impersonate_Self = NULL;
6615 HMODULE hm_advapi32 = NULL;
6616 if (is_windows_9x () == TRUE)
6618 return FALSE;
6620 if (g_b_init_impersonate_self == 0)
6622 g_b_init_impersonate_self = 1;
6623 hm_advapi32 = LoadLibrary ("Advapi32.dll");
6624 s_pfn_Impersonate_Self =
6625 (ImpersonateSelf_Proc) GetProcAddress (hm_advapi32, "ImpersonateSelf");
6627 if (s_pfn_Impersonate_Self == NULL)
6629 return FALSE;
6631 return s_pfn_Impersonate_Self (ImpersonationLevel);
6634 static BOOL WINAPI
6635 revert_to_self (void)
6637 static RevertToSelf_Proc s_pfn_Revert_To_Self = NULL;
6638 HMODULE hm_advapi32 = NULL;
6639 if (is_windows_9x () == TRUE)
6641 return FALSE;
6643 if (g_b_init_revert_to_self == 0)
6645 g_b_init_revert_to_self = 1;
6646 hm_advapi32 = LoadLibrary ("Advapi32.dll");
6647 s_pfn_Revert_To_Self =
6648 (RevertToSelf_Proc) GetProcAddress (hm_advapi32, "RevertToSelf");
6650 if (s_pfn_Revert_To_Self == NULL)
6652 return FALSE;
6654 return s_pfn_Revert_To_Self ();
6657 static BOOL WINAPI
6658 get_process_memory_info (HANDLE h_proc,
6659 PPROCESS_MEMORY_COUNTERS mem_counters,
6660 DWORD bufsize)
6662 static GetProcessMemoryInfo_Proc s_pfn_Get_Process_Memory_Info = NULL;
6663 HMODULE hm_psapi = NULL;
6664 if (is_windows_9x () == TRUE)
6666 return FALSE;
6668 if (g_b_init_get_process_memory_info == 0)
6670 g_b_init_get_process_memory_info = 1;
6671 hm_psapi = LoadLibrary ("Psapi.dll");
6672 if (hm_psapi)
6673 s_pfn_Get_Process_Memory_Info = (GetProcessMemoryInfo_Proc)
6674 GetProcAddress (hm_psapi, "GetProcessMemoryInfo");
6676 if (s_pfn_Get_Process_Memory_Info == NULL)
6678 return FALSE;
6680 return s_pfn_Get_Process_Memory_Info (h_proc, mem_counters, bufsize);
6683 static BOOL WINAPI
6684 get_process_working_set_size (HANDLE h_proc,
6685 PSIZE_T minrss,
6686 PSIZE_T maxrss)
6688 static GetProcessWorkingSetSize_Proc
6689 s_pfn_Get_Process_Working_Set_Size = NULL;
6691 if (is_windows_9x () == TRUE)
6693 return FALSE;
6695 if (g_b_init_get_process_working_set_size == 0)
6697 g_b_init_get_process_working_set_size = 1;
6698 s_pfn_Get_Process_Working_Set_Size = (GetProcessWorkingSetSize_Proc)
6699 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6700 "GetProcessWorkingSetSize");
6702 if (s_pfn_Get_Process_Working_Set_Size == NULL)
6704 return FALSE;
6706 return s_pfn_Get_Process_Working_Set_Size (h_proc, minrss, maxrss);
6709 static BOOL WINAPI
6710 global_memory_status (MEMORYSTATUS *buf)
6712 static GlobalMemoryStatus_Proc s_pfn_Global_Memory_Status = NULL;
6714 if (is_windows_9x () == TRUE)
6716 return FALSE;
6718 if (g_b_init_global_memory_status == 0)
6720 g_b_init_global_memory_status = 1;
6721 s_pfn_Global_Memory_Status = (GlobalMemoryStatus_Proc)
6722 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6723 "GlobalMemoryStatus");
6725 if (s_pfn_Global_Memory_Status == NULL)
6727 return FALSE;
6729 return s_pfn_Global_Memory_Status (buf);
6732 static BOOL WINAPI
6733 global_memory_status_ex (MEMORY_STATUS_EX *buf)
6735 static GlobalMemoryStatusEx_Proc s_pfn_Global_Memory_Status_Ex = NULL;
6737 if (is_windows_9x () == TRUE)
6739 return FALSE;
6741 if (g_b_init_global_memory_status_ex == 0)
6743 g_b_init_global_memory_status_ex = 1;
6744 s_pfn_Global_Memory_Status_Ex = (GlobalMemoryStatusEx_Proc)
6745 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6746 "GlobalMemoryStatusEx");
6748 if (s_pfn_Global_Memory_Status_Ex == NULL)
6750 return FALSE;
6752 return s_pfn_Global_Memory_Status_Ex (buf);
6755 Lisp_Object
6756 list_system_processes (void)
6758 Lisp_Object proclist = Qnil;
6759 HANDLE h_snapshot;
6761 h_snapshot = create_toolhelp32_snapshot (TH32CS_SNAPPROCESS, 0);
6763 if (h_snapshot != INVALID_HANDLE_VALUE)
6765 PROCESSENTRY32 proc_entry;
6766 DWORD proc_id;
6767 BOOL res;
6769 proc_entry.dwSize = sizeof (PROCESSENTRY32);
6770 for (res = process32_first (h_snapshot, &proc_entry); res;
6771 res = process32_next (h_snapshot, &proc_entry))
6773 proc_id = proc_entry.th32ProcessID;
6774 proclist = Fcons (make_fixnum_or_float (proc_id), proclist);
6777 CloseHandle (h_snapshot);
6778 proclist = Fnreverse (proclist);
6781 return proclist;
6784 static int
6785 enable_privilege (LPCTSTR priv_name, BOOL enable_p, TOKEN_PRIVILEGES *old_priv)
6787 TOKEN_PRIVILEGES priv;
6788 DWORD priv_size = sizeof (priv);
6789 DWORD opriv_size = sizeof (*old_priv);
6790 HANDLE h_token = NULL;
6791 HANDLE h_thread = GetCurrentThread ();
6792 int ret_val = 0;
6793 BOOL res;
6795 res = open_thread_token (h_thread,
6796 TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
6797 FALSE, &h_token);
6798 if (!res && GetLastError () == ERROR_NO_TOKEN)
6800 if (impersonate_self (SecurityImpersonation))
6801 res = open_thread_token (h_thread,
6802 TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
6803 FALSE, &h_token);
6805 if (res)
6807 priv.PrivilegeCount = 1;
6808 priv.Privileges[0].Attributes = enable_p ? SE_PRIVILEGE_ENABLED : 0;
6809 LookupPrivilegeValue (NULL, priv_name, &priv.Privileges[0].Luid);
6810 if (AdjustTokenPrivileges (h_token, FALSE, &priv, priv_size,
6811 old_priv, &opriv_size)
6812 && GetLastError () != ERROR_NOT_ALL_ASSIGNED)
6813 ret_val = 1;
6815 if (h_token)
6816 CloseHandle (h_token);
6818 return ret_val;
6821 static int
6822 restore_privilege (TOKEN_PRIVILEGES *priv)
6824 DWORD priv_size = sizeof (*priv);
6825 HANDLE h_token = NULL;
6826 int ret_val = 0;
6828 if (open_thread_token (GetCurrentThread (),
6829 TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
6830 FALSE, &h_token))
6832 if (AdjustTokenPrivileges (h_token, FALSE, priv, priv_size, NULL, NULL)
6833 && GetLastError () != ERROR_NOT_ALL_ASSIGNED)
6834 ret_val = 1;
6836 if (h_token)
6837 CloseHandle (h_token);
6839 return ret_val;
6842 static Lisp_Object
6843 ltime (ULONGLONG time_100ns)
6845 ULONGLONG time_sec = time_100ns / 10000000;
6846 int subsec = time_100ns % 10000000;
6847 return list4i (time_sec >> 16, time_sec & 0xffff,
6848 subsec / 10, subsec % 10 * 100000);
6851 #define U64_TO_LISP_TIME(time) ltime (time)
6853 static int
6854 process_times (HANDLE h_proc, Lisp_Object *ctime, Lisp_Object *etime,
6855 Lisp_Object *stime, Lisp_Object *utime, Lisp_Object *ttime,
6856 double *pcpu)
6858 FILETIME ft_creation, ft_exit, ft_kernel, ft_user, ft_current;
6859 ULONGLONG tem1, tem2, tem3, tem;
6861 if (!h_proc
6862 || !get_process_times_fn
6863 || !(*get_process_times_fn) (h_proc, &ft_creation, &ft_exit,
6864 &ft_kernel, &ft_user))
6865 return 0;
6867 GetSystemTimeAsFileTime (&ft_current);
6869 FILETIME_TO_U64 (tem1, ft_kernel);
6870 *stime = U64_TO_LISP_TIME (tem1);
6872 FILETIME_TO_U64 (tem2, ft_user);
6873 *utime = U64_TO_LISP_TIME (tem2);
6875 tem3 = tem1 + tem2;
6876 *ttime = U64_TO_LISP_TIME (tem3);
6878 FILETIME_TO_U64 (tem, ft_creation);
6879 /* Process no 4 (System) returns zero creation time. */
6880 if (tem)
6881 tem -= utc_base;
6882 *ctime = U64_TO_LISP_TIME (tem);
6884 if (tem)
6886 FILETIME_TO_U64 (tem3, ft_current);
6887 tem = (tem3 - utc_base) - tem;
6889 *etime = U64_TO_LISP_TIME (tem);
6891 if (tem)
6893 *pcpu = 100.0 * (tem1 + tem2) / tem;
6894 if (*pcpu > 100)
6895 *pcpu = 100.0;
6897 else
6898 *pcpu = 0;
6900 return 1;
6903 Lisp_Object
6904 system_process_attributes (Lisp_Object pid)
6906 Lisp_Object attrs = Qnil;
6907 Lisp_Object cmd_str, decoded_cmd, tem;
6908 HANDLE h_snapshot, h_proc;
6909 DWORD proc_id;
6910 int found_proc = 0;
6911 char uname[UNLEN+1], gname[GNLEN+1], domain[1025];
6912 DWORD ulength = sizeof (uname), dlength = sizeof (domain), needed;
6913 DWORD glength = sizeof (gname);
6914 HANDLE token = NULL;
6915 SID_NAME_USE user_type;
6916 unsigned char *buf = NULL;
6917 DWORD blen = 0;
6918 TOKEN_USER user_token;
6919 TOKEN_PRIMARY_GROUP group_token;
6920 unsigned euid;
6921 unsigned egid;
6922 PROCESS_MEMORY_COUNTERS mem;
6923 PROCESS_MEMORY_COUNTERS_EX mem_ex;
6924 SIZE_T minrss, maxrss;
6925 MEMORYSTATUS memst;
6926 MEMORY_STATUS_EX memstex;
6927 double totphys = 0.0;
6928 Lisp_Object ctime, stime, utime, etime, ttime;
6929 double pcpu;
6930 BOOL result = FALSE;
6932 CHECK_NUMBER_OR_FLOAT (pid);
6933 proc_id = FLOATP (pid) ? XFLOAT_DATA (pid) : XINT (pid);
6935 h_snapshot = create_toolhelp32_snapshot (TH32CS_SNAPPROCESS, 0);
6937 if (h_snapshot != INVALID_HANDLE_VALUE)
6939 PROCESSENTRY32 pe;
6940 BOOL res;
6942 pe.dwSize = sizeof (PROCESSENTRY32);
6943 for (res = process32_first (h_snapshot, &pe); res;
6944 res = process32_next (h_snapshot, &pe))
6946 if (proc_id == pe.th32ProcessID)
6948 if (proc_id == 0)
6949 decoded_cmd = build_string ("Idle");
6950 else
6952 /* Decode the command name from locale-specific
6953 encoding. */
6954 cmd_str = build_unibyte_string (pe.szExeFile);
6956 decoded_cmd =
6957 code_convert_string_norecord (cmd_str,
6958 Vlocale_coding_system, 0);
6960 attrs = Fcons (Fcons (Qcomm, decoded_cmd), attrs);
6961 attrs = Fcons (Fcons (Qppid,
6962 make_fixnum_or_float (pe.th32ParentProcessID)),
6963 attrs);
6964 attrs = Fcons (Fcons (Qpri, make_number (pe.pcPriClassBase)),
6965 attrs);
6966 attrs = Fcons (Fcons (Qthcount,
6967 make_fixnum_or_float (pe.cntThreads)),
6968 attrs);
6969 found_proc = 1;
6970 break;
6974 CloseHandle (h_snapshot);
6977 if (!found_proc)
6978 return Qnil;
6980 h_proc = OpenProcess (PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
6981 FALSE, proc_id);
6982 /* If we were denied a handle to the process, try again after
6983 enabling the SeDebugPrivilege in our process. */
6984 if (!h_proc)
6986 TOKEN_PRIVILEGES priv_current;
6988 if (enable_privilege (SE_DEBUG_NAME, TRUE, &priv_current))
6990 h_proc = OpenProcess (PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
6991 FALSE, proc_id);
6992 restore_privilege (&priv_current);
6993 revert_to_self ();
6996 if (h_proc)
6998 result = open_process_token (h_proc, TOKEN_QUERY, &token);
6999 if (result)
7001 result = get_token_information (token, TokenUser, NULL, 0, &blen);
7002 if (!result && GetLastError () == ERROR_INSUFFICIENT_BUFFER)
7004 buf = xmalloc (blen);
7005 result = get_token_information (token, TokenUser,
7006 (LPVOID)buf, blen, &needed);
7007 if (result)
7009 memcpy (&user_token, buf, sizeof (user_token));
7010 if (!w32_cached_id (user_token.User.Sid, &euid, uname))
7012 euid = get_rid (user_token.User.Sid);
7013 result = lookup_account_sid (NULL, user_token.User.Sid,
7014 uname, &ulength,
7015 domain, &dlength,
7016 &user_type);
7017 if (result)
7018 w32_add_to_cache (user_token.User.Sid, euid, uname);
7019 else
7021 strcpy (uname, "unknown");
7022 result = TRUE;
7025 ulength = strlen (uname);
7029 if (result)
7031 /* Determine a reasonable euid and gid values. */
7032 if (xstrcasecmp ("administrator", uname) == 0)
7034 euid = 500; /* well-known Administrator uid */
7035 egid = 513; /* well-known None gid */
7037 else
7039 /* Get group id and name. */
7040 result = get_token_information (token, TokenPrimaryGroup,
7041 (LPVOID)buf, blen, &needed);
7042 if (!result && GetLastError () == ERROR_INSUFFICIENT_BUFFER)
7044 buf = xrealloc (buf, blen = needed);
7045 result = get_token_information (token, TokenPrimaryGroup,
7046 (LPVOID)buf, blen, &needed);
7048 if (result)
7050 memcpy (&group_token, buf, sizeof (group_token));
7051 if (!w32_cached_id (group_token.PrimaryGroup, &egid, gname))
7053 egid = get_rid (group_token.PrimaryGroup);
7054 dlength = sizeof (domain);
7055 result =
7056 lookup_account_sid (NULL, group_token.PrimaryGroup,
7057 gname, &glength, NULL, &dlength,
7058 &user_type);
7059 if (result)
7060 w32_add_to_cache (group_token.PrimaryGroup,
7061 egid, gname);
7062 else
7064 strcpy (gname, "None");
7065 result = TRUE;
7068 glength = strlen (gname);
7072 xfree (buf);
7074 if (!result)
7076 if (!is_windows_9x ())
7078 /* We couldn't open the process token, presumably because of
7079 insufficient access rights. Assume this process is run
7080 by the system. */
7081 strcpy (uname, "SYSTEM");
7082 strcpy (gname, "None");
7083 euid = 18; /* SYSTEM */
7084 egid = 513; /* None */
7085 glength = strlen (gname);
7086 ulength = strlen (uname);
7088 /* If we are running under Windows 9X, where security calls are
7089 not supported, we assume all processes are run by the current
7090 user. */
7091 else if (GetUserName (uname, &ulength))
7093 if (xstrcasecmp ("administrator", uname) == 0)
7094 euid = 0;
7095 else
7096 euid = 123;
7097 egid = euid;
7098 strcpy (gname, "None");
7099 glength = strlen (gname);
7100 ulength = strlen (uname);
7102 else
7104 euid = 123;
7105 egid = 123;
7106 strcpy (uname, "administrator");
7107 ulength = strlen (uname);
7108 strcpy (gname, "None");
7109 glength = strlen (gname);
7111 if (token)
7112 CloseHandle (token);
7115 attrs = Fcons (Fcons (Qeuid, make_fixnum_or_float (euid)), attrs);
7116 tem = make_unibyte_string (uname, ulength);
7117 attrs = Fcons (Fcons (Quser,
7118 code_convert_string_norecord (tem, Vlocale_coding_system, 0)),
7119 attrs);
7120 attrs = Fcons (Fcons (Qegid, make_fixnum_or_float (egid)), attrs);
7121 tem = make_unibyte_string (gname, glength);
7122 attrs = Fcons (Fcons (Qgroup,
7123 code_convert_string_norecord (tem, Vlocale_coding_system, 0)),
7124 attrs);
7126 if (global_memory_status_ex (&memstex))
7127 #if __GNUC__ || (defined (_MSC_VER) && _MSC_VER >= 1300)
7128 totphys = memstex.ullTotalPhys / 1024.0;
7129 #else
7130 /* Visual Studio 6 cannot convert an unsigned __int64 type to
7131 double, so we need to do this for it... */
7133 DWORD tot_hi = memstex.ullTotalPhys >> 32;
7134 DWORD tot_md = (memstex.ullTotalPhys & 0x00000000ffffffff) >> 10;
7135 DWORD tot_lo = memstex.ullTotalPhys % 1024;
7137 totphys = tot_hi * 4194304.0 + tot_md + tot_lo / 1024.0;
7139 #endif /* __GNUC__ || _MSC_VER >= 1300 */
7140 else if (global_memory_status (&memst))
7141 totphys = memst.dwTotalPhys / 1024.0;
7143 if (h_proc
7144 && get_process_memory_info (h_proc, (PROCESS_MEMORY_COUNTERS *)&mem_ex,
7145 sizeof (mem_ex)))
7147 SIZE_T rss = mem_ex.WorkingSetSize / 1024;
7149 attrs = Fcons (Fcons (Qmajflt,
7150 make_fixnum_or_float (mem_ex.PageFaultCount)),
7151 attrs);
7152 attrs = Fcons (Fcons (Qvsize,
7153 make_fixnum_or_float (mem_ex.PrivateUsage / 1024)),
7154 attrs);
7155 attrs = Fcons (Fcons (Qrss, make_fixnum_or_float (rss)), attrs);
7156 if (totphys)
7157 attrs = Fcons (Fcons (Qpmem, make_float (100. * rss / totphys)), attrs);
7159 else if (h_proc
7160 && get_process_memory_info (h_proc, &mem, sizeof (mem)))
7162 SIZE_T rss = mem_ex.WorkingSetSize / 1024;
7164 attrs = Fcons (Fcons (Qmajflt,
7165 make_fixnum_or_float (mem.PageFaultCount)),
7166 attrs);
7167 attrs = Fcons (Fcons (Qrss, make_fixnum_or_float (rss)), attrs);
7168 if (totphys)
7169 attrs = Fcons (Fcons (Qpmem, make_float (100. * rss / totphys)), attrs);
7171 else if (h_proc
7172 && get_process_working_set_size (h_proc, &minrss, &maxrss))
7174 DWORD rss = maxrss / 1024;
7176 attrs = Fcons (Fcons (Qrss, make_fixnum_or_float (maxrss / 1024)), attrs);
7177 if (totphys)
7178 attrs = Fcons (Fcons (Qpmem, make_float (100. * rss / totphys)), attrs);
7181 if (process_times (h_proc, &ctime, &etime, &stime, &utime, &ttime, &pcpu))
7183 attrs = Fcons (Fcons (Qutime, utime), attrs);
7184 attrs = Fcons (Fcons (Qstime, stime), attrs);
7185 attrs = Fcons (Fcons (Qtime, ttime), attrs);
7186 attrs = Fcons (Fcons (Qstart, ctime), attrs);
7187 attrs = Fcons (Fcons (Qetime, etime), attrs);
7188 attrs = Fcons (Fcons (Qpcpu, make_float (pcpu)), attrs);
7191 /* FIXME: Retrieve command line by walking the PEB of the process. */
7193 if (h_proc)
7194 CloseHandle (h_proc);
7195 return attrs;
7199 w32_memory_info (unsigned long long *totalram, unsigned long long *freeram,
7200 unsigned long long *totalswap, unsigned long long *freeswap)
7202 MEMORYSTATUS memst;
7203 MEMORY_STATUS_EX memstex;
7205 /* Use GlobalMemoryStatusEx if available, as it can report more than
7206 2GB of memory. */
7207 if (global_memory_status_ex (&memstex))
7209 *totalram = memstex.ullTotalPhys;
7210 *freeram = memstex.ullAvailPhys;
7211 *totalswap = memstex.ullTotalPageFile;
7212 *freeswap = memstex.ullAvailPageFile;
7213 return 0;
7215 else if (global_memory_status (&memst))
7217 *totalram = memst.dwTotalPhys;
7218 *freeram = memst.dwAvailPhys;
7219 *totalswap = memst.dwTotalPageFile;
7220 *freeswap = memst.dwAvailPageFile;
7221 return 0;
7223 else
7224 return -1;
7228 /* Wrappers for winsock functions to map between our file descriptors
7229 and winsock's handles; also set h_errno for convenience.
7231 To allow Emacs to run on systems which don't have winsock support
7232 installed, we dynamically link to winsock on startup if present, and
7233 otherwise provide the minimum necessary functionality
7234 (eg. gethostname). */
7236 /* function pointers for relevant socket functions */
7237 int (PASCAL *pfn_WSAStartup) (WORD wVersionRequired, LPWSADATA lpWSAData);
7238 void (PASCAL *pfn_WSASetLastError) (int iError);
7239 int (PASCAL *pfn_WSAGetLastError) (void);
7240 int (PASCAL *pfn_WSAEventSelect) (SOCKET s, HANDLE hEventObject, long lNetworkEvents);
7241 int (PASCAL *pfn_WSAEnumNetworkEvents) (SOCKET s, HANDLE hEventObject,
7242 WSANETWORKEVENTS *NetworkEvents);
7244 HANDLE (PASCAL *pfn_WSACreateEvent) (void);
7245 int (PASCAL *pfn_WSACloseEvent) (HANDLE hEvent);
7246 int (PASCAL *pfn_socket) (int af, int type, int protocol);
7247 int (PASCAL *pfn_bind) (SOCKET s, const struct sockaddr *addr, int namelen);
7248 int (PASCAL *pfn_connect) (SOCKET s, const struct sockaddr *addr, int namelen);
7249 int (PASCAL *pfn_ioctlsocket) (SOCKET s, long cmd, u_long *argp);
7250 int (PASCAL *pfn_recv) (SOCKET s, char * buf, int len, int flags);
7251 int (PASCAL *pfn_send) (SOCKET s, const char * buf, int len, int flags);
7252 int (PASCAL *pfn_closesocket) (SOCKET s);
7253 int (PASCAL *pfn_shutdown) (SOCKET s, int how);
7254 int (PASCAL *pfn_WSACleanup) (void);
7256 u_short (PASCAL *pfn_htons) (u_short hostshort);
7257 u_short (PASCAL *pfn_ntohs) (u_short netshort);
7258 unsigned long (PASCAL *pfn_inet_addr) (const char * cp);
7259 int (PASCAL *pfn_gethostname) (char * name, int namelen);
7260 struct hostent * (PASCAL *pfn_gethostbyname) (const char * name);
7261 struct servent * (PASCAL *pfn_getservbyname) (const char * name, const char * proto);
7262 int (PASCAL *pfn_getpeername) (SOCKET s, struct sockaddr *addr, int * namelen);
7263 int (PASCAL *pfn_setsockopt) (SOCKET s, int level, int optname,
7264 const char * optval, int optlen);
7265 int (PASCAL *pfn_listen) (SOCKET s, int backlog);
7266 int (PASCAL *pfn_getsockname) (SOCKET s, struct sockaddr * name,
7267 int * namelen);
7268 SOCKET (PASCAL *pfn_accept) (SOCKET s, struct sockaddr * addr, int * addrlen);
7269 int (PASCAL *pfn_recvfrom) (SOCKET s, char * buf, int len, int flags,
7270 struct sockaddr * from, int * fromlen);
7271 int (PASCAL *pfn_sendto) (SOCKET s, const char * buf, int len, int flags,
7272 const struct sockaddr * to, int tolen);
7274 int (PASCAL *pfn_getaddrinfo) (const char *, const char *,
7275 const struct addrinfo *, struct addrinfo **);
7276 void (PASCAL *pfn_freeaddrinfo) (struct addrinfo *);
7278 /* SetHandleInformation is only needed to make sockets non-inheritable. */
7279 BOOL (WINAPI *pfn_SetHandleInformation) (HANDLE object, DWORD mask, DWORD flags);
7280 #ifndef HANDLE_FLAG_INHERIT
7281 #define HANDLE_FLAG_INHERIT 1
7282 #endif
7284 HANDLE winsock_lib;
7285 static int winsock_inuse;
7287 BOOL term_winsock (void);
7289 BOOL
7290 term_winsock (void)
7292 if (winsock_lib != NULL && winsock_inuse == 0)
7294 release_listen_threads ();
7295 /* Not sure what would cause WSAENETDOWN, or even if it can happen
7296 after WSAStartup returns successfully, but it seems reasonable
7297 to allow unloading winsock anyway in that case. */
7298 if (pfn_WSACleanup () == 0 ||
7299 pfn_WSAGetLastError () == WSAENETDOWN)
7301 if (FreeLibrary (winsock_lib))
7302 winsock_lib = NULL;
7303 return TRUE;
7306 return FALSE;
7309 BOOL
7310 init_winsock (int load_now)
7312 WSADATA winsockData;
7314 if (winsock_lib != NULL)
7315 return TRUE;
7317 pfn_SetHandleInformation
7318 = (void *) GetProcAddress (GetModuleHandle ("kernel32.dll"),
7319 "SetHandleInformation");
7321 winsock_lib = LoadLibrary ("Ws2_32.dll");
7323 if (winsock_lib != NULL)
7325 /* dynamically link to socket functions */
7327 #define LOAD_PROC(fn) \
7328 if ((pfn_##fn = (void *) GetProcAddress (winsock_lib, #fn)) == NULL) \
7329 goto fail;
7331 LOAD_PROC (WSAStartup);
7332 LOAD_PROC (WSASetLastError);
7333 LOAD_PROC (WSAGetLastError);
7334 LOAD_PROC (WSAEventSelect);
7335 LOAD_PROC (WSAEnumNetworkEvents);
7336 LOAD_PROC (WSACreateEvent);
7337 LOAD_PROC (WSACloseEvent);
7338 LOAD_PROC (socket);
7339 LOAD_PROC (bind);
7340 LOAD_PROC (connect);
7341 LOAD_PROC (ioctlsocket);
7342 LOAD_PROC (recv);
7343 LOAD_PROC (send);
7344 LOAD_PROC (closesocket);
7345 LOAD_PROC (shutdown);
7346 LOAD_PROC (htons);
7347 LOAD_PROC (ntohs);
7348 LOAD_PROC (inet_addr);
7349 LOAD_PROC (gethostname);
7350 LOAD_PROC (gethostbyname);
7351 LOAD_PROC (getservbyname);
7352 LOAD_PROC (getpeername);
7353 LOAD_PROC (WSACleanup);
7354 LOAD_PROC (setsockopt);
7355 LOAD_PROC (listen);
7356 LOAD_PROC (getsockname);
7357 LOAD_PROC (accept);
7358 LOAD_PROC (recvfrom);
7359 LOAD_PROC (sendto);
7360 #undef LOAD_PROC
7362 /* Try loading functions not available before XP. */
7363 pfn_getaddrinfo = (void *) GetProcAddress (winsock_lib, "getaddrinfo");
7364 pfn_freeaddrinfo = (void *) GetProcAddress (winsock_lib, "freeaddrinfo");
7365 /* Paranoia: these two functions should go together, so if one
7366 is absent, we cannot use the other. */
7367 if (pfn_getaddrinfo == NULL)
7368 pfn_freeaddrinfo = NULL;
7369 else if (pfn_freeaddrinfo == NULL)
7370 pfn_getaddrinfo = NULL;
7372 /* specify version 1.1 of winsock */
7373 if (pfn_WSAStartup (0x101, &winsockData) == 0)
7375 if (winsockData.wVersion != 0x101)
7376 goto fail;
7378 if (!load_now)
7380 /* Report that winsock exists and is usable, but leave
7381 socket functions disabled. I am assuming that calling
7382 WSAStartup does not require any network interaction,
7383 and in particular does not cause or require a dial-up
7384 connection to be established. */
7386 pfn_WSACleanup ();
7387 FreeLibrary (winsock_lib);
7388 winsock_lib = NULL;
7390 winsock_inuse = 0;
7391 return TRUE;
7394 fail:
7395 FreeLibrary (winsock_lib);
7396 winsock_lib = NULL;
7399 return FALSE;
7403 int h_errno = 0;
7405 /* Function to map winsock error codes to errno codes for those errno
7406 code defined in errno.h (errno values not defined by errno.h are
7407 already in nt/inc/sys/socket.h). */
7408 static void
7409 set_errno (void)
7411 int wsa_err;
7413 h_errno = 0;
7414 if (winsock_lib == NULL)
7415 wsa_err = EINVAL;
7416 else
7417 wsa_err = pfn_WSAGetLastError ();
7419 switch (wsa_err)
7421 case WSAEACCES: errno = EACCES; break;
7422 case WSAEBADF: errno = EBADF; break;
7423 case WSAEFAULT: errno = EFAULT; break;
7424 case WSAEINTR: errno = EINTR; break;
7425 case WSAEINVAL: errno = EINVAL; break;
7426 case WSAEMFILE: errno = EMFILE; break;
7427 case WSAENAMETOOLONG: errno = ENAMETOOLONG; break;
7428 case WSAENOTEMPTY: errno = ENOTEMPTY; break;
7429 case WSAEWOULDBLOCK: errno = EWOULDBLOCK; break;
7430 case WSAENOTCONN: errno = ENOTCONN; break;
7431 default: errno = wsa_err; break;
7435 static void
7436 check_errno (void)
7438 h_errno = 0;
7439 if (winsock_lib != NULL)
7440 pfn_WSASetLastError (0);
7443 /* Extend strerror to handle the winsock-specific error codes. */
7444 struct {
7445 int errnum;
7446 const char * msg;
7447 } _wsa_errlist[] = {
7448 {WSAEINTR , "Interrupted function call"},
7449 {WSAEBADF , "Bad file descriptor"},
7450 {WSAEACCES , "Permission denied"},
7451 {WSAEFAULT , "Bad address"},
7452 {WSAEINVAL , "Invalid argument"},
7453 {WSAEMFILE , "Too many open files"},
7455 {WSAEWOULDBLOCK , "Resource temporarily unavailable"},
7456 {WSAEINPROGRESS , "Operation now in progress"},
7457 {WSAEALREADY , "Operation already in progress"},
7458 {WSAENOTSOCK , "Socket operation on non-socket"},
7459 {WSAEDESTADDRREQ , "Destination address required"},
7460 {WSAEMSGSIZE , "Message too long"},
7461 {WSAEPROTOTYPE , "Protocol wrong type for socket"},
7462 {WSAENOPROTOOPT , "Bad protocol option"},
7463 {WSAEPROTONOSUPPORT , "Protocol not supported"},
7464 {WSAESOCKTNOSUPPORT , "Socket type not supported"},
7465 {WSAEOPNOTSUPP , "Operation not supported"},
7466 {WSAEPFNOSUPPORT , "Protocol family not supported"},
7467 {WSAEAFNOSUPPORT , "Address family not supported by protocol family"},
7468 {WSAEADDRINUSE , "Address already in use"},
7469 {WSAEADDRNOTAVAIL , "Cannot assign requested address"},
7470 {WSAENETDOWN , "Network is down"},
7471 {WSAENETUNREACH , "Network is unreachable"},
7472 {WSAENETRESET , "Network dropped connection on reset"},
7473 {WSAECONNABORTED , "Software caused connection abort"},
7474 {WSAECONNRESET , "Connection reset by peer"},
7475 {WSAENOBUFS , "No buffer space available"},
7476 {WSAEISCONN , "Socket is already connected"},
7477 {WSAENOTCONN , "Socket is not connected"},
7478 {WSAESHUTDOWN , "Cannot send after socket shutdown"},
7479 {WSAETOOMANYREFS , "Too many references"}, /* not sure */
7480 {WSAETIMEDOUT , "Connection timed out"},
7481 {WSAECONNREFUSED , "Connection refused"},
7482 {WSAELOOP , "Network loop"}, /* not sure */
7483 {WSAENAMETOOLONG , "Name is too long"},
7484 {WSAEHOSTDOWN , "Host is down"},
7485 {WSAEHOSTUNREACH , "No route to host"},
7486 {WSAENOTEMPTY , "Buffer not empty"}, /* not sure */
7487 {WSAEPROCLIM , "Too many processes"},
7488 {WSAEUSERS , "Too many users"}, /* not sure */
7489 {WSAEDQUOT , "Double quote in host name"}, /* really not sure */
7490 {WSAESTALE , "Data is stale"}, /* not sure */
7491 {WSAEREMOTE , "Remote error"}, /* not sure */
7493 {WSASYSNOTREADY , "Network subsystem is unavailable"},
7494 {WSAVERNOTSUPPORTED , "WINSOCK.DLL version out of range"},
7495 {WSANOTINITIALISED , "Winsock not initialized successfully"},
7496 {WSAEDISCON , "Graceful shutdown in progress"},
7497 #ifdef WSAENOMORE
7498 {WSAENOMORE , "No more operations allowed"}, /* not sure */
7499 {WSAECANCELLED , "Operation cancelled"}, /* not sure */
7500 {WSAEINVALIDPROCTABLE , "Invalid procedure table from service provider"},
7501 {WSAEINVALIDPROVIDER , "Invalid service provider version number"},
7502 {WSAEPROVIDERFAILEDINIT , "Unable to initialize a service provider"},
7503 {WSASYSCALLFAILURE , "System call failure"},
7504 {WSASERVICE_NOT_FOUND , "Service not found"}, /* not sure */
7505 {WSATYPE_NOT_FOUND , "Class type not found"},
7506 {WSA_E_NO_MORE , "No more resources available"}, /* really not sure */
7507 {WSA_E_CANCELLED , "Operation already cancelled"}, /* really not sure */
7508 {WSAEREFUSED , "Operation refused"}, /* not sure */
7509 #endif
7511 {WSAHOST_NOT_FOUND , "Host not found"},
7512 {WSATRY_AGAIN , "Authoritative host not found during name lookup"},
7513 {WSANO_RECOVERY , "Non-recoverable error during name lookup"},
7514 {WSANO_DATA , "Valid name, no data record of requested type"},
7516 {-1, NULL}
7519 char *
7520 sys_strerror (int error_no)
7522 int i;
7523 static char unknown_msg[40];
7525 if (error_no >= 0 && error_no < sys_nerr)
7526 return sys_errlist[error_no];
7528 for (i = 0; _wsa_errlist[i].errnum >= 0; i++)
7529 if (_wsa_errlist[i].errnum == error_no)
7530 return (char *)_wsa_errlist[i].msg;
7532 sprintf (unknown_msg, "Unidentified error: %d", error_no);
7533 return unknown_msg;
7536 /* [andrewi 3-May-96] I've had conflicting results using both methods,
7537 but I believe the method of keeping the socket handle separate (and
7538 insuring it is not inheritable) is the correct one. */
7540 #define SOCK_HANDLE(fd) ((SOCKET) fd_info[fd].hnd)
7542 static int socket_to_fd (SOCKET s);
7545 sys_socket (int af, int type, int protocol)
7547 SOCKET s;
7549 if (winsock_lib == NULL)
7551 errno = ENETDOWN;
7552 return -1;
7555 check_errno ();
7557 /* call the real socket function */
7558 s = pfn_socket (af, type, protocol);
7560 if (s != INVALID_SOCKET)
7561 return socket_to_fd (s);
7563 set_errno ();
7564 return -1;
7567 /* Convert a SOCKET to a file descriptor. */
7568 static int
7569 socket_to_fd (SOCKET s)
7571 int fd;
7572 child_process * cp;
7574 /* Although under NT 3.5 _open_osfhandle will accept a socket
7575 handle, if opened with SO_OPENTYPE == SO_SYNCHRONOUS_NONALERT,
7576 that does not work under NT 3.1. However, we can get the same
7577 effect by using a backdoor function to replace an existing
7578 descriptor handle with the one we want. */
7580 /* allocate a file descriptor (with appropriate flags) */
7581 fd = _open ("NUL:", _O_RDWR);
7582 if (fd >= 0)
7584 /* Make a non-inheritable copy of the socket handle. Note
7585 that it is possible that sockets aren't actually kernel
7586 handles, which appears to be the case on Windows 9x when
7587 the MS Proxy winsock client is installed. */
7589 /* Apparently there is a bug in NT 3.51 with some service
7590 packs, which prevents using DuplicateHandle to make a
7591 socket handle non-inheritable (causes WSACleanup to
7592 hang). The work-around is to use SetHandleInformation
7593 instead if it is available and implemented. */
7594 if (pfn_SetHandleInformation)
7596 pfn_SetHandleInformation ((HANDLE) s, HANDLE_FLAG_INHERIT, 0);
7598 else
7600 HANDLE parent = GetCurrentProcess ();
7601 HANDLE new_s = INVALID_HANDLE_VALUE;
7603 if (DuplicateHandle (parent,
7604 (HANDLE) s,
7605 parent,
7606 &new_s,
7608 FALSE,
7609 DUPLICATE_SAME_ACCESS))
7611 /* It is possible that DuplicateHandle succeeds even
7612 though the socket wasn't really a kernel handle,
7613 because a real handle has the same value. So
7614 test whether the new handle really is a socket. */
7615 unsigned long nonblocking = 0;
7616 if (pfn_ioctlsocket ((SOCKET) new_s, FIONBIO, &nonblocking) == 0)
7618 pfn_closesocket (s);
7619 s = (SOCKET) new_s;
7621 else
7623 CloseHandle (new_s);
7628 eassert (fd < MAXDESC);
7629 fd_info[fd].hnd = (HANDLE) s;
7631 /* set our own internal flags */
7632 fd_info[fd].flags = FILE_SOCKET | FILE_BINARY | FILE_READ | FILE_WRITE;
7634 cp = new_child ();
7635 if (cp)
7637 cp->fd = fd;
7638 cp->status = STATUS_READ_ACKNOWLEDGED;
7640 /* attach child_process to fd_info */
7641 if (fd_info[ fd ].cp != NULL)
7643 DebPrint (("sys_socket: fd_info[%d] apparently in use!\n", fd));
7644 emacs_abort ();
7647 fd_info[ fd ].cp = cp;
7649 /* success! */
7650 winsock_inuse++; /* count open sockets */
7651 return fd;
7654 /* clean up */
7655 _close (fd);
7657 else
7658 pfn_closesocket (s);
7659 errno = EMFILE;
7660 return -1;
7664 sys_bind (int s, const struct sockaddr * addr, int namelen)
7666 if (winsock_lib == NULL)
7668 errno = ENOTSOCK;
7669 return SOCKET_ERROR;
7672 check_errno ();
7673 if (fd_info[s].flags & FILE_SOCKET)
7675 int rc = pfn_bind (SOCK_HANDLE (s), addr, namelen);
7676 if (rc == SOCKET_ERROR)
7677 set_errno ();
7678 return rc;
7680 errno = ENOTSOCK;
7681 return SOCKET_ERROR;
7685 sys_connect (int s, const struct sockaddr * name, int namelen)
7687 if (winsock_lib == NULL)
7689 errno = ENOTSOCK;
7690 return SOCKET_ERROR;
7693 check_errno ();
7694 if (fd_info[s].flags & FILE_SOCKET)
7696 int rc = pfn_connect (SOCK_HANDLE (s), name, namelen);
7697 if (rc == SOCKET_ERROR)
7699 set_errno ();
7700 /* If this is a non-blocking 'connect', set the bit in flags
7701 that will tell reader_thread to wait for connection
7702 before trying to read. */
7703 if (errno == EWOULDBLOCK && (fd_info[s].flags & FILE_NDELAY) != 0)
7705 errno = EINPROGRESS; /* that's what process.c expects */
7706 fd_info[s].flags |= FILE_CONNECT;
7709 return rc;
7711 errno = ENOTSOCK;
7712 return SOCKET_ERROR;
7715 u_short
7716 sys_htons (u_short hostshort)
7718 return (winsock_lib != NULL) ?
7719 pfn_htons (hostshort) : hostshort;
7722 u_short
7723 sys_ntohs (u_short netshort)
7725 return (winsock_lib != NULL) ?
7726 pfn_ntohs (netshort) : netshort;
7729 unsigned long
7730 sys_inet_addr (const char * cp)
7732 return (winsock_lib != NULL) ?
7733 pfn_inet_addr (cp) : INADDR_NONE;
7737 sys_gethostname (char * name, int namelen)
7739 if (winsock_lib != NULL)
7741 int retval;
7743 check_errno ();
7744 retval = pfn_gethostname (name, namelen);
7745 if (retval == SOCKET_ERROR)
7746 set_errno ();
7747 return retval;
7750 if (namelen > MAX_COMPUTERNAME_LENGTH)
7751 return !GetComputerName (name, (DWORD *)&namelen);
7753 errno = EFAULT;
7754 return SOCKET_ERROR;
7757 struct hostent *
7758 sys_gethostbyname (const char * name)
7760 struct hostent * host;
7761 int h_err = h_errno;
7763 if (winsock_lib == NULL)
7765 h_errno = NO_RECOVERY;
7766 errno = ENETDOWN;
7767 return NULL;
7770 check_errno ();
7771 host = pfn_gethostbyname (name);
7772 if (!host)
7774 set_errno ();
7775 h_errno = errno;
7777 else
7778 h_errno = h_err;
7779 return host;
7782 struct servent *
7783 sys_getservbyname (const char * name, const char * proto)
7785 struct servent * serv;
7787 if (winsock_lib == NULL)
7789 errno = ENETDOWN;
7790 return NULL;
7793 check_errno ();
7794 serv = pfn_getservbyname (name, proto);
7795 if (!serv)
7796 set_errno ();
7797 return serv;
7801 sys_getpeername (int s, struct sockaddr *addr, int * namelen)
7803 if (winsock_lib == NULL)
7805 errno = ENETDOWN;
7806 return SOCKET_ERROR;
7809 check_errno ();
7810 if (fd_info[s].flags & FILE_SOCKET)
7812 int rc = pfn_getpeername (SOCK_HANDLE (s), addr, namelen);
7813 if (rc == SOCKET_ERROR)
7814 set_errno ();
7815 return rc;
7817 errno = ENOTSOCK;
7818 return SOCKET_ERROR;
7822 sys_getaddrinfo (const char *node, const char *service,
7823 const struct addrinfo *hints, struct addrinfo **res)
7825 int rc;
7827 if (winsock_lib == NULL)
7829 errno = ENETDOWN;
7830 return SOCKET_ERROR;
7833 check_errno ();
7834 if (pfn_getaddrinfo)
7835 rc = pfn_getaddrinfo (node, service, hints, res);
7836 else
7838 int port = 0;
7839 struct hostent *host_info;
7840 struct gai_storage {
7841 struct addrinfo addrinfo;
7842 struct sockaddr_in sockaddr_in;
7843 } *gai_storage;
7845 /* We don't (yet) support any flags, as Emacs doesn't need that. */
7846 if (hints && hints->ai_flags != 0)
7847 return WSAEINVAL;
7848 /* NODE cannot be NULL, since process.c has fallbacks for that. */
7849 if (!node)
7850 return WSAHOST_NOT_FOUND;
7852 if (service)
7854 const char *protocol =
7855 (hints && hints->ai_socktype == SOCK_DGRAM) ? "udp" : "tcp";
7856 struct servent *srv = sys_getservbyname (service, protocol);
7858 if (srv)
7859 port = srv->s_port;
7860 else if (*service >= '0' && *service <= '9')
7862 char *endp;
7864 port = strtoul (service, &endp, 10);
7865 if (*endp || port > 65536)
7866 return WSAHOST_NOT_FOUND;
7867 port = sys_htons ((unsigned short) port);
7869 else
7870 return WSAHOST_NOT_FOUND;
7873 gai_storage = xzalloc (sizeof *gai_storage);
7874 gai_storage->sockaddr_in.sin_port = port;
7875 host_info = sys_gethostbyname (node);
7876 if (host_info)
7878 memcpy (&gai_storage->sockaddr_in.sin_addr,
7879 host_info->h_addr, host_info->h_length);
7880 gai_storage->sockaddr_in.sin_family = host_info->h_addrtype;
7882 else
7884 /* Attempt to interpret host as numeric inet address. */
7885 unsigned long numeric_addr = sys_inet_addr (node);
7887 if (numeric_addr == -1)
7889 free (gai_storage);
7890 return WSAHOST_NOT_FOUND;
7893 memcpy (&gai_storage->sockaddr_in.sin_addr, &numeric_addr,
7894 sizeof (gai_storage->sockaddr_in.sin_addr));
7895 gai_storage->sockaddr_in.sin_family = (hints) ? hints->ai_family : 0;
7898 gai_storage->addrinfo.ai_addr =
7899 (struct sockaddr *)&gai_storage->sockaddr_in;
7900 gai_storage->addrinfo.ai_addrlen = sizeof (gai_storage->sockaddr_in);
7901 gai_storage->addrinfo.ai_protocol = (hints) ? hints->ai_protocol : 0;
7902 gai_storage->addrinfo.ai_socktype = (hints) ? hints->ai_socktype : 0;
7903 gai_storage->addrinfo.ai_family = gai_storage->sockaddr_in.sin_family;
7904 gai_storage->addrinfo.ai_next = NULL;
7906 *res = &gai_storage->addrinfo;
7907 rc = 0;
7910 return rc;
7913 void
7914 sys_freeaddrinfo (struct addrinfo *ai)
7916 if (winsock_lib == NULL)
7918 errno = ENETDOWN;
7919 return;
7922 check_errno ();
7923 if (pfn_freeaddrinfo)
7924 pfn_freeaddrinfo (ai);
7925 else
7927 eassert (ai->ai_next == NULL);
7928 xfree (ai);
7933 sys_shutdown (int s, int how)
7935 if (winsock_lib == NULL)
7937 errno = ENETDOWN;
7938 return SOCKET_ERROR;
7941 check_errno ();
7942 if (fd_info[s].flags & FILE_SOCKET)
7944 int rc = pfn_shutdown (SOCK_HANDLE (s), how);
7945 if (rc == SOCKET_ERROR)
7946 set_errno ();
7947 return rc;
7949 errno = ENOTSOCK;
7950 return SOCKET_ERROR;
7954 sys_setsockopt (int s, int level, int optname, const void * optval, int optlen)
7956 if (winsock_lib == NULL)
7958 errno = ENETDOWN;
7959 return SOCKET_ERROR;
7962 check_errno ();
7963 if (fd_info[s].flags & FILE_SOCKET)
7965 int rc = pfn_setsockopt (SOCK_HANDLE (s), level, optname,
7966 (const char *)optval, optlen);
7967 if (rc == SOCKET_ERROR)
7968 set_errno ();
7969 return rc;
7971 errno = ENOTSOCK;
7972 return SOCKET_ERROR;
7976 sys_listen (int s, int backlog)
7978 if (winsock_lib == NULL)
7980 errno = ENETDOWN;
7981 return SOCKET_ERROR;
7984 check_errno ();
7985 if (fd_info[s].flags & FILE_SOCKET)
7987 int rc = pfn_listen (SOCK_HANDLE (s), backlog);
7988 if (rc == SOCKET_ERROR)
7989 set_errno ();
7990 else
7991 fd_info[s].flags |= FILE_LISTEN;
7992 return rc;
7994 errno = ENOTSOCK;
7995 return SOCKET_ERROR;
7999 sys_getsockname (int s, struct sockaddr * name, int * namelen)
8001 if (winsock_lib == NULL)
8003 errno = ENETDOWN;
8004 return SOCKET_ERROR;
8007 check_errno ();
8008 if (fd_info[s].flags & FILE_SOCKET)
8010 int rc = pfn_getsockname (SOCK_HANDLE (s), name, namelen);
8011 if (rc == SOCKET_ERROR)
8012 set_errno ();
8013 return rc;
8015 errno = ENOTSOCK;
8016 return SOCKET_ERROR;
8020 sys_accept (int s, struct sockaddr * addr, int * addrlen)
8022 if (winsock_lib == NULL)
8024 errno = ENETDOWN;
8025 return -1;
8028 check_errno ();
8029 if (fd_info[s].flags & FILE_LISTEN)
8031 SOCKET t = pfn_accept (SOCK_HANDLE (s), addr, addrlen);
8032 int fd = -1;
8033 if (t == INVALID_SOCKET)
8034 set_errno ();
8035 else
8036 fd = socket_to_fd (t);
8038 if (fd >= 0)
8040 fd_info[s].cp->status = STATUS_READ_ACKNOWLEDGED;
8041 ResetEvent (fd_info[s].cp->char_avail);
8043 return fd;
8045 errno = ENOTSOCK;
8046 return -1;
8050 sys_recvfrom (int s, char * buf, int len, int flags,
8051 struct sockaddr * from, int * fromlen)
8053 if (winsock_lib == NULL)
8055 errno = ENETDOWN;
8056 return SOCKET_ERROR;
8059 check_errno ();
8060 if (fd_info[s].flags & FILE_SOCKET)
8062 int rc = pfn_recvfrom (SOCK_HANDLE (s), buf, len, flags, from, fromlen);
8063 if (rc == SOCKET_ERROR)
8064 set_errno ();
8065 return rc;
8067 errno = ENOTSOCK;
8068 return SOCKET_ERROR;
8072 sys_sendto (int s, const char * buf, int len, int flags,
8073 const struct sockaddr * to, int tolen)
8075 if (winsock_lib == NULL)
8077 errno = ENETDOWN;
8078 return SOCKET_ERROR;
8081 check_errno ();
8082 if (fd_info[s].flags & FILE_SOCKET)
8084 int rc = pfn_sendto (SOCK_HANDLE (s), buf, len, flags, to, tolen);
8085 if (rc == SOCKET_ERROR)
8086 set_errno ();
8087 return rc;
8089 errno = ENOTSOCK;
8090 return SOCKET_ERROR;
8093 /* Windows does not have an fcntl function. Provide an implementation
8094 good enough for Emacs. */
8096 fcntl (int s, int cmd, int options)
8098 /* In the w32 Emacs port, fcntl (fd, F_DUPFD_CLOEXEC, fd1) is always
8099 invoked in a context where fd1 is closed and all descriptors less
8100 than fd1 are open, so sys_dup is an adequate implementation. */
8101 if (cmd == F_DUPFD_CLOEXEC)
8102 return sys_dup (s);
8104 check_errno ();
8105 if (fd_info[s].flags & FILE_SOCKET)
8107 if (winsock_lib == NULL)
8109 errno = ENETDOWN;
8110 return -1;
8113 if (cmd == F_SETFL && options == O_NONBLOCK)
8115 unsigned long nblock = 1;
8116 int rc = pfn_ioctlsocket (SOCK_HANDLE (s), FIONBIO, &nblock);
8117 if (rc == SOCKET_ERROR)
8118 set_errno ();
8119 /* Keep track of the fact that we set this to non-blocking. */
8120 fd_info[s].flags |= FILE_NDELAY;
8121 return rc;
8123 else
8125 errno = EINVAL;
8126 return SOCKET_ERROR;
8129 else if ((fd_info[s].flags & (FILE_PIPE | FILE_WRITE))
8130 == (FILE_PIPE | FILE_WRITE))
8132 /* Force our writes to pipes be non-blocking. */
8133 if (cmd == F_SETFL && options == O_NONBLOCK)
8135 HANDLE h = (HANDLE)_get_osfhandle (s);
8136 DWORD pipe_mode = PIPE_NOWAIT;
8138 if (!SetNamedPipeHandleState (h, &pipe_mode, NULL, NULL))
8140 DebPrint (("SetNamedPipeHandleState: %lu\n", GetLastError ()));
8141 return SOCKET_ERROR;
8143 fd_info[s].flags |= FILE_NDELAY;
8144 return 0;
8146 else
8148 errno = EINVAL;
8149 return SOCKET_ERROR;
8152 errno = ENOTSOCK;
8153 return SOCKET_ERROR;
8157 /* Shadow main io functions: we need to handle pipes and sockets more
8158 intelligently. */
8161 sys_close (int fd)
8163 int rc;
8165 if (fd < 0)
8167 errno = EBADF;
8168 return -1;
8171 if (fd < MAXDESC && fd_info[fd].cp)
8173 child_process * cp = fd_info[fd].cp;
8175 fd_info[fd].cp = NULL;
8177 if (CHILD_ACTIVE (cp))
8179 /* if last descriptor to active child_process then cleanup */
8180 int i;
8181 for (i = 0; i < MAXDESC; i++)
8183 if (i == fd)
8184 continue;
8185 if (fd_info[i].cp == cp)
8186 break;
8188 if (i == MAXDESC)
8190 if (fd_info[fd].flags & FILE_SOCKET)
8192 if (winsock_lib == NULL) emacs_abort ();
8194 pfn_shutdown (SOCK_HANDLE (fd), 2);
8195 rc = pfn_closesocket (SOCK_HANDLE (fd));
8197 winsock_inuse--; /* count open sockets */
8199 /* If the process handle is NULL, it's either a socket
8200 or serial connection, or a subprocess that was
8201 already reaped by reap_subprocess, but whose
8202 resources were not yet freed, because its output was
8203 not fully read yet by the time it was reaped. (This
8204 usually happens with async subprocesses whose output
8205 is being read by Emacs.) Otherwise, this process was
8206 not reaped yet, so we set its FD to a negative value
8207 to make sure sys_select will eventually get to
8208 calling the SIGCHLD handler for it, which will then
8209 invoke waitpid and reap_subprocess. */
8210 if (cp->procinfo.hProcess == NULL)
8211 delete_child (cp);
8212 else
8213 cp->fd = -1;
8218 if (fd >= 0 && fd < MAXDESC)
8219 fd_info[fd].flags = 0;
8221 /* Note that sockets do not need special treatment here (at least on
8222 NT and Windows 95 using the standard tcp/ip stacks) - it appears that
8223 closesocket is equivalent to CloseHandle, which is to be expected
8224 because socket handles are fully fledged kernel handles. */
8225 rc = _close (fd);
8227 return rc;
8231 sys_dup (int fd)
8233 int new_fd;
8235 new_fd = _dup (fd);
8236 if (new_fd >= 0 && new_fd < MAXDESC)
8238 /* duplicate our internal info as well */
8239 fd_info[new_fd] = fd_info[fd];
8241 return new_fd;
8245 sys_dup2 (int src, int dst)
8247 int rc;
8249 if (dst < 0 || dst >= MAXDESC)
8251 errno = EBADF;
8252 return -1;
8255 /* MS _dup2 seems to have weird side effect when invoked with 2
8256 identical arguments: an attempt to fclose the corresponding stdio
8257 stream after that hangs (we do close standard streams in
8258 init_ntproc). Attempt to avoid that by not calling _dup2 that
8259 way: if SRC is valid, we know that dup2 should be a no-op, so do
8260 nothing and return DST. */
8261 if (src == dst)
8263 if ((HANDLE)_get_osfhandle (src) == INVALID_HANDLE_VALUE)
8265 errno = EBADF;
8266 return -1;
8268 return dst;
8271 /* Make sure we close the destination first if it's a pipe or socket. */
8272 if (fd_info[dst].flags != 0)
8273 sys_close (dst);
8275 rc = _dup2 (src, dst);
8276 if (rc == 0)
8278 /* Duplicate our internal info as well. */
8279 fd_info[dst] = fd_info[src];
8281 return rc == 0 ? dst : rc;
8285 pipe2 (int * phandles, int pipe2_flags)
8287 int rc;
8288 unsigned flags;
8289 unsigned pipe_size = 0;
8291 eassert (pipe2_flags == (O_BINARY | O_CLOEXEC));
8293 /* Allow Lisp to override the default buffer size of the pipe. */
8294 if (w32_pipe_buffer_size > 0 && w32_pipe_buffer_size < UINT_MAX)
8295 pipe_size = w32_pipe_buffer_size;
8297 /* make pipe handles non-inheritable; when we spawn a child, we
8298 replace the relevant handle with an inheritable one. Also put
8299 pipes into binary mode; we will do text mode translation ourselves
8300 if required. */
8301 rc = _pipe (phandles, pipe_size, _O_NOINHERIT | _O_BINARY);
8303 if (rc == 0)
8305 /* Protect against overflow, since Windows can open more handles than
8306 our fd_info array has room for. */
8307 if (phandles[0] >= MAXDESC || phandles[1] >= MAXDESC)
8309 _close (phandles[0]);
8310 _close (phandles[1]);
8311 errno = EMFILE;
8312 rc = -1;
8314 else
8316 flags = FILE_PIPE | FILE_READ | FILE_BINARY;
8317 fd_info[phandles[0]].flags = flags;
8319 flags = FILE_PIPE | FILE_WRITE | FILE_BINARY;
8320 fd_info[phandles[1]].flags = flags;
8324 return rc;
8327 /* Function to do blocking read of one byte, needed to implement
8328 select. It is only allowed on communication ports, sockets, or
8329 pipes. */
8331 _sys_read_ahead (int fd)
8333 child_process * cp;
8334 int rc;
8336 if (fd < 0 || fd >= MAXDESC)
8337 return STATUS_READ_ERROR;
8339 cp = fd_info[fd].cp;
8341 if (cp == NULL || cp->fd != fd || cp->status != STATUS_READ_READY)
8342 return STATUS_READ_ERROR;
8344 if ((fd_info[fd].flags & (FILE_PIPE | FILE_SERIAL | FILE_SOCKET)) == 0
8345 || (fd_info[fd].flags & FILE_READ) == 0)
8347 DebPrint (("_sys_read_ahead: internal error: fd %d is not a pipe, serial port, or socket!\n", fd));
8348 emacs_abort ();
8351 if ((fd_info[fd].flags & FILE_CONNECT) != 0)
8352 DebPrint (("_sys_read_ahead: read requested from fd %d, which waits for async connect!\n", fd));
8353 cp->status = STATUS_READ_IN_PROGRESS;
8355 if (fd_info[fd].flags & FILE_PIPE)
8357 rc = _read (fd, &cp->chr, sizeof (char));
8359 /* Give subprocess time to buffer some more output for us before
8360 reporting that input is available; we need this because Windows 95
8361 connects DOS programs to pipes by making the pipe appear to be
8362 the normal console stdout - as a result most DOS programs will
8363 write to stdout without buffering, ie. one character at a
8364 time. Even some W32 programs do this - "dir" in a command
8365 shell on NT is very slow if we don't do this. */
8366 if (rc > 0)
8368 int wait = w32_pipe_read_delay;
8370 if (wait > 0)
8371 Sleep (wait);
8372 else if (wait < 0)
8373 while (++wait <= 0)
8374 /* Yield remainder of our time slice, effectively giving a
8375 temporary priority boost to the child process. */
8376 Sleep (0);
8379 else if (fd_info[fd].flags & FILE_SERIAL)
8381 HANDLE hnd = fd_info[fd].hnd;
8382 OVERLAPPED *ovl = &fd_info[fd].cp->ovl_read;
8383 COMMTIMEOUTS ct;
8385 /* Configure timeouts for blocking read. */
8386 if (!GetCommTimeouts (hnd, &ct))
8388 cp->status = STATUS_READ_ERROR;
8389 return STATUS_READ_ERROR;
8391 ct.ReadIntervalTimeout = 0;
8392 ct.ReadTotalTimeoutMultiplier = 0;
8393 ct.ReadTotalTimeoutConstant = 0;
8394 if (!SetCommTimeouts (hnd, &ct))
8396 cp->status = STATUS_READ_ERROR;
8397 return STATUS_READ_ERROR;
8400 if (!ReadFile (hnd, &cp->chr, sizeof (char), (DWORD*) &rc, ovl))
8402 if (GetLastError () != ERROR_IO_PENDING)
8404 cp->status = STATUS_READ_ERROR;
8405 return STATUS_READ_ERROR;
8407 if (!GetOverlappedResult (hnd, ovl, (DWORD*) &rc, TRUE))
8409 cp->status = STATUS_READ_ERROR;
8410 return STATUS_READ_ERROR;
8414 else if (fd_info[fd].flags & FILE_SOCKET)
8416 unsigned long nblock = 0;
8417 /* We always want this to block, so temporarily disable NDELAY. */
8418 if (fd_info[fd].flags & FILE_NDELAY)
8419 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONBIO, &nblock);
8421 rc = pfn_recv (SOCK_HANDLE (fd), &cp->chr, sizeof (char), 0);
8423 if (fd_info[fd].flags & FILE_NDELAY)
8425 nblock = 1;
8426 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONBIO, &nblock);
8430 if (rc == sizeof (char))
8431 cp->status = STATUS_READ_SUCCEEDED;
8432 else
8433 cp->status = STATUS_READ_FAILED;
8435 return cp->status;
8439 _sys_wait_accept (int fd)
8441 HANDLE hEv;
8442 child_process * cp;
8443 int rc;
8445 if (fd < 0 || fd >= MAXDESC)
8446 return STATUS_READ_ERROR;
8448 cp = fd_info[fd].cp;
8450 if (cp == NULL || cp->fd != fd || cp->status != STATUS_READ_READY)
8451 return STATUS_READ_ERROR;
8453 cp->status = STATUS_READ_FAILED;
8455 hEv = pfn_WSACreateEvent ();
8456 rc = pfn_WSAEventSelect (SOCK_HANDLE (fd), hEv, FD_ACCEPT);
8457 if (rc != SOCKET_ERROR)
8459 do {
8460 rc = WaitForSingleObject (hEv, 500);
8461 Sleep (5);
8462 } while (rc == WAIT_TIMEOUT
8463 && cp->status != STATUS_READ_ERROR
8464 && cp->char_avail);
8465 pfn_WSAEventSelect (SOCK_HANDLE (fd), NULL, 0);
8466 if (rc == WAIT_OBJECT_0)
8467 cp->status = STATUS_READ_SUCCEEDED;
8469 pfn_WSACloseEvent (hEv);
8471 return cp->status;
8475 _sys_wait_connect (int fd)
8477 HANDLE hEv;
8478 child_process * cp;
8479 int rc;
8481 if (fd < 0 || fd >= MAXDESC)
8482 return STATUS_READ_ERROR;
8484 cp = fd_info[fd].cp;
8485 if (cp == NULL || cp->fd != fd || cp->status != STATUS_READ_READY)
8486 return STATUS_READ_ERROR;
8488 cp->status = STATUS_READ_FAILED;
8490 hEv = pfn_WSACreateEvent ();
8491 rc = pfn_WSAEventSelect (SOCK_HANDLE (fd), hEv, FD_CONNECT);
8492 if (rc != SOCKET_ERROR)
8494 do {
8495 rc = WaitForSingleObject (hEv, 500);
8496 Sleep (5);
8497 } while (rc == WAIT_TIMEOUT
8498 && cp->status != STATUS_READ_ERROR
8499 && cp->char_avail);
8500 if (rc == WAIT_OBJECT_0)
8502 /* We've got an event, but it could be a successful
8503 connection, or it could be a failure. Find out
8504 which one is it. */
8505 WSANETWORKEVENTS events;
8507 pfn_WSAEnumNetworkEvents (SOCK_HANDLE (fd), hEv, &events);
8508 if ((events.lNetworkEvents & FD_CONNECT) != 0
8509 && events.iErrorCode[FD_CONNECT_BIT])
8511 cp->status = STATUS_CONNECT_FAILED;
8512 cp->errcode = events.iErrorCode[FD_CONNECT_BIT];
8514 else
8516 cp->status = STATUS_READ_SUCCEEDED;
8517 cp->errcode = 0;
8520 pfn_WSAEventSelect (SOCK_HANDLE (fd), NULL, 0);
8522 else
8523 pfn_WSACloseEvent (hEv);
8525 return cp->status;
8529 sys_read (int fd, char * buffer, unsigned int count)
8531 int nchars;
8532 int to_read;
8533 DWORD waiting;
8534 char * orig_buffer = buffer;
8536 if (fd < 0)
8538 errno = EBADF;
8539 return -1;
8542 if (fd < MAXDESC && fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET | FILE_SERIAL))
8544 child_process *cp = fd_info[fd].cp;
8546 if ((fd_info[fd].flags & FILE_READ) == 0)
8548 errno = EBADF;
8549 return -1;
8552 nchars = 0;
8554 /* re-read CR carried over from last read */
8555 if (fd_info[fd].flags & FILE_LAST_CR)
8557 if (fd_info[fd].flags & FILE_BINARY) emacs_abort ();
8558 *buffer++ = 0x0d;
8559 count--;
8560 nchars++;
8561 fd_info[fd].flags &= ~FILE_LAST_CR;
8564 /* presence of a child_process structure means we are operating in
8565 non-blocking mode - otherwise we just call _read directly.
8566 Note that the child_process structure might be missing because
8567 reap_subprocess has been called; in this case the pipe is
8568 already broken, so calling _read on it is okay. */
8569 if (cp)
8571 int current_status = cp->status;
8573 switch (current_status)
8575 case STATUS_READ_FAILED:
8576 case STATUS_READ_ERROR:
8577 /* report normal EOF if nothing in buffer */
8578 if (nchars <= 0)
8579 fd_info[fd].flags |= FILE_AT_EOF;
8580 return nchars;
8582 case STATUS_READ_READY:
8583 case STATUS_READ_IN_PROGRESS:
8584 #if 0
8585 /* This happens all the time during GnuTLS handshake
8586 with the remote, evidently because GnuTLS waits for
8587 the read to complete by retrying the read operation
8588 upon EAGAIN. So I'm disabling the DebPrint to avoid
8589 wasting cycles on something that is not a real
8590 problem. Enable if you need to debug something that
8591 bumps into this. */
8592 DebPrint (("sys_read called when read is in progress %d\n",
8593 current_status));
8594 #endif
8595 errno = EWOULDBLOCK;
8596 return -1;
8598 case STATUS_READ_SUCCEEDED:
8599 /* consume read-ahead char */
8600 *buffer++ = cp->chr;
8601 count--;
8602 nchars++;
8603 cp->status = STATUS_READ_ACKNOWLEDGED;
8604 ResetEvent (cp->char_avail);
8606 case STATUS_READ_ACKNOWLEDGED:
8607 case STATUS_CONNECT_FAILED:
8608 break;
8610 default:
8611 DebPrint (("sys_read: bad status %d\n", current_status));
8612 errno = EBADF;
8613 return -1;
8616 if (fd_info[fd].flags & FILE_PIPE)
8618 PeekNamedPipe ((HANDLE) _get_osfhandle (fd), NULL, 0, NULL, &waiting, NULL);
8619 to_read = min (waiting, (DWORD) count);
8621 if (to_read > 0)
8622 nchars += _read (fd, buffer, to_read);
8624 else if (fd_info[fd].flags & FILE_SERIAL)
8626 HANDLE hnd = fd_info[fd].hnd;
8627 OVERLAPPED *ovl = &fd_info[fd].cp->ovl_read;
8628 int rc = 0;
8629 COMMTIMEOUTS ct;
8631 if (count > 0)
8633 /* Configure timeouts for non-blocking read. */
8634 if (!GetCommTimeouts (hnd, &ct))
8636 errno = EIO;
8637 return -1;
8639 ct.ReadIntervalTimeout = MAXDWORD;
8640 ct.ReadTotalTimeoutMultiplier = 0;
8641 ct.ReadTotalTimeoutConstant = 0;
8642 if (!SetCommTimeouts (hnd, &ct))
8644 errno = EIO;
8645 return -1;
8648 if (!ResetEvent (ovl->hEvent))
8650 errno = EIO;
8651 return -1;
8653 if (!ReadFile (hnd, buffer, count, (DWORD*) &rc, ovl))
8655 if (GetLastError () != ERROR_IO_PENDING)
8657 errno = EIO;
8658 return -1;
8660 if (!GetOverlappedResult (hnd, ovl, (DWORD*) &rc, TRUE))
8662 errno = EIO;
8663 return -1;
8666 nchars += rc;
8669 else /* FILE_SOCKET */
8671 if (winsock_lib == NULL) emacs_abort ();
8673 /* When a non-blocking 'connect' call fails,
8674 wait_reading_process_output detects this by calling
8675 'getpeername', and then attempts to obtain the connection
8676 error code by trying to read 1 byte from the socket. If
8677 we try to serve that read by calling 'recv' below, the
8678 error we get is a generic WSAENOTCONN, not the actual
8679 connection error. So instead, we use the actual error
8680 code stashed by '_sys_wait_connect' in cp->errcode.
8681 Alternatively, we could have used 'getsockopt', like on
8682 GNU/Linux, but: (a) I have no idea whether the winsock
8683 version could hang, as it does "on some systems" (see the
8684 comment in process.c); and (b) 'getsockopt' on Windows is
8685 documented to clear the socket error for the entire
8686 process, which I'm not sure is TRT; FIXME. */
8687 if (current_status == STATUS_CONNECT_FAILED
8688 && (fd_info[fd].flags & FILE_CONNECT) != 0
8689 && cp->errcode != 0)
8691 pfn_WSASetLastError (cp->errcode);
8692 set_errno ();
8693 return -1;
8695 /* Do the equivalent of a non-blocking read. */
8696 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONREAD, &waiting);
8697 if (waiting == 0 && nchars == 0)
8699 errno = EWOULDBLOCK;
8700 return -1;
8703 if (waiting)
8705 /* always use binary mode for sockets */
8706 int res = pfn_recv (SOCK_HANDLE (fd), buffer, count, 0);
8707 if (res == SOCKET_ERROR)
8709 set_errno ();
8710 DebPrint (("sys_read.recv failed with error %d on socket %ld\n",
8711 errno, SOCK_HANDLE (fd)));
8712 return -1;
8714 nchars += res;
8718 else
8720 int nread = _read (fd, buffer, count);
8721 if (nread >= 0)
8722 nchars += nread;
8723 else if (nchars == 0)
8724 nchars = nread;
8727 if (nchars <= 0)
8728 fd_info[fd].flags |= FILE_AT_EOF;
8729 /* Perform text mode translation if required. */
8730 else if ((fd_info[fd].flags & FILE_BINARY) == 0)
8732 nchars = crlf_to_lf (nchars, orig_buffer);
8733 /* If buffer contains only CR, return that. To be absolutely
8734 sure we should attempt to read the next char, but in
8735 practice a CR to be followed by LF would not appear by
8736 itself in the buffer. */
8737 if (nchars > 1 && orig_buffer[nchars - 1] == 0x0d)
8739 fd_info[fd].flags |= FILE_LAST_CR;
8740 nchars--;
8744 else
8745 nchars = _read (fd, buffer, count);
8747 return nchars;
8750 /* From w32xfns.c */
8751 extern HANDLE interrupt_handle;
8754 sys_write (int fd, const void * buffer, unsigned int count)
8756 int nchars;
8757 USE_SAFE_ALLOCA;
8759 if (fd < 0)
8761 errno = EBADF;
8762 return -1;
8765 if (fd < MAXDESC && fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET | FILE_SERIAL))
8767 if ((fd_info[fd].flags & FILE_WRITE) == 0)
8769 errno = EBADF;
8770 return -1;
8773 /* Perform text mode translation if required. */
8774 if ((fd_info[fd].flags & FILE_BINARY) == 0)
8776 char * tmpbuf;
8777 const unsigned char * src = buffer;
8778 unsigned char * dst;
8779 int nbytes = count;
8781 SAFE_NALLOCA (tmpbuf, 2, count);
8782 dst = (unsigned char *)tmpbuf;
8784 while (1)
8786 unsigned char *next;
8787 /* Copy next line or remaining bytes. */
8788 next = _memccpy (dst, src, '\n', nbytes);
8789 if (next)
8791 /* Copied one line ending with '\n'. */
8792 int copied = next - dst;
8793 nbytes -= copied;
8794 src += copied;
8795 /* Insert '\r' before '\n'. */
8796 next[-1] = '\r';
8797 next[0] = '\n';
8798 dst = next + 1;
8799 count++;
8801 else
8802 /* Copied remaining partial line -> now finished. */
8803 break;
8805 buffer = tmpbuf;
8809 if (fd < MAXDESC && fd_info[fd].flags & FILE_SERIAL)
8811 HANDLE hnd = (HANDLE) _get_osfhandle (fd);
8812 OVERLAPPED *ovl = &fd_info[fd].cp->ovl_write;
8813 HANDLE wait_hnd[2] = { interrupt_handle, ovl->hEvent };
8814 DWORD active = 0;
8816 /* This is async (a.k.a. "overlapped") I/O, so the return value
8817 of FALSE from WriteFile means either an error or the output
8818 will be completed asynchronously (ERROR_IO_PENDING). */
8819 if (!WriteFile (hnd, buffer, count, (DWORD*) &nchars, ovl))
8821 if (GetLastError () != ERROR_IO_PENDING)
8823 errno = EIO;
8824 nchars = -1;
8826 else
8828 /* Wait for the write to complete, and watch C-g while
8829 at that. */
8830 if (detect_input_pending ())
8831 active = MsgWaitForMultipleObjects (2, wait_hnd, FALSE,
8832 INFINITE, QS_ALLINPUT);
8833 else
8834 active = WaitForMultipleObjects (2, wait_hnd, FALSE, INFINITE);
8835 switch (active)
8837 case WAIT_OBJECT_0:
8838 /* User pressed C-g, cancel write, then leave.
8839 Don't bother cleaning up as we may only get stuck
8840 in buggy drivers. */
8841 PurgeComm (hnd, PURGE_TXABORT | PURGE_TXCLEAR);
8842 CancelIo (hnd);
8843 errno = EIO; /* Why not EINTR? */
8844 nchars = -1;
8845 break;
8846 case WAIT_OBJECT_0 + 1:
8847 if (!GetOverlappedResult (hnd, ovl, (DWORD*) &nchars, TRUE))
8849 errno = EIO;
8850 nchars = -1;
8852 break;
8857 else if (fd < MAXDESC && fd_info[fd].flags & FILE_SOCKET)
8859 unsigned long nblock = 0;
8860 if (winsock_lib == NULL) emacs_abort ();
8862 child_process *cp = fd_info[fd].cp;
8864 /* If this is a non-blocking socket whose connection is in
8865 progress or terminated with an error already, return the
8866 proper error code to the caller. */
8867 if (cp != NULL && (fd_info[fd].flags & FILE_CONNECT) != 0)
8869 /* In case connection is in progress, ENOTCONN that would
8870 result from calling pfn_send is not what callers expect. */
8871 if (cp->status != STATUS_CONNECT_FAILED)
8873 errno = EWOULDBLOCK;
8874 return -1;
8876 /* In case connection failed, use the actual error code
8877 stashed by '_sys_wait_connect' in cp->errcode. */
8878 else if (cp->errcode != 0)
8880 pfn_WSASetLastError (cp->errcode);
8881 set_errno ();
8882 return -1;
8886 /* TODO: implement select() properly so non-blocking I/O works. */
8887 /* For now, make sure the write blocks. */
8888 if (fd_info[fd].flags & FILE_NDELAY)
8889 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONBIO, &nblock);
8891 nchars = pfn_send (SOCK_HANDLE (fd), buffer, count, 0);
8893 if (nchars == SOCKET_ERROR)
8895 set_errno ();
8896 DebPrint (("sys_write.send failed with error %d on socket %ld\n",
8897 pfn_WSAGetLastError (), SOCK_HANDLE (fd)));
8900 /* Set the socket back to non-blocking if it was before,
8901 for other operations that support it. */
8902 if (fd_info[fd].flags & FILE_NDELAY)
8904 nblock = 1;
8905 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONBIO, &nblock);
8908 else
8910 /* Some networked filesystems don't like too large writes, so
8911 break them into smaller chunks. See the Comments section of
8912 the MSDN documentation of WriteFile for details behind the
8913 choice of the value of CHUNK below. See also the thread
8914 http://thread.gmane.org/gmane.comp.version-control.git/145294
8915 in the git mailing list. */
8916 const unsigned char *p = buffer;
8917 const bool is_pipe = (fd < MAXDESC
8918 && ((fd_info[fd].flags & (FILE_PIPE | FILE_NDELAY))
8919 == (FILE_PIPE | FILE_NDELAY)));
8920 /* Some programs, notably Node.js's node.exe, seem to never
8921 completely empty the pipe, so writing more than the size of
8922 the pipe's buffer always returns ENOSPC, and we loop forever
8923 between send_process and here. As a workaround, write no
8924 more than the pipe's buffer can hold. */
8925 DWORD pipe_buffer_size;
8926 if (is_pipe)
8928 if (!GetNamedPipeInfo ((HANDLE)_get_osfhandle (fd),
8929 NULL, &pipe_buffer_size, NULL, NULL))
8931 DebPrint (("GetNamedPipeInfo: error %u\n", GetLastError ()));
8932 pipe_buffer_size = 4096;
8935 const unsigned chunk = is_pipe ? pipe_buffer_size : 30 * 1024 * 1024;
8937 nchars = 0;
8938 errno = 0;
8939 while (count > 0)
8941 unsigned this_chunk = count < chunk ? count : chunk;
8942 int n = _write (fd, p, this_chunk);
8944 if (n > 0)
8945 nchars += n;
8946 if (n < 0)
8948 /* When there's no buffer space in a pipe that is in the
8949 non-blocking mode, _write returns ENOSPC. We return
8950 EAGAIN instead, which should trigger the logic in
8951 send_process that enters waiting loop and calls
8952 wait_reading_process_output to allow process input to
8953 be accepted during the wait. Those calls to
8954 wait_reading_process_output allow sys_select to
8955 notice when process input becomes available, thus
8956 avoiding deadlock whereby each side of the pipe is
8957 blocked on write, waiting for the other party to read
8958 its end of the pipe. */
8959 if (errno == ENOSPC && is_pipe)
8960 errno = EAGAIN;
8961 if (nchars == 0)
8962 nchars = -1;
8963 break;
8965 else if (n < this_chunk)
8966 break;
8967 count -= n;
8968 p += n;
8972 SAFE_FREE ();
8973 return nchars;
8977 /* Emulation of SIOCGIFCONF and getifaddrs, see process.c. */
8979 /* Return information about network interface IFNAME, or about all
8980 interfaces (if IFNAME is nil). */
8981 static Lisp_Object
8982 network_interface_get_info (Lisp_Object ifname)
8984 ULONG ainfo_len = sizeof (IP_ADAPTER_INFO);
8985 IP_ADAPTER_INFO *adapter, *ainfo = xmalloc (ainfo_len);
8986 DWORD retval = get_adapters_info (ainfo, &ainfo_len);
8987 Lisp_Object res = Qnil;
8989 if (retval == ERROR_BUFFER_OVERFLOW)
8991 ainfo = xrealloc (ainfo, ainfo_len);
8992 retval = get_adapters_info (ainfo, &ainfo_len);
8995 if (retval == ERROR_SUCCESS)
8997 int eth_count = 0, tr_count = 0, fddi_count = 0, ppp_count = 0;
8998 int sl_count = 0, wlan_count = 0, lo_count = 0, ifx_count = 0;
8999 int if_num;
9000 struct sockaddr_in sa;
9002 /* For the below, we need some winsock functions, so make sure
9003 the winsock DLL is loaded. If we cannot successfully load
9004 it, they will have no use of the information we provide,
9005 anyway, so punt. */
9006 if (!winsock_lib && !init_winsock (1))
9007 goto done;
9009 for (adapter = ainfo; adapter; adapter = adapter->Next)
9011 char namebuf[MAX_ADAPTER_NAME_LENGTH + 4];
9012 u_long ip_addr;
9013 /* Present Unix-compatible interface names, instead of the
9014 Windows names, which are really GUIDs not readable by
9015 humans. */
9016 static const char *ifmt[] = {
9017 "eth%d", "tr%d", "fddi%d", "ppp%d", "sl%d", "wlan%d",
9018 "lo", "ifx%d"
9020 enum {
9021 NONE = -1,
9022 ETHERNET = 0,
9023 TOKENRING = 1,
9024 FDDI = 2,
9025 PPP = 3,
9026 SLIP = 4,
9027 WLAN = 5,
9028 LOOPBACK = 6,
9029 OTHER_IF = 7
9030 } ifmt_idx;
9032 switch (adapter->Type)
9034 case MIB_IF_TYPE_ETHERNET:
9035 /* Windows before Vista reports wireless adapters as
9036 Ethernet. Work around by looking at the Description
9037 string. */
9038 if (strstr (adapter->Description, "Wireless "))
9040 ifmt_idx = WLAN;
9041 if_num = wlan_count++;
9043 else
9045 ifmt_idx = ETHERNET;
9046 if_num = eth_count++;
9048 break;
9049 case MIB_IF_TYPE_TOKENRING:
9050 ifmt_idx = TOKENRING;
9051 if_num = tr_count++;
9052 break;
9053 case MIB_IF_TYPE_FDDI:
9054 ifmt_idx = FDDI;
9055 if_num = fddi_count++;
9056 break;
9057 case MIB_IF_TYPE_PPP:
9058 ifmt_idx = PPP;
9059 if_num = ppp_count++;
9060 break;
9061 case MIB_IF_TYPE_SLIP:
9062 ifmt_idx = SLIP;
9063 if_num = sl_count++;
9064 break;
9065 case IF_TYPE_IEEE80211:
9066 ifmt_idx = WLAN;
9067 if_num = wlan_count++;
9068 break;
9069 case MIB_IF_TYPE_LOOPBACK:
9070 if (lo_count < 0)
9072 ifmt_idx = LOOPBACK;
9073 if_num = lo_count++;
9075 else
9076 ifmt_idx = NONE;
9077 break;
9078 default:
9079 ifmt_idx = OTHER_IF;
9080 if_num = ifx_count++;
9081 break;
9083 if (ifmt_idx == NONE)
9084 continue;
9085 sprintf (namebuf, ifmt[ifmt_idx], if_num);
9087 sa.sin_family = AF_INET;
9088 ip_addr = sys_inet_addr (adapter->IpAddressList.IpAddress.String);
9089 if (ip_addr == INADDR_NONE)
9091 /* Bogus address, skip this interface. */
9092 continue;
9094 sa.sin_addr.s_addr = ip_addr;
9095 sa.sin_port = 0;
9096 if (NILP (ifname))
9097 res = Fcons (Fcons (build_string (namebuf),
9098 conv_sockaddr_to_lisp ((struct sockaddr*) &sa,
9099 sizeof (struct sockaddr))),
9100 res);
9101 else if (strcmp (namebuf, SSDATA (ifname)) == 0)
9103 Lisp_Object hwaddr = Fmake_vector (make_number (6), Qnil);
9104 register struct Lisp_Vector *p = XVECTOR (hwaddr);
9105 Lisp_Object flags = Qnil;
9106 int n;
9107 u_long net_mask;
9109 /* Flags. We guess most of them by type, since the
9110 Windows flags are different and hard to get by. */
9111 flags = Fcons (intern ("up"), flags);
9112 if (ifmt_idx == ETHERNET || ifmt_idx == WLAN)
9114 flags = Fcons (intern ("broadcast"), flags);
9115 flags = Fcons (intern ("multicast"), flags);
9117 flags = Fcons (intern ("running"), flags);
9118 if (ifmt_idx == PPP)
9120 flags = Fcons (intern ("pointopoint"), flags);
9121 flags = Fcons (intern ("noarp"), flags);
9123 if (adapter->HaveWins)
9124 flags = Fcons (intern ("WINS"), flags);
9125 if (adapter->DhcpEnabled)
9126 flags = Fcons (intern ("dynamic"), flags);
9128 res = Fcons (flags, res);
9130 /* Hardware address and its family. */
9131 for (n = 0; n < adapter->AddressLength; n++)
9132 p->contents[n] = make_number ((int) adapter->Address[n]);
9133 /* Windows does not support AF_LINK or AF_PACKET family
9134 of addresses. Use an arbitrary family number that is
9135 identical to what GNU/Linux returns. */
9136 res = Fcons (Fcons (make_number (1), hwaddr), res);
9138 /* Network mask. */
9139 sa.sin_family = AF_INET;
9140 net_mask = sys_inet_addr (adapter->IpAddressList.IpMask.String);
9141 if (net_mask != INADDR_NONE)
9143 sa.sin_addr.s_addr = net_mask;
9144 sa.sin_port = 0;
9145 res = Fcons (conv_sockaddr_to_lisp ((struct sockaddr *) &sa,
9146 sizeof (struct sockaddr)),
9147 res);
9149 else
9150 res = Fcons (Qnil, res);
9152 sa.sin_family = AF_INET;
9153 if (ip_addr != INADDR_NONE)
9155 /* Broadcast address is only reported by
9156 GetAdaptersAddresses, which is of limited
9157 availability. Generate it on our own. */
9158 u_long bcast_addr = (ip_addr & net_mask) | ~net_mask;
9160 sa.sin_addr.s_addr = bcast_addr;
9161 sa.sin_port = 0;
9162 res = Fcons (conv_sockaddr_to_lisp ((struct sockaddr *) &sa,
9163 sizeof (struct sockaddr)),
9164 res);
9166 /* IP address. */
9167 sa.sin_addr.s_addr = ip_addr;
9168 sa.sin_port = 0;
9169 res = Fcons (conv_sockaddr_to_lisp ((struct sockaddr *) &sa,
9170 sizeof (struct sockaddr)),
9171 res);
9173 else
9174 res = Fcons (Qnil, Fcons (Qnil, res));
9177 /* GetAdaptersInfo is documented to not report loopback
9178 interfaces, so we generate one out of thin air. */
9179 if (!lo_count)
9181 sa.sin_family = AF_INET;
9182 sa.sin_port = 0;
9183 if (NILP (ifname))
9185 sa.sin_addr.s_addr = sys_inet_addr ("127.0.0.1");
9186 res = Fcons (Fcons (build_string ("lo"),
9187 conv_sockaddr_to_lisp ((struct sockaddr*) &sa,
9188 sizeof (struct sockaddr))),
9189 res);
9191 else if (strcmp (SSDATA (ifname), "lo") == 0)
9193 res = Fcons (Fcons (intern ("running"),
9194 Fcons (intern ("loopback"),
9195 Fcons (intern ("up"), Qnil))), Qnil);
9196 /* 772 is what 3 different GNU/Linux systems report for
9197 the loopback interface. */
9198 res = Fcons (Fcons (make_number (772),
9199 Fmake_vector (make_number (6),
9200 make_number (0))),
9201 res);
9202 sa.sin_addr.s_addr = sys_inet_addr ("255.0.0.0");
9203 res = Fcons (conv_sockaddr_to_lisp ((struct sockaddr *) &sa,
9204 sizeof (struct sockaddr)),
9205 res);
9206 sa.sin_addr.s_addr = sys_inet_addr ("0.0.0.0");
9207 res = Fcons (conv_sockaddr_to_lisp ((struct sockaddr *) &sa,
9208 sizeof (struct sockaddr)),
9209 res);
9210 sa.sin_addr.s_addr = sys_inet_addr ("127.0.0.1");
9211 res = Fcons (conv_sockaddr_to_lisp ((struct sockaddr *) &sa,
9212 sizeof (struct sockaddr)),
9213 res);
9219 done:
9220 xfree (ainfo);
9221 return res;
9224 Lisp_Object
9225 network_interface_list (void)
9227 return network_interface_get_info (Qnil);
9230 Lisp_Object
9231 network_interface_info (Lisp_Object ifname)
9233 CHECK_STRING (ifname);
9234 return network_interface_get_info (ifname);
9238 /* The Windows CRT functions are "optimized for speed", so they don't
9239 check for timezone and DST changes if they were last called less
9240 than 1 minute ago (see http://support.microsoft.com/kb/821231). So
9241 all Emacs features that repeatedly call time functions (e.g.,
9242 display-time) are in real danger of missing timezone and DST
9243 changes. Calling tzset before each localtime call fixes that. */
9244 struct tm *
9245 sys_localtime (const time_t *t)
9247 tzset ();
9248 return localtime (t);
9253 /* Try loading LIBRARY_ID from the file(s) specified in
9254 Vdynamic_library_alist. If the library is loaded successfully,
9255 return the handle of the DLL, and record the filename in the
9256 property :loaded-from of LIBRARY_ID. If the library could not be
9257 found, or when it was already loaded (because the handle is not
9258 recorded anywhere, and so is lost after use), return NULL.
9260 We could also save the handle in :loaded-from, but currently
9261 there's no use case for it. */
9262 HMODULE
9263 w32_delayed_load (Lisp_Object library_id)
9265 HMODULE dll_handle = NULL;
9267 CHECK_SYMBOL (library_id);
9269 if (CONSP (Vdynamic_library_alist)
9270 && NILP (Fassq (library_id, Vlibrary_cache)))
9272 Lisp_Object found = Qnil;
9273 Lisp_Object dlls = Fassq (library_id, Vdynamic_library_alist);
9275 if (CONSP (dlls))
9276 for (dlls = XCDR (dlls); CONSP (dlls); dlls = XCDR (dlls))
9278 Lisp_Object dll = XCAR (dlls);
9279 char name[MAX_UTF8_PATH];
9280 DWORD res = -1;
9282 CHECK_STRING (dll);
9283 dll = ENCODE_FILE (dll);
9284 if (w32_unicode_filenames)
9286 wchar_t name_w[MAX_PATH];
9288 filename_to_utf16 (SSDATA (dll), name_w);
9289 dll_handle = LoadLibraryW (name_w);
9290 if (dll_handle)
9292 res = GetModuleFileNameW (dll_handle, name_w,
9293 sizeof (name_w));
9294 if (res > 0)
9295 filename_from_utf16 (name_w, name);
9298 else
9300 char name_a[MAX_PATH];
9302 filename_to_ansi (SSDATA (dll), name_a);
9303 dll_handle = LoadLibraryA (name_a);
9304 if (dll_handle)
9306 res = GetModuleFileNameA (dll_handle, name_a,
9307 sizeof (name_a));
9308 if (res > 0)
9309 filename_from_ansi (name_a, name);
9312 if (dll_handle)
9314 ptrdiff_t len = strlen (name);
9315 found = Fcons (dll,
9316 (res > 0)
9317 /* Possibly truncated */
9318 ? make_specified_string (name, -1, len, 1)
9319 : Qnil);
9320 /* This prevents thread start and end notifications
9321 from being sent to the DLL, for every thread we
9322 start. We don't need those notifications because
9323 threads we create never use any of these DLLs, only
9324 the main thread uses them. This is supposed to
9325 speed up thread creation. */
9326 DisableThreadLibraryCalls (dll_handle);
9327 break;
9331 Fput (library_id, QCloaded_from, found);
9334 return dll_handle;
9338 void
9339 check_windows_init_file (void)
9341 /* A common indication that Emacs is not installed properly is when
9342 it cannot find the Windows installation file. If this file does
9343 not exist in the expected place, tell the user. */
9345 if (!noninteractive && !inhibit_window_system
9346 /* Vload_path is not yet initialized when we are loading
9347 loadup.el. */
9348 && NILP (Vpurify_flag))
9350 Lisp_Object init_file;
9351 int fd;
9353 /* Implementation note: this function runs early during Emacs
9354 startup, before startup.el is run. So Vload_path is still in
9355 its initial unibyte form, but it holds UTF-8 encoded file
9356 names, since init_callproc was already called. So we do not
9357 need to ENCODE_FILE here, but we do need to convert the file
9358 names from UTF-8 to ANSI. */
9359 init_file = build_string ("term/w32-win");
9360 fd = openp (Vload_path, init_file, Fget_load_suffixes (), NULL, Qnil, 0);
9361 if (fd < 0)
9363 Lisp_Object load_path_print = Fprin1_to_string (Vload_path, Qnil);
9364 char *init_file_name = SSDATA (init_file);
9365 char *load_path = SSDATA (load_path_print);
9366 char *buffer = alloca (1024
9367 + strlen (init_file_name)
9368 + strlen (load_path));
9369 char *msg = buffer;
9370 int needed;
9372 sprintf (buffer,
9373 "The Emacs Windows initialization file \"%s.el\" "
9374 "could not be found in your Emacs installation. "
9375 "Emacs checked the following directories for this file:\n"
9376 "\n%s\n\n"
9377 "When Emacs cannot find this file, it usually means that it "
9378 "was not installed properly, or its distribution file was "
9379 "not unpacked properly.\nSee the README.W32 file in the "
9380 "top-level Emacs directory for more information.",
9381 init_file_name, load_path);
9382 needed = pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags,
9383 buffer, -1, NULL, 0);
9384 if (needed > 0)
9386 wchar_t *msg_w = alloca ((needed + 1) * sizeof (wchar_t));
9388 pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags, buffer,
9389 -1, msg_w, needed);
9390 needed = pWideCharToMultiByte (CP_ACP, 0, msg_w, -1,
9391 NULL, 0, NULL, NULL);
9392 if (needed > 0)
9394 char *msg_a = alloca (needed + 1);
9396 pWideCharToMultiByte (CP_ACP, 0, msg_w, -1, msg_a, needed,
9397 NULL, NULL);
9398 msg = msg_a;
9401 MessageBox (NULL,
9402 msg,
9403 "Emacs Abort Dialog",
9404 MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL);
9405 /* Use the low-level system abort. */
9406 abort ();
9408 else
9410 _close (fd);
9415 void
9416 term_ntproc (int ignored)
9418 (void)ignored;
9420 term_timers ();
9422 /* shutdown the socket interface if necessary */
9423 term_winsock ();
9425 term_w32select ();
9428 void
9429 init_ntproc (int dumping)
9431 sigset_t initial_mask = 0;
9433 /* Initialize the socket interface now if available and requested by
9434 the user by defining PRELOAD_WINSOCK; otherwise loading will be
9435 delayed until open-network-stream is called (w32-has-winsock can
9436 also be used to dynamically load or reload winsock).
9438 Conveniently, init_environment is called before us, so
9439 PRELOAD_WINSOCK can be set in the registry. */
9441 /* Always initialize this correctly. */
9442 winsock_lib = NULL;
9444 if (getenv ("PRELOAD_WINSOCK") != NULL)
9445 init_winsock (TRUE);
9447 /* Initial preparation for subprocess support: replace our standard
9448 handles with non-inheritable versions. */
9450 HANDLE parent;
9451 HANDLE stdin_save = INVALID_HANDLE_VALUE;
9452 HANDLE stdout_save = INVALID_HANDLE_VALUE;
9453 HANDLE stderr_save = INVALID_HANDLE_VALUE;
9455 parent = GetCurrentProcess ();
9457 /* ignore errors when duplicating and closing; typically the
9458 handles will be invalid when running as a gui program. */
9459 DuplicateHandle (parent,
9460 GetStdHandle (STD_INPUT_HANDLE),
9461 parent,
9462 &stdin_save,
9464 FALSE,
9465 DUPLICATE_SAME_ACCESS);
9467 DuplicateHandle (parent,
9468 GetStdHandle (STD_OUTPUT_HANDLE),
9469 parent,
9470 &stdout_save,
9472 FALSE,
9473 DUPLICATE_SAME_ACCESS);
9475 DuplicateHandle (parent,
9476 GetStdHandle (STD_ERROR_HANDLE),
9477 parent,
9478 &stderr_save,
9480 FALSE,
9481 DUPLICATE_SAME_ACCESS);
9483 fclose (stdin);
9484 fclose (stdout);
9485 fclose (stderr);
9487 if (stdin_save != INVALID_HANDLE_VALUE)
9488 _open_osfhandle ((intptr_t) stdin_save, O_TEXT);
9489 else
9490 _open ("nul", O_TEXT | O_NOINHERIT | O_RDONLY);
9491 _fdopen (0, "r");
9493 if (stdout_save != INVALID_HANDLE_VALUE)
9494 _open_osfhandle ((intptr_t) stdout_save, O_TEXT);
9495 else
9496 _open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY);
9497 _fdopen (1, "w");
9499 if (stderr_save != INVALID_HANDLE_VALUE)
9500 _open_osfhandle ((intptr_t) stderr_save, O_TEXT);
9501 else
9502 _open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY);
9503 _fdopen (2, "w");
9506 /* unfortunately, atexit depends on implementation of malloc */
9507 /* atexit (term_ntproc); */
9508 if (!dumping)
9510 /* Make sure we start with all signals unblocked. */
9511 sigprocmask (SIG_SETMASK, &initial_mask, NULL);
9512 signal (SIGABRT, term_ntproc);
9514 init_timers ();
9516 /* determine which drives are fixed, for GetCachedVolumeInformation */
9518 /* GetDriveType must have trailing backslash. */
9519 char drive[] = "A:\\";
9521 /* Loop over all possible drive letters */
9522 while (*drive <= 'Z')
9524 /* Record if this drive letter refers to a fixed drive. */
9525 fixed_drives[DRIVE_INDEX (*drive)] =
9526 (GetDriveType (drive) == DRIVE_FIXED);
9528 (*drive)++;
9531 /* Reset the volume info cache. */
9532 volume_cache = NULL;
9537 shutdown_handler ensures that buffers' autosave files are
9538 up to date when the user logs off, or the system shuts down.
9540 static BOOL WINAPI
9541 shutdown_handler (DWORD type)
9543 /* Ctrl-C and Ctrl-Break are already suppressed, so don't handle them. */
9544 if (type == CTRL_CLOSE_EVENT /* User closes console window. */
9545 || type == CTRL_LOGOFF_EVENT /* User logs off. */
9546 || type == CTRL_SHUTDOWN_EVENT) /* User shutsdown. */
9548 /* Shut down cleanly, making sure autosave files are up to date. */
9549 shut_down_emacs (0, Qnil);
9552 /* Allow other handlers to handle this signal. */
9553 return FALSE;
9556 /* On Windows 9X, load UNICOWS.DLL and return its handle, or die. On
9557 NT, return a handle to GDI32.DLL. */
9558 HANDLE
9559 maybe_load_unicows_dll (void)
9561 if (os_subtype == OS_9X)
9563 HANDLE ret = LoadLibrary ("Unicows.dll");
9564 if (ret)
9566 /* These two functions are present on Windows 9X as stubs
9567 that always fail. We need the real implementations from
9568 UNICOWS.DLL, so we must call these functions through
9569 pointers, and assign the correct addresses to these
9570 pointers at program startup (see emacs.c, which calls
9571 this function early on). */
9572 pMultiByteToWideChar =
9573 (MultiByteToWideChar_Proc)GetProcAddress (ret, "MultiByteToWideChar");
9574 pWideCharToMultiByte =
9575 (WideCharToMultiByte_Proc)GetProcAddress (ret, "WideCharToMultiByte");
9576 multiByteToWideCharFlags = MB_ERR_INVALID_CHARS;
9577 return ret;
9579 else
9581 int button;
9583 button = MessageBox (NULL,
9584 "Emacs cannot load the UNICOWS.DLL library.\n"
9585 "This library is essential for using Emacs\n"
9586 "on this system. You need to install it.\n\n"
9587 "Emacs will exit when you click OK.",
9588 "Emacs cannot load UNICOWS.DLL",
9589 MB_ICONERROR | MB_TASKMODAL
9590 | MB_SETFOREGROUND | MB_OK);
9591 switch (button)
9593 case IDOK:
9594 default:
9595 exit (1);
9599 else
9601 /* On NT family of Windows, these two functions are always
9602 linked in, so we just assign their addresses to the 2
9603 pointers; no need for the LoadLibrary dance. */
9604 pMultiByteToWideChar = MultiByteToWideChar;
9605 pWideCharToMultiByte = WideCharToMultiByte;
9606 /* On NT 4.0, though, MB_ERR_INVALID_CHARS is not supported. */
9607 if (w32_major_version < 5)
9608 multiByteToWideCharFlags = 0;
9609 else
9610 multiByteToWideCharFlags = MB_ERR_INVALID_CHARS;
9611 return LoadLibrary ("Gdi32.dll");
9616 globals_of_w32 is used to initialize those global variables that
9617 must always be initialized on startup even when the global variable
9618 initialized is non zero (see the function main in emacs.c).
9620 void
9621 globals_of_w32 (void)
9623 HMODULE kernel32 = GetModuleHandle ("kernel32.dll");
9625 get_process_times_fn = (GetProcessTimes_Proc)
9626 GetProcAddress (kernel32, "GetProcessTimes");
9628 DEFSYM (QCloaded_from, ":loaded-from");
9630 g_b_init_is_windows_9x = 0;
9631 g_b_init_open_process_token = 0;
9632 g_b_init_get_token_information = 0;
9633 g_b_init_lookup_account_sid = 0;
9634 g_b_init_get_sid_sub_authority = 0;
9635 g_b_init_get_sid_sub_authority_count = 0;
9636 g_b_init_get_security_info = 0;
9637 g_b_init_get_file_security_w = 0;
9638 g_b_init_get_file_security_a = 0;
9639 g_b_init_get_security_descriptor_owner = 0;
9640 g_b_init_get_security_descriptor_group = 0;
9641 g_b_init_is_valid_sid = 0;
9642 g_b_init_create_toolhelp32_snapshot = 0;
9643 g_b_init_process32_first = 0;
9644 g_b_init_process32_next = 0;
9645 g_b_init_open_thread_token = 0;
9646 g_b_init_impersonate_self = 0;
9647 g_b_init_revert_to_self = 0;
9648 g_b_init_get_process_memory_info = 0;
9649 g_b_init_get_process_working_set_size = 0;
9650 g_b_init_global_memory_status = 0;
9651 g_b_init_global_memory_status_ex = 0;
9652 g_b_init_equal_sid = 0;
9653 g_b_init_copy_sid = 0;
9654 g_b_init_get_length_sid = 0;
9655 g_b_init_get_native_system_info = 0;
9656 g_b_init_get_system_times = 0;
9657 g_b_init_create_symbolic_link_w = 0;
9658 g_b_init_create_symbolic_link_a = 0;
9659 g_b_init_get_security_descriptor_dacl = 0;
9660 g_b_init_convert_sd_to_sddl = 0;
9661 g_b_init_convert_sddl_to_sd = 0;
9662 g_b_init_is_valid_security_descriptor = 0;
9663 g_b_init_set_file_security_w = 0;
9664 g_b_init_set_file_security_a = 0;
9665 g_b_init_set_named_security_info_w = 0;
9666 g_b_init_set_named_security_info_a = 0;
9667 g_b_init_get_adapters_info = 0;
9668 g_b_init_compare_string_w = 0;
9669 g_b_init_debug_break_process = 0;
9670 num_of_processors = 0;
9671 /* The following sets a handler for shutdown notifications for
9672 console apps. This actually applies to Emacs in both console and
9673 GUI modes, since we had to fool windows into thinking emacs is a
9674 console application to get console mode to work. */
9675 SetConsoleCtrlHandler (shutdown_handler, TRUE);
9677 /* "None" is the default group name on standalone workstations. */
9678 strcpy (dflt_group_name, "None");
9680 /* Reset, in case it has some value inherited from dump time. */
9681 w32_stat_get_owner_group = 0;
9683 /* If w32_unicode_filenames is non-zero, we will be using Unicode
9684 (a.k.a. "wide") APIs to invoke functions that accept file
9685 names. */
9686 if (is_windows_9x ())
9687 w32_unicode_filenames = 0;
9688 else
9689 w32_unicode_filenames = 1;
9691 #ifdef HAVE_MODULES
9692 dynlib_reset_last_error ();
9693 #endif
9695 w32_crypto_hprov = (HCRYPTPROV)0;
9698 /* For make-serial-process */
9700 serial_open (Lisp_Object port_obj)
9702 char *port = SSDATA (port_obj);
9703 HANDLE hnd;
9704 child_process *cp;
9705 int fd = -1;
9707 hnd = CreateFile (port, GENERIC_READ | GENERIC_WRITE, 0, 0,
9708 OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
9709 if (hnd == INVALID_HANDLE_VALUE)
9710 error ("Could not open %s", port);
9711 fd = (int) _open_osfhandle ((intptr_t) hnd, 0);
9712 if (fd == -1)
9713 error ("Could not open %s", port);
9715 cp = new_child ();
9716 if (!cp)
9717 error ("Could not create child process");
9718 cp->fd = fd;
9719 cp->status = STATUS_READ_ACKNOWLEDGED;
9720 fd_info[ fd ].hnd = hnd;
9721 fd_info[ fd ].flags |=
9722 FILE_READ | FILE_WRITE | FILE_BINARY | FILE_SERIAL;
9723 if (fd_info[ fd ].cp != NULL)
9725 error ("fd_info[fd = %d] is already in use", fd);
9727 fd_info[ fd ].cp = cp;
9728 cp->ovl_read.hEvent = CreateEvent (NULL, TRUE, FALSE, NULL);
9729 if (cp->ovl_read.hEvent == NULL)
9730 error ("Could not create read event");
9731 cp->ovl_write.hEvent = CreateEvent (NULL, TRUE, FALSE, NULL);
9732 if (cp->ovl_write.hEvent == NULL)
9733 error ("Could not create write event");
9735 return fd;
9738 /* For serial-process-configure */
9739 void
9740 serial_configure (struct Lisp_Process *p, Lisp_Object contact)
9742 Lisp_Object childp2 = Qnil;
9743 Lisp_Object tem = Qnil;
9744 HANDLE hnd;
9745 DCB dcb;
9746 COMMTIMEOUTS ct;
9747 char summary[4] = "???"; /* This usually becomes "8N1". */
9749 if ((fd_info[ p->outfd ].flags & FILE_SERIAL) == 0)
9750 error ("Not a serial process");
9751 hnd = fd_info[ p->outfd ].hnd;
9753 childp2 = Fcopy_sequence (p->childp);
9755 /* Initialize timeouts for blocking read and blocking write. */
9756 if (!GetCommTimeouts (hnd, &ct))
9757 error ("GetCommTimeouts() failed");
9758 ct.ReadIntervalTimeout = 0;
9759 ct.ReadTotalTimeoutMultiplier = 0;
9760 ct.ReadTotalTimeoutConstant = 0;
9761 ct.WriteTotalTimeoutMultiplier = 0;
9762 ct.WriteTotalTimeoutConstant = 0;
9763 if (!SetCommTimeouts (hnd, &ct))
9764 error ("SetCommTimeouts() failed");
9765 /* Read port attributes and prepare default configuration. */
9766 memset (&dcb, 0, sizeof (dcb));
9767 dcb.DCBlength = sizeof (DCB);
9768 if (!GetCommState (hnd, &dcb))
9769 error ("GetCommState() failed");
9770 dcb.fBinary = TRUE;
9771 dcb.fNull = FALSE;
9772 dcb.fAbortOnError = FALSE;
9773 /* dcb.XonLim and dcb.XoffLim are set by GetCommState() */
9774 dcb.ErrorChar = 0;
9775 dcb.EofChar = 0;
9776 dcb.EvtChar = 0;
9778 /* Configure speed. */
9779 if (!NILP (Fplist_member (contact, QCspeed)))
9780 tem = Fplist_get (contact, QCspeed);
9781 else
9782 tem = Fplist_get (p->childp, QCspeed);
9783 CHECK_NUMBER (tem);
9784 dcb.BaudRate = XINT (tem);
9785 childp2 = Fplist_put (childp2, QCspeed, tem);
9787 /* Configure bytesize. */
9788 if (!NILP (Fplist_member (contact, QCbytesize)))
9789 tem = Fplist_get (contact, QCbytesize);
9790 else
9791 tem = Fplist_get (p->childp, QCbytesize);
9792 if (NILP (tem))
9793 tem = make_number (8);
9794 CHECK_NUMBER (tem);
9795 if (XINT (tem) != 7 && XINT (tem) != 8)
9796 error (":bytesize must be nil (8), 7, or 8");
9797 dcb.ByteSize = XINT (tem);
9798 summary[0] = XINT (tem) + '0';
9799 childp2 = Fplist_put (childp2, QCbytesize, tem);
9801 /* Configure parity. */
9802 if (!NILP (Fplist_member (contact, QCparity)))
9803 tem = Fplist_get (contact, QCparity);
9804 else
9805 tem = Fplist_get (p->childp, QCparity);
9806 if (!NILP (tem) && !EQ (tem, Qeven) && !EQ (tem, Qodd))
9807 error (":parity must be nil (no parity), `even', or `odd'");
9808 dcb.fParity = FALSE;
9809 dcb.Parity = NOPARITY;
9810 dcb.fErrorChar = FALSE;
9811 if (NILP (tem))
9813 summary[1] = 'N';
9815 else if (EQ (tem, Qeven))
9817 summary[1] = 'E';
9818 dcb.fParity = TRUE;
9819 dcb.Parity = EVENPARITY;
9820 dcb.fErrorChar = TRUE;
9822 else if (EQ (tem, Qodd))
9824 summary[1] = 'O';
9825 dcb.fParity = TRUE;
9826 dcb.Parity = ODDPARITY;
9827 dcb.fErrorChar = TRUE;
9829 childp2 = Fplist_put (childp2, QCparity, tem);
9831 /* Configure stopbits. */
9832 if (!NILP (Fplist_member (contact, QCstopbits)))
9833 tem = Fplist_get (contact, QCstopbits);
9834 else
9835 tem = Fplist_get (p->childp, QCstopbits);
9836 if (NILP (tem))
9837 tem = make_number (1);
9838 CHECK_NUMBER (tem);
9839 if (XINT (tem) != 1 && XINT (tem) != 2)
9840 error (":stopbits must be nil (1 stopbit), 1, or 2");
9841 summary[2] = XINT (tem) + '0';
9842 if (XINT (tem) == 1)
9843 dcb.StopBits = ONESTOPBIT;
9844 else if (XINT (tem) == 2)
9845 dcb.StopBits = TWOSTOPBITS;
9846 childp2 = Fplist_put (childp2, QCstopbits, tem);
9848 /* Configure flowcontrol. */
9849 if (!NILP (Fplist_member (contact, QCflowcontrol)))
9850 tem = Fplist_get (contact, QCflowcontrol);
9851 else
9852 tem = Fplist_get (p->childp, QCflowcontrol);
9853 if (!NILP (tem) && !EQ (tem, Qhw) && !EQ (tem, Qsw))
9854 error (":flowcontrol must be nil (no flowcontrol), `hw', or `sw'");
9855 dcb.fOutxCtsFlow = FALSE;
9856 dcb.fOutxDsrFlow = FALSE;
9857 dcb.fDtrControl = DTR_CONTROL_DISABLE;
9858 dcb.fDsrSensitivity = FALSE;
9859 dcb.fTXContinueOnXoff = FALSE;
9860 dcb.fOutX = FALSE;
9861 dcb.fInX = FALSE;
9862 dcb.fRtsControl = RTS_CONTROL_DISABLE;
9863 dcb.XonChar = 17; /* Control-Q */
9864 dcb.XoffChar = 19; /* Control-S */
9865 if (NILP (tem))
9867 /* Already configured. */
9869 else if (EQ (tem, Qhw))
9871 dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
9872 dcb.fOutxCtsFlow = TRUE;
9874 else if (EQ (tem, Qsw))
9876 dcb.fOutX = TRUE;
9877 dcb.fInX = TRUE;
9879 childp2 = Fplist_put (childp2, QCflowcontrol, tem);
9881 /* Activate configuration. */
9882 if (!SetCommState (hnd, &dcb))
9883 error ("SetCommState() failed");
9885 childp2 = Fplist_put (childp2, QCsummary, build_string (summary));
9886 pset_childp (p, childp2);
9889 /* For make-pipe-process */
9890 void
9891 register_aux_fd (int infd)
9893 child_process *cp;
9895 cp = new_child ();
9896 if (!cp)
9897 error ("Could not create child process");
9898 cp->fd = infd;
9899 cp->status = STATUS_READ_ACKNOWLEDGED;
9901 if (fd_info[ infd ].cp != NULL)
9903 error ("fd_info[fd = %d] is already in use", infd);
9905 fd_info[ infd ].cp = cp;
9906 fd_info[ infd ].hnd = (HANDLE) _get_osfhandle (infd);
9909 #ifdef HAVE_GNUTLS
9911 ssize_t
9912 emacs_gnutls_pull (gnutls_transport_ptr_t p, void* buf, size_t sz)
9914 int n, err;
9915 struct Lisp_Process *process = (struct Lisp_Process *)p;
9916 int fd = process->infd;
9918 n = sys_read (fd, (char*)buf, sz);
9920 if (n >= 0)
9921 return n;
9923 err = errno;
9925 /* Translate the WSAEWOULDBLOCK alias EWOULDBLOCK to EAGAIN. */
9926 if (err == EWOULDBLOCK)
9927 err = EAGAIN;
9929 emacs_gnutls_transport_set_errno (process->gnutls_state, err);
9931 return -1;
9934 ssize_t
9935 emacs_gnutls_push (gnutls_transport_ptr_t p, const void* buf, size_t sz)
9937 struct Lisp_Process *process = (struct Lisp_Process *)p;
9938 int fd = process->outfd;
9939 ssize_t n = sys_write (fd, buf, sz);
9941 /* 0 or more bytes written means everything went fine. */
9942 if (n >= 0)
9943 return n;
9945 /* Negative bytes written means we got an error in errno.
9946 Translate the WSAEWOULDBLOCK alias EWOULDBLOCK to EAGAIN. */
9947 emacs_gnutls_transport_set_errno (process->gnutls_state,
9948 errno == EWOULDBLOCK ? EAGAIN : errno);
9950 return -1;
9952 #endif /* HAVE_GNUTLS */
9954 /* end of w32.c */