Define _GNU_SOURCE in files delaying config.h
[emacs.git] / src / w32.c
blob6cb8e748bd52af21d1e8d34a827e70329885d25a
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 /* Enable GNU extensions in gnulib replacement headers. */
25 #define _GNU_SOURCE 1
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 /* must include CRT headers *before* config.h */
45 #include <config.h>
46 #include <mbstring.h> /* for _mbspbrk, _mbslwr, _mbsrchr, ... */
48 #undef access
49 #undef chdir
50 #undef chmod
51 #undef creat
52 #undef ctime
53 #undef fopen
54 #undef link
55 #undef mkdir
56 #undef open
57 #undef rename
58 #undef rmdir
59 #undef unlink
61 #undef close
62 #undef dup
63 #undef dup2
64 #undef pipe
65 #undef read
66 #undef write
68 #undef strerror
70 #undef localtime
72 char *sys_ctime (const time_t *);
73 int sys_chdir (const char *);
74 int sys_creat (const char *, int);
75 FILE *sys_fopen (const char *, const char *);
76 int sys_mkdir (const char *);
77 int sys_open (const char *, int, int);
78 int sys_rename (char const *, char const *);
79 int sys_rmdir (const char *);
80 int sys_close (int);
81 int sys_dup2 (int, int);
82 int sys_read (int, char *, unsigned int);
83 int sys_write (int, const void *, unsigned int);
84 struct tm *sys_localtime (const time_t *);
86 #ifdef HAVE_MODULES
87 extern void dynlib_reset_last_error (void);
88 #endif
90 #include "lisp.h"
91 #include "epaths.h" /* for PATH_EXEC */
93 #include <pwd.h>
94 #include <grp.h>
96 /* MinGW64 defines these in its _mingw.h. */
97 #ifndef _ANONYMOUS_UNION
98 # define _ANONYMOUS_UNION
99 #endif
100 #ifndef _ANONYMOUS_STRUCT
101 # define _ANONYMOUS_STRUCT
102 #endif
103 #include <windows.h>
104 /* Some versions of compiler define MEMORYSTATUSEX, some don't, so we
105 use a different name to avoid compilation problems. */
106 typedef struct _MEMORY_STATUS_EX {
107 DWORD dwLength;
108 DWORD dwMemoryLoad;
109 DWORDLONG ullTotalPhys;
110 DWORDLONG ullAvailPhys;
111 DWORDLONG ullTotalPageFile;
112 DWORDLONG ullAvailPageFile;
113 DWORDLONG ullTotalVirtual;
114 DWORDLONG ullAvailVirtual;
115 DWORDLONG ullAvailExtendedVirtual;
116 } MEMORY_STATUS_EX,*LPMEMORY_STATUS_EX;
118 /* These are here so that GDB would know about these data types. This
119 allows attaching GDB to Emacs when a fatal exception is triggered
120 and Windows pops up the "application needs to be closed" dialog.
121 At that point, _gnu_exception_handler, the top-level exception
122 handler installed by the MinGW startup code, is somewhere on the
123 call-stack of the main thread, so going to that call frame and
124 looking at the argument to _gnu_exception_handler, which is a
125 PEXCEPTION_POINTERS pointer, can reveal the exception code
126 (excptr->ExceptionRecord->ExceptionCode) and the address where the
127 exception happened (excptr->ExceptionRecord->ExceptionAddress), as
128 well as some additional information specific to the exception. */
129 PEXCEPTION_POINTERS excptr;
130 PEXCEPTION_RECORD excprec;
131 PCONTEXT ctxrec;
133 #include <lmcons.h>
134 #include <shlobj.h>
136 #include <tlhelp32.h>
137 #include <psapi.h>
138 #ifndef _MSC_VER
139 #include <w32api.h>
140 #endif
141 #if _WIN32_WINNT < 0x0500
142 #if !defined (__MINGW32__) || __W32API_MAJOR_VERSION < 3 || (__W32API_MAJOR_VERSION == 3 && __W32API_MINOR_VERSION < 15)
143 /* This either is not in psapi.h or guarded by higher value of
144 _WIN32_WINNT than what we use. w32api supplied with MinGW 3.15
145 defines it in psapi.h */
146 typedef struct _PROCESS_MEMORY_COUNTERS_EX {
147 DWORD cb;
148 DWORD PageFaultCount;
149 SIZE_T PeakWorkingSetSize;
150 SIZE_T WorkingSetSize;
151 SIZE_T QuotaPeakPagedPoolUsage;
152 SIZE_T QuotaPagedPoolUsage;
153 SIZE_T QuotaPeakNonPagedPoolUsage;
154 SIZE_T QuotaNonPagedPoolUsage;
155 SIZE_T PagefileUsage;
156 SIZE_T PeakPagefileUsage;
157 SIZE_T PrivateUsage;
158 } PROCESS_MEMORY_COUNTERS_EX,*PPROCESS_MEMORY_COUNTERS_EX;
159 #endif
160 #endif
162 #include <winioctl.h>
163 #include <aclapi.h>
164 #include <sddl.h>
166 #include <sys/acl.h>
167 #include <acl.h>
169 /* This is not in MinGW's sddl.h (but they are in MSVC headers), so we
170 define them by hand if not already defined. */
171 #ifndef SDDL_REVISION_1
172 #define SDDL_REVISION_1 1
173 #endif /* SDDL_REVISION_1 */
175 #if defined(_MSC_VER) || defined(MINGW_W64)
176 /* MSVC and MinGW64 don't provide the definition of
177 REPARSE_DATA_BUFFER and the associated macros, except on ntifs.h,
178 which cannot be included because it triggers conflicts with other
179 Windows API headers. So we define it here by hand. */
181 typedef struct _REPARSE_DATA_BUFFER {
182 ULONG ReparseTag;
183 USHORT ReparseDataLength;
184 USHORT Reserved;
185 union {
186 struct {
187 USHORT SubstituteNameOffset;
188 USHORT SubstituteNameLength;
189 USHORT PrintNameOffset;
190 USHORT PrintNameLength;
191 ULONG Flags;
192 WCHAR PathBuffer[1];
193 } SymbolicLinkReparseBuffer;
194 struct {
195 USHORT SubstituteNameOffset;
196 USHORT SubstituteNameLength;
197 USHORT PrintNameOffset;
198 USHORT PrintNameLength;
199 WCHAR PathBuffer[1];
200 } MountPointReparseBuffer;
201 struct {
202 UCHAR DataBuffer[1];
203 } GenericReparseBuffer;
204 } DUMMYUNIONNAME;
205 } REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
207 #ifndef FILE_DEVICE_FILE_SYSTEM
208 #define FILE_DEVICE_FILE_SYSTEM 9
209 #endif
210 #ifndef METHOD_BUFFERED
211 #define METHOD_BUFFERED 0
212 #endif
213 #ifndef FILE_ANY_ACCESS
214 #define FILE_ANY_ACCESS 0x00000000
215 #endif
216 #ifndef CTL_CODE
217 #define CTL_CODE(t,f,m,a) (((t)<<16)|((a)<<14)|((f)<<2)|(m))
218 #endif
219 /* MinGW64 defines FSCTL_GET_REPARSE_POINT on winioctl.h. */
220 #ifndef FSCTL_GET_REPARSE_POINT
221 #define FSCTL_GET_REPARSE_POINT \
222 CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS)
223 #endif
224 #endif
226 /* TCP connection support. */
227 #include <sys/socket.h>
228 #undef socket
229 #undef bind
230 #undef connect
231 #undef htons
232 #undef ntohs
233 #undef inet_addr
234 #undef gethostname
235 #undef gethostbyname
236 #undef getservbyname
237 #undef getpeername
238 #undef shutdown
239 #undef setsockopt
240 #undef listen
241 #undef getsockname
242 #undef accept
243 #undef recvfrom
244 #undef sendto
246 #include <iphlpapi.h> /* should be after winsock2.h */
248 #include <wincrypt.h>
250 #include <c-strcase.h>
251 #include <utimens.h> /* for fdutimens */
253 #include "w32.h"
254 #include <dirent.h>
255 #include "w32common.h"
256 #include "w32select.h"
257 #include "systime.h" /* for current_timespec, struct timespec */
258 #include "dispextern.h" /* for xstrcasecmp */
259 #include "coding.h" /* for Vlocale_coding_system */
261 #include "careadlinkat.h"
262 #include "allocator.h"
264 /* For Lisp_Process, serial_configure and serial_open. */
265 #include "process.h"
266 #include "systty.h"
268 typedef HRESULT (WINAPI * ShGetFolderPath_fn)
269 (IN HWND, IN int, IN HANDLE, IN DWORD, OUT char *);
271 static DWORD get_rid (PSID);
272 static int is_symlink (const char *);
273 static char * chase_symlinks (const char *);
274 static int enable_privilege (LPCTSTR, BOOL, TOKEN_PRIVILEGES *);
275 static int restore_privilege (TOKEN_PRIVILEGES *);
276 static BOOL WINAPI revert_to_self (void);
278 static int sys_access (const char *, int);
279 extern void *e_malloc (size_t);
280 extern int sys_select (int, SELECT_TYPE *, SELECT_TYPE *, SELECT_TYPE *,
281 struct timespec *, void *);
282 extern int sys_dup (int);
287 /* Initialization states.
289 WARNING: If you add any more such variables for additional APIs,
290 you MUST add initialization for them to globals_of_w32
291 below. This is because these variables might get set
292 to non-NULL values during dumping, but the dumped Emacs
293 cannot reuse those values, because it could be run on a
294 different version of the OS, where API addresses are
295 different. */
296 static BOOL g_b_init_is_windows_9x;
297 static BOOL g_b_init_open_process_token;
298 static BOOL g_b_init_get_token_information;
299 static BOOL g_b_init_lookup_account_sid;
300 static BOOL g_b_init_get_sid_sub_authority;
301 static BOOL g_b_init_get_sid_sub_authority_count;
302 static BOOL g_b_init_get_security_info;
303 static BOOL g_b_init_get_file_security_w;
304 static BOOL g_b_init_get_file_security_a;
305 static BOOL g_b_init_get_security_descriptor_owner;
306 static BOOL g_b_init_get_security_descriptor_group;
307 static BOOL g_b_init_is_valid_sid;
308 static BOOL g_b_init_create_toolhelp32_snapshot;
309 static BOOL g_b_init_process32_first;
310 static BOOL g_b_init_process32_next;
311 static BOOL g_b_init_open_thread_token;
312 static BOOL g_b_init_impersonate_self;
313 static BOOL g_b_init_revert_to_self;
314 static BOOL g_b_init_get_process_memory_info;
315 static BOOL g_b_init_get_process_working_set_size;
316 static BOOL g_b_init_global_memory_status;
317 static BOOL g_b_init_global_memory_status_ex;
318 static BOOL g_b_init_get_length_sid;
319 static BOOL g_b_init_equal_sid;
320 static BOOL g_b_init_copy_sid;
321 static BOOL g_b_init_get_native_system_info;
322 static BOOL g_b_init_get_system_times;
323 static BOOL g_b_init_create_symbolic_link_w;
324 static BOOL g_b_init_create_symbolic_link_a;
325 static BOOL g_b_init_get_security_descriptor_dacl;
326 static BOOL g_b_init_convert_sd_to_sddl;
327 static BOOL g_b_init_convert_sddl_to_sd;
328 static BOOL g_b_init_is_valid_security_descriptor;
329 static BOOL g_b_init_set_file_security_w;
330 static BOOL g_b_init_set_file_security_a;
331 static BOOL g_b_init_set_named_security_info_w;
332 static BOOL g_b_init_set_named_security_info_a;
333 static BOOL g_b_init_get_adapters_info;
335 BOOL g_b_init_compare_string_w;
338 BEGIN: Wrapper functions around OpenProcessToken
339 and other functions in advapi32.dll that are only
340 supported in Windows NT / 2k / XP
342 /* ** Function pointer typedefs ** */
343 typedef BOOL (WINAPI * OpenProcessToken_Proc) (
344 HANDLE ProcessHandle,
345 DWORD DesiredAccess,
346 PHANDLE TokenHandle);
347 typedef BOOL (WINAPI * GetTokenInformation_Proc) (
348 HANDLE TokenHandle,
349 TOKEN_INFORMATION_CLASS TokenInformationClass,
350 LPVOID TokenInformation,
351 DWORD TokenInformationLength,
352 PDWORD ReturnLength);
353 typedef BOOL (WINAPI * GetProcessTimes_Proc) (
354 HANDLE process_handle,
355 LPFILETIME creation_time,
356 LPFILETIME exit_time,
357 LPFILETIME kernel_time,
358 LPFILETIME user_time);
360 GetProcessTimes_Proc get_process_times_fn = NULL;
362 #ifdef _UNICODE
363 const char * const LookupAccountSid_Name = "LookupAccountSidW";
364 #else
365 const char * const LookupAccountSid_Name = "LookupAccountSidA";
366 #endif
367 typedef BOOL (WINAPI * LookupAccountSid_Proc) (
368 LPCTSTR lpSystemName,
369 PSID Sid,
370 LPTSTR Name,
371 LPDWORD cbName,
372 LPTSTR DomainName,
373 LPDWORD cbDomainName,
374 PSID_NAME_USE peUse);
375 typedef PDWORD (WINAPI * GetSidSubAuthority_Proc) (
376 PSID pSid,
377 DWORD n);
378 typedef PUCHAR (WINAPI * GetSidSubAuthorityCount_Proc) (
379 PSID pSid);
380 typedef DWORD (WINAPI * GetSecurityInfo_Proc) (
381 HANDLE handle,
382 SE_OBJECT_TYPE ObjectType,
383 SECURITY_INFORMATION SecurityInfo,
384 PSID *ppsidOwner,
385 PSID *ppsidGroup,
386 PACL *ppDacl,
387 PACL *ppSacl,
388 PSECURITY_DESCRIPTOR *ppSecurityDescriptor);
389 typedef BOOL (WINAPI * GetFileSecurityW_Proc) (
390 LPCWSTR lpFileName,
391 SECURITY_INFORMATION RequestedInformation,
392 PSECURITY_DESCRIPTOR pSecurityDescriptor,
393 DWORD nLength,
394 LPDWORD lpnLengthNeeded);
395 typedef BOOL (WINAPI * GetFileSecurityA_Proc) (
396 LPCSTR lpFileName,
397 SECURITY_INFORMATION RequestedInformation,
398 PSECURITY_DESCRIPTOR pSecurityDescriptor,
399 DWORD nLength,
400 LPDWORD lpnLengthNeeded);
401 typedef BOOL (WINAPI *SetFileSecurityW_Proc) (
402 LPCWSTR lpFileName,
403 SECURITY_INFORMATION SecurityInformation,
404 PSECURITY_DESCRIPTOR pSecurityDescriptor);
405 typedef BOOL (WINAPI *SetFileSecurityA_Proc) (
406 LPCSTR lpFileName,
407 SECURITY_INFORMATION SecurityInformation,
408 PSECURITY_DESCRIPTOR pSecurityDescriptor);
409 typedef DWORD (WINAPI *SetNamedSecurityInfoW_Proc) (
410 LPCWSTR lpObjectName,
411 SE_OBJECT_TYPE ObjectType,
412 SECURITY_INFORMATION SecurityInformation,
413 PSID psidOwner,
414 PSID psidGroup,
415 PACL pDacl,
416 PACL pSacl);
417 typedef DWORD (WINAPI *SetNamedSecurityInfoA_Proc) (
418 LPCSTR lpObjectName,
419 SE_OBJECT_TYPE ObjectType,
420 SECURITY_INFORMATION SecurityInformation,
421 PSID psidOwner,
422 PSID psidGroup,
423 PACL pDacl,
424 PACL pSacl);
425 typedef BOOL (WINAPI * GetSecurityDescriptorOwner_Proc) (
426 PSECURITY_DESCRIPTOR pSecurityDescriptor,
427 PSID *pOwner,
428 LPBOOL lpbOwnerDefaulted);
429 typedef BOOL (WINAPI * GetSecurityDescriptorGroup_Proc) (
430 PSECURITY_DESCRIPTOR pSecurityDescriptor,
431 PSID *pGroup,
432 LPBOOL lpbGroupDefaulted);
433 typedef BOOL (WINAPI *GetSecurityDescriptorDacl_Proc) (
434 PSECURITY_DESCRIPTOR pSecurityDescriptor,
435 LPBOOL lpbDaclPresent,
436 PACL *pDacl,
437 LPBOOL lpbDaclDefaulted);
438 typedef BOOL (WINAPI * IsValidSid_Proc) (
439 PSID sid);
440 typedef HANDLE (WINAPI * CreateToolhelp32Snapshot_Proc) (
441 DWORD dwFlags,
442 DWORD th32ProcessID);
443 typedef BOOL (WINAPI * Process32First_Proc) (
444 HANDLE hSnapshot,
445 LPPROCESSENTRY32 lppe);
446 typedef BOOL (WINAPI * Process32Next_Proc) (
447 HANDLE hSnapshot,
448 LPPROCESSENTRY32 lppe);
449 typedef BOOL (WINAPI * OpenThreadToken_Proc) (
450 HANDLE ThreadHandle,
451 DWORD DesiredAccess,
452 BOOL OpenAsSelf,
453 PHANDLE TokenHandle);
454 typedef BOOL (WINAPI * ImpersonateSelf_Proc) (
455 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel);
456 typedef BOOL (WINAPI * RevertToSelf_Proc) (void);
457 typedef BOOL (WINAPI * GetProcessMemoryInfo_Proc) (
458 HANDLE Process,
459 PPROCESS_MEMORY_COUNTERS ppsmemCounters,
460 DWORD cb);
461 typedef BOOL (WINAPI * GetProcessWorkingSetSize_Proc) (
462 HANDLE hProcess,
463 PSIZE_T lpMinimumWorkingSetSize,
464 PSIZE_T lpMaximumWorkingSetSize);
465 typedef BOOL (WINAPI * GlobalMemoryStatus_Proc) (
466 LPMEMORYSTATUS lpBuffer);
467 typedef BOOL (WINAPI * GlobalMemoryStatusEx_Proc) (
468 LPMEMORY_STATUS_EX lpBuffer);
469 typedef BOOL (WINAPI * CopySid_Proc) (
470 DWORD nDestinationSidLength,
471 PSID pDestinationSid,
472 PSID pSourceSid);
473 typedef BOOL (WINAPI * EqualSid_Proc) (
474 PSID pSid1,
475 PSID pSid2);
476 typedef DWORD (WINAPI * GetLengthSid_Proc) (
477 PSID pSid);
478 typedef void (WINAPI * GetNativeSystemInfo_Proc) (
479 LPSYSTEM_INFO lpSystemInfo);
480 typedef BOOL (WINAPI * GetSystemTimes_Proc) (
481 LPFILETIME lpIdleTime,
482 LPFILETIME lpKernelTime,
483 LPFILETIME lpUserTime);
484 typedef BOOLEAN (WINAPI *CreateSymbolicLinkW_Proc) (
485 LPCWSTR lpSymlinkFileName,
486 LPCWSTR lpTargetFileName,
487 DWORD dwFlags);
488 typedef BOOLEAN (WINAPI *CreateSymbolicLinkA_Proc) (
489 LPCSTR lpSymlinkFileName,
490 LPCSTR lpTargetFileName,
491 DWORD dwFlags);
492 typedef BOOL (WINAPI *ConvertStringSecurityDescriptorToSecurityDescriptor_Proc) (
493 LPCTSTR StringSecurityDescriptor,
494 DWORD StringSDRevision,
495 PSECURITY_DESCRIPTOR *SecurityDescriptor,
496 PULONG SecurityDescriptorSize);
497 typedef BOOL (WINAPI *ConvertSecurityDescriptorToStringSecurityDescriptor_Proc) (
498 PSECURITY_DESCRIPTOR SecurityDescriptor,
499 DWORD RequestedStringSDRevision,
500 SECURITY_INFORMATION SecurityInformation,
501 LPTSTR *StringSecurityDescriptor,
502 PULONG StringSecurityDescriptorLen);
503 typedef BOOL (WINAPI *IsValidSecurityDescriptor_Proc) (PSECURITY_DESCRIPTOR);
504 typedef DWORD (WINAPI *GetAdaptersInfo_Proc) (
505 PIP_ADAPTER_INFO pAdapterInfo,
506 PULONG pOutBufLen);
508 int (WINAPI *pMultiByteToWideChar)(UINT,DWORD,LPCSTR,int,LPWSTR,int);
509 int (WINAPI *pWideCharToMultiByte)(UINT,DWORD,LPCWSTR,int,LPSTR,int,LPCSTR,LPBOOL);
510 DWORD multiByteToWideCharFlags;
512 /* ** A utility function ** */
513 static BOOL
514 is_windows_9x (void)
516 static BOOL s_b_ret = 0;
517 OSVERSIONINFO os_ver;
518 if (g_b_init_is_windows_9x == 0)
520 g_b_init_is_windows_9x = 1;
521 ZeroMemory (&os_ver, sizeof (OSVERSIONINFO));
522 os_ver.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
523 if (GetVersionEx (&os_ver))
525 s_b_ret = (os_ver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS);
528 return s_b_ret;
531 static Lisp_Object ltime (ULONGLONG);
533 /* Get total user and system times for get-internal-run-time.
534 Returns a list of integers if the times are provided by the OS
535 (NT derivatives), otherwise it returns the result of current-time. */
536 Lisp_Object w32_get_internal_run_time (void);
538 Lisp_Object
539 w32_get_internal_run_time (void)
541 if (get_process_times_fn)
543 FILETIME create, exit, kernel, user;
544 HANDLE proc = GetCurrentProcess ();
545 if ((*get_process_times_fn) (proc, &create, &exit, &kernel, &user))
547 LARGE_INTEGER user_int, kernel_int, total;
548 user_int.LowPart = user.dwLowDateTime;
549 user_int.HighPart = user.dwHighDateTime;
550 kernel_int.LowPart = kernel.dwLowDateTime;
551 kernel_int.HighPart = kernel.dwHighDateTime;
552 total.QuadPart = user_int.QuadPart + kernel_int.QuadPart;
553 return ltime (total.QuadPart);
557 return Fcurrent_time ();
560 /* ** The wrapper functions ** */
562 static BOOL WINAPI
563 open_process_token (HANDLE ProcessHandle,
564 DWORD DesiredAccess,
565 PHANDLE TokenHandle)
567 static OpenProcessToken_Proc s_pfn_Open_Process_Token = NULL;
568 HMODULE hm_advapi32 = NULL;
569 if (is_windows_9x () == TRUE)
571 return FALSE;
573 if (g_b_init_open_process_token == 0)
575 g_b_init_open_process_token = 1;
576 hm_advapi32 = LoadLibrary ("Advapi32.dll");
577 s_pfn_Open_Process_Token =
578 (OpenProcessToken_Proc) GetProcAddress (hm_advapi32, "OpenProcessToken");
580 if (s_pfn_Open_Process_Token == NULL)
582 return FALSE;
584 return (
585 s_pfn_Open_Process_Token (
586 ProcessHandle,
587 DesiredAccess,
588 TokenHandle)
592 static BOOL WINAPI
593 get_token_information (HANDLE TokenHandle,
594 TOKEN_INFORMATION_CLASS TokenInformationClass,
595 LPVOID TokenInformation,
596 DWORD TokenInformationLength,
597 PDWORD ReturnLength)
599 static GetTokenInformation_Proc s_pfn_Get_Token_Information = NULL;
600 HMODULE hm_advapi32 = NULL;
601 if (is_windows_9x () == TRUE)
603 return FALSE;
605 if (g_b_init_get_token_information == 0)
607 g_b_init_get_token_information = 1;
608 hm_advapi32 = LoadLibrary ("Advapi32.dll");
609 s_pfn_Get_Token_Information =
610 (GetTokenInformation_Proc) GetProcAddress (hm_advapi32, "GetTokenInformation");
612 if (s_pfn_Get_Token_Information == NULL)
614 return FALSE;
616 return (
617 s_pfn_Get_Token_Information (
618 TokenHandle,
619 TokenInformationClass,
620 TokenInformation,
621 TokenInformationLength,
622 ReturnLength)
626 static BOOL WINAPI
627 lookup_account_sid (LPCTSTR lpSystemName,
628 PSID Sid,
629 LPTSTR Name,
630 LPDWORD cbName,
631 LPTSTR DomainName,
632 LPDWORD cbDomainName,
633 PSID_NAME_USE peUse)
635 static LookupAccountSid_Proc s_pfn_Lookup_Account_Sid = NULL;
636 HMODULE hm_advapi32 = NULL;
637 if (is_windows_9x () == TRUE)
639 return FALSE;
641 if (g_b_init_lookup_account_sid == 0)
643 g_b_init_lookup_account_sid = 1;
644 hm_advapi32 = LoadLibrary ("Advapi32.dll");
645 s_pfn_Lookup_Account_Sid =
646 (LookupAccountSid_Proc) GetProcAddress (hm_advapi32, LookupAccountSid_Name);
648 if (s_pfn_Lookup_Account_Sid == NULL)
650 return FALSE;
652 return (
653 s_pfn_Lookup_Account_Sid (
654 lpSystemName,
655 Sid,
656 Name,
657 cbName,
658 DomainName,
659 cbDomainName,
660 peUse)
664 static PDWORD WINAPI
665 get_sid_sub_authority (PSID pSid, DWORD n)
667 static GetSidSubAuthority_Proc s_pfn_Get_Sid_Sub_Authority = NULL;
668 static DWORD zero = 0U;
669 HMODULE hm_advapi32 = NULL;
670 if (is_windows_9x () == TRUE)
672 return &zero;
674 if (g_b_init_get_sid_sub_authority == 0)
676 g_b_init_get_sid_sub_authority = 1;
677 hm_advapi32 = LoadLibrary ("Advapi32.dll");
678 s_pfn_Get_Sid_Sub_Authority =
679 (GetSidSubAuthority_Proc) GetProcAddress (
680 hm_advapi32, "GetSidSubAuthority");
682 if (s_pfn_Get_Sid_Sub_Authority == NULL)
684 return &zero;
686 return (s_pfn_Get_Sid_Sub_Authority (pSid, n));
689 static PUCHAR WINAPI
690 get_sid_sub_authority_count (PSID pSid)
692 static GetSidSubAuthorityCount_Proc s_pfn_Get_Sid_Sub_Authority_Count = NULL;
693 static UCHAR zero = 0U;
694 HMODULE hm_advapi32 = NULL;
695 if (is_windows_9x () == TRUE)
697 return &zero;
699 if (g_b_init_get_sid_sub_authority_count == 0)
701 g_b_init_get_sid_sub_authority_count = 1;
702 hm_advapi32 = LoadLibrary ("Advapi32.dll");
703 s_pfn_Get_Sid_Sub_Authority_Count =
704 (GetSidSubAuthorityCount_Proc) GetProcAddress (
705 hm_advapi32, "GetSidSubAuthorityCount");
707 if (s_pfn_Get_Sid_Sub_Authority_Count == NULL)
709 return &zero;
711 return (s_pfn_Get_Sid_Sub_Authority_Count (pSid));
714 static DWORD WINAPI
715 get_security_info (HANDLE handle,
716 SE_OBJECT_TYPE ObjectType,
717 SECURITY_INFORMATION SecurityInfo,
718 PSID *ppsidOwner,
719 PSID *ppsidGroup,
720 PACL *ppDacl,
721 PACL *ppSacl,
722 PSECURITY_DESCRIPTOR *ppSecurityDescriptor)
724 static GetSecurityInfo_Proc s_pfn_Get_Security_Info = NULL;
725 HMODULE hm_advapi32 = NULL;
726 if (is_windows_9x () == TRUE)
728 return FALSE;
730 if (g_b_init_get_security_info == 0)
732 g_b_init_get_security_info = 1;
733 hm_advapi32 = LoadLibrary ("Advapi32.dll");
734 s_pfn_Get_Security_Info =
735 (GetSecurityInfo_Proc) GetProcAddress (
736 hm_advapi32, "GetSecurityInfo");
738 if (s_pfn_Get_Security_Info == NULL)
740 return FALSE;
742 return (s_pfn_Get_Security_Info (handle, ObjectType, SecurityInfo,
743 ppsidOwner, ppsidGroup, ppDacl, ppSacl,
744 ppSecurityDescriptor));
747 static BOOL WINAPI
748 get_file_security (const char *lpFileName,
749 SECURITY_INFORMATION RequestedInformation,
750 PSECURITY_DESCRIPTOR pSecurityDescriptor,
751 DWORD nLength,
752 LPDWORD lpnLengthNeeded)
754 static GetFileSecurityA_Proc s_pfn_Get_File_SecurityA = NULL;
755 static GetFileSecurityW_Proc s_pfn_Get_File_SecurityW = NULL;
756 HMODULE hm_advapi32 = NULL;
757 if (is_windows_9x () == TRUE)
759 errno = ENOTSUP;
760 return FALSE;
762 if (w32_unicode_filenames)
764 wchar_t filename_w[MAX_PATH];
766 if (g_b_init_get_file_security_w == 0)
768 g_b_init_get_file_security_w = 1;
769 hm_advapi32 = LoadLibrary ("Advapi32.dll");
770 s_pfn_Get_File_SecurityW =
771 (GetFileSecurityW_Proc) GetProcAddress (hm_advapi32,
772 "GetFileSecurityW");
774 if (s_pfn_Get_File_SecurityW == NULL)
776 errno = ENOTSUP;
777 return FALSE;
779 filename_to_utf16 (lpFileName, filename_w);
780 return (s_pfn_Get_File_SecurityW (filename_w, RequestedInformation,
781 pSecurityDescriptor, nLength,
782 lpnLengthNeeded));
784 else
786 char filename_a[MAX_PATH];
788 if (g_b_init_get_file_security_a == 0)
790 g_b_init_get_file_security_a = 1;
791 hm_advapi32 = LoadLibrary ("Advapi32.dll");
792 s_pfn_Get_File_SecurityA =
793 (GetFileSecurityA_Proc) GetProcAddress (hm_advapi32,
794 "GetFileSecurityA");
796 if (s_pfn_Get_File_SecurityA == NULL)
798 errno = ENOTSUP;
799 return FALSE;
801 filename_to_ansi (lpFileName, filename_a);
802 return (s_pfn_Get_File_SecurityA (filename_a, RequestedInformation,
803 pSecurityDescriptor, nLength,
804 lpnLengthNeeded));
808 static BOOL WINAPI
809 set_file_security (const char *lpFileName,
810 SECURITY_INFORMATION SecurityInformation,
811 PSECURITY_DESCRIPTOR pSecurityDescriptor)
813 static SetFileSecurityW_Proc s_pfn_Set_File_SecurityW = NULL;
814 static SetFileSecurityA_Proc s_pfn_Set_File_SecurityA = NULL;
815 HMODULE hm_advapi32 = NULL;
816 if (is_windows_9x () == TRUE)
818 errno = ENOTSUP;
819 return FALSE;
821 if (w32_unicode_filenames)
823 wchar_t filename_w[MAX_PATH];
825 if (g_b_init_set_file_security_w == 0)
827 g_b_init_set_file_security_w = 1;
828 hm_advapi32 = LoadLibrary ("Advapi32.dll");
829 s_pfn_Set_File_SecurityW =
830 (SetFileSecurityW_Proc) GetProcAddress (hm_advapi32,
831 "SetFileSecurityW");
833 if (s_pfn_Set_File_SecurityW == NULL)
835 errno = ENOTSUP;
836 return FALSE;
838 filename_to_utf16 (lpFileName, filename_w);
839 return (s_pfn_Set_File_SecurityW (filename_w, SecurityInformation,
840 pSecurityDescriptor));
842 else
844 char filename_a[MAX_PATH];
846 if (g_b_init_set_file_security_a == 0)
848 g_b_init_set_file_security_a = 1;
849 hm_advapi32 = LoadLibrary ("Advapi32.dll");
850 s_pfn_Set_File_SecurityA =
851 (SetFileSecurityA_Proc) GetProcAddress (hm_advapi32,
852 "SetFileSecurityA");
854 if (s_pfn_Set_File_SecurityA == NULL)
856 errno = ENOTSUP;
857 return FALSE;
859 filename_to_ansi (lpFileName, filename_a);
860 return (s_pfn_Set_File_SecurityA (filename_a, SecurityInformation,
861 pSecurityDescriptor));
865 static DWORD WINAPI
866 set_named_security_info (LPCTSTR lpObjectName,
867 SE_OBJECT_TYPE ObjectType,
868 SECURITY_INFORMATION SecurityInformation,
869 PSID psidOwner,
870 PSID psidGroup,
871 PACL pDacl,
872 PACL pSacl)
874 static SetNamedSecurityInfoW_Proc s_pfn_Set_Named_Security_InfoW = NULL;
875 static SetNamedSecurityInfoA_Proc s_pfn_Set_Named_Security_InfoA = NULL;
876 HMODULE hm_advapi32 = NULL;
877 if (is_windows_9x () == TRUE)
879 errno = ENOTSUP;
880 return ENOTSUP;
882 if (w32_unicode_filenames)
884 wchar_t filename_w[MAX_PATH];
886 if (g_b_init_set_named_security_info_w == 0)
888 g_b_init_set_named_security_info_w = 1;
889 hm_advapi32 = LoadLibrary ("Advapi32.dll");
890 s_pfn_Set_Named_Security_InfoW =
891 (SetNamedSecurityInfoW_Proc) GetProcAddress (hm_advapi32,
892 "SetNamedSecurityInfoW");
894 if (s_pfn_Set_Named_Security_InfoW == NULL)
896 errno = ENOTSUP;
897 return ENOTSUP;
899 filename_to_utf16 (lpObjectName, filename_w);
900 return (s_pfn_Set_Named_Security_InfoW (filename_w, ObjectType,
901 SecurityInformation, psidOwner,
902 psidGroup, pDacl, pSacl));
904 else
906 char filename_a[MAX_PATH];
908 if (g_b_init_set_named_security_info_a == 0)
910 g_b_init_set_named_security_info_a = 1;
911 hm_advapi32 = LoadLibrary ("Advapi32.dll");
912 s_pfn_Set_Named_Security_InfoA =
913 (SetNamedSecurityInfoA_Proc) GetProcAddress (hm_advapi32,
914 "SetNamedSecurityInfoA");
916 if (s_pfn_Set_Named_Security_InfoA == NULL)
918 errno = ENOTSUP;
919 return ENOTSUP;
921 filename_to_ansi (lpObjectName, filename_a);
922 return (s_pfn_Set_Named_Security_InfoA (filename_a, ObjectType,
923 SecurityInformation, psidOwner,
924 psidGroup, pDacl, pSacl));
928 static BOOL WINAPI
929 get_security_descriptor_owner (PSECURITY_DESCRIPTOR pSecurityDescriptor,
930 PSID *pOwner,
931 LPBOOL lpbOwnerDefaulted)
933 static GetSecurityDescriptorOwner_Proc s_pfn_Get_Security_Descriptor_Owner = NULL;
934 HMODULE hm_advapi32 = NULL;
935 if (is_windows_9x () == TRUE)
937 errno = ENOTSUP;
938 return FALSE;
940 if (g_b_init_get_security_descriptor_owner == 0)
942 g_b_init_get_security_descriptor_owner = 1;
943 hm_advapi32 = LoadLibrary ("Advapi32.dll");
944 s_pfn_Get_Security_Descriptor_Owner =
945 (GetSecurityDescriptorOwner_Proc) GetProcAddress (
946 hm_advapi32, "GetSecurityDescriptorOwner");
948 if (s_pfn_Get_Security_Descriptor_Owner == NULL)
950 errno = ENOTSUP;
951 return FALSE;
953 return (s_pfn_Get_Security_Descriptor_Owner (pSecurityDescriptor, pOwner,
954 lpbOwnerDefaulted));
957 static BOOL WINAPI
958 get_security_descriptor_group (PSECURITY_DESCRIPTOR pSecurityDescriptor,
959 PSID *pGroup,
960 LPBOOL lpbGroupDefaulted)
962 static GetSecurityDescriptorGroup_Proc s_pfn_Get_Security_Descriptor_Group = NULL;
963 HMODULE hm_advapi32 = NULL;
964 if (is_windows_9x () == TRUE)
966 errno = ENOTSUP;
967 return FALSE;
969 if (g_b_init_get_security_descriptor_group == 0)
971 g_b_init_get_security_descriptor_group = 1;
972 hm_advapi32 = LoadLibrary ("Advapi32.dll");
973 s_pfn_Get_Security_Descriptor_Group =
974 (GetSecurityDescriptorGroup_Proc) GetProcAddress (
975 hm_advapi32, "GetSecurityDescriptorGroup");
977 if (s_pfn_Get_Security_Descriptor_Group == NULL)
979 errno = ENOTSUP;
980 return FALSE;
982 return (s_pfn_Get_Security_Descriptor_Group (pSecurityDescriptor, pGroup,
983 lpbGroupDefaulted));
986 static BOOL WINAPI
987 get_security_descriptor_dacl (PSECURITY_DESCRIPTOR pSecurityDescriptor,
988 LPBOOL lpbDaclPresent,
989 PACL *pDacl,
990 LPBOOL lpbDaclDefaulted)
992 static GetSecurityDescriptorDacl_Proc s_pfn_Get_Security_Descriptor_Dacl = NULL;
993 HMODULE hm_advapi32 = NULL;
994 if (is_windows_9x () == TRUE)
996 errno = ENOTSUP;
997 return FALSE;
999 if (g_b_init_get_security_descriptor_dacl == 0)
1001 g_b_init_get_security_descriptor_dacl = 1;
1002 hm_advapi32 = LoadLibrary ("Advapi32.dll");
1003 s_pfn_Get_Security_Descriptor_Dacl =
1004 (GetSecurityDescriptorDacl_Proc) GetProcAddress (
1005 hm_advapi32, "GetSecurityDescriptorDacl");
1007 if (s_pfn_Get_Security_Descriptor_Dacl == NULL)
1009 errno = ENOTSUP;
1010 return FALSE;
1012 return (s_pfn_Get_Security_Descriptor_Dacl (pSecurityDescriptor,
1013 lpbDaclPresent, pDacl,
1014 lpbDaclDefaulted));
1017 static BOOL WINAPI
1018 is_valid_sid (PSID sid)
1020 static IsValidSid_Proc s_pfn_Is_Valid_Sid = NULL;
1021 HMODULE hm_advapi32 = NULL;
1022 if (is_windows_9x () == TRUE)
1024 return FALSE;
1026 if (g_b_init_is_valid_sid == 0)
1028 g_b_init_is_valid_sid = 1;
1029 hm_advapi32 = LoadLibrary ("Advapi32.dll");
1030 s_pfn_Is_Valid_Sid =
1031 (IsValidSid_Proc) GetProcAddress (
1032 hm_advapi32, "IsValidSid");
1034 if (s_pfn_Is_Valid_Sid == NULL)
1036 return FALSE;
1038 return (s_pfn_Is_Valid_Sid (sid));
1041 static BOOL WINAPI
1042 equal_sid (PSID sid1, PSID sid2)
1044 static EqualSid_Proc s_pfn_Equal_Sid = NULL;
1045 HMODULE hm_advapi32 = NULL;
1046 if (is_windows_9x () == TRUE)
1048 return FALSE;
1050 if (g_b_init_equal_sid == 0)
1052 g_b_init_equal_sid = 1;
1053 hm_advapi32 = LoadLibrary ("Advapi32.dll");
1054 s_pfn_Equal_Sid =
1055 (EqualSid_Proc) GetProcAddress (
1056 hm_advapi32, "EqualSid");
1058 if (s_pfn_Equal_Sid == NULL)
1060 return FALSE;
1062 return (s_pfn_Equal_Sid (sid1, sid2));
1065 static DWORD WINAPI
1066 get_length_sid (PSID sid)
1068 static GetLengthSid_Proc s_pfn_Get_Length_Sid = NULL;
1069 HMODULE hm_advapi32 = NULL;
1070 if (is_windows_9x () == TRUE)
1072 return 0;
1074 if (g_b_init_get_length_sid == 0)
1076 g_b_init_get_length_sid = 1;
1077 hm_advapi32 = LoadLibrary ("Advapi32.dll");
1078 s_pfn_Get_Length_Sid =
1079 (GetLengthSid_Proc) GetProcAddress (
1080 hm_advapi32, "GetLengthSid");
1082 if (s_pfn_Get_Length_Sid == NULL)
1084 return 0;
1086 return (s_pfn_Get_Length_Sid (sid));
1089 static BOOL WINAPI
1090 copy_sid (DWORD destlen, PSID dest, PSID src)
1092 static CopySid_Proc s_pfn_Copy_Sid = NULL;
1093 HMODULE hm_advapi32 = NULL;
1094 if (is_windows_9x () == TRUE)
1096 return FALSE;
1098 if (g_b_init_copy_sid == 0)
1100 g_b_init_copy_sid = 1;
1101 hm_advapi32 = LoadLibrary ("Advapi32.dll");
1102 s_pfn_Copy_Sid =
1103 (CopySid_Proc) GetProcAddress (
1104 hm_advapi32, "CopySid");
1106 if (s_pfn_Copy_Sid == NULL)
1108 return FALSE;
1110 return (s_pfn_Copy_Sid (destlen, dest, src));
1114 END: Wrapper functions around OpenProcessToken
1115 and other functions in advapi32.dll that are only
1116 supported in Windows NT / 2k / XP
1119 static void WINAPI
1120 get_native_system_info (LPSYSTEM_INFO lpSystemInfo)
1122 static GetNativeSystemInfo_Proc s_pfn_Get_Native_System_Info = NULL;
1123 if (is_windows_9x () != TRUE)
1125 if (g_b_init_get_native_system_info == 0)
1127 g_b_init_get_native_system_info = 1;
1128 s_pfn_Get_Native_System_Info =
1129 (GetNativeSystemInfo_Proc)GetProcAddress (GetModuleHandle ("kernel32.dll"),
1130 "GetNativeSystemInfo");
1132 if (s_pfn_Get_Native_System_Info != NULL)
1133 s_pfn_Get_Native_System_Info (lpSystemInfo);
1135 else
1136 lpSystemInfo->dwNumberOfProcessors = -1;
1139 static BOOL WINAPI
1140 get_system_times (LPFILETIME lpIdleTime,
1141 LPFILETIME lpKernelTime,
1142 LPFILETIME lpUserTime)
1144 static GetSystemTimes_Proc s_pfn_Get_System_times = NULL;
1145 if (is_windows_9x () == TRUE)
1147 return FALSE;
1149 if (g_b_init_get_system_times == 0)
1151 g_b_init_get_system_times = 1;
1152 s_pfn_Get_System_times =
1153 (GetSystemTimes_Proc)GetProcAddress (GetModuleHandle ("kernel32.dll"),
1154 "GetSystemTimes");
1156 if (s_pfn_Get_System_times == NULL)
1157 return FALSE;
1158 return (s_pfn_Get_System_times (lpIdleTime, lpKernelTime, lpUserTime));
1161 static BOOLEAN WINAPI
1162 create_symbolic_link (LPCSTR lpSymlinkFilename,
1163 LPCSTR lpTargetFileName,
1164 DWORD dwFlags)
1166 static CreateSymbolicLinkW_Proc s_pfn_Create_Symbolic_LinkW = NULL;
1167 static CreateSymbolicLinkA_Proc s_pfn_Create_Symbolic_LinkA = NULL;
1168 BOOLEAN retval;
1170 if (is_windows_9x () == TRUE)
1172 errno = ENOSYS;
1173 return 0;
1175 if (w32_unicode_filenames)
1177 wchar_t symfn_w[MAX_PATH], tgtfn_w[MAX_PATH];
1179 if (g_b_init_create_symbolic_link_w == 0)
1181 g_b_init_create_symbolic_link_w = 1;
1182 s_pfn_Create_Symbolic_LinkW =
1183 (CreateSymbolicLinkW_Proc)GetProcAddress (GetModuleHandle ("kernel32.dll"),
1184 "CreateSymbolicLinkW");
1186 if (s_pfn_Create_Symbolic_LinkW == NULL)
1188 errno = ENOSYS;
1189 return 0;
1192 filename_to_utf16 (lpSymlinkFilename, symfn_w);
1193 filename_to_utf16 (lpTargetFileName, tgtfn_w);
1194 retval = s_pfn_Create_Symbolic_LinkW (symfn_w, tgtfn_w, dwFlags);
1195 /* If we were denied creation of the symlink, try again after
1196 enabling the SeCreateSymbolicLinkPrivilege for our process. */
1197 if (!retval)
1199 TOKEN_PRIVILEGES priv_current;
1201 if (enable_privilege (SE_CREATE_SYMBOLIC_LINK_NAME, TRUE,
1202 &priv_current))
1204 retval = s_pfn_Create_Symbolic_LinkW (symfn_w, tgtfn_w, dwFlags);
1205 restore_privilege (&priv_current);
1206 revert_to_self ();
1210 else
1212 char symfn_a[MAX_PATH], tgtfn_a[MAX_PATH];
1214 if (g_b_init_create_symbolic_link_a == 0)
1216 g_b_init_create_symbolic_link_a = 1;
1217 s_pfn_Create_Symbolic_LinkA =
1218 (CreateSymbolicLinkA_Proc)GetProcAddress (GetModuleHandle ("kernel32.dll"),
1219 "CreateSymbolicLinkA");
1221 if (s_pfn_Create_Symbolic_LinkA == NULL)
1223 errno = ENOSYS;
1224 return 0;
1227 filename_to_ansi (lpSymlinkFilename, symfn_a);
1228 filename_to_ansi (lpTargetFileName, tgtfn_a);
1229 retval = s_pfn_Create_Symbolic_LinkA (symfn_a, tgtfn_a, dwFlags);
1230 /* If we were denied creation of the symlink, try again after
1231 enabling the SeCreateSymbolicLinkPrivilege for our process. */
1232 if (!retval)
1234 TOKEN_PRIVILEGES priv_current;
1236 if (enable_privilege (SE_CREATE_SYMBOLIC_LINK_NAME, TRUE,
1237 &priv_current))
1239 retval = s_pfn_Create_Symbolic_LinkA (symfn_a, tgtfn_a, dwFlags);
1240 restore_privilege (&priv_current);
1241 revert_to_self ();
1245 return retval;
1248 static BOOL WINAPI
1249 is_valid_security_descriptor (PSECURITY_DESCRIPTOR pSecurityDescriptor)
1251 static IsValidSecurityDescriptor_Proc s_pfn_Is_Valid_Security_Descriptor_Proc = NULL;
1253 if (is_windows_9x () == TRUE)
1255 errno = ENOTSUP;
1256 return FALSE;
1259 if (g_b_init_is_valid_security_descriptor == 0)
1261 g_b_init_is_valid_security_descriptor = 1;
1262 s_pfn_Is_Valid_Security_Descriptor_Proc =
1263 (IsValidSecurityDescriptor_Proc)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1264 "IsValidSecurityDescriptor");
1266 if (s_pfn_Is_Valid_Security_Descriptor_Proc == NULL)
1268 errno = ENOTSUP;
1269 return FALSE;
1272 return s_pfn_Is_Valid_Security_Descriptor_Proc (pSecurityDescriptor);
1275 static BOOL WINAPI
1276 convert_sd_to_sddl (PSECURITY_DESCRIPTOR SecurityDescriptor,
1277 DWORD RequestedStringSDRevision,
1278 SECURITY_INFORMATION SecurityInformation,
1279 LPTSTR *StringSecurityDescriptor,
1280 PULONG StringSecurityDescriptorLen)
1282 static ConvertSecurityDescriptorToStringSecurityDescriptor_Proc s_pfn_Convert_SD_To_SDDL = NULL;
1283 BOOL retval;
1285 if (is_windows_9x () == TRUE)
1287 errno = ENOTSUP;
1288 return FALSE;
1291 if (g_b_init_convert_sd_to_sddl == 0)
1293 g_b_init_convert_sd_to_sddl = 1;
1294 #ifdef _UNICODE
1295 s_pfn_Convert_SD_To_SDDL =
1296 (ConvertSecurityDescriptorToStringSecurityDescriptor_Proc)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1297 "ConvertSecurityDescriptorToStringSecurityDescriptorW");
1298 #else
1299 s_pfn_Convert_SD_To_SDDL =
1300 (ConvertSecurityDescriptorToStringSecurityDescriptor_Proc)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1301 "ConvertSecurityDescriptorToStringSecurityDescriptorA");
1302 #endif
1304 if (s_pfn_Convert_SD_To_SDDL == NULL)
1306 errno = ENOTSUP;
1307 return FALSE;
1310 retval = s_pfn_Convert_SD_To_SDDL (SecurityDescriptor,
1311 RequestedStringSDRevision,
1312 SecurityInformation,
1313 StringSecurityDescriptor,
1314 StringSecurityDescriptorLen);
1316 return retval;
1319 static BOOL WINAPI
1320 convert_sddl_to_sd (LPCTSTR StringSecurityDescriptor,
1321 DWORD StringSDRevision,
1322 PSECURITY_DESCRIPTOR *SecurityDescriptor,
1323 PULONG SecurityDescriptorSize)
1325 static ConvertStringSecurityDescriptorToSecurityDescriptor_Proc s_pfn_Convert_SDDL_To_SD = NULL;
1326 BOOL retval;
1328 if (is_windows_9x () == TRUE)
1330 errno = ENOTSUP;
1331 return FALSE;
1334 if (g_b_init_convert_sddl_to_sd == 0)
1336 g_b_init_convert_sddl_to_sd = 1;
1337 #ifdef _UNICODE
1338 s_pfn_Convert_SDDL_To_SD =
1339 (ConvertStringSecurityDescriptorToSecurityDescriptor_Proc)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1340 "ConvertStringSecurityDescriptorToSecurityDescriptorW");
1341 #else
1342 s_pfn_Convert_SDDL_To_SD =
1343 (ConvertStringSecurityDescriptorToSecurityDescriptor_Proc)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1344 "ConvertStringSecurityDescriptorToSecurityDescriptorA");
1345 #endif
1347 if (s_pfn_Convert_SDDL_To_SD == NULL)
1349 errno = ENOTSUP;
1350 return FALSE;
1353 retval = s_pfn_Convert_SDDL_To_SD (StringSecurityDescriptor,
1354 StringSDRevision,
1355 SecurityDescriptor,
1356 SecurityDescriptorSize);
1358 return retval;
1361 static DWORD WINAPI
1362 get_adapters_info (PIP_ADAPTER_INFO pAdapterInfo, PULONG pOutBufLen)
1364 static GetAdaptersInfo_Proc s_pfn_Get_Adapters_Info = NULL;
1365 HMODULE hm_iphlpapi = NULL;
1367 if (is_windows_9x () == TRUE)
1368 return ERROR_NOT_SUPPORTED;
1370 if (g_b_init_get_adapters_info == 0)
1372 g_b_init_get_adapters_info = 1;
1373 hm_iphlpapi = LoadLibrary ("Iphlpapi.dll");
1374 if (hm_iphlpapi)
1375 s_pfn_Get_Adapters_Info = (GetAdaptersInfo_Proc)
1376 GetProcAddress (hm_iphlpapi, "GetAdaptersInfo");
1378 if (s_pfn_Get_Adapters_Info == NULL)
1379 return ERROR_NOT_SUPPORTED;
1380 return s_pfn_Get_Adapters_Info (pAdapterInfo, pOutBufLen);
1385 /* Return 1 if P is a valid pointer to an object of size SIZE. Return
1386 0 if P is NOT a valid pointer. Return -1 if we cannot validate P.
1388 This is called from alloc.c:valid_pointer_p. */
1390 w32_valid_pointer_p (void *p, int size)
1392 SIZE_T done;
1393 HANDLE h = OpenProcess (PROCESS_VM_READ, FALSE, GetCurrentProcessId ());
1395 if (h)
1397 unsigned char *buf = alloca (size);
1398 int retval = ReadProcessMemory (h, p, buf, size, &done);
1400 CloseHandle (h);
1401 return retval;
1403 else
1404 return -1;
1409 /* Here's an overview of how the Windows build supports file names
1410 that cannot be encoded by the current system codepage.
1412 From the POV of Lisp and layers of C code above the functions here,
1413 Emacs on Windows pretends that its file names are encoded in UTF-8;
1414 see encode_file and decode_file on coding.c. Any file name that is
1415 passed as a unibyte string to C functions defined here is assumed
1416 to be in UTF-8 encoding. Any file name returned by functions
1417 defined here must be in UTF-8 encoding, with only a few exceptions
1418 reserved for a couple of special cases. (Be sure to use
1419 MAX_UTF8_PATH for char arrays that store UTF-8 encoded file names,
1420 as they can be much longer than MAX_PATH!)
1422 The UTF-8 encoded file names cannot be passed to system APIs, as
1423 Windows does not support that. Therefore, they are converted
1424 either to UTF-16 or to the ANSI codepage, depending on the value of
1425 w32-unicode-filenames, before calling any system APIs or CRT library
1426 functions. The default value of that variable is determined by the
1427 OS on which Emacs runs: nil on Windows 9X and t otherwise, but the
1428 user can change that default (although I don't see why would she
1429 want to).
1431 The 4 functions defined below, filename_to_utf16, filename_to_ansi,
1432 filename_from_utf16, and filename_from_ansi, are the workhorses of
1433 these conversions. They rely on Windows native APIs
1434 MultiByteToWideChar and WideCharToMultiByte; we cannot use
1435 functions from coding.c here, because they allocate memory, which
1436 is a bad idea on the level of libc, which is what the functions
1437 here emulate. (If you worry about performance due to constant
1438 conversion back and forth from UTF-8 to UTF-16, then don't: first,
1439 it was measured to take only a few microseconds on a not-so-fast
1440 machine, and second, that's exactly what the ANSI APIs we used
1441 before did anyway, because they are just thin wrappers around the
1442 Unicode APIs.)
1444 The variables file-name-coding-system and default-file-name-coding-system
1445 still exist, but are actually used only when a file name needs to
1446 be converted to the ANSI codepage. This happens all the time when
1447 w32-unicode-filenames is nil, but can also happen from time to time
1448 when it is t. Otherwise, these variables have no effect on file-name
1449 encoding when w32-unicode-filenames is t; this is similar to
1450 selection-coding-system.
1452 This arrangement works very well, but it has a few gotchas and
1453 limitations:
1455 . Lisp code that encodes or decodes file names manually should
1456 normally use 'utf-8' as the coding-system on Windows,
1457 disregarding file-name-coding-system. This is a somewhat
1458 unpleasant consequence, but it cannot be avoided. Fortunately,
1459 very few Lisp packages need to do that.
1461 More generally, passing to library functions (e.g., fopen or
1462 opendir) file names already encoded in the ANSI codepage is
1463 explicitly *verboten*, as all those functions, as shadowed and
1464 emulated here, assume they will receive UTF-8 encoded file names.
1466 For the same reasons, no CRT function or Win32 API can be called
1467 directly in Emacs sources, without either converting the file
1468 names from UTF-8 to UTF-16 or ANSI codepage, or going through
1469 some shadowing function defined here.
1471 . Environment variables stored in Vprocess_environment are encoded
1472 in the ANSI codepage, so if getenv/egetenv is used for a variable
1473 whose value is a file name or a list of directories, it needs to
1474 be converted to UTF-8, before it is used as argument to functions
1475 or decoded into a Lisp string.
1477 . File names passed to external libraries, like the image libraries
1478 and GnuTLS, need special handling. These libraries generally
1479 don't support UTF-16 or UTF-8 file names, so they must get file
1480 names encoded in the ANSI codepage. To facilitate using these
1481 libraries with file names that are not encodable in the ANSI
1482 codepage, use the function ansi_encode_filename, which will try
1483 to use the short 8+3 alias of a file name if that file name is
1484 not encodable in the ANSI codepage. See image.c and gnutls.c for
1485 examples of how this should be done.
1487 . Running subprocesses in non-ASCII directories and with non-ASCII
1488 file arguments is limited to the current codepage (even though
1489 Emacs is perfectly capable of finding an executable program file
1490 in a directory whose name cannot be encoded in the current
1491 codepage). This is because the command-line arguments are
1492 encoded _before_ they get to the w32-specific level, and the
1493 encoding is not known in advance (it doesn't have to be the
1494 current ANSI codepage), so w32proc.c functions cannot re-encode
1495 them in UTF-16. This should be fixed, but will also require
1496 changes in cmdproxy. The current limitation is not terribly bad
1497 anyway, since very few, if any, Windows console programs that are
1498 likely to be invoked by Emacs support UTF-16 encoded command
1499 lines.
1501 . For similar reasons, server.el and emacsclient are also limited
1502 to the current ANSI codepage for now.
1504 . Emacs itself can only handle command-line arguments encoded in
1505 the current codepage.
1507 . Turning on w32-unicode-filename on Windows 9X (if it at all
1508 works) requires UNICOWS.DLL, which is thus a requirement even in
1509 non-GUI sessions, something the we previously avoided. */
1513 /* Converting file names from UTF-8 to either UTF-16 or the ANSI
1514 codepage defined by file-name-coding-system. */
1516 /* Current codepage for encoding file names. */
1517 static int file_name_codepage;
1519 /* Produce a Windows ANSI codepage suitable for encoding file names.
1520 Return the information about that codepage in CP_INFO. */
1522 codepage_for_filenames (CPINFO *cp_info)
1524 /* A simple cache to avoid calling GetCPInfo every time we need to
1525 encode/decode a file name. The file-name encoding is not
1526 supposed to be changed too frequently, if ever. */
1527 static Lisp_Object last_file_name_encoding;
1528 static CPINFO cp;
1529 Lisp_Object current_encoding;
1531 current_encoding = Vfile_name_coding_system;
1532 if (NILP (current_encoding))
1533 current_encoding = Vdefault_file_name_coding_system;
1535 if (!EQ (last_file_name_encoding, current_encoding))
1537 /* Default to the current ANSI codepage. */
1538 file_name_codepage = w32_ansi_code_page;
1540 if (NILP (current_encoding))
1542 char *cpname = SSDATA (SYMBOL_NAME (current_encoding));
1543 char *cp = NULL, *end;
1544 int cpnum;
1546 if (strncmp (cpname, "cp", 2) == 0)
1547 cp = cpname + 2;
1548 else if (strncmp (cpname, "windows-", 8) == 0)
1549 cp = cpname + 8;
1551 if (cp)
1553 end = cp;
1554 cpnum = strtol (cp, &end, 10);
1555 if (cpnum && *end == '\0' && end - cp >= 2)
1556 file_name_codepage = cpnum;
1560 if (!file_name_codepage)
1561 file_name_codepage = CP_ACP; /* CP_ACP = 0, but let's not assume that */
1563 if (!GetCPInfo (file_name_codepage, &cp))
1565 file_name_codepage = CP_ACP;
1566 if (!GetCPInfo (file_name_codepage, &cp))
1567 emacs_abort ();
1570 if (cp_info)
1571 *cp_info = cp;
1573 return file_name_codepage;
1577 filename_to_utf16 (const char *fn_in, wchar_t *fn_out)
1579 int result = pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags, fn_in,
1580 -1, fn_out, MAX_PATH);
1582 if (!result)
1584 DWORD err = GetLastError ();
1586 switch (err)
1588 case ERROR_INVALID_FLAGS:
1589 case ERROR_INVALID_PARAMETER:
1590 errno = EINVAL;
1591 break;
1592 case ERROR_INSUFFICIENT_BUFFER:
1593 case ERROR_NO_UNICODE_TRANSLATION:
1594 default:
1595 errno = ENOENT;
1596 break;
1598 return -1;
1600 return 0;
1604 filename_from_utf16 (const wchar_t *fn_in, char *fn_out)
1606 int result = pWideCharToMultiByte (CP_UTF8, 0, fn_in, -1,
1607 fn_out, MAX_UTF8_PATH, NULL, NULL);
1609 if (!result)
1611 DWORD err = GetLastError ();
1613 switch (err)
1615 case ERROR_INVALID_FLAGS:
1616 case ERROR_INVALID_PARAMETER:
1617 errno = EINVAL;
1618 break;
1619 case ERROR_INSUFFICIENT_BUFFER:
1620 case ERROR_NO_UNICODE_TRANSLATION:
1621 default:
1622 errno = ENOENT;
1623 break;
1625 return -1;
1627 return 0;
1631 filename_to_ansi (const char *fn_in, char *fn_out)
1633 wchar_t fn_utf16[MAX_PATH];
1635 if (filename_to_utf16 (fn_in, fn_utf16) == 0)
1637 int result;
1638 int codepage = codepage_for_filenames (NULL);
1640 result = pWideCharToMultiByte (codepage, 0, fn_utf16, -1,
1641 fn_out, MAX_PATH, NULL, NULL);
1642 if (!result)
1644 DWORD err = GetLastError ();
1646 switch (err)
1648 case ERROR_INVALID_FLAGS:
1649 case ERROR_INVALID_PARAMETER:
1650 errno = EINVAL;
1651 break;
1652 case ERROR_INSUFFICIENT_BUFFER:
1653 case ERROR_NO_UNICODE_TRANSLATION:
1654 default:
1655 errno = ENOENT;
1656 break;
1658 return -1;
1660 return 0;
1662 return -1;
1666 filename_from_ansi (const char *fn_in, char *fn_out)
1668 wchar_t fn_utf16[MAX_PATH];
1669 int codepage = codepage_for_filenames (NULL);
1670 int result = pMultiByteToWideChar (codepage, multiByteToWideCharFlags, fn_in,
1671 -1, fn_utf16, MAX_PATH);
1673 if (!result)
1675 DWORD err = GetLastError ();
1677 switch (err)
1679 case ERROR_INVALID_FLAGS:
1680 case ERROR_INVALID_PARAMETER:
1681 errno = EINVAL;
1682 break;
1683 case ERROR_INSUFFICIENT_BUFFER:
1684 case ERROR_NO_UNICODE_TRANSLATION:
1685 default:
1686 errno = ENOENT;
1687 break;
1689 return -1;
1691 return filename_from_utf16 (fn_utf16, fn_out);
1696 /* The directory where we started, in UTF-8. */
1697 static char startup_dir[MAX_UTF8_PATH];
1699 /* Get the current working directory. */
1700 char *
1701 getcwd (char *dir, int dirsize)
1703 if (!dirsize)
1705 errno = EINVAL;
1706 return NULL;
1708 if (dirsize <= strlen (startup_dir))
1710 errno = ERANGE;
1711 return NULL;
1713 #if 0
1714 if (GetCurrentDirectory (MAXPATHLEN, dir) > 0)
1715 return dir;
1716 return NULL;
1717 #else
1718 /* Emacs doesn't actually change directory itself, it stays in the
1719 same directory where it was started. */
1720 strcpy (dir, startup_dir);
1721 return dir;
1722 #endif
1725 /* Emulate getloadavg. */
1727 struct load_sample {
1728 time_t sample_time;
1729 ULONGLONG idle;
1730 ULONGLONG kernel;
1731 ULONGLONG user;
1734 /* Number of processors on this machine. */
1735 static unsigned num_of_processors;
1737 /* We maintain 1-sec samples for the last 16 minutes in a circular buffer. */
1738 static struct load_sample samples[16*60];
1739 static int first_idx = -1, last_idx = -1;
1740 static int max_idx = ARRAYELTS (samples);
1742 static int
1743 buf_next (int from)
1745 int next_idx = from + 1;
1747 if (next_idx >= max_idx)
1748 next_idx = 0;
1750 return next_idx;
1753 static int
1754 buf_prev (int from)
1756 int prev_idx = from - 1;
1758 if (prev_idx < 0)
1759 prev_idx = max_idx - 1;
1761 return prev_idx;
1764 static void
1765 sample_system_load (ULONGLONG *idle, ULONGLONG *kernel, ULONGLONG *user)
1767 SYSTEM_INFO sysinfo;
1768 FILETIME ft_idle, ft_user, ft_kernel;
1770 /* Initialize the number of processors on this machine. */
1771 if (num_of_processors <= 0)
1773 get_native_system_info (&sysinfo);
1774 num_of_processors = sysinfo.dwNumberOfProcessors;
1775 if (num_of_processors <= 0)
1777 GetSystemInfo (&sysinfo);
1778 num_of_processors = sysinfo.dwNumberOfProcessors;
1780 if (num_of_processors <= 0)
1781 num_of_processors = 1;
1784 /* TODO: Take into account threads that are ready to run, by
1785 sampling the "\System\Processor Queue Length" performance
1786 counter. The code below accounts only for threads that are
1787 actually running. */
1789 if (get_system_times (&ft_idle, &ft_kernel, &ft_user))
1791 ULARGE_INTEGER uidle, ukernel, uuser;
1793 memcpy (&uidle, &ft_idle, sizeof (ft_idle));
1794 memcpy (&ukernel, &ft_kernel, sizeof (ft_kernel));
1795 memcpy (&uuser, &ft_user, sizeof (ft_user));
1796 *idle = uidle.QuadPart;
1797 *kernel = ukernel.QuadPart;
1798 *user = uuser.QuadPart;
1800 else
1802 *idle = 0;
1803 *kernel = 0;
1804 *user = 0;
1808 /* Produce the load average for a given time interval, using the
1809 samples in the samples[] array. WHICH can be 0, 1, or 2, meaning
1810 1-minute, 5-minute, or 15-minute average, respectively. */
1811 static double
1812 getavg (int which)
1814 double retval = -1.0;
1815 double tdiff;
1816 int idx;
1817 double span = (which == 0 ? 1.0 : (which == 1 ? 5.0 : 15.0)) * 60;
1818 time_t now = samples[last_idx].sample_time;
1820 if (first_idx != last_idx)
1822 for (idx = buf_prev (last_idx); ; idx = buf_prev (idx))
1824 tdiff = difftime (now, samples[idx].sample_time);
1825 if (tdiff >= span - 2*DBL_EPSILON*now)
1827 long double sys =
1828 samples[last_idx].kernel + samples[last_idx].user
1829 - (samples[idx].kernel + samples[idx].user);
1830 long double idl = samples[last_idx].idle - samples[idx].idle;
1832 retval = (1.0 - idl / sys) * num_of_processors;
1833 break;
1835 if (idx == first_idx)
1836 break;
1840 return retval;
1844 getloadavg (double loadavg[], int nelem)
1846 int elem;
1847 ULONGLONG idle, kernel, user;
1848 time_t now = time (NULL);
1850 /* If system time jumped back for some reason, delete all samples
1851 whose time is later than the current wall-clock time. This
1852 prevents load average figures from becoming frozen for prolonged
1853 periods of time, when system time is reset backwards. */
1854 if (last_idx >= 0)
1856 while (difftime (now, samples[last_idx].sample_time) < -1.0)
1858 if (last_idx == first_idx)
1860 first_idx = last_idx = -1;
1861 break;
1863 last_idx = buf_prev (last_idx);
1867 /* Store another sample. We ignore samples that are less than 1 sec
1868 apart. */
1869 if (last_idx < 0
1870 || (difftime (now, samples[last_idx].sample_time)
1871 >= 1.0 - 2*DBL_EPSILON*now))
1873 sample_system_load (&idle, &kernel, &user);
1874 last_idx = buf_next (last_idx);
1875 samples[last_idx].sample_time = now;
1876 samples[last_idx].idle = idle;
1877 samples[last_idx].kernel = kernel;
1878 samples[last_idx].user = user;
1879 /* If the buffer has more that 15 min worth of samples, discard
1880 the old ones. */
1881 if (first_idx == -1)
1882 first_idx = last_idx;
1883 while (first_idx != last_idx
1884 && (difftime (now, samples[first_idx].sample_time)
1885 >= 15.0*60 + 2*DBL_EPSILON*now))
1886 first_idx = buf_next (first_idx);
1889 for (elem = 0; elem < nelem; elem++)
1891 double avg = getavg (elem);
1893 if (avg < 0)
1894 break;
1895 loadavg[elem] = avg;
1898 return elem;
1901 /* Emulate getpwuid, getpwnam and others. */
1903 #define PASSWD_FIELD_SIZE 256
1905 static char dflt_passwd_name[PASSWD_FIELD_SIZE];
1906 static char dflt_passwd_passwd[PASSWD_FIELD_SIZE];
1907 static char dflt_passwd_gecos[PASSWD_FIELD_SIZE];
1908 static char dflt_passwd_dir[MAX_UTF8_PATH];
1909 static char dflt_passwd_shell[MAX_UTF8_PATH];
1911 static struct passwd dflt_passwd =
1913 dflt_passwd_name,
1914 dflt_passwd_passwd,
1918 dflt_passwd_gecos,
1919 dflt_passwd_dir,
1920 dflt_passwd_shell,
1923 static char dflt_group_name[GNLEN+1];
1925 static struct group dflt_group =
1927 /* When group information is not available, we return this as the
1928 group for all files. */
1929 dflt_group_name,
1933 unsigned
1934 getuid (void)
1936 return dflt_passwd.pw_uid;
1939 unsigned
1940 geteuid (void)
1942 /* I could imagine arguing for checking to see whether the user is
1943 in the Administrators group and returning a UID of 0 for that
1944 case, but I don't know how wise that would be in the long run. */
1945 return getuid ();
1948 unsigned
1949 getgid (void)
1951 return dflt_passwd.pw_gid;
1954 unsigned
1955 getegid (void)
1957 return getgid ();
1960 struct passwd *
1961 getpwuid (unsigned uid)
1963 if (uid == dflt_passwd.pw_uid)
1964 return &dflt_passwd;
1965 return NULL;
1968 struct group *
1969 getgrgid (gid_t gid)
1971 return &dflt_group;
1974 struct passwd *
1975 getpwnam (char *name)
1977 struct passwd *pw;
1979 pw = getpwuid (getuid ());
1980 if (!pw)
1981 return pw;
1983 if (xstrcasecmp (name, pw->pw_name))
1984 return NULL;
1986 return pw;
1989 static void
1990 init_user_info (void)
1992 /* Find the user's real name by opening the process token and
1993 looking up the name associated with the user-sid in that token.
1995 Use the relative portion of the identifier authority value from
1996 the user-sid as the user id value (same for group id using the
1997 primary group sid from the process token). */
1999 char uname[UNLEN+1], gname[GNLEN+1], domain[1025];
2000 DWORD ulength = sizeof (uname), dlength = sizeof (domain), needed;
2001 DWORD glength = sizeof (gname);
2002 HANDLE token = NULL;
2003 SID_NAME_USE user_type;
2004 unsigned char *buf = NULL;
2005 DWORD blen = 0;
2006 TOKEN_USER user_token;
2007 TOKEN_PRIMARY_GROUP group_token;
2008 BOOL result;
2010 result = open_process_token (GetCurrentProcess (), TOKEN_QUERY, &token);
2011 if (result)
2013 result = get_token_information (token, TokenUser, NULL, 0, &blen);
2014 if (!result && GetLastError () == ERROR_INSUFFICIENT_BUFFER)
2016 buf = xmalloc (blen);
2017 result = get_token_information (token, TokenUser,
2018 (LPVOID)buf, blen, &needed);
2019 if (result)
2021 memcpy (&user_token, buf, sizeof (user_token));
2022 result = lookup_account_sid (NULL, user_token.User.Sid,
2023 uname, &ulength,
2024 domain, &dlength, &user_type);
2027 else
2028 result = FALSE;
2030 if (result)
2032 strcpy (dflt_passwd.pw_name, uname);
2033 /* Determine a reasonable uid value. */
2034 if (xstrcasecmp ("administrator", uname) == 0)
2036 dflt_passwd.pw_uid = 500; /* well-known Administrator uid */
2037 dflt_passwd.pw_gid = 513; /* well-known None gid */
2039 else
2041 /* Use the last sub-authority value of the RID, the relative
2042 portion of the SID, as user/group ID. */
2043 dflt_passwd.pw_uid = get_rid (user_token.User.Sid);
2045 /* Get group id and name. */
2046 result = get_token_information (token, TokenPrimaryGroup,
2047 (LPVOID)buf, blen, &needed);
2048 if (!result && GetLastError () == ERROR_INSUFFICIENT_BUFFER)
2050 buf = xrealloc (buf, blen = needed);
2051 result = get_token_information (token, TokenPrimaryGroup,
2052 (LPVOID)buf, blen, &needed);
2054 if (result)
2056 memcpy (&group_token, buf, sizeof (group_token));
2057 dflt_passwd.pw_gid = get_rid (group_token.PrimaryGroup);
2058 dlength = sizeof (domain);
2059 /* If we can get at the real Primary Group name, use that.
2060 Otherwise, the default group name was already set to
2061 "None" in globals_of_w32. */
2062 if (lookup_account_sid (NULL, group_token.PrimaryGroup,
2063 gname, &glength, NULL, &dlength,
2064 &user_type))
2065 strcpy (dflt_group_name, gname);
2067 else
2068 dflt_passwd.pw_gid = dflt_passwd.pw_uid;
2071 /* If security calls are not supported (presumably because we
2072 are running under Windows 9X), fallback to this: */
2073 else if (GetUserName (uname, &ulength))
2075 strcpy (dflt_passwd.pw_name, uname);
2076 if (xstrcasecmp ("administrator", uname) == 0)
2077 dflt_passwd.pw_uid = 0;
2078 else
2079 dflt_passwd.pw_uid = 123;
2080 dflt_passwd.pw_gid = dflt_passwd.pw_uid;
2082 else
2084 strcpy (dflt_passwd.pw_name, "unknown");
2085 dflt_passwd.pw_uid = 123;
2086 dflt_passwd.pw_gid = 123;
2088 dflt_group.gr_gid = dflt_passwd.pw_gid;
2090 /* Set dir and shell from environment variables. */
2091 if (w32_unicode_filenames)
2093 wchar_t *home = _wgetenv (L"HOME");
2094 wchar_t *shell = _wgetenv (L"SHELL");
2096 /* Ensure HOME and SHELL are defined. */
2097 if (home == NULL)
2098 emacs_abort ();
2099 if (shell == NULL)
2100 emacs_abort ();
2101 filename_from_utf16 (home, dflt_passwd.pw_dir);
2102 filename_from_utf16 (shell, dflt_passwd.pw_shell);
2104 else
2106 char *home = getenv ("HOME");
2107 char *shell = getenv ("SHELL");
2109 if (home == NULL)
2110 emacs_abort ();
2111 if (shell == NULL)
2112 emacs_abort ();
2113 filename_from_ansi (home, dflt_passwd.pw_dir);
2114 filename_from_ansi (shell, dflt_passwd.pw_shell);
2117 xfree (buf);
2118 if (token)
2119 CloseHandle (token);
2122 static HCRYPTPROV w32_crypto_hprov;
2123 static int
2124 w32_init_crypt_random (void)
2126 if (!CryptAcquireContext (&w32_crypto_hprov, NULL, NULL, PROV_RSA_FULL,
2127 CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
2129 DebPrint (("CryptAcquireContext failed with error %x\n",
2130 GetLastError ()));
2131 w32_crypto_hprov = 0;
2132 return -1;
2134 return 0;
2138 w32_init_random (void *buf, ptrdiff_t buflen)
2140 if (!w32_crypto_hprov)
2141 w32_init_crypt_random ();
2142 if (w32_crypto_hprov)
2144 if (CryptGenRandom (w32_crypto_hprov, buflen, (BYTE *)buf))
2145 return 0;
2147 return -1;
2151 random (void)
2153 /* rand () on NT gives us 15 random bits...hack together 30 bits. */
2154 return ((rand () << 15) | rand ());
2157 void
2158 srandom (int seed)
2160 srand (seed);
2163 /* Return the maximum length in bytes of a multibyte character
2164 sequence encoded in the current ANSI codepage. This is required to
2165 correctly walk the encoded file names one character at a time. */
2166 static int
2167 max_filename_mbslen (void)
2169 CPINFO cp_info;
2171 codepage_for_filenames (&cp_info);
2172 return cp_info.MaxCharSize;
2175 /* Normalize filename by converting in-place all of its path
2176 separators to the separator specified by PATH_SEP. */
2178 static void
2179 normalize_filename (register char *fp, char path_sep)
2181 char *p2;
2183 /* Always lower-case drive letters a-z, even if the filesystem
2184 preserves case in filenames.
2185 This is so filenames can be compared by string comparison
2186 functions that are case-sensitive. Even case-preserving filesystems
2187 do not distinguish case in drive letters. */
2188 p2 = fp + 1;
2190 if (*p2 == ':' && *fp >= 'A' && *fp <= 'Z')
2192 *fp += 'a' - 'A';
2193 fp += 2;
2196 while (*fp)
2198 if ((*fp == '/' || *fp == '\\') && *fp != path_sep)
2199 *fp = path_sep;
2200 fp++;
2204 /* Destructively turn backslashes into slashes. */
2205 void
2206 dostounix_filename (register char *p)
2208 normalize_filename (p, '/');
2211 /* Destructively turn slashes into backslashes. */
2212 void
2213 unixtodos_filename (register char *p)
2215 normalize_filename (p, '\\');
2218 /* Remove all CR's that are followed by a LF.
2219 (From msdos.c...probably should figure out a way to share it,
2220 although this code isn't going to ever change.) */
2221 static int
2222 crlf_to_lf (register int n, register char *buf)
2224 unsigned char *np = (unsigned char *)buf;
2225 unsigned char *startp = np;
2226 char *endp = buf + n;
2228 if (n == 0)
2229 return n;
2230 while (buf < endp - 1)
2232 if (*buf == 0x0d)
2234 if (*(++buf) != 0x0a)
2235 *np++ = 0x0d;
2237 else
2238 *np++ = *buf++;
2240 if (buf < endp)
2241 *np++ = *buf++;
2242 return np - startp;
2245 /* Parse the root part of file name, if present. Return length and
2246 optionally store pointer to char after root. */
2247 static int
2248 parse_root (const char * name, const char ** pPath)
2250 const char * start = name;
2252 if (name == NULL)
2253 return 0;
2255 /* find the root name of the volume if given */
2256 if (isalpha (name[0]) && name[1] == ':')
2258 /* skip past drive specifier */
2259 name += 2;
2260 if (IS_DIRECTORY_SEP (name[0]))
2261 name++;
2263 else if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1]))
2265 int slashes = 2;
2267 name += 2;
2270 if (IS_DIRECTORY_SEP (*name) && --slashes == 0)
2271 break;
2272 name++;
2274 while ( *name );
2275 if (IS_DIRECTORY_SEP (name[0]))
2276 name++;
2279 if (pPath)
2280 *pPath = name;
2282 return name - start;
2285 /* Get long base name for name; name is assumed to be absolute. */
2286 static int
2287 get_long_basename (char * name, char * buf, int size)
2289 HANDLE dir_handle = INVALID_HANDLE_VALUE;
2290 char fname_utf8[MAX_UTF8_PATH];
2291 int len = 0;
2292 int cstatus = -1;
2294 /* Must be valid filename, no wild cards or other invalid characters. */
2295 if (strpbrk (name, "*?|<>\""))
2296 return 0;
2298 if (w32_unicode_filenames)
2300 wchar_t fname_utf16[MAX_PATH];
2301 WIN32_FIND_DATAW find_data_wide;
2303 filename_to_utf16 (name, fname_utf16);
2304 dir_handle = FindFirstFileW (fname_utf16, &find_data_wide);
2305 if (dir_handle != INVALID_HANDLE_VALUE)
2306 cstatus = filename_from_utf16 (find_data_wide.cFileName, fname_utf8);
2308 else
2310 char fname_ansi[MAX_PATH];
2311 WIN32_FIND_DATAA find_data_ansi;
2313 filename_to_ansi (name, fname_ansi);
2314 /* If the ANSI name includes ? characters, it is not encodable
2315 in the ANSI codepage. In that case, we deliver the question
2316 marks to the caller; calling FindFirstFileA in this case
2317 could return some unrelated file name in the same
2318 directory. */
2319 if (_mbspbrk (fname_ansi, "?"))
2321 /* Find the basename of fname_ansi. */
2322 char *p = strrchr (fname_ansi, '\\');
2324 if (!p)
2325 p = fname_ansi;
2326 else
2327 p++;
2328 cstatus = filename_from_ansi (p, fname_utf8);
2330 else
2332 dir_handle = FindFirstFileA (fname_ansi, &find_data_ansi);
2333 if (dir_handle != INVALID_HANDLE_VALUE)
2334 cstatus = filename_from_ansi (find_data_ansi.cFileName, fname_utf8);
2338 if (cstatus == 0 && (len = strlen (fname_utf8)) < size)
2339 memcpy (buf, fname_utf8, len + 1);
2340 else
2341 len = 0;
2343 if (dir_handle != INVALID_HANDLE_VALUE)
2344 FindClose (dir_handle);
2346 return len;
2349 /* Get long name for file, if possible (assumed to be absolute). */
2350 BOOL
2351 w32_get_long_filename (const char * name, char * buf, int size)
2353 char * o = buf;
2354 char * p;
2355 const char * q;
2356 char full[ MAX_UTF8_PATH ];
2357 int len;
2359 len = strlen (name);
2360 if (len >= MAX_UTF8_PATH)
2361 return FALSE;
2363 /* Use local copy for destructive modification. */
2364 memcpy (full, name, len+1);
2365 unixtodos_filename (full);
2367 /* Copy root part verbatim. */
2368 len = parse_root (full, (const char **)&p);
2369 memcpy (o, full, len);
2370 o += len;
2371 *o = '\0';
2372 size -= len;
2374 while (p != NULL && *p)
2376 q = p;
2377 p = strchr (q, '\\');
2378 if (p) *p = '\0';
2379 len = get_long_basename (full, o, size);
2380 if (len > 0)
2382 o += len;
2383 size -= len;
2384 if (p != NULL)
2386 *p++ = '\\';
2387 if (size < 2)
2388 return FALSE;
2389 *o++ = '\\';
2390 size--;
2391 *o = '\0';
2394 else
2395 return FALSE;
2398 return TRUE;
2401 unsigned int
2402 w32_get_short_filename (const char * name, char * buf, int size)
2404 if (w32_unicode_filenames)
2406 wchar_t name_utf16[MAX_PATH], short_name[MAX_PATH];
2407 unsigned int retval;
2409 filename_to_utf16 (name, name_utf16);
2410 retval = GetShortPathNameW (name_utf16, short_name, size);
2411 if (retval && retval < size)
2412 filename_from_utf16 (short_name, buf);
2413 return retval;
2415 else
2417 char name_ansi[MAX_PATH];
2419 filename_to_ansi (name, name_ansi);
2420 return GetShortPathNameA (name_ansi, buf, size);
2424 /* Re-encode FILENAME, a UTF-8 encoded unibyte string, using the
2425 MS-Windows ANSI codepage. If FILENAME includes characters not
2426 supported by the ANSI codepage, return the 8+3 alias of FILENAME,
2427 if it exists. This is needed because the w32 build wants to
2428 support file names outside of the system locale, but image
2429 libraries typically don't support wide (a.k.a. "Unicode") APIs
2430 required for that. */
2432 Lisp_Object
2433 ansi_encode_filename (Lisp_Object filename)
2435 Lisp_Object encoded_filename;
2436 char fname[MAX_PATH];
2438 filename_to_ansi (SSDATA (filename), fname);
2439 if (_mbspbrk (fname, "?"))
2441 char shortname[MAX_PATH];
2443 if (w32_get_short_filename (SSDATA (filename), shortname, MAX_PATH))
2445 dostounix_filename (shortname);
2446 encoded_filename = build_string (shortname);
2448 else
2449 encoded_filename = build_unibyte_string (fname);
2451 else
2452 encoded_filename = build_unibyte_string (fname);
2453 return encoded_filename;
2456 static int
2457 is_unc_volume (const char *filename)
2459 const char *ptr = filename;
2461 if (!IS_DIRECTORY_SEP (ptr[0]) || !IS_DIRECTORY_SEP (ptr[1]) || !ptr[2])
2462 return 0;
2464 if (strpbrk (ptr + 2, "*?|<>\"\\/"))
2465 return 0;
2467 return 1;
2470 /* Emulate the Posix unsetenv. */
2472 unsetenv (const char *name)
2474 char *var;
2475 size_t name_len;
2477 if (name == NULL || *name == '\0' || strchr (name, '=') != NULL)
2479 errno = EINVAL;
2480 return -1;
2482 name_len = strlen (name);
2483 /* MS docs says an environment variable cannot be longer than 32K. */
2484 if (name_len > 32767)
2486 errno = ENOMEM;
2487 return 0;
2489 /* It is safe to use 'alloca' with 32K size, since the stack is at
2490 least 2MB, and we set it to 8MB in the link command line. */
2491 var = alloca (name_len + 2);
2492 strncpy (var, name, name_len);
2493 var[name_len++] = '=';
2494 var[name_len] = '\0';
2495 return _putenv (var);
2498 /* MS _putenv doesn't support removing a variable when the argument
2499 does not include the '=' character, so we fix that here. */
2501 sys_putenv (char *str)
2503 const char *const name_end = strchr (str, '=');
2505 if (name_end == NULL)
2507 /* Remove the variable from the environment. */
2508 return unsetenv (str);
2511 if (strncmp (str, "TZ=<", 4) == 0)
2513 /* MS-Windows does not support POSIX.1-2001 angle-bracket TZ
2514 abbreviation syntax. Convert to POSIX.1-1988 syntax if possible,
2515 and to the undocumented placeholder "ZZZ" otherwise. */
2516 bool supported_abbr = true;
2517 for (char *p = str + 4; *p; p++)
2519 if (('0' <= *p && *p <= '9') || *p == '-' || *p == '+')
2520 supported_abbr = false;
2521 else if (*p == '>')
2523 ptrdiff_t abbrlen;
2524 if (supported_abbr)
2526 abbrlen = p - (str + 4);
2527 memmove (str + 3, str + 4, abbrlen);
2529 else
2531 abbrlen = 3;
2532 memset (str + 3, 'Z', abbrlen);
2534 memmove (str + 3 + abbrlen, p + 1, strlen (p));
2535 break;
2540 return _putenv (str);
2543 #define REG_ROOT "SOFTWARE\\GNU\\Emacs"
2545 LPBYTE
2546 w32_get_resource (const char *key, LPDWORD lpdwtype)
2548 LPBYTE lpvalue;
2549 HKEY hrootkey = NULL;
2550 DWORD cbData;
2552 /* Check both the current user and the local machine to see if
2553 we have any resources. */
2555 if (RegOpenKeyEx (HKEY_CURRENT_USER, REG_ROOT, 0, KEY_READ, &hrootkey) == ERROR_SUCCESS)
2557 lpvalue = NULL;
2559 if (RegQueryValueEx (hrootkey, key, NULL, NULL, NULL, &cbData) == ERROR_SUCCESS
2560 && (lpvalue = xmalloc (cbData)) != NULL
2561 && RegQueryValueEx (hrootkey, key, NULL, lpdwtype, lpvalue, &cbData) == ERROR_SUCCESS)
2563 RegCloseKey (hrootkey);
2564 return (lpvalue);
2567 xfree (lpvalue);
2569 RegCloseKey (hrootkey);
2572 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, REG_ROOT, 0, KEY_READ, &hrootkey) == ERROR_SUCCESS)
2574 lpvalue = NULL;
2576 if (RegQueryValueEx (hrootkey, key, NULL, NULL, NULL, &cbData) == ERROR_SUCCESS
2577 && (lpvalue = xmalloc (cbData)) != NULL
2578 && RegQueryValueEx (hrootkey, key, NULL, lpdwtype, lpvalue, &cbData) == ERROR_SUCCESS)
2580 RegCloseKey (hrootkey);
2581 return (lpvalue);
2584 xfree (lpvalue);
2586 RegCloseKey (hrootkey);
2589 return (NULL);
2592 /* The argv[] array holds ANSI-encoded strings, and so this function
2593 works with ANS_encoded strings. */
2594 void
2595 init_environment (char ** argv)
2597 static const char * const tempdirs[] = {
2598 "$TMPDIR", "$TEMP", "$TMP", "c:/"
2601 int i;
2603 const int imax = ARRAYELTS (tempdirs);
2605 /* Implementation note: This function explicitly works with ANSI
2606 file names, not with UTF-8 encoded file names. This is because
2607 this function pushes variables into the Emacs's environment, and
2608 the environment variables are always assumed to be in the
2609 locale-specific encoding. Do NOT call any functions that accept
2610 UTF-8 file names from this function! */
2612 /* Make sure they have a usable $TMPDIR. Many Emacs functions use
2613 temporary files and assume "/tmp" if $TMPDIR is unset, which
2614 will break on DOS/Windows. Refuse to work if we cannot find
2615 a directory, not even "c:/", usable for that purpose. */
2616 for (i = 0; i < imax ; i++)
2618 const char *tmp = tempdirs[i];
2620 if (*tmp == '$')
2621 tmp = getenv (tmp + 1);
2622 /* Note that `access' can lie to us if the directory resides on a
2623 read-only filesystem, like CD-ROM or a write-protected floppy.
2624 The only way to be really sure is to actually create a file and
2625 see if it succeeds. But I think that's too much to ask. */
2627 /* MSVCRT's _access crashes with D_OK, so we use our replacement. */
2628 if (tmp && sys_access (tmp, D_OK) == 0)
2630 char * var = alloca (strlen (tmp) + 8);
2631 sprintf (var, "TMPDIR=%s", tmp);
2632 _putenv (strdup (var));
2633 break;
2636 if (i >= imax)
2637 cmd_error_internal
2638 (Fcons (Qerror,
2639 Fcons (build_string ("no usable temporary directories found!!"),
2640 Qnil)),
2641 "While setting TMPDIR: ");
2643 /* Check for environment variables and use registry settings if they
2644 don't exist. Fallback on default values where applicable. */
2646 int i;
2647 LPBYTE lpval;
2648 DWORD dwType;
2649 char locale_name[32];
2650 char default_home[MAX_PATH];
2651 int appdata = 0;
2653 static const struct env_entry
2655 const char * name;
2656 const char * def_value;
2657 } dflt_envvars[] =
2659 /* If the default value is NULL, we will use the value from the
2660 outside environment or the Registry, but will not push the
2661 variable into the Emacs environment if it is defined neither
2662 in the Registry nor in the outside environment. */
2663 {"HOME", "C:/"},
2664 {"PRELOAD_WINSOCK", NULL},
2665 {"emacs_dir", "C:/emacs"},
2666 {"EMACSLOADPATH", NULL},
2667 {"SHELL", "cmdproxy.exe"}, /* perhaps it is somewhere on PATH */
2668 {"EMACSDATA", NULL},
2669 {"EMACSPATH", NULL},
2670 {"INFOPATH", NULL},
2671 {"EMACSDOC", NULL},
2672 {"TERM", "cmd"},
2673 {"LANG", NULL},
2676 #define N_ENV_VARS ARRAYELTS (dflt_envvars)
2678 /* We need to copy dflt_envvars[] and work on the copy because we
2679 don't want the dumped Emacs to inherit the values of
2680 environment variables we saw during dumping (which could be on
2681 a different system). The defaults above must be left intact. */
2682 struct env_entry env_vars[N_ENV_VARS];
2684 for (i = 0; i < N_ENV_VARS; i++)
2685 env_vars[i] = dflt_envvars[i];
2687 /* For backwards compatibility, check if a .emacs file exists in C:/
2688 If not, then we can try to default to the appdata directory under the
2689 user's profile, which is more likely to be writable. */
2690 if (sys_access ("C:/.emacs", F_OK) != 0)
2692 HRESULT profile_result;
2693 /* Dynamically load ShGetFolderPath, as it won't exist on versions
2694 of Windows 95 and NT4 that have not been updated to include
2695 MSIE 5. */
2696 ShGetFolderPath_fn get_folder_path;
2697 get_folder_path = (ShGetFolderPath_fn)
2698 GetProcAddress (GetModuleHandle ("shell32.dll"), "SHGetFolderPathA");
2700 if (get_folder_path != NULL)
2702 profile_result = get_folder_path (NULL, CSIDL_APPDATA, NULL,
2703 0, default_home);
2705 /* If we can't get the appdata dir, revert to old behavior. */
2706 if (profile_result == S_OK)
2708 env_vars[0].def_value = default_home;
2709 appdata = 1;
2714 /* Get default locale info and use it for LANG. */
2715 if (GetLocaleInfo (LOCALE_USER_DEFAULT,
2716 LOCALE_SABBREVLANGNAME | LOCALE_USE_CP_ACP,
2717 locale_name, sizeof (locale_name)))
2719 for (i = 0; i < N_ENV_VARS; i++)
2721 if (strcmp (env_vars[i].name, "LANG") == 0)
2723 env_vars[i].def_value = locale_name;
2724 break;
2729 #define SET_ENV_BUF_SIZE (4 * MAX_PATH) /* to cover EMACSLOADPATH */
2731 /* Treat emacs_dir specially: set it unconditionally based on our
2732 location. */
2734 char *p;
2735 char modname[MAX_PATH];
2737 if (!GetModuleFileNameA (NULL, modname, MAX_PATH))
2738 emacs_abort ();
2739 if ((p = _mbsrchr (modname, '\\')) == NULL)
2740 emacs_abort ();
2741 *p = 0;
2743 if ((p = _mbsrchr (modname, '\\'))
2744 /* From bin means installed Emacs, from src means uninstalled. */
2745 && (xstrcasecmp (p, "\\bin") == 0 || xstrcasecmp (p, "\\src") == 0))
2747 char buf[SET_ENV_BUF_SIZE];
2748 int within_build_tree = xstrcasecmp (p, "\\src") == 0;
2750 *p = 0;
2751 for (p = modname; *p; p = CharNext (p))
2752 if (*p == '\\') *p = '/';
2754 _snprintf (buf, sizeof (buf)-1, "emacs_dir=%s", modname);
2755 _putenv (strdup (buf));
2756 /* If we are running from the Posix-like build tree, define
2757 SHELL to point to our own cmdproxy. The loop below will
2758 then disregard PATH_EXEC and the default value. */
2759 if (within_build_tree)
2761 _snprintf (buf, sizeof (buf) - 1,
2762 "SHELL=%s/nt/cmdproxy.exe", modname);
2763 _putenv (strdup (buf));
2768 for (i = 0; i < N_ENV_VARS; i++)
2770 if (!getenv (env_vars[i].name))
2772 int dont_free = 0;
2773 char bufc[SET_ENV_BUF_SIZE];
2775 if ((lpval = w32_get_resource (env_vars[i].name, &dwType)) == NULL
2776 /* Also ignore empty environment variables. */
2777 || *lpval == 0)
2779 xfree (lpval);
2780 dont_free = 1;
2781 if (strcmp (env_vars[i].name, "SHELL") == 0)
2783 /* Look for cmdproxy.exe in every directory in
2784 PATH_EXEC. FIXME: This does not find cmdproxy
2785 in nt/ when we run uninstalled. */
2786 char fname[MAX_PATH];
2787 const char *pstart = PATH_EXEC, *pend;
2789 do {
2790 pend = _mbschr (pstart, ';');
2791 if (!pend)
2792 pend = pstart + strlen (pstart);
2793 /* Be defensive against series of ;;; characters. */
2794 if (pend > pstart)
2796 strncpy (fname, pstart, pend - pstart);
2797 fname[pend - pstart] = '/';
2798 strcpy (&fname[pend - pstart + 1], "cmdproxy.exe");
2799 ExpandEnvironmentStrings ((LPSTR) fname, bufc,
2800 sizeof (bufc));
2801 if (sys_access (bufc, F_OK) == 0)
2803 lpval = bufc;
2804 dwType = REG_SZ;
2805 break;
2808 if (*pend)
2809 pstart = pend + 1;
2810 else
2811 pstart = pend;
2812 if (!*pstart)
2814 /* If not found in any directory, use the
2815 default as the last resort. */
2816 lpval = (char *)env_vars[i].def_value;
2817 dwType = REG_EXPAND_SZ;
2819 } while (*pstart);
2821 else
2823 lpval = (char *)env_vars[i].def_value;
2824 dwType = REG_EXPAND_SZ;
2826 if (strcmp (env_vars[i].name, "HOME") == 0 && !appdata)
2827 Vdelayed_warnings_list
2828 = Fcons
2829 (listn (CONSTYPE_HEAP, 2,
2830 intern ("initialization"), build_string
2831 ("Use of `C:\\.emacs' without defining `HOME'\n"
2832 "in the environment is deprecated, "
2833 "see `Windows HOME' in the Emacs manual.")),
2834 Vdelayed_warnings_list);
2837 if (lpval)
2839 char buf1[SET_ENV_BUF_SIZE], buf2[SET_ENV_BUF_SIZE];
2841 if (dwType == REG_EXPAND_SZ)
2842 ExpandEnvironmentStrings ((LPSTR) lpval, buf1, sizeof (buf1));
2843 else if (dwType == REG_SZ)
2844 strcpy (buf1, (char *)lpval);
2845 if (dwType == REG_EXPAND_SZ || dwType == REG_SZ)
2847 _snprintf (buf2, sizeof (buf2)-1, "%s=%s", env_vars[i].name,
2848 buf1);
2849 _putenv (strdup (buf2));
2852 if (!dont_free)
2853 xfree (lpval);
2859 /* Rebuild system configuration to reflect invoking system. */
2860 Vsystem_configuration = build_string (EMACS_CONFIGURATION);
2862 /* Another special case: on NT, the PATH variable is actually named
2863 "Path" although cmd.exe (perhaps NT itself) arranges for
2864 environment variable lookup and setting to be case insensitive.
2865 However, Emacs assumes a fully case sensitive environment, so we
2866 need to change "Path" to "PATH" to match the expectations of
2867 various elisp packages. We do this by the sneaky method of
2868 modifying the string in the C runtime environ entry.
2870 The same applies to COMSPEC. */
2872 char ** envp;
2874 for (envp = environ; *envp; envp++)
2875 if (_strnicmp (*envp, "PATH=", 5) == 0)
2876 memcpy (*envp, "PATH=", 5);
2877 else if (_strnicmp (*envp, "COMSPEC=", 8) == 0)
2878 memcpy (*envp, "COMSPEC=", 8);
2881 /* Remember the initial working directory for getcwd. */
2882 /* FIXME: Do we need to resolve possible symlinks in startup_dir?
2883 Does it matter anywhere in Emacs? */
2884 if (w32_unicode_filenames)
2886 wchar_t wstartup_dir[MAX_PATH];
2888 if (!GetCurrentDirectoryW (MAX_PATH, wstartup_dir))
2889 emacs_abort ();
2890 filename_from_utf16 (wstartup_dir, startup_dir);
2892 else
2894 char astartup_dir[MAX_PATH];
2896 if (!GetCurrentDirectoryA (MAX_PATH, astartup_dir))
2897 emacs_abort ();
2898 filename_from_ansi (astartup_dir, startup_dir);
2902 static char modname[MAX_PATH];
2904 if (!GetModuleFileNameA (NULL, modname, MAX_PATH))
2905 emacs_abort ();
2906 argv[0] = modname;
2909 /* Determine if there is a middle mouse button, to allow parse_button
2910 to decide whether right mouse events should be mouse-2 or
2911 mouse-3. */
2912 w32_num_mouse_buttons = GetSystemMetrics (SM_CMOUSEBUTTONS);
2914 init_user_info ();
2917 /* Called from expand-file-name when default-directory is not a string. */
2919 char *
2920 emacs_root_dir (void)
2922 static char root_dir[MAX_UTF8_PATH];
2923 const char *p;
2925 p = getenv ("emacs_dir");
2926 if (p == NULL)
2927 emacs_abort ();
2928 filename_from_ansi (p, root_dir);
2929 root_dir[parse_root (root_dir, NULL)] = '\0';
2930 dostounix_filename (root_dir);
2931 return root_dir;
2934 #include <sys/timeb.h>
2936 /* Emulate gettimeofday (Ulrich Leodolter, 1/11/95). */
2938 gettimeofday (struct timeval *__restrict tv, struct timezone *__restrict tz)
2940 struct _timeb tb;
2941 _ftime (&tb);
2943 tv->tv_sec = tb.time;
2944 tv->tv_usec = tb.millitm * 1000L;
2945 /* Implementation note: _ftime sometimes doesn't update the dstflag
2946 according to the new timezone when the system timezone is
2947 changed. We could fix that by using GetSystemTime and
2948 GetTimeZoneInformation, but that doesn't seem necessary, since
2949 Emacs always calls gettimeofday with the 2nd argument NULL (see
2950 current_emacs_time). */
2951 if (tz)
2953 tz->tz_minuteswest = tb.timezone; /* minutes west of Greenwich */
2954 tz->tz_dsttime = tb.dstflag; /* type of dst correction */
2956 return 0;
2959 /* Emulate fdutimens. */
2961 /* Set the access and modification time stamps of FD (a.k.a. FILE) to be
2962 TIMESPEC[0] and TIMESPEC[1], respectively.
2963 FD must be either negative -- in which case it is ignored --
2964 or a file descriptor that is open on FILE.
2965 If FD is nonnegative, then FILE can be NULL, which means
2966 use just futimes instead of utimes.
2967 If TIMESPEC is null, FAIL.
2968 Return 0 on success, -1 (setting errno) on failure. */
2971 fdutimens (int fd, char const *file, struct timespec const timespec[2])
2973 if (!timespec)
2975 errno = ENOSYS;
2976 return -1;
2978 if (fd < 0 && !file)
2980 errno = EBADF;
2981 return -1;
2983 /* _futime's prototype defines 2nd arg as having the type 'struct
2984 _utimbuf', while utime needs to accept 'struct utimbuf' for
2985 compatibility with Posix. So we need to use 2 different (but
2986 equivalent) types to avoid compiler warnings, sigh. */
2987 if (fd >= 0)
2989 struct _utimbuf _ut;
2991 _ut.actime = timespec[0].tv_sec;
2992 _ut.modtime = timespec[1].tv_sec;
2993 return _futime (fd, &_ut);
2995 else
2997 struct utimbuf ut;
2999 ut.actime = timespec[0].tv_sec;
3000 ut.modtime = timespec[1].tv_sec;
3001 /* Call 'utime', which is implemented below, not the MS library
3002 function, which fails on directories. */
3003 return utime (file, &ut);
3008 /* ------------------------------------------------------------------------- */
3009 /* IO support and wrapper functions for the Windows API. */
3010 /* ------------------------------------------------------------------------- */
3012 /* Place a wrapper around the MSVC version of ctime. It returns NULL
3013 on network directories, so we handle that case here.
3014 (Ulrich Leodolter, 1/11/95). */
3015 char *
3016 sys_ctime (const time_t *t)
3018 char *str = (char *) ctime (t);
3019 return (str ? str : (char *)"Sun Jan 01 00:00:00 1970");
3022 /* Emulate sleep...we could have done this with a define, but that
3023 would necessitate including windows.h in the files that used it.
3024 This is much easier. */
3025 void
3026 sys_sleep (int seconds)
3028 Sleep (seconds * 1000);
3031 /* Internal MSVC functions for low-level descriptor munging */
3032 extern int __cdecl _set_osfhnd (int fd, long h);
3033 extern int __cdecl _free_osfhnd (int fd);
3035 /* parallel array of private info on file handles */
3036 filedesc fd_info [ MAXDESC ];
3038 typedef struct volume_info_data {
3039 struct volume_info_data * next;
3041 /* time when info was obtained */
3042 DWORD timestamp;
3044 /* actual volume info */
3045 char * root_dir;
3046 DWORD serialnum;
3047 DWORD maxcomp;
3048 DWORD flags;
3049 char * name;
3050 char * type;
3051 } volume_info_data;
3053 /* Global referenced by various functions. */
3054 static volume_info_data volume_info;
3056 /* Vector to indicate which drives are local and fixed (for which cached
3057 data never expires). */
3058 static BOOL fixed_drives[26];
3060 /* Consider cached volume information to be stale if older than 10s,
3061 at least for non-local drives. Info for fixed drives is never stale. */
3062 #define DRIVE_INDEX( c ) ( (c) <= 'Z' ? (c) - 'A' : (c) - 'a' )
3063 #define VOLINFO_STILL_VALID( root_dir, info ) \
3064 ( ( isalpha (root_dir[0]) && \
3065 fixed_drives[ DRIVE_INDEX (root_dir[0]) ] ) \
3066 || GetTickCount () - info->timestamp < 10000 )
3068 /* Cache support functions. */
3070 /* Simple linked list with linear search is sufficient. */
3071 static volume_info_data *volume_cache = NULL;
3073 static volume_info_data *
3074 lookup_volume_info (char * root_dir)
3076 volume_info_data * info;
3078 for (info = volume_cache; info; info = info->next)
3079 if (xstrcasecmp (info->root_dir, root_dir) == 0)
3080 break;
3081 return info;
3084 static void
3085 add_volume_info (char * root_dir, volume_info_data * info)
3087 info->root_dir = xstrdup (root_dir);
3088 unixtodos_filename (info->root_dir);
3089 info->next = volume_cache;
3090 volume_cache = info;
3094 /* Wrapper for GetVolumeInformation, which uses caching to avoid
3095 performance penalty (~2ms on 486 for local drives, 7.5ms for local
3096 cdrom drive, ~5-10ms or more for remote drives on LAN). */
3097 static volume_info_data *
3098 GetCachedVolumeInformation (char * root_dir)
3100 volume_info_data * info;
3101 char default_root[ MAX_UTF8_PATH ];
3102 char name[MAX_PATH+1];
3103 char type[MAX_PATH+1];
3105 /* NULL for root_dir means use root from current directory. */
3106 if (root_dir == NULL)
3108 if (w32_unicode_filenames)
3110 wchar_t curdirw[MAX_PATH];
3112 if (GetCurrentDirectoryW (MAX_PATH, curdirw) == 0)
3113 return NULL;
3114 filename_from_utf16 (curdirw, default_root);
3116 else
3118 char curdira[MAX_PATH];
3120 if (GetCurrentDirectoryA (MAX_PATH, curdira) == 0)
3121 return NULL;
3122 filename_from_ansi (curdira, default_root);
3124 parse_root (default_root, (const char **)&root_dir);
3125 *root_dir = 0;
3126 root_dir = default_root;
3129 /* Local fixed drives can be cached permanently. Removable drives
3130 cannot be cached permanently, since the volume name and serial
3131 number (if nothing else) can change. Remote drives should be
3132 treated as if they are removable, since there is no sure way to
3133 tell whether they are or not. Also, the UNC association of drive
3134 letters mapped to remote volumes can be changed at any time (even
3135 by other processes) without notice.
3137 As a compromise, so we can benefit from caching info for remote
3138 volumes, we use a simple expiry mechanism to invalidate cache
3139 entries that are more than ten seconds old. */
3141 #if 0
3142 /* No point doing this, because WNetGetConnection is even slower than
3143 GetVolumeInformation, consistently taking ~50ms on a 486 (FWIW,
3144 GetDriveType is about the only call of this type which does not
3145 involve network access, and so is extremely quick). */
3147 /* Map drive letter to UNC if remote. */
3148 if (isalpha (root_dir[0]) && !fixed[DRIVE_INDEX (root_dir[0])])
3150 char remote_name[ 256 ];
3151 char drive[3] = { root_dir[0], ':' };
3153 if (WNetGetConnection (drive, remote_name, sizeof (remote_name))
3154 == NO_ERROR)
3155 /* do something */ ;
3157 #endif
3159 info = lookup_volume_info (root_dir);
3161 if (info == NULL || ! VOLINFO_STILL_VALID (root_dir, info))
3163 DWORD serialnum;
3164 DWORD maxcomp;
3165 DWORD flags;
3167 /* Info is not cached, or is stale. */
3168 if (w32_unicode_filenames)
3170 wchar_t root_w[MAX_PATH];
3171 wchar_t name_w[MAX_PATH+1];
3172 wchar_t type_w[MAX_PATH+1];
3174 filename_to_utf16 (root_dir, root_w);
3175 if (!GetVolumeInformationW (root_w,
3176 name_w, sizeof (name_w),
3177 &serialnum,
3178 &maxcomp,
3179 &flags,
3180 type_w, sizeof (type_w)))
3181 return NULL;
3182 /* Hmm... not really 100% correct, as these 2 are not file
3183 names... */
3184 filename_from_utf16 (name_w, name);
3185 filename_from_utf16 (type_w, type);
3187 else
3189 char root_a[MAX_PATH];
3190 char name_a[MAX_PATH+1];
3191 char type_a[MAX_PATH+1];
3193 filename_to_ansi (root_dir, root_a);
3194 if (!GetVolumeInformationA (root_a,
3195 name_a, sizeof (name_a),
3196 &serialnum,
3197 &maxcomp,
3198 &flags,
3199 type_a, sizeof (type_a)))
3200 return NULL;
3201 filename_from_ansi (name_a, name);
3202 filename_from_ansi (type_a, type);
3205 /* Cache the volume information for future use, overwriting existing
3206 entry if present. */
3207 if (info == NULL)
3209 info = xmalloc (sizeof (volume_info_data));
3210 add_volume_info (root_dir, info);
3212 else
3214 xfree (info->name);
3215 xfree (info->type);
3218 info->name = xstrdup (name);
3219 unixtodos_filename (info->name);
3220 info->serialnum = serialnum;
3221 info->maxcomp = maxcomp;
3222 info->flags = flags;
3223 info->type = xstrdup (type);
3224 info->timestamp = GetTickCount ();
3227 return info;
3230 /* Get information on the volume where NAME is held; set path pointer to
3231 start of pathname in NAME (past UNC header\volume header if present),
3232 if pPath is non-NULL.
3234 Note: if NAME includes symlinks, the information is for the volume
3235 of the symlink, not of its target. That's because, even though
3236 GetVolumeInformation returns information about the symlink target
3237 of its argument, we only pass the root directory to
3238 GetVolumeInformation, not the full NAME. */
3239 static int
3240 get_volume_info (const char * name, const char ** pPath)
3242 char temp[MAX_UTF8_PATH];
3243 char *rootname = NULL; /* default to current volume */
3244 volume_info_data * info;
3245 int root_len = parse_root (name, pPath);
3247 if (name == NULL)
3248 return FALSE;
3250 /* Copy the root name of the volume, if given. */
3251 if (root_len)
3253 strncpy (temp, name, root_len);
3254 temp[root_len] = '\0';
3255 unixtodos_filename (temp);
3256 rootname = temp;
3259 info = GetCachedVolumeInformation (rootname);
3260 if (info != NULL)
3262 /* Set global referenced by other functions. */
3263 volume_info = *info;
3264 return TRUE;
3266 return FALSE;
3269 /* Determine if volume is FAT format (ie. only supports short 8.3
3270 names); also set path pointer to start of pathname in name, if
3271 pPath is non-NULL. */
3272 static int
3273 is_fat_volume (const char * name, const char ** pPath)
3275 if (get_volume_info (name, pPath))
3276 return (volume_info.maxcomp == 12);
3277 return FALSE;
3280 /* Convert all slashes in a filename to backslashes, and map filename
3281 to a valid 8.3 name if necessary. The result is a pointer to a
3282 static buffer, so CAVEAT EMPTOR! */
3283 const char *map_w32_filename (const char *, const char **);
3285 const char *
3286 map_w32_filename (const char * name, const char ** pPath)
3288 static char shortname[MAX_UTF8_PATH];
3289 char * str = shortname;
3290 char c;
3291 char * path;
3292 const char * save_name = name;
3294 if (strlen (name) >= sizeof (shortname))
3296 /* Return a filename which will cause callers to fail. */
3297 strcpy (shortname, "?");
3298 return shortname;
3301 if (!fatal_error_in_progress /* disable fancy processing during crash */
3302 && is_fat_volume (name, (const char **)&path)) /* truncate to 8.3 */
3304 register int left = 8; /* maximum number of chars in part */
3305 register int extn = 0; /* extension added? */
3306 register int dots = 2; /* maximum number of dots allowed */
3308 while (name < path)
3309 *str++ = *name++; /* skip past UNC header */
3311 while ((c = *name++))
3313 switch ( c )
3315 case ':':
3316 case '\\':
3317 case '/':
3318 *str++ = (c == ':' ? ':' : '\\');
3319 extn = 0; /* reset extension flags */
3320 dots = 2; /* max 2 dots */
3321 left = 8; /* max length 8 for main part */
3322 break;
3323 case '.':
3324 if ( dots )
3326 /* Convert path components of the form .xxx to _xxx,
3327 but leave . and .. as they are. This allows .emacs
3328 to be read as _emacs, for example. */
3330 if (! *name ||
3331 *name == '.' ||
3332 IS_DIRECTORY_SEP (*name))
3334 *str++ = '.';
3335 dots--;
3337 else
3339 *str++ = '_';
3340 left--;
3341 dots = 0;
3344 else if ( !extn )
3346 *str++ = '.';
3347 extn = 1; /* we've got an extension */
3348 left = 3; /* 3 chars in extension */
3350 else
3352 /* any embedded dots after the first are converted to _ */
3353 *str++ = '_';
3355 break;
3356 case '~':
3357 case '#': /* don't lose these, they're important */
3358 if ( ! left )
3359 str[-1] = c; /* replace last character of part */
3360 /* FALLTHRU */
3361 default:
3362 if ( left && 'A' <= c && c <= 'Z' )
3364 *str++ = tolower (c); /* map to lower case (looks nicer) */
3365 left--;
3366 dots = 0; /* started a path component */
3368 break;
3371 *str = '\0';
3373 else
3375 strcpy (shortname, name);
3376 unixtodos_filename (shortname);
3379 if (pPath)
3380 *pPath = shortname + (path - save_name);
3382 return shortname;
3385 static int
3386 is_exec (const char * name)
3388 char * p = strrchr (name, '.');
3389 return
3390 (p != NULL
3391 && (xstrcasecmp (p, ".exe") == 0 ||
3392 xstrcasecmp (p, ".com") == 0 ||
3393 xstrcasecmp (p, ".bat") == 0 ||
3394 xstrcasecmp (p, ".cmd") == 0));
3397 /* Emulate the Unix directory procedures opendir, closedir, and
3398 readdir. We rename them to sys_* names because some versions of
3399 MinGW startup code call opendir and readdir to glob wildcards, and
3400 the code that calls them doesn't grok UTF-8 encoded file names we
3401 produce in dirent->d_name[]. */
3403 struct dirent dir_static; /* simulated directory contents */
3404 static HANDLE dir_find_handle = INVALID_HANDLE_VALUE;
3405 static int dir_is_fat;
3406 static char dir_pathname[MAX_UTF8_PATH];
3407 static WIN32_FIND_DATAW dir_find_data_w;
3408 static WIN32_FIND_DATAA dir_find_data_a;
3409 #define DIR_FIND_DATA_W 1
3410 #define DIR_FIND_DATA_A 2
3411 static int last_dir_find_data = -1;
3413 /* Support shares on a network resource as subdirectories of a read-only
3414 root directory. */
3415 static HANDLE wnet_enum_handle = INVALID_HANDLE_VALUE;
3416 static HANDLE open_unc_volume (const char *);
3417 static void *read_unc_volume (HANDLE, wchar_t *, char *, int);
3418 static void close_unc_volume (HANDLE);
3420 DIR *
3421 sys_opendir (const char *filename)
3423 DIR *dirp;
3425 /* Opening is done by FindFirstFile. However, a read is inherent to
3426 this operation, so we defer the open until read time. */
3428 if (dir_find_handle != INVALID_HANDLE_VALUE)
3429 return NULL;
3430 if (wnet_enum_handle != INVALID_HANDLE_VALUE)
3431 return NULL;
3433 /* Note: We don't support traversal of UNC volumes via symlinks.
3434 Doing so would mean punishing 99.99% of use cases by resolving
3435 all the possible symlinks in FILENAME, recursively. */
3436 if (is_unc_volume (filename))
3438 wnet_enum_handle = open_unc_volume (filename);
3439 if (wnet_enum_handle == INVALID_HANDLE_VALUE)
3440 return NULL;
3443 if (!(dirp = (DIR *) malloc (sizeof (DIR))))
3444 return NULL;
3446 dirp->dd_fd = 0;
3447 dirp->dd_loc = 0;
3448 dirp->dd_size = 0;
3450 strncpy (dir_pathname, map_w32_filename (filename, NULL), MAX_UTF8_PATH - 1);
3451 dir_pathname[MAX_UTF8_PATH - 1] = '\0';
3452 /* Note: We don't support symlinks to file names on FAT volumes.
3453 Doing so would mean punishing 99.99% of use cases by resolving
3454 all the possible symlinks in FILENAME, recursively. */
3455 dir_is_fat = is_fat_volume (filename, NULL);
3457 return dirp;
3460 void
3461 sys_closedir (DIR *dirp)
3463 /* If we have a find-handle open, close it. */
3464 if (dir_find_handle != INVALID_HANDLE_VALUE)
3466 FindClose (dir_find_handle);
3467 dir_find_handle = INVALID_HANDLE_VALUE;
3469 else if (wnet_enum_handle != INVALID_HANDLE_VALUE)
3471 close_unc_volume (wnet_enum_handle);
3472 wnet_enum_handle = INVALID_HANDLE_VALUE;
3474 xfree ((char *) dirp);
3477 struct dirent *
3478 sys_readdir (DIR *dirp)
3480 int downcase = !NILP (Vw32_downcase_file_names);
3482 if (wnet_enum_handle != INVALID_HANDLE_VALUE)
3484 if (!read_unc_volume (wnet_enum_handle,
3485 dir_find_data_w.cFileName,
3486 dir_find_data_a.cFileName,
3487 MAX_PATH))
3488 return NULL;
3490 /* If we aren't dir_finding, do a find-first, otherwise do a find-next. */
3491 else if (dir_find_handle == INVALID_HANDLE_VALUE)
3493 char filename[MAX_UTF8_PATH];
3494 int ln;
3495 bool last_slash = true;
3497 /* Note: We don't need to worry about dir_pathname being longer
3498 than MAX_UTF8_PATH, as sys_opendir already took care of that
3499 when it called map_w32_filename: that function will put a "?"
3500 in its return value in that case, thus failing all the calls
3501 below. */
3502 strcpy (filename, dir_pathname);
3503 ln = strlen (filename);
3504 if (!IS_DIRECTORY_SEP (filename[ln - 1]))
3505 last_slash = false;
3507 /* Note: No need to resolve symlinks in FILENAME, because
3508 FindFirst opens the directory that is the target of a
3509 symlink. */
3510 if (w32_unicode_filenames)
3512 wchar_t fnw[MAX_PATH + 2];
3514 filename_to_utf16 (filename, fnw);
3515 if (!last_slash)
3516 wcscat (fnw, L"\\");
3517 wcscat (fnw, L"*");
3518 dir_find_handle = FindFirstFileW (fnw, &dir_find_data_w);
3520 else
3522 char fna[MAX_PATH + 2];
3524 filename_to_ansi (filename, fna);
3525 if (!last_slash)
3526 strcat (fna, "\\");
3527 strcat (fna, "*");
3528 /* If FILENAME is not representable by the current ANSI
3529 codepage, we don't want FindFirstFileA to interpret the
3530 '?' characters as a wildcard. */
3531 if (_mbspbrk (fna, "?"))
3532 dir_find_handle = INVALID_HANDLE_VALUE;
3533 else
3534 dir_find_handle = FindFirstFileA (fna, &dir_find_data_a);
3537 if (dir_find_handle == INVALID_HANDLE_VALUE)
3539 /* Any changes in the value of errno here should be in sync
3540 with what directory_files_internal does when it calls
3541 readdir. */
3542 switch (GetLastError ())
3544 /* Windows uses this value when FindFirstFile finds no
3545 files that match the wildcard. This is not supposed
3546 to happen, since our wildcard is "*", but just in
3547 case, if there's some weird empty directory with not
3548 even "." and ".." entries... */
3549 case ERROR_FILE_NOT_FOUND:
3550 errno = 0;
3551 /* FALLTHRU */
3552 default:
3553 break;
3554 case ERROR_ACCESS_DENIED:
3555 case ERROR_NETWORK_ACCESS_DENIED:
3556 errno = EACCES;
3557 break;
3558 case ERROR_PATH_NOT_FOUND:
3559 case ERROR_INVALID_DRIVE:
3560 case ERROR_NOT_READY:
3561 case ERROR_BAD_NETPATH:
3562 case ERROR_BAD_NET_NAME:
3563 errno = ENOENT;
3564 break;
3566 return NULL;
3569 else if (w32_unicode_filenames)
3571 if (!FindNextFileW (dir_find_handle, &dir_find_data_w))
3573 errno = 0;
3574 return NULL;
3577 else
3579 if (!FindNextFileA (dir_find_handle, &dir_find_data_a))
3581 errno = 0;
3582 return NULL;
3586 /* Emacs never uses this value, so don't bother making it match
3587 value returned by stat(). */
3588 dir_static.d_ino = 1;
3590 if (w32_unicode_filenames)
3592 if (downcase || dir_is_fat)
3594 wchar_t tem[MAX_PATH];
3596 wcscpy (tem, dir_find_data_w.cFileName);
3597 CharLowerW (tem);
3598 filename_from_utf16 (tem, dir_static.d_name);
3600 else
3601 filename_from_utf16 (dir_find_data_w.cFileName, dir_static.d_name);
3602 last_dir_find_data = DIR_FIND_DATA_W;
3604 else
3606 char tem[MAX_PATH];
3608 /* If the file name in cFileName[] includes `?' characters, it
3609 means the original file name used characters that cannot be
3610 represented by the current ANSI codepage. To avoid total
3611 lossage, retrieve the short 8+3 alias of the long file
3612 name. */
3613 if (_mbspbrk (dir_find_data_a.cFileName, "?"))
3615 strcpy (tem, dir_find_data_a.cAlternateFileName);
3616 /* 8+3 aliases are returned in all caps, which could break
3617 various alists that look at filenames' extensions. */
3618 downcase = 1;
3620 else if (downcase || dir_is_fat)
3621 strcpy (tem, dir_find_data_a.cFileName);
3622 else
3623 filename_from_ansi (dir_find_data_a.cFileName, dir_static.d_name);
3624 if (downcase || dir_is_fat)
3626 _mbslwr (tem);
3627 filename_from_ansi (tem, dir_static.d_name);
3629 last_dir_find_data = DIR_FIND_DATA_A;
3632 dir_static.d_namlen = strlen (dir_static.d_name);
3633 dir_static.d_reclen = sizeof (struct dirent) - MAX_UTF8_PATH + 3 +
3634 dir_static.d_namlen - dir_static.d_namlen % 4;
3636 return &dir_static;
3639 static HANDLE
3640 open_unc_volume (const char *path)
3642 const char *fn = map_w32_filename (path, NULL);
3643 DWORD result;
3644 HANDLE henum;
3646 if (w32_unicode_filenames)
3648 NETRESOURCEW nrw;
3649 wchar_t fnw[MAX_PATH];
3651 nrw.dwScope = RESOURCE_GLOBALNET;
3652 nrw.dwType = RESOURCETYPE_DISK;
3653 nrw.dwDisplayType = RESOURCEDISPLAYTYPE_SERVER;
3654 nrw.dwUsage = RESOURCEUSAGE_CONTAINER;
3655 nrw.lpLocalName = NULL;
3656 filename_to_utf16 (fn, fnw);
3657 nrw.lpRemoteName = fnw;
3658 nrw.lpComment = NULL;
3659 nrw.lpProvider = NULL;
3661 result = WNetOpenEnumW (RESOURCE_GLOBALNET, RESOURCETYPE_DISK,
3662 RESOURCEUSAGE_CONNECTABLE, &nrw, &henum);
3664 else
3666 NETRESOURCEA nra;
3667 char fna[MAX_PATH];
3669 nra.dwScope = RESOURCE_GLOBALNET;
3670 nra.dwType = RESOURCETYPE_DISK;
3671 nra.dwDisplayType = RESOURCEDISPLAYTYPE_SERVER;
3672 nra.dwUsage = RESOURCEUSAGE_CONTAINER;
3673 nra.lpLocalName = NULL;
3674 filename_to_ansi (fn, fna);
3675 nra.lpRemoteName = fna;
3676 nra.lpComment = NULL;
3677 nra.lpProvider = NULL;
3679 result = WNetOpenEnumA (RESOURCE_GLOBALNET, RESOURCETYPE_DISK,
3680 RESOURCEUSAGE_CONNECTABLE, &nra, &henum);
3682 if (result == NO_ERROR)
3683 return henum;
3684 else
3686 /* Make sure directory_files_internal reports a sensible error. */
3687 errno = ENOENT;
3688 return INVALID_HANDLE_VALUE;
3692 static void *
3693 read_unc_volume (HANDLE henum, wchar_t *fname_w, char *fname_a, int size)
3695 DWORD count;
3696 int result;
3697 char *buffer;
3698 DWORD bufsize = 512;
3699 void *retval;
3701 count = 1;
3702 if (w32_unicode_filenames)
3704 wchar_t *ptrw;
3706 bufsize *= 2;
3707 buffer = alloca (bufsize);
3708 result = WNetEnumResourceW (henum, &count, buffer, &bufsize);
3709 if (result != NO_ERROR)
3710 return NULL;
3711 /* WNetEnumResource returns \\resource\share...skip forward to "share". */
3712 ptrw = ((LPNETRESOURCEW) buffer)->lpRemoteName;
3713 ptrw += 2;
3714 while (*ptrw && *ptrw != L'/' && *ptrw != L'\\') ptrw++;
3715 ptrw++;
3716 wcsncpy (fname_w, ptrw, size);
3717 retval = fname_w;
3719 else
3721 int dbcs_p = max_filename_mbslen () > 1;
3722 char *ptra;
3724 buffer = alloca (bufsize);
3725 result = WNetEnumResourceA (henum, &count, buffer, &bufsize);
3726 if (result != NO_ERROR)
3727 return NULL;
3728 ptra = ((LPNETRESOURCEA) buffer)->lpRemoteName;
3729 ptra += 2;
3730 if (!dbcs_p)
3731 while (*ptra && !IS_DIRECTORY_SEP (*ptra)) ptra++;
3732 else
3734 while (*ptra && !IS_DIRECTORY_SEP (*ptra))
3735 ptra = CharNextExA (file_name_codepage, ptra, 0);
3737 ptra++;
3738 strncpy (fname_a, ptra, size);
3739 retval = fname_a;
3742 return retval;
3745 static void
3746 close_unc_volume (HANDLE henum)
3748 if (henum != INVALID_HANDLE_VALUE)
3749 WNetCloseEnum (henum);
3752 static DWORD
3753 unc_volume_file_attributes (const char *path)
3755 HANDLE henum;
3756 DWORD attrs;
3758 henum = open_unc_volume (path);
3759 if (henum == INVALID_HANDLE_VALUE)
3760 return -1;
3762 attrs = FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_DIRECTORY;
3764 close_unc_volume (henum);
3766 return attrs;
3769 /* Ensure a network connection is authenticated. */
3770 static void
3771 logon_network_drive (const char *path)
3773 char share[MAX_UTF8_PATH];
3774 int n_slashes;
3775 char drive[4];
3776 UINT drvtype;
3777 char *p;
3778 DWORD val;
3780 if (IS_DIRECTORY_SEP (path[0]) && IS_DIRECTORY_SEP (path[1]))
3781 drvtype = DRIVE_REMOTE;
3782 else if (path[0] == '\0' || path[1] != ':')
3783 drvtype = GetDriveType (NULL);
3784 else
3786 drive[0] = path[0];
3787 drive[1] = ':';
3788 drive[2] = '\\';
3789 drive[3] = '\0';
3790 drvtype = GetDriveType (drive);
3793 /* Only logon to networked drives. */
3794 if (drvtype != DRIVE_REMOTE)
3795 return;
3797 n_slashes = 2;
3798 strncpy (share, path, MAX_UTF8_PATH);
3799 /* Truncate to just server and share name. */
3800 for (p = share + 2; *p && p < share + MAX_UTF8_PATH; p++)
3802 if (IS_DIRECTORY_SEP (*p) && ++n_slashes > 3)
3804 *p = '\0';
3805 break;
3809 if (w32_unicode_filenames)
3811 NETRESOURCEW resourcew;
3812 wchar_t share_w[MAX_PATH];
3814 resourcew.dwScope = RESOURCE_GLOBALNET;
3815 resourcew.dwType = RESOURCETYPE_DISK;
3816 resourcew.dwDisplayType = RESOURCEDISPLAYTYPE_SHARE;
3817 resourcew.dwUsage = RESOURCEUSAGE_CONTAINER;
3818 resourcew.lpLocalName = NULL;
3819 filename_to_utf16 (share, share_w);
3820 resourcew.lpRemoteName = share_w;
3821 resourcew.lpProvider = NULL;
3823 val = WNetAddConnection2W (&resourcew, NULL, NULL, CONNECT_INTERACTIVE);
3825 else
3827 NETRESOURCEA resourcea;
3828 char share_a[MAX_PATH];
3830 resourcea.dwScope = RESOURCE_GLOBALNET;
3831 resourcea.dwType = RESOURCETYPE_DISK;
3832 resourcea.dwDisplayType = RESOURCEDISPLAYTYPE_SHARE;
3833 resourcea.dwUsage = RESOURCEUSAGE_CONTAINER;
3834 resourcea.lpLocalName = NULL;
3835 filename_to_ansi (share, share_a);
3836 resourcea.lpRemoteName = share_a;
3837 resourcea.lpProvider = NULL;
3839 val = WNetAddConnection2A (&resourcea, NULL, NULL, CONNECT_INTERACTIVE);
3842 switch (val)
3844 case NO_ERROR:
3845 case ERROR_ALREADY_ASSIGNED:
3846 break;
3847 case ERROR_ACCESS_DENIED:
3848 case ERROR_LOGON_FAILURE:
3849 errno = EACCES;
3850 break;
3851 case ERROR_BUSY:
3852 errno = EAGAIN;
3853 break;
3854 case ERROR_BAD_NET_NAME:
3855 case ERROR_NO_NET_OR_BAD_PATH:
3856 case ERROR_NO_NETWORK:
3857 case ERROR_CANCELLED:
3858 default:
3859 errno = ENOENT;
3860 break;
3864 /* Emulate faccessat(2). */
3866 faccessat (int dirfd, const char * path, int mode, int flags)
3868 DWORD attributes;
3870 if (dirfd != AT_FDCWD
3871 && !(IS_DIRECTORY_SEP (path[0])
3872 || IS_DEVICE_SEP (path[1])))
3874 errno = EBADF;
3875 return -1;
3878 /* MSVCRT implementation of 'access' doesn't recognize D_OK, and its
3879 newer versions blow up when passed D_OK. */
3880 path = map_w32_filename (path, NULL);
3881 /* If the last element of PATH is a symlink, we need to resolve it
3882 to get the attributes of its target file. Note: any symlinks in
3883 PATH elements other than the last one are transparently resolved
3884 by GetFileAttributes below. */
3885 if ((volume_info.flags & FILE_SUPPORTS_REPARSE_POINTS) != 0
3886 && (flags & AT_SYMLINK_NOFOLLOW) == 0)
3887 path = chase_symlinks (path);
3889 if (w32_unicode_filenames)
3891 wchar_t path_w[MAX_PATH];
3893 filename_to_utf16 (path, path_w);
3894 attributes = GetFileAttributesW (path_w);
3896 else
3898 char path_a[MAX_PATH];
3900 filename_to_ansi (path, path_a);
3901 attributes = GetFileAttributesA (path_a);
3904 if (attributes == -1)
3906 DWORD w32err = GetLastError ();
3908 switch (w32err)
3910 case ERROR_INVALID_NAME:
3911 case ERROR_BAD_PATHNAME:
3912 if (is_unc_volume (path))
3914 attributes = unc_volume_file_attributes (path);
3915 if (attributes == -1)
3917 errno = EACCES;
3918 return -1;
3920 goto check_attrs;
3922 /* FALLTHROUGH */
3923 case ERROR_FILE_NOT_FOUND:
3924 case ERROR_BAD_NETPATH:
3925 errno = ENOENT;
3926 break;
3927 default:
3928 errno = EACCES;
3929 break;
3931 return -1;
3934 check_attrs:
3935 if ((mode & X_OK) != 0
3936 && !(is_exec (path) || (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0))
3938 errno = EACCES;
3939 return -1;
3941 if ((mode & W_OK) != 0 && (attributes & FILE_ATTRIBUTE_READONLY) != 0)
3943 errno = EACCES;
3944 return -1;
3946 if ((mode & D_OK) != 0 && (attributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
3948 errno = EACCES;
3949 return -1;
3951 return 0;
3954 /* A special test for DIRNAME being a directory accessible by the
3955 current user. This is needed because the security permissions in
3956 directory's ACLs are not visible in the Posix-style mode bits
3957 returned by 'stat' and in attributes returned by GetFileAttributes.
3958 So a directory would seem like it's readable by the current user,
3959 but will in fact error out with EACCES when they actually try. */
3961 w32_accessible_directory_p (const char *dirname, ptrdiff_t dirlen)
3963 char pattern[MAX_UTF8_PATH];
3964 bool last_slash = dirlen > 0 && IS_DIRECTORY_SEP (dirname[dirlen - 1]);
3965 HANDLE dh;
3967 /* Network volumes need a different reading method. */
3968 if (is_unc_volume (dirname))
3970 void *read_result = NULL;
3971 wchar_t fnw[MAX_PATH];
3972 char fna[MAX_PATH];
3974 dh = open_unc_volume (dirname);
3975 if (dh != INVALID_HANDLE_VALUE)
3977 read_result = read_unc_volume (dh, fnw, fna, MAX_PATH);
3978 close_unc_volume (dh);
3980 /* Treat empty volumes as accessible. */
3981 return read_result != NULL || GetLastError () == ERROR_NO_MORE_ITEMS;
3984 /* Note: map_w32_filename makes sure DIRNAME is not longer than
3985 MAX_UTF8_PATH. */
3986 strcpy (pattern, map_w32_filename (dirname, NULL));
3988 /* Note: No need to resolve symlinks in FILENAME, because FindFirst
3989 opens the directory that is the target of a symlink. */
3990 if (w32_unicode_filenames)
3992 wchar_t pat_w[MAX_PATH + 2];
3993 WIN32_FIND_DATAW dfd_w;
3995 filename_to_utf16 (pattern, pat_w);
3996 if (!last_slash)
3997 wcscat (pat_w, L"\\");
3998 wcscat (pat_w, L"*");
3999 dh = FindFirstFileW (pat_w, &dfd_w);
4001 else
4003 char pat_a[MAX_PATH + 2];
4004 WIN32_FIND_DATAA dfd_a;
4006 filename_to_ansi (pattern, pat_a);
4007 if (!last_slash)
4008 strcpy (pat_a, "\\");
4009 strcat (pat_a, "*");
4010 /* In case DIRNAME cannot be expressed in characters from the
4011 current ANSI codepage. */
4012 if (_mbspbrk (pat_a, "?"))
4013 dh = INVALID_HANDLE_VALUE;
4014 else
4015 dh = FindFirstFileA (pat_a, &dfd_a);
4018 if (dh == INVALID_HANDLE_VALUE)
4019 return 0;
4020 FindClose (dh);
4021 return 1;
4024 /* A version of 'access' to be used locally with file names in
4025 locale-specific encoding. Does not resolve symlinks and does not
4026 support file names on FAT12 and FAT16 volumes, but that's OK, since
4027 we only invoke this function for files inside the Emacs source or
4028 installation tree, on directories (so any symlinks should have the
4029 directory bit set), and on short file names such as "C:/.emacs". */
4030 static int
4031 sys_access (const char *fname, int mode)
4033 char fname_copy[MAX_PATH], *p;
4034 DWORD attributes;
4036 strcpy (fname_copy, fname);
4037 /* Do the equivalent of unixtodos_filename. */
4038 for (p = fname_copy; *p; p = CharNext (p))
4039 if (*p == '/')
4040 *p = '\\';
4042 if ((attributes = GetFileAttributesA (fname_copy)) == -1)
4044 DWORD w32err = GetLastError ();
4046 switch (w32err)
4048 case ERROR_INVALID_NAME:
4049 case ERROR_BAD_PATHNAME:
4050 case ERROR_FILE_NOT_FOUND:
4051 case ERROR_BAD_NETPATH:
4052 errno = ENOENT;
4053 break;
4054 default:
4055 errno = EACCES;
4056 break;
4058 return -1;
4060 if ((mode & X_OK) != 0
4061 && !(is_exec (fname_copy)
4062 || (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0))
4064 errno = EACCES;
4065 return -1;
4067 if ((mode & W_OK) != 0 && (attributes & FILE_ATTRIBUTE_READONLY) != 0)
4069 errno = EACCES;
4070 return -1;
4072 if ((mode & D_OK) != 0 && (attributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
4074 errno = EACCES;
4075 return -1;
4077 return 0;
4080 /* Shadow some MSVC runtime functions to map requests for long filenames
4081 to reasonable short names if necessary. This was originally added to
4082 permit running Emacs on NT 3.1 on a FAT partition, which doesn't support
4083 long file names. */
4086 sys_chdir (const char * path)
4088 path = map_w32_filename (path, NULL);
4089 if (w32_unicode_filenames)
4091 wchar_t newdir_w[MAX_PATH];
4093 if (filename_to_utf16 (path, newdir_w) == 0)
4094 return _wchdir (newdir_w);
4095 return -1;
4097 else
4099 char newdir_a[MAX_PATH];
4101 if (filename_to_ansi (path, newdir_a) == 0)
4102 return _chdir (newdir_a);
4103 return -1;
4108 sys_chmod (const char * path, int mode)
4110 path = chase_symlinks (map_w32_filename (path, NULL));
4111 if (w32_unicode_filenames)
4113 wchar_t path_w[MAX_PATH];
4115 filename_to_utf16 (path, path_w);
4116 return _wchmod (path_w, mode);
4118 else
4120 char path_a[MAX_PATH];
4122 filename_to_ansi (path, path_a);
4123 return _chmod (path_a, mode);
4128 sys_creat (const char * path, int mode)
4130 path = map_w32_filename (path, NULL);
4131 if (w32_unicode_filenames)
4133 wchar_t path_w[MAX_PATH];
4135 filename_to_utf16 (path, path_w);
4136 return _wcreat (path_w, mode);
4138 else
4140 char path_a[MAX_PATH];
4142 filename_to_ansi (path, path_a);
4143 return _creat (path_a, mode);
4147 FILE *
4148 sys_fopen (const char * path, const char * mode)
4150 int fd;
4151 int oflag;
4152 const char * mode_save = mode;
4154 /* Force all file handles to be non-inheritable. This is necessary to
4155 ensure child processes don't unwittingly inherit handles that might
4156 prevent future file access. */
4158 if (mode[0] == 'r')
4159 oflag = O_RDONLY;
4160 else if (mode[0] == 'w' || mode[0] == 'a')
4161 oflag = O_WRONLY | O_CREAT | O_TRUNC;
4162 else
4163 return NULL;
4165 /* Only do simplistic option parsing. */
4166 while (*++mode)
4167 if (mode[0] == '+')
4169 oflag &= ~(O_RDONLY | O_WRONLY);
4170 oflag |= O_RDWR;
4172 else if (mode[0] == 'b')
4174 oflag &= ~O_TEXT;
4175 oflag |= O_BINARY;
4177 else if (mode[0] == 't')
4179 oflag &= ~O_BINARY;
4180 oflag |= O_TEXT;
4182 else break;
4184 path = map_w32_filename (path, NULL);
4185 if (w32_unicode_filenames)
4187 wchar_t path_w[MAX_PATH];
4189 filename_to_utf16 (path, path_w);
4190 fd = _wopen (path_w, oflag | _O_NOINHERIT, 0644);
4192 else
4194 char path_a[MAX_PATH];
4196 filename_to_ansi (path, path_a);
4197 fd = _open (path_a, oflag | _O_NOINHERIT, 0644);
4199 if (fd < 0)
4200 return NULL;
4202 return _fdopen (fd, mode_save);
4205 /* This only works on NTFS volumes, but is useful to have. */
4207 sys_link (const char * old, const char * new)
4209 HANDLE fileh;
4210 int result = -1;
4211 char oldname[MAX_UTF8_PATH], newname[MAX_UTF8_PATH];
4212 wchar_t oldname_w[MAX_PATH];
4213 char oldname_a[MAX_PATH];
4215 if (old == NULL || new == NULL)
4217 errno = ENOENT;
4218 return -1;
4221 strcpy (oldname, map_w32_filename (old, NULL));
4222 strcpy (newname, map_w32_filename (new, NULL));
4224 if (w32_unicode_filenames)
4226 filename_to_utf16 (oldname, oldname_w);
4227 fileh = CreateFileW (oldname_w, 0, 0, NULL, OPEN_EXISTING,
4228 FILE_FLAG_BACKUP_SEMANTICS, NULL);
4230 else
4232 filename_to_ansi (oldname, oldname_a);
4233 fileh = CreateFileA (oldname_a, 0, 0, NULL, OPEN_EXISTING,
4234 FILE_FLAG_BACKUP_SEMANTICS, NULL);
4236 if (fileh != INVALID_HANDLE_VALUE)
4238 int wlen;
4240 /* Confusingly, the "alternate" stream name field does not apply
4241 when restoring a hard link, and instead contains the actual
4242 stream data for the link (ie. the name of the link to create).
4243 The WIN32_STREAM_ID structure before the cStreamName field is
4244 the stream header, which is then immediately followed by the
4245 stream data. */
4247 struct {
4248 WIN32_STREAM_ID wid;
4249 WCHAR wbuffer[MAX_PATH]; /* extra space for link name */
4250 } data;
4252 /* We used to pass MB_PRECOMPOSED as the 2nd arg here, but MSDN
4253 indicates that flag is unsupported for CP_UTF8, and OTOH says
4254 it is the default anyway. */
4255 wlen = pMultiByteToWideChar (CP_UTF8, 0, newname, -1,
4256 data.wid.cStreamName, MAX_PATH);
4257 if (wlen > 0)
4259 LPVOID context = NULL;
4260 DWORD wbytes = 0;
4262 data.wid.dwStreamId = BACKUP_LINK;
4263 data.wid.dwStreamAttributes = 0;
4264 data.wid.Size.LowPart = wlen * sizeof (WCHAR);
4265 data.wid.Size.HighPart = 0;
4266 data.wid.dwStreamNameSize = 0;
4268 if (BackupWrite (fileh, (LPBYTE)&data,
4269 offsetof (WIN32_STREAM_ID, cStreamName)
4270 + data.wid.Size.LowPart,
4271 &wbytes, FALSE, FALSE, &context)
4272 && BackupWrite (fileh, NULL, 0, &wbytes, TRUE, FALSE, &context))
4274 /* succeeded */
4275 result = 0;
4277 else
4279 DWORD err = GetLastError ();
4280 DWORD attributes;
4282 switch (err)
4284 case ERROR_ACCESS_DENIED:
4285 /* This is what happens when OLDNAME is a directory,
4286 since Windows doesn't support hard links to
4287 directories. Posix says to set errno to EPERM in
4288 that case. */
4289 if (w32_unicode_filenames)
4290 attributes = GetFileAttributesW (oldname_w);
4291 else
4292 attributes = GetFileAttributesA (oldname_a);
4293 if (attributes != -1
4294 && (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
4295 errno = EPERM;
4296 else if (attributes == -1
4297 && is_unc_volume (oldname)
4298 && unc_volume_file_attributes (oldname) != -1)
4299 errno = EPERM;
4300 else
4301 errno = EACCES;
4302 break;
4303 case ERROR_TOO_MANY_LINKS:
4304 errno = EMLINK;
4305 break;
4306 case ERROR_NOT_SAME_DEVICE:
4307 errno = EXDEV;
4308 break;
4309 default:
4310 errno = EINVAL;
4311 break;
4316 CloseHandle (fileh);
4318 else
4319 errno = ENOENT;
4321 return result;
4325 sys_mkdir (const char * path)
4327 path = map_w32_filename (path, NULL);
4329 if (w32_unicode_filenames)
4331 wchar_t path_w[MAX_PATH];
4333 filename_to_utf16 (path, path_w);
4334 return _wmkdir (path_w);
4336 else
4338 char path_a[MAX_PATH];
4340 filename_to_ansi (path, path_a);
4341 return _mkdir (path_a);
4346 sys_open (const char * path, int oflag, int mode)
4348 const char* mpath = map_w32_filename (path, NULL);
4349 int res = -1;
4351 if (w32_unicode_filenames)
4353 wchar_t mpath_w[MAX_PATH];
4355 filename_to_utf16 (mpath, mpath_w);
4356 /* If possible, try to open file without _O_CREAT, to be able to
4357 write to existing hidden and system files. Force all file
4358 handles to be non-inheritable. */
4359 if ((oflag & (_O_CREAT | _O_EXCL)) != (_O_CREAT | _O_EXCL))
4360 res = _wopen (mpath_w, (oflag & ~_O_CREAT) | _O_NOINHERIT, mode);
4361 if (res < 0)
4362 res = _wopen (mpath_w, oflag | _O_NOINHERIT, mode);
4364 else
4366 char mpath_a[MAX_PATH];
4368 filename_to_ansi (mpath, mpath_a);
4369 if ((oflag & (_O_CREAT | _O_EXCL)) != (_O_CREAT | _O_EXCL))
4370 res = _open (mpath_a, (oflag & ~_O_CREAT) | _O_NOINHERIT, mode);
4371 if (res < 0)
4372 res = _open (mpath_a, oflag | _O_NOINHERIT, mode);
4375 return res;
4378 /* Implementation of mkostemp for MS-Windows, to avoid race conditions
4379 when using mktemp.
4381 Standard algorithm for generating a temporary file name seems to be
4382 use pid or tid with a letter on the front (in place of the 6 X's)
4383 and cycle through the letters to find a unique name. We extend
4384 that to allow any reasonable character as the first of the 6 X's,
4385 so that the number of simultaneously used temporary files will be
4386 greater. */
4389 mkostemp (char * template, int flags)
4391 char * p;
4392 int i, fd = -1;
4393 unsigned uid = GetCurrentThreadId ();
4394 int save_errno = errno;
4395 static char first_char[] = "abcdefghijklmnopqrstuvwyz0123456789!%-_@#";
4397 errno = EINVAL;
4398 if (template == NULL)
4399 return -1;
4401 p = template + strlen (template);
4402 i = 5;
4403 /* replace up to the last 5 X's with uid in decimal */
4404 while (--p >= template && p[0] == 'X' && --i >= 0)
4406 p[0] = '0' + uid % 10;
4407 uid /= 10;
4410 if (i < 0 && p[0] == 'X')
4412 i = 0;
4415 p[0] = first_char[i];
4416 if ((fd = sys_open (template,
4417 flags | _O_CREAT | _O_EXCL | _O_RDWR,
4418 S_IRUSR | S_IWUSR)) >= 0
4419 || errno != EEXIST)
4421 if (fd >= 0)
4422 errno = save_errno;
4423 return fd;
4426 while (++i < sizeof (first_char));
4429 /* Template is badly formed or else we can't generate a unique name. */
4430 return -1;
4434 fchmod (int fd, mode_t mode)
4436 return 0;
4440 sys_rename_replace (const char *oldname, const char *newname, BOOL force)
4442 BOOL result;
4443 char temp[MAX_UTF8_PATH], temp_a[MAX_PATH];;
4444 int newname_dev;
4445 int oldname_dev;
4446 bool have_temp_a = false;
4448 /* MoveFile on Windows 95 doesn't correctly change the short file name
4449 alias in a number of circumstances (it is not easy to predict when
4450 just by looking at oldname and newname, unfortunately). In these
4451 cases, renaming through a temporary name avoids the problem.
4453 A second problem on Windows 95 is that renaming through a temp name when
4454 newname is uppercase fails (the final long name ends up in
4455 lowercase, although the short alias might be uppercase) UNLESS the
4456 long temp name is not 8.3.
4458 So, on Windows 95 we always rename through a temp name, and we make sure
4459 the temp name has a long extension to ensure correct renaming. */
4461 strcpy (temp, map_w32_filename (oldname, NULL));
4463 /* volume_info is set indirectly by map_w32_filename. */
4464 oldname_dev = volume_info.serialnum;
4466 if (os_subtype == OS_9X)
4468 char * o;
4469 char * p;
4470 int i = 0;
4471 char oldname_a[MAX_PATH];
4473 oldname = map_w32_filename (oldname, NULL);
4474 filename_to_ansi (oldname, oldname_a);
4475 filename_to_ansi (temp, temp_a);
4476 if ((o = strrchr (oldname_a, '\\')))
4477 o++;
4478 else
4479 o = (char *) oldname_a;
4481 if ((p = strrchr (temp_a, '\\')))
4482 p++;
4483 else
4484 p = temp_a;
4488 /* Force temp name to require a manufactured 8.3 alias - this
4489 seems to make the second rename work properly. */
4490 sprintf (p, "_.%s.%d", o, i);
4491 i++;
4492 result = rename (oldname_a, temp_a);
4494 /* This loop must surely terminate! */
4495 while (result < 0 && errno == EEXIST);
4496 if (result < 0)
4497 return -1;
4498 have_temp_a = true;
4501 /* If FORCE, emulate Unix behavior - newname is deleted if it already exists
4502 (at least if it is a file; don't do this for directories).
4504 Since we mustn't do this if we are just changing the case of the
4505 file name (we would end up deleting the file we are trying to
4506 rename!), we let rename detect if the destination file already
4507 exists - that way we avoid the possible pitfalls of trying to
4508 determine ourselves whether two names really refer to the same
4509 file, which is not always possible in the general case. (Consider
4510 all the permutations of shared or subst'd drives, etc.) */
4512 newname = map_w32_filename (newname, NULL);
4514 /* volume_info is set indirectly by map_w32_filename. */
4515 newname_dev = volume_info.serialnum;
4517 if (w32_unicode_filenames)
4519 wchar_t temp_w[MAX_PATH], newname_w[MAX_PATH];
4521 filename_to_utf16 (temp, temp_w);
4522 filename_to_utf16 (newname, newname_w);
4523 result = _wrename (temp_w, newname_w);
4524 if (result < 0 && force)
4526 DWORD w32err = GetLastError ();
4528 if (errno == EACCES
4529 && newname_dev != oldname_dev)
4531 /* The implementation of `rename' on Windows does not return
4532 errno = EXDEV when you are moving a directory to a
4533 different storage device (ex. logical disk). It returns
4534 EACCES instead. So here we handle such situations and
4535 return EXDEV. */
4536 DWORD attributes;
4538 if ((attributes = GetFileAttributesW (temp_w)) != -1
4539 && (attributes & FILE_ATTRIBUTE_DIRECTORY))
4540 errno = EXDEV;
4542 else if (errno == EEXIST)
4544 if (_wchmod (newname_w, 0666) != 0)
4545 return result;
4546 if (_wunlink (newname_w) != 0)
4547 return result;
4548 result = _wrename (temp_w, newname_w);
4550 else if (w32err == ERROR_PRIVILEGE_NOT_HELD
4551 && is_symlink (temp))
4553 /* This is Windows prohibiting the user from creating a
4554 symlink in another place, since that requires
4555 privileges. */
4556 errno = EPERM;
4560 else
4562 char newname_a[MAX_PATH];
4564 if (!have_temp_a)
4565 filename_to_ansi (temp, temp_a);
4566 filename_to_ansi (newname, newname_a);
4567 result = rename (temp_a, newname_a);
4568 if (result < 0 && force)
4570 DWORD w32err = GetLastError ();
4572 if (errno == EACCES
4573 && newname_dev != oldname_dev)
4575 DWORD attributes;
4577 if ((attributes = GetFileAttributesA (temp_a)) != -1
4578 && (attributes & FILE_ATTRIBUTE_DIRECTORY))
4579 errno = EXDEV;
4581 else if (errno == EEXIST)
4583 if (_chmod (newname_a, 0666) != 0)
4584 return result;
4585 if (_unlink (newname_a) != 0)
4586 return result;
4587 result = rename (temp_a, newname_a);
4589 else if (w32err == ERROR_PRIVILEGE_NOT_HELD
4590 && is_symlink (temp))
4591 errno = EPERM;
4595 return result;
4599 sys_rename (char const *old, char const *new)
4601 return sys_rename_replace (old, new, TRUE);
4605 sys_rmdir (const char * path)
4607 path = map_w32_filename (path, NULL);
4609 if (w32_unicode_filenames)
4611 wchar_t path_w[MAX_PATH];
4613 filename_to_utf16 (path, path_w);
4614 return _wrmdir (path_w);
4616 else
4618 char path_a[MAX_PATH];
4620 filename_to_ansi (path, path_a);
4621 return _rmdir (path_a);
4626 sys_unlink (const char * path)
4628 int rmstatus, e;
4630 path = map_w32_filename (path, NULL);
4632 if (w32_unicode_filenames)
4634 wchar_t path_w[MAX_PATH];
4636 filename_to_utf16 (path, path_w);
4637 /* On Unix, unlink works without write permission. */
4638 _wchmod (path_w, 0666);
4639 rmstatus = _wunlink (path_w);
4640 e = errno;
4641 /* Symlinks to directories can only be deleted by _rmdir;
4642 _unlink returns EACCES. */
4643 if (rmstatus != 0
4644 && errno == EACCES
4645 && (is_symlink (path) & FILE_ATTRIBUTE_DIRECTORY) != 0)
4646 rmstatus = _wrmdir (path_w);
4647 else
4648 errno = e;
4650 else
4652 char path_a[MAX_PATH];
4654 filename_to_ansi (path, path_a);
4655 _chmod (path_a, 0666);
4656 rmstatus = _unlink (path_a);
4657 e = errno;
4658 if (rmstatus != 0
4659 && errno == EACCES
4660 && (is_symlink (path) & FILE_ATTRIBUTE_DIRECTORY) != 0)
4661 rmstatus = _rmdir (path_a);
4662 else
4663 errno = e;
4666 return rmstatus;
4669 static FILETIME utc_base_ft;
4670 static ULONGLONG utc_base; /* In 100ns units */
4671 static int init = 0;
4673 #define FILETIME_TO_U64(result, ft) \
4674 do { \
4675 ULARGE_INTEGER uiTemp; \
4676 uiTemp.LowPart = (ft).dwLowDateTime; \
4677 uiTemp.HighPart = (ft).dwHighDateTime; \
4678 result = uiTemp.QuadPart; \
4679 } while (0)
4681 static void
4682 initialize_utc_base (void)
4684 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
4685 SYSTEMTIME st;
4687 st.wYear = 1970;
4688 st.wMonth = 1;
4689 st.wDay = 1;
4690 st.wHour = 0;
4691 st.wMinute = 0;
4692 st.wSecond = 0;
4693 st.wMilliseconds = 0;
4695 SystemTimeToFileTime (&st, &utc_base_ft);
4696 FILETIME_TO_U64 (utc_base, utc_base_ft);
4699 static time_t
4700 convert_time (FILETIME ft)
4702 ULONGLONG tmp;
4704 if (!init)
4706 initialize_utc_base ();
4707 init = 1;
4710 if (CompareFileTime (&ft, &utc_base_ft) < 0)
4711 return 0;
4713 FILETIME_TO_U64 (tmp, ft);
4714 return (time_t) ((tmp - utc_base) / 10000000L);
4717 static void
4718 convert_from_time_t (time_t time, FILETIME * pft)
4720 ULARGE_INTEGER tmp;
4722 if (!init)
4724 initialize_utc_base ();
4725 init = 1;
4728 /* time in 100ns units since 1-Jan-1601 */
4729 tmp.QuadPart = (ULONGLONG) time * 10000000L + utc_base;
4730 pft->dwHighDateTime = tmp.HighPart;
4731 pft->dwLowDateTime = tmp.LowPart;
4734 static PSECURITY_DESCRIPTOR
4735 get_file_security_desc_by_handle (HANDLE h)
4737 PSECURITY_DESCRIPTOR psd = NULL;
4738 DWORD err;
4739 SECURITY_INFORMATION si = OWNER_SECURITY_INFORMATION
4740 | GROUP_SECURITY_INFORMATION /* | DACL_SECURITY_INFORMATION */ ;
4742 err = get_security_info (h, SE_FILE_OBJECT, si,
4743 NULL, NULL, NULL, NULL, &psd);
4744 if (err != ERROR_SUCCESS)
4745 return NULL;
4747 return psd;
4750 static PSECURITY_DESCRIPTOR
4751 get_file_security_desc_by_name (const char *fname)
4753 PSECURITY_DESCRIPTOR psd = NULL;
4754 DWORD sd_len, err;
4755 SECURITY_INFORMATION si = OWNER_SECURITY_INFORMATION
4756 | GROUP_SECURITY_INFORMATION /* | DACL_SECURITY_INFORMATION */ ;
4758 if (!get_file_security (fname, si, psd, 0, &sd_len))
4760 err = GetLastError ();
4761 if (err != ERROR_INSUFFICIENT_BUFFER)
4762 return NULL;
4765 psd = xmalloc (sd_len);
4766 if (!get_file_security (fname, si, psd, sd_len, &sd_len))
4768 xfree (psd);
4769 return NULL;
4772 return psd;
4775 static DWORD
4776 get_rid (PSID sid)
4778 unsigned n_subauthorities;
4780 /* Use the last sub-authority value of the RID, the relative
4781 portion of the SID, as user/group ID. */
4782 n_subauthorities = *get_sid_sub_authority_count (sid);
4783 if (n_subauthorities < 1)
4784 return 0; /* the "World" RID */
4785 return *get_sid_sub_authority (sid, n_subauthorities - 1);
4788 /* Caching SID and account values for faster lokup. */
4790 struct w32_id {
4791 unsigned rid;
4792 struct w32_id *next;
4793 char name[GNLEN+1];
4794 unsigned char sid[FLEXIBLE_ARRAY_MEMBER];
4797 static struct w32_id *w32_idlist;
4799 static int
4800 w32_cached_id (PSID sid, unsigned *id, char *name)
4802 struct w32_id *tail, *found;
4804 for (found = NULL, tail = w32_idlist; tail; tail = tail->next)
4806 if (equal_sid ((PSID)tail->sid, sid))
4808 found = tail;
4809 break;
4812 if (found)
4814 *id = found->rid;
4815 strcpy (name, found->name);
4816 return 1;
4818 else
4819 return 0;
4822 static void
4823 w32_add_to_cache (PSID sid, unsigned id, char *name)
4825 DWORD sid_len;
4826 struct w32_id *new_entry;
4828 /* We don't want to leave behind stale cache from when Emacs was
4829 dumped. */
4830 if (initialized)
4832 sid_len = get_length_sid (sid);
4833 new_entry = xmalloc (offsetof (struct w32_id, sid) + sid_len);
4834 if (new_entry)
4836 new_entry->rid = id;
4837 strcpy (new_entry->name, name);
4838 copy_sid (sid_len, (PSID)new_entry->sid, sid);
4839 new_entry->next = w32_idlist;
4840 w32_idlist = new_entry;
4845 #define UID 1
4846 #define GID 2
4848 static int
4849 get_name_and_id (PSECURITY_DESCRIPTOR psd, unsigned *id, char *nm, int what)
4851 PSID sid = NULL;
4852 BOOL dflt;
4853 SID_NAME_USE ignore;
4854 char name[UNLEN+1];
4855 DWORD name_len = sizeof (name);
4856 char domain[1024];
4857 DWORD domain_len = sizeof (domain);
4858 int use_dflt = 0;
4859 int result;
4861 if (what == UID)
4862 result = get_security_descriptor_owner (psd, &sid, &dflt);
4863 else if (what == GID)
4864 result = get_security_descriptor_group (psd, &sid, &dflt);
4865 else
4866 result = 0;
4868 if (!result || !is_valid_sid (sid))
4869 use_dflt = 1;
4870 else if (!w32_cached_id (sid, id, nm))
4872 if (!lookup_account_sid (NULL, sid, name, &name_len,
4873 domain, &domain_len, &ignore)
4874 || name_len > UNLEN+1)
4875 use_dflt = 1;
4876 else
4878 *id = get_rid (sid);
4879 strcpy (nm, name);
4880 w32_add_to_cache (sid, *id, name);
4883 return use_dflt;
4886 static void
4887 get_file_owner_and_group (PSECURITY_DESCRIPTOR psd, struct stat *st)
4889 int dflt_usr = 0, dflt_grp = 0;
4891 if (!psd)
4893 dflt_usr = 1;
4894 dflt_grp = 1;
4896 else
4898 if (get_name_and_id (psd, &st->st_uid, st->st_uname, UID))
4899 dflt_usr = 1;
4900 if (get_name_and_id (psd, &st->st_gid, st->st_gname, GID))
4901 dflt_grp = 1;
4903 /* Consider files to belong to current user/group, if we cannot get
4904 more accurate information. */
4905 if (dflt_usr)
4907 st->st_uid = dflt_passwd.pw_uid;
4908 strcpy (st->st_uname, dflt_passwd.pw_name);
4910 if (dflt_grp)
4912 st->st_gid = dflt_passwd.pw_gid;
4913 strcpy (st->st_gname, dflt_group.gr_name);
4917 /* Return non-zero if NAME is a potentially slow filesystem. */
4918 int is_slow_fs (const char *);
4921 is_slow_fs (const char *name)
4923 char drive_root[4];
4924 UINT devtype;
4926 if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1]))
4927 devtype = DRIVE_REMOTE; /* assume UNC name is remote */
4928 else if (!(strlen (name) >= 2 && IS_DEVICE_SEP (name[1])))
4929 devtype = GetDriveType (NULL); /* use root of current drive */
4930 else
4932 /* GetDriveType needs the root directory of the drive. */
4933 strncpy (drive_root, name, 2);
4934 drive_root[2] = '\\';
4935 drive_root[3] = '\0';
4936 devtype = GetDriveType (drive_root);
4938 return !(devtype == DRIVE_FIXED || devtype == DRIVE_RAMDISK);
4941 /* If this is non-zero, the caller wants accurate information about
4942 file's owner and group, which could be expensive to get. dired.c
4943 uses this flag when needed for the job at hand. */
4944 int w32_stat_get_owner_group;
4946 /* MSVC stat function can't cope with UNC names and has other bugs, so
4947 replace it with our own. This also allows us to calculate consistent
4948 inode values and owner/group without hacks in the main Emacs code,
4949 and support file names encoded in UTF-8. */
4951 static int
4952 stat_worker (const char * path, struct stat * buf, int follow_symlinks)
4954 char *name, *save_name, *r;
4955 WIN32_FIND_DATAW wfd_w;
4956 WIN32_FIND_DATAA wfd_a;
4957 HANDLE fh;
4958 unsigned __int64 fake_inode = 0;
4959 int permission;
4960 int len;
4961 int rootdir = FALSE;
4962 PSECURITY_DESCRIPTOR psd = NULL;
4963 int is_a_symlink = 0;
4964 DWORD file_flags = FILE_FLAG_BACKUP_SEMANTICS;
4965 DWORD access_rights = 0;
4966 DWORD fattrs = 0, serialnum = 0, fs_high = 0, fs_low = 0, nlinks = 1;
4967 FILETIME ctime, atime, wtime;
4968 wchar_t name_w[MAX_PATH];
4969 char name_a[MAX_PATH];
4971 if (path == NULL || buf == NULL)
4973 errno = EFAULT;
4974 return -1;
4977 save_name = name = (char *) map_w32_filename (path, &path);
4978 /* Must be valid filename, no wild cards or other invalid
4979 characters. */
4980 if (strpbrk (name, "*?|<>\""))
4982 errno = ENOENT;
4983 return -1;
4986 len = strlen (name);
4987 /* Allocate 1 extra byte so that we could append a slash to a root
4988 directory, down below. */
4989 name = strcpy (alloca (len + 2), name);
4991 /* Avoid a somewhat costly call to is_symlink if the filesystem
4992 doesn't support symlinks. */
4993 if ((volume_info.flags & FILE_SUPPORTS_REPARSE_POINTS) != 0)
4994 is_a_symlink = is_symlink (name);
4996 /* Plan A: Open the file and get all the necessary information via
4997 the resulting handle. This solves several issues in one blow:
4999 . retrieves attributes for the target of a symlink, if needed
5000 . gets attributes of root directories and symlinks pointing to
5001 root directories, thus avoiding the need for special-casing
5002 these and detecting them by examining the file-name format
5003 . retrieves more accurate attributes (e.g., non-zero size for
5004 some directories, esp. directories that are junction points)
5005 . correctly resolves "c:/..", "/.." and similar file names
5006 . avoids run-time penalties for 99% of use cases
5008 Plan A is always tried first, unless the user asked not to (but
5009 if the file is a symlink and we need to follow links, we try Plan
5010 A even if the user asked not to).
5012 If Plan A fails, we go to Plan B (below), where various
5013 potentially expensive techniques must be used to handle "special"
5014 files such as UNC volumes etc. */
5015 if (!(NILP (Vw32_get_true_file_attributes)
5016 || (EQ (Vw32_get_true_file_attributes, Qlocal) && is_slow_fs (name)))
5017 /* Following symlinks requires getting the info by handle. */
5018 || (is_a_symlink && follow_symlinks))
5020 BY_HANDLE_FILE_INFORMATION info;
5022 if (is_a_symlink && !follow_symlinks)
5023 file_flags |= FILE_FLAG_OPEN_REPARSE_POINT;
5024 /* READ_CONTROL access rights are required to get security info
5025 by handle. But if the OS doesn't support security in the
5026 first place, we don't need to try. */
5027 if (is_windows_9x () != TRUE)
5028 access_rights |= READ_CONTROL;
5030 if (w32_unicode_filenames)
5032 filename_to_utf16 (name, name_w);
5033 fh = CreateFileW (name_w, access_rights, 0, NULL, OPEN_EXISTING,
5034 file_flags, NULL);
5035 /* If CreateFile fails with READ_CONTROL, try again with
5036 zero as access rights. */
5037 if (fh == INVALID_HANDLE_VALUE && access_rights)
5038 fh = CreateFileW (name_w, 0, 0, NULL, OPEN_EXISTING,
5039 file_flags, NULL);
5041 else
5043 filename_to_ansi (name, name_a);
5044 fh = CreateFileA (name_a, access_rights, 0, NULL, OPEN_EXISTING,
5045 file_flags, NULL);
5046 if (fh == INVALID_HANDLE_VALUE && access_rights)
5047 fh = CreateFileA (name_a, 0, 0, NULL, OPEN_EXISTING,
5048 file_flags, NULL);
5050 if (fh == INVALID_HANDLE_VALUE)
5051 goto no_true_file_attributes;
5053 /* This is more accurate in terms of getting the correct number
5054 of links, but is quite slow (it is noticeable when Emacs is
5055 making a list of file name completions). */
5056 if (GetFileInformationByHandle (fh, &info))
5058 nlinks = info.nNumberOfLinks;
5059 /* Might as well use file index to fake inode values, but this
5060 is not guaranteed to be unique unless we keep a handle open
5061 all the time (even then there are situations where it is
5062 not unique). Reputedly, there are at most 48 bits of info
5063 (on NTFS, presumably less on FAT). */
5064 fake_inode = info.nFileIndexHigh;
5065 fake_inode <<= 32;
5066 fake_inode += info.nFileIndexLow;
5067 serialnum = info.dwVolumeSerialNumber;
5068 fs_high = info.nFileSizeHigh;
5069 fs_low = info.nFileSizeLow;
5070 ctime = info.ftCreationTime;
5071 atime = info.ftLastAccessTime;
5072 wtime = info.ftLastWriteTime;
5073 fattrs = info.dwFileAttributes;
5075 else
5077 /* We don't go to Plan B here, because it's not clear that
5078 it's a good idea. The only known use case where
5079 CreateFile succeeds, but GetFileInformationByHandle fails
5080 (with ERROR_INVALID_FUNCTION) is for character devices
5081 such as NUL, PRN, etc. For these, switching to Plan B is
5082 a net loss, because we lose the character device
5083 attribute returned by GetFileType below (FindFirstFile
5084 doesn't set that bit in the attributes), and the other
5085 fields don't make sense for character devices anyway.
5086 Emacs doesn't really care for non-file entities in the
5087 context of l?stat, so neither do we. */
5089 /* w32err is assigned so one could put a breakpoint here and
5090 examine its value, when GetFileInformationByHandle
5091 fails. */
5092 DWORD w32err = GetLastError ();
5094 switch (w32err)
5096 case ERROR_FILE_NOT_FOUND: /* can this ever happen? */
5097 errno = ENOENT;
5098 return -1;
5102 /* Test for a symlink before testing for a directory, since
5103 symlinks to directories have the directory bit set, but we
5104 don't want them to appear as directories. */
5105 if (is_a_symlink && !follow_symlinks)
5106 buf->st_mode = S_IFLNK;
5107 else if (fattrs & FILE_ATTRIBUTE_DIRECTORY)
5108 buf->st_mode = S_IFDIR;
5109 else
5111 DWORD ftype = GetFileType (fh);
5113 switch (ftype)
5115 case FILE_TYPE_DISK:
5116 buf->st_mode = S_IFREG;
5117 break;
5118 case FILE_TYPE_PIPE:
5119 buf->st_mode = S_IFIFO;
5120 break;
5121 case FILE_TYPE_CHAR:
5122 case FILE_TYPE_UNKNOWN:
5123 default:
5124 buf->st_mode = S_IFCHR;
5127 /* We produce the fallback owner and group data, based on the
5128 current user that runs Emacs, in the following cases:
5130 . caller didn't request owner and group info
5131 . this is Windows 9X
5132 . getting security by handle failed, and we need to produce
5133 information for the target of a symlink (this is better
5134 than producing a potentially misleading info about the
5135 symlink itself)
5137 If getting security by handle fails, and we don't need to
5138 resolve symlinks, we try getting security by name. */
5139 if (!w32_stat_get_owner_group || is_windows_9x () == TRUE)
5140 get_file_owner_and_group (NULL, buf);
5141 else
5143 psd = get_file_security_desc_by_handle (fh);
5144 if (psd)
5146 get_file_owner_and_group (psd, buf);
5147 LocalFree (psd);
5149 else if (!(is_a_symlink && follow_symlinks))
5151 psd = get_file_security_desc_by_name (name);
5152 get_file_owner_and_group (psd, buf);
5153 xfree (psd);
5155 else
5156 get_file_owner_and_group (NULL, buf);
5158 CloseHandle (fh);
5160 else
5162 no_true_file_attributes:
5163 /* Plan B: Either getting a handle on the file failed, or the
5164 caller explicitly asked us to not bother making this
5165 information more accurate.
5167 Implementation note: In Plan B, we never bother to resolve
5168 symlinks, even if we got here because we tried Plan A and
5169 failed. That's because, even if the caller asked for extra
5170 precision by setting Vw32_get_true_file_attributes to t,
5171 resolving symlinks requires acquiring a file handle to the
5172 symlink, which we already know will fail. And if the user
5173 did not ask for extra precision, resolving symlinks will fly
5174 in the face of that request, since the user then wants the
5175 lightweight version of the code. */
5176 rootdir = (path >= save_name + len - 1
5177 && (IS_DIRECTORY_SEP (*path) || *path == 0));
5179 /* If name is "c:/.." or "/.." then stat "c:/" or "/". */
5180 r = IS_DEVICE_SEP (name[1]) ? &name[2] : name;
5181 if (IS_DIRECTORY_SEP (r[0])
5182 && r[1] == '.' && r[2] == '.' && r[3] == '\0')
5183 r[1] = r[2] = '\0';
5185 /* Note: If NAME is a symlink to the root of a UNC volume
5186 (i.e. "\\SERVER"), we will not detect that here, and we will
5187 return data about the symlink as result of FindFirst below.
5188 This is unfortunate, but that marginal use case does not
5189 justify a call to chase_symlinks which would impose a penalty
5190 on all the other use cases. (We get here for symlinks to
5191 roots of UNC volumes because CreateFile above fails for them,
5192 unlike with symlinks to root directories X:\ of drives.) */
5193 if (is_unc_volume (name))
5195 fattrs = unc_volume_file_attributes (name);
5196 if (fattrs == -1)
5197 return -1;
5199 ctime = atime = wtime = utc_base_ft;
5201 else if (rootdir)
5203 /* Make sure root directories end in a slash. */
5204 if (!IS_DIRECTORY_SEP (name[len-1]))
5205 strcpy (name + len, "\\");
5206 if (GetDriveType (name) < 2)
5208 errno = ENOENT;
5209 return -1;
5212 fattrs = FILE_ATTRIBUTE_DIRECTORY;
5213 ctime = atime = wtime = utc_base_ft;
5215 else
5217 int have_wfd = -1;
5219 /* Make sure non-root directories do NOT end in a slash,
5220 otherwise FindFirstFile might fail. */
5221 if (IS_DIRECTORY_SEP (name[len-1]))
5222 name[len - 1] = 0;
5224 /* (This is hacky, but helps when doing file completions on
5225 network drives.) Optimize by using information available from
5226 active readdir if possible. */
5227 len = strlen (dir_pathname);
5228 if (IS_DIRECTORY_SEP (dir_pathname[len-1]))
5229 len--;
5230 if (dir_find_handle != INVALID_HANDLE_VALUE
5231 && last_dir_find_data != -1
5232 && !(is_a_symlink && follow_symlinks)
5233 /* The 2 file-name comparisons below support only ASCII
5234 characters, and will lose (compare not equal) when
5235 the file names include non-ASCII characters that are
5236 the same but for the case. However, doing this
5237 properly involves: (a) converting both file names to
5238 UTF-16, (b) lower-casing both names using CharLowerW,
5239 and (c) comparing the results; this would be quite a
5240 bit slower, whereas Plan B is for users who want
5241 lightweight albeit inaccurate version of 'stat'. */
5242 && c_strncasecmp (save_name, dir_pathname, len) == 0
5243 && IS_DIRECTORY_SEP (name[len])
5244 && xstrcasecmp (name + len + 1, dir_static.d_name) == 0)
5246 have_wfd = last_dir_find_data;
5247 /* This was the last entry returned by readdir. */
5248 if (last_dir_find_data == DIR_FIND_DATA_W)
5249 wfd_w = dir_find_data_w;
5250 else
5251 wfd_a = dir_find_data_a;
5253 else
5255 logon_network_drive (name);
5257 if (w32_unicode_filenames)
5259 filename_to_utf16 (name, name_w);
5260 fh = FindFirstFileW (name_w, &wfd_w);
5261 have_wfd = DIR_FIND_DATA_W;
5263 else
5265 filename_to_ansi (name, name_a);
5266 /* If NAME includes characters not representable by
5267 the current ANSI codepage, filename_to_ansi
5268 usually replaces them with a '?'. We don't want
5269 to let FindFirstFileA interpret those as wildcards,
5270 and "succeed", returning us data from some random
5271 file in the same directory. */
5272 if (_mbspbrk (name_a, "?"))
5273 fh = INVALID_HANDLE_VALUE;
5274 else
5275 fh = FindFirstFileA (name_a, &wfd_a);
5276 have_wfd = DIR_FIND_DATA_A;
5278 if (fh == INVALID_HANDLE_VALUE)
5280 errno = ENOENT;
5281 return -1;
5283 FindClose (fh);
5285 /* Note: if NAME is a symlink, the information we get from
5286 FindFirstFile is for the symlink, not its target. */
5287 if (have_wfd == DIR_FIND_DATA_W)
5289 fattrs = wfd_w.dwFileAttributes;
5290 ctime = wfd_w.ftCreationTime;
5291 atime = wfd_w.ftLastAccessTime;
5292 wtime = wfd_w.ftLastWriteTime;
5293 fs_high = wfd_w.nFileSizeHigh;
5294 fs_low = wfd_w.nFileSizeLow;
5296 else
5298 fattrs = wfd_a.dwFileAttributes;
5299 ctime = wfd_a.ftCreationTime;
5300 atime = wfd_a.ftLastAccessTime;
5301 wtime = wfd_a.ftLastWriteTime;
5302 fs_high = wfd_a.nFileSizeHigh;
5303 fs_low = wfd_a.nFileSizeLow;
5305 fake_inode = 0;
5306 nlinks = 1;
5307 serialnum = volume_info.serialnum;
5309 if (is_a_symlink && !follow_symlinks)
5310 buf->st_mode = S_IFLNK;
5311 else if (fattrs & FILE_ATTRIBUTE_DIRECTORY)
5312 buf->st_mode = S_IFDIR;
5313 else
5314 buf->st_mode = S_IFREG;
5316 get_file_owner_and_group (NULL, buf);
5319 buf->st_ino = fake_inode;
5321 buf->st_dev = serialnum;
5322 buf->st_rdev = serialnum;
5324 buf->st_size = fs_high;
5325 buf->st_size <<= 32;
5326 buf->st_size += fs_low;
5327 buf->st_nlink = nlinks;
5329 /* Convert timestamps to Unix format. */
5330 buf->st_mtime = convert_time (wtime);
5331 buf->st_atime = convert_time (atime);
5332 if (buf->st_atime == 0) buf->st_atime = buf->st_mtime;
5333 buf->st_ctime = convert_time (ctime);
5334 if (buf->st_ctime == 0) buf->st_ctime = buf->st_mtime;
5336 /* determine rwx permissions */
5337 if (is_a_symlink && !follow_symlinks)
5338 permission = S_IREAD | S_IWRITE | S_IEXEC; /* Posix expectations */
5339 else
5341 if (fattrs & FILE_ATTRIBUTE_READONLY)
5342 permission = S_IREAD;
5343 else
5344 permission = S_IREAD | S_IWRITE;
5346 if (fattrs & FILE_ATTRIBUTE_DIRECTORY)
5347 permission |= S_IEXEC;
5348 else if (is_exec (name))
5349 permission |= S_IEXEC;
5352 buf->st_mode |= permission | (permission >> 3) | (permission >> 6);
5354 return 0;
5358 stat (const char * path, struct stat * buf)
5360 return stat_worker (path, buf, 1);
5364 lstat (const char * path, struct stat * buf)
5366 return stat_worker (path, buf, 0);
5370 fstatat (int fd, char const *name, struct stat *st, int flags)
5372 /* Rely on a hack: an open directory is modeled as file descriptor 0.
5373 This is good enough for the current usage in Emacs, but is fragile.
5375 FIXME: Add proper support for fdopendir, fstatat, readlinkat.
5376 Gnulib does this and can serve as a model. */
5377 char fullname[MAX_UTF8_PATH];
5379 if (fd != AT_FDCWD)
5381 char lastc = dir_pathname[strlen (dir_pathname) - 1];
5383 if (_snprintf (fullname, sizeof fullname, "%s%s%s",
5384 dir_pathname, IS_DIRECTORY_SEP (lastc) ? "" : "/", name)
5385 < 0)
5387 errno = ENAMETOOLONG;
5388 return -1;
5390 name = fullname;
5393 return stat_worker (name, st, ! (flags & AT_SYMLINK_NOFOLLOW));
5396 /* Provide fstat and utime as well as stat for consistent handling of
5397 file timestamps. */
5399 fstat (int desc, struct stat * buf)
5401 HANDLE fh = (HANDLE) _get_osfhandle (desc);
5402 BY_HANDLE_FILE_INFORMATION info;
5403 unsigned __int64 fake_inode;
5404 int permission;
5406 switch (GetFileType (fh) & ~FILE_TYPE_REMOTE)
5408 case FILE_TYPE_DISK:
5409 buf->st_mode = S_IFREG;
5410 if (!GetFileInformationByHandle (fh, &info))
5412 errno = EACCES;
5413 return -1;
5415 break;
5416 case FILE_TYPE_PIPE:
5417 buf->st_mode = S_IFIFO;
5418 goto non_disk;
5419 case FILE_TYPE_CHAR:
5420 case FILE_TYPE_UNKNOWN:
5421 default:
5422 buf->st_mode = S_IFCHR;
5423 non_disk:
5424 memset (&info, 0, sizeof (info));
5425 info.dwFileAttributes = 0;
5426 info.ftCreationTime = utc_base_ft;
5427 info.ftLastAccessTime = utc_base_ft;
5428 info.ftLastWriteTime = utc_base_ft;
5431 if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
5432 buf->st_mode = S_IFDIR;
5434 buf->st_nlink = info.nNumberOfLinks;
5435 /* Might as well use file index to fake inode values, but this
5436 is not guaranteed to be unique unless we keep a handle open
5437 all the time (even then there are situations where it is
5438 not unique). Reputedly, there are at most 48 bits of info
5439 (on NTFS, presumably less on FAT). */
5440 fake_inode = info.nFileIndexHigh;
5441 fake_inode <<= 32;
5442 fake_inode += info.nFileIndexLow;
5444 /* MSVC defines _ino_t to be short; other libc's might not. */
5445 if (sizeof (buf->st_ino) == 2)
5446 buf->st_ino = fake_inode ^ (fake_inode >> 16);
5447 else
5448 buf->st_ino = fake_inode;
5450 /* If the caller so requested, get the true file owner and group.
5451 Otherwise, consider the file to belong to the current user. */
5452 if (!w32_stat_get_owner_group || is_windows_9x () == TRUE)
5453 get_file_owner_and_group (NULL, buf);
5454 else
5456 PSECURITY_DESCRIPTOR psd = NULL;
5458 psd = get_file_security_desc_by_handle (fh);
5459 if (psd)
5461 get_file_owner_and_group (psd, buf);
5462 LocalFree (psd);
5464 else
5465 get_file_owner_and_group (NULL, buf);
5468 buf->st_dev = info.dwVolumeSerialNumber;
5469 buf->st_rdev = info.dwVolumeSerialNumber;
5471 buf->st_size = info.nFileSizeHigh;
5472 buf->st_size <<= 32;
5473 buf->st_size += info.nFileSizeLow;
5475 /* Convert timestamps to Unix format. */
5476 buf->st_mtime = convert_time (info.ftLastWriteTime);
5477 buf->st_atime = convert_time (info.ftLastAccessTime);
5478 if (buf->st_atime == 0) buf->st_atime = buf->st_mtime;
5479 buf->st_ctime = convert_time (info.ftCreationTime);
5480 if (buf->st_ctime == 0) buf->st_ctime = buf->st_mtime;
5482 /* determine rwx permissions */
5483 if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
5484 permission = S_IREAD;
5485 else
5486 permission = S_IREAD | S_IWRITE;
5488 if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
5489 permission |= S_IEXEC;
5490 else
5492 #if 0 /* no way of knowing the filename */
5493 char * p = strrchr (name, '.');
5494 if (p != NULL &&
5495 (xstrcasecmp (p, ".exe") == 0 ||
5496 xstrcasecmp (p, ".com") == 0 ||
5497 xstrcasecmp (p, ".bat") == 0 ||
5498 xstrcasecmp (p, ".cmd") == 0))
5499 permission |= S_IEXEC;
5500 #endif
5503 buf->st_mode |= permission | (permission >> 3) | (permission >> 6);
5505 return 0;
5508 /* A version of 'utime' which handles directories as well as
5509 files. */
5512 utime (const char *name, struct utimbuf *times)
5514 struct utimbuf deftime;
5515 HANDLE fh;
5516 FILETIME mtime;
5517 FILETIME atime;
5519 if (times == NULL)
5521 deftime.modtime = deftime.actime = time (NULL);
5522 times = &deftime;
5525 if (w32_unicode_filenames)
5527 wchar_t name_utf16[MAX_PATH];
5529 if (filename_to_utf16 (name, name_utf16) != 0)
5530 return -1; /* errno set by filename_to_utf16 */
5532 /* Need write access to set times. */
5533 fh = CreateFileW (name_utf16, FILE_WRITE_ATTRIBUTES,
5534 /* If NAME specifies a directory, FILE_SHARE_DELETE
5535 allows other processes to delete files inside it,
5536 while we have the directory open. */
5537 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
5538 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
5540 else
5542 char name_ansi[MAX_PATH];
5544 if (filename_to_ansi (name, name_ansi) != 0)
5545 return -1; /* errno set by filename_to_ansi */
5547 fh = CreateFileA (name_ansi, FILE_WRITE_ATTRIBUTES,
5548 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
5549 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
5551 if (fh != INVALID_HANDLE_VALUE)
5553 convert_from_time_t (times->actime, &atime);
5554 convert_from_time_t (times->modtime, &mtime);
5555 if (!SetFileTime (fh, NULL, &atime, &mtime))
5557 CloseHandle (fh);
5558 errno = EACCES;
5559 return -1;
5561 CloseHandle (fh);
5563 else
5565 DWORD err = GetLastError ();
5567 switch (err)
5569 case ERROR_FILE_NOT_FOUND:
5570 case ERROR_PATH_NOT_FOUND:
5571 case ERROR_INVALID_DRIVE:
5572 case ERROR_BAD_NETPATH:
5573 case ERROR_DEV_NOT_EXIST:
5574 /* ERROR_INVALID_NAME is the error CreateFile sets when the
5575 file name includes ?s, i.e. translation to ANSI failed. */
5576 case ERROR_INVALID_NAME:
5577 errno = ENOENT;
5578 break;
5579 case ERROR_TOO_MANY_OPEN_FILES:
5580 errno = ENFILE;
5581 break;
5582 case ERROR_ACCESS_DENIED:
5583 case ERROR_SHARING_VIOLATION:
5584 errno = EACCES;
5585 break;
5586 default:
5587 errno = EINVAL;
5588 break;
5590 return -1;
5592 return 0;
5596 sys_umask (int mode)
5598 static int current_mask;
5599 int retval, arg = 0;
5601 /* The only bit we really support is the write bit. Files are
5602 always readable on MS-Windows, and the execute bit does not exist
5603 at all. */
5604 /* FIXME: if the GROUP and OTHER bits are reset, we should use ACLs
5605 to prevent access by other users on NTFS. */
5606 if ((mode & S_IWRITE) != 0)
5607 arg |= S_IWRITE;
5609 retval = _umask (arg);
5610 /* Merge into the return value the bits they've set the last time,
5611 which msvcrt.dll ignores and never returns. Emacs insists on its
5612 notion of mask being identical to what we return. */
5613 retval |= (current_mask & ~S_IWRITE);
5614 current_mask = mode;
5616 return retval;
5620 /* Symlink-related functions. */
5621 #ifndef SYMBOLIC_LINK_FLAG_DIRECTORY
5622 #define SYMBOLIC_LINK_FLAG_DIRECTORY 0x1
5623 #endif
5626 symlink (char const *filename, char const *linkname)
5628 char linkfn[MAX_UTF8_PATH], *tgtfn;
5629 DWORD flags = 0;
5630 int dir_access, filename_ends_in_slash;
5632 /* Diagnostics follows Posix as much as possible. */
5633 if (filename == NULL || linkname == NULL)
5635 errno = EFAULT;
5636 return -1;
5638 if (!*filename)
5640 errno = ENOENT;
5641 return -1;
5643 if (strlen (filename) > MAX_UTF8_PATH || strlen (linkname) > MAX_UTF8_PATH)
5645 errno = ENAMETOOLONG;
5646 return -1;
5649 strcpy (linkfn, map_w32_filename (linkname, NULL));
5650 if ((volume_info.flags & FILE_SUPPORTS_REPARSE_POINTS) == 0)
5652 errno = EPERM;
5653 return -1;
5656 /* Note: since empty FILENAME was already rejected, we can safely
5657 refer to FILENAME[1]. */
5658 if (!(IS_DIRECTORY_SEP (filename[0]) || IS_DEVICE_SEP (filename[1])))
5660 /* Non-absolute FILENAME is understood as being relative to
5661 LINKNAME's directory. We need to prepend that directory to
5662 FILENAME to get correct results from faccessat below, since
5663 otherwise it will interpret FILENAME relative to the
5664 directory where the Emacs process runs. Note that
5665 make-symbolic-link always makes sure LINKNAME is a fully
5666 expanded file name. */
5667 char tem[MAX_UTF8_PATH];
5668 char *p = linkfn + strlen (linkfn);
5670 while (p > linkfn && !IS_ANY_SEP (p[-1]))
5671 p--;
5672 if (p > linkfn)
5673 strncpy (tem, linkfn, p - linkfn);
5674 strcpy (tem + (p - linkfn), filename);
5675 dir_access = faccessat (AT_FDCWD, tem, D_OK, AT_EACCESS);
5677 else
5678 dir_access = faccessat (AT_FDCWD, filename, D_OK, AT_EACCESS);
5680 /* Since Windows distinguishes between symlinks to directories and
5681 to files, we provide a kludgy feature: if FILENAME doesn't
5682 exist, but ends in a slash, we create a symlink to directory. If
5683 FILENAME exists and is a directory, we always create a symlink to
5684 directory. */
5685 filename_ends_in_slash = IS_DIRECTORY_SEP (filename[strlen (filename) - 1]);
5686 if (dir_access == 0 || filename_ends_in_slash)
5687 flags = SYMBOLIC_LINK_FLAG_DIRECTORY;
5689 tgtfn = (char *)map_w32_filename (filename, NULL);
5690 if (filename_ends_in_slash)
5691 tgtfn[strlen (tgtfn) - 1] = '\0';
5693 errno = 0;
5694 if (!create_symbolic_link (linkfn, tgtfn, flags))
5696 /* ENOSYS is set by create_symbolic_link, when it detects that
5697 the OS doesn't support the CreateSymbolicLink API. */
5698 if (errno != ENOSYS)
5700 DWORD w32err = GetLastError ();
5702 switch (w32err)
5704 /* ERROR_SUCCESS is sometimes returned when LINKFN and
5705 TGTFN point to the same file name, go figure. */
5706 case ERROR_SUCCESS:
5707 case ERROR_FILE_EXISTS:
5708 errno = EEXIST;
5709 break;
5710 case ERROR_ACCESS_DENIED:
5711 errno = EACCES;
5712 break;
5713 case ERROR_FILE_NOT_FOUND:
5714 case ERROR_PATH_NOT_FOUND:
5715 case ERROR_BAD_NETPATH:
5716 case ERROR_INVALID_REPARSE_DATA:
5717 errno = ENOENT;
5718 break;
5719 case ERROR_DIRECTORY:
5720 errno = EISDIR;
5721 break;
5722 case ERROR_PRIVILEGE_NOT_HELD:
5723 case ERROR_NOT_ALL_ASSIGNED:
5724 errno = EPERM;
5725 break;
5726 case ERROR_DISK_FULL:
5727 errno = ENOSPC;
5728 break;
5729 default:
5730 errno = EINVAL;
5731 break;
5734 return -1;
5736 return 0;
5739 /* A quick inexpensive test of whether FILENAME identifies a file that
5740 is a symlink. Returns non-zero if it is, zero otherwise. FILENAME
5741 must already be in the normalized form returned by
5742 map_w32_filename. If the symlink is to a directory, the
5743 FILE_ATTRIBUTE_DIRECTORY bit will be set in the return value.
5745 Note: for repeated operations on many files, it is best to test
5746 whether the underlying volume actually supports symlinks, by
5747 testing the FILE_SUPPORTS_REPARSE_POINTS bit in volume's flags, and
5748 avoid the call to this function if it doesn't. That's because the
5749 call to GetFileAttributes takes a non-negligible time, especially
5750 on non-local or removable filesystems. See stat_worker for an
5751 example of how to do that. */
5752 static int
5753 is_symlink (const char *filename)
5755 DWORD attrs;
5756 wchar_t filename_w[MAX_PATH];
5757 char filename_a[MAX_PATH];
5758 WIN32_FIND_DATAW wfdw;
5759 WIN32_FIND_DATAA wfda;
5760 HANDLE fh;
5761 int attrs_mean_symlink;
5763 if (w32_unicode_filenames)
5765 filename_to_utf16 (filename, filename_w);
5766 attrs = GetFileAttributesW (filename_w);
5768 else
5770 filename_to_ansi (filename, filename_a);
5771 attrs = GetFileAttributesA (filename_a);
5773 if (attrs == -1)
5775 DWORD w32err = GetLastError ();
5777 switch (w32err)
5779 case ERROR_BAD_NETPATH: /* network share, can't be a symlink */
5780 break;
5781 case ERROR_ACCESS_DENIED:
5782 errno = EACCES;
5783 break;
5784 case ERROR_FILE_NOT_FOUND:
5785 case ERROR_PATH_NOT_FOUND:
5786 default:
5787 errno = ENOENT;
5788 break;
5790 return 0;
5792 if ((attrs & FILE_ATTRIBUTE_REPARSE_POINT) == 0)
5793 return 0;
5794 logon_network_drive (filename);
5795 if (w32_unicode_filenames)
5797 fh = FindFirstFileW (filename_w, &wfdw);
5798 attrs_mean_symlink =
5799 (wfdw.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0
5800 && (wfdw.dwReserved0 & IO_REPARSE_TAG_SYMLINK) == IO_REPARSE_TAG_SYMLINK;
5801 if (attrs_mean_symlink)
5802 attrs_mean_symlink |= (wfdw.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
5804 else if (_mbspbrk (filename_a, "?"))
5806 /* filename_to_ansi failed to convert the file name. */
5807 errno = ENOENT;
5808 return 0;
5810 else
5812 fh = FindFirstFileA (filename_a, &wfda);
5813 attrs_mean_symlink =
5814 (wfda.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0
5815 && (wfda.dwReserved0 & IO_REPARSE_TAG_SYMLINK) == IO_REPARSE_TAG_SYMLINK;
5816 if (attrs_mean_symlink)
5817 attrs_mean_symlink |= (wfda.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
5819 if (fh == INVALID_HANDLE_VALUE)
5820 return 0;
5821 FindClose (fh);
5822 return attrs_mean_symlink;
5825 /* If NAME identifies a symbolic link, copy into BUF the file name of
5826 the symlink's target. Copy at most BUF_SIZE bytes, and do NOT
5827 null-terminate the target name, even if it fits. Return the number
5828 of bytes copied, or -1 if NAME is not a symlink or any error was
5829 encountered while resolving it. The file name copied into BUF is
5830 encoded in the current ANSI codepage. */
5831 ssize_t
5832 readlink (const char *name, char *buf, size_t buf_size)
5834 const char *path;
5835 TOKEN_PRIVILEGES privs;
5836 int restore_privs = 0;
5837 HANDLE sh;
5838 ssize_t retval;
5839 char resolved[MAX_UTF8_PATH];
5841 if (name == NULL)
5843 errno = EFAULT;
5844 return -1;
5846 if (!*name)
5848 errno = ENOENT;
5849 return -1;
5852 path = map_w32_filename (name, NULL);
5854 if (strlen (path) > MAX_UTF8_PATH)
5856 errno = ENAMETOOLONG;
5857 return -1;
5860 errno = 0;
5861 if (is_windows_9x () == TRUE
5862 || (volume_info.flags & FILE_SUPPORTS_REPARSE_POINTS) == 0
5863 || !is_symlink (path))
5865 if (!errno)
5866 errno = EINVAL; /* not a symlink */
5867 return -1;
5870 /* Done with simple tests, now we're in for some _real_ work. */
5871 if (enable_privilege (SE_BACKUP_NAME, TRUE, &privs))
5872 restore_privs = 1;
5873 /* Implementation note: From here and onward, don't return early,
5874 since that will fail to restore the original set of privileges of
5875 the calling thread. */
5877 retval = -1; /* not too optimistic, are we? */
5879 /* Note: In the next call to CreateFile, we use zero as the 2nd
5880 argument because, when the symlink is a hidden/system file,
5881 e.g. 'C:\Users\All Users', GENERIC_READ fails with
5882 ERROR_ACCESS_DENIED. Zero seems to work just fine, both for file
5883 and directory symlinks. */
5884 if (w32_unicode_filenames)
5886 wchar_t path_w[MAX_PATH];
5888 filename_to_utf16 (path, path_w);
5889 sh = CreateFileW (path_w, 0, 0, NULL, OPEN_EXISTING,
5890 FILE_FLAG_OPEN_REPARSE_POINT
5891 | FILE_FLAG_BACKUP_SEMANTICS,
5892 NULL);
5894 else
5896 char path_a[MAX_PATH];
5898 filename_to_ansi (path, path_a);
5899 sh = CreateFileA (path_a, 0, 0, NULL, OPEN_EXISTING,
5900 FILE_FLAG_OPEN_REPARSE_POINT
5901 | FILE_FLAG_BACKUP_SEMANTICS,
5902 NULL);
5904 if (sh != INVALID_HANDLE_VALUE)
5906 BYTE reparse_buf[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
5907 REPARSE_DATA_BUFFER *reparse_data = (REPARSE_DATA_BUFFER *)&reparse_buf[0];
5908 DWORD retbytes;
5910 if (!DeviceIoControl (sh, FSCTL_GET_REPARSE_POINT, NULL, 0,
5911 reparse_buf, MAXIMUM_REPARSE_DATA_BUFFER_SIZE,
5912 &retbytes, NULL))
5913 errno = EIO;
5914 else if (reparse_data->ReparseTag != IO_REPARSE_TAG_SYMLINK)
5915 errno = EINVAL;
5916 else
5918 /* Copy the link target name, in wide characters, from
5919 reparse_data, then convert it to multibyte encoding in
5920 the current locale's codepage. */
5921 WCHAR *lwname;
5922 size_t lname_size;
5923 USHORT lwname_len =
5924 reparse_data->SymbolicLinkReparseBuffer.PrintNameLength;
5925 WCHAR *lwname_src =
5926 reparse_data->SymbolicLinkReparseBuffer.PathBuffer
5927 + reparse_data->SymbolicLinkReparseBuffer.PrintNameOffset/sizeof(WCHAR);
5928 size_t size_to_copy = buf_size;
5930 /* According to MSDN, PrintNameLength does not include the
5931 terminating null character. */
5932 lwname = alloca ((lwname_len + 1) * sizeof(WCHAR));
5933 memcpy (lwname, lwname_src, lwname_len);
5934 lwname[lwname_len/sizeof(WCHAR)] = 0; /* null-terminate */
5935 filename_from_utf16 (lwname, resolved);
5936 dostounix_filename (resolved);
5937 lname_size = strlen (resolved) + 1;
5938 if (lname_size <= buf_size)
5939 size_to_copy = lname_size;
5940 strncpy (buf, resolved, size_to_copy);
5941 /* Success! */
5942 retval = size_to_copy;
5944 CloseHandle (sh);
5946 else
5948 /* CreateFile failed. */
5949 DWORD w32err2 = GetLastError ();
5951 switch (w32err2)
5953 case ERROR_FILE_NOT_FOUND:
5954 case ERROR_PATH_NOT_FOUND:
5955 errno = ENOENT;
5956 break;
5957 case ERROR_ACCESS_DENIED:
5958 case ERROR_TOO_MANY_OPEN_FILES:
5959 errno = EACCES;
5960 break;
5961 default:
5962 errno = EPERM;
5963 break;
5966 if (restore_privs)
5968 restore_privilege (&privs);
5969 revert_to_self ();
5972 return retval;
5975 ssize_t
5976 readlinkat (int fd, char const *name, char *buffer,
5977 size_t buffer_size)
5979 /* Rely on a hack: an open directory is modeled as file descriptor 0,
5980 as in fstatat. FIXME: Add proper support for readlinkat. */
5981 char fullname[MAX_UTF8_PATH];
5983 if (fd != AT_FDCWD)
5985 if (_snprintf (fullname, sizeof fullname, "%s/%s", dir_pathname, name)
5986 < 0)
5988 errno = ENAMETOOLONG;
5989 return -1;
5991 name = fullname;
5994 return readlink (name, buffer, buffer_size);
5997 /* If FILE is a symlink, return its target (stored in a static
5998 buffer); otherwise return FILE.
6000 This function repeatedly resolves symlinks in the last component of
6001 a chain of symlink file names, as in foo -> bar -> baz -> ...,
6002 until it arrives at a file whose last component is not a symlink,
6003 or some error occurs. It returns the target of the last
6004 successfully resolved symlink in the chain. If it succeeds to
6005 resolve even a single symlink, the value returned is an absolute
6006 file name with backslashes (result of GetFullPathName). By
6007 contrast, if the original FILE is returned, it is unaltered.
6009 Note: This function can set errno even if it succeeds.
6011 Implementation note: we only resolve the last portion ("basename")
6012 of the argument FILE and of each following file in the chain,
6013 disregarding any possible symlinks in its leading directories.
6014 This is because Windows system calls and library functions
6015 transparently resolve symlinks in leading directories and return
6016 correct information, as long as the basename is not a symlink. */
6017 static char *
6018 chase_symlinks (const char *file)
6020 static char target[MAX_UTF8_PATH];
6021 char link[MAX_UTF8_PATH];
6022 wchar_t target_w[MAX_PATH], link_w[MAX_PATH];
6023 char target_a[MAX_PATH], link_a[MAX_PATH];
6024 ssize_t res, link_len;
6025 int loop_count = 0;
6027 if (is_windows_9x () == TRUE || !is_symlink (file))
6028 return (char *)file;
6030 if (w32_unicode_filenames)
6032 wchar_t file_w[MAX_PATH];
6034 filename_to_utf16 (file, file_w);
6035 if (GetFullPathNameW (file_w, MAX_PATH, link_w, NULL) == 0)
6036 return (char *)file;
6037 filename_from_utf16 (link_w, link);
6039 else
6041 char file_a[MAX_PATH];
6043 filename_to_ansi (file, file_a);
6044 if (GetFullPathNameA (file_a, MAX_PATH, link_a, NULL) == 0)
6045 return (char *)file;
6046 filename_from_ansi (link_a, link);
6048 link_len = strlen (link);
6050 target[0] = '\0';
6051 do {
6053 /* Remove trailing slashes, as we want to resolve the last
6054 non-trivial part of the link name. */
6055 while (link_len > 3 && IS_DIRECTORY_SEP (link[link_len-1]))
6056 link[link_len--] = '\0';
6058 res = readlink (link, target, MAX_UTF8_PATH);
6059 if (res > 0)
6061 target[res] = '\0';
6062 if (!(IS_DEVICE_SEP (target[1])
6063 || (IS_DIRECTORY_SEP (target[0]) && IS_DIRECTORY_SEP (target[1]))))
6065 /* Target is relative. Append it to the directory part of
6066 the symlink, then copy the result back to target. */
6067 char *p = link + link_len;
6069 while (p > link && !IS_ANY_SEP (p[-1]))
6070 p--;
6071 strcpy (p, target);
6072 strcpy (target, link);
6074 /* Resolve any "." and ".." to get a fully-qualified file name
6075 in link[] again. */
6076 if (w32_unicode_filenames)
6078 filename_to_utf16 (target, target_w);
6079 link_len = GetFullPathNameW (target_w, MAX_PATH, link_w, NULL);
6080 if (link_len > 0)
6081 filename_from_utf16 (link_w, link);
6083 else
6085 filename_to_ansi (target, target_a);
6086 link_len = GetFullPathNameA (target_a, MAX_PATH, link_a, NULL);
6087 if (link_len > 0)
6088 filename_from_ansi (link_a, link);
6090 link_len = strlen (link);
6092 } while (res > 0 && link_len > 0 && ++loop_count <= 100);
6094 if (loop_count > 100)
6095 errno = ELOOP;
6097 if (target[0] == '\0') /* not a single call to readlink succeeded */
6098 return (char *)file;
6099 return target;
6103 /* Posix ACL emulation. */
6106 acl_valid (acl_t acl)
6108 return is_valid_security_descriptor ((PSECURITY_DESCRIPTOR)acl) ? 0 : -1;
6111 char *
6112 acl_to_text (acl_t acl, ssize_t *size)
6114 LPTSTR str_acl;
6115 SECURITY_INFORMATION flags =
6116 OWNER_SECURITY_INFORMATION |
6117 GROUP_SECURITY_INFORMATION |
6118 DACL_SECURITY_INFORMATION;
6119 char *retval = NULL;
6120 ULONG local_size;
6121 int e = errno;
6123 errno = 0;
6125 if (convert_sd_to_sddl ((PSECURITY_DESCRIPTOR)acl, SDDL_REVISION_1, flags, &str_acl, &local_size))
6127 errno = e;
6128 /* We don't want to mix heaps, so we duplicate the string in our
6129 heap and free the one allocated by the API. */
6130 retval = xstrdup (str_acl);
6131 if (size)
6132 *size = local_size;
6133 LocalFree (str_acl);
6135 else if (errno != ENOTSUP)
6136 errno = EINVAL;
6138 return retval;
6141 acl_t
6142 acl_from_text (const char *acl_str)
6144 PSECURITY_DESCRIPTOR psd, retval = NULL;
6145 ULONG sd_size;
6146 int e = errno;
6148 errno = 0;
6150 if (convert_sddl_to_sd (acl_str, SDDL_REVISION_1, &psd, &sd_size))
6152 errno = e;
6153 retval = xmalloc (sd_size);
6154 memcpy (retval, psd, sd_size);
6155 LocalFree (psd);
6157 else if (errno != ENOTSUP)
6158 errno = EINVAL;
6160 return retval;
6164 acl_free (void *ptr)
6166 xfree (ptr);
6167 return 0;
6170 acl_t
6171 acl_get_file (const char *fname, acl_type_t type)
6173 PSECURITY_DESCRIPTOR psd = NULL;
6174 const char *filename;
6176 if (type == ACL_TYPE_ACCESS)
6178 DWORD sd_len, err;
6179 SECURITY_INFORMATION si =
6180 OWNER_SECURITY_INFORMATION |
6181 GROUP_SECURITY_INFORMATION |
6182 DACL_SECURITY_INFORMATION ;
6183 int e = errno;
6185 filename = map_w32_filename (fname, NULL);
6186 if ((volume_info.flags & FILE_SUPPORTS_REPARSE_POINTS) != 0)
6187 fname = chase_symlinks (filename);
6188 else
6189 fname = filename;
6191 errno = 0;
6192 if (!get_file_security (fname, si, psd, 0, &sd_len)
6193 && errno != ENOTSUP)
6195 err = GetLastError ();
6196 if (err == ERROR_INSUFFICIENT_BUFFER)
6198 psd = xmalloc (sd_len);
6199 if (!get_file_security (fname, si, psd, sd_len, &sd_len))
6201 xfree (psd);
6202 errno = EIO;
6203 psd = NULL;
6206 else if (err == ERROR_FILE_NOT_FOUND
6207 || err == ERROR_PATH_NOT_FOUND
6208 /* ERROR_INVALID_NAME is what we get if
6209 w32-unicode-filenames is nil and the file cannot
6210 be encoded in the current ANSI codepage. */
6211 || err == ERROR_INVALID_NAME)
6212 errno = ENOENT;
6213 else
6214 errno = EIO;
6216 else if (!errno)
6217 errno = e;
6219 else if (type != ACL_TYPE_DEFAULT)
6220 errno = EINVAL;
6222 return psd;
6226 acl_set_file (const char *fname, acl_type_t type, acl_t acl)
6228 TOKEN_PRIVILEGES old1, old2;
6229 DWORD err;
6230 int st = 0, retval = -1;
6231 SECURITY_INFORMATION flags = 0;
6232 PSID psidOwner, psidGroup;
6233 PACL pacl;
6234 BOOL dflt;
6235 BOOL dacl_present;
6236 int e;
6237 const char *filename;
6239 if (acl_valid (acl) != 0
6240 || (type != ACL_TYPE_DEFAULT && type != ACL_TYPE_ACCESS))
6242 errno = EINVAL;
6243 return -1;
6246 if (type == ACL_TYPE_DEFAULT)
6248 errno = ENOSYS;
6249 return -1;
6252 filename = map_w32_filename (fname, NULL);
6253 if ((volume_info.flags & FILE_SUPPORTS_REPARSE_POINTS) != 0)
6254 fname = chase_symlinks (filename);
6255 else
6256 fname = filename;
6258 if (get_security_descriptor_owner ((PSECURITY_DESCRIPTOR)acl, &psidOwner,
6259 &dflt)
6260 && psidOwner)
6261 flags |= OWNER_SECURITY_INFORMATION;
6262 if (get_security_descriptor_group ((PSECURITY_DESCRIPTOR)acl, &psidGroup,
6263 &dflt)
6264 && psidGroup)
6265 flags |= GROUP_SECURITY_INFORMATION;
6266 if (get_security_descriptor_dacl ((PSECURITY_DESCRIPTOR)acl, &dacl_present,
6267 &pacl, &dflt)
6268 && dacl_present)
6269 flags |= DACL_SECURITY_INFORMATION;
6270 if (!flags)
6271 return 0;
6273 /* According to KB-245153, setting the owner will succeed if either:
6274 (1) the caller is the user who will be the new owner, and has the
6275 SE_TAKE_OWNERSHIP privilege, or
6276 (2) the caller has the SE_RESTORE privilege, in which case she can
6277 set any valid user or group as the owner
6279 We request below both SE_TAKE_OWNERSHIP and SE_RESTORE
6280 privileges, and disregard any failures in obtaining them. If
6281 these privileges cannot be obtained, and do not already exist in
6282 the calling thread's security token, this function could fail
6283 with EPERM. */
6284 if (enable_privilege (SE_TAKE_OWNERSHIP_NAME, TRUE, &old1))
6285 st++;
6286 if (enable_privilege (SE_RESTORE_NAME, TRUE, &old2))
6287 st++;
6289 e = errno;
6290 errno = 0;
6291 /* SetFileSecurity is deprecated by MS, and sometimes fails when
6292 DACL inheritance is involved, but it seems to preserve ownership
6293 better than SetNamedSecurityInfo, which is important e.g., in
6294 copy-file. */
6295 if (!set_file_security (fname, flags, (PSECURITY_DESCRIPTOR)acl))
6297 err = GetLastError ();
6299 if (errno != ENOTSUP)
6300 err = set_named_security_info (fname, SE_FILE_OBJECT, flags,
6301 psidOwner, psidGroup, pacl, NULL);
6303 else
6304 err = ERROR_SUCCESS;
6305 if (err != ERROR_SUCCESS)
6307 if (errno == ENOTSUP)
6309 else if (err == ERROR_INVALID_OWNER
6310 || err == ERROR_NOT_ALL_ASSIGNED
6311 || err == ERROR_ACCESS_DENIED)
6313 /* Maybe the requested ACL and the one the file already has
6314 are identical, in which case we can silently ignore the
6315 failure. (And no, Windows doesn't.) */
6316 acl_t current_acl = acl_get_file (fname, ACL_TYPE_ACCESS);
6318 errno = EPERM;
6319 if (current_acl)
6321 char *acl_from = acl_to_text (current_acl, NULL);
6322 char *acl_to = acl_to_text (acl, NULL);
6324 if (acl_from && acl_to && xstrcasecmp (acl_from, acl_to) == 0)
6326 retval = 0;
6327 errno = e;
6329 if (acl_from)
6330 acl_free (acl_from);
6331 if (acl_to)
6332 acl_free (acl_to);
6333 acl_free (current_acl);
6336 else if (err == ERROR_FILE_NOT_FOUND
6337 || err == ERROR_PATH_NOT_FOUND
6338 /* ERROR_INVALID_NAME is what we get if
6339 w32-unicode-filenames is nil and the file cannot be
6340 encoded in the current ANSI codepage. */
6341 || err == ERROR_INVALID_NAME)
6342 errno = ENOENT;
6343 else
6344 errno = EACCES;
6346 else
6348 retval = 0;
6349 errno = e;
6352 if (st)
6354 if (st >= 2)
6355 restore_privilege (&old2);
6356 restore_privilege (&old1);
6357 revert_to_self ();
6360 return retval;
6364 /* MS-Windows version of careadlinkat (cf. ../lib/careadlinkat.c). We
6365 have a fixed max size for file names, so we don't need the kind of
6366 alloc/malloc/realloc dance the gnulib version does. We also don't
6367 support FD-relative symlinks. */
6368 char *
6369 careadlinkat (int fd, char const *filename,
6370 char *buffer, size_t buffer_size,
6371 struct allocator const *alloc,
6372 ssize_t (*preadlinkat) (int, char const *, char *, size_t))
6374 char linkname[MAX_UTF8_PATH];
6375 ssize_t link_size;
6377 link_size = preadlinkat (fd, filename, linkname, sizeof(linkname));
6379 if (link_size > 0)
6381 char *retval = buffer;
6383 linkname[link_size++] = '\0';
6384 if (link_size > buffer_size)
6385 retval = (char *)(alloc ? alloc->allocate : xmalloc) (link_size);
6386 if (retval)
6387 memcpy (retval, linkname, link_size);
6389 return retval;
6391 return NULL;
6395 w32_copy_file (const char *from, const char *to,
6396 int keep_time, int preserve_ownership, int copy_acls)
6398 acl_t acl = NULL;
6399 BOOL copy_result;
6400 wchar_t from_w[MAX_PATH], to_w[MAX_PATH];
6401 char from_a[MAX_PATH], to_a[MAX_PATH];
6403 /* We ignore preserve_ownership for now. */
6404 preserve_ownership = preserve_ownership;
6406 if (copy_acls)
6408 acl = acl_get_file (from, ACL_TYPE_ACCESS);
6409 if (acl == NULL && acl_errno_valid (errno))
6410 return -2;
6412 if (w32_unicode_filenames)
6414 filename_to_utf16 (from, from_w);
6415 filename_to_utf16 (to, to_w);
6416 copy_result = CopyFileW (from_w, to_w, FALSE);
6418 else
6420 filename_to_ansi (from, from_a);
6421 filename_to_ansi (to, to_a);
6422 copy_result = CopyFileA (from_a, to_a, FALSE);
6424 if (!copy_result)
6426 /* CopyFile doesn't set errno when it fails. By far the most
6427 "popular" reason is that the target is read-only. */
6428 DWORD err = GetLastError ();
6430 switch (err)
6432 case ERROR_FILE_NOT_FOUND:
6433 errno = ENOENT;
6434 break;
6435 case ERROR_ACCESS_DENIED:
6436 errno = EACCES;
6437 break;
6438 case ERROR_ENCRYPTION_FAILED:
6439 errno = EIO;
6440 break;
6441 default:
6442 errno = EPERM;
6443 break;
6446 if (acl)
6447 acl_free (acl);
6448 return -1;
6450 /* CopyFile retains the timestamp by default. However, see
6451 "Community Additions" for CopyFile: it sounds like that is not
6452 entirely true. Testing on Windows XP confirms that modified time
6453 is copied, but creation and last-access times are not.
6454 FIXME? */
6455 else if (!keep_time)
6457 struct timespec now;
6458 DWORD attributes;
6460 if (w32_unicode_filenames)
6462 /* Ensure file is writable while its times are set. */
6463 attributes = GetFileAttributesW (to_w);
6464 SetFileAttributesW (to_w, attributes & ~FILE_ATTRIBUTE_READONLY);
6465 now = current_timespec ();
6466 if (set_file_times (-1, to, now, now))
6468 /* Restore original attributes. */
6469 SetFileAttributesW (to_w, attributes);
6470 if (acl)
6471 acl_free (acl);
6472 return -3;
6474 /* Restore original attributes. */
6475 SetFileAttributesW (to_w, attributes);
6477 else
6479 attributes = GetFileAttributesA (to_a);
6480 SetFileAttributesA (to_a, attributes & ~FILE_ATTRIBUTE_READONLY);
6481 now = current_timespec ();
6482 if (set_file_times (-1, to, now, now))
6484 SetFileAttributesA (to_a, attributes);
6485 if (acl)
6486 acl_free (acl);
6487 return -3;
6489 SetFileAttributesA (to_a, attributes);
6492 if (acl != NULL)
6494 bool fail =
6495 acl_set_file (to, ACL_TYPE_ACCESS, acl) != 0;
6496 acl_free (acl);
6497 if (fail && acl_errno_valid (errno))
6498 return -4;
6501 return 0;
6505 /* Support for browsing other processes and their attributes. See
6506 process.c for the Lisp bindings. */
6508 /* Helper wrapper functions. */
6510 static HANDLE WINAPI
6511 create_toolhelp32_snapshot (DWORD Flags, DWORD Ignored)
6513 static CreateToolhelp32Snapshot_Proc s_pfn_Create_Toolhelp32_Snapshot = NULL;
6515 if (g_b_init_create_toolhelp32_snapshot == 0)
6517 g_b_init_create_toolhelp32_snapshot = 1;
6518 s_pfn_Create_Toolhelp32_Snapshot = (CreateToolhelp32Snapshot_Proc)
6519 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6520 "CreateToolhelp32Snapshot");
6522 if (s_pfn_Create_Toolhelp32_Snapshot == NULL)
6524 return INVALID_HANDLE_VALUE;
6526 return (s_pfn_Create_Toolhelp32_Snapshot (Flags, Ignored));
6529 static BOOL WINAPI
6530 process32_first (HANDLE hSnapshot, LPPROCESSENTRY32 lppe)
6532 static Process32First_Proc s_pfn_Process32_First = NULL;
6534 if (g_b_init_process32_first == 0)
6536 g_b_init_process32_first = 1;
6537 s_pfn_Process32_First = (Process32First_Proc)
6538 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6539 "Process32First");
6541 if (s_pfn_Process32_First == NULL)
6543 return FALSE;
6545 return (s_pfn_Process32_First (hSnapshot, lppe));
6548 static BOOL WINAPI
6549 process32_next (HANDLE hSnapshot, LPPROCESSENTRY32 lppe)
6551 static Process32Next_Proc s_pfn_Process32_Next = NULL;
6553 if (g_b_init_process32_next == 0)
6555 g_b_init_process32_next = 1;
6556 s_pfn_Process32_Next = (Process32Next_Proc)
6557 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6558 "Process32Next");
6560 if (s_pfn_Process32_Next == NULL)
6562 return FALSE;
6564 return (s_pfn_Process32_Next (hSnapshot, lppe));
6567 static BOOL WINAPI
6568 open_thread_token (HANDLE ThreadHandle,
6569 DWORD DesiredAccess,
6570 BOOL OpenAsSelf,
6571 PHANDLE TokenHandle)
6573 static OpenThreadToken_Proc s_pfn_Open_Thread_Token = NULL;
6574 HMODULE hm_advapi32 = NULL;
6575 if (is_windows_9x () == TRUE)
6577 SetLastError (ERROR_NOT_SUPPORTED);
6578 return FALSE;
6580 if (g_b_init_open_thread_token == 0)
6582 g_b_init_open_thread_token = 1;
6583 hm_advapi32 = LoadLibrary ("Advapi32.dll");
6584 s_pfn_Open_Thread_Token =
6585 (OpenThreadToken_Proc) GetProcAddress (hm_advapi32, "OpenThreadToken");
6587 if (s_pfn_Open_Thread_Token == NULL)
6589 SetLastError (ERROR_NOT_SUPPORTED);
6590 return FALSE;
6592 return (
6593 s_pfn_Open_Thread_Token (
6594 ThreadHandle,
6595 DesiredAccess,
6596 OpenAsSelf,
6597 TokenHandle)
6601 static BOOL WINAPI
6602 impersonate_self (SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
6604 static ImpersonateSelf_Proc s_pfn_Impersonate_Self = NULL;
6605 HMODULE hm_advapi32 = NULL;
6606 if (is_windows_9x () == TRUE)
6608 return FALSE;
6610 if (g_b_init_impersonate_self == 0)
6612 g_b_init_impersonate_self = 1;
6613 hm_advapi32 = LoadLibrary ("Advapi32.dll");
6614 s_pfn_Impersonate_Self =
6615 (ImpersonateSelf_Proc) GetProcAddress (hm_advapi32, "ImpersonateSelf");
6617 if (s_pfn_Impersonate_Self == NULL)
6619 return FALSE;
6621 return s_pfn_Impersonate_Self (ImpersonationLevel);
6624 static BOOL WINAPI
6625 revert_to_self (void)
6627 static RevertToSelf_Proc s_pfn_Revert_To_Self = NULL;
6628 HMODULE hm_advapi32 = NULL;
6629 if (is_windows_9x () == TRUE)
6631 return FALSE;
6633 if (g_b_init_revert_to_self == 0)
6635 g_b_init_revert_to_self = 1;
6636 hm_advapi32 = LoadLibrary ("Advapi32.dll");
6637 s_pfn_Revert_To_Self =
6638 (RevertToSelf_Proc) GetProcAddress (hm_advapi32, "RevertToSelf");
6640 if (s_pfn_Revert_To_Self == NULL)
6642 return FALSE;
6644 return s_pfn_Revert_To_Self ();
6647 static BOOL WINAPI
6648 get_process_memory_info (HANDLE h_proc,
6649 PPROCESS_MEMORY_COUNTERS mem_counters,
6650 DWORD bufsize)
6652 static GetProcessMemoryInfo_Proc s_pfn_Get_Process_Memory_Info = NULL;
6653 HMODULE hm_psapi = NULL;
6654 if (is_windows_9x () == TRUE)
6656 return FALSE;
6658 if (g_b_init_get_process_memory_info == 0)
6660 g_b_init_get_process_memory_info = 1;
6661 hm_psapi = LoadLibrary ("Psapi.dll");
6662 if (hm_psapi)
6663 s_pfn_Get_Process_Memory_Info = (GetProcessMemoryInfo_Proc)
6664 GetProcAddress (hm_psapi, "GetProcessMemoryInfo");
6666 if (s_pfn_Get_Process_Memory_Info == NULL)
6668 return FALSE;
6670 return s_pfn_Get_Process_Memory_Info (h_proc, mem_counters, bufsize);
6673 static BOOL WINAPI
6674 get_process_working_set_size (HANDLE h_proc,
6675 PSIZE_T minrss,
6676 PSIZE_T maxrss)
6678 static GetProcessWorkingSetSize_Proc
6679 s_pfn_Get_Process_Working_Set_Size = NULL;
6681 if (is_windows_9x () == TRUE)
6683 return FALSE;
6685 if (g_b_init_get_process_working_set_size == 0)
6687 g_b_init_get_process_working_set_size = 1;
6688 s_pfn_Get_Process_Working_Set_Size = (GetProcessWorkingSetSize_Proc)
6689 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6690 "GetProcessWorkingSetSize");
6692 if (s_pfn_Get_Process_Working_Set_Size == NULL)
6694 return FALSE;
6696 return s_pfn_Get_Process_Working_Set_Size (h_proc, minrss, maxrss);
6699 static BOOL WINAPI
6700 global_memory_status (MEMORYSTATUS *buf)
6702 static GlobalMemoryStatus_Proc s_pfn_Global_Memory_Status = NULL;
6704 if (is_windows_9x () == TRUE)
6706 return FALSE;
6708 if (g_b_init_global_memory_status == 0)
6710 g_b_init_global_memory_status = 1;
6711 s_pfn_Global_Memory_Status = (GlobalMemoryStatus_Proc)
6712 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6713 "GlobalMemoryStatus");
6715 if (s_pfn_Global_Memory_Status == NULL)
6717 return FALSE;
6719 return s_pfn_Global_Memory_Status (buf);
6722 static BOOL WINAPI
6723 global_memory_status_ex (MEMORY_STATUS_EX *buf)
6725 static GlobalMemoryStatusEx_Proc s_pfn_Global_Memory_Status_Ex = NULL;
6727 if (is_windows_9x () == TRUE)
6729 return FALSE;
6731 if (g_b_init_global_memory_status_ex == 0)
6733 g_b_init_global_memory_status_ex = 1;
6734 s_pfn_Global_Memory_Status_Ex = (GlobalMemoryStatusEx_Proc)
6735 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6736 "GlobalMemoryStatusEx");
6738 if (s_pfn_Global_Memory_Status_Ex == NULL)
6740 return FALSE;
6742 return s_pfn_Global_Memory_Status_Ex (buf);
6745 Lisp_Object
6746 list_system_processes (void)
6748 Lisp_Object proclist = Qnil;
6749 HANDLE h_snapshot;
6751 h_snapshot = create_toolhelp32_snapshot (TH32CS_SNAPPROCESS, 0);
6753 if (h_snapshot != INVALID_HANDLE_VALUE)
6755 PROCESSENTRY32 proc_entry;
6756 DWORD proc_id;
6757 BOOL res;
6759 proc_entry.dwSize = sizeof (PROCESSENTRY32);
6760 for (res = process32_first (h_snapshot, &proc_entry); res;
6761 res = process32_next (h_snapshot, &proc_entry))
6763 proc_id = proc_entry.th32ProcessID;
6764 proclist = Fcons (make_fixnum_or_float (proc_id), proclist);
6767 CloseHandle (h_snapshot);
6768 proclist = Fnreverse (proclist);
6771 return proclist;
6774 static int
6775 enable_privilege (LPCTSTR priv_name, BOOL enable_p, TOKEN_PRIVILEGES *old_priv)
6777 TOKEN_PRIVILEGES priv;
6778 DWORD priv_size = sizeof (priv);
6779 DWORD opriv_size = sizeof (*old_priv);
6780 HANDLE h_token = NULL;
6781 HANDLE h_thread = GetCurrentThread ();
6782 int ret_val = 0;
6783 BOOL res;
6785 res = open_thread_token (h_thread,
6786 TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
6787 FALSE, &h_token);
6788 if (!res && GetLastError () == ERROR_NO_TOKEN)
6790 if (impersonate_self (SecurityImpersonation))
6791 res = open_thread_token (h_thread,
6792 TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
6793 FALSE, &h_token);
6795 if (res)
6797 priv.PrivilegeCount = 1;
6798 priv.Privileges[0].Attributes = enable_p ? SE_PRIVILEGE_ENABLED : 0;
6799 LookupPrivilegeValue (NULL, priv_name, &priv.Privileges[0].Luid);
6800 if (AdjustTokenPrivileges (h_token, FALSE, &priv, priv_size,
6801 old_priv, &opriv_size)
6802 && GetLastError () != ERROR_NOT_ALL_ASSIGNED)
6803 ret_val = 1;
6805 if (h_token)
6806 CloseHandle (h_token);
6808 return ret_val;
6811 static int
6812 restore_privilege (TOKEN_PRIVILEGES *priv)
6814 DWORD priv_size = sizeof (*priv);
6815 HANDLE h_token = NULL;
6816 int ret_val = 0;
6818 if (open_thread_token (GetCurrentThread (),
6819 TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
6820 FALSE, &h_token))
6822 if (AdjustTokenPrivileges (h_token, FALSE, priv, priv_size, NULL, NULL)
6823 && GetLastError () != ERROR_NOT_ALL_ASSIGNED)
6824 ret_val = 1;
6826 if (h_token)
6827 CloseHandle (h_token);
6829 return ret_val;
6832 static Lisp_Object
6833 ltime (ULONGLONG time_100ns)
6835 ULONGLONG time_sec = time_100ns / 10000000;
6836 int subsec = time_100ns % 10000000;
6837 return list4i (time_sec >> 16, time_sec & 0xffff,
6838 subsec / 10, subsec % 10 * 100000);
6841 #define U64_TO_LISP_TIME(time) ltime (time)
6843 static int
6844 process_times (HANDLE h_proc, Lisp_Object *ctime, Lisp_Object *etime,
6845 Lisp_Object *stime, Lisp_Object *utime, Lisp_Object *ttime,
6846 double *pcpu)
6848 FILETIME ft_creation, ft_exit, ft_kernel, ft_user, ft_current;
6849 ULONGLONG tem1, tem2, tem3, tem;
6851 if (!h_proc
6852 || !get_process_times_fn
6853 || !(*get_process_times_fn) (h_proc, &ft_creation, &ft_exit,
6854 &ft_kernel, &ft_user))
6855 return 0;
6857 GetSystemTimeAsFileTime (&ft_current);
6859 FILETIME_TO_U64 (tem1, ft_kernel);
6860 *stime = U64_TO_LISP_TIME (tem1);
6862 FILETIME_TO_U64 (tem2, ft_user);
6863 *utime = U64_TO_LISP_TIME (tem2);
6865 tem3 = tem1 + tem2;
6866 *ttime = U64_TO_LISP_TIME (tem3);
6868 FILETIME_TO_U64 (tem, ft_creation);
6869 /* Process no 4 (System) returns zero creation time. */
6870 if (tem)
6871 tem -= utc_base;
6872 *ctime = U64_TO_LISP_TIME (tem);
6874 if (tem)
6876 FILETIME_TO_U64 (tem3, ft_current);
6877 tem = (tem3 - utc_base) - tem;
6879 *etime = U64_TO_LISP_TIME (tem);
6881 if (tem)
6883 *pcpu = 100.0 * (tem1 + tem2) / tem;
6884 if (*pcpu > 100)
6885 *pcpu = 100.0;
6887 else
6888 *pcpu = 0;
6890 return 1;
6893 Lisp_Object
6894 system_process_attributes (Lisp_Object pid)
6896 Lisp_Object attrs = Qnil;
6897 Lisp_Object cmd_str, decoded_cmd, tem;
6898 HANDLE h_snapshot, h_proc;
6899 DWORD proc_id;
6900 int found_proc = 0;
6901 char uname[UNLEN+1], gname[GNLEN+1], domain[1025];
6902 DWORD ulength = sizeof (uname), dlength = sizeof (domain), needed;
6903 DWORD glength = sizeof (gname);
6904 HANDLE token = NULL;
6905 SID_NAME_USE user_type;
6906 unsigned char *buf = NULL;
6907 DWORD blen = 0;
6908 TOKEN_USER user_token;
6909 TOKEN_PRIMARY_GROUP group_token;
6910 unsigned euid;
6911 unsigned egid;
6912 PROCESS_MEMORY_COUNTERS mem;
6913 PROCESS_MEMORY_COUNTERS_EX mem_ex;
6914 SIZE_T minrss, maxrss;
6915 MEMORYSTATUS memst;
6916 MEMORY_STATUS_EX memstex;
6917 double totphys = 0.0;
6918 Lisp_Object ctime, stime, utime, etime, ttime;
6919 double pcpu;
6920 BOOL result = FALSE;
6922 CHECK_NUMBER_OR_FLOAT (pid);
6923 proc_id = FLOATP (pid) ? XFLOAT_DATA (pid) : XINT (pid);
6925 h_snapshot = create_toolhelp32_snapshot (TH32CS_SNAPPROCESS, 0);
6927 if (h_snapshot != INVALID_HANDLE_VALUE)
6929 PROCESSENTRY32 pe;
6930 BOOL res;
6932 pe.dwSize = sizeof (PROCESSENTRY32);
6933 for (res = process32_first (h_snapshot, &pe); res;
6934 res = process32_next (h_snapshot, &pe))
6936 if (proc_id == pe.th32ProcessID)
6938 if (proc_id == 0)
6939 decoded_cmd = build_string ("Idle");
6940 else
6942 /* Decode the command name from locale-specific
6943 encoding. */
6944 cmd_str = build_unibyte_string (pe.szExeFile);
6946 decoded_cmd =
6947 code_convert_string_norecord (cmd_str,
6948 Vlocale_coding_system, 0);
6950 attrs = Fcons (Fcons (Qcomm, decoded_cmd), attrs);
6951 attrs = Fcons (Fcons (Qppid,
6952 make_fixnum_or_float (pe.th32ParentProcessID)),
6953 attrs);
6954 attrs = Fcons (Fcons (Qpri, make_number (pe.pcPriClassBase)),
6955 attrs);
6956 attrs = Fcons (Fcons (Qthcount,
6957 make_fixnum_or_float (pe.cntThreads)),
6958 attrs);
6959 found_proc = 1;
6960 break;
6964 CloseHandle (h_snapshot);
6967 if (!found_proc)
6968 return Qnil;
6970 h_proc = OpenProcess (PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
6971 FALSE, proc_id);
6972 /* If we were denied a handle to the process, try again after
6973 enabling the SeDebugPrivilege in our process. */
6974 if (!h_proc)
6976 TOKEN_PRIVILEGES priv_current;
6978 if (enable_privilege (SE_DEBUG_NAME, TRUE, &priv_current))
6980 h_proc = OpenProcess (PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
6981 FALSE, proc_id);
6982 restore_privilege (&priv_current);
6983 revert_to_self ();
6986 if (h_proc)
6988 result = open_process_token (h_proc, TOKEN_QUERY, &token);
6989 if (result)
6991 result = get_token_information (token, TokenUser, NULL, 0, &blen);
6992 if (!result && GetLastError () == ERROR_INSUFFICIENT_BUFFER)
6994 buf = xmalloc (blen);
6995 result = get_token_information (token, TokenUser,
6996 (LPVOID)buf, blen, &needed);
6997 if (result)
6999 memcpy (&user_token, buf, sizeof (user_token));
7000 if (!w32_cached_id (user_token.User.Sid, &euid, uname))
7002 euid = get_rid (user_token.User.Sid);
7003 result = lookup_account_sid (NULL, user_token.User.Sid,
7004 uname, &ulength,
7005 domain, &dlength,
7006 &user_type);
7007 if (result)
7008 w32_add_to_cache (user_token.User.Sid, euid, uname);
7009 else
7011 strcpy (uname, "unknown");
7012 result = TRUE;
7015 ulength = strlen (uname);
7019 if (result)
7021 /* Determine a reasonable euid and gid values. */
7022 if (xstrcasecmp ("administrator", uname) == 0)
7024 euid = 500; /* well-known Administrator uid */
7025 egid = 513; /* well-known None gid */
7027 else
7029 /* Get group id and name. */
7030 result = get_token_information (token, TokenPrimaryGroup,
7031 (LPVOID)buf, blen, &needed);
7032 if (!result && GetLastError () == ERROR_INSUFFICIENT_BUFFER)
7034 buf = xrealloc (buf, blen = needed);
7035 result = get_token_information (token, TokenPrimaryGroup,
7036 (LPVOID)buf, blen, &needed);
7038 if (result)
7040 memcpy (&group_token, buf, sizeof (group_token));
7041 if (!w32_cached_id (group_token.PrimaryGroup, &egid, gname))
7043 egid = get_rid (group_token.PrimaryGroup);
7044 dlength = sizeof (domain);
7045 result =
7046 lookup_account_sid (NULL, group_token.PrimaryGroup,
7047 gname, &glength, NULL, &dlength,
7048 &user_type);
7049 if (result)
7050 w32_add_to_cache (group_token.PrimaryGroup,
7051 egid, gname);
7052 else
7054 strcpy (gname, "None");
7055 result = TRUE;
7058 glength = strlen (gname);
7062 xfree (buf);
7064 if (!result)
7066 if (!is_windows_9x ())
7068 /* We couldn't open the process token, presumably because of
7069 insufficient access rights. Assume this process is run
7070 by the system. */
7071 strcpy (uname, "SYSTEM");
7072 strcpy (gname, "None");
7073 euid = 18; /* SYSTEM */
7074 egid = 513; /* None */
7075 glength = strlen (gname);
7076 ulength = strlen (uname);
7078 /* If we are running under Windows 9X, where security calls are
7079 not supported, we assume all processes are run by the current
7080 user. */
7081 else if (GetUserName (uname, &ulength))
7083 if (xstrcasecmp ("administrator", uname) == 0)
7084 euid = 0;
7085 else
7086 euid = 123;
7087 egid = euid;
7088 strcpy (gname, "None");
7089 glength = strlen (gname);
7090 ulength = strlen (uname);
7092 else
7094 euid = 123;
7095 egid = 123;
7096 strcpy (uname, "administrator");
7097 ulength = strlen (uname);
7098 strcpy (gname, "None");
7099 glength = strlen (gname);
7101 if (token)
7102 CloseHandle (token);
7105 attrs = Fcons (Fcons (Qeuid, make_fixnum_or_float (euid)), attrs);
7106 tem = make_unibyte_string (uname, ulength);
7107 attrs = Fcons (Fcons (Quser,
7108 code_convert_string_norecord (tem, Vlocale_coding_system, 0)),
7109 attrs);
7110 attrs = Fcons (Fcons (Qegid, make_fixnum_or_float (egid)), attrs);
7111 tem = make_unibyte_string (gname, glength);
7112 attrs = Fcons (Fcons (Qgroup,
7113 code_convert_string_norecord (tem, Vlocale_coding_system, 0)),
7114 attrs);
7116 if (global_memory_status_ex (&memstex))
7117 #if __GNUC__ || (defined (_MSC_VER) && _MSC_VER >= 1300)
7118 totphys = memstex.ullTotalPhys / 1024.0;
7119 #else
7120 /* Visual Studio 6 cannot convert an unsigned __int64 type to
7121 double, so we need to do this for it... */
7123 DWORD tot_hi = memstex.ullTotalPhys >> 32;
7124 DWORD tot_md = (memstex.ullTotalPhys & 0x00000000ffffffff) >> 10;
7125 DWORD tot_lo = memstex.ullTotalPhys % 1024;
7127 totphys = tot_hi * 4194304.0 + tot_md + tot_lo / 1024.0;
7129 #endif /* __GNUC__ || _MSC_VER >= 1300 */
7130 else if (global_memory_status (&memst))
7131 totphys = memst.dwTotalPhys / 1024.0;
7133 if (h_proc
7134 && get_process_memory_info (h_proc, (PROCESS_MEMORY_COUNTERS *)&mem_ex,
7135 sizeof (mem_ex)))
7137 SIZE_T rss = mem_ex.WorkingSetSize / 1024;
7139 attrs = Fcons (Fcons (Qmajflt,
7140 make_fixnum_or_float (mem_ex.PageFaultCount)),
7141 attrs);
7142 attrs = Fcons (Fcons (Qvsize,
7143 make_fixnum_or_float (mem_ex.PrivateUsage / 1024)),
7144 attrs);
7145 attrs = Fcons (Fcons (Qrss, make_fixnum_or_float (rss)), attrs);
7146 if (totphys)
7147 attrs = Fcons (Fcons (Qpmem, make_float (100. * rss / totphys)), attrs);
7149 else if (h_proc
7150 && get_process_memory_info (h_proc, &mem, sizeof (mem)))
7152 SIZE_T rss = mem_ex.WorkingSetSize / 1024;
7154 attrs = Fcons (Fcons (Qmajflt,
7155 make_fixnum_or_float (mem.PageFaultCount)),
7156 attrs);
7157 attrs = Fcons (Fcons (Qrss, make_fixnum_or_float (rss)), attrs);
7158 if (totphys)
7159 attrs = Fcons (Fcons (Qpmem, make_float (100. * rss / totphys)), attrs);
7161 else if (h_proc
7162 && get_process_working_set_size (h_proc, &minrss, &maxrss))
7164 DWORD rss = maxrss / 1024;
7166 attrs = Fcons (Fcons (Qrss, make_fixnum_or_float (maxrss / 1024)), attrs);
7167 if (totphys)
7168 attrs = Fcons (Fcons (Qpmem, make_float (100. * rss / totphys)), attrs);
7171 if (process_times (h_proc, &ctime, &etime, &stime, &utime, &ttime, &pcpu))
7173 attrs = Fcons (Fcons (Qutime, utime), attrs);
7174 attrs = Fcons (Fcons (Qstime, stime), attrs);
7175 attrs = Fcons (Fcons (Qtime, ttime), attrs);
7176 attrs = Fcons (Fcons (Qstart, ctime), attrs);
7177 attrs = Fcons (Fcons (Qetime, etime), attrs);
7178 attrs = Fcons (Fcons (Qpcpu, make_float (pcpu)), attrs);
7181 /* FIXME: Retrieve command line by walking the PEB of the process. */
7183 if (h_proc)
7184 CloseHandle (h_proc);
7185 return attrs;
7189 w32_memory_info (unsigned long long *totalram, unsigned long long *freeram,
7190 unsigned long long *totalswap, unsigned long long *freeswap)
7192 MEMORYSTATUS memst;
7193 MEMORY_STATUS_EX memstex;
7195 /* Use GlobalMemoryStatusEx if available, as it can report more than
7196 2GB of memory. */
7197 if (global_memory_status_ex (&memstex))
7199 *totalram = memstex.ullTotalPhys;
7200 *freeram = memstex.ullAvailPhys;
7201 *totalswap = memstex.ullTotalPageFile;
7202 *freeswap = memstex.ullAvailPageFile;
7203 return 0;
7205 else if (global_memory_status (&memst))
7207 *totalram = memst.dwTotalPhys;
7208 *freeram = memst.dwAvailPhys;
7209 *totalswap = memst.dwTotalPageFile;
7210 *freeswap = memst.dwAvailPageFile;
7211 return 0;
7213 else
7214 return -1;
7218 /* Wrappers for winsock functions to map between our file descriptors
7219 and winsock's handles; also set h_errno for convenience.
7221 To allow Emacs to run on systems which don't have winsock support
7222 installed, we dynamically link to winsock on startup if present, and
7223 otherwise provide the minimum necessary functionality
7224 (eg. gethostname). */
7226 /* function pointers for relevant socket functions */
7227 int (PASCAL *pfn_WSAStartup) (WORD wVersionRequired, LPWSADATA lpWSAData);
7228 void (PASCAL *pfn_WSASetLastError) (int iError);
7229 int (PASCAL *pfn_WSAGetLastError) (void);
7230 int (PASCAL *pfn_WSAEventSelect) (SOCKET s, HANDLE hEventObject, long lNetworkEvents);
7231 int (PASCAL *pfn_WSAEnumNetworkEvents) (SOCKET s, HANDLE hEventObject,
7232 WSANETWORKEVENTS *NetworkEvents);
7234 HANDLE (PASCAL *pfn_WSACreateEvent) (void);
7235 int (PASCAL *pfn_WSACloseEvent) (HANDLE hEvent);
7236 int (PASCAL *pfn_socket) (int af, int type, int protocol);
7237 int (PASCAL *pfn_bind) (SOCKET s, const struct sockaddr *addr, int namelen);
7238 int (PASCAL *pfn_connect) (SOCKET s, const struct sockaddr *addr, int namelen);
7239 int (PASCAL *pfn_ioctlsocket) (SOCKET s, long cmd, u_long *argp);
7240 int (PASCAL *pfn_recv) (SOCKET s, char * buf, int len, int flags);
7241 int (PASCAL *pfn_send) (SOCKET s, const char * buf, int len, int flags);
7242 int (PASCAL *pfn_closesocket) (SOCKET s);
7243 int (PASCAL *pfn_shutdown) (SOCKET s, int how);
7244 int (PASCAL *pfn_WSACleanup) (void);
7246 u_short (PASCAL *pfn_htons) (u_short hostshort);
7247 u_short (PASCAL *pfn_ntohs) (u_short netshort);
7248 unsigned long (PASCAL *pfn_inet_addr) (const char * cp);
7249 int (PASCAL *pfn_gethostname) (char * name, int namelen);
7250 struct hostent * (PASCAL *pfn_gethostbyname) (const char * name);
7251 struct servent * (PASCAL *pfn_getservbyname) (const char * name, const char * proto);
7252 int (PASCAL *pfn_getpeername) (SOCKET s, struct sockaddr *addr, int * namelen);
7253 int (PASCAL *pfn_setsockopt) (SOCKET s, int level, int optname,
7254 const char * optval, int optlen);
7255 int (PASCAL *pfn_listen) (SOCKET s, int backlog);
7256 int (PASCAL *pfn_getsockname) (SOCKET s, struct sockaddr * name,
7257 int * namelen);
7258 SOCKET (PASCAL *pfn_accept) (SOCKET s, struct sockaddr * addr, int * addrlen);
7259 int (PASCAL *pfn_recvfrom) (SOCKET s, char * buf, int len, int flags,
7260 struct sockaddr * from, int * fromlen);
7261 int (PASCAL *pfn_sendto) (SOCKET s, const char * buf, int len, int flags,
7262 const struct sockaddr * to, int tolen);
7264 int (PASCAL *pfn_getaddrinfo) (const char *, const char *,
7265 const struct addrinfo *, struct addrinfo **);
7266 void (PASCAL *pfn_freeaddrinfo) (struct addrinfo *);
7268 /* SetHandleInformation is only needed to make sockets non-inheritable. */
7269 BOOL (WINAPI *pfn_SetHandleInformation) (HANDLE object, DWORD mask, DWORD flags);
7270 #ifndef HANDLE_FLAG_INHERIT
7271 #define HANDLE_FLAG_INHERIT 1
7272 #endif
7274 HANDLE winsock_lib;
7275 static int winsock_inuse;
7277 BOOL term_winsock (void);
7279 BOOL
7280 term_winsock (void)
7282 if (winsock_lib != NULL && winsock_inuse == 0)
7284 release_listen_threads ();
7285 /* Not sure what would cause WSAENETDOWN, or even if it can happen
7286 after WSAStartup returns successfully, but it seems reasonable
7287 to allow unloading winsock anyway in that case. */
7288 if (pfn_WSACleanup () == 0 ||
7289 pfn_WSAGetLastError () == WSAENETDOWN)
7291 if (FreeLibrary (winsock_lib))
7292 winsock_lib = NULL;
7293 return TRUE;
7296 return FALSE;
7299 BOOL
7300 init_winsock (int load_now)
7302 WSADATA winsockData;
7304 if (winsock_lib != NULL)
7305 return TRUE;
7307 pfn_SetHandleInformation
7308 = (void *) GetProcAddress (GetModuleHandle ("kernel32.dll"),
7309 "SetHandleInformation");
7311 winsock_lib = LoadLibrary ("Ws2_32.dll");
7313 if (winsock_lib != NULL)
7315 /* dynamically link to socket functions */
7317 #define LOAD_PROC(fn) \
7318 if ((pfn_##fn = (void *) GetProcAddress (winsock_lib, #fn)) == NULL) \
7319 goto fail;
7321 LOAD_PROC (WSAStartup);
7322 LOAD_PROC (WSASetLastError);
7323 LOAD_PROC (WSAGetLastError);
7324 LOAD_PROC (WSAEventSelect);
7325 LOAD_PROC (WSAEnumNetworkEvents);
7326 LOAD_PROC (WSACreateEvent);
7327 LOAD_PROC (WSACloseEvent);
7328 LOAD_PROC (socket);
7329 LOAD_PROC (bind);
7330 LOAD_PROC (connect);
7331 LOAD_PROC (ioctlsocket);
7332 LOAD_PROC (recv);
7333 LOAD_PROC (send);
7334 LOAD_PROC (closesocket);
7335 LOAD_PROC (shutdown);
7336 LOAD_PROC (htons);
7337 LOAD_PROC (ntohs);
7338 LOAD_PROC (inet_addr);
7339 LOAD_PROC (gethostname);
7340 LOAD_PROC (gethostbyname);
7341 LOAD_PROC (getservbyname);
7342 LOAD_PROC (getpeername);
7343 LOAD_PROC (WSACleanup);
7344 LOAD_PROC (setsockopt);
7345 LOAD_PROC (listen);
7346 LOAD_PROC (getsockname);
7347 LOAD_PROC (accept);
7348 LOAD_PROC (recvfrom);
7349 LOAD_PROC (sendto);
7350 #undef LOAD_PROC
7352 /* Try loading functions not available before XP. */
7353 pfn_getaddrinfo = (void *) GetProcAddress (winsock_lib, "getaddrinfo");
7354 pfn_freeaddrinfo = (void *) GetProcAddress (winsock_lib, "freeaddrinfo");
7355 /* Paranoia: these two functions should go together, so if one
7356 is absent, we cannot use the other. */
7357 if (pfn_getaddrinfo == NULL)
7358 pfn_freeaddrinfo = NULL;
7359 else if (pfn_freeaddrinfo == NULL)
7360 pfn_getaddrinfo = NULL;
7362 /* specify version 1.1 of winsock */
7363 if (pfn_WSAStartup (0x101, &winsockData) == 0)
7365 if (winsockData.wVersion != 0x101)
7366 goto fail;
7368 if (!load_now)
7370 /* Report that winsock exists and is usable, but leave
7371 socket functions disabled. I am assuming that calling
7372 WSAStartup does not require any network interaction,
7373 and in particular does not cause or require a dial-up
7374 connection to be established. */
7376 pfn_WSACleanup ();
7377 FreeLibrary (winsock_lib);
7378 winsock_lib = NULL;
7380 winsock_inuse = 0;
7381 return TRUE;
7384 fail:
7385 FreeLibrary (winsock_lib);
7386 winsock_lib = NULL;
7389 return FALSE;
7393 int h_errno = 0;
7395 /* Function to map winsock error codes to errno codes for those errno
7396 code defined in errno.h (errno values not defined by errno.h are
7397 already in nt/inc/sys/socket.h). */
7398 static void
7399 set_errno (void)
7401 int wsa_err;
7403 h_errno = 0;
7404 if (winsock_lib == NULL)
7405 wsa_err = EINVAL;
7406 else
7407 wsa_err = pfn_WSAGetLastError ();
7409 switch (wsa_err)
7411 case WSAEACCES: errno = EACCES; break;
7412 case WSAEBADF: errno = EBADF; break;
7413 case WSAEFAULT: errno = EFAULT; break;
7414 case WSAEINTR: errno = EINTR; break;
7415 case WSAEINVAL: errno = EINVAL; break;
7416 case WSAEMFILE: errno = EMFILE; break;
7417 case WSAENAMETOOLONG: errno = ENAMETOOLONG; break;
7418 case WSAENOTEMPTY: errno = ENOTEMPTY; break;
7419 case WSAEWOULDBLOCK: errno = EWOULDBLOCK; break;
7420 case WSAENOTCONN: errno = ENOTCONN; break;
7421 default: errno = wsa_err; break;
7425 static void
7426 check_errno (void)
7428 h_errno = 0;
7429 if (winsock_lib != NULL)
7430 pfn_WSASetLastError (0);
7433 /* Extend strerror to handle the winsock-specific error codes. */
7434 struct {
7435 int errnum;
7436 const char * msg;
7437 } _wsa_errlist[] = {
7438 {WSAEINTR , "Interrupted function call"},
7439 {WSAEBADF , "Bad file descriptor"},
7440 {WSAEACCES , "Permission denied"},
7441 {WSAEFAULT , "Bad address"},
7442 {WSAEINVAL , "Invalid argument"},
7443 {WSAEMFILE , "Too many open files"},
7445 {WSAEWOULDBLOCK , "Resource temporarily unavailable"},
7446 {WSAEINPROGRESS , "Operation now in progress"},
7447 {WSAEALREADY , "Operation already in progress"},
7448 {WSAENOTSOCK , "Socket operation on non-socket"},
7449 {WSAEDESTADDRREQ , "Destination address required"},
7450 {WSAEMSGSIZE , "Message too long"},
7451 {WSAEPROTOTYPE , "Protocol wrong type for socket"},
7452 {WSAENOPROTOOPT , "Bad protocol option"},
7453 {WSAEPROTONOSUPPORT , "Protocol not supported"},
7454 {WSAESOCKTNOSUPPORT , "Socket type not supported"},
7455 {WSAEOPNOTSUPP , "Operation not supported"},
7456 {WSAEPFNOSUPPORT , "Protocol family not supported"},
7457 {WSAEAFNOSUPPORT , "Address family not supported by protocol family"},
7458 {WSAEADDRINUSE , "Address already in use"},
7459 {WSAEADDRNOTAVAIL , "Cannot assign requested address"},
7460 {WSAENETDOWN , "Network is down"},
7461 {WSAENETUNREACH , "Network is unreachable"},
7462 {WSAENETRESET , "Network dropped connection on reset"},
7463 {WSAECONNABORTED , "Software caused connection abort"},
7464 {WSAECONNRESET , "Connection reset by peer"},
7465 {WSAENOBUFS , "No buffer space available"},
7466 {WSAEISCONN , "Socket is already connected"},
7467 {WSAENOTCONN , "Socket is not connected"},
7468 {WSAESHUTDOWN , "Cannot send after socket shutdown"},
7469 {WSAETOOMANYREFS , "Too many references"}, /* not sure */
7470 {WSAETIMEDOUT , "Connection timed out"},
7471 {WSAECONNREFUSED , "Connection refused"},
7472 {WSAELOOP , "Network loop"}, /* not sure */
7473 {WSAENAMETOOLONG , "Name is too long"},
7474 {WSAEHOSTDOWN , "Host is down"},
7475 {WSAEHOSTUNREACH , "No route to host"},
7476 {WSAENOTEMPTY , "Buffer not empty"}, /* not sure */
7477 {WSAEPROCLIM , "Too many processes"},
7478 {WSAEUSERS , "Too many users"}, /* not sure */
7479 {WSAEDQUOT , "Double quote in host name"}, /* really not sure */
7480 {WSAESTALE , "Data is stale"}, /* not sure */
7481 {WSAEREMOTE , "Remote error"}, /* not sure */
7483 {WSASYSNOTREADY , "Network subsystem is unavailable"},
7484 {WSAVERNOTSUPPORTED , "WINSOCK.DLL version out of range"},
7485 {WSANOTINITIALISED , "Winsock not initialized successfully"},
7486 {WSAEDISCON , "Graceful shutdown in progress"},
7487 #ifdef WSAENOMORE
7488 {WSAENOMORE , "No more operations allowed"}, /* not sure */
7489 {WSAECANCELLED , "Operation cancelled"}, /* not sure */
7490 {WSAEINVALIDPROCTABLE , "Invalid procedure table from service provider"},
7491 {WSAEINVALIDPROVIDER , "Invalid service provider version number"},
7492 {WSAEPROVIDERFAILEDINIT , "Unable to initialize a service provider"},
7493 {WSASYSCALLFAILURE , "System call failure"},
7494 {WSASERVICE_NOT_FOUND , "Service not found"}, /* not sure */
7495 {WSATYPE_NOT_FOUND , "Class type not found"},
7496 {WSA_E_NO_MORE , "No more resources available"}, /* really not sure */
7497 {WSA_E_CANCELLED , "Operation already cancelled"}, /* really not sure */
7498 {WSAEREFUSED , "Operation refused"}, /* not sure */
7499 #endif
7501 {WSAHOST_NOT_FOUND , "Host not found"},
7502 {WSATRY_AGAIN , "Authoritative host not found during name lookup"},
7503 {WSANO_RECOVERY , "Non-recoverable error during name lookup"},
7504 {WSANO_DATA , "Valid name, no data record of requested type"},
7506 {-1, NULL}
7509 char *
7510 sys_strerror (int error_no)
7512 int i;
7513 static char unknown_msg[40];
7515 if (error_no >= 0 && error_no < sys_nerr)
7516 return sys_errlist[error_no];
7518 for (i = 0; _wsa_errlist[i].errnum >= 0; i++)
7519 if (_wsa_errlist[i].errnum == error_no)
7520 return (char *)_wsa_errlist[i].msg;
7522 sprintf (unknown_msg, "Unidentified error: %d", error_no);
7523 return unknown_msg;
7526 /* [andrewi 3-May-96] I've had conflicting results using both methods,
7527 but I believe the method of keeping the socket handle separate (and
7528 insuring it is not inheritable) is the correct one. */
7530 #define SOCK_HANDLE(fd) ((SOCKET) fd_info[fd].hnd)
7532 static int socket_to_fd (SOCKET s);
7535 sys_socket (int af, int type, int protocol)
7537 SOCKET s;
7539 if (winsock_lib == NULL)
7541 errno = ENETDOWN;
7542 return -1;
7545 check_errno ();
7547 /* call the real socket function */
7548 s = pfn_socket (af, type, protocol);
7550 if (s != INVALID_SOCKET)
7551 return socket_to_fd (s);
7553 set_errno ();
7554 return -1;
7557 /* Convert a SOCKET to a file descriptor. */
7558 static int
7559 socket_to_fd (SOCKET s)
7561 int fd;
7562 child_process * cp;
7564 /* Although under NT 3.5 _open_osfhandle will accept a socket
7565 handle, if opened with SO_OPENTYPE == SO_SYNCHRONOUS_NONALERT,
7566 that does not work under NT 3.1. However, we can get the same
7567 effect by using a backdoor function to replace an existing
7568 descriptor handle with the one we want. */
7570 /* allocate a file descriptor (with appropriate flags) */
7571 fd = _open ("NUL:", _O_RDWR);
7572 if (fd >= 0)
7574 /* Make a non-inheritable copy of the socket handle. Note
7575 that it is possible that sockets aren't actually kernel
7576 handles, which appears to be the case on Windows 9x when
7577 the MS Proxy winsock client is installed. */
7579 /* Apparently there is a bug in NT 3.51 with some service
7580 packs, which prevents using DuplicateHandle to make a
7581 socket handle non-inheritable (causes WSACleanup to
7582 hang). The work-around is to use SetHandleInformation
7583 instead if it is available and implemented. */
7584 if (pfn_SetHandleInformation)
7586 pfn_SetHandleInformation ((HANDLE) s, HANDLE_FLAG_INHERIT, 0);
7588 else
7590 HANDLE parent = GetCurrentProcess ();
7591 HANDLE new_s = INVALID_HANDLE_VALUE;
7593 if (DuplicateHandle (parent,
7594 (HANDLE) s,
7595 parent,
7596 &new_s,
7598 FALSE,
7599 DUPLICATE_SAME_ACCESS))
7601 /* It is possible that DuplicateHandle succeeds even
7602 though the socket wasn't really a kernel handle,
7603 because a real handle has the same value. So
7604 test whether the new handle really is a socket. */
7605 unsigned long nonblocking = 0;
7606 if (pfn_ioctlsocket ((SOCKET) new_s, FIONBIO, &nonblocking) == 0)
7608 pfn_closesocket (s);
7609 s = (SOCKET) new_s;
7611 else
7613 CloseHandle (new_s);
7618 eassert (fd < MAXDESC);
7619 fd_info[fd].hnd = (HANDLE) s;
7621 /* set our own internal flags */
7622 fd_info[fd].flags = FILE_SOCKET | FILE_BINARY | FILE_READ | FILE_WRITE;
7624 cp = new_child ();
7625 if (cp)
7627 cp->fd = fd;
7628 cp->status = STATUS_READ_ACKNOWLEDGED;
7630 /* attach child_process to fd_info */
7631 if (fd_info[ fd ].cp != NULL)
7633 DebPrint (("sys_socket: fd_info[%d] apparently in use!\n", fd));
7634 emacs_abort ();
7637 fd_info[ fd ].cp = cp;
7639 /* success! */
7640 winsock_inuse++; /* count open sockets */
7641 return fd;
7644 /* clean up */
7645 _close (fd);
7647 else
7648 pfn_closesocket (s);
7649 errno = EMFILE;
7650 return -1;
7654 sys_bind (int s, const struct sockaddr * addr, int namelen)
7656 if (winsock_lib == NULL)
7658 errno = ENOTSOCK;
7659 return SOCKET_ERROR;
7662 check_errno ();
7663 if (fd_info[s].flags & FILE_SOCKET)
7665 int rc = pfn_bind (SOCK_HANDLE (s), addr, namelen);
7666 if (rc == SOCKET_ERROR)
7667 set_errno ();
7668 return rc;
7670 errno = ENOTSOCK;
7671 return SOCKET_ERROR;
7675 sys_connect (int s, const struct sockaddr * name, int namelen)
7677 if (winsock_lib == NULL)
7679 errno = ENOTSOCK;
7680 return SOCKET_ERROR;
7683 check_errno ();
7684 if (fd_info[s].flags & FILE_SOCKET)
7686 int rc = pfn_connect (SOCK_HANDLE (s), name, namelen);
7687 if (rc == SOCKET_ERROR)
7689 set_errno ();
7690 /* If this is a non-blocking 'connect', set the bit in flags
7691 that will tell reader_thread to wait for connection
7692 before trying to read. */
7693 if (errno == EWOULDBLOCK && (fd_info[s].flags & FILE_NDELAY) != 0)
7695 errno = EINPROGRESS; /* that's what process.c expects */
7696 fd_info[s].flags |= FILE_CONNECT;
7699 return rc;
7701 errno = ENOTSOCK;
7702 return SOCKET_ERROR;
7705 u_short
7706 sys_htons (u_short hostshort)
7708 return (winsock_lib != NULL) ?
7709 pfn_htons (hostshort) : hostshort;
7712 u_short
7713 sys_ntohs (u_short netshort)
7715 return (winsock_lib != NULL) ?
7716 pfn_ntohs (netshort) : netshort;
7719 unsigned long
7720 sys_inet_addr (const char * cp)
7722 return (winsock_lib != NULL) ?
7723 pfn_inet_addr (cp) : INADDR_NONE;
7727 sys_gethostname (char * name, int namelen)
7729 if (winsock_lib != NULL)
7731 int retval;
7733 check_errno ();
7734 retval = pfn_gethostname (name, namelen);
7735 if (retval == SOCKET_ERROR)
7736 set_errno ();
7737 return retval;
7740 if (namelen > MAX_COMPUTERNAME_LENGTH)
7741 return !GetComputerName (name, (DWORD *)&namelen);
7743 errno = EFAULT;
7744 return SOCKET_ERROR;
7747 struct hostent *
7748 sys_gethostbyname (const char * name)
7750 struct hostent * host;
7751 int h_err = h_errno;
7753 if (winsock_lib == NULL)
7755 h_errno = NO_RECOVERY;
7756 errno = ENETDOWN;
7757 return NULL;
7760 check_errno ();
7761 host = pfn_gethostbyname (name);
7762 if (!host)
7764 set_errno ();
7765 h_errno = errno;
7767 else
7768 h_errno = h_err;
7769 return host;
7772 struct servent *
7773 sys_getservbyname (const char * name, const char * proto)
7775 struct servent * serv;
7777 if (winsock_lib == NULL)
7779 errno = ENETDOWN;
7780 return NULL;
7783 check_errno ();
7784 serv = pfn_getservbyname (name, proto);
7785 if (!serv)
7786 set_errno ();
7787 return serv;
7791 sys_getpeername (int s, struct sockaddr *addr, int * namelen)
7793 if (winsock_lib == NULL)
7795 errno = ENETDOWN;
7796 return SOCKET_ERROR;
7799 check_errno ();
7800 if (fd_info[s].flags & FILE_SOCKET)
7802 int rc = pfn_getpeername (SOCK_HANDLE (s), addr, namelen);
7803 if (rc == SOCKET_ERROR)
7804 set_errno ();
7805 return rc;
7807 errno = ENOTSOCK;
7808 return SOCKET_ERROR;
7812 sys_getaddrinfo (const char *node, const char *service,
7813 const struct addrinfo *hints, struct addrinfo **res)
7815 int rc;
7817 if (winsock_lib == NULL)
7819 errno = ENETDOWN;
7820 return SOCKET_ERROR;
7823 check_errno ();
7824 if (pfn_getaddrinfo)
7825 rc = pfn_getaddrinfo (node, service, hints, res);
7826 else
7828 int port = 0;
7829 struct hostent *host_info;
7830 struct gai_storage {
7831 struct addrinfo addrinfo;
7832 struct sockaddr_in sockaddr_in;
7833 } *gai_storage;
7835 /* We don't (yet) support any flags, as Emacs doesn't need that. */
7836 if (hints && hints->ai_flags != 0)
7837 return WSAEINVAL;
7838 /* NODE cannot be NULL, since process.c has fallbacks for that. */
7839 if (!node)
7840 return WSAHOST_NOT_FOUND;
7842 if (service)
7844 const char *protocol =
7845 (hints && hints->ai_socktype == SOCK_DGRAM) ? "udp" : "tcp";
7846 struct servent *srv = sys_getservbyname (service, protocol);
7848 if (srv)
7849 port = srv->s_port;
7850 else if (*service >= '0' && *service <= '9')
7852 char *endp;
7854 port = strtoul (service, &endp, 10);
7855 if (*endp || port > 65536)
7856 return WSAHOST_NOT_FOUND;
7857 port = sys_htons ((unsigned short) port);
7859 else
7860 return WSAHOST_NOT_FOUND;
7863 gai_storage = xzalloc (sizeof *gai_storage);
7864 gai_storage->sockaddr_in.sin_port = port;
7865 host_info = sys_gethostbyname (node);
7866 if (host_info)
7868 memcpy (&gai_storage->sockaddr_in.sin_addr,
7869 host_info->h_addr, host_info->h_length);
7870 gai_storage->sockaddr_in.sin_family = host_info->h_addrtype;
7872 else
7874 /* Attempt to interpret host as numeric inet address. */
7875 unsigned long numeric_addr = sys_inet_addr (node);
7877 if (numeric_addr == -1)
7879 free (gai_storage);
7880 return WSAHOST_NOT_FOUND;
7883 memcpy (&gai_storage->sockaddr_in.sin_addr, &numeric_addr,
7884 sizeof (gai_storage->sockaddr_in.sin_addr));
7885 gai_storage->sockaddr_in.sin_family = (hints) ? hints->ai_family : 0;
7888 gai_storage->addrinfo.ai_addr =
7889 (struct sockaddr *)&gai_storage->sockaddr_in;
7890 gai_storage->addrinfo.ai_addrlen = sizeof (gai_storage->sockaddr_in);
7891 gai_storage->addrinfo.ai_protocol = (hints) ? hints->ai_protocol : 0;
7892 gai_storage->addrinfo.ai_socktype = (hints) ? hints->ai_socktype : 0;
7893 gai_storage->addrinfo.ai_family = gai_storage->sockaddr_in.sin_family;
7894 gai_storage->addrinfo.ai_next = NULL;
7896 *res = &gai_storage->addrinfo;
7897 rc = 0;
7900 return rc;
7903 void
7904 sys_freeaddrinfo (struct addrinfo *ai)
7906 if (winsock_lib == NULL)
7908 errno = ENETDOWN;
7909 return;
7912 check_errno ();
7913 if (pfn_freeaddrinfo)
7914 pfn_freeaddrinfo (ai);
7915 else
7917 eassert (ai->ai_next == NULL);
7918 xfree (ai);
7923 sys_shutdown (int s, int how)
7925 if (winsock_lib == NULL)
7927 errno = ENETDOWN;
7928 return SOCKET_ERROR;
7931 check_errno ();
7932 if (fd_info[s].flags & FILE_SOCKET)
7934 int rc = pfn_shutdown (SOCK_HANDLE (s), how);
7935 if (rc == SOCKET_ERROR)
7936 set_errno ();
7937 return rc;
7939 errno = ENOTSOCK;
7940 return SOCKET_ERROR;
7944 sys_setsockopt (int s, int level, int optname, const void * optval, int optlen)
7946 if (winsock_lib == NULL)
7948 errno = ENETDOWN;
7949 return SOCKET_ERROR;
7952 check_errno ();
7953 if (fd_info[s].flags & FILE_SOCKET)
7955 int rc = pfn_setsockopt (SOCK_HANDLE (s), level, optname,
7956 (const char *)optval, optlen);
7957 if (rc == SOCKET_ERROR)
7958 set_errno ();
7959 return rc;
7961 errno = ENOTSOCK;
7962 return SOCKET_ERROR;
7966 sys_listen (int s, int backlog)
7968 if (winsock_lib == NULL)
7970 errno = ENETDOWN;
7971 return SOCKET_ERROR;
7974 check_errno ();
7975 if (fd_info[s].flags & FILE_SOCKET)
7977 int rc = pfn_listen (SOCK_HANDLE (s), backlog);
7978 if (rc == SOCKET_ERROR)
7979 set_errno ();
7980 else
7981 fd_info[s].flags |= FILE_LISTEN;
7982 return rc;
7984 errno = ENOTSOCK;
7985 return SOCKET_ERROR;
7989 sys_getsockname (int s, struct sockaddr * name, int * namelen)
7991 if (winsock_lib == NULL)
7993 errno = ENETDOWN;
7994 return SOCKET_ERROR;
7997 check_errno ();
7998 if (fd_info[s].flags & FILE_SOCKET)
8000 int rc = pfn_getsockname (SOCK_HANDLE (s), name, namelen);
8001 if (rc == SOCKET_ERROR)
8002 set_errno ();
8003 return rc;
8005 errno = ENOTSOCK;
8006 return SOCKET_ERROR;
8010 sys_accept (int s, struct sockaddr * addr, int * addrlen)
8012 if (winsock_lib == NULL)
8014 errno = ENETDOWN;
8015 return -1;
8018 check_errno ();
8019 if (fd_info[s].flags & FILE_LISTEN)
8021 SOCKET t = pfn_accept (SOCK_HANDLE (s), addr, addrlen);
8022 int fd = -1;
8023 if (t == INVALID_SOCKET)
8024 set_errno ();
8025 else
8026 fd = socket_to_fd (t);
8028 if (fd >= 0)
8030 fd_info[s].cp->status = STATUS_READ_ACKNOWLEDGED;
8031 ResetEvent (fd_info[s].cp->char_avail);
8033 return fd;
8035 errno = ENOTSOCK;
8036 return -1;
8040 sys_recvfrom (int s, char * buf, int len, int flags,
8041 struct sockaddr * from, int * fromlen)
8043 if (winsock_lib == NULL)
8045 errno = ENETDOWN;
8046 return SOCKET_ERROR;
8049 check_errno ();
8050 if (fd_info[s].flags & FILE_SOCKET)
8052 int rc = pfn_recvfrom (SOCK_HANDLE (s), buf, len, flags, from, fromlen);
8053 if (rc == SOCKET_ERROR)
8054 set_errno ();
8055 return rc;
8057 errno = ENOTSOCK;
8058 return SOCKET_ERROR;
8062 sys_sendto (int s, const char * buf, int len, int flags,
8063 const struct sockaddr * to, int tolen)
8065 if (winsock_lib == NULL)
8067 errno = ENETDOWN;
8068 return SOCKET_ERROR;
8071 check_errno ();
8072 if (fd_info[s].flags & FILE_SOCKET)
8074 int rc = pfn_sendto (SOCK_HANDLE (s), buf, len, flags, to, tolen);
8075 if (rc == SOCKET_ERROR)
8076 set_errno ();
8077 return rc;
8079 errno = ENOTSOCK;
8080 return SOCKET_ERROR;
8083 /* Windows does not have an fcntl function. Provide an implementation
8084 good enough for Emacs. */
8086 fcntl (int s, int cmd, int options)
8088 /* In the w32 Emacs port, fcntl (fd, F_DUPFD_CLOEXEC, fd1) is always
8089 invoked in a context where fd1 is closed and all descriptors less
8090 than fd1 are open, so sys_dup is an adequate implementation. */
8091 if (cmd == F_DUPFD_CLOEXEC)
8092 return sys_dup (s);
8094 check_errno ();
8095 if (fd_info[s].flags & FILE_SOCKET)
8097 if (winsock_lib == NULL)
8099 errno = ENETDOWN;
8100 return -1;
8103 if (cmd == F_SETFL && options == O_NONBLOCK)
8105 unsigned long nblock = 1;
8106 int rc = pfn_ioctlsocket (SOCK_HANDLE (s), FIONBIO, &nblock);
8107 if (rc == SOCKET_ERROR)
8108 set_errno ();
8109 /* Keep track of the fact that we set this to non-blocking. */
8110 fd_info[s].flags |= FILE_NDELAY;
8111 return rc;
8113 else
8115 errno = EINVAL;
8116 return SOCKET_ERROR;
8119 else if ((fd_info[s].flags & (FILE_PIPE | FILE_WRITE))
8120 == (FILE_PIPE | FILE_WRITE))
8122 /* Force our writes to pipes be non-blocking. */
8123 if (cmd == F_SETFL && options == O_NONBLOCK)
8125 HANDLE h = (HANDLE)_get_osfhandle (s);
8126 DWORD pipe_mode = PIPE_NOWAIT;
8128 if (!SetNamedPipeHandleState (h, &pipe_mode, NULL, NULL))
8130 DebPrint (("SetNamedPipeHandleState: %lu\n", GetLastError ()));
8131 return SOCKET_ERROR;
8133 fd_info[s].flags |= FILE_NDELAY;
8134 return 0;
8136 else
8138 errno = EINVAL;
8139 return SOCKET_ERROR;
8142 errno = ENOTSOCK;
8143 return SOCKET_ERROR;
8147 /* Shadow main io functions: we need to handle pipes and sockets more
8148 intelligently. */
8151 sys_close (int fd)
8153 int rc;
8155 if (fd < 0)
8157 errno = EBADF;
8158 return -1;
8161 if (fd < MAXDESC && fd_info[fd].cp)
8163 child_process * cp = fd_info[fd].cp;
8165 fd_info[fd].cp = NULL;
8167 if (CHILD_ACTIVE (cp))
8169 /* if last descriptor to active child_process then cleanup */
8170 int i;
8171 for (i = 0; i < MAXDESC; i++)
8173 if (i == fd)
8174 continue;
8175 if (fd_info[i].cp == cp)
8176 break;
8178 if (i == MAXDESC)
8180 if (fd_info[fd].flags & FILE_SOCKET)
8182 if (winsock_lib == NULL) emacs_abort ();
8184 pfn_shutdown (SOCK_HANDLE (fd), 2);
8185 rc = pfn_closesocket (SOCK_HANDLE (fd));
8187 winsock_inuse--; /* count open sockets */
8189 /* If the process handle is NULL, it's either a socket
8190 or serial connection, or a subprocess that was
8191 already reaped by reap_subprocess, but whose
8192 resources were not yet freed, because its output was
8193 not fully read yet by the time it was reaped. (This
8194 usually happens with async subprocesses whose output
8195 is being read by Emacs.) Otherwise, this process was
8196 not reaped yet, so we set its FD to a negative value
8197 to make sure sys_select will eventually get to
8198 calling the SIGCHLD handler for it, which will then
8199 invoke waitpid and reap_subprocess. */
8200 if (cp->procinfo.hProcess == NULL)
8201 delete_child (cp);
8202 else
8203 cp->fd = -1;
8208 if (fd >= 0 && fd < MAXDESC)
8209 fd_info[fd].flags = 0;
8211 /* Note that sockets do not need special treatment here (at least on
8212 NT and Windows 95 using the standard tcp/ip stacks) - it appears that
8213 closesocket is equivalent to CloseHandle, which is to be expected
8214 because socket handles are fully fledged kernel handles. */
8215 rc = _close (fd);
8217 return rc;
8221 sys_dup (int fd)
8223 int new_fd;
8225 new_fd = _dup (fd);
8226 if (new_fd >= 0 && new_fd < MAXDESC)
8228 /* duplicate our internal info as well */
8229 fd_info[new_fd] = fd_info[fd];
8231 return new_fd;
8235 sys_dup2 (int src, int dst)
8237 int rc;
8239 if (dst < 0 || dst >= MAXDESC)
8241 errno = EBADF;
8242 return -1;
8245 /* MS _dup2 seems to have weird side effect when invoked with 2
8246 identical arguments: an attempt to fclose the corresponding stdio
8247 stream after that hangs (we do close standard streams in
8248 init_ntproc). Attempt to avoid that by not calling _dup2 that
8249 way: if SRC is valid, we know that dup2 should be a no-op, so do
8250 nothing and return DST. */
8251 if (src == dst)
8253 if ((HANDLE)_get_osfhandle (src) == INVALID_HANDLE_VALUE)
8255 errno = EBADF;
8256 return -1;
8258 return dst;
8261 /* Make sure we close the destination first if it's a pipe or socket. */
8262 if (fd_info[dst].flags != 0)
8263 sys_close (dst);
8265 rc = _dup2 (src, dst);
8266 if (rc == 0)
8268 /* Duplicate our internal info as well. */
8269 fd_info[dst] = fd_info[src];
8271 return rc == 0 ? dst : rc;
8275 pipe2 (int * phandles, int pipe2_flags)
8277 int rc;
8278 unsigned flags;
8279 unsigned pipe_size = 0;
8281 eassert (pipe2_flags == (O_BINARY | O_CLOEXEC));
8283 /* Allow Lisp to override the default buffer size of the pipe. */
8284 if (w32_pipe_buffer_size > 0 && w32_pipe_buffer_size < UINT_MAX)
8285 pipe_size = w32_pipe_buffer_size;
8287 /* make pipe handles non-inheritable; when we spawn a child, we
8288 replace the relevant handle with an inheritable one. Also put
8289 pipes into binary mode; we will do text mode translation ourselves
8290 if required. */
8291 rc = _pipe (phandles, pipe_size, _O_NOINHERIT | _O_BINARY);
8293 if (rc == 0)
8295 /* Protect against overflow, since Windows can open more handles than
8296 our fd_info array has room for. */
8297 if (phandles[0] >= MAXDESC || phandles[1] >= MAXDESC)
8299 _close (phandles[0]);
8300 _close (phandles[1]);
8301 errno = EMFILE;
8302 rc = -1;
8304 else
8306 flags = FILE_PIPE | FILE_READ | FILE_BINARY;
8307 fd_info[phandles[0]].flags = flags;
8309 flags = FILE_PIPE | FILE_WRITE | FILE_BINARY;
8310 fd_info[phandles[1]].flags = flags;
8314 return rc;
8317 /* Function to do blocking read of one byte, needed to implement
8318 select. It is only allowed on communication ports, sockets, or
8319 pipes. */
8321 _sys_read_ahead (int fd)
8323 child_process * cp;
8324 int rc;
8326 if (fd < 0 || fd >= MAXDESC)
8327 return STATUS_READ_ERROR;
8329 cp = fd_info[fd].cp;
8331 if (cp == NULL || cp->fd != fd || cp->status != STATUS_READ_READY)
8332 return STATUS_READ_ERROR;
8334 if ((fd_info[fd].flags & (FILE_PIPE | FILE_SERIAL | FILE_SOCKET)) == 0
8335 || (fd_info[fd].flags & FILE_READ) == 0)
8337 DebPrint (("_sys_read_ahead: internal error: fd %d is not a pipe, serial port, or socket!\n", fd));
8338 emacs_abort ();
8341 if ((fd_info[fd].flags & FILE_CONNECT) != 0)
8342 DebPrint (("_sys_read_ahead: read requested from fd %d, which waits for async connect!\n", fd));
8343 cp->status = STATUS_READ_IN_PROGRESS;
8345 if (fd_info[fd].flags & FILE_PIPE)
8347 rc = _read (fd, &cp->chr, sizeof (char));
8349 /* Give subprocess time to buffer some more output for us before
8350 reporting that input is available; we need this because Windows 95
8351 connects DOS programs to pipes by making the pipe appear to be
8352 the normal console stdout - as a result most DOS programs will
8353 write to stdout without buffering, ie. one character at a
8354 time. Even some W32 programs do this - "dir" in a command
8355 shell on NT is very slow if we don't do this. */
8356 if (rc > 0)
8358 int wait = w32_pipe_read_delay;
8360 if (wait > 0)
8361 Sleep (wait);
8362 else if (wait < 0)
8363 while (++wait <= 0)
8364 /* Yield remainder of our time slice, effectively giving a
8365 temporary priority boost to the child process. */
8366 Sleep (0);
8369 else if (fd_info[fd].flags & FILE_SERIAL)
8371 HANDLE hnd = fd_info[fd].hnd;
8372 OVERLAPPED *ovl = &fd_info[fd].cp->ovl_read;
8373 COMMTIMEOUTS ct;
8375 /* Configure timeouts for blocking read. */
8376 if (!GetCommTimeouts (hnd, &ct))
8378 cp->status = STATUS_READ_ERROR;
8379 return STATUS_READ_ERROR;
8381 ct.ReadIntervalTimeout = 0;
8382 ct.ReadTotalTimeoutMultiplier = 0;
8383 ct.ReadTotalTimeoutConstant = 0;
8384 if (!SetCommTimeouts (hnd, &ct))
8386 cp->status = STATUS_READ_ERROR;
8387 return STATUS_READ_ERROR;
8390 if (!ReadFile (hnd, &cp->chr, sizeof (char), (DWORD*) &rc, ovl))
8392 if (GetLastError () != ERROR_IO_PENDING)
8394 cp->status = STATUS_READ_ERROR;
8395 return STATUS_READ_ERROR;
8397 if (!GetOverlappedResult (hnd, ovl, (DWORD*) &rc, TRUE))
8399 cp->status = STATUS_READ_ERROR;
8400 return STATUS_READ_ERROR;
8404 else if (fd_info[fd].flags & FILE_SOCKET)
8406 unsigned long nblock = 0;
8407 /* We always want this to block, so temporarily disable NDELAY. */
8408 if (fd_info[fd].flags & FILE_NDELAY)
8409 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONBIO, &nblock);
8411 rc = pfn_recv (SOCK_HANDLE (fd), &cp->chr, sizeof (char), 0);
8413 if (fd_info[fd].flags & FILE_NDELAY)
8415 nblock = 1;
8416 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONBIO, &nblock);
8420 if (rc == sizeof (char))
8421 cp->status = STATUS_READ_SUCCEEDED;
8422 else
8423 cp->status = STATUS_READ_FAILED;
8425 return cp->status;
8429 _sys_wait_accept (int fd)
8431 HANDLE hEv;
8432 child_process * cp;
8433 int rc;
8435 if (fd < 0 || fd >= MAXDESC)
8436 return STATUS_READ_ERROR;
8438 cp = fd_info[fd].cp;
8440 if (cp == NULL || cp->fd != fd || cp->status != STATUS_READ_READY)
8441 return STATUS_READ_ERROR;
8443 cp->status = STATUS_READ_FAILED;
8445 hEv = pfn_WSACreateEvent ();
8446 rc = pfn_WSAEventSelect (SOCK_HANDLE (fd), hEv, FD_ACCEPT);
8447 if (rc != SOCKET_ERROR)
8449 do {
8450 rc = WaitForSingleObject (hEv, 500);
8451 Sleep (5);
8452 } while (rc == WAIT_TIMEOUT
8453 && cp->status != STATUS_READ_ERROR
8454 && cp->char_avail);
8455 pfn_WSAEventSelect (SOCK_HANDLE (fd), NULL, 0);
8456 if (rc == WAIT_OBJECT_0)
8457 cp->status = STATUS_READ_SUCCEEDED;
8459 pfn_WSACloseEvent (hEv);
8461 return cp->status;
8465 _sys_wait_connect (int fd)
8467 HANDLE hEv;
8468 child_process * cp;
8469 int rc;
8471 if (fd < 0 || fd >= MAXDESC)
8472 return STATUS_READ_ERROR;
8474 cp = fd_info[fd].cp;
8475 if (cp == NULL || cp->fd != fd || cp->status != STATUS_READ_READY)
8476 return STATUS_READ_ERROR;
8478 cp->status = STATUS_READ_FAILED;
8480 hEv = pfn_WSACreateEvent ();
8481 rc = pfn_WSAEventSelect (SOCK_HANDLE (fd), hEv, FD_CONNECT);
8482 if (rc != SOCKET_ERROR)
8484 do {
8485 rc = WaitForSingleObject (hEv, 500);
8486 Sleep (5);
8487 } while (rc == WAIT_TIMEOUT
8488 && cp->status != STATUS_READ_ERROR
8489 && cp->char_avail);
8490 if (rc == WAIT_OBJECT_0)
8492 /* We've got an event, but it could be a successful
8493 connection, or it could be a failure. Find out
8494 which one is it. */
8495 WSANETWORKEVENTS events;
8497 pfn_WSAEnumNetworkEvents (SOCK_HANDLE (fd), hEv, &events);
8498 if ((events.lNetworkEvents & FD_CONNECT) != 0
8499 && events.iErrorCode[FD_CONNECT_BIT])
8501 cp->status = STATUS_CONNECT_FAILED;
8502 cp->errcode = events.iErrorCode[FD_CONNECT_BIT];
8504 else
8506 cp->status = STATUS_READ_SUCCEEDED;
8507 cp->errcode = 0;
8510 pfn_WSAEventSelect (SOCK_HANDLE (fd), NULL, 0);
8512 else
8513 pfn_WSACloseEvent (hEv);
8515 return cp->status;
8519 sys_read (int fd, char * buffer, unsigned int count)
8521 int nchars;
8522 int to_read;
8523 DWORD waiting;
8524 char * orig_buffer = buffer;
8526 if (fd < 0)
8528 errno = EBADF;
8529 return -1;
8532 if (fd < MAXDESC && fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET | FILE_SERIAL))
8534 child_process *cp = fd_info[fd].cp;
8536 if ((fd_info[fd].flags & FILE_READ) == 0)
8538 errno = EBADF;
8539 return -1;
8542 nchars = 0;
8544 /* re-read CR carried over from last read */
8545 if (fd_info[fd].flags & FILE_LAST_CR)
8547 if (fd_info[fd].flags & FILE_BINARY) emacs_abort ();
8548 *buffer++ = 0x0d;
8549 count--;
8550 nchars++;
8551 fd_info[fd].flags &= ~FILE_LAST_CR;
8554 /* presence of a child_process structure means we are operating in
8555 non-blocking mode - otherwise we just call _read directly.
8556 Note that the child_process structure might be missing because
8557 reap_subprocess has been called; in this case the pipe is
8558 already broken, so calling _read on it is okay. */
8559 if (cp)
8561 int current_status = cp->status;
8563 switch (current_status)
8565 case STATUS_READ_FAILED:
8566 case STATUS_READ_ERROR:
8567 /* report normal EOF if nothing in buffer */
8568 if (nchars <= 0)
8569 fd_info[fd].flags |= FILE_AT_EOF;
8570 return nchars;
8572 case STATUS_READ_READY:
8573 case STATUS_READ_IN_PROGRESS:
8574 #if 0
8575 /* This happens all the time during GnuTLS handshake
8576 with the remote, evidently because GnuTLS waits for
8577 the read to complete by retrying the read operation
8578 upon EAGAIN. So I'm disabling the DebPrint to avoid
8579 wasting cycles on something that is not a real
8580 problem. Enable if you need to debug something that
8581 bumps into this. */
8582 DebPrint (("sys_read called when read is in progress %d\n",
8583 current_status));
8584 #endif
8585 errno = EWOULDBLOCK;
8586 return -1;
8588 case STATUS_READ_SUCCEEDED:
8589 /* consume read-ahead char */
8590 *buffer++ = cp->chr;
8591 count--;
8592 nchars++;
8593 cp->status = STATUS_READ_ACKNOWLEDGED;
8594 ResetEvent (cp->char_avail);
8596 case STATUS_READ_ACKNOWLEDGED:
8597 case STATUS_CONNECT_FAILED:
8598 break;
8600 default:
8601 DebPrint (("sys_read: bad status %d\n", current_status));
8602 errno = EBADF;
8603 return -1;
8606 if (fd_info[fd].flags & FILE_PIPE)
8608 PeekNamedPipe ((HANDLE) _get_osfhandle (fd), NULL, 0, NULL, &waiting, NULL);
8609 to_read = min (waiting, (DWORD) count);
8611 if (to_read > 0)
8612 nchars += _read (fd, buffer, to_read);
8614 else if (fd_info[fd].flags & FILE_SERIAL)
8616 HANDLE hnd = fd_info[fd].hnd;
8617 OVERLAPPED *ovl = &fd_info[fd].cp->ovl_read;
8618 int rc = 0;
8619 COMMTIMEOUTS ct;
8621 if (count > 0)
8623 /* Configure timeouts for non-blocking read. */
8624 if (!GetCommTimeouts (hnd, &ct))
8626 errno = EIO;
8627 return -1;
8629 ct.ReadIntervalTimeout = MAXDWORD;
8630 ct.ReadTotalTimeoutMultiplier = 0;
8631 ct.ReadTotalTimeoutConstant = 0;
8632 if (!SetCommTimeouts (hnd, &ct))
8634 errno = EIO;
8635 return -1;
8638 if (!ResetEvent (ovl->hEvent))
8640 errno = EIO;
8641 return -1;
8643 if (!ReadFile (hnd, buffer, count, (DWORD*) &rc, ovl))
8645 if (GetLastError () != ERROR_IO_PENDING)
8647 errno = EIO;
8648 return -1;
8650 if (!GetOverlappedResult (hnd, ovl, (DWORD*) &rc, TRUE))
8652 errno = EIO;
8653 return -1;
8656 nchars += rc;
8659 else /* FILE_SOCKET */
8661 if (winsock_lib == NULL) emacs_abort ();
8663 /* When a non-blocking 'connect' call fails,
8664 wait_reading_process_output detects this by calling
8665 'getpeername', and then attempts to obtain the connection
8666 error code by trying to read 1 byte from the socket. If
8667 we try to serve that read by calling 'recv' below, the
8668 error we get is a generic WSAENOTCONN, not the actual
8669 connection error. So instead, we use the actual error
8670 code stashed by '_sys_wait_connect' in cp->errcode.
8671 Alternatively, we could have used 'getsockopt', like on
8672 GNU/Linux, but: (a) I have no idea whether the winsock
8673 version could hang, as it does "on some systems" (see the
8674 comment in process.c); and (b) 'getsockopt' on Windows is
8675 documented to clear the socket error for the entire
8676 process, which I'm not sure is TRT; FIXME. */
8677 if (current_status == STATUS_CONNECT_FAILED
8678 && (fd_info[fd].flags & FILE_CONNECT) != 0
8679 && cp->errcode != 0)
8681 pfn_WSASetLastError (cp->errcode);
8682 set_errno ();
8683 return -1;
8685 /* Do the equivalent of a non-blocking read. */
8686 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONREAD, &waiting);
8687 if (waiting == 0 && nchars == 0)
8689 errno = EWOULDBLOCK;
8690 return -1;
8693 if (waiting)
8695 /* always use binary mode for sockets */
8696 int res = pfn_recv (SOCK_HANDLE (fd), buffer, count, 0);
8697 if (res == SOCKET_ERROR)
8699 set_errno ();
8700 DebPrint (("sys_read.recv failed with error %d on socket %ld\n",
8701 errno, SOCK_HANDLE (fd)));
8702 return -1;
8704 nchars += res;
8708 else
8710 int nread = _read (fd, buffer, count);
8711 if (nread >= 0)
8712 nchars += nread;
8713 else if (nchars == 0)
8714 nchars = nread;
8717 if (nchars <= 0)
8718 fd_info[fd].flags |= FILE_AT_EOF;
8719 /* Perform text mode translation if required. */
8720 else if ((fd_info[fd].flags & FILE_BINARY) == 0)
8722 nchars = crlf_to_lf (nchars, orig_buffer);
8723 /* If buffer contains only CR, return that. To be absolutely
8724 sure we should attempt to read the next char, but in
8725 practice a CR to be followed by LF would not appear by
8726 itself in the buffer. */
8727 if (nchars > 1 && orig_buffer[nchars - 1] == 0x0d)
8729 fd_info[fd].flags |= FILE_LAST_CR;
8730 nchars--;
8734 else
8735 nchars = _read (fd, buffer, count);
8737 return nchars;
8740 /* From w32xfns.c */
8741 extern HANDLE interrupt_handle;
8744 sys_write (int fd, const void * buffer, unsigned int count)
8746 int nchars;
8747 USE_SAFE_ALLOCA;
8749 if (fd < 0)
8751 errno = EBADF;
8752 return -1;
8755 if (fd < MAXDESC && fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET | FILE_SERIAL))
8757 if ((fd_info[fd].flags & FILE_WRITE) == 0)
8759 errno = EBADF;
8760 return -1;
8763 /* Perform text mode translation if required. */
8764 if ((fd_info[fd].flags & FILE_BINARY) == 0)
8766 char * tmpbuf;
8767 const unsigned char * src = buffer;
8768 unsigned char * dst;
8769 int nbytes = count;
8771 SAFE_NALLOCA (tmpbuf, 2, count);
8772 dst = (unsigned char *)tmpbuf;
8774 while (1)
8776 unsigned char *next;
8777 /* Copy next line or remaining bytes. */
8778 next = _memccpy (dst, src, '\n', nbytes);
8779 if (next)
8781 /* Copied one line ending with '\n'. */
8782 int copied = next - dst;
8783 nbytes -= copied;
8784 src += copied;
8785 /* Insert '\r' before '\n'. */
8786 next[-1] = '\r';
8787 next[0] = '\n';
8788 dst = next + 1;
8789 count++;
8791 else
8792 /* Copied remaining partial line -> now finished. */
8793 break;
8795 buffer = tmpbuf;
8799 if (fd < MAXDESC && fd_info[fd].flags & FILE_SERIAL)
8801 HANDLE hnd = (HANDLE) _get_osfhandle (fd);
8802 OVERLAPPED *ovl = &fd_info[fd].cp->ovl_write;
8803 HANDLE wait_hnd[2] = { interrupt_handle, ovl->hEvent };
8804 DWORD active = 0;
8806 /* This is async (a.k.a. "overlapped") I/O, so the return value
8807 of FALSE from WriteFile means either an error or the output
8808 will be completed asynchronously (ERROR_IO_PENDING). */
8809 if (!WriteFile (hnd, buffer, count, (DWORD*) &nchars, ovl))
8811 if (GetLastError () != ERROR_IO_PENDING)
8813 errno = EIO;
8814 nchars = -1;
8816 else
8818 /* Wait for the write to complete, and watch C-g while
8819 at that. */
8820 if (detect_input_pending ())
8821 active = MsgWaitForMultipleObjects (2, wait_hnd, FALSE,
8822 INFINITE, QS_ALLINPUT);
8823 else
8824 active = WaitForMultipleObjects (2, wait_hnd, FALSE, INFINITE);
8825 switch (active)
8827 case WAIT_OBJECT_0:
8828 /* User pressed C-g, cancel write, then leave.
8829 Don't bother cleaning up as we may only get stuck
8830 in buggy drivers. */
8831 PurgeComm (hnd, PURGE_TXABORT | PURGE_TXCLEAR);
8832 CancelIo (hnd);
8833 errno = EIO; /* Why not EINTR? */
8834 nchars = -1;
8835 break;
8836 case WAIT_OBJECT_0 + 1:
8837 if (!GetOverlappedResult (hnd, ovl, (DWORD*) &nchars, TRUE))
8839 errno = EIO;
8840 nchars = -1;
8842 break;
8847 else if (fd < MAXDESC && fd_info[fd].flags & FILE_SOCKET)
8849 unsigned long nblock = 0;
8850 if (winsock_lib == NULL) emacs_abort ();
8852 child_process *cp = fd_info[fd].cp;
8854 /* If this is a non-blocking socket whose connection is in
8855 progress or terminated with an error already, return the
8856 proper error code to the caller. */
8857 if (cp != NULL && (fd_info[fd].flags & FILE_CONNECT) != 0)
8859 /* In case connection is in progress, ENOTCONN that would
8860 result from calling pfn_send is not what callers expect. */
8861 if (cp->status != STATUS_CONNECT_FAILED)
8863 errno = EWOULDBLOCK;
8864 return -1;
8866 /* In case connection failed, use the actual error code
8867 stashed by '_sys_wait_connect' in cp->errcode. */
8868 else if (cp->errcode != 0)
8870 pfn_WSASetLastError (cp->errcode);
8871 set_errno ();
8872 return -1;
8876 /* TODO: implement select() properly so non-blocking I/O works. */
8877 /* For now, make sure the write blocks. */
8878 if (fd_info[fd].flags & FILE_NDELAY)
8879 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONBIO, &nblock);
8881 nchars = pfn_send (SOCK_HANDLE (fd), buffer, count, 0);
8883 if (nchars == SOCKET_ERROR)
8885 set_errno ();
8886 DebPrint (("sys_write.send failed with error %d on socket %ld\n",
8887 pfn_WSAGetLastError (), SOCK_HANDLE (fd)));
8890 /* Set the socket back to non-blocking if it was before,
8891 for other operations that support it. */
8892 if (fd_info[fd].flags & FILE_NDELAY)
8894 nblock = 1;
8895 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONBIO, &nblock);
8898 else
8900 /* Some networked filesystems don't like too large writes, so
8901 break them into smaller chunks. See the Comments section of
8902 the MSDN documentation of WriteFile for details behind the
8903 choice of the value of CHUNK below. See also the thread
8904 http://thread.gmane.org/gmane.comp.version-control.git/145294
8905 in the git mailing list. */
8906 const unsigned char *p = buffer;
8907 const bool is_pipe = (fd < MAXDESC
8908 && ((fd_info[fd].flags & (FILE_PIPE | FILE_NDELAY))
8909 == (FILE_PIPE | FILE_NDELAY)));
8910 /* Some programs, notably Node.js's node.exe, seem to never
8911 completely empty the pipe, so writing more than the size of
8912 the pipe's buffer always returns ENOSPC, and we loop forever
8913 between send_process and here. As a workaround, write no
8914 more than the pipe's buffer can hold. */
8915 DWORD pipe_buffer_size;
8916 if (is_pipe)
8918 if (!GetNamedPipeInfo ((HANDLE)_get_osfhandle (fd),
8919 NULL, &pipe_buffer_size, NULL, NULL))
8921 DebPrint (("GetNamedPipeInfo: error %u\n", GetLastError ()));
8922 pipe_buffer_size = 4096;
8925 const unsigned chunk = is_pipe ? pipe_buffer_size : 30 * 1024 * 1024;
8927 nchars = 0;
8928 errno = 0;
8929 while (count > 0)
8931 unsigned this_chunk = count < chunk ? count : chunk;
8932 int n = _write (fd, p, this_chunk);
8934 if (n > 0)
8935 nchars += n;
8936 if (n < 0)
8938 /* When there's no buffer space in a pipe that is in the
8939 non-blocking mode, _write returns ENOSPC. We return
8940 EAGAIN instead, which should trigger the logic in
8941 send_process that enters waiting loop and calls
8942 wait_reading_process_output to allow process input to
8943 be accepted during the wait. Those calls to
8944 wait_reading_process_output allow sys_select to
8945 notice when process input becomes available, thus
8946 avoiding deadlock whereby each side of the pipe is
8947 blocked on write, waiting for the other party to read
8948 its end of the pipe. */
8949 if (errno == ENOSPC && is_pipe)
8950 errno = EAGAIN;
8951 if (nchars == 0)
8952 nchars = -1;
8953 break;
8955 else if (n < this_chunk)
8956 break;
8957 count -= n;
8958 p += n;
8962 SAFE_FREE ();
8963 return nchars;
8967 /* Emulation of SIOCGIFCONF and getifaddrs, see process.c. */
8969 /* Return information about network interface IFNAME, or about all
8970 interfaces (if IFNAME is nil). */
8971 static Lisp_Object
8972 network_interface_get_info (Lisp_Object ifname)
8974 ULONG ainfo_len = sizeof (IP_ADAPTER_INFO);
8975 IP_ADAPTER_INFO *adapter, *ainfo = xmalloc (ainfo_len);
8976 DWORD retval = get_adapters_info (ainfo, &ainfo_len);
8977 Lisp_Object res = Qnil;
8979 if (retval == ERROR_BUFFER_OVERFLOW)
8981 ainfo = xrealloc (ainfo, ainfo_len);
8982 retval = get_adapters_info (ainfo, &ainfo_len);
8985 if (retval == ERROR_SUCCESS)
8987 int eth_count = 0, tr_count = 0, fddi_count = 0, ppp_count = 0;
8988 int sl_count = 0, wlan_count = 0, lo_count = 0, ifx_count = 0;
8989 int if_num;
8990 struct sockaddr_in sa;
8992 /* For the below, we need some winsock functions, so make sure
8993 the winsock DLL is loaded. If we cannot successfully load
8994 it, they will have no use of the information we provide,
8995 anyway, so punt. */
8996 if (!winsock_lib && !init_winsock (1))
8997 goto done;
8999 for (adapter = ainfo; adapter; adapter = adapter->Next)
9001 char namebuf[MAX_ADAPTER_NAME_LENGTH + 4];
9002 u_long ip_addr;
9003 /* Present Unix-compatible interface names, instead of the
9004 Windows names, which are really GUIDs not readable by
9005 humans. */
9006 static const char *ifmt[] = {
9007 "eth%d", "tr%d", "fddi%d", "ppp%d", "sl%d", "wlan%d",
9008 "lo", "ifx%d"
9010 enum {
9011 NONE = -1,
9012 ETHERNET = 0,
9013 TOKENRING = 1,
9014 FDDI = 2,
9015 PPP = 3,
9016 SLIP = 4,
9017 WLAN = 5,
9018 LOOPBACK = 6,
9019 OTHER_IF = 7
9020 } ifmt_idx;
9022 switch (adapter->Type)
9024 case MIB_IF_TYPE_ETHERNET:
9025 /* Windows before Vista reports wireless adapters as
9026 Ethernet. Work around by looking at the Description
9027 string. */
9028 if (strstr (adapter->Description, "Wireless "))
9030 ifmt_idx = WLAN;
9031 if_num = wlan_count++;
9033 else
9035 ifmt_idx = ETHERNET;
9036 if_num = eth_count++;
9038 break;
9039 case MIB_IF_TYPE_TOKENRING:
9040 ifmt_idx = TOKENRING;
9041 if_num = tr_count++;
9042 break;
9043 case MIB_IF_TYPE_FDDI:
9044 ifmt_idx = FDDI;
9045 if_num = fddi_count++;
9046 break;
9047 case MIB_IF_TYPE_PPP:
9048 ifmt_idx = PPP;
9049 if_num = ppp_count++;
9050 break;
9051 case MIB_IF_TYPE_SLIP:
9052 ifmt_idx = SLIP;
9053 if_num = sl_count++;
9054 break;
9055 case IF_TYPE_IEEE80211:
9056 ifmt_idx = WLAN;
9057 if_num = wlan_count++;
9058 break;
9059 case MIB_IF_TYPE_LOOPBACK:
9060 if (lo_count < 0)
9062 ifmt_idx = LOOPBACK;
9063 if_num = lo_count++;
9065 else
9066 ifmt_idx = NONE;
9067 break;
9068 default:
9069 ifmt_idx = OTHER_IF;
9070 if_num = ifx_count++;
9071 break;
9073 if (ifmt_idx == NONE)
9074 continue;
9075 sprintf (namebuf, ifmt[ifmt_idx], if_num);
9077 sa.sin_family = AF_INET;
9078 ip_addr = sys_inet_addr (adapter->IpAddressList.IpAddress.String);
9079 if (ip_addr == INADDR_NONE)
9081 /* Bogus address, skip this interface. */
9082 continue;
9084 sa.sin_addr.s_addr = ip_addr;
9085 sa.sin_port = 0;
9086 if (NILP (ifname))
9087 res = Fcons (Fcons (build_string (namebuf),
9088 conv_sockaddr_to_lisp ((struct sockaddr*) &sa,
9089 sizeof (struct sockaddr))),
9090 res);
9091 else if (strcmp (namebuf, SSDATA (ifname)) == 0)
9093 Lisp_Object hwaddr = Fmake_vector (make_number (6), Qnil);
9094 register struct Lisp_Vector *p = XVECTOR (hwaddr);
9095 Lisp_Object flags = Qnil;
9096 int n;
9097 u_long net_mask;
9099 /* Flags. We guess most of them by type, since the
9100 Windows flags are different and hard to get by. */
9101 flags = Fcons (intern ("up"), flags);
9102 if (ifmt_idx == ETHERNET || ifmt_idx == WLAN)
9104 flags = Fcons (intern ("broadcast"), flags);
9105 flags = Fcons (intern ("multicast"), flags);
9107 flags = Fcons (intern ("running"), flags);
9108 if (ifmt_idx == PPP)
9110 flags = Fcons (intern ("pointopoint"), flags);
9111 flags = Fcons (intern ("noarp"), flags);
9113 if (adapter->HaveWins)
9114 flags = Fcons (intern ("WINS"), flags);
9115 if (adapter->DhcpEnabled)
9116 flags = Fcons (intern ("dynamic"), flags);
9118 res = Fcons (flags, res);
9120 /* Hardware address and its family. */
9121 for (n = 0; n < adapter->AddressLength; n++)
9122 p->contents[n] = make_number ((int) adapter->Address[n]);
9123 /* Windows does not support AF_LINK or AF_PACKET family
9124 of addresses. Use an arbitrary family number that is
9125 identical to what GNU/Linux returns. */
9126 res = Fcons (Fcons (make_number (1), hwaddr), res);
9128 /* Network mask. */
9129 sa.sin_family = AF_INET;
9130 net_mask = sys_inet_addr (adapter->IpAddressList.IpMask.String);
9131 if (net_mask != INADDR_NONE)
9133 sa.sin_addr.s_addr = net_mask;
9134 sa.sin_port = 0;
9135 res = Fcons (conv_sockaddr_to_lisp ((struct sockaddr *) &sa,
9136 sizeof (struct sockaddr)),
9137 res);
9139 else
9140 res = Fcons (Qnil, res);
9142 sa.sin_family = AF_INET;
9143 if (ip_addr != INADDR_NONE)
9145 /* Broadcast address is only reported by
9146 GetAdaptersAddresses, which is of limited
9147 availability. Generate it on our own. */
9148 u_long bcast_addr = (ip_addr & net_mask) | ~net_mask;
9150 sa.sin_addr.s_addr = bcast_addr;
9151 sa.sin_port = 0;
9152 res = Fcons (conv_sockaddr_to_lisp ((struct sockaddr *) &sa,
9153 sizeof (struct sockaddr)),
9154 res);
9156 /* IP address. */
9157 sa.sin_addr.s_addr = ip_addr;
9158 sa.sin_port = 0;
9159 res = Fcons (conv_sockaddr_to_lisp ((struct sockaddr *) &sa,
9160 sizeof (struct sockaddr)),
9161 res);
9163 else
9164 res = Fcons (Qnil, Fcons (Qnil, res));
9167 /* GetAdaptersInfo is documented to not report loopback
9168 interfaces, so we generate one out of thin air. */
9169 if (!lo_count)
9171 sa.sin_family = AF_INET;
9172 sa.sin_port = 0;
9173 if (NILP (ifname))
9175 sa.sin_addr.s_addr = sys_inet_addr ("127.0.0.1");
9176 res = Fcons (Fcons (build_string ("lo"),
9177 conv_sockaddr_to_lisp ((struct sockaddr*) &sa,
9178 sizeof (struct sockaddr))),
9179 res);
9181 else if (strcmp (SSDATA (ifname), "lo") == 0)
9183 res = Fcons (Fcons (intern ("running"),
9184 Fcons (intern ("loopback"),
9185 Fcons (intern ("up"), Qnil))), Qnil);
9186 /* 772 is what 3 different GNU/Linux systems report for
9187 the loopback interface. */
9188 res = Fcons (Fcons (make_number (772),
9189 Fmake_vector (make_number (6),
9190 make_number (0))),
9191 res);
9192 sa.sin_addr.s_addr = sys_inet_addr ("255.0.0.0");
9193 res = Fcons (conv_sockaddr_to_lisp ((struct sockaddr *) &sa,
9194 sizeof (struct sockaddr)),
9195 res);
9196 sa.sin_addr.s_addr = sys_inet_addr ("0.0.0.0");
9197 res = Fcons (conv_sockaddr_to_lisp ((struct sockaddr *) &sa,
9198 sizeof (struct sockaddr)),
9199 res);
9200 sa.sin_addr.s_addr = sys_inet_addr ("127.0.0.1");
9201 res = Fcons (conv_sockaddr_to_lisp ((struct sockaddr *) &sa,
9202 sizeof (struct sockaddr)),
9203 res);
9209 done:
9210 xfree (ainfo);
9211 return res;
9214 Lisp_Object
9215 network_interface_list (void)
9217 return network_interface_get_info (Qnil);
9220 Lisp_Object
9221 network_interface_info (Lisp_Object ifname)
9223 CHECK_STRING (ifname);
9224 return network_interface_get_info (ifname);
9228 /* The Windows CRT functions are "optimized for speed", so they don't
9229 check for timezone and DST changes if they were last called less
9230 than 1 minute ago (see http://support.microsoft.com/kb/821231). So
9231 all Emacs features that repeatedly call time functions (e.g.,
9232 display-time) are in real danger of missing timezone and DST
9233 changes. Calling tzset before each localtime call fixes that. */
9234 struct tm *
9235 sys_localtime (const time_t *t)
9237 tzset ();
9238 return localtime (t);
9243 /* Try loading LIBRARY_ID from the file(s) specified in
9244 Vdynamic_library_alist. If the library is loaded successfully,
9245 return the handle of the DLL, and record the filename in the
9246 property :loaded-from of LIBRARY_ID. If the library could not be
9247 found, or when it was already loaded (because the handle is not
9248 recorded anywhere, and so is lost after use), return NULL.
9250 We could also save the handle in :loaded-from, but currently
9251 there's no use case for it. */
9252 HMODULE
9253 w32_delayed_load (Lisp_Object library_id)
9255 HMODULE dll_handle = NULL;
9257 CHECK_SYMBOL (library_id);
9259 if (CONSP (Vdynamic_library_alist)
9260 && NILP (Fassq (library_id, Vlibrary_cache)))
9262 Lisp_Object found = Qnil;
9263 Lisp_Object dlls = Fassq (library_id, Vdynamic_library_alist);
9265 if (CONSP (dlls))
9266 for (dlls = XCDR (dlls); CONSP (dlls); dlls = XCDR (dlls))
9268 Lisp_Object dll = XCAR (dlls);
9269 char name[MAX_UTF8_PATH];
9270 DWORD res = -1;
9272 CHECK_STRING (dll);
9273 dll = ENCODE_FILE (dll);
9274 if (w32_unicode_filenames)
9276 wchar_t name_w[MAX_PATH];
9278 filename_to_utf16 (SSDATA (dll), name_w);
9279 dll_handle = LoadLibraryW (name_w);
9280 if (dll_handle)
9282 res = GetModuleFileNameW (dll_handle, name_w,
9283 sizeof (name_w));
9284 if (res > 0)
9285 filename_from_utf16 (name_w, name);
9288 else
9290 char name_a[MAX_PATH];
9292 filename_to_ansi (SSDATA (dll), name_a);
9293 dll_handle = LoadLibraryA (name_a);
9294 if (dll_handle)
9296 res = GetModuleFileNameA (dll_handle, name_a,
9297 sizeof (name_a));
9298 if (res > 0)
9299 filename_from_ansi (name_a, name);
9302 if (dll_handle)
9304 ptrdiff_t len = strlen (name);
9305 found = Fcons (dll,
9306 (res > 0)
9307 /* Possibly truncated */
9308 ? make_specified_string (name, -1, len, 1)
9309 : Qnil);
9310 /* This prevents thread start and end notifications
9311 from being sent to the DLL, for every thread we
9312 start. We don't need those notifications because
9313 threads we create never use any of these DLLs, only
9314 the main thread uses them. This is supposed to
9315 speed up thread creation. */
9316 DisableThreadLibraryCalls (dll_handle);
9317 break;
9321 Fput (library_id, QCloaded_from, found);
9324 return dll_handle;
9328 void
9329 check_windows_init_file (void)
9331 /* A common indication that Emacs is not installed properly is when
9332 it cannot find the Windows installation file. If this file does
9333 not exist in the expected place, tell the user. */
9335 if (!noninteractive && !inhibit_window_system
9336 /* Vload_path is not yet initialized when we are loading
9337 loadup.el. */
9338 && NILP (Vpurify_flag))
9340 Lisp_Object init_file;
9341 int fd;
9343 /* Implementation note: this function runs early during Emacs
9344 startup, before startup.el is run. So Vload_path is still in
9345 its initial unibyte form, but it holds UTF-8 encoded file
9346 names, since init_callproc was already called. So we do not
9347 need to ENCODE_FILE here, but we do need to convert the file
9348 names from UTF-8 to ANSI. */
9349 init_file = build_string ("term/w32-win");
9350 fd = openp (Vload_path, init_file, Fget_load_suffixes (), NULL, Qnil, 0);
9351 if (fd < 0)
9353 Lisp_Object load_path_print = Fprin1_to_string (Vload_path, Qnil);
9354 char *init_file_name = SSDATA (init_file);
9355 char *load_path = SSDATA (load_path_print);
9356 char *buffer = alloca (1024
9357 + strlen (init_file_name)
9358 + strlen (load_path));
9359 char *msg = buffer;
9360 int needed;
9362 sprintf (buffer,
9363 "The Emacs Windows initialization file \"%s.el\" "
9364 "could not be found in your Emacs installation. "
9365 "Emacs checked the following directories for this file:\n"
9366 "\n%s\n\n"
9367 "When Emacs cannot find this file, it usually means that it "
9368 "was not installed properly, or its distribution file was "
9369 "not unpacked properly.\nSee the README.W32 file in the "
9370 "top-level Emacs directory for more information.",
9371 init_file_name, load_path);
9372 needed = pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags,
9373 buffer, -1, NULL, 0);
9374 if (needed > 0)
9376 wchar_t *msg_w = alloca ((needed + 1) * sizeof (wchar_t));
9378 pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags, buffer,
9379 -1, msg_w, needed);
9380 needed = pWideCharToMultiByte (CP_ACP, 0, msg_w, -1,
9381 NULL, 0, NULL, NULL);
9382 if (needed > 0)
9384 char *msg_a = alloca (needed + 1);
9386 pWideCharToMultiByte (CP_ACP, 0, msg_w, -1, msg_a, needed,
9387 NULL, NULL);
9388 msg = msg_a;
9391 MessageBox (NULL,
9392 msg,
9393 "Emacs Abort Dialog",
9394 MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL);
9395 /* Use the low-level system abort. */
9396 abort ();
9398 else
9400 _close (fd);
9405 void
9406 term_ntproc (int ignored)
9408 (void)ignored;
9410 term_timers ();
9412 /* shutdown the socket interface if necessary */
9413 term_winsock ();
9415 term_w32select ();
9418 void
9419 init_ntproc (int dumping)
9421 sigset_t initial_mask = 0;
9423 /* Initialize the socket interface now if available and requested by
9424 the user by defining PRELOAD_WINSOCK; otherwise loading will be
9425 delayed until open-network-stream is called (w32-has-winsock can
9426 also be used to dynamically load or reload winsock).
9428 Conveniently, init_environment is called before us, so
9429 PRELOAD_WINSOCK can be set in the registry. */
9431 /* Always initialize this correctly. */
9432 winsock_lib = NULL;
9434 if (getenv ("PRELOAD_WINSOCK") != NULL)
9435 init_winsock (TRUE);
9437 /* Initial preparation for subprocess support: replace our standard
9438 handles with non-inheritable versions. */
9440 HANDLE parent;
9441 HANDLE stdin_save = INVALID_HANDLE_VALUE;
9442 HANDLE stdout_save = INVALID_HANDLE_VALUE;
9443 HANDLE stderr_save = INVALID_HANDLE_VALUE;
9445 parent = GetCurrentProcess ();
9447 /* ignore errors when duplicating and closing; typically the
9448 handles will be invalid when running as a gui program. */
9449 DuplicateHandle (parent,
9450 GetStdHandle (STD_INPUT_HANDLE),
9451 parent,
9452 &stdin_save,
9454 FALSE,
9455 DUPLICATE_SAME_ACCESS);
9457 DuplicateHandle (parent,
9458 GetStdHandle (STD_OUTPUT_HANDLE),
9459 parent,
9460 &stdout_save,
9462 FALSE,
9463 DUPLICATE_SAME_ACCESS);
9465 DuplicateHandle (parent,
9466 GetStdHandle (STD_ERROR_HANDLE),
9467 parent,
9468 &stderr_save,
9470 FALSE,
9471 DUPLICATE_SAME_ACCESS);
9473 fclose (stdin);
9474 fclose (stdout);
9475 fclose (stderr);
9477 if (stdin_save != INVALID_HANDLE_VALUE)
9478 _open_osfhandle ((intptr_t) stdin_save, O_TEXT);
9479 else
9480 _open ("nul", O_TEXT | O_NOINHERIT | O_RDONLY);
9481 _fdopen (0, "r");
9483 if (stdout_save != INVALID_HANDLE_VALUE)
9484 _open_osfhandle ((intptr_t) stdout_save, O_TEXT);
9485 else
9486 _open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY);
9487 _fdopen (1, "w");
9489 if (stderr_save != INVALID_HANDLE_VALUE)
9490 _open_osfhandle ((intptr_t) stderr_save, O_TEXT);
9491 else
9492 _open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY);
9493 _fdopen (2, "w");
9496 /* unfortunately, atexit depends on implementation of malloc */
9497 /* atexit (term_ntproc); */
9498 if (!dumping)
9500 /* Make sure we start with all signals unblocked. */
9501 sigprocmask (SIG_SETMASK, &initial_mask, NULL);
9502 signal (SIGABRT, term_ntproc);
9504 init_timers ();
9506 /* determine which drives are fixed, for GetCachedVolumeInformation */
9508 /* GetDriveType must have trailing backslash. */
9509 char drive[] = "A:\\";
9511 /* Loop over all possible drive letters */
9512 while (*drive <= 'Z')
9514 /* Record if this drive letter refers to a fixed drive. */
9515 fixed_drives[DRIVE_INDEX (*drive)] =
9516 (GetDriveType (drive) == DRIVE_FIXED);
9518 (*drive)++;
9521 /* Reset the volume info cache. */
9522 volume_cache = NULL;
9527 shutdown_handler ensures that buffers' autosave files are
9528 up to date when the user logs off, or the system shuts down.
9530 static BOOL WINAPI
9531 shutdown_handler (DWORD type)
9533 /* Ctrl-C and Ctrl-Break are already suppressed, so don't handle them. */
9534 if (type == CTRL_CLOSE_EVENT /* User closes console window. */
9535 || type == CTRL_LOGOFF_EVENT /* User logs off. */
9536 || type == CTRL_SHUTDOWN_EVENT) /* User shutsdown. */
9538 /* Shut down cleanly, making sure autosave files are up to date. */
9539 shut_down_emacs (0, Qnil);
9542 /* Allow other handlers to handle this signal. */
9543 return FALSE;
9546 /* On Windows 9X, load UNICOWS.DLL and return its handle, or die. On
9547 NT, return a handle to GDI32.DLL. */
9548 HANDLE
9549 maybe_load_unicows_dll (void)
9551 if (os_subtype == OS_9X)
9553 HANDLE ret = LoadLibrary ("Unicows.dll");
9554 if (ret)
9556 /* These two functions are present on Windows 9X as stubs
9557 that always fail. We need the real implementations from
9558 UNICOWS.DLL, so we must call these functions through
9559 pointers, and assign the correct addresses to these
9560 pointers at program startup (see emacs.c, which calls
9561 this function early on). */
9562 pMultiByteToWideChar =
9563 (MultiByteToWideChar_Proc)GetProcAddress (ret, "MultiByteToWideChar");
9564 pWideCharToMultiByte =
9565 (WideCharToMultiByte_Proc)GetProcAddress (ret, "WideCharToMultiByte");
9566 multiByteToWideCharFlags = MB_ERR_INVALID_CHARS;
9567 return ret;
9569 else
9571 int button;
9573 button = MessageBox (NULL,
9574 "Emacs cannot load the UNICOWS.DLL library.\n"
9575 "This library is essential for using Emacs\n"
9576 "on this system. You need to install it.\n\n"
9577 "Emacs will exit when you click OK.",
9578 "Emacs cannot load UNICOWS.DLL",
9579 MB_ICONERROR | MB_TASKMODAL
9580 | MB_SETFOREGROUND | MB_OK);
9581 switch (button)
9583 case IDOK:
9584 default:
9585 exit (1);
9589 else
9591 /* On NT family of Windows, these two functions are always
9592 linked in, so we just assign their addresses to the 2
9593 pointers; no need for the LoadLibrary dance. */
9594 pMultiByteToWideChar = MultiByteToWideChar;
9595 pWideCharToMultiByte = WideCharToMultiByte;
9596 /* On NT 4.0, though, MB_ERR_INVALID_CHARS is not supported. */
9597 if (w32_major_version < 5)
9598 multiByteToWideCharFlags = 0;
9599 else
9600 multiByteToWideCharFlags = MB_ERR_INVALID_CHARS;
9601 return LoadLibrary ("Gdi32.dll");
9606 globals_of_w32 is used to initialize those global variables that
9607 must always be initialized on startup even when the global variable
9608 initialized is non zero (see the function main in emacs.c).
9610 void
9611 globals_of_w32 (void)
9613 HMODULE kernel32 = GetModuleHandle ("kernel32.dll");
9615 get_process_times_fn = (GetProcessTimes_Proc)
9616 GetProcAddress (kernel32, "GetProcessTimes");
9618 DEFSYM (QCloaded_from, ":loaded-from");
9620 g_b_init_is_windows_9x = 0;
9621 g_b_init_open_process_token = 0;
9622 g_b_init_get_token_information = 0;
9623 g_b_init_lookup_account_sid = 0;
9624 g_b_init_get_sid_sub_authority = 0;
9625 g_b_init_get_sid_sub_authority_count = 0;
9626 g_b_init_get_security_info = 0;
9627 g_b_init_get_file_security_w = 0;
9628 g_b_init_get_file_security_a = 0;
9629 g_b_init_get_security_descriptor_owner = 0;
9630 g_b_init_get_security_descriptor_group = 0;
9631 g_b_init_is_valid_sid = 0;
9632 g_b_init_create_toolhelp32_snapshot = 0;
9633 g_b_init_process32_first = 0;
9634 g_b_init_process32_next = 0;
9635 g_b_init_open_thread_token = 0;
9636 g_b_init_impersonate_self = 0;
9637 g_b_init_revert_to_self = 0;
9638 g_b_init_get_process_memory_info = 0;
9639 g_b_init_get_process_working_set_size = 0;
9640 g_b_init_global_memory_status = 0;
9641 g_b_init_global_memory_status_ex = 0;
9642 g_b_init_equal_sid = 0;
9643 g_b_init_copy_sid = 0;
9644 g_b_init_get_length_sid = 0;
9645 g_b_init_get_native_system_info = 0;
9646 g_b_init_get_system_times = 0;
9647 g_b_init_create_symbolic_link_w = 0;
9648 g_b_init_create_symbolic_link_a = 0;
9649 g_b_init_get_security_descriptor_dacl = 0;
9650 g_b_init_convert_sd_to_sddl = 0;
9651 g_b_init_convert_sddl_to_sd = 0;
9652 g_b_init_is_valid_security_descriptor = 0;
9653 g_b_init_set_file_security_w = 0;
9654 g_b_init_set_file_security_a = 0;
9655 g_b_init_set_named_security_info_w = 0;
9656 g_b_init_set_named_security_info_a = 0;
9657 g_b_init_get_adapters_info = 0;
9658 g_b_init_compare_string_w = 0;
9659 num_of_processors = 0;
9660 /* The following sets a handler for shutdown notifications for
9661 console apps. This actually applies to Emacs in both console and
9662 GUI modes, since we had to fool windows into thinking emacs is a
9663 console application to get console mode to work. */
9664 SetConsoleCtrlHandler (shutdown_handler, TRUE);
9666 /* "None" is the default group name on standalone workstations. */
9667 strcpy (dflt_group_name, "None");
9669 /* Reset, in case it has some value inherited from dump time. */
9670 w32_stat_get_owner_group = 0;
9672 /* If w32_unicode_filenames is non-zero, we will be using Unicode
9673 (a.k.a. "wide") APIs to invoke functions that accept file
9674 names. */
9675 if (is_windows_9x ())
9676 w32_unicode_filenames = 0;
9677 else
9678 w32_unicode_filenames = 1;
9680 #ifdef HAVE_MODULES
9681 dynlib_reset_last_error ();
9682 #endif
9684 w32_crypto_hprov = (HCRYPTPROV)0;
9687 /* For make-serial-process */
9689 serial_open (Lisp_Object port_obj)
9691 char *port = SSDATA (port_obj);
9692 HANDLE hnd;
9693 child_process *cp;
9694 int fd = -1;
9696 hnd = CreateFile (port, GENERIC_READ | GENERIC_WRITE, 0, 0,
9697 OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
9698 if (hnd == INVALID_HANDLE_VALUE)
9699 error ("Could not open %s", port);
9700 fd = (int) _open_osfhandle ((intptr_t) hnd, 0);
9701 if (fd == -1)
9702 error ("Could not open %s", port);
9704 cp = new_child ();
9705 if (!cp)
9706 error ("Could not create child process");
9707 cp->fd = fd;
9708 cp->status = STATUS_READ_ACKNOWLEDGED;
9709 fd_info[ fd ].hnd = hnd;
9710 fd_info[ fd ].flags |=
9711 FILE_READ | FILE_WRITE | FILE_BINARY | FILE_SERIAL;
9712 if (fd_info[ fd ].cp != NULL)
9714 error ("fd_info[fd = %d] is already in use", fd);
9716 fd_info[ fd ].cp = cp;
9717 cp->ovl_read.hEvent = CreateEvent (NULL, TRUE, FALSE, NULL);
9718 if (cp->ovl_read.hEvent == NULL)
9719 error ("Could not create read event");
9720 cp->ovl_write.hEvent = CreateEvent (NULL, TRUE, FALSE, NULL);
9721 if (cp->ovl_write.hEvent == NULL)
9722 error ("Could not create write event");
9724 return fd;
9727 /* For serial-process-configure */
9728 void
9729 serial_configure (struct Lisp_Process *p, Lisp_Object contact)
9731 Lisp_Object childp2 = Qnil;
9732 Lisp_Object tem = Qnil;
9733 HANDLE hnd;
9734 DCB dcb;
9735 COMMTIMEOUTS ct;
9736 char summary[4] = "???"; /* This usually becomes "8N1". */
9738 if ((fd_info[ p->outfd ].flags & FILE_SERIAL) == 0)
9739 error ("Not a serial process");
9740 hnd = fd_info[ p->outfd ].hnd;
9742 childp2 = Fcopy_sequence (p->childp);
9744 /* Initialize timeouts for blocking read and blocking write. */
9745 if (!GetCommTimeouts (hnd, &ct))
9746 error ("GetCommTimeouts() failed");
9747 ct.ReadIntervalTimeout = 0;
9748 ct.ReadTotalTimeoutMultiplier = 0;
9749 ct.ReadTotalTimeoutConstant = 0;
9750 ct.WriteTotalTimeoutMultiplier = 0;
9751 ct.WriteTotalTimeoutConstant = 0;
9752 if (!SetCommTimeouts (hnd, &ct))
9753 error ("SetCommTimeouts() failed");
9754 /* Read port attributes and prepare default configuration. */
9755 memset (&dcb, 0, sizeof (dcb));
9756 dcb.DCBlength = sizeof (DCB);
9757 if (!GetCommState (hnd, &dcb))
9758 error ("GetCommState() failed");
9759 dcb.fBinary = TRUE;
9760 dcb.fNull = FALSE;
9761 dcb.fAbortOnError = FALSE;
9762 /* dcb.XonLim and dcb.XoffLim are set by GetCommState() */
9763 dcb.ErrorChar = 0;
9764 dcb.EofChar = 0;
9765 dcb.EvtChar = 0;
9767 /* Configure speed. */
9768 if (!NILP (Fplist_member (contact, QCspeed)))
9769 tem = Fplist_get (contact, QCspeed);
9770 else
9771 tem = Fplist_get (p->childp, QCspeed);
9772 CHECK_NUMBER (tem);
9773 dcb.BaudRate = XINT (tem);
9774 childp2 = Fplist_put (childp2, QCspeed, tem);
9776 /* Configure bytesize. */
9777 if (!NILP (Fplist_member (contact, QCbytesize)))
9778 tem = Fplist_get (contact, QCbytesize);
9779 else
9780 tem = Fplist_get (p->childp, QCbytesize);
9781 if (NILP (tem))
9782 tem = make_number (8);
9783 CHECK_NUMBER (tem);
9784 if (XINT (tem) != 7 && XINT (tem) != 8)
9785 error (":bytesize must be nil (8), 7, or 8");
9786 dcb.ByteSize = XINT (tem);
9787 summary[0] = XINT (tem) + '0';
9788 childp2 = Fplist_put (childp2, QCbytesize, tem);
9790 /* Configure parity. */
9791 if (!NILP (Fplist_member (contact, QCparity)))
9792 tem = Fplist_get (contact, QCparity);
9793 else
9794 tem = Fplist_get (p->childp, QCparity);
9795 if (!NILP (tem) && !EQ (tem, Qeven) && !EQ (tem, Qodd))
9796 error (":parity must be nil (no parity), `even', or `odd'");
9797 dcb.fParity = FALSE;
9798 dcb.Parity = NOPARITY;
9799 dcb.fErrorChar = FALSE;
9800 if (NILP (tem))
9802 summary[1] = 'N';
9804 else if (EQ (tem, Qeven))
9806 summary[1] = 'E';
9807 dcb.fParity = TRUE;
9808 dcb.Parity = EVENPARITY;
9809 dcb.fErrorChar = TRUE;
9811 else if (EQ (tem, Qodd))
9813 summary[1] = 'O';
9814 dcb.fParity = TRUE;
9815 dcb.Parity = ODDPARITY;
9816 dcb.fErrorChar = TRUE;
9818 childp2 = Fplist_put (childp2, QCparity, tem);
9820 /* Configure stopbits. */
9821 if (!NILP (Fplist_member (contact, QCstopbits)))
9822 tem = Fplist_get (contact, QCstopbits);
9823 else
9824 tem = Fplist_get (p->childp, QCstopbits);
9825 if (NILP (tem))
9826 tem = make_number (1);
9827 CHECK_NUMBER (tem);
9828 if (XINT (tem) != 1 && XINT (tem) != 2)
9829 error (":stopbits must be nil (1 stopbit), 1, or 2");
9830 summary[2] = XINT (tem) + '0';
9831 if (XINT (tem) == 1)
9832 dcb.StopBits = ONESTOPBIT;
9833 else if (XINT (tem) == 2)
9834 dcb.StopBits = TWOSTOPBITS;
9835 childp2 = Fplist_put (childp2, QCstopbits, tem);
9837 /* Configure flowcontrol. */
9838 if (!NILP (Fplist_member (contact, QCflowcontrol)))
9839 tem = Fplist_get (contact, QCflowcontrol);
9840 else
9841 tem = Fplist_get (p->childp, QCflowcontrol);
9842 if (!NILP (tem) && !EQ (tem, Qhw) && !EQ (tem, Qsw))
9843 error (":flowcontrol must be nil (no flowcontrol), `hw', or `sw'");
9844 dcb.fOutxCtsFlow = FALSE;
9845 dcb.fOutxDsrFlow = FALSE;
9846 dcb.fDtrControl = DTR_CONTROL_DISABLE;
9847 dcb.fDsrSensitivity = FALSE;
9848 dcb.fTXContinueOnXoff = FALSE;
9849 dcb.fOutX = FALSE;
9850 dcb.fInX = FALSE;
9851 dcb.fRtsControl = RTS_CONTROL_DISABLE;
9852 dcb.XonChar = 17; /* Control-Q */
9853 dcb.XoffChar = 19; /* Control-S */
9854 if (NILP (tem))
9856 /* Already configured. */
9858 else if (EQ (tem, Qhw))
9860 dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
9861 dcb.fOutxCtsFlow = TRUE;
9863 else if (EQ (tem, Qsw))
9865 dcb.fOutX = TRUE;
9866 dcb.fInX = TRUE;
9868 childp2 = Fplist_put (childp2, QCflowcontrol, tem);
9870 /* Activate configuration. */
9871 if (!SetCommState (hnd, &dcb))
9872 error ("SetCommState() failed");
9874 childp2 = Fplist_put (childp2, QCsummary, build_string (summary));
9875 pset_childp (p, childp2);
9878 /* For make-pipe-process */
9879 void
9880 register_aux_fd (int infd)
9882 child_process *cp;
9884 cp = new_child ();
9885 if (!cp)
9886 error ("Could not create child process");
9887 cp->fd = infd;
9888 cp->status = STATUS_READ_ACKNOWLEDGED;
9890 if (fd_info[ infd ].cp != NULL)
9892 error ("fd_info[fd = %d] is already in use", infd);
9894 fd_info[ infd ].cp = cp;
9895 fd_info[ infd ].hnd = (HANDLE) _get_osfhandle (infd);
9898 #ifdef HAVE_GNUTLS
9900 ssize_t
9901 emacs_gnutls_pull (gnutls_transport_ptr_t p, void* buf, size_t sz)
9903 int n, err;
9904 struct Lisp_Process *process = (struct Lisp_Process *)p;
9905 int fd = process->infd;
9907 n = sys_read (fd, (char*)buf, sz);
9909 if (n >= 0)
9910 return n;
9912 err = errno;
9914 /* Translate the WSAEWOULDBLOCK alias EWOULDBLOCK to EAGAIN. */
9915 if (err == EWOULDBLOCK)
9916 err = EAGAIN;
9918 emacs_gnutls_transport_set_errno (process->gnutls_state, err);
9920 return -1;
9923 ssize_t
9924 emacs_gnutls_push (gnutls_transport_ptr_t p, const void* buf, size_t sz)
9926 struct Lisp_Process *process = (struct Lisp_Process *)p;
9927 int fd = process->outfd;
9928 ssize_t n = sys_write (fd, buf, sz);
9930 /* 0 or more bytes written means everything went fine. */
9931 if (n >= 0)
9932 return n;
9934 /* Negative bytes written means we got an error in errno.
9935 Translate the WSAEWOULDBLOCK alias EWOULDBLOCK to EAGAIN. */
9936 emacs_gnutls_transport_set_errno (process->gnutls_state,
9937 errno == EWOULDBLOCK ? EAGAIN : errno);
9939 return -1;
9941 #endif /* HAVE_GNUTLS */
9943 /* end of w32.c */